Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

How to do when a player dies to be removed from a table?

Asked by 3 years ago
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.

0
table.remove(playersAlive, table.find(playersAlive, v)) Ziffixture 6913 — 3y
0
@Ziffixture, same result, but at least you answered another question i had, i think it has something to do with the event yuni_Boy1234 320 — 3y

3 answers

Log in to vote
1
Answered by 3 years ago
Edited 3 years ago

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)
0
Edited the code a bit and it worked, thanks yuni_Boy1234 320 — 3y
1
what you said about the index was correct, but you can use table.find to return the index of that player in the table. Doing this allows you to simply do table.remove(playersAlive, table.find(playersAlive, player))  R_alatch 394 — 3y
Ad
Log in to vote
0
Answered by 3 years ago

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
0
Ends the same way, nothing changes, but thanks for trying yuni_Boy1234 320 — 3y
Log in to vote
0
Answered by
R_alatch 394 Moderation Voter
3 years ago
Edited 3 years ago

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
0
already got answered but thanks alot! please dont delete this answer, as it may be important, also you made good points yuni_Boy1234 320 — 3y
0
the main point of this is that what you had was correct and there was no need to change it, you were just using return and not continue so whatever you accepted i do not suggest using as its much more than whats needed R_alatch 394 — 3y
0
just edited my answer a lot to get rid of some of the comments, and tried to simplify the issues and what i did R_alatch 394 — 3y

Answer this question