Setting value more than once

The title is probably not the best one, as I could not think of a title suited well for this. I am currently making a game that involves players trying to be the top 3 in touching a part. In simple terms, a race. I am using code that gives the top 3 player names who touch the part to 3 seperate values (WinnerValue, SecondPlace, ThirdPlace). There is also a part of the code that makes it so that a player who has already touched the object, cannot get second place or third place and vice versa. The problem is, if a player competes in multiple rounds and wins/gets second or third twice or more, their name will not become the value if they get top 3 because the code I am using does not allow it. How should I fix the code so it allows players who compete in multiple rounds and get top 3 both times have their name as the according value but still make it so players who already finished in top 3 cannot get another spot by touching the part?

local Values = game.ReplicatedStorage:WaitForChild("Values");
local FinishedPlayers = {}; --All the players who touched the FinishPart will be added to this list in order.
local FinishPart = game.Workspace.GameSystem.Finish

FinishPart.Touched:Connect(function(Hit)
	local Player = game.Players:GetPlayerFromCharacter(Hit.Parent); --Get the player.

	if Player --[[New code here]]and not table.find(FinishedPlayers, Player)--[[New code here]] then --If the player exist then continue.
		local Rank = (#FinishedPlayers + 1); --Get the rank.
		FinishedPlayers[Rank] = Player; --Add the player to the list.

		if Rank == 1 then
			Values.WinnerValue.Value = Player.Name;
		elseif Rank == 2 then
			Values.SecondPlace.Value = Player.Name; 
		elseif Rank == 3 then
			Values.ThirdPlace.Value = Player.Name; 
		end
	end
end)

If my explanation was sub-par, please let me know what questions you have.

To avoid that, you’ll want to empty the table after each round is over. To empty the FinishedPlayers list, do this:

for _, obj in pairs(FinishedPlayers) do
    obj = nil
end

When the table is emptied, the next round the player names won’t be there which will allow the same person to get 1st, 2nd, or 3rd place more than once in a row.

I have two seperate scripts. One is the round system which has the countdown system, who won, etc. The other script is this one which is under the finish brick. Where would I incorporate the code you gave since I want to empty the list after each round?

I think the best solution is to incorporate that loop I wrote at the very beginning of a round.

This way, each time a new round starts, it’ll ensure the table is empty before filling it with new finished players.

Since they are two different scripts, I can’t bring the FinishedPlayers list over to the other. How would I be able to make or find the list over to the round script so it can wipe the it?

You could either combine the two scripts so that they can share information with one another or you could use something called a BindableEvent.

BindableEvents work similar to RemoteEvents but are just used to send info to other scripts in general. You could use them to send the winners over to the other script and then just empty the table afterward.

AlvinBlox has a good tutorial on it.

Thank you for linking the video. It was actually really easy to follow and I made a bindable event that fires before every round. The only issue I had was that the code you put did not clear the table so the value was not able to be changed. Instead, I made it so when the event is fired, it just makes a new table and it worked well:

ClearTable.Event:Connect(function()
	FinishedPlayers = {}
	print("Event fired.")
end)	

Do you think this is efficient and could this cause problems in the future?

Technically that doesn’t empty the table, it simply creates a new one in its place and the old one is left behind as extraneous data. It’s relatively small data though so the build up would likely be negligible.

If it works for you, I would try to test it after maybe 10 rounds to see if a lot of lag is going on and if there’s no difference, I say go with what works.

I know I have been dragging this on with questions but I think I found something that completes the same purpose as the code you wrote for me.

ClearTable.Event:Connect(function()
	table.clear(FinishedPlayers)
	print("Event fired.")
end)	

It works fine but I want to know your opinion on it.

Oh, I’ve never heard of table.clear before honestly. This is new to me.

According to the Developer page, this does exactly what the earlier for loop was meant to do, so this should be your best solution to avoid any build up of unused data.

Thank you so much for taking time out of your day to help me. I appreciate it.

Happy to help! Remember to mark one of the replies as a solution so that future developers who have your same problem can see this and know how to fix it.