Restart while loop

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    I am making a map system that has an AFK system.

  2. What is the issue? Include screenshots / videos if possible!
    The main script works but the afk system does not. The afk system works like this: If you are AFK, you will not join the match. If the server has only 1 or no non afk players, the match will not start. But the problem is, the match starts anyway.

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I’ve looked for many solutions on the hub but none of them fit my script

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

my script (serversided)

local status = game.ReplicatedStorage.Values.Status
local ticker = 0

local roundtime = 60

local winAmount = 1
local experienceAmount = 50
local cashAmount = 20

function getWinners()
local winners = table.create(1, "a")
table.clear(winners)
for _, player in pairs(game.Players:GetPlayers()) do
local plr = workspace.CurrentlyPlaying:FindFirstChild(player.Name)
if plr then
table.insert(winners, player.Name)
end
end
return winners
end

while true do
ticker = 20
local nonafkplayers = game:GetService("ReplicatedStorage").GetNonAFK:Invoke()

repeat
ticker -= 1
status.Value = "Intermission: "..ticker
wait(1)
until ticker == 0 or #nonafkplayers < 2

if #nonafkplayers < 2 then
status.Value = "Waiting for more players!"
else
status.Value = "Minigame Selected! Teleporting Players..."
end
wait(2)

local selectedMap = game:GetService("ReplicatedStorage").Maps:GetChildren()
local chosenMap = math.random(1, #selectedMap)
cN = 0
local clone
for i = 1, #selectedMap do
cN += 1
if cN == chosenMap then
clone = selectedMap[i].Map:Clone()
clone.Name = "CurrentMap"
clone.Parent = workspace

currentMap = selectedMap[i].Name
status.Value = "Minigame: "..currentMap
end
end
wait(3)
local players = game:GetService("Players"):GetPlayers()

for i = 1, #players do
local spawnpoint = workspace.CurrentMap.Spawn

if players[i]:WaitForChild("AFK").Value == false then
players[i].Character.HumanoidRootPart.CFrame = CFrame.new(spawnpoint.Position)
players[i].Team = game.Teams.Playing
players[i].Character.Parent = workspace.CurrentlyPlaying
end
end
clone.MapScript.Disabled = false
ticker = roundtime
repeat ticker -= 1
status.Value = ticker.." seconds left!"
wait(1)
until ticker == 0 or #workspace.CurrentlyPlaying:GetChildren() == 0

local winners = getWinners()
if #winners == 0 then
status.Value = "Winner: No One"
elseif #winners == 1 then
status.Value = "Winner: "..table.unpack(winners)
local playerthatwon = game.Players[winners[1]]
playerthatwon.leaderstats.Wins.Value += winAmount
playerthatwon.Experience.Value += experienceAmount
playerthatwon.Cash.Value += cashAmount
else
for _, v in pairs(winners) do
local playerthatwon = game.Players:FindFirstChild(v)
if playerthatwon then
playerthatwon.leaderstats.Wins.Value += winAmount
playerthatwon.Experience.Value += experienceAmount
playerthatwon.Cash.Value += cashAmount
end
end
status.Value = "Winners: "..table.concat(winners, ", ", 1, #winners)
end

wait(3)
for _, player in pairs(game.Players:GetPlayers()) do
if player.Team == game.Teams.Playing then
player:LoadCharacter()
player.Character.Parent = workspace
end
end

workspace.CurrentMap:Destroy()
end

Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.

Make the loop a thread and run task.cancel on it when you want to stop it:

function loop()
	for i = 1, math.huge do
		print(i)
		task.wait(1)
	end
end

local t = task.spawn(loop)
task.wait(5) --wait for 5 seconds
--restart it(basically stop the old thread and start a new one)
task.cancel(t)
t = task.spawn(loop)
1 Like

how would I implement it into my code?

Just put the loop that you want to restart in the loop function and activate and restart it with the example code below it.

the problem is, I want to restart the loop from within the loop

Recursion is what you’re looking for then:

function loop()
	for i = 1, 20 do
		print(i)
		--when it reaches 5, it calls itself(starting the loop again) and breaks(stops the current loop)
		if i == 5 then
			loop()
			break
		end
		task.wait(1)
	end
end

loop() --start it for the first time

Recursion is basically when a function calls itself. It needs a break condition else you get the error “stack overflow”, in this case, the break condition is that the recursion is done in a linear fashion in the sense that the current loop stops when a new one starts.

this looks reasonable, I will try it and mark as solution if it works, thanks.

Also small note, if you want to skip a loop iteration(for example if your loop is a game loop, and on each iteration a new game begins) you can use the keyword continue that does exactly that:

for i = 1, 10 do
	if i%2 == 0 then continue end --skip all the iterations that i is even
	print(i)
	task.wait(1)
end

after converting the loop into a function, global variables were underlined in orange, is that normal

my original thought was to use continue to restart the loop

And what was the issue with that?

you can see the use in the script i provided in my issue and check if it would work

Well if you’re looking for the optimal answer the first step is to manage to describe the issue logically and in detail(basically figure out exactly what you’re trying to solve).

My script uses a ticker (placeholder counter) that is used in concatenation within a status value which is used in local scripts to provide a bar with a string.
Starting from 20, the ticker will count down each second until 0.
The loop for the ticker countdown will break either when it hits 0 or there is less than 2 non afk players.
The script will detect if it broke because it hit 0 or if there are less than 2 non afk players.
If it broke because there are not enough non afk players, it will set the status to “Waiting For More Players…”
It will then wait until there are enough non afk players then restart the script

I’m not sure when it broke but now the status bar doesnt work

I can add you to team create if that helps

  1. prob typo idk but you defined the variable selectedmap , but later you are using selectedMap with an uppercase ‘M’ when selecting the map.

  2. in your while loop, you are checking if the number of the players that are not afk is less than 2 before starting the match. however, in the condition #nonafkplayers < 2 , you are not taking into account the case when there is only 1 non-AFK player. you should change the condition to #nonafkplayers < 2 and #nonafkplayers > 0 to check for both cases.

I also edited the code, but I recommend manually reviewing the issues too:

local status = game.ReplicatedStorage.Values.Status
local ticker = 0

local roundtime = 60

local winAmount = 1
local experienceAmount = 50
local cashAmount = 20

function getWinners()
    local winners = {}
    for _, player in pairs(game.Players:GetPlayers()) do
        local plr = workspace.CurrentlyPlaying:FindFirstChild(player.Name)
        if plr then
            table.insert(winners, player.Name)
        end
    end
    return winners
end

while true do
    ticker = 20
    local nonafkplayers = game:GetService("ReplicatedStorage").GetNonAFK:Invoke()

    repeat
        ticker -= 1
        status.Value = "Intermission: "..ticker
        wait(1)
    until ticker == 0 or (#nonafkplayers < 2 and #nonafkplayers > 0)

    if #nonafkplayers < 2 then
        status.Value = "Waiting for more players!"
        continue
    else
        status.Value = "Minigame Selected! Teleporting Players..."
    end
    wait(2)

    local selectedMap = game:GetService("ReplicatedStorage").Maps:GetChildren()
    local chosenMap = math.random(1, #selectedMap)
    local cN = 0
    local clone
    for i = 1, #selectedMap do
        cN += 1
        if cN == chosenMap then
            clone = selectedMap[i].Map:Clone()
            clone.Name = "CurrentMap"
            clone.Parent = workspace

            currentMap = selectedMap[i].Name
            status.Value = "Minigame: "..currentMap
        end
    end
    wait(3)
    local players = game:GetService("Players"):GetPlayers()

    for i = 1, #players do
        local spawnpoint = workspace.CurrentMap.Spawn

        if players[i]:WaitForChild("AFK").Value == false then
            players[i].Character.HumanoidRootPart.CFrame = CFrame.new(spawnpoint.Position)
            players[i].Team = game.Teams.Playing
            players[i].Character.Parent = workspace.CurrentlyPlaying
        end
    end
    clone.MapScript.Disabled = false
    ticker = roundtime
    repeat
        ticker -= 1
        status.Value = ticker.." seconds left!"
        wait(1)
    until ticker == 0 or #workspace.CurrentlyPlaying:GetChildren() == 0

    local winners = getWinners()
    if #winners == 0 then
        status.Value = "Winner: No One"
    elseif #winners == 1 then
        status.Value = "Winner: "..table.unpack(winners)
        local playerthatwon = game.Players[winners[1]]
        playerthatwon.leaderstats.Wins.Value += winAmount
        playerthatwon.Experience.Value += experienceAmount
        playerthatwon.Cash.Value += cashAmount
    else
        for _, v in pairs(winners) do
            local playerthatwon = game.Players:FindFirstChild(v)
            if playerthatwon then
                playerthatwon.leaderstats.Wins.Value += winAmount
                playerthatwon.Experience.Value += experienceAmount
                playerthatwon.Cash.Value += cashAmount
            end
        end
        status.Value = "Winners: "..table.concat(winners, ", ", 1, #winners)
    end

    wait(3)
    for _, player in pairs(game.Players:GetPlayers()) do
        if player.Team == game.Teams.Playing then
            player:LoadCharacter()
            player.Character.Parent = workspace
        end
    end

    workspace.CurrentMap:Destroy()
end

These are the issues I found by examining the topics’ title, description, and code.

function gameLoop()
	for i = 20, 0, -1 do
		--imagine instead of actual players it checks for AFK ones
		if #game.Players:GetPlayers() < 2 then
			print("Waiting For More Players...")
			repeat task.wait() until game.Players:GetPlayers() >= 2
			gameLoop()
			break
		end
		print(i)
	end
end

gameLoop()

I was typing and not copy pasting so I was bound to have some typos when writing this topic

point no 2. the game only starts if there are more than 1 non afk players so I don’t see how checking if there is 1 non afk player being helpful

@NyrionDev how would checking for afk players help