# How To Make A Round-Based System

Hello everyone! If you remember from my last tutorial I showed you guys how to make a Random Map Picker. In this tutorial I am going to show you how to make a Round-based system (this tutorial was asked for from @f1nneas).

(Quick note that there are many ways to make this system, this is my way)

The things that this system will do is:

1.) wait an intermission time
2.) pick a map from our random map picker
3.) sort the teams, one killer and the rest are survivors
4.) destroy the map and teleport the players back from our map picker
5.) repeat the steps 1-4

# Intermission And Round Time

the first thing we want to do is figure out how long our round time and intermission time is going to be. In my case I made my intermission time 20 seconds and my round time 200 seconds. I have made two variables to help me know that this is either intermission time or round time in my script. when you are done with that we are going to want to make a variable that will let us know whether to skip the round or not just in case someone leaves and there are not enough players. Next we are going to want to set up the actual intermission time that will make sure there are enough players to play and set everything up for your game. Inside a while true do loop (so it continues forever), we will create a while loop that tells us how long to wait before starting the round, during this time we will constantly check to make sure there are enough players to play.

If there arenâ€™t enough players we will wait until there are enough, here is how I set this up:

local roundtime = 200
local inter = 20

while true do
local skip = false
print("Inter")
while inter > 0 do
local ps = game.Players:GetPlayers()
if #ps >= 2 then
inter = inter - 1
wait(1)
else
while #ps < 2 do
ps = game.Players:GetPlayers()
print("Need More")
wait(1)
end
skip = true
inter = 0
end
end
end

Now we will have to mess with the round time, in here we will have a while loop to tell if we are in a round or not just like the intermission. Before we do this though, we will have to check if the skip variable is set to false, meaning there was enough players. If it is we will continue through, otherwise we will reset everything and repeat the steps again.

I have set up my final result to look like this:

local roundtime = 200
local inter = 20

while true do
local skip = false
print("Inter")
while inter > 0 do
local ps = game.Players:GetPlayers()
if #ps >= 2 then
inter = inter - 1
wait(1)
else
while #ps < 2 do
ps = game.Players:GetPlayers()
print("Need More")
wait(1)
end
skip = true
inter = 0
end
end
wait(1)
if skip == false then
sortTeams()
print("round")
while roundtime > 0 do
wait(1)
end
end
print("not enough")
skip = false
inter = 20
roundtime = 200
end

# Sorting The Teams

Now we are going to have to set up the teams when the round starts, and bring everyone back to the lobby when the round is over. First make sure to define the teams game service at the top of your script, then in our sortTeams() function we will start by choosing and loading in the map from our Random Map Picker. Now we are going to define the players that are currently in the lobby, and everyone in general. Using the players in the lobby, lets pick one random person to be the Killer with math.random, we will also make sure to remove them from the table after this, so they canâ€™t be picked again. Now we will get the remaining players and add them into the Survivor team using table.foreach and teleport them to the map.

My script looks like this:

local teams = game:GetService("Teams")
local roundtime = 200
local inter = 20

function sortTeams()
chooseMap()
wait(3)
local Players = game.Players:GetPlayers()
local players = teams.Lobby:GetPlayers()

-- Chooses Killer

