Rotating doors that bugs

So I’ve made these doors and I’m having some trouble with them in those cases where they are being used a lot.
I had people complain about it too, even though it isn’t something that happens really easily.

So the doors are supposed to rotate open and closed, and auto close after 10 seconds.

I believe that the problem is because the mix of while true do repeatedly checking for the timer.value to hit 0 and when it finally does, and somebody activates the click function right in that moment, the door somehow double rotates or doesn’t rotate properly. That’s the problem we’ve been having.

Here’s a picture of a door that is “closed” but is stuck in a wrong rotation.

Summary

So I’ve already made a solution myself and that was to add a variable to the door that says when the timer hits 0 and it’s time to auto close, do not let people use the door. The variable stops the door from working as soon as it hits 0 and I wanted to ask if there’s somebody that could help me go through this “solution” and if it should even work as it would take a while for me to replace this in different door scripts.

I was thinking if I should change it to so, whenever the timer.value is 1, variable should be true so that it kind of warms up the variable right before auto-close.

The original door script:

Summary
local Can = true
local Open = false
local Click = script.Parent.Part.ClickDetector
local Timer = script.Parent.Timer
local Knock = script.Parent.Center.Knock
local LS = game:GetService("Lighting")
local Unauth = game.Teams.Patient.TeamColor
local Max = game.Teams["Max Security Patient"].TeamColor
local Box = game.Teams["The Box"].TeamColor
local Solitary = game.Teams["Solitary Confinement"].TeamColor
local Cooldown = 0
local GlobalSchedule = LS.Schedule

Click.MouseClick:Connect(function(Player)
	if GlobalSchedule.Value == 3 and Player.TeamColor == Unauth or GlobalSchedule.Value == 3 and Player.TeamColor == Max or GlobalSchedule.Value == 4 and Player.TeamColor == Unauth or GlobalSchedule.Value == 4 and Player.TeamColor == Max or GlobalSchedule.Value == 3 and Player.TeamColor == Box or GlobalSchedule.Value == 3 and Player.TeamColor == Solitary or GlobalSchedule.Value == 4 and Player.TeamColor == Box or GlobalSchedule.Value == 4 and Player.TeamColor == Solitary then
		if Player.TeamColor == Unauth and Cooldown == 0 or Player.TeamColor == Max and Cooldown == 0 then
			Cooldown = 5
			Knock:Play()
			wait(2)
			Cooldown = 0
		elseif Player.TeamColor == Unauth and Cooldown == 5 or Player.TeamColor == Max and Cooldown == 5 then
			return
		end
	else
	local Mag = (script.Parent.Center.Position-Player.Character.HumanoidRootPart.Position).magnitude
	if Mag <= script.Parent.Range.Value then
		if Can then
			Can = false
			if Open == false then
				local finish = script.Parent.PrimaryPart.CFrame*CFrame.Angles(0,math.rad(90),0)
				for i = 0,1,.1 do
					local cfm = script.Parent.PrimaryPart.CFrame:lerp(finish,i)
					script.Parent:SetPrimaryPartCFrame(cfm)
					wait()
				end
				Open = true
				Timer.Value = 10
			else
				Open = false
				local finish = script.Parent.PrimaryPart.CFrame*CFrame.Angles(0,-math.rad(90),0)
				for i = 0,1,.1 do
					local cfm = script.Parent.PrimaryPart.CFrame:lerp(finish,i)
					script.Parent:SetPrimaryPartCFrame(cfm)
					wait()
				end
			end
			Can = true
		end
	end
	end
end)

while true do
	while Timer.Value > 0 do
		Timer.Value = Timer.Value - 1
		wait(1)
	end
	if Open == true and Timer.Value == 0 then
		Open = false
			local finish = script.Parent.PrimaryPart.CFrame*CFrame.Angles(0,-math.rad(90),0)
			for i = 0,1,.1 do
				local cfm = script.Parent.PrimaryPart.CFrame:lerp(finish,i)
				script.Parent:SetPrimaryPartCFrame(cfm)
				wait()
			end
			Can = true
	end
	wait()
