if game.Workspace.GameMode.Value == "FFA" then --FFA gamemode local spawnsTable = {} for i, v in pairs(chosenClone.Spawns:GetChildren()) do if v.Name == "Spawn" then spawnsTable[#spawnsTable + 1] = v end end local playersAlive = {} for i, v in pairs(game.Players:GetPlayers()) do if v.Character.Humanoid.Health == 0 then return end v.Character:MoveTo(spawnsTable[math.random(1, #spawnsTable)].Position) local sword = game.ReplicatedStorage.ClassicSword:Clone() sword.Parent = v.Backpack playersAlive[#playersAlive + 1] = v end for i, v in pairs(playersAlive) do v.Character.Humanoid.Died:Connect(function() table.remove(playersAlive, i) end) end while true do wait() if #playersAlive > 1 then return end break end editGUI("ChangeText", playersAlive[1].Name.." wins!") wait(3) chosenClone:Destroy() playersAlive[1]:LoadCharacter() end
I am trying to make a sword fighting game (the script is too long so i did not include it all,just the important part). The problem is that when a player dies, it does not gt removed from the playersAlive table, and the round will not end. Can someone please fix my code or find a more efficient way to do this? Thanks.
I would create a function that finds the player by name, and removes it based off of the current index. When you remove an object from a table like you did in line 19, it moves the other elements down, making the i index incorrect.
function removePlayerByName(plyrnm) local i = 1 while playersAlive[i].Name ~= plyrnm and i <= #playersAlive do i += 1 end if playersAlive[i] then table.remove(playersAlive, i) end end
And:
for i = 1, #playersAlive do local plyr = playersAlive[i] plyr.Character:WaitForChild("Humanoid").Died:Connect(function() removePlayerByName(plyr.Name) end) end
I think it would be better to do this though:
function checkGameCondition(plyr) if workspace.GameMode.Value == "FFA" then removePlayerByName(plyr.Name) end end game.Players.PlayerAdded:Connect(function(plyr) plyr.CharacterAdded:Connect(function(char) char:WaitForChild("Humanoid").Died:Connect(function() checkGameCondition(plyr) end) end) end)
I think something like this would work, this would remove the character from the table and replace it with nil(basically doesn't exist).
for i, v in pairs(playersAlive) do v.Character.Humanoid.Died:Connect(function() playersAlive[i] = nil end) end
I think the main issue was with the while loop, specifically the use of return
instead of continue
. I made a lot of changes here and there and did my best to explain each one.
local sword = game.ReplicatedStorage.ClassicSword if workspace.GameMode.Value == "FFA" then --Use GetChildren() to return an array of the spawns local spawnsTable = chosenClone.Spawns:GetChildren()) local playersAlive = {} for _, player in ipairs(game:GetService("Players"):GetPlayers()) do local character = player.Character if not character then continue end table.insert(playersAlive, player) --table.insert shifts the table --connect the died event here, dont make a new loop --edit: table.find returns an index, useful for removing them character.Humanoid.Died:Connect(function() table.remove(playersAlive, table.find(playersAlive, player)) end) player.Character:SetPrimaryPartCFrame(spawnsTable[math.random(1, #spawnsTable)].CFrame) sword:Clone().Parent = player.Backpack end --main issue here, the use of return was unneeded and dont use wait() while true do wait(1) if #playersAlive < 2 then break end end --check if playersAlive[1] exists in the case of a tie local winner = playersAlive[1] if winner then editGUI("ChangeText", winner.Name .. " wins!") wait(3) winner:LoadCharacter() else editGUI("ChangeText", "There was a tie!") end chosenClone:Destroy() end