Rounds system review

This system includes:

  1. Lobby
  2. Mode selector
  3. Map voting
  4. Character selecting
  5. When a player dies, if the number of times he dies is smaller than 3 he will respawn
  6. When the game ends, a winner will be selected (If he is the last player alive or if he has the most wins)
  7. The winner will be awarded one win and some points

This is the script:

Script
game.ServerStorage.Mains.ChangeTeam.OnServerEvent:Connect(function(plr,team)
    local chr = plr.Character
	chr.Team.Value = team
end)

local Games = game.ServerStorage.Games
local LobbyTime = 60
local Mains = game.ServerStorage.Mains
local Text = Mains.Text
local MinPlayers = 1
local ChosingTime = 60
local AlGameModes = script.GameModes:GetChildren()
local TagModule = require(script.AntiLagMain)
local RunService = game:GetService("RunService")
local Votes = workspace.Votes

function ChangeTT(self)
	if self == 'Team1' then
		return 'Heavy'
	elseif self == 'Team2' then
		return 'Sniper'
	elseif self == 'Team3' then
		return 'Shock'
	elseif self == 'Team4' then
		return 'Medic'
	elseif self == 'Team5' then
		return 'Warrior'
	elseif self == 'Team6' then
		return 'Rouge'
	elseif self == 'Team7' then
		return 'Bombarder'
	elseif self == 'Team8' then
		return 'Blackout'
	end
end

function Respawn(Cframe,char)
	delay(0.2,function()
	    char.Head.CFrame = Cframe
	end)
end

function GireArmor(char,Type)
  local plr = game.Players:GetPlayerFromCharacter(char)
  if plr then
    local Armor = game.ReplicatedStorage.Mains.Armors[Type..'Armor']:Clone()
    plr.Character:Destroy()
    Armor.Parent = workspace
    Armor.Name = plr.Name
    plr.Character = Armor
	end
end
function CharacterMain(char)
	local Team = Instance.new("StringValue",char) ; Team.Value = 'Spectators' ; Team.Name = 'Team'
	local Kills = Instance.new("IntValue",char) ; Kills.Value = 0 ; Kills.Name = 'Kills'
end
game.Players.PlayerAdded:Connect(function(plr)
	local AFK = Instance.new("BoolValue",plr) ; AFK.Name = 'AFK' ; AFK.Value = false
	plr.CharacterAdded:Connect(CharacterMain)
end)

function EnableChoser(Choser)
	for _,Part in ipairs(Choser:GetDescendants()) do
		if Part:IsA("BasePart") then
			Part.Transparency = 0
			Part.CanCollide = true
		elseif Part:IsA("SurfaceGui") then
			Part.Enabled = true
		elseif Part:IsA("Decal") then
			Part.Transparency = 0
		end
	end
end

function DisableChoser()
	for _,Part in ipairs(Votes:GetDescendants()) do
		if Part:IsA("BasePart") then
			Part.Transparency = 1
			Part.CanCollide = false
		elseif Part:IsA("SurfaceGui") then
			Part.Enabled = false
		elseif Part:IsA("Decal") then
			Part.Transparency = 1
		end
	end
end