end

The scripted solution:

Summary
local Can = true
local Open = false
local Bug = false
local Click = script.Parent.Part.ClickDetector
local Timer = script.Parent.Timer
local Knock = script.Parent.Center.Knock
local LS = game:GetService("Lighting")
local Unauth = game.Teams.Patient.TeamColor
local Max = game.Teams["Max Security Patient"].TeamColor
local Box = game.Teams["The Box"].TeamColor
local Solitary = game.Teams["Solitary Confinement"].TeamColor
local Cooldown = 0
local GlobalSchedule = LS.Schedule

Click.MouseClick:Connect(function(Player)
	if GlobalSchedule.Value == 3 and Player.TeamColor == Unauth or GlobalSchedule.Value == 3 and Player.TeamColor == Max or GlobalSchedule.Value == 4 and Player.TeamColor == Unauth or GlobalSchedule.Value == 4 and Player.TeamColor == Max or GlobalSchedule.Value == 3 and Player.TeamColor == Box or GlobalSchedule.Value == 3 and Player.TeamColor == Solitary or GlobalSchedule.Value == 4 and Player.TeamColor == Box or GlobalSchedule.Value == 4 and Player.TeamColor == Solitary then
		if Player.TeamColor == Unauth and Cooldown == 0 or Player.TeamColor == Max and Cooldown == 0 then
			Cooldown = 5
			Knock:Play()
			wait(2)
			Cooldown = 0
		elseif Player.TeamColor == Unauth and Cooldown == 5 or Player.TeamColor == Max and Cooldown == 5 then
			return
		end
	else
	if Bug == true then
		return
	end
	local Mag = (script.Parent.Center.Position-Player.Character.HumanoidRootPart.Position).magnitude
	if Mag <= script.Parent.Range.Value then
		if Can then
			Can = false
			if Open == false then
				local finish = script.Parent.PrimaryPart.CFrame*CFrame.Angles(0,math.rad(90),0)
				for i = 0,1,.1 do
					local cfm = script.Parent.PrimaryPart.CFrame:lerp(finish,i)
					script.Parent:SetPrimaryPartCFrame(cfm)
					wait()
				end
				Open = true
				Timer.Value = 10
			else
				if Bug == true then
					return
				end
				Open = false
				local finish = script.Parent.PrimaryPart.CFrame*CFrame.Angles(0,-math.rad(90),0)
				for i = 0,1,.1 do
					local cfm = script.Parent.PrimaryPart.CFrame:lerp(finish,i)
					script.Parent:SetPrimaryPartCFrame(cfm)
					wait()
				end
			end
			Can = true
		end
	end
	end
end)

while true do
	while Timer.Value > 0 do
		Timer.Value = Timer.Value - 1
		wait(1)
	end
	if Open == true and Timer.Value == 0 then
		Bug = true
		Open = false
			local finish = script.Parent.PrimaryPart.CFrame*CFrame.Angles(0,-math.rad(90),0)
			for i = 0,1,.1 do
				local cfm = script.Parent.PrimaryPart.CFrame:lerp(finish,i)
				script.Parent:SetPrimaryPartCFrame(cfm)
				wait()
			end
			Can = true
			wait(.25)
			Bug = false
	end
	wait()
end

Sorry if the script is kind of messy.

I could rewrite it into a better version without the use of physical objects(such as NumberValue). This is my version of your script.


local Lighting = game:GetService("Lighting")
local Teams = game:GetService("Teams")

local MAX_RANGE = sccript.Parent.Range.Value

local debounce = false
local open = false
local opening
local knocking
local debug -- lol who needs setting false when they are automatically nil
local doorTimer = 0

local GlobalSchedule = Lighting.Schedule
local ClickDetector = script.Parent.Part.ClickDetector
local Knock = script.Parent.Center.Knock

