How do I fix this intermission system issue? Where did I go wrong?

I have made an intermission system, and it works when it’s only one player, however, when there are two+ players, it gets stuck on intermission after the first round.

Server:

local DSS = game:GetService("DataStoreService")
local TotalWinsStore = DSS:GetDataStore("BETAWins")
local TotalKillsStore = DSS:GetDataStore("BETAKills")
local TimeLeft = 20
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local GUIChanger = ReplicatedStorage:WaitForChild("GUIChanger")
local GUIChangerTwo = ReplicatedStorage:WaitForChild("GUIChangerB")
local GUIChangerThree = ReplicatedStorage:WaitForChild("GUIChangerC")

wait(1)

game.Players.PlayerAdded:Connect(function(p)
	local leaderstats = Instance.new("Folder", p)
	leaderstats.Name = "leaderstats"
	local TotalWins = Instance.new("IntValue", leaderstats)
	TotalWins.Name = "Wins"
	TotalWins.Value = 0
	local TotalKills = Instance.new("IntValue", leaderstats)
	TotalKills.Name = "Total Kills"
	TotalKills.Value = 0
	local RoundKills = Instance.new("IntValue", leaderstats)
	RoundKills.Name = "Round Kills"
	RoundKills.Value = 0
	local Playing = Instance.new("BoolValue", p)
	Playing.Name = "Playing"
	Playing.Value = false
	
	local data
	local dataII
	local success, errormessage = pcall(function()
		data = TotalWinsStore:GetAsync(p.UserId.."-wins")
		dataII = TotalKillsStore:GetAsync(p.UserId.."-kills")
	end)
	
	if success then
		p.leaderstats["Wins"].Value = data
		p.leaderstats["Total Kills"].Value = dataII
		print("Data saved!")
	else
		warn(errormessage)
		print("Error while loading data!")
	end
end)

game.Players.PlayerRemoving:Connect(function(p)
	local success, errormessage = pcall(function()
		TotalWinsStore:SetAsync(p.UserId.."-wins", p.leaderstats["Wins"].Value)
		TotalKillsStore:SetAsync(p.UserId.."-kills", p.leaderstats["Total Kills"].Value)
	end)
	
	if success then
		print("Success!")
	else
		warn(errormessage)
		print("Error while saving data!")
	end
end)

while true do
	repeat
		wait(1)
		TimeLeft = TimeLeft - 1
		GUIChanger:FireAllClients(TimeLeft)
	until TimeLeft == 0
	
	wait(2)
	
    for i,v in pairs(game.Players:GetPlayers()) do
        spawna = game.Workspace.A
        spawnb = game.Workspace.B
        spawnc = game.Workspace.C
        spawnd = game.Workspace.D
        spawne = game.Workspace.E
        
        local spawns = {spawna, spawnb, spawnc, spawnd, spawne}
        local random = math.random(1, #spawns)
        local picked = spawns[random]
        
        v.Playing.Value = true
        
        v.Character.HumanoidRootPart.Position = picked.Position
        wait(0.1)
    end
    
    GUIChangerTwo:FireAllClients()
    
    local alldead = false
    while alldead == false do
        wait()
        local allpdead = true
        for i,v in pairs(game.Players:GetPlayers()) do
            if v.Playing.Value == true and v.Character.Humanoid.Health > 0 then
                allpdead = false
            end
        end  
        if allpdead then
            alldead = true
            break
        end
    end
	
	function higherScoreThan(playerA, playerB)
    	return playerA.leaderstats.Score.Value > playerB.leaderstats.Score.Value
	end


	local players = {}
	for _, player in pairs(game.Players:GetPlayers()) do
    	if player:FindFirstChild("leaderstats") and player.leaderstats:FindFirstChild("Round Kills") then
        	table.insert(players, player)
    	end
	end

	table.sort(players, higherScoreThan)

	if players[1] then
		local Winner = players[1].Name
		GUIChangerThree:FireAllClients(Winner)
		players[1].leaderstats["Wins"].Value = players[1].leaderstats["Wins"].Value + 1
	end
	
	for i,v in pairs(game.Players:GetPlayers()) do
		v.leaderstats["Total Kills"].Value = v.leaderstats["Total Kills"].Value + v.leaderstats["Round Kills"].Value
		wait(0.5)
		v.leaderstats["Round Kills"].Value = 0
	end
	
	wait(6)
	
	TimeLeft = 20
end

Client:

 local ReplicatedStorage = game:GetService("ReplicatedStorage")
local GUIChanger = ReplicatedStorage:WaitForChild("GUIChanger")
local GUIChangerTwo = ReplicatedStorage:WaitForChild("GUIChangerB")
local GUIChangerThree = ReplicatedStorage:WaitForChild("GUIChangerC")

local function Change(TimeLeft)
	local TextLabel = game.Players.LocalPlayer.PlayerGui.Intermission.TextFrame.TextLabel
	TextLabel.Text = " - Intermission ("..TimeLeft..") - "
end

local function ChangeTwo()
	local TextLabel = game.Players.LocalPlayer.PlayerGui.Intermission.TextFrame.TextLabel
	TextLabel.Text = " - Round in Progress - "
end

local function ChangeThree(Winner)
	local TextLabel = game.Players.LocalPlayer.PlayerGui.Intermission.TextFrame.TextLabel
	TextLabel.Text = " - Round Winner: "..Winner.." - "
end

GUIChanger.OnClientEvent:Connect(Change)
GUIChangerTwo.OnClientEvent:Connect(ChangeTwo)
GUIChangerThree.OnClientEvent:Connect(ChangeThree)

No errors.

This part here may spark the problem, in the first round (where the server is still fresh), the TimeLeft value is set to 20 at the start of the script, the code loop runs until TimeLeft is 0. Okay, thats normal, the round goes normally, but on the second round, it freezes. Why? because in the second round, TimeLeft is still 0 and the loop runs once before checking if TimeLeft is exactly 0, at that point, TimeLeft has gone negative and will continue running forever.

So a fix for this would be:

while true do
    TimeLeft = 20
    repeat
        wait(1)
        TimeLeft = TimeLeft - 1
		GUIChanger:FireAllClients(TimeLeft)
	until TimeLeft == 0

It still doesn’t work with two players. It just freezes.

I’m afraid i can’t help you any further until i have more information. you should use print() to properly dissect the problem like:

while true do
    TimeLeft = 20
    repeat
        wait(1)
        TimeLeft = TimeLeft - 1
		GUIChanger:FireAllClients(TimeLeft)
        print("Currently at "..TimeLeft)
	until TimeLeft == 0
    print("TimeLeft is 0")

just put prints whenever something happens in the script, and if it doesnt print, thats where your problem is.