Timer stops when killer leaves game

Hello, I’m creating a murder type game where one player is selected as the killer while the rest are meant to survive. The issue I’m having is that when the killer leaves the game, the timer stops working and the round is stuck indefinitely. I tried using “Player.PlayerRemoving” but its not working properly in the script when I test it in an actual server. I also tried detecting if the player is “chosenSanic” but leaves then the round automatically resets since theres a function (gameReset), that resets the entire system.
The code:

local RepStore = game:GetService("ReplicatedStorage")
local MapsFolder = RepStore.Maps
local EventsFolder = RepStore.Events
local Status = RepStore.Status
local PlayersInGame = game.Workspace.PlayersInGame
local PlayerService = game:GetService("Players")
local PercentagesTable = {}
local MarketPlace = game:GetService("MarketplaceService")
local SanicPercentageBoostID = 1340188491-- put developer product Id here
local SanicGamepassID = 106350268-- put gamepass here
local MapClone = nil
local Selected = false
local highest = nil
local ChosenSanic = nil
local TouchDB = false

for i, v in pairs(game.Workspace:GetDescendants()) do
	if v.Name == "MainVote" then
		v.Touched:Connect(function(Hit)
			task.spawn(function()
				if TouchDB == false and Hit.Parent:FindFirstChild("Humanoid") then
					TouchDB = true
					local plr = game.Players:GetPlayerFromCharacter(Hit.Parent)
					local VoteTag = plr.PlayerInfo.VotedTag

					if VoteTag.Value == nil then
						v.Parent.Parent.Votes.Value += 1 
					else
						VoteTag.Value.Parent.Parent.Votes.Value = VoteTag.Value.Parent.Parent.Votes.Value - 1
						v.Parent.Parent.Votes.Value += 1 
					end

					for i, x in pairs(game.Workspace:GetDescendants()) do
						if x.Name == "MainVote" then
							x.Parent.Parent.VoteInfo.VoteCountUI.VoteText.Text = "Votes: "..x.Parent.Parent.Votes.Value
						end
					end

					VoteTag.Value = v

					task.wait(1)
					TouchDB = false
				end
			end)
		end)
	end
end

local function gameReset()
	Selected = false
	newSanicPart = nil
	table.clear(Chosen)
	table.clear(VotesTable)
	GameInfo["Minutes"] = 3
	GameInfo["Seconds"] = 20
end

PlayerService.PlayerAdded:Connect(function(Player)
	local PlayerInfo = Instance.new("Folder")
	PlayerInfo.Name = "PlayerInfo"
	PlayerInfo.Parent = Player

	local SanicPercentage = Instance.new("IntValue")
	SanicPercentage.Name = "Percentage"
	SanicPercentage.Value = 0
	SanicPercentage.Parent = PlayerInfo

	local Sanic = Instance.new("BoolValue")
	Sanic.Name = "Sanic"
	Sanic.Value = false
	Sanic.Parent = PlayerInfo

	local VotedTag = Instance.new("ObjectValue")
	VotedTag.Name = "VotedTag"
	VotedTag.Parent = PlayerInfo

	Player.CharacterAdded:Connect(function(char)
		--char.Parent = game:WaitForChild("Workspace")
		Player.PlayerInfo.Sanic.Value = false
	end)
end)

