Loop breaks even though it doesn't fit criteria

You have to constantly check for new players using a loop, if this is a server script then #game.Teams.Runners:GetPlayers() would be 0, wait for a player to be added and update on every player added, also I really don’t use == because it’s kinda messy, suppose the game glitches and returns -1 then it won’t be 0 and it wouldn’t break. I normally use < or >… Anywho tell me if this works…

I’m a little new to scripting, how would I translate what you just said into a line of code?

local runners
spawn(function()
while true do wait()
    runners = game.Players:GetPlayers()
end
end)
-- where ever this goes v
if #runners < 1 then
    break
end
1 Like

Well try doing this instead:

local runnersTable = game.Teams.Runners:GetPlayers()
--Inside the loop
runnersTable = game.Teams.Runners:GetPlayers()
if #runnersTable == 0 then
 break
end
1 Like

ServerScriptService.RoundSetter:91: attempt to get length of a nil value

and the line it sent me to was “if #runners < 1 then”

That would probably mean that runners doesn’t exist yet and is not a number yet therefore attempting to index absolutely nothing, add a wait of like 10 seconds or wait till your character loads.

@AstralBlu_e That did not work.

@greatneil80 Where would I put the wait? Also it may be a problem on my part of where I put your code. Here is where your code is in my loop:

		for i = roundLength, 0, -1 do			
			InRound.Value = true	

			local runners
			spawn(function()
				while true do wait()
					runners = game.Players:GetPlayers()
				end
			end)
			-- where ever this goes v
			if #runners < 1 then
			   break
			end

			if won.Value == true then
				break
			end
			wait(1)
			status.Value = "Game: ".. i .." seconds left!"
		end

Ok, thats excessive threads in that for loop, that will cause lag, put my part on line 1,

        local runners
		spawn(function()
			while true do wait()
				runners = game.Players:GetPlayers()
			end
		end)
repeat wait() until #game.Players:GetPlayers() > 0
for i = roundLength, 0, -1 do			
		InRound.Value = true
		-- where ever this goes v
		if #runners < 1 then
		   break
		end

		if won.Value == true then
			break
		end
		wait(1)
		status.Value = "Game: ".. i .." seconds left!"
	end

When you mean line 1, do you mean before the script actually starts and after all the variables are set? If so, it had no effect. The game just continued as normal without change. The only difference is that the script didn’t work in single player.

Yeah, a thread in the start then waiting for the player count to increase to more than 0, then start the loop. That will constantly update the player count.

local roundLength = 60
local intermissionLength = 10
local victoryLength = 15
local deathLength = 5
local InRound = game.ReplicatedStorage.InRound
local lobbyspawn = game.Workspace.LobbyAreaSpawn
local gamespawn = game.Workspace.GameAreaSpawn
local deathspawn = game.Workspace.deathspawn
local status = game.ReplicatedStorage.Status
local won = game.ReplicatedStorage.Won
local died = game.ReplicatedStorage.Died

local music = game.Workspace.music
local music1 = game.Workspace.music_duplex
local music2 = game.Workspace.music_duplexwon
local trombone = game.Workspace.trombone

local runnersTable = game.Teams.Runners:GetPlayers()

local title = game.StarterGui.Menu.TitleScreen

        local runners
		spawn(function()
			while true do wait()
				runners = game.Players:GetPlayers()
			end
		end)
repeat wait() until #game.Players:GetPlayers() > 0
for i = roundLength, 0, -1 do			
		InRound.Value = true
		-- where ever this goes v
		if #runners < 1 then
		   break
		end

		if won.Value == true then
			break
		end
		wait(1)
		status.Value = "Game: ".. i .." seconds left!"
	end

game.Players.PlayerAdded:Connect(function(player)
	local Neutral = game.Teams.Neutral
    player.Team = Neutral
end)

