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

How could i remove a player from a Table when he died or disconnected?

Asked by 5 years ago
Edited 5 years ago

So this is kinda complicated to explain but im just gonna give you my whole Script so you might be able to understand what i did here. So i got a District System going like the Hunger games and i know how to check, how many Players are alive. But my major problem is to make a "Death/Leave" Script so it updates the Table when a player dies or disconnects. The Problem here is that If i want to check how many Players are alive i use

if #Players == 0 then
            print("Everybody died")
            break
        end

which is the only way i believe in this code. If i want to use _G.Districts it wont work. #Players gives me an Number of how many are in the table i believe.

So Is there a better way to write this script? Is there even a way to get my Death/Leave script working? Im so confused by now and my head hurts.

Here is my Whole Script + my attempt to write a Death and Leave Script. Basicly what i wanna know is how to make a death and leave script and make it comportable with mine. Thanks alot if you're still reading <3

DEATH AND LEAVE SCRIPT

game:GetService("Players").PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(function(character)
        character:WaitForChild("Humanoid").Died:Connect(function()
        local Update = {}
        for i, v in pairs(_G.Districts) do
            if v ~= player.Name then
               table.insert(Update,1,v)
            end
        end
    _G.Districts = Update
        end)
    end)
end)

game:GetService("Players").PlayerRemoving:Connect(function(player)

    local Update = {}
    for i, v in pairs(_G.Districts) do
        if v ~= player.Name then
            table.insert(Update,1,v)
        end

    end
    _G.Districts = Update
end)

MAIN SCRIPT

--//Services
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--//Remotes
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
    local Names = Remotes:WaitForChild("Names")
    local Round = Remotes:WaitForChild("Round")

--//Variables 
local Tributspawn = workspace:WaitForChild("Tribut")

--//Functions
    function Shuffle(Table)
    local Size = (#Table)
    for i = Size, 1, -1 do
        local RandomObject = Random.new():NextInteger(1, Size)
        Table[i], Table[RandomObject] = Table[RandomObject], Table[i]
        end
    return Table
end 

--//Main
while true do
    wait(3)
    _G.Districts = {}
local Players = (Shuffle(game:GetService("Players"):GetPlayers()))

for i = (1),(math.ceil(#Players/2)) do
    _G.Districts[#_G.Districts + 1] = {}
end

for Player = (1),(#Players) do
    local DesiredDistrict = (math.ceil(Player/2))
    table.insert(_G.Districts[DesiredDistrict], Players[Player])
Names:FireAllClients(DesiredDistrict,Players[Player])
wait(2)
end
    print("Round starts")
        for t = 10,0,-1 do
        wait(1)
            print(t)
            if #Players == 0 then
            print("Everybody died")
            break
        end
    end
end

1 answer

Log in to vote
2
Answered by 5 years ago
Edited 5 years ago

You should avoid using _G as any scripts are able to read / make changes to this. Instead I would use a module script to manage this task.

There are a lot of ways this can be done but for this example I will show a self contained process which will return a round object. The idea behind this is so you would then be able to expand the functionality of what a round is.

-- module script code
local f = {}
local plrServ = game:GetService("Players")

-- vars
local curRound = nil

-- returns the cur round object or nil
function f:GetCurRound()
    return curRound
end

-- roundTime, the time for this round
function f:NewRound(roundTime)
    -- example validation for rounds
    if curRound then error("round is active cannot make a new round") end

    local round = {} -- our new round object
    local conObj = {} -- active event connections
    local endTime = tick() + roundTime -- cal total time of round
    local totalPlayers = 0 -- player count for round
    local plrList = {}

    -- to avoid duplication of code
    local function rmPlayerFromList(plr)
        if plrList[plr] then -- if plauer is in the list
            plrList[plr] = nil -- remove player
            totalPlayers = totalPlayers - 1 -- dec player count
        end
    end

    for _, plr in pairs(plrServ:GetPlayers()) do
        if plr.Character then -- check for a players model ?
            local hum = plr.Character:FindFirstChild("Humanoid")

            -- check humanoid is not dead
            if hum and hum:GetState() ~= Enum.HumanoidStateType.Dead then

                -- add this valid player to the list
                conObj[#conObj+1] = hum.Died:Connect(function()
                    rmPlayerFromList(plr)
                    print(plr.Name, " died")
                end)

                totalPlayers = totalPlayers + 1 -- inc player count
                plrList[plr] = true -- the value is just a place holdder
            end
        end
    end

    -- add the player removing 
    conObj[#conObj+1] = plrServ.PlayerRemoving:Connect(function(plr)
        rmPlayerFromList(plr)
        print(plr.Name, " left")
    end)

    -- returns the player count for the round
    function round:GetPlayerCount()
        return totalPlayers 
    end

    -- returns true if the round is still active
    function round:IsActive()
        return tick() < endTime 
    end

    -- ends the round and curRound variable
    function round:End()
        for _, con in pairs(conObj) do
            con:Disconnect()
        end

        -- cleanup
        conObj = nil
        totalPlayers = 0
        plrList = nil
        curRound = nil
    end

    -- returns an array of players in theround
    function round:GetPlayers()
        local lst = {}
        for _, plr in pairs(plrList) do
            lst[#lst+1] = plr
        end
        return
    end

    -- set this as the active round
    curRound = round
    return round -- return round object
end

return f -- return our table of functions 

Example script

local round = require(script.Parent.ModuleScript)

while true do
    local newRound = round:NewRound(10)

    while newRound:IsActive() do
        print(newRound:GetPlayerCount(), "Players in round")
        wait(1)
    end

    print("round end")
    newRound:End()
end

I know this is a lot to work with at first but the round object returned is safe to use in other scripts. Please comment if there are parts of this code you do not understand and I will add additional info below.

Usefull links

OOP in Lua

OOP in Lua dev forum

RBXScriptConnection

Hope this helps.

0
I see you did a lot of work there, sadly my knowledge is not good enough for this kind of code. I never invented time into ModuleScripts etc also sadly i dont know how to make it comportable with mine. Still you did a great job, i tested it in a new game and it works well :) Paintertable 171 — 5y
0
You can do a lot of things with modules. A module script will only run once upon using the function require. It helps lead to better code design by reusing code and making for better code strucures ie one thing does one task. User#5423 17 — 5y
Ad

Answer this question