for i = 20, 1, -1 do
DisplayManager:SetStatus('Time left: ' .. i, true)
for i, v in pairs(players) do
v.Character.Humanoid.Died:Connect(function()
table.remove(players, i)
end)
end
if #players <= 1 then
break
end
wait(1)
end
if mainRound then
if #players == 2 then
-- Kill both players
else
for _, v in pairs(Mats:GetChildren()) do
print(players[1])
local Character = players[1].Character
if v.Taken.Value == players[1] then
Character:SetPrimaryPartCFrame(v.CFrame * CFrame.new(0, 3, 0))
Character.PrimaryPart.Anchored = true
-- Remove weapons
end
end
end
end
Basically, ‘players’ is a list of 2 players. The idea is they fight in a 1v1. If time runs out and they both still alive, I just kill them both, it’s a tie (havent added that yet) but my problem lies when one kills the other. This error occurs 50/50, and it has to do with getting the Character.
print(players[1]) SHOULD return the surviving player, however, sometimes it prints nil? Not sure if this has something to do with how I’m removing the dead player from the list. If the list looked like this
players = {Player1, Player2}
then
table.remove(players, i) -- i being the index for the table, lets say player 1 died, so we remove player1
Then the table should then be
players = {Player2}
and thus players[1] should return Player2, correct?
If a table had two values, one with the index 1 and the other at the index 2, remvoing the value at index 1 doesn’t mean that the value at index 2 is gonna become 1, it’s not retrieved back, it stays the same. A table can have a value at any index, and there doesn’t have to be values before the index, I can set a value to the index 25 even though there is not a 24 or anything before it.
To fix your problem, you can simply do, using the or logical operator
local surviver = player[1] or player[2]
This is saying, if player[1] is nil, meaning that player isn’t the one who won, it would chose player[2] instead.
If your game only uses two players, I would make sure if its absolutely necessary to use a table to store the players. What you could do is have it so you have two variables representing the state of the player.
local Alive1 = true
local Alive2 = true
local Player1 = --player here
local Player2 == --player here
Upon dying, you can change these values to false. That way, when the round ends, all you have to check is whether Player1 or Player2 is true or false, and whichever one is true, you can then apply the winner logic too.
However, if you want the ability to scale it up to as many players as you want, a table may be much better. I would suggest you use two tables, one to indicate the players and another to represent whether they’ve died or not. These two tables would be connected by the index that players are assigned in the players table
local players = {[1] = Mariofly5, [2] = NinjoOnline} -- players here, the [1]'s and [2]'s are just for your understanding
local playerStates = {}
-- When a player has died, set the index in playerStates to false
for i,v in pairs(players) do
playerStates[i] = true
v.Character.Humanoid.Died:connect(function()
playerStates[i] = false
-- indentation got me triggered >:(
end)
end
-- wait for round to end then decide winners etc
In general, I would avoid removing players from the table, as it removes the reference to all the players who have lost that game, and by keeping them, you can reward anyone who has lost with a “Better Luck Next Time” gift or similar.
Prints empty, why is that tho? The only time I remove a player is like so:
for i = 20, 1, -1 do
DisplayManager:SetStatus('Time left: ' .. i, true)
for i, v in pairs(players) do
v.Character.Humanoid.Died:Connect(function()
table.remove(players, i)
end)
end
if #players <= 1 then
break
end
wait(1)
end
Not sure, but this may have a relation with the fact that the even is being fired within the for loop.
There are two options here, to either move the Died event outside.
for i, v in pairs(players) do
v.Character.Humanoid.Died:Connect(function()
table.remove(players, i)
end)
end
for i = 20, 1, -1 do
DisplayManager:SetStatus('Time left: ' .. i, true)
if #players <= 1 then
break
end
wait(1)
end
Or use keys instead of indices.
local players = {}
for i, v in pairs(game.Players:GetPlayers()) do
players[v] = v
end
for i = 20, 1, -1 do
DisplayManager:SetStatus('Time left: ' .. i, true)
for i, v in pairs(players) do
v.Character.Humanoid.Died:Connect(function()
if players[v] then
players[v] = nil
end
end)
end
if #players <= 1 then
break
end
wait(1)
end
What we’re doing here, inserting all the players inside of the players table, where each player’s key is the player object itself. Then each time the Died event fires, we check if that player even existed doing if players[v] then, and if so removed that specific player.