while wait() do
	if #game.Players:GetChildren() >= MinPlayers then
	for i = LobbyTime,1,-1 do
		wait(1)
		Text.Value = 'Game Starts in '..tostring(i)
	end
	local ChosenGameMode = AlGameModes[Random.new(tick() * math.random(1,100000) / math.random(1,100000)):NextInteger(1,#AlGameModes)] 
	local GameModeData = require(ChosenGameMode)
	GameModeData = GameModeData.GetData()
	local GameTime = GameModeData.GameTime
	local KniveMode = GameModeData.KniveMode
	local Maps = Games[GameModeData.MapsName]:GetChildren()
	local GameModeName = GameModeData.ModeName	
    Text.Value = 'The chosen game mode: '..GameModeName	
	wait(3)	
	local CM = nil
	local Corountines = table.create(3)
	local Numbers = table.create(3)
	for i = 1,3 do
		local Map = Maps[i]
		if Map then
		local Votes2 = Votes:GetChildren()[i]
		EnableChoser(Votes2)
		local Frame = Votes2:WaitForChild("Image")
		local MapName = Map.Name
		local MapDecal = "http://www.roblox.com/asset/?id="..Map.DecalName.Value
		local VotesText = Votes2:WaitForChild("Sign"):GetDescendants()
		for _,i in ipairs(VotesText) do
			if i:IsA("SurfaceGui") then
				VotesText = i
				break
			end
		end
		Votes2.Decal.Image.Texture = MapDecal
		Votes2.Image.SurfaceGui.MapName.Text = MapName
		local corountine = coroutine.wrap(function()
			while wait(0.2) do
				local Region = Region3.new(Frame.Position-(Frame.Size/2),Frame.Position+(Frame.Size/2))
				local Parts = workspace:FindPartsInRegion3WithIgnoreList(Region,Votes2:GetDescendants(),999999)
				local PartsNum = math.floor((#Parts)/2)
				Numbers[i] = PartsNum
				VotesText.TextLabel.Text = string.format("Votes: %s",tostring(PartsNum))
			end
		end)
		corountine()
		table.insert(Corountines,corountine)
	end
	end
	for i = 15,1,-1 do
		Text.Value = "Voting maps: "..tostring(i)
		wait(1)
	end
	for _,v in ipairs(Corountines) do
		v = nil
	end
	local maxNumber = 1
	local MN = 0
	for i = 1,3 do
		if Numbers[i] then
			if Numbers[i] > MN then
				maxNumber = i
				MN = Numbers[i]
			end
		end
	end
    CM = Numbers[maxNumber]
	Corountines = nil
    local WinnerNumber = 1
	local ChosenMap = Maps[CM]	
	local ChangeGui = script[GameModeData.ChosenGuiName]
	local Data = ChosenMap:WaitForChild('Data')
	local GameEnded = false
	Text.Value = 'We will play '..ChosenMap.Name
	DisableChoser()
	wait(3)
	for _,Player in ipairs(game.Players:GetChildren()) do
		ChangeGui:Clone().Parent = Player:WaitForChild("PlayerGui")
	end
	for i = ChosingTime,1,-1 do
		wait(1) do
			Text.Value = string.format('Chosing Teams %s',i)	
		end
	end
	for _,Player in ipairs(game.Players:GetChildren()) do
		if Player:WaitForChild("PlayerGui"):FindFirstChild('ChangeTeam') then
			Player:WaitForChild("PlayerGui"):FindFirstChild(ChangeGui.Name):Destroy()	
		end
	end
	local NewFolder = Instance.new("Folder",workspace.CurrentMinigame) ; NewFolder.Name = ChosenMap.Name
	local SpawnsFolder = Instance.new("Folder",NewFolder) ; SpawnsFolder.Name = 'Spawns'
	local BuildingsFolder = Instance.new("Folder",NewFolder) ; BuildingsFolder.Name = 'Buildings'
		
	for _, SpawnFolder in ipairs(ChosenMap:FindFirstChild('Spawns'):GetChildren()) do
		SpawnFolder:Clone().Parent = SpawnsFolder
	end
		local Respawns = table.create(#game.Players:GetChildren())
		for _,Player in ipairs(TagModule:GetTagged()) do
			if not table.find(Respawns,Player) then
				Respawns[Player] = 0
			end
		end
	for _, i in ipairs(ChosenMap:FindFirstChild('Buildings'):GetChildren()) do
		i.Parent = BuildingsFolder
	end
		for _,Player in ipairs(game.Players:GetChildren()) do
			if Player.AFK.Value == false and Player.Character.Team ~= 'Spectators' then
				Player.Character.Archivable = true
			    TagModule:SetTag(Player.Character)
			end
		end
		
		local Connections
		do
		Connections = table.create(#game.Players:GetChildren())
		end
		for _,Character in ipairs(TagModule:GetTagged()) do
			local hum = Character:FindFirstChildOfClass('Humanoid')
			if hum then
			coroutine.wrap(function()
			local con ; con = hum.Died:Connect(function()
			    if Respawns[Character.Name] < 3 then
				    Respawn(Character:FindFirstChild('Head').CFrame,Character)
				    Respawns[Character.Name] = Respawns[Character.Name] + 1
				    table.insert(Connections,con)
			    else
				    con:Disconnect()
				    con = nil
		            local num = table.find(Connections,con)
		            if num then
			           table.remove(Connections,con)
			        end
				end
			end)
			end)()
		end
	end
	for _,Player in ipairs(TagModule:GetTagged()) do
		local team = Player:WaitForChild('Team')
		if not team.Value == 'Team1' and not team.Value == nil then
			local Spawns = workspace[ChosenMap.Name]:FindFirstChild(team.Value..'Spawns')
			local n = math.random(1,#Spawns:GetChildren())
		    local TSpawn = Spawns:GetChildren()[n]
			Player:SetPrimaryPartCFrame(TSpawn.CFrame)
			GireArmor(Player.Character,team.Value)
		end
	end
		local DoTeam = require(script.ClassesMain)
		for _,Character in ipairs(TagModule:GetTagged()) do
		  if KniveMode == false then
			DoTeam:DoClass(Character,Character:WaitForChild('Team').Value)
			else
				local BackPack = game.Players:GetPlayerFromCharacter(Character):WaitForChild('BackPack')
			    script.Knife:Clone().Parent = BackPack
			end
		end
	     
		local t = GameTime
		
		 repeat
			     t = t - 1
				 Text.Value = string.format('Game ends in %s',t)
				wait(1)
		until #TagModule:GetTagged() <= 1 or t == 0
		
		for i,Connection in ipairs(Connections) do
			Connection:Disconnect()
		end
	    GameEnded = true

		if GameEnded == true then
			delay(2,function()
			for _,Player in ipairs(game.Players:GetChildren()) do
				local Kills = Player.Character.Kills
				Kills.Value = 0
				local Team = Player.Character.Team
				Team.Value = 'Spectators'
				end
			end)
		end
		
		if #TagModule:GetTagged() == 0 then
            Text.Value = 'No One Wins!'
		elseif #TagModule:GetTagged() == 1 then
			local Winner = TagModule:GetTagged()[1]
			local PWinner = game.Players:GetPlayerFromCharacter(Winner)
			PWinner.leaderstats:FindFirstChild('Wins').Value = PWinner.leaderstats:FindFirstChild('Wins').Value + 1
			PWinner.leaderstats:FindFirstChild('Points').Value = PWinner.leaderstats:FindFirstChild('Points').Value + 15
			local Val = ChangeTT(Winner.Team.Value) or 'Spectators'
			Text.Value = Val..' has won!'
		elseif #TagModule:GetTagged() >= 2 then
		    local OldBestWin = 0
			for _,Player in ipairs(TagModule:GetTagged()) do
				if Player.Kills.Value > OldBestWin then
					OldBestWin = Player.Kills.Value
				end
			end
			local Winner = nil
			delay(0.2,function()
			    for _,Character in ipairs(TagModule:GetTagged()) do
					for _,Children in ipairs(Character:GetChildren()) do
				   if Children.Name == 'Kills' and Character.Team.Value ~= 'Spectators' then
					    if Children.Value == OldBestWin then
						   Winner = game.Players:GetPlayerFromCharacter(Character)
							end
						end
					end
				end
			end)
				delay(0.2,function()
				 Winner.leaderstats:FindFirstChild('Wins').Value = Winner.leaderstats:FindFirstChild('Wins').Value + 1
				 Winner.leaderstats:FindFirstChild('Points').Value = Winner.leaderstats:FindFirstChild('Points').Value + 15
				 Text.Value = ChangeTT(Winner.Team.Value)..' Has Won'
			end)
		end
		
		for _,Character in ipairs(TagModule:GetTagged()) do
			TagModule:DeleteTagged(Character)
			local plr = game.Players:GetPlayerFromCharacter(Character)
			plr.Character.Parent = workspace
			plr:LoadCharacter()
		end
		
		workspace.CurrentMinigame:ClearAllChildren()
	else
		Text.Value = 'You need to be at least '..tostring(MinPlayers)..' players  to play!'
	end
end

Make a post if you find something that should be changed.

Vote here how the script is:

  • Very Good
  • Good
  • Bad
  • Very Bad

0 voters

1 Like

Mostly the code is not bad, it’s fine. I put “Good”, but really I mean “Not bad”
One thing I must note, is this part

function ChangeTT(self)
	if self == 'Team1' then
		return 'Heavy'
	elseif self == 'Team2' then
		return 'Sniper'
	elseif self == 'Team3' then
		return 'Shock'
	elseif self == 'Team4' then
		return 'Medic'
	elseif self == 'Team5' then
		return 'Warrior'
	elseif self == 'Team6' then
		return 'Rouge'
	elseif self == 'Team7' then
		return 'Bombarder'
	elseif self == 'Team8' then
		return 'Blackout'
	end
end

Instead, you can put all the weapons inside of a dictionarry, and return the value corresponding to the given key self.

function ChangeTT(self)
     local Teams = {Team1 = "Heavy", Team2 = "Sniper", Team3 ...and put all the teams in here

     return Teams[self]
3 Likes

I am unsure why you have this remote event and I do not know why this is being placed in server storage?

If this is being accessed by the client (assuming its places in rep storage, workspace ect) they any client can freely change their team at will.

game.ServerStorage.Mains.ChangeTeam.OnServerEvent:Connect(function(plr,team) 
local chr = plr.Character
chr.Team.Value = team 
end)
1 Like

Thanks for finding this out! I will repair it.

I changed that function in this:

function ChangeTT(self)
	local Teams = {["Team1"]="Heavy",["Team2"]="Sniper",["Team3"]="Shock",["Team4"]="Medic",["Team5"]="Warrior",["Team6"]="Rouge",["Team7"]="Bombarder",["Team8"]="Blackout"}
	local IsFound,Name = false,nil
	for TeamName,TeamRealName in pairs(Teams) do
		if TeamName == self then
			IsFound = true
			Name = TeamRealName
			break
		end
	end
	return IsFound and Name or self
end

Use local functions where possible.

There is no need for a loop in this case as you can index it directly.

local temList = {
	Team1 = 'Heavy',
	Team2 = 'Sniper'
}

local function ChangeTT(teamName) -- self is realy misleading 
	return temList[teamName] and temList[teamName] or teamName
end
1 Like

Just make a dictionary table for this.

For example, the code

function example(...)

local value = ...

if value == "bruh" then
   return "why you bruh me"
elseif value == "joe" then
   return "mama, but it's a dead meme :("
end

end

local myValue = example("bruh") -- Returns "why you bruh me"

can be shortened to:

local example= {
   bruh = "why you bruh me",
   joe = "mama, but it's a dead meme :("
}

local myValue = example["bruh"] -- Returns "why you bruh me"

Don’t teleport the head! Use one of the three methods below:

  • char.HumanoidRootPart.CFrame = cframehere
  • char.PrimaryPart.CFrame = cframehere
  • char:SetPrimaryPartCFrame(cframehere) -- Best one!

This is just a bad function. What does this even do?


NEVER, EVER USE WHILE WAIT(), REPEAT WAIT, OR SIMILAR METHODS!
Always, always put a number in the wait() when possible, and make it as high as possible.


Once you fix those, I can help fix some more issues.
I honestly hope I helped :slight_smile:

2 Likes

Keep in mind you have to have your table inside a function, do method, or somthing similar, as weak tables don’t get garbage collected.

This is a old topic and I repaired that problems some weeks ago.

1 Like