Problem with party system for lobby

Hello everyone, i’ve wanted to add a party system. But when a player join a party, the player list in the party load correctly, but when the same player leave and rejoin the party, the players in the player list is multiplied. Help me : (

Here is the script that add player to list :

game.ReplicatedStorage.PartySystemRE.OnClientEvent:Connect(function(joiningParty, partyName, TheChapter)

	inParty = joiningParty and true or false

	if inParty then	

		script.Parent.PartyGuiFrame.PartyFrame.PartyTitle.Text = partyName

		script.Parent.PartyGuiFrame.PartyFrame.Visible = true
		script.Parent.PartyGuiFrame.PartyListFrame.Visible = false
		script.Parent.PartyGuiFrame.CreateButton.Visible = false

		if TheChapter == 1 then
			script.Parent.PartyGuiFrame.PartyFrame.ChapterName.Text = "CHAPTER 1"
			script.Parent.PartyGuiFrame.PartyFrame.ChapterImage.Image = "rbxassetid://"..game.ReplicatedStorage.ChapterImages.Chapter1.Value
		end

		local function displayPlayers()

			for i, child in pairs(script.Parent.PartyGuiFrame.PartyFrame.PlayerList:GetChildren()) do
				if child:IsA("Frame") then
					child:Destroy()
				end
			end
			
			for i, player in pairs(game.ReplicatedStorage.Parties[partyName].Players:GetChildren()) do

				local template = script.PlayerTemplate:Clone()
				template.PlayerName.Text = player.Value

				local ThePlayer = game.Players:FindFirstChild(player.Value)

				local userId = ThePlayer.UserId
				local thumbType = Enum.ThumbnailType.HeadShot
				local thumbSize = Enum.ThumbnailSize.Size420x420
				local content, isReady = game.Players:GetUserThumbnailAsync(userId, thumbType, thumbSize)

				template.PlayerImage.Image = content

				template.Parent = script.Parent.PartyGuiFrame.PartyFrame.PlayerList

				template.Parent.Parent.LeaveButton.MouseButton1Click:Connect(function()
					if CanLeaveParty == true then
						game.ReplicatedStorage.PartySystemRE:FireServer("kickPlayer", partyName, player)
					end
				end)

				script.Parent.PartyGuiFrame.PartyFrame.PlayerList.CanvasSize = UDim2.new(0, 0, 0, script.Parent.PartyGuiFrame.PartyFrame.PlayerList.UIListLayout.AbsoluteContentSize.Y)
			end
		end

		displayPlayers()
		game.ReplicatedStorage.Parties[partyName].Players.ChildAdded:Connect(displayPlayers)
		game.ReplicatedStorage.Parties[partyName].Players.ChildRemoved:Connect(displayPlayers)

	else		
		script.Parent.PartyGuiFrame.PartyListFrame.Visible = false
		script.Parent.PartyGuiFrame.PartyFrame.Visible = false
		script.Parent.PartyGuiFrame.CreateButton.Visible = true
		script.Parent.PartyGuiFrame.JoinPartyButton.Visible = true
	end
end)
6 Likes

It looks like you don’t remove the players in this list when a player leaves so they are already in the list when the frames are added to the player list in the GUI.

2 Likes

How can I do it. I don’t know how can I delete them…

2 Likes

Just set the index equal to nil. Or you can use table.remove()

Sorry but, what is the index I should change ? (sorry I’m not very professional on scripting)

How are you adding players to this Parties list?

Like this :

if game.ReplicatedStorage.Parties:FindFirstChild(value1) and #game.ReplicatedStorage.Parties[value1].Players:GetChildren() < game.ReplicatedStorage.Parties[value1].PlayerLimit.Value then
			
			local playerValue = Instance.new("StringValue")
			playerValue.Value = player.Name
			playerValue.Parent = game.ReplicatedStorage.Parties[value1].Players
			
			game.ReplicatedStorage.PartySystemRE:FireClient(player, true, value1)
		end

It’s a different method to parent string Instance values rather than store them in a table.

You could just use a table of players; something like this:

local playerParties = {};
local maxPartySize = 3;
local function addPlayer(playerName,partyName)

	-- firstly check if the party exists in the table, create an empty table value if it doesn't
	if not playerParties[partyName] then
		playerParties[partyName] = {}; -- make new empty table value
	end

	-- now check if the players name is in the table
	if table.find(playerParties[partyName],playerName) then
		-- player already in table
		warn("Player " .. playerName .. " is already in the party called " .. partyName );
		return -- return since we don't need to add the player
	end 

	-- party exists, and the player isn't in the party
	-- now check if the party is FULL!
	if table.maxn(playerParties[partyName]) == maxPartySize then
		warn(playerName .. " cant be added to the party named " .. partyName .. " it is already FULL!");
		return -- do not add player to party
	end
	
	-- Now we can add the player to the party list
	table.insert(playerParties[partyName],playerName);
	print("Player " .. playerName .. " has been added to the party called " .. partyName );

end

local function removePlayer(playerName,partyName)

	-- check if the party name exists in the table first
	if playerParties[partyName] then
		local playerIndex = table.find(playerParties[partyName],playerName); -- get the player index from the partyTable using the player name
		if playerIndex == nil then -- if this is nil then ...
			-- ... player is not in the table
			warn("Player " .. playerName .. " is NOT in the party called " .. partyName );
			return
		end 

		-- remove the player from the party list using the index obtained in the table.find above
		table.remove(playerParties[partyName],playerIndex);
		print("Player " .. playerName .. " has been removed from the party called " .. partyName );
		if table.maxn(playerParties[partyName]) == 0 then -- check if the party is empty
			playerParties[partyName] = {}; -- set the party back to an empty table
			print("Players table called " .. partyName .. " is empty, removing index");
		end
		return -- all good just return now to stop fail safe below
	end

	-- fail safe
	warn(partyName .. " does not exist!!");

end

-- some test bed code to check all eventualities
wait(3);
addPlayer(game.Players:GetChildren()[1].Name,"MyParty");
addPlayer("Jeff","MyParty");
wait(3);
addPlayer(game.Players:GetChildren()[1].Name,"MyParty");
addPlayer("Allan","MyParty");
wait(3);
removePlayer(game.Players:GetChildren()[1].Name,"MyParty");
removePlayer("Jeff","MyParty");
removePlayer("Dave","MyParty"); -- not in party
removePlayer("Allan","MyParty"); -- party is empty
wait(3);
addPlayer(game.Players:GetChildren()[1].Name,"MyParty");
removePlayer("Jeff","MyParty"); -- not in party
addPlayer("Jeff","MyParty");
addPlayer("Dave","MyParty");
addPlayer("Bob","MyParty"); -- party full
addPlayer("Frank","MyParty"); -- party full
wait(3);
removePlayer("Jeff","MyParty");
removePlayer("Dave","MyParty");
removePlayer("Bob","MyParty"); -- not in party
removePlayer("Frank","MyParty"); -- not in party
removePlayer(game.Players:GetChildren()[1].Name,"MyParty"); -- party empty
removePlayer(game.Players:GetChildren()[1].Name,"OopsParty!"); -- party doesn't exist

You should try using OOP it would seriously help for something like this, like a party module on the server that setups up a new party with variables like how many players are in it, whos the party leader etc.

I found the problem, the

game.ReplicatedStorage.Parties[partyName].Players.ChildAdded:Connect(displayPlayers)
game.ReplicatedStorage.Parties[partyName].Players.ChildRemoved:Connect(displayPlayers)

When the value in playerlist is removed, the event is fired a multiple of times. How can I make it fired only one time ?

1 Like

Because you are hooking the same logic in both Add and Remove. Separate the logic for these two events and you will be fine. As I did with two distinct functions (addPlayer, removePlayer). They must be separated for clarity, and simplicity.