How to prevent from looking THROUGH AN ENTIRE table when a SPECIFIC item is already found?

Basically, I am making a keycard system, but there is a bug. If the player SOMEHOW has several keycards, it will LOOP THROUGH ALL OF THEM, and will basically repeatedly open the door until one of the keycards do not match.
The check:

local plrBackpackContent = plr.Backpack:GetChildren()
	print("Children obtained.")
	for i,tool in pairs(plrBackpackContent) do
		print(tool.Name)
		if cards[tool.Name] ~= nil and cards[tool.Name] == true then
			for i,card in pairs(cards) do

The table:

local cards = {
	["LightAccessKeycard"] = true,
	["MediumAccessKeycard"] = true,
	["HeavyAccessKeycard"] = true,
	["HostileHackBypasser"] = true,
	["AdminBypasser"] = true;
	
}

image

EDIT:
Second check:

elseif cards[tool.Name] == false then
			deny:Play()				
			print("Invalid card inserted by: "..plr.Name)
		end
3 Likes

Try breaking the loop once a valid keycard is found:

if cards[tool.Name] then -- this `cards[tool.Name] ~= nil and cards[tool.Name] == true` is unnecessary
    --do something
    --put your code here

    break
else
    deny:Play()				
    print("Invalid card inserted by: "..plr.Name)
end
2 Likes

A condition-controlled loop (while) over a count-controlled loop (for) can be used; which is what is being used in your code at the moment. Like @DiscoDino01 has mentioned, you can alternatively use the break keyword to pre-emptively end the for loop after the key card has been found. Either method works fine, it’s more so on personal preferences.

Condition-controlled loop example:

while not keycardFound do
end
2 Likes

How would I use it in my check?

1 Like

For a condition-controlled loop, you would replace all of your for loops with a singular while loop. You would also have a variable acting as a flag to stop the loop. The flag’s value is changed to True when a key card is found; in turn, terminating the loop.

local foundKeycard = False

local plrBackpackContent = plr.Backpack:GetChildren() -- No need to loop through this; the object returned is an array/list
	print("Children obtained.")
    while foundKeycard == False do -- Alternatively: while not foundKeycard do
        if cards[tool.Name] ~= nil and cards[tool.Name] == true then
            --Stuff
            foundKeycard = True -- Breaks the loop because the condition of the loop is now false (True ~= False)
        end

Alternatively, with @DiscoDino01’s method, you simply just need to add a break after finding a key card.

 if cards[tool.Name] ~= nil and cards[tool.Name] == true then
    --Stuff
    break
end
2 Likes

It works but the denied action plays either way.
This is the entire script:

prompt.Triggered:Connect(function(plr)
	local accepted = false
	local debounce = doorModel.IsMoving.Value
	local char = plr.Character or plr.CharacterAdded:Wait()
	print("No debounce.")
	local plrBackpackContent = plr.Backpack:GetChildren()
	print("Children obtained.")
	for i,tool in pairs(plrBackpackContent) do
		print(tool.Name)
		if cards[tool.Name] ~= nil and cards[tool.Name] == true then
			for i,card in pairs(cards) do
				if debounce then return end
				debounce = true
				accepted = true
				accept:Play()
				print("Debounce check.")
				print("Success!")
				prompt.Enabled = false
				prompt2.Enabled = false
				keycardLight1.Color = Color3.fromRGB(26, 255, 0)
				keycardLight2.Color = Color3.fromRGB(26, 255, 0)
				tweenD1:Play(nil,1000)
				tweenD2:Play(nil,1000)
				tweenD1.Completed:Wait()
				keycardLight1.Color = Color3.fromRGB(255, 0, 4)
				keycardLight2.Color = Color3.fromRGB(255, 0, 4)
				task.wait(2)
				tweenClse1:Play(nil,1000)
				tweenClse2:Play(nil,1000)
				tweenClse1.Completed:Wait()
				prompt.Enabled = true
				prompt2.Enabled = true
				debounce = false
				break
			end
		else
			deny:Play()				
			print("Invalid card inserted by: "..plr.Name)
		end

	end
end)

(I use TweenServicePlus)