Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

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

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.

2 comments

0

table.remove(playersAlive, table.find(playersAlive, v))

0

@Ziffixture, same result, but at least you answered another question i had, i think it has something to do with the event

3 answers

✓ Accepted answer

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)

2 comments

0

Edited the code a bit and it worked, thanks

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)) 

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

1 comment

0

Ends the same way, nothing changes, but thanks for trying

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

3 comments

0

already got answered but thanks alot! please dont delete this answer, as it may be important, also you made good points

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

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

This discussion is preserved as it was. New answers, comments, and votes are closed.