Making parallel, player-specific timers?

Hi all.
So the title says what i’m trying to do, make timers that are player specific, and running in parallel for everyone, but I find it to be quite a bit of a confusing topic…

The idea is, when the global timer gets to a specific point in round-making loop, everyone is assigned a different zone, and there different timers for each zone, which is why they’d be required to run in parallel, because it would pretty much be different for everyone.

I have a contestants table, and my idea was run an in pairs loop through it and call a function, that handles the teleportation and timer, but the thing is, there would be many cycles (as many as players), so my idea was, when that timer ends, call the same function again, for the second cycle, which, again, would be different for everyone.

So I realized there’s no way I would be able to do this without coroutines… problem is… I’m not so sure where and how would I use them, and yes, I’m aware that it wouldn’t truly be parallel, I at least need the illusion of…

Would I have to have a coroutine version of the function that assigns it, and have a table of connections, each time I call it, as in:

local corutine_function = coroutine.wrap(function(player) 
     -- timer stuff
    local message = coroutine_function(player)
end)

for i,player in pairs(contestants) do
   local message = coroutine_function(player)
end

… or something like that?
I have a plan B for this system in my game, but I’d prefer to do the timers parallel and player specific…

function StartTimers(players)
	local Timers = {}
	for i,v in pairs(players) do
		if v then
			Timers[v.UserId] = tick()
		end
	end
	return Timers
end


function CheckTimer(Player, Timers, duration)
	local FoundTick = nil
	for i,v in pairs(Timers) do
		if i == Player.UserId then
			FoundTick = v
		end
	end
	if FoundTick ~= nil then
		if tick() - FoundTick >= duration then
			return "Duration-Reached"
		elseif tick() - FoundTick < duration then
			return "Duration-Not-Reached"
		end
	else
		return "Player-Not-Found"
	end
end

repeat
	wait()
until
	#game.Players:GetPlayers() > 0


local Timers = StartTimers(game.Players:GetPlayers())
for i,v in pairs(game.Players:GetPlayers()) do
	print(CheckTimer(game.Players.kylerzong, Timers, 5))
end
wait(5.12)
for i,v in pairs(game.Players:GetPlayers()) do
	print(CheckTimer(game.Players.kylerzong, Timers, 5))
end
1 Like

Thanks, this is good! I hadn’t considered using tick(), had forgotten that I don’t actually need to iterate through the time, as I do on client…

This also has pretty much no yielding, although considering all the iterations I’m not sure which between this and coroutines would be the most accurate. I’d have to hook it up to a stepped or heartbeat event, and i’d have to iterate through at the very least 1 time per second.

Also, I said that once one timer is done, I’d have to immediately switch to a new one, how would I switch them? I assume I could return a boolean and if it’s done, on the next iteration, switch to a new time…

I’ll mark it as a solution later, when I get to go through everything in-depth.Still can’t believe I forgot about getting delta time, instead of iterating :smiley:

1 Like

local NewTimers = StartTimers(players)
or…
Timers[player.UserId] = tick()

1 Like

Sorry, forgot to mention that players would get out of sync with each other and the durations would change player-specifically, too. But I already have a table that keeps each players current round, thanks.