InRound.Changed:Connect(function()
	if InRound.Value == true then	
		local death = game.Teams.Death -- this sets the teams
		local runnersTeam = game.Teams.Runners
		local plrs = game.Players
		local runners = {}
			repeat wait(1) until #plrs:GetPlayers() > 0
		local chosen = plrs:GetChildren()[math.random(1, #plrs:GetChildren())]
		for i, plr in pairs(plrs:GetChildren()) do 
			if plr ~= chosen then
				table.insert(runners, plr)
				plr.Team = runnersTeam
			else
				plr.Team = death
			end
		print("teams have been chosen")
		end	
	
		for _, player in pairs(game.Players:GetChildren()) do -- this teleports the players
			local char = player.Character
			if player.Team == runnersTeam then
				char.HumanoidRootPart.CFrame = gamespawn.CFrame
			else
				char.HumanoidRootPart.CFrame = deathspawn.CFrame
			end
		end
		print("players have teleported to the game area")
	else --if the round isn't going, this places everyone in the neutral team and teleports them to the lobby
		local plrs = game.Players
		local Neutral = game.Teams.Neutral
		for i, plr in pairs(plrs:GetChildren()) do
			plr.Team = Neutral
		end
		print("all players have been placed in neutral")
		for _, player in pairs(game.Players:GetChildren()) do
			local char = player.Character
			char.HumanoidRootPart.CFrame = lobbyspawn.CFrame
		end		
		print("players have teleported to the lobby")
	end
end)

local function RoundTimer() --this is the timer for the rounds. It changes the text in a GUI as well
	while wait() do
		if won.Value == false then
			music:Play()
			music1:Stop()
			for i = intermissionLength, 0, -1 do
				InRound.Value = false
				wait(1)
				status.Value = "Intermission: ".. i .." seconds left!"
			end
			music:Stop()
			music1:Play()
			for i = roundLength, 0, -1 do			
				InRound.Value = true	

				if won.Value == true then
					break
				end
				wait(1)
				status.Value = "Game: ".. i .." seconds left!"
			end
		else
			music:Stop()
			music1:Stop()
			music2:Play()
			for i = victoryLength, 0, -1 do
				wait(1)
				status.Value = "The runners have beaten death!"
			end

			for _, player in pairs(game.Players:GetChildren()) do
				local char = player.Character
				char.HumanoidRootPart.CFrame = lobbyspawn.CFrame
			end		
			won.Value = false
		end
	end
end

spawn(RoundTimer)

Your code is after all of the variables are set.

I couldn’t find it lol I had to search it to check if I was blind lOl

ok this indenting is the most painful thing ive ever done… just change the word “runners” to runnersTable and remove the line that says local runnersTable = game.Teams.Runners:GetPlayers()

That didn’t work. What was different this time was that when the runner died, he went to the neutral team on his screen, but when I looked at death’s screen, it still showed him on the runners team. Weird.

we might have been going about this wrong, put the check in here,

for i = roundLength, 0, -1 do
			InRound.Value = true		
			if won.Value == true then
				break
			end
			wait(1)
			status.Value = "Game: ".. i .." seconds left!"
                           if #runnersTable < 1 then break end
		end

go back to the original script because you were using runnerstable and removing data from it whereas my script overwrites that, replace that in the original script.

but I thought you said

I put this:

local runners
	spawn(function()
		while true do wait()
			runners = game.Players:GetPlayers()
		end
	end)
repeat wait() until #game.Players:GetPlayers() > 0
for i = roundLength, 0, -1 do			
		InRound.Value = true
		-- where ever this goes v
		if #runners < 1 then
		   break
		end

	if won.Value == true then
		break
	end
	wait(1)
	status.Value = "Game: ".. i .." seconds left!"
end

in this:

for i = roundLength, 0, -1 do
			InRound.Value = true		
			if won.Value == true then
				break
			end
			wait(1)
			status.Value = "Game: ".. i .." seconds left!"
                           if #runnersTable < 1 then break end
		end

earlier.

that was the update check but then I realized it updated in the start to begin with, I didn’t see it earlier, since it is in the timer loop, the script I gave you should work, discard what all happened earlier…

All right, so put this:

local runners
	spawn(function()
		while true do wait()
			runners = game.Players:GetPlayers()
		end

	end)
repeat wait() until #game.Players:GetPlayers() > 0
for i = roundLength, 0, -1 do			
		InRound.Value = true
		-- where ever this goes v
		if #runners < 1 then
		   break
		end

	if won.Value == true then
		break
	end
	wait(1)
	status.Value = "Game: ".. i .." seconds left!"
end

In this?

for i = roundLength, 0, -1 do
			InRound.Value = true		
			if won.Value == true then
				break
			end
			wait(1)
			status.Value = "Game: ".. i .." seconds left!"
                           if #runnersTable < 1 then break end
		end

And do you want me to remove “if #runnersTable < 1 then break end”?

1 Like

no, don’t replace that, it looks good with that “if #runnersTable < 1 then break end”, it should work

1 Like

I placed this:

local runners
	spawn(function()
		while true do wait()
			runners = game.Players:GetPlayers()
		end

	end)
repeat wait() until #game.Players:GetPlayers() > 0
for i = roundLength, 0, -1 do			
		InRound.Value = true
		-- where ever this goes v
		if #runners < 1 then
		   break
		end

	if won.Value == true then
		break
	end
	wait(1)
	status.Value = "Game: ".. i .." seconds left!"
end

inside this:

for i = roundLength, 0, -1 do
			InRound.Value = true		
			if won.Value == true then
				break
			end
			wait(1)
			status.Value = "Game: ".. i .." seconds left!"
                           if #runnersTable < 1 then break end
		end

Specifically I put it right below “InRound.Value = true”. It did not work, and it still shows the player on the runners team on death’s screen.

1 Like