Adding a cooldown to an automatic door module

making a system for doors in a friend’s game, and making it so if a player is in a sensor range the door will open, and remain open until they go through or leave.
BUT
it partially breaks the door if you repeatedly go in and out of the sensor, and I’m not sure how I can prevent this…
Example :

Also the part of the modulescript for controlling the doors:

BMRF_Doors = function(Door) --formerly black mesa doors remade but now original doors lol
			
			local DoorOpen = false
			local Cooldown = false
			local HitTable = {}

			local function CheckForClose()
				if #HitTable < 1 then
					DoorOpen = false

					ModelTween:TweenModel(Door.Door1,Door.Positions.Door1.Shut.CFrame,0.8,{Direction=Enum.EasingDirection.InOut,Style=Enum.EasingStyle.Quad})
					ModelTween:TweenModel(Door.Door2,Door.Positions.Door2.Shut.CFrame,0.8,{Direction=Enum.EasingDirection.InOut,Style=Enum.EasingStyle.Quad})

					Door.Sensor.Close:Play()
					task.wait(0.7)	
				end
			end

			Door.Sensor.Touched:Connect(function(Obj)
				local player = game.Players:GetPlayerFromCharacter(Obj.Parent)
				if player and player.Character and player.Character.PrimaryPart == Obj then
					if not table.find(HitTable,player.UserId) then
						table.insert(HitTable,player.UserId)
					end
					if not DoorOpen then
						Door.Sensor.Close:Stop()
						Door.Sensor.Open:Play()

						ModelTween:TweenModel(Door.Door1,Door.Positions.Door1.Open.CFrame,0.8,{Direction=Enum.EasingDirection.InOut,Style=Enum.EasingStyle.Quad})
						ModelTween:TweenModel(Door.Door2,Door.Positions.Door2.Open.CFrame,0.8,{Direction=Enum.EasingDirection.InOut,Style=Enum.EasingStyle.Quad})
						task.wait(0.8)
						Door.Sensor.Open:Stop()
						DoorOpen = true
						CheckForClose()
					end
				end
			end)

			Door.Sensor.TouchEnded:Connect(function(Obj)
				local player = game.Players:GetPlayerFromCharacter(Obj.Parent)
				if player and player.Character and player.Character.PrimaryPart == Obj then
					local index = table.find(HitTable,player.UserId)
					if index then 
						table.remove(HitTable,index)
					end
					if DoorOpen then
						CheckForClose()
					end
				end
			end)
			
		end,
1 Like

Are you aware of, or have you ever used the Promise library?

(if you know how to use coroutines and the threads from the task library that also works too)

1 Like

But the solution is essentially to just cancel the thread (and therefore the animation) if the player leaves / re-enters the sensor range before the door had a chance to play its animation.

(or wait until its over if the animation is already playing)

1 Like

I wasn’t aware of the Promise Library, seems a little confusing to me though…

1 Like

It is one of the most widely used modules

I promise you it’s nothing too complicated (pun not intended), it essentially boils down to be able to assign threads that will run and finish in the future, but are able to be cancelled. I can provide a code example if you wish

1 Like

If you can provide the example, that’d help.

1 Like
--[[
    in this simple example we are just waiting
    for the animation to end playing
    no cancelling happening
]]

local Promise = require(somewhere.Promise)

local lastPromise = Promise.resolve() --an empty promise
local DoorOpen = false

local function openDoor()
    --create the promise
    lastPromise = Promise.new((function(resolve)
        --do what you need to open the door
        Door.Sensor.Open:Play()
        task.wait(.8)
        DoorOpen = true;
        --then declare that the promise finished
        resolve()
    end))
    
end

local function closeDoor()
    lastPromise = Promise.new((function(resolve)
        --play whatever you need here to close the door
        CheckForClose()
        Door.Sensor.Close:Play()

        --then tell the promise you finished
        resolve()
    end))
end



Door.Sensor.Touched:Connect(function(Obj)
    local player = game.Players:GetPlayerFromCharacter(Obj.Parent)
    if not player then return end

    lastPromise:await() --waits for the last promise to finish
    --IF IT ALREADY FINISHED IT WONT WAIT ANYTHING

    if not DoorOpen then
        openDoor()
    end

end)

Door.Sensor.TouchEnded:Connect(function(Obj)
    local player = game.Players:GetPlayerFromCharacter(Obj.Parent)
    if not player then return end

    lastPromise:await() -- wait for the last promise to finish
    --if it already finish it doesn't wait at all.

    if DoorOpen then
        closeDoor()
    end
end)
2 Likes

Sorry for such a delayed response, I think I may have messed something up…