Debounce not working correctly

Hello developers,

Im making a “buy random items” game. Current problem is that users are accessing the RemoteEvent via hacks. My goal is to get this to where I dont have to rescript the entire game (which will have to be done if I remove the remote event)

Anyway, something is failing to detect the debounce. I want the local player to have to wait 4 seconds before buying another item. I’ve been trying for quite a while and cannot figure it out.

The Main Item handler (localscript in StarterGui)

local Items = workspace.BuyingParts.Items:GetChildren()
local debounce = game.StarterGui.Debounce
local PlayerPassthrow = game:GetService("ReplicatedStorage").Overseer

for i,v in pairs(Items) do

	local itemPrice = v.Price
	local BLmembers = {1}

	v.ProximityPrompt.ActionText = ("Buy " .. v.Name)

	v.ProximityPrompt.TriggerEnded:Connect(function(player)
		
		for i,v in pairs(BLmembers) do
			if player.UserId == v then
				player:WaitForChild("PlayerGui"):WaitForChild("Notifications").BlockedNotification.Disabled = false
				player:WaitForChild("PlayerGui"):WaitForChild("Notifications").BlockedNotification.Disabled = true
				return
			end
		end
		
		local function callback(Text)

			if Text == "Yes" and debounce == false then
				if player.leaderstats.Money.Value >= v.Price.Value then

					local NotificationBindable1 = Instance.new("BindableFunction")
					NotificationBindable1.OnInvoke = callback
					debounce = true
					
					game.StarterGui:SetCore("SendNotification" , {
						Title = "Purchase Success";
						Text = "You have purchaced " .. v.Name .. " for the price of $" .. itemPrice.Value;
						Icon = "";
						Duration = 5;
						Callback = NotificationBindable1;
					})

					PlayerPassthrow:FireServer(itemPrice.Value)

				elseif player.leaderstats.Money.Value < v.Price.Value then

					local NotificationBindable2 = Instance.new("BindableFunction")
					NotificationBindable2.OnInvoke = callback


					game.StarterGui:SetCore("SendNotification" , {
						Title = "Purchase Failure";
						Text = "The purchase of " .. v.Name .. " has failed because you do not have at least $" .. itemPrice.Value;
						Icon = "";
						Duration = 5;
						Callback = NotificationBindable2;
					})
				end

			elseif Text == "No" then
				local NotificationBindable2 = Instance.new("BindableFunction")
				NotificationBindable2.OnInvoke = callback


				game.StarterGui:SetCore("SendNotification" , {
					Title = "Purchase Declined";
					Text = "The purchase of " .. v.Name .. " has been successfully declined, you have not been charged";
					Icon = "";
					Duration = 5;
					Callback = NotificationBindable2;
				})
			end
		end

		local NotificationBindable = Instance.new("BindableFunction")
		NotificationBindable.OnInvoke = callback


		game.StarterGui:SetCore("SendNotification" , {
			Title = "Purchase Confirmation";
			Text = "Are you sure you want to purchase " .. v.Name .. " for the price of $" .. itemPrice.Value;
			Icon = "";
			Duration = 5;
			Button1 = "Yes";
			Button2 = "No";
			Callback = NotificationBindable;
			})
	end)
end

BuyDebounce in ServerScriptService:

while true do
	local debounce = game.StarterGui.Debounce
	
	if debounce == true then
	task.wait(4)
	debounce.Value = false
		script.Disabled = true
	end
	task.wait()
end

if game.StarterGui.Debounce is a BoolValue you must reference debounce.Value to get whether the value contained within is true or false; your comparison if debounce == true will always evaluate true should debounce exist (do if debounce.Value instead)

onto the next problem, the player is still handling their own debounce. If they’re already cheating, they can spoof past that condition and fire the event whenever. Ideally the server would hold a table of purchasers and time of purchase, iterating through it whenever a new purchase is prompted to see if they have to wait still, else remove them from the table.

it also looks like you’re entrusting the client to tell the server how much something costs? The server should always handle a game-critical value like that to prevent cheating.