while true do
	wait(1)
	if #PlayerService:GetChildren() >= GameInfo["PlayersNeeded"] then -- checks if there are enough players before starting
		local minutes = GameInfo["Minutes"]
		local seconds = GameInfo["Seconds"]

		SelectRandomMaps()
		for i = 1, GameInfo["Intermission"] do
			wait(1)
			Status.Value = "Intermission: "..GameInfo["Intermission"] - i
		end

		if Status.Value == "Intermission: 0" and #PlayerService:GetChildren() >= GameInfo["PlayersNeeded"]  then
			for i, v in pairs(game.Workspace:GetDescendants()) do
				if v:IsA("IntValue") and v.Name == "Votes" then
					table.insert(VotesTable, v.Value)
				end
			end

			local highestVotes = math.max(unpack(VotesTable))

			for i, v in pairs(game.Workspace:GetDescendants()) do
				if v:IsA("IntValue") and v.Name == "Votes" then
					if v.Value == highestVotes then
						VotedMap = v.Parent.Map.Value
					end
				end
			end

			local MapClone = VotedMap:Clone()
			MapClone.Parent = game.Workspace
			print(MapClone.Name.." has been added to the workspace")

			Status.Value = MapClone.Name.." has been selected"
			wait(2)

			for i = 1, GameInfo["StartTime"] do
				wait(1)
				Status.Value = "Game starting in: "..GameInfo["StartTime"] - i
			end

			if Status.Value == "Game starting in: 0" and #PlayerService:GetChildren() >= GameInfo["PlayersNeeded"] then
				Status.Value = ""
				RepStore.Events.ResetClientVotes:FireAllClients()
				for i, v in pairs(game.Players:GetChildren()) do
					local Percentage = v.PlayerInfo.Percentage.Value
					table.insert(PercentagesTable, Percentage)
					print(PercentagesTable)
					print(v.Name.." has "..Percentage)
				end
				local highest = math.max(unpack(PercentagesTable))
				print(highest)

				for i, v in pairs(game.Players:GetChildren()) do -- loops through all the players and teleports them
					if v.PlayerInfo.Percentage.Value == highest and Selected == false then
						Selected = true
						local PlayerBoughtThisGamePass =  MarketPlace:UserOwnsGamePassAsync(v.UserId, SanicGamepassID)
						print(v.Name.." has been selected to be sanic")
						v.PlayerInfo.Sanic.Value = true
						ChosenSanic = v
						for i, x in pairs(v.Character:GetDescendants()) do
							if x:IsA("BasePart") then
								x.Transparency = 1
							end

							if x:IsA("Accessory") or x:IsA("Decal") then
								x:Destroy()
							end

						end
						local newSanicPart = nil

						if PlayerBoughtThisGamePass then
							ChosenSanic.Character.Humanoid.WalkSpeed = GameInfo["GoldSanicWalkspeed"]
							ChosenSanic.Character.Humanoid.JumpPower = GameInfo["GoldSanicJumpPower"]
							newSanicPart = RepStore:WaitForChild("GoldSanicModel"):Clone()

							newSanicPart.Touched:Connect(function(Hit)
								if Hit.Parent:FindFirstChild("Humanoid") and Hit.Parent:FindFirstChild("Humanoid").Health > 0 and Hit.Parent.Name ~= v.Name then
									newSanicPart.TooSlow:Play()
									Hit.Parent.Humanoid.Health = 0
									Hit.Parent:BreakJoints()

									for i, x in pairs(Hit.Parent:GetDescendants()) do
										if x:IsA("BasePart") then
											x.BrickColor = BrickColor.new("Gold")
										end
									end

									EventsFolder.GuiKill:FireClient(v, Hit.Parent.Name, v)
									game.Workspace.Data[v.Name].Socks.Value += GameInfo["KillReward"]
								end
							end)

							newSanicPart.Parent = game.Workspace
							newSanicPart.CFrame = ChosenSanic.Character.HumanoidRootPart.CFrame * CFrame.new(0,1,0)
						else
							ChosenSanic.Character.Humanoid.WalkSpeed = GameInfo["SanicWalkSpeed"]
							newSanicPart = RepStore:WaitForChild("SanicModel"):Clone()

							newSanicPart.Touched:Connect(function(Hit)
								if Hit.Parent:FindFirstChild("Humanoid") and Hit.Parent:FindFirstChild("Humanoid").Health > 0 and Hit.Parent.Name ~= v.Name then
									newSanicPart.TooSlow:Play()
									Hit.Parent.Humanoid.Health = 0
									Hit.Parent:BreakJoints()
									EventsFolder.GuiKill:FireClient(v, Hit.Parent.Name, v)
									game.Workspace.Data[v.Name].Socks.Value += GameInfo["KillReward"]
								end
							end)

							newSanicPart.Parent = game.Workspace
							newSanicPart.CFrame = ChosenSanic.Character.HumanoidRootPart.CFrame * CFrame.new(0,1,0)
						end

						local newWeld = Instance.new("WeldConstraint")
						newWeld.Parent = v.Character.HumanoidRootPart
						newWeld.Part0 = v.Character.HumanoidRootPart
						newWeld.Part1 = newSanicPart					
						newSanicPart.Anchored = false
						newSanicPart.CanCollide = false
					end

					local char = v.Character or v.CharacterAdded:Wait()
					game.Workspace.Data[v.Name].Socks.Value += GameInfo["PlayReward"]
					v.Character.Torso.CFrame = MapClone:WaitForChild("Spawns")[i].CFrame 
					char.Parent = PlayersInGame
				end

				for i, v in pairs(game.Players:GetChildren()) do -- this adds more percentage towards every other player that didn't get picked
					if ChosenSanic.Name == v.Name then
						EventsFolder.Role:FireClient(v, true, v)
					else
						EventsFolder.Role:FireClient(v, false, v)
					end

					if v.PlayerInfo.Percentage.Value <= 10 and v.PlayerInfo.Sanic.Value == false then
						v.PlayerInfo.Percentage.Value += 1
					elseif v.PlayerInfo.Sanic.Value == true then
						print(v.Name.." data has been reset")
						v.PlayerInfo.Percentage.Value = 0
					end
				end

				table.clear(PercentagesTable)
				game.Lighting.ClockTime = 1
				repeat 
					if seconds <= 0 then
						minutes = minutes - 1
						seconds = 59
					else
						seconds = seconds - 1
					end
					if seconds < 10 then
						Status.Value = tostring(minutes)..":0"..tostring(seconds)
					else
						Status.Value = tostring(minutes)..":".. tostring(seconds)	
					end	
					if minutes <= 0 then
						Status.Value = tostring(seconds)..""
					end

					wait(1)
				until (minutes <= 0 and seconds <= 0) or #PlayersInGame:GetChildren() <= 1 or not ChosenSanic.Character:FindFirstChild("Humanoid") or ChosenSanic.Character.Parent == game.Workspace

				print(#PlayersInGame:GetChildren())
				if #PlayersInGame:GetChildren() <= 1 and ChosenSanic.Character ~= nil and ChosenSanic.Character.Parent == PlayersInGame then -- checks to see if theres only 1 player remaining which is sanic
					EventsFolder.ShowWinners:FireAllClients(false)
					for i, v in pairs(game.Workspace:WaitForChild("PlayersInGame"):GetChildren()) do
						local plr = game.Players:GetPlayerFromCharacter(v)
						if plr.PlayerInfo.Sanic.Value == true then
							game.Workspace.Data[v.Name].Socks.Value += GameInfo["SurvivorReward"]
							print("added sanic reward")
						end
						v.Humanoid.Health = 0
						v.Humanoid.Parent:BreakJoints()
						task.delay(1, function()
							plr.PlayerInfo.Sanic.Value = false
						end)
					end
				else
					EventsFolder.ShowWinners:FireAllClients(true)
					for i, v in pairs(game.Workspace:WaitForChild("PlayersInGame"):GetChildren()) do
						local plr = game.Players:GetPlayerFromCharacter(v)
						if plr.PlayerInfo.Sanic.Value == false then
							game.Workspace.Data[v.Name].Socks.Value += GameInfo["SurvivorReward"]
						end
						print("added survivor reward")
						v.Humanoid.Health = 0
						v.Humanoid.Parent:BreakJoints()
						task.delay(1, function()
							plr.PlayerInfo.Sanic.Value = false
						end)
					end
				end
				Selected = false
				newSanicPart = nil
				MapClone:Destroy()
				table.clear(Chosen)
				table.clear(VotesTable)
				GameInfo["Minutes"] = 3
				GameInfo["Seconds"] = 20
				ResetMapVotes()
				game.Lighting.ClockTime = 6.1
				task.delay(5, function()
					EventsFolder.HideAllUIS:FireAllClients()
				end)
			end
		else

		end
	else
		EventsFolder.HideAllUIS:FireAllClients()
		gameReset()
		Status.Value = "you need atleast 2 players before starting!"
	end
end

I’ve removed the unnecessary portions of the code so you don’t have to read it all so the code won’t compile

1 Like

I’ve also been messing with this line maybe to add another or condition that checks if the killer has left so the timer would end but not sure how I would add this check

You may do this

game.Players.PlayerRemoving:Connect(player)
if player:FindFirstChild(whatever you added inside the player who is killer) then
gameReset()
end
end)