local AuthorizationTable = {
	[3] = {
		Teams.Patient.TeamColor;
		Teams["Max Security Patient"].TeamColor;
		Teams["The Box"].TeamColor;
		Teams["Solitary Confinement"].TeamColor;
	};
	
	[4] = {
		Teams.Patient.TeamColor;
		Teams["Max Security Patient"].TeamColor;
		Teams["The Box"].TeamColor;
		Teams["Solitary Confinement"].TeamColor;
	};
}

local function ToggleDoor(open)
	if opening then
		return
	end

	opening = true
	if not open then
		local finish = script.Parent.PrimaryPart.CFrame * CFrame.Angles(0,math.rad(90),0) -- try TweenService
		for i = 0, 1, 0.1 do
			script.Parent:SetPrimaryPartCFrame(script.Parent.PrimaryPart.CFrame:lerp(finish, i))
		end

		open = true
	else
		local finish = script.Parent.PrimaryPart.CFrame * CFrame.Angles(0,-math.rad(90),0) -- try TweenService
		for i = 0, 1, 0.1 do
			script.Parent:SetPrimaryPartCFrame(script.Parent.PrimaryPart.CFrame:lerp(finish, i))
		end

		open = false
	end
	opening = false
end

Click.MouseClick:Connect(function(player)
	local authorized
	if Authorization[GlobalSchedule.Value] then
		for _, teamColor in next, Authorization[GlobalSchedule.Value] do
			if teamColor == player.TeamColor then
				authorized = true
				break
			end
		end
	end

	if authorized and not knocking then
		knocking = true
		Knock:Play()
		wait(5)

		knocking = false
	end

	if debounce or knocking then
		return
	end

	local distance = player:DistanceFromCharacter(script.Parent.Center.Position)
	if distance <= MAX_RANGE then
		debounce = true
		
		if not open then
			ToggleDoor(open)
			doorTimer = 10
			coroutine.wrap(function()
				local start = tick()

				while doorTimer > 0 do
					wait(0.1)
					doorTimer = doorTimer - tick() - start
					start = tick()
				end

				if open then
					ToggleDoor(open)
				end
			end)()
		else
			ToggleDoor(open)
			doorTimer = 0
		end
	end

	wait(0.5) -- lol
	debounce = false
end

What a mess. :sunglasses:

1 Like

Alright, so. The script you made doesn’t really make that smooth movement, it just teleports the door in place which is quite frustrating. Still thank you for the effort.

The script is really amazing it’s just the few mistakes and it’s good, thank you.

Added a wait() and the door moves smoothly.

Also, if you spam knock it lets you open it on authorized team for some reason which also wasn’t supposed to happen.

Speaking of smooth movement. Have you tried using TweenService? It actually supports tweening of CFrame.


I think fixing the spam knocking requires the fix of this:

if authorized and not knocking then
    -- truncated
else
    return
end

Also was the teams mentioned in your previous scripts not authorized to open them? If so, just put an additional statement to limit it and modify the table if necessary.

Yeah the “authorization” was supposed to say if you’re on one of those teams, you can’t open the door and it will knock instead.

Also your script didn’t close it back again it just keeps rotating the same way and I don’t understand why.

Also another thing, the script you made, when it gets to

The script doesn’t allow you to close the door since it’s running that thing, and I had to increase wait() or it’d just auto close instantly. So it’s like, a con if you want autoclose in the script here it doesn’t allow you to close it beforehand.

coroutine.wrap(function()
	local start = tick()

	while doorTimer > 0 do	
		wait(0.1)
		doorTimer = doorTimer - (tick() - start)
		start = tick()
	end

	if open then
		ToggleDoor(open)
	end
end)()

The oopsie was that I forgot about the parenthesis on the calculation, so it should be fixed opposed to the previous version.

All good, I did some changes myself and it work quite amazing now.

1 Like