Timer Script Help?

Hi! I am currently making a game called Minigame Frenzy! Though, I need some help on making a timer script. What I want is a timer that counts down to 0, but if all players die it changes to Game Over! Or if multiple players are still alive they all get teleported to the spawn, and if one person is left, the text changes to …plr.Name"Wins!" I know this feels like a request, but I’ve been trying, and I couldn’t accomplish it. Could anyone atleast lead me in the right direction for this? Thanks!
-Aztralzz

1 Like

You’re looking for multiple, already made systems mashed together. For the timer itself it would be something like the following:

-- Server Script
local TimeLeft = 120 -- 2 minutes

while wait(1) and TimeLeft > 0 do
    TimeLeft = TimeLeft - 1
end

print'Timer ran out!'

Then for the other things, like for “if all players die” you could do something like this

-- Server Script
local PlayersInGame = {} -- This will store all the players in the game still, pre-game

for _, v in pairs(game.Players:GetPlayers())) do
    local Character = v.Character or v.CharacterAdded:Wait()
    local Humanoid = Character:WaitForChild'Humanoid'
    table.insert(PlayersInGame, v.Name) -- Add them to the list of players playing

    Humanoid.Died:Connect(function() -- The player died
        table.remove(PlayersInGame, v.Name) -- Remove them so the game knows
        if #PlayersInGame == 0 then -- Check if there's any alive players
            print'Game Over!' -- All players are dead, end the game
        elseif #PlayersInGame == 1 then -- One player survived
            print(('%s Wins!'):format(v.Name)
        end
    end)
end

Read more API references for more help:
Humanoid.Died, Tables

Or for a full tutorial practically all about your question to an extent, use this tutorial made by Roblox.
Timers and Custom Events

2 Likes

Sorry in advance, the code toggle font that does stuff like this was being a little finicky, so it might be formatted a little weird.

Hello,

I have a game called Frenzy Sprint (Ironically the two games share a word) but I have a timer script that essentially works the same way. I also added an AFK option for players who want to temporarily go AFK, but I’m not gonna get into that. If you want to implement an AFK button, the stuff I’m talking about should work seamlessly with a feature like that. If you want to see how it works you can play my game Frenzy Sprint, as I have implemented that feature.

If you want to see how I implemented the AFK feature, look here:

  • There’s a BoolValue under the player called IsAFK. When you click on a button, it fires a RemoteEvent and tells the server to toggle the value.
  • I used the following code to teleport only players who are AFK:
 local function tpAllPlayers()
 for i, player in ipairs(game.Players:GetChildren()) do
 	if player.Character and player.Character:FindFirstChild("HumanoidRootPart") and player.IsAFK.Value == false then -- If the player's Character exists and it's not marked as AFK then...
			player.Character.HumanoidRootPart.CFrame = target + Vector3.new(0, i * 5, 0) --Teleports players to the round
 		end
 	end
 end
  • Look at the next part to see how I make it not count AFK players.

Back to how I checked if the players are playing and how I made a timer:

  • When the server is created, create a stat under player called PlayedThisRound or something along the lines of that. I’ll use PlayedThisRound for reference. Note that you can put this under leaderstats, but if you don’t want it to be seen on the leaderboard just put it straight under the player’s object. You would create this the same way you create leaderstats, but obviously it’s not under that folder.
  • At the beginning of the round, loop through all players in the game by using the following code:
local playersThisRound = {}
local tableIndex = 1

for _, player in ipairs(game.Players:GetPlayers()) do
	if player.IsAFK.Value == false then
		player.PlayedThisRound.Value = true
		playersThisRound[tableIndex] = player
        tableIndex = tableIndex + 1
	end
end

Basically what it does is it checks to see if the player is not AFK, and if it’s not then it makes that player’s PlayedThisRound.Value to true.

  • Now for the countdown. I did the following:
local roundTime = 120 --Your number here, I made a separate variable because depending on the maps in my game, there's different amounts of time left

for timeLeft = roundTime, 1, -1 do
    game:GetService("ReplicatedStorage"):FindFirstChild("YourRemoteEvent"):FireAllClients(timeLeft)
wait()
end

I did game:GetService("ReplicatedStorage") vs game.ReplicatedStorage because I’ve been told that the latter is prone to exploits from players in the event that a hacker changes the name of ReplicatedStorage. If the hacker does, all of a sudden everything that references will throw an error… and that’s that.

This is the code in my LocalScript that displays the timer to all players:

local gameStatement = "Round time left: "

game:GetService("ReplicatedStorage"):FindFirstChild("GameCountdown").OnClientEvent:Connect(function(timeInSecs)
	if timeInSecs >= 10 then -- It will display something like 0:10
		script.Parent.Text = gameStatement .. "0:" .. timeInSecs
	end
	if timeInSecs <= 9 then -- It will display something like 0:9 if I don't make this simple fix
		script.Parent.Text = gameStatement .. "0:0" .. timeInSecs
	end
end)

That’s the timer. Now, if you want to count the players it’s quite a bit of code, so I’ll just list out the functions in bullet points.

  • When the player dies, set their PlayedThisRound value to false to designate that they’re not playing anymore.
  • Now, create yet another table within the for timeLeft = roundTime, 1, -1 do statement, so that it recreates itself every time that is run.
  • Create a variable called num in that same for loop.
  • Use another enhanced for loop that runs through the first table you made, which I had named playersThisRound. If the player’s PlayedThisRound value is still true, run the following code: num = num + 1
  • At the end of that loop, use an if statement. If num’s value is still 0, then you can safely say that no players are in the round anymore and you can go on with starting the next round.

Sorry for writing so much, but I tried to maintain clarity as I’ve gotten some responses on my own questions that were… vague… to say the least. Hopefully you found this useful! If you have any questions, feel free to let me know! :smiley:

2 Likes

Didn’t notice you already put pretty much the same stuff, my bad. Some of your stuff was more efficient when it came to the table, so probably just use @Warriorfoox’s method to the PlayersInGame table.

Well you could add players to the table when the game starts and then remove them from the table when they die. When there is no players in the table then the game ends.

1 Like

My code isn’t known for being the most efficient, it might work but it’s generally pretty bulky, I’ve been working on cutting down how much I use. Thanks !

1 Like

It’s alright, it’s always nice to see people put this effort in helping the people who don’t quite understand it yet!

1 Like

Hello there! A way I can think of to accomplish this would be to use a numeric for loop, as well as teams. Allow me to explain.

For Loop

You could use the for loop to count down the time, but also check the amount of players in or out of the minigame.

The Teams

You could place the players within teams such as Playing or Waiting, indicating which team they’re on. To note, a Team object also has a GetPlayers method, which returns the players on that team.

The Downsides Of Doing This

As pointed out by @ActiveFrenzy (thanx again btw), the Roblox chat would be spammed with constant messages saying You're now on team X. It could also be slower to do this since you’d have to constantly call the GetPlayers method, and compare the number of items to a number.

Another to note’s that you also need to insert the Teams service. I managed to find a page on the devhub which can be found here.

The Duo In Action

With these two combinations, you could check the number of players on the Playing team, and when a player dies they’re set to the Waiting team. An example of this would be…

local WaitingTeam = game.Teams.Waiting;

game.Players.PlayerAdded:Connect(function(Player)
	Player.Team = WaitingTeam; -- When they first join the server, set the player to waiting
	Player.CharacterAdded:Connect(function(Character) -- Listens for a new character
		local Humanoid = Character:WaitForChild("Humanoid"); -- Waits for the Humanoid
		Humanoid.Died:Connect(function() -- Listens for when the Humanoid dies
			Player.Team = WaitingTeam; -- Sets the player's team back to WaitingTeam
		end);
	end);
end);

Wala! We have something set to change the player to the Waiting team when they die.

Now, you might be wondering about the for loop. It’s actually quite simple. We just need the Playing team to accomplish this, and have it work together with the for loop to make the ultimate duo!

local PlayingTeam = game.Teams.Playing;
local GameEnded = false; -- A bool determining whether the game ended during the match or not

...

for Count = 120, 1, -1 do
	wait(1);
	if (#PlayingTeam:GetPlayers() < 2) then -- Is there 1 or less players standing?
		GameEnded = true; -- The match has ended
		break; -- Break the for loop, stopping the countdown
	end
end

local NumPlayers = #PlayingTeam:GetPlayers(); -- Get the number of players on the team
if (GameEnded) then -- Did the game end during the match?
	if (NumPlayers == 1) then -- Was there 1 player standing?
		-- Code
	elseif (NumPlayers == 0) then -- Did everyone lose?
		-- Code
	end
elseif (NumPlayers > 1) then -- The countdown had ended without being stopped, so was there more than 1 player standing?
	-- Code
end

And tada, we have a system set up to check for any winning player(s)! :tada: …Or for those who lost.

References

  1. Team:GetPlayers
  2. Numeric For
  3. Humanoid.Died
  4. Player.Team
  5. Spawns and Teams

If you have any questions, please don’t hesitate to ask. I hope this helped. :slight_smile:

2 Likes

He should just use tables not teams.

1 Like

Agreed, it’ll probably flood the players’ chats with “You have joined team [xyz].” If you do this every single second, for two minutes that’ll be an easy 120 messages happening in two minutes, so players trying to communicate with each other won’t even be able to see their own messages.

I feel like teams also take longer to sort, while tables would just do it instantly without the player even needing to see.

Edit: I realized that it wouldn’t flood them with 120 messages but it could still be considered inconvenient because after just a couple rounds they could approach a large amount of server messages.

1 Like

I hadn’t thought about the message saying about team change. Tbh, I forgot about that message lol. I’ll note that in my post, thanx for letting me know. :slight_smile:

EDIT
Alright, I made the edits. :slight_smile:

3 Likes

I mean, I did that code, and this error showed up.

Teams is not a valid member of DataModel

So, any help?

Apologies for the late response. That could be because the Teams service wasn’t inserted into the game. It’s quite simple to add, simply go to the MODEL ribbon and look for the service icon located under the Advanced section service_icon. When you click on that a window should pop up with a list of service(s), prompting to select and insert one.
teams_insert
Once you click on the service you want and click insert, it’s added into the game. I hope this helped. :slight_smile:

EDIT
I noted the inserting of the Teams service in my original post. :slight_smile:

K, thank youuu! (30char))))))))

1 Like