What I would do if I had this problem is, I would create a variable called TimerEnded and the value would be false. I make a function and when the function is runned, the variable turns true, while the timer is counting, each time it counts down, it would check if the murder is still in the game and would also check if TimerEnded is equal to true. When the murder isnt found in the game, then it will run the function, and if the TimerEnded is equal to true and the murder is still in the game, the game would end the same way it would do when the murder leaves.

Hope it helped! :pray:

Thats a good idea, the issue is I’m not sure how to check if the murder is still in game. I’ve tried the “PlayerRemoving” approach but that doesn’t work so I don’t know how I would track if the killer has left

You could have a variable storing the murderer’s player object. When he left, it would be destroyed, making it nil. If its nil, then run your code.

I don’t know how to indicate when the player has left. I’ve tried using PlayerRemoving and PlayerDisconnecting but both aren’t working

wow easily in the upper part you put player: added blah blah blah
or else you use player removing

PlayerAdded is working perfectly but PlayerRemoving isn’t working at all. I’ve checked both with print functions and tested them in game

That is strange… is your PlayerRemoving event connection for sure being run by the script? I would make sure it’s set up just like your PlayerAdded one. Just in case, here is the documentation

Would you be able to post your script with the PlayerRemoving you added?

but you should also use condition if you know I would recommend you also use a repeat untill loop
otherwise it would have many bugs

What about using collection service (tag service)?

Can it be that you think that the Timer stops when the Killer leaves? With how many Players are u testing the game? This line: #PlayersInGame:GetChildren() <= 1 says if 1 Player is left in your Game the Timer will stop, test it with three or more Players and see if it works or not.

ChosenSanic.Character:FindFirstChild("Humanoid") or ChosenSanic.Character.Parent == game.Workspace
this prob breaks your scripts execution because chosensanic.character would be nil, it would throw a nil error for trying to find humanoid of a nil value.

The issue was that there an error with “ChosenSanic.Character:FindFirstChild(“Humanoid”).” Changing this allowed me to use PlayerRemoving then. Thanks for everyones help

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.