Queue Button Detection Error!

The goal of this piece of code is to achieve an idea where players can go on top of a button and detect if the player’s character is on it or not. If the character is on the button, another button appears where other players can join in; similar to what a queue system is. To do this, a heartbeat event is used to check every frame to detect if a player is within a “zone”, that is the button. However, only 1 player, which is the last player to join, is able to do any changes. Print statements were implemented to see if the code was running okay and they all worked as expected. The next button however does not lit up and does not do any changes to it’s string values. When testing with 2 players the last player to join was the only one to do any changes, but the first could not. Once, the last player has left, the first player could do changes. I’m not sure if it’s my coding logic or something else. Many thanks for actually reading this!

Player1 (first player to join):

Player2 (last player to join):

Player1 (with Player2 no longer in the server):

Script:

local q1 = script.Parent.q1
local q2 = script.Parent.q2

local function isPointInZone(point, zonePart)
    local relPoint = zonePart.CFrame:PointToObjectSpace(point)
    return math.abs(relPoint.X) < zonePart.Size.X * 0.5 and math.abs(relPoint.Z) < zonePart.Size.Z * 0.5
end

function findnextbutton(currentPos)
	local nextbuttonpos = currentPos + 1
	for i,v in ipairs(script.Parent.q1:GetChildren())do
		if v.pos.Value == nextbuttonpos then
			return v
		end
	end
	for i,v in ipairs(script.Parent.q2:GetChildren())do
		if v.pos.Value == nextbuttonpos then
			return v
		end
	end
end

function findprevbutton(currentPos)
	local prevbuttonpos = currentPos - 1
	for i,v in ipairs(script.Parent.q1:GetChildren())do
		if v.pos.Value == prevbuttonpos then
			return v
		end
	end
	for i,v in ipairs(script.Parent.q2:GetChildren())do
		if v.pos.Value == prevbuttonpos then
			return v
		end
	end
end

function buttonTouched(part)
	game:GetService("RunService").Heartbeat:Connect(function()
		for _,plr in pairs(game.Players:GetChildren())do
			local atzone = isPointInZone(plr.Character.PrimaryPart.Position, part)
				 if atzone == true and part.enabled.Value == true then
					withinzone(part,plr)
				else
					notwithinzone(part,plr)
				end			
		end
	end)
end

function withinzone(part, plr)
	part.plr.Value = plr.Name
	buttonEffect(part)		
	print(plr.Name)		
	if part.pos.Value+1 <= 10 then
		print("this is working")
		local nextbutton = findnextbutton(part.pos.Value)
		nextbutton.Transparency = 0
		nextbutton.enabled.Value = true
	end
end

function  notwithinzone(part, plr)
	if part.name == "1" and plr.Name == "Player1" then
		print("1 is off by "..plr.Name)
	end
	part.plr.Value = "n/a"
	nobuttonEffect(part)
	if part.pos.Value+1 <= 10 then
		local nextbutton = findnextbutton(part.pos.Value)
		nextbutton.Transparency = 1
		nextbutton.enabled.Value = false
	end
end

function buttonEffect(part)
	print("changing colour effect")
	part.BrickColor = BrickColor.new("Medium stone grey")
	part.Material = Enum.Material.Neon
end

function nobuttonEffect(part)
	part.BrickColor = BrickColor.new("Dark stone grey")
	part.Material = Enum.Material.Plastic
end

function settingup()
	wait(3)
	local q1parts = q1:GetChildren()
	local q2parts = q2:GetChildren()
	for i,v in ipairs(q1parts)do		
			local val = Instance.new("StringValue")
			val.Parent = v
			val.Name = "plr"
			val.Value = "n/a"
			local bool = Instance.new("BoolValue")
			bool.Parent = v
			bool.Name = "enabled"
			bool.Value = false
			if v.Name == "1" then
				v.Transparency = 0
				bool.Value = true
			end
			buttonTouched(v)
		
	end
	for i,v in ipairs(q2parts)do
		v.Transparency = 1
		local val = Instance.new("StringValue")
		val.Parent = v
		val.Name = "plr"
		val.Value = "n/a"
		local bool = Instance.new("BoolValue")
		bool.Parent = v
		bool.Name = "enabled"
		bool.Value = false
		buttonTouched(v)
	end
end
settingup()

I’ve been stuck for 3 days trying to figure this out.

In your script, the print() function runs even though the other functions don’t. I’m not sure what is going on here, but we can use even MORE prints until we locate the source.

local Foo = workspace.Foo
local FailedValue = 0 --This should be 1, but the value failed for whatever reason

print(Foo.Transparency) --Print it once

Foo.Transparency = FailedValue --This is where we assign a value

print(Foo.Transparency) --Prints it again

In the above snippet, we print Foo.Transparency twice, the first before we change it’s value, and one after, to see if the value actually changed. If it doesn’t, it means that the value we assigned was faulty. If it does, then the bug might be caused elsewhere. If the value does change but the bug still occurs, it might be caused later in the script.

1 Like

After trying this out, I realize the problem might be the 2nd player doing changes as well such as calling the “notiwthinzone”

The problem is that since it loops through all the players, it reverts it to its original color if the latest person it has checked is not within the zone. Hence, since the last player to join is the last player checked, this issue occurs.

To fix this, use a flag that’s set to nil. If a player is within the range and the flag is still nil, change the flag’s value to the player. If flag is not nil, check if the player occupying the slot is still within the range. If they are not, set the flag to nil and scan for all other players. At the end of each heartbeat, check if the flag is still nil, and if so make it gray, otherwise make it red.

2 Likes

You’re right, That could be it! I’ll edit my script and test it to see if it works.