How to prevent a player from being inserted into a table twice

I’m currently working on a round system and I’ve been using tables to teleport players and change their values

But the problem I’ve been experiencing lately is sometimes the same player will be inserted twice or more.

I’ve been researching certain ways such as table.find. I came across a post with the a similar issue but, the person who responded, didn’t give too much detail as to how I may go about using table.find. Specifically how I could prevent a player from being inserted too many times.

Please feel free to give me some advice on my code if needed. I might be missing a very key detail.
Thanks.

Code:

local roundLength = 20
local intermissionLength = 2
local inRound = game.ReplicatedStorage.InRound
local Status = game.ReplicatedStorage.Status

local LobbySpawn = game.Workspace.Spawns.LobbySpawn.Position + Vector3.new(0, 3, 0)
local GameAreaSpawn = game.Workspace.Spawns.GameSpawn.Position + Vector3.new(0, 3, 0)

local debounce = true

local playerTable = require(game.ReplicatedStorage.PlayerModule)

inRound.Changed:Connect(function()
	if inRound.Value == true then
		-- Round Begins
		-----------------
		for i, v in pairs(game.Players:GetChildren()) do
			if v.Character.ValuesFolder.Playing.Value == true then
				-- checks to see if the player has the playing value turned on
				table.insert(playerTable, v)
				for i, v in ipairs(playerTable) do
					v.Character.HumanoidRootPart.Position = GameAreaSpawn
				end
			end
		end
		--teleports players to gameArea
	else
		-- Round Ends
		----------------
		for i, v in ipairs(playerTable) do
			v.Character.HumanoidRootPart.Position = LobbySpawn	
		end
		-- teleports player to intermission
	end
end)

local function resetTimer()
	while wait() do
		wait(1)
		if debounce == true then
			-- Intermission Timer
			------------------------
			for i, v in pairs(game.Players:GetChildren()) do
				local Character = v.Character or v.CharacterAdded:Wait()
				local valuesFolder = Character:WaitForChild("ValuesFolder")
				valuesFolder.WonValue.Value = false
				continue
			end
			-- Resets values
			for i = intermissionLength, 0 , -1 do
				inRound.Value = false
				Status.Value = "Intermission: ".. i .." seconds left"
				wait(1)
			end
			-- intermission countdown
			Status.Value = "Game begins!"
			wait(2)
			debounce = false
		else
			-- Game Timer
			---------------
			for i = roundLength, 0, -1 do
				gameOver = true
				inRound.Value = true
				Status.Value = "Game: ".. i .. " seconds left"
				for int, player in ipairs(playerTable) do
					local char = player.Character or player.CharacterAdded:Wait()
					local valuesFolder = char:WaitForChild("ValuesFolder")
					if valuesFolder.WonValue.Value == false then
						gameOver = false
						continue
					end
				end
				-- loop that checks over if every value is still false and continues if true
				if gameOver == true then
					for i, v in ipairs(playerTable) do
						table.remove(playerTable, i)
						continue
					end
					break
				end
				-- if every value is true then it breaks the loop and continues
				wait(1)
			end
			Status.Value = "Round over!"
			wait(2)
			debounce = true
		end
	end
end
	
spawn(resetTimer)

I would use a dictionary rather than an array.

With a dictionary you can easily set and index values

-- put player in dictionary
dictionary[player] = true

then

if dictionary[player] == true then
     -- player is in dictionary
else
     -- player is not in dictionary
end

you can retrieve keys at a constant (almost) time with dictionaries, whereas doing table.find will take longer the more elements are in the array

1 Like