-- Constants
local PlayersRequiredToStartAwardingPoints = 4
local SpawnDistanceThreshold = 500
local PointsAward = 100
local CooldownTime = 1 -- Cooldown in seconds
-- Helper Functions
local function getTeams()
local teams = {}
for _, team in pairs(game.Teams:GetTeams()) do
if team.AutoAssignable then
table.insert(teams, team)
end
end
return teams
end
local function assignPlayersToTeams()
local teams = getTeams()
local players = game.Players:GetPlayers()
local numberOfTeams = #teams
local numberOfPlayers = #players
if numberOfTeams == 0 or numberOfPlayers == 0 then
return
end
local playersPerTeam = math.floor(numberOfPlayers / numberOfTeams)
local leftoverPlayers = numberOfPlayers - (playersPerTeam *
numberOfTeams)
local teamCounts = {}
for _, team in ipairs(teams) do
teamCounts[team] = 0
for i = 1, playersPerTeam do
local playerIndex = math.random(1, #players)
local player = players[playerIndex]
if player then
player.TeamColor = team.TeamColor
teamCounts[team] = teamCounts[team] + 1
table.remove(players, playerIndex)
end
end
end
for i = 1, leftoverPlayers do
local playerIndex = math.random(1, #players)
local player = players[playerIndex]
local teamIndex = math.random(1, #teams)
local team = teams[teamIndex]
if player and team then
player.TeamColor = team.TeamColor
table.remove(players, playerIndex)
table.remove(teams, teamIndex)
end
end
end
local function balanceTeams()
local players = game.Players:GetPlayers()
local teams = getTeams()
local teamCounts = {}
if #teams == 0 or #players == 0 then
return
end
for _, team in pairs(teams) do
teamCounts[team] = 0
for _, player in pairs(players) do
if player.TeamColor == team.TeamColor then
teamCounts[team] = teamCounts[team] + 1
end
end
end
while true do
local smallestTeam = next(teamCounts)
local largestTeam = smallestTeam
for team, count in pairs(teamCounts) do
if count < teamCounts[smallestTeam] then
smallestTeam = team
end
if count > teamCounts[largestTeam] then
largestTeam = team
end
end
if (teamCounts[largestTeam] - teamCounts[smallestTeam]) > 1 then
for _, player in pairs(players) do
if player.TeamColor == largestTeam.TeamColor then
player.TeamColor = smallestTeam.TeamColor
teamCounts[smallestTeam] =
teamCounts[smallestTeam] + 1
teamCounts[largestTeam] =
teamCounts[largestTeam] - 1
break
end
end
else
return
end
end
end
local function regenerateMap()
-- Assuming this function is called to regenerate the map
-- Make sure leaderstats are preserved and not reset
script.RegenScriptLocation.Value.Signal.Value = true
end
local function resetAllPlayers()
for _, player in pairs(game.Players:GetPlayers()) do
local character = player.Character
if character then
-- Reset player character
character:BreakJoints() -- Removes all joints in the
character, effectively resetting it
player:LoadCharacter() -- Reloads the player's character
end
end
end
local function manageSpawns()
local baseplate = workspace:FindFirstChild("Baseplate")
if baseplate then
local spawns = workspace.Doomspires:GetDescendants()
local spawnsCount = 0
for _, spawn in ipairs(spawns) do
if spawn:IsA("SpawnLocation") then
if (spawn.Position - baseplate.Position).magnitude >
SpawnDistanceThreshold then
spawn:Destroy()
else
spawnsCount = spawnsCount + 1
end
end
end
if spawnsCount <= 0 then
warn("Game might have broken, regenerating")
regenerateMap()
resetAllPlayers()
wait(CooldownTime) -- Wait for cooldown before allowing
further actions
end
else
for _, player in ipairs(game.Players:GetPlayers()) do
player:Kick("Possible exploit, shutting down server")
end
end
end
local function teleportPlayersToTeams()
for _, player in pairs(game.Players:GetPlayers()) do
local playerTeam =
game.Teams:FindFirstChild(player.TeamColor.Name)
if playerTeam then
local spawnLocations =
workspace.Doomspires:FindFirstChild(playerTeam.Name):GetChildren()
local spawnLocation = nil
for _, location in pairs(spawnLocations) do
if location:IsA("SpawnLocation") then
spawnLocation = location
break
end
end
if spawnLocation then
player.Character:SetPrimaryPartCFrame(spawnLocation.CFrame)
end
end
end
end
function AssignableTeams()
local assignableTeams = {}
for _, team in pairs(game.Teams:GetTeams()) do
if team.AutoAssignable then
table.insert(assignableTeams, team)
end
end
return assignableTeams
end
script:WaitForChild("ShuffleTeams").OnInvoke = function()
local teams = AssignableTeams()
local numberOfTeams = #teams
local playersList = game.Players:GetPlayers()
local numberOfPlayers = #playersList
-- Quit early if there are no teams, this avoids a divide by zero
if #teams == 0 or #playersList == 0 then
return
end
local playersPerTeam = math.floor(numberOfPlayers / numberOfTeams)
local leftOverPlayers = numberOfPlayers - (playersPerTeam *
numberOfTeams)
local teamCount = {}
for _, team in ipairs(teams) do
teamCount[team] = 0
for i = 1, playersPerTeam do
local k = math.random(1, #playersList)
local player = playersList[k]
if player then
player.TeamColor = team.TeamColor
teamCount[team] = teamCount[team] + 1
table.remove(playersList, k)
end
end
end
-- Now place the remaining players
for i = 1, leftOverPlayers do
local k, player = next(playersList)
local teamIndex = math.random(1, #teams)
local team = teams[teamIndex]
if player and teamIndex then
player.TeamColor = team.TeamColor
table.remove(playersList, k)
table.remove(teams, teamIndex)
end
end
end
-- Main Script Execution
local function createAnnouncement(text, teamColor, playVictorySound)
local color = teamColor.Color
local soundService = game:GetService("SoundService")
local sound
if playVictorySound and not soundService:FindFirstChild("VictorySound") then
sound = Instance.new("Sound")
sound.Parent = soundService
sound.Name = "VictorySound"
sound.SoundId = "rbxassetid://6286482559"
sound.Volume = 1
end
for _, player in ipairs(game.Players:GetPlayers()) do
if player:FindFirstChild("PlayerGui") then
local gui = Instance.new("ScreenGui")
gui.Parent = player.PlayerGui
gui.Name = "AnnouncementGui"
local label = Instance.new("TextLabel")
label.Parent = gui
label.Size = UDim2.new(1, 0, 0.1, 0)
label.Position = UDim2.new(0, 0, 0.4, 0)
label.BackgroundTransparency = 0.666
label.BackgroundColor3 = Color3.new(1, 1, 1) -- White color (RGB
values from 0 to 1)
label.TextColor3 = color
label.Font = Enum.Font.FredokaOne
label.TextSize = 32
label.Text = text
label.TextTransparency = 0
if sound then
sound:Play()
end
wait(2) -- Show the message for 4 seconds
game:GetService("Debris"):AddItem(gui, 1)
end
end
if sound then
game:GetService("Debris"):AddItem(sound, 3)
end
end
local function setupGame()
local y = workspace:GetDescendants()
for s = 1, #y do
if y[s].Name == "Doomspires" then
local GVF = Instance.new("Folder")
GVF.Parent = y[s]
GVF.Name = "GameValues"
local TF = Instance.new("Folder")
TF.Parent = GVF
TF.Name = "Teams"
local TeamsLeftInt = Instance.new("IntValue")
TeamsLeftInt.Parent = GVF
TeamsLeftInt.Name = "TeamsLeft"
local k = y[s]:GetChildren()
for o = 1, #k do
if not k[o]:IsA("Script") and k[o].Name ~= "GameValues" and
k[o].Name ~= "Holder" then
local BCV = Instance.new("BrickColorValue")
BCV.Parent = TF
BCV.Name = k[o].Name
local SpawnVal = Instance.new("IntValue")
SpawnVal.Parent = BCV
SpawnVal.Name = "Spawns"
local u = k[o]:GetDescendants()
for h = 1, #u do
if u[h]:IsA("SpawnLocation") then
BCV.Value = u[h].TeamColor
SpawnVal.Value =
#u[h].Parent:GetChildren()
end
end
end
end
TeamsLeftInt.Value = #TF:GetChildren()
local x = y[s]:GetDescendants()
for i = 1, #x do
if x[i]:IsA("SpawnLocation") then
x[i].AncestryChanged:Connect(function(SpawnPart)
local c = y[s]:WaitForChild("GameValues",
1):WaitForChild("Teams", 1):GetChildren()
for g = 1, #c do
if SpawnPart:IsA("SpawnLocation") and
c[g].Value == SpawnPart.TeamColor then
local spawns =
c[g]:WaitForChild("Spawns", 1)
spawns.Value = spawns.Value - 1
if spawns.Value == 0 then
local teamsLeft =
y[s]:WaitForChild("GameValues", 1):WaitForChild("TeamsLeft", 1)
teamsLeft.Value =
teamsLeft.Value - 1
game.Teams:FindFirstChild(c[g].Name).AutoAssignable = false
createAnnouncement(c[g].Name .. " TEAM has been eliminated!", c[g].Value)
-- ✅ Team remaining
announcement
createAnnouncement("Teams
Remaining: " .. tostring(teamsLeft.Value), BrickColor.White())
end
end
end
local teamsLeft =
y[s]:WaitForChild("GameValues", 1):WaitForChild("TeamsLeft", 1)
if teamsLeft.Value == 1 then
local e = y[s]:WaitForChild("GameValues",
1):WaitForChild("Teams", 1):GetDescendants()
for j = 1, #e do
if e[j].Name == "Spawns" and
e[j].Value ~= 0 then
wait(2)
local winningTeamName =
e[j].Parent.Name
local winningTeamColor =
e[j].Parent.Value
createAnnouncement(winningTeamName .. " TEAM has won the game🏆",
winningTeamColor, true)
for _, player in
ipairs(game.Players:GetPlayers()) do
if player.TeamColor ==
winningTeamColor then
local playerStats
= player:FindFirstChild("leaderstats")
if playerStats
then
local wins =
playerStats:FindFirstChild("Wins")
if wins then
wins.Value = wins.Value + 1
end
end
end
end
regenerateMap()
resetAllPlayers()
-- ✅ Countdown with dot-dot-
dot movement
spawn(function()
for i = CooldownTime, 1,
-1 do
local dots =
string.rep(".", (CooldownTime - i) % 4)
createAnnouncement("Restarting in " .. i .. " seconds" .. dots,
BrickColor.White())
wait(2)
end
end)
wait(CooldownTime)
teleportPlayersToTeams()
return
end
end
end
end)
end
end
end
end
end
setupGame()
-- Main Game Loop
while wait(10) do
manageSpawns()
end
-- Team Shuffle and Balance Functions
script:WaitForChild("ShuffleTeams").OnInvoke = assignPlayersToTeams
script:WaitForChild("BalanceTeams").OnInvoke = balanceTeams