Hi, I’m making a wave based zombie game but I’m having an issue that I haven’t been able to solve. My for loop acts as a timer, if the timer hits zero the while loop restarts again but the problem is if the wave changes the timer needs to restart but I don’t know how to do that. Can anyone help. Here’s the script:
local Players = game:GetService("Players")
local RS = game:GetService("ReplicatedStorage")
local gv = RS.Values.gv
local DiedValue = RS.Values.DV
local wave = RS.Values.Wave
local ZombiesRemaining = RS.Values.ZombiesRemaning
local TimeToWait = RS.Values.TimeToWait.Value
local IGT = RS.Values.InGameTime
local Restart = false
local playersInRound = {}
local playersDisconnected = {}
local playerDies = {}
local lobbyTime = 20
local isOverrided = false
local inRound = false
Players.PlayerRemoving:Connect(function(Player)
table.insert(playersDisconnected, Player)
if table.find(playersInRound, Player) then
table.remove(playersInRound, table.find(playersInRound, Player))
if #playersInRound == 0 then
print("Everyone has died!")
inRound = false
end
end
end)
local function doRound()
inRound = true
playersInRound = {}
playersDisconnected = {}
for _, Player in ipairs(Players:GetPlayers()) do
local Character = Player.Character
local Humanoid = Character:WaitForChild("Humanoid")
local HRP = Character:WaitForChild("HumanoidRootPart")
HRP.CFrame = CFrame.new(0, 0, 0) --good spawn location
table.insert(playersInRound, Player)
Humanoid.Died:Connect(function()
table.insert(playersDisconnected, Player.Name)
table.remove(playersInRound, table.find(playersInRound, Player))
if #playersInRound == 0 then
print("Everyone has died!")
inRound = false
task.wait(3)
end
end)
end
end
wave.Value = 1
function Loop()
while true do
Restart = false
for i = lobbyTime, 0, -1 do
gv.Value = i
wait(1)
end
coroutine.wrap(function()
for i = 120, 0, -1 do
IGT.Value = i
wait(1)
end
end)
if ZombiesRemaining.Value <= 0 then
wave.Value = wave.Value + 1
ZombiesRemaining.Value = 10 + wave.Value
if TimeToWait ~= 0.5 then -- If it hasn't reached 0.5 yet
TimeToWait = TimeToWait - 0.1 -- Decrease the current TimeToWait by 0.1
else
TimeToWait = 0.5
end
if wave.Changed:Connect(function()
DON'T KNOW WHAT TO DO HERE OR IF THIS IS THE RIGHT THING TO DO.
end)
end
if IGT == 0 then
Restart = true
break
end
end
end
end
if Restart == true then
Loop()
end
task.spawn(function()
while task.wait() do
if not inRound then
doRound()
end
end
end)
I think you should rebuild the entire timer approach, I was reading your code and I think it has some issues, read the comments:
I removed everything and just focusing on the Loop function.
local lobbyTime = 20
local IGT
local gv
function Loop()
warn("the while loop started")
-- Constantly repeat this block by using while loop
while true do
warn("loop ran")
Restart = false
-- Counting to 20 yielding, when its over, the rest of code will run
for i = lobbyTime, 0, -1 do
print("lobby time:", i)
gv = i
wait(1)
end
-- First time the "lobby 20 seconds" are over
-- wrap and run
coroutine.wrap(function()
warn("coroutine started")
for i = 120, 0, -1 do
IGT = i
warn("seconds in coroutine:", i)
wait(1)
end
end)() -- you were forgeting the run (), otherwise the coroutine never fires
-- and its running independently from the iteration
-- In first iteration, this doesnt fires, CONTINUE
if IGT == 0 then
Restart = true
break
end
-- We reached here while coroutine still running, it will last 120 seconds independently from the iterations
-- A new iteration is about to start
-- And it will repeat whole code again
-- Means, after the first 20 seconds "lobby loop" everything in this block will run again
-- Starting a new for i = lobbyTime, 0, -1 do loop, while coroutine of 120secs still running
-- Causing overlapping loops
end
end
And how you could change reset/set the timer.
You did a coroutine.wrap which is never yielding or accepting a updated value, it will perform a loop until reaching 120 seconds, no way to stop it/change it, unless you referenced the amount of “time” to iterate outside the coroutine, a variable that holds a number of seconds in which the loop will react, so you can overwrite it from outside.
So how could I change the second timer, the reason for the coroutine is so if the wave changes it will still listen for that, but I have no idea how to restart the second timer when the wave changes without repeating the while loop. If I repeat the while loop the intermission will start again and the wave will revert back to wave one. Can I change the coroutine loop to something else?
if you only want to change the variable that the coroutine is using without yielding it to receive updated data, you could use an external variable, check this example (you can even run it in command bar)
-- "global" value of the timer
local value = 5
-- the coroutine
coroutine.wrap(function()
while true do
task.wait(1)
value -= 1
print("Timer:", value)
end
end)() -- run
-- Change value after 10 seconds
task.wait(10)
value = 500
-- You can just change that "global" variable for the coroutine to any number you want
value = 100
Or you could yield the coroutine, or you could get rid of coroutine and use task.spawn, and constantly reading your timer based on events/stages in your round.
Idk depends what you prefer. I just suggest rebuilding your timer, specially if its very important for the game. Focus on it and give it more importance as a “leading system”
I have updated the code but how do I run the coroutine?
function Loop()
while true do
Restart = false
for i = lobbyTime, 0, -1 do
gv.Value = i
wait(1)
end
local value = RS.Values.MainGame
coroutine.wrap(function()
while true do
task.wait(1)
value.Value -= 1
IGT.Value = value.Value
print("Timer:", value.Value)
end
end)
if ZombiesRemaining.Value <= 0 then
wave.Value = wave.Value + 1
value.Value = 120
ZombiesRemaining.Value = 10 + wave.Value
if TimeToWait ~= 0.5 then -- If it hasn't reached 0.5 yet
TimeToWait = TimeToWait - 0.1 -- Decrease the current TimeToWait by 0.1
else
TimeToWait = 0.5
end
if IGT == 0 then
Restart = true
break
end
end
end
end
Add the parenthesis, but I see almost everything is the same
coroutine.wrap(function()
while true do
task.wait(1)
value.Value -= 1
IGT.Value = value.Value
print("Timer:", value.Value)
end
end)() -- this last parenthesis