0
votes

I am working on a 6 player rounds-based Roblox game with each round ending if either time runs out OR if every player except for one survivor remains. After each round players (and those killed during the round) are teleported back to a lobby, followed by a brief intermission, and then teleported bak into a map to start a new round (there are lots of different maps chosen randomly). My strategy for this game was to create a large region surrounding all the maps and during the rounds as the timer is counting down, continually detect the # players in the region. When that number gets to 1 the round would end and a winner would be declared. There are 2 problems with this approach:

  1. I had to create a huge region to encompass all the different maps and as I add more maps the region will have to get bigger and bigger. Is detecting # players in such a large region when at most 6 players will be in only one map at a time?

  2. My player detection script isn't working. It detects one player but when there are 2 players it still returns "1" as # of players. To trouble shoot this problem I created a simple game that detects when a player is in a region (gray baseplate) and when they leave the region (red baseplate). When I run the game - https://www.roblox.com/games/6060804433/Rounds - publicly with 2 players in the game it only returns 1 player in the game (which I display in an upper left GUI). My code is below - I think the problem is with how the table / dictionary playersFound works.

CODE:

regionPart = game.Workspace.RegionFromThisPart -- I created a transparent cube to define the region
pos1, pos2 = (regionPart.Position - (regionPart.Size/2)),(regionPart.Position + (regionPart.Size/2))
region = Region3.new(pos1,pos2)
Status = game.ReplicatedStorage.Status

wait(5)

while wait(1) do

    partsInRegion = workspace:FindPartsInRegion3(region, game.Workspace.Baseplate,1000) 
    playersFound = {} -- table of players found

    for i, part in pairs (partsInRegion) do
        if part.Parent:FindFirstChild("Humanoid") ~= nil then
            playersFound["playerinregion"] = part.Parent -- add players character to table
            print (i, part) -- 0
        end 
    end

    function Length(playersFound)
        local counter = 0 
        for _, v in pairs(playersFound) do
            counter =counter + 1
        end
        return counter
    end

    Status.Value = Length(playersFound) .." players in region"

end 

Bonus question: The GUI I created to show the number of players in the region shows on my screen but not the other player's scree (it says "label" on their screen).

I have spent an incredible amount of time spinning my wheels and would GREATLY appreciate help solving this problem.

Thank you!

1

1 Answers

0
votes

You're absolutely right that your issue stems from how you're putting players into your playersFound table. Because you are using the same key in the table every time, you are overwriting the old player with any new one you find. Instead, try using a unique key to hold onto the players. This could be i or better yet, the player's name. And since you are just looping over the table again, why not just keep a counter of how many players there are.

local regionPart = game.Workspace.RegionFromThisPart -- I created a transparent cube to define the region
local pos1 = (regionPart.Position - (regionPart.Size/2))
local pos2 = (regionPart.Position + (regionPart.Size/2))
local region = Region3.new(pos1,pos2)
local Status = game.ReplicatedStorage.Status
local BasePlate = game.Workspace.Baseplate
local time = 30 -- seconds

wait(5)

while wait(1) do
    
    -- count how many players are left
    local playersFound = {}
    local totalPlayersFound = 0
    local partsInRegion = workspace:FindPartsInRegion3(region, baseplate, 1000)
    for i, part in pairs(partsInRegion) do
        if part.Parent:FindFirstChild("Humanoid") ~= nil then
            -- keep track of all the players still alive
            -- since a player's character is made of many parts, each player will show up multiple times,
            -- so only hold onto each player once
            local character = part.Parent
            if (playersFound[character.Name] == nil) then
                playersFound[character.Name] = character
                print ("Found Player : ", character.Name)
                totalPlayersFound = totalPlayersFound + 1
            end
        end 
    end

    -- EDIT BASED ON COMMENTS --
    -- update the UI based on the game state
    if time == 0 then
        Status.Value = "Round over!"
        break
    elseif totalPlayersFound == 1 then
        -- since we know that there's only one entry in the playersFound table,
        -- grab it using the next() function
        local playerName, character = next(playersFound)
        StatusValue = "Winner : " .. playerName
        wait(5)
        break
    --elseif totalPlayersFound  == 0 then
        -- make sure to check in case no players are left
    else
        Status.Value = tostring(totalPlayersFound) .. " players in round"
        time = time - 1
        -- DEBUG :
        -- print("There are " .. tostring(totalPlayersFound) .. " players in the round")
        -- for playerName, character in pairs(playersFound) do
        --     print(" - " .. playerName .. " is still in the game")
        -- end
    end
end

As for your bonus question, you should ask a follow up question and post the code that shows how you're creating the label and updating it.