I'm wondering the best way to check the amount of players remaining in a round. If I do:
hum.Died:connect(function() alive[player][1] = false checkAlive() end)
then I'm scared the two players will tie and the game will end twice.. or is the best option to add a game ending debounce?? Here's my script so far:
--// Services local ws = game:GetService("Workspace"); local pls = game:GetService("Players"); local repstr = game:GetService("ReplicatedStorage"); local ss = game:GetService("ServerStorage"); --// References local gameFolder = Instance.new("Folder", ws) gameFolder.Name = ".GameSettings" -- Has . in the beginning because hopefully the player GameSettings doesn't join lol local alive = {} -- alive[player] = {PLAYING(TRUE/FALSE, KILLS/POINTS} local playing = {} -- playing[player] = true/false --// Variables local vars = {"GameState", "Intermission"} local varInfo = { -- Value type, default value ["GameState"] = {"StringValue", ""}; ["Intermission"] = {"IntValue", 0} }; for i = 1,#vars do local newValue = Instance.new(varInfo[vars[i]][1], gameFolder) newValue.Value = varInfo[vars[i]][2] end --// Game functions (intermission, begin, end, etc) function checkAlive() a = 0 for _,player in pairs(pls:GetPlayers()) do pcall(function() -- just incase the player isnt even in the dictionary if alive[player][1] == true then a = a+1 end) end return a end function intermission(startTime, gameMode) -- ignore this im finishing this later on cuz ez local timerValue = gameFolder:WaitForChild("Intermission") end function beginGame(gameMode) for _,player in pairs(pls:GetPlayers()) do if playing[player] == true then -- if player is marked as playing, then let him join!! alive[player] = {true, 0} player:LoadCharacter() repeat wait() until player.Character local hum = player.Character:WaitForChild("Humanoid") hum.Died:connect(function() alive[player][1] = false checkAlive() -- can do the ending after this blablabla end) end end end
Events will not run at the same time so the game will never end twice. But you need to consider that a player may leave the game resulting in the function checkAlive
not running at all.
Using a table is a good way to keep track of who is ingame or not but I would remove the players when they die instead.
You also do not need to add a pcall into the checkAlive
function as you should be checking if the player is not nil.
Example:-
-- services local plrServ = game:GetService("Players"); -- vars local alivePlayers = {} local playingList = {} local function checkAlive() local i = 0 for _, _ in pairs(alivePlayers) do i = i + 1 -- inc player count end print('Players alive', i) return i end local function beginGame() alivePlayers = {} -- reset data each round to make surre it has no errors for _,plr in pairs(plrServ:GetPlayers()) do if playingList[plr] then -- if plr is in the list ie not nil alivePlayers[plr] = {true, 0} -- not sure about the data plr:LoadCharacter() -- will cause the script to wait (yield) -- warning player could leave the game or reset befor the script connects -- the died event. if plr.Character then -- wait for 10 seconds player could also leave the game local hum = plr.Character:WaitForChild('Humanoid', 10) if hum then hum.Died:connect(function() alivePlayers[plr] = nil -- clear plr from list checkAlive() end) else -- needs more checks end else -- no character needs more checks end end end end plrServ.PlayerRemoving:Connect(function(plr) alivePlayers[plr] = nil -- clear the player from the list even if they are not in the list playingList[plr] = nil end)
The main issue is when the script pauses (yeilds, calls a wait function) as players could leave the game reset their character causing your game to go out of sync. I think it would be best to just move the players torso as this will not yield in any way. This means the player setup can be done without being interupted.
I hope this helps please comment if you have any more questions.