Round system halts when player joins mid game

Here is the round system code. Basically a murder mystery game. When a player joins while a game is in progress (with 2 players in the current round), the round never ends so something goes wrong. I’m assuming line 64 is at fault here. If anyone could have a quick scan that would be great :slight_smile:

--> SERVICES
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Teams = game:GetService("Teams")
local SoundService = game:GetService("SoundService")

--> FOLDERS
local MapFolder = ServerStorage.Maps
local Console = script.Parent
local UI_Events = game:GetService("ReplicatedStorage").MainUI_Events

--> MODULES
local Maps = require(ServerStorage.MapsModule)

--> OBJECTS
local Pads = Console.Pads
local ScreenNames = Console.Screens.Names
local ScreenImages = Console.Screens.Images
local Count1 = ScreenImages.Image1.SurfaceGui.TextLabel
local Count2 = ScreenImages.Image2.SurfaceGui.TextLabel
local Count3 = ScreenImages.Image3.SurfaceGui.TextLabel
local Title = Console.Title.SurfaceGui.TextLabel

--> LOCAL VARIABLES
local MapVote = false
local InProgress = false
local RoundTime = 120
local ChosenMap
local Map1
local Map2
local Map3

--> FUNCTIONS
local function MainGame(Map)
	if #Players:GetPlayers() == 1 then 
		Title.Text = "2 PLAYERS REQUIRED"
	return end
	InProgress = true
	local Plr_Murderer = Teams.Intermission:GetPlayers()[math.random(#Teams.Intermission:GetPlayers())]
	Plr_Murderer.Team = Teams.Murderer
	local Plr_Sheriff = Teams.Intermission:GetPlayers()[math.random(#Teams.Intermission:GetPlayers())]
	Plr_Sheriff.Team = Teams.Sheriff
	if #Teams.Intermission:GetPlayers() > 0 then
		local Innocents = Teams.Intermission:GetPlayers()
		for i, v in pairs(Innocents) do
			v.Team = Teams.Innocents
		end
	end
	UI_Events.TransitionScreen:FireAllClients()
	wait(1)
	for i, v in pairs(Players:GetPlayers()) do
		v:LoadCharacter()
	end
	ServerStorage.Weapons.Sword:Clone().Parent = Plr_Murderer.Backpack
	ServerStorage.Weapons.Gun:Clone().Parent = Plr_Sheriff.Backpack
	local StartTime = tick()
	repeat wait(.5) 
		for i, v in pairs(Players:GetPlayers()) do
			v.Character.Humanoid.Died:Connect(function()
				wait()
				v.Team = Teams.Intermission
			end)
		end	
	until tick() - StartTime >= RoundTime or #Teams.Murderer:GetPlayers() == 0 or #Teams.Sheriff:GetPlayers() == 0 and #Teams.Innocent:GetPlayers() == 0
	wait(5)
	UI_Events.TransitionScreen:FireAllClients()
	wait(1)
	for i, v in pairs(Players:GetPlayers()) do
		if v.Team == Teams.Innocent or v.Team == Teams.Murderer or v.Team == Teams.Sheriff then
			v.Team = Teams.Intermission
			v:LoadCharacter()
		end
	end
end

local function Reset()
	Count1.Count.Value = 0
	Count2.Count.Value = 0
	Count3.Count.Value = 0
	Count1.Text = 0
	Count2.Text = 0
	Count3.Text = 0
	for i, Plr in pairs(Players:GetPlayers()) do
		Plr.Vote.Value = 0
	end
	ChosenMap = nil
	InProgress = false
end

local function ChooseMaps()
	for i, plr in pairs(Players:GetChildren()) do
		if plr:FindFirstChild("Map") then
			plr.Map.Value = 0
		end
	end
	local MapList = Maps:GetMaps()
	for i = 1, 3 do
		if i == 1 then
			map1 = table.remove(MapList, math.random(1, #MapList))
			ScreenNames.Name1.SurfaceGUI.Map.Text = map1.Name
			ScreenImages.Image1.SurfaceGui.ImageLabel.Image = "rbxassetid://" ..map1.Image
		elseif i == 2 then
			map2 = table.remove(MapList, math.random(1, #MapList))
			ScreenNames.Name2.SurfaceGUI.Map.Text = map2.Name
			ScreenImages.Image2.SurfaceGui.ImageLabel.Image = "rbxassetid://" ..map2.Image
		elseif i == 3 then
			map3 = table.remove(MapList, math.random(1, #MapList))
			ScreenNames.Name3.SurfaceGUI.Map.Text = map3.Name
			ScreenImages.Image3.SurfaceGui.ImageLabel.Image = "rbxassetid://" ..map3.Image
		end
	end
end

local function SelectVotedMap()
	if Count1.Count.Value > Count2.Count.Value and Count1.Count.Value > Count3.Count.Value then
		ChosenMap = map1
	elseif Count2.Count.Value > Count1.Count.Value and Count2.Count.Value > Count3.Count.Value then
		ChosenMap = map2
	elseif Count3.Count.Value > Count1.Count.Value and Count3.Count.Value > Count2.Count.Value then
		ChosenMap = map3
	elseif Count1.Count.Value == Count2.Count.Value and Count1.Count.Value > Count3.Count.Value then
		ChosenMap = "map"..math.random(1,2)
	elseif Count1.Count.Value == Count3.Count.Value and Count1.Count.Value > Count2.Count.Value then
		local Options = {1,3}
		local Number = Options[math.random(1, #Options)]
		if Number == 1 then
			ChosenMap = 1
		elseif Number == 3 then
			ChosenMap = 3
		end
	elseif Count2.Count.Value == Count3.Count.Value and Count2.Count.Value > Count1.Count.Value then
		local Number = math.random(2,3)
		if Number == 2 then
			ChosenMap = map2
		elseif Number == 3 then
			ChosenMap = map3
		end
	elseif Count1.Count.Value == Count2.Count.Value and Count1.Count.Value == Count3.Count.Value then
		local Number = math.random(1,3)
		if Number == 1 then
			ChosenMap = map1
		elseif Number == 2 then
			ChosenMap = map2
		elseif Number == 3 then
			ChosenMap = map3
		end
	end
	local MapClone = MapFolder:FindFirstChild(ChosenMap.Name):Clone()
	MapClone.Parent = workspace
	MapClone:MakeJoints()
	return MapClone
end

local function vote(Player, VotedMap, Count, PlayerVote)
	if PlayerVote == VotedMap then
		return
	elseif PlayerVote == 0 then
		Player.Vote.Value = VotedMap
		Count.Count.Value += 1
		Count.Text = Count.Count.Value
	elseif VotedMap == 1 then
		if PlayerVote == 2 then
			Count2.Count.Value -= 1
			Count2.Text = Count2.Count.Value
		elseif PlayerVote == 3 then
			Count3.Count.Value -= 1
			Count3.Text = Count3.Count.Value
		end
		Player.Vote.Value = VotedMap
		Count1.Count.Value += 1	
		Count1.Text = Count1.Count.Value
	elseif VotedMap == 2 then
		if PlayerVote == 1 then
			Count1.Count.Value -= 1
			Count1.Text = Count1.Count.Value
		elseif PlayerVote == 3 then
			Count3.Count.Value -= 1
			Count3.Text = Count3.Count.Value
		end
		Player.Vote.Value = VotedMap
		Count2.Count.Value += 1	
		Count2.Text = Count2.Count.Value
	elseif VotedMap == 3 then
		if PlayerVote == 1 then
			Count1.Count.Value -= 1
			Count1.Text = Count1.Count.Value
		elseif PlayerVote == 2 then
			Count2.Count.Value -= 1
			Count2.Text = Count2.Count.Value
		end
		Player.Vote.Value = VotedMap
		Count3.Count.Value += 1	
		Count3.Text = Count3.Count.Value
	end	
end

local function StartGame()
	ChooseMaps()
	MapVote = true
	for i = 15, 0, -1 do
		Title.Text = "VOTE FOR MAP: " ..i
		if i <= 5 then
			Title.TextColor3 = Color3.new(1, 0, 0)
			wait(0.5)
			Title.TextColor3 = Color3.new(1, 1, 1)
			wait(0.5)
		else
			wait(1)
		end
	end
	Title.Text = "ROUND IN PROGRESS"
	MapVote = false
	local SpawnedMap = SelectVotedMap()
	MainGame(SpawnedMap)
	SpawnedMap:Destroy()
	for i, v in pairs(game.Workspace:GetChildren()) do
		if v.Name == "RAGDOLL" then
			v:Destroy()
		end
	end
	wait(1)
	Reset()
	for i = 1, 3 do
		Title.Text = "LOADING MAPS"
		wait(0.2)
		Title.Text = "LOADING MAPS."
		wait(0.2)
		Title.Text = "LOADING MAPS.."
		wait(0.2)
		Title.Text = "LOADING MAPS..."
		wait(0.2)
	end
end

--> CODE
Pads.Map1.Touched:Connect(function(hit)
	if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Humanoid.Health > 0 and MapVote == true then
		local Plr = Players:GetPlayerFromCharacter(hit.Parent)
		vote(Plr, 1, Count1, Plr.Vote.Value)
	end
end)

Pads.Map2.Touched:Connect(function(hit)
	if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Humanoid.Health > 0 and MapVote == true then
		local Plr = Players:GetPlayerFromCharacter(hit.Parent)
		vote(Plr, 2, Count2, Plr.Vote.Value)
	end
end)

Pads.Map3.Touched:Connect(function(hit)
	if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Humanoid.Health > 0 and MapVote == true then
		local Plr = Players:GetPlayerFromCharacter(hit.Parent)
		vote(Plr, 3, Count3, Plr.Vote.Value)
	end
end)

coroutine.wrap(function()
	while true do
		pcall (function()
			wait(3)
			if #game.Players:GetPlayers() > 1 and InProgress == false then
				StartGame()
			end
		end)
		wait(2)
	end
end)()
repeat wait(.5) 
		for i, v in pairs(Players:GetPlayers()) do
			v.Character.Humanoid.Died:Connect(function()
				wait()
				v.Team = Teams.Intermission
			end)
		end	
	until

I feel as if it may have something to do with this section. If a player joins mid game their character may not be loaded causing an error.

Also could that be included above the repeat loop? It seems unnecessary to have it repeat every 0.5 seconds

I found the issue. I needed to define the alive players for the loop not to play for players who just joined. I did this by doing:

local AlivePlayers = Players:GetPlayers()
	repeat wait(.5) 
		for i, v in pairs(AlivePlayers) do
			v.Character.Humanoid.Died:Connect(function()
				wait()
				v.Team = Teams.Intermission
			end)
		end	
	until tick() - StartTime >= RoundTime or #Teams.Murderer:GetPlayers() == 0 or #Teams.Sheriff:GetPlayers() == 0 and #Teams.Innocent:GetPlayers() == 0