local index = math.random(1,#players) -- choose a random index between 1 and the length of the table
players[index].Team = teams["Killer"] -- set the randomly chosen player to the Killer team
table.remove(players,index) -- removes them from the pool of players, ensuring no duplicate picking later

-- Sort Remaining Players

table.foreach(players,function (_,player) player.Team = teams["Survivor"] end)
teleportPlayers()
end

# Finishing Up And Playing The Round

Now comes our final step, actually having the round play until either the killer leaves the game, there are no more survivors left, or the round time has hit 0. We are going to first create a local timer for the server to use just so nothing breaks or messes up and set the local timer to our roundtime. We will also make sure that the killer is still in the game by creating a variable called kactive and add the survivors in a table to make sure that they are still in the game. Once you have finished that, I added a wait(3) as a little stall and then set everyone back to the lobby using the general players variable and table.foreach. I then called the teleportBack() and deleteMap() function from the Random Map Picker and set the roundtime to 0 so everything could reset and start over again.

Here is how the final function turned out:

local teams = game:GetService("Teams")
local roundtime = 200
local inter = 20

function sortTeams()
chooseMap()
wait(3)
local Players = game.Players:GetPlayers()
local players = teams.Lobby:GetPlayers()

-- Chooses Killer

local index = math.random(1,#players) -- choose a random index between 1 and the length of the table
players[index].Team = teams["Killer"] -- set the randomly chosen player to the Killer team
table.remove(players,index) -- removes them from the pool of players, ensuring no duplicate picking later

-- Sort Remaining Players

table.foreach(players,function (_,player) player.Team = teams["Survivor"] end)
teleportPlayers()
print("time")
local localtimer = roundtime
while localtimer > 0 do
wait(1)
localtimer = localtimer - 1
local kactive = false
local activepeople = {}
for _, s in pairs(teams.Survivor:GetPlayers()) do
if s then
table.insert(activepeople, s)
end
end
for _, k in pairs(teams.Killer:GetPlayers()) do
if k then
kactive = true
end
end
if #activepeople < 1 then
for _, k in pairs(teams.Killer:GetPlayers()) do
-- k.Cash.Value = k.Cash.Value + 50
end
break
end
if not kactive then
for _, s in pairs(teams.Survivor:GetPlayers()) do
--s.Cash.Value = s.Cash.Value + 20
end
break
end
if localtimer == 0 then
for _, s in pairs(teams.Survivor:GetPlayers()) do
--s.Cash.Value = s.Cash.Value + 20
end
end
end

-- Back To Lobby

roundtime = 0
wait(3)
teleportBack()
deleteMap()
table.foreach(Players,function (_,Player) Player.Team = teams["Lobby"] end)
end

# Extra Information

table.foreach is deprecated, thx for letting me know @incapaz! use this for loop instead

for i, player in ipairs (players) do
player.Team = teams["Survivor"]
end

This is a really big tutorial, if you had any trouble with this, make sure to let me know down below. If you have any thing that might make this better, please let me know below as well.

Here is the Random Map Picker tutorial I made: How To Make A Random Map Picker

If you want feel free to add in any extra things such as giving certain players cash if they win, I have added features such as that on this downloadable version if you are still having trouble or want to use those features: Round-Based System.rbxl (23.9 KB)

125 Likes

Hey everyone! I made a useful tutorial on this that may help you understand how to make this system better.

30 Likes

Thanks for the post.
How can we adjust the script so that the Killer and Survivors spawn to their respective
Spawn Locations?
(e.g. one spawn point for Killer, multiple spawn points for survivors).

7 Likes

Just make different spawnpoints for killer and survivors teams, you can see TeamColor property in it or something and just change it to the team you want.

2 Likes

I did that, but the script calls for:

function teleportPlayers()
local players = game.Players:GetPlayers()
for i,v in pairs(players) do
v.Character.HumanoidRootPart.CFrame = currentmap:FindFirstChild(chosenmap.Value).Spawn.CFrame
end
end

Iâ€™m new to scripting, so Iâ€™m assuming, in this case, I have to put something in the teleport function to link to the team spawns. ?

4 Likes

So where it calls this, â€śSpawnâ€ť would be the spawn point in the map, this would be where all the players are brought to when this function is called.

if you wanted to change the spawn for the killer, you would need to add a if statement to change the spawn area.

if v.Team == game.Teams.Killer then
-- spawn for the killer
else
-- spawn for the survivors
end
6 Likes

Thanks!
I was just looking into that.
I still donâ€™t know what the scripting is to send the Killer to the specific team spawn though (digging through threadsâ€¦ nada)

2 Likes

So just add in the if statement to the function and if they are on the Killer team, change â€śSpawnâ€ť to the Killer Spawn and do the same with the survivors.

3 Likes

How do I set the spawn to the team color spawn?

1 Like

I donâ€™t quite understand, like I said â€śSpawnâ€ť is the name of the spawn point for every player. If you have two separate spawns in the map (one for killer, other for survivors), change â€śSpawnâ€ť to your spawn name using the if statement.

1 Like

Yeah, Iâ€™m super novice, so the quality of my queries can be lacking. Sorry about that.

So for example, here is what I was just trying as a test to send players to the team spawns:

v.Character.HumanoidRootPart.CFrame = currentmap:FindFirstChild(chosenmap.Value).SpawnLocation.TeamColor

Clearly this (â€śSpawnLocation.TeamColorâ€ť) is wrong, as no teleport occurs.

1 Like

I see your problem, you are trying to move the player to a TeamColor, which isnâ€™t possible, you need to use CFrame to get the player to the spawn.

Example:

local players = game.Players:GetPlayers()
for i, v in pairs (players) do
if v.Team == game.Teams.Killer then
v.Character.HumanoidRootPart.CFrame = currentmap:FindFirstChild(chosenmap.Value).KillerSpawn.CFrame
else
v.Character.HumanoidRootPart.CFrame = currentmap:FindFirstChild(chosenmap.Value).SurvivorSpawn.CFrame
end
end

you canâ€™t move a position (1,1,1) to a color (Grey)

4 Likes

Thatâ€™s what I have been trying to figure out.
Seems so simple when you list it outâ€¦ which tells me I really need to learn some basic computer science at minimum.
Much appreciated!!!

2 Likes

Bummer. Didnâ€™t work for some reason. Hereâ€™s what I added:

function teleportPlayers()
local players = game.Players:GetPlayers()
for i, v in pairs (players) do
if v.Team == game.Teams.Killer then
v.Character.HumanoidRootPart.CFrame = currentmap:FindFirstChild(chosenmap.Value).KillerSpawn.CFrame
else
v.Character.HumanoidRootPart.CFrame = currentmap:FindFirstChild(chosenmap.Value).SurvivorSpawn.CFrame
end
end
end

1 Like

Extra note guys! thx to @incapaz for letting me know, table.foreach is deprecated. so instead of that one line, change it to this:

for i, player in ipairs(players) do
player.Team = teams["Survivor"]
end

@JUDOBABY_PSL, make sure the players change to the team before you try to teleport them to the spawn, second make sure all spawn names and team names are spelled correctly.

3 Likes

Thanks! The names are all set correct.
Giving this a try now!

1 Like

So tenacious!
I swapped the two â€śtable.foreach(players,function (_,player) player.Team = teams[â€śSurvivorâ€ť] end)â€ť cases as suggested. Still doesnâ€™t work.
Seems like it should be so simple, but, no go so far. I attached the file in case thatâ€™s easier to see where Iâ€™m going wrong. Greatly appreciate the help.

Round - Team Spawn.rbxl (27.9 KB)

Hereâ€™s the script:

> --[[
>
> Round - Based System
>
> Created By: HeIIo42bacon
>
> ]]--
>
>
> -- TERMS
>
> local teams = game:GetService("Teams")
> local roundtime = 200
> local inter = 20
> local status = game.ReplicatedStorage:WaitForChild("Status")
> local maps = game.Lighting.Maps:GetChildren()
> local currentmap = workspace:WaitForChild("CurrentMap")
> local chosenmap = script:WaitForChild("ChosenMap")
> local spawner = workspace.Lobby.Spawn
>
> -- MAP SYSTEM [MAKE SURE TO GRAB ANY OTHER NECESSARY THINGS FROM THE RANDOM MAP PICKER TUTORIAL]!
>
> function chooseMap()
> 	local choices = {}
> 	for i = 1, #maps do
> 		if maps[i]:IsA("Model") then
> 			table.insert(choices, maps[i])
> 		end
> 	end
> 	local picked = math.random(1,#maps)
> 	chosenmap.Value = choices[picked].Name
> end
>
> 	local map = game.Lighting.Maps:FindFirstChild(chosenmap.Value):Clone()
> 	map.Parent = currentmap
> 	--game.ReplicatedStorage.MapPicked:FireAllClients(chosenmap.Value) (text to tell the player what map it is)
> end
>
> function deleteMap()
> 	for i,v in pairs(currentmap:GetChildren()) do
> 		if v:IsA("Model") then
> 			v:Destroy()
> 		end
> 	end
> end
>
> function teleportPlayers()
> 	local players = game.Players:GetPlayers()
> 	for i, v in pairs (players) do
>     	if v.Team == game.Teams.Killer then
>         v.Character.HumanoidRootPart.CFrame = currentmap:FindFirstChild(chosenmap.Value).KillerSpawn.CFrame
>     else
>         v.Character.HumanoidRootPart.CFrame = currentmap:FindFirstChild(chosenmap.Value).SurvivorSpawn.CFrame
> 	end
>  end
> end
>
> function teleportBack()
> 	local players = game.Players:GetPlayers()
> 	for i,v in pairs(players) do
> 		v.Character.HumanoidRootPart.CFrame = spawner.CFrame
> 	end
> end
>
> -- TEAM SORTING
>
> function sortTeams()
> 	chooseMap()
> 	wait(3)
> 	local Players = game.Players:GetPlayers()
> 	local players = teams.Lobby:GetPlayers()
>
> 	-- Chooses Killer
>
> 	local index = math.random(1,#players) -- choose a random index between 1 and the length of the table
> 	players[index].Team = teams["Killer"] -- set the randomly chosen player to the Killer team
> 	table.remove(players,index) -- removes them from the pool of players, ensuring no duplicate picking later
>
> 	-- Sort Remaining Players
>
> 	for i, player in ipairs(players) do
>     player.Team = teams["Survivor"]
> 	end
> 	teleportPlayers()
> 	--game.ReplicatedStorage.timer:FireAllClients() (this is a timer for the players)
> 	print("time")
> 	local localtimer = roundtime
> 	while localtimer > 0 do
> 		wait(1)
> 		status.Value = localtimer
> 		localtimer = localtimer - 1
> 		local kactive = false
> 		local activepeople = {}
> 		for _, s in pairs(teams.Survivor:GetPlayers()) do
> 			if s then
> 				table.insert(activepeople, s)
> 			end
> 		end
> 		for _, k in pairs(teams.Killer:GetPlayers()) do
> 			if k then
> 				kactive = true
> 			end
> 		end
> 		if #activepeople < 1 then
> 			--game.ReplicatedStorage.Killer:FireAllClients() (this is a winners/losers text)
> 			status.Value = "Killer Wins!"
> 			for _, k in pairs(teams.Killer:GetPlayers()) do
> 				-- k.Cash.Value = k.Cash.Value + 50 (gives cash)
> 			end
> 			break
> 		end
> 		if not kactive then
> 			--game.ReplicatedStorage.Survivor:FireAllClients() (this is a winners/losers text)
> 			status.Value = "Survivors Win!"
> 			for _, s in pairs(teams.Survivor:GetPlayers()) do
> 				--s.Cash.Value = s.Cash.Value + 20 (gives cash)
> 			end
> 			break
> 		end
> 		if localtimer == 0 then
> 			status.Value = "Killer Win!"
> 			--game.ReplicatedStorage.Survivor:FireAllClients() (this is a winners/losers text)
> 			for _, s in pairs(teams.Survivor:GetPlayers()) do
> 				--s.Cash.Value = s.Cash.Value + 20 (gives cash)
> 			end
> 		end
> 	end
>
> 	-- Back To Lobby
>
> 	roundtime = 0
> 	wait(3)
> 	teleportBack()
> 	deleteMap()
> 	for i, player in ipairs(players) do
>     player.Team = teams["Lobby"]
> 	end
> end
>
> -- MAIN FUNCTION
>
> while true do
> 	local skip = false
> 	status.Value = ""
> 	print("Inter")
> 	--game.ReplicatedStorage.EnoughPlayers:FireAllClients() (gets rid of need more players text)
> 	--game.ReplicatedStorage.Inter:FireAllClients() (Intermission text) --- changing for >=1 to test
> 	while inter > 0 do
> 		local ps = game.Players:GetPlayers()
> 		if #ps >= 1 then
> 			status.Value = "Intermission For: "..inter
> 			inter = inter - 1
> 			wait(1)
> 		else
> 			while #ps < 1 do
> 				status.Value = "You Need 2 More Players To Play"
> 				ps = game.Players:GetPlayers()
> 				--game.ReplicatedStorage.NeedMorePlayers:FireAllClients() (tells the player they need more players to play)
> 				print("Need More")
> 				wait(1)
> 			end
> 			skip = true
> 			inter = 0
> 		end
> 	end
> 	wait(1)
> 	if skip == false then
> 		sortTeams()
> 		print("round")
> 		while roundtime > 0 do
> 			wait(1)
> 		end
> 	end
> 	print("not enough")
> 	skip = false
> 	inter = 20
> 	roundtime = 200
> end
2 Likes

when I did the test, it worked perfectly fine for me, get rid of â€ś>â€ť sign because it will cause an error in your script. Other then that, again make sure all spawns and team names are spelled correctly.

Check the output too for any errors you need to fix

2 Likes

Hmmâ€¦ interesting.
Did you test it with two players in Roblox?
When I do that, teams are assigned, timer counts down to 1, the map is loaded, but the players do not teleport from the lobby.
???

yes, you have to test it with two players. look in your output to see if you find any errors.

1 Like