Loop running multiple times & overlapping itself

I am making a keybinds changing system for my game.
You pick an ability, then a keybind, and then the keybind to trigger that ability is changed.
This part works, however I tried to make a system to stop people from binding every ability to the same keybind, and then I started having issues.

When its the same keybind as another ability, a notification is sent to tell the player, and the keybind is changed to nothing. However, the previous part of the script is still running and is still setting the keybind despite it being a duplicate.

I’m not sure if I’m just doing something completely wrong or if there’s something I’m missing.

Here’s the section of code:

For reference, I want it to work where the keybind is set to nothing when it’s a duplicate. And only 1 notification should be sent, however, it sends multiple, and even though it sends the “already bound” notification, the original part of the loop still seems to be running over top and changing the keybind regardless.

I thought about making a debounce to force it to only run once, but I think that would break the script if you tried to change another keybind.

local Powers = Character:WaitForChild("Keys (T)")

if Powers then
	local Keybinds = Powers.Keybinds
	for _,keys in pairs(Keybinds:GetChildren()) do
		local Button = Instance.new("TextButton", script.Parent)
		Button.Name = keys.Name
		Button.Text = keys.Name
	end

	for _,buttons in pairs(script.Parent:GetChildren()) do
		if buttons:IsA("TextButton") then
			buttons.MouseButton1Click:Connect(function()
				script.Parent.Parent.Keys.TextLabel.Text = buttons.Text
			end)
		end
	end

	for _,options in pairs(script.Parent.Parent.Keys:GetChildren()) do
		if options:IsA("TextButton") then
			options.MouseButton1Click:Connect(function()
				local Chosen = options.Text
				if script.Parent.Parent.Keys.TextLabel.Text ~= "name" then
					local NewKey = Keybinds:FindFirstChild(script.Parent.Parent.Keys.TextLabel.Text)
					if NewKey ~= nil then
						for _,allkeybinds in pairs(Keybinds:GetChildren()) do
							if allkeybinds.Value ~= Chosen then
								NewKey.Value = Chosen
								print("Bound "..script.Parent.Parent.Keys.TextLabel.Text.." to ".. options.Text)
								task.spawn(function()
									Notifications:Notify("Keybind Changed", "Bound "..script.Parent.Parent.Keys.TextLabel.Text.." to "..options.Text, "rbxassetid://15122356778", 5, notifConfig, Player)
								end)
							else
								print("something else is bound to "..options.Text)
								NewKey.Value = ""

								task.spawn(function()
									Notifications:Notify("Keybind Changed", "Something else is already bound to "..options.Text..", so "..script.Parent.Parent.Keys.TextLabel.Text.." was unbound.", "rbxassetid://15122356778", 5, notifConfig, Player)
								end)

							end
						end
					end
				end
			end)
		end
	end

end
1 Like

This is what you are currently doing:

For every keybind (that already exists):
Is my desired keybind this keybind?
If it is, clearly this keybind already exists, unbind. Else, bind.

Clearly, you will end up binding and unbinding several times as this action is within your loop which iterates over every single existing keybind. Even if your keybind already exists, you are binding it whenever the given keybind you are iterating over is not the same as your desired one.

Instead what you should be doing is:

For every keybind (that already exists):
Is my desired keybind this keybind?
If it is, clearly this keybind already exists. If not, keep going.
If there was a single match within that loop, then the keybind exists, unbind. Else, bind.

Try this instead:

local Powers = Character:WaitForChild("Keys (T)")

if Powers then
	local Keybinds = Powers.Keybinds
	for _,keys in pairs(Keybinds:GetChildren()) do
		local Button = Instance.new("TextButton", script.Parent)
		Button.Name = keys.Name
		Button.Text = keys.Name
	end

	for _,buttons in pairs(script.Parent:GetChildren()) do
		if buttons:IsA("TextButton") then
			buttons.MouseButton1Click:Connect(function()
				script.Parent.Parent.Keys.TextLabel.Text = buttons.Text
			end)
		end
	end

	for _,options in pairs(script.Parent.Parent.Keys:GetChildren()) do
		if options:IsA("TextButton") then
			options.MouseButton1Click:Connect(function()
				local Chosen = options.Text
				if script.Parent.Parent.Keys.TextLabel.Text ~= "name" then
					local NewKey = Keybinds:FindFirstChild(script.Parent.Parent.Keys.TextLabel.Text)
					if NewKey ~= nil then
						local found = false -- Edit starts here
						for _,allkeybinds in pairs(Keybinds:GetChildren()) do
							if allkeybinds.Value == Chosen then
								found = true
								break
							end
						end
						if found == false then
							NewKey.Value = Chosen
							print("Bound "..script.Parent.Parent.Keys.TextLabel.Text.." to ".. options.Text)
							task.spawn(function()
								Notifications:Notify("Keybind Changed", "Bound "..script.Parent.Parent.Keys.TextLabel.Text.." to "..options.Text, "rbxassetid://15122356778", 5, notifConfig, Player)
							end)
						else
							print("something else is bound to "..options.Text)
							NewKey.Value = ""

							task.spawn(function()
								Notifications:Notify("Keybind Changed", "Something else is already bound to "..options.Text..", so "..script.Parent.Parent.Keys.TextLabel.Text.." was unbound.", "rbxassetid://15122356778", 5, notifConfig, Player)
							end)
						end
					end
				end
			end)
		end
	end
end

1 Like

Worked perfectly, thank you! :heart:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.