How to only allow the player to buy item once?

How would I change my script to only allow the player to buy the item once?

I’ve tried to rewrite the script a few times but all I could figure out was how to prevent the tool from going into the player’s backpack again; however, it would still subtract the funds.

I’m going to also create another ScreenGUI called “Repeat” that would pop up if they’ve already purchased the item! But, I wanted to get the code right first!

Here’s the original script:

local RequiredGold = script.Parent.Parent.Parent.Price.Value
local player = game.Players.LocalPlayer
local tool = game.ServerStorage.Shop["Star Sword"]

script.Parent.MouseClick:Connect(function(player)
	if player.Data.Beli.Value >= RequiredGold then
		player.Data.Beli.Value = player.Data.Beli.Value - RequiredGold
		player.PlayerGui:FindFirstChild("Success") 
		local Success = script.Success:clone()
		Success.Parent = player.PlayerGui
		wait(2)
		tool:Clone().Parent = player.Backpack
		player.Character.Humanoid:UnequipTools()
		Success:Destroy()

	else 

		if player.Data.Beli.Value <= RequiredGold then
			player.PlayerGui:FindFirstChild("Failed")
			local Failed = script.Failed:clone()
			Failed.Parent = player.PlayerGui
			wait(2)
			Failed:Destroy()
		end
	end
	wait(2)
end)

Here’s the script with the edit (but still subtracts the currency without giving the tool):

local RequiredGold = script.Parent.Parent.Parent.Price.Value
local player = game.Players.LocalPlayer
local tool = game.ServerStorage.Shop["Star Sword"]:Clone()
local Backpack = player:WaitForChild("Backpack")

script.Parent.MouseClick:Connect(function(player)
	if player.Data.Beli.Value >= RequiredGold then
		player.Data.Beli.Value = player.Data.Beli.Value - RequiredGold
		player.PlayerGui:FindFirstChild("Success") 
		local Success = script.Success:clone()
		Success.Parent = player.PlayerGui
		wait(2)
		
		if player.Backpack:FindFirstChild("Star Sword") then return end
		tool.Parent = player.Backpack
		
		player.Character.Humanoid:UnequipTools()
		Success:Destroy()

	else 

		if player.Data.Beli.Value <= RequiredGold then
			player.PlayerGui:FindFirstChild("Failed")
			local Failed = script.Failed:clone()
			Failed.Parent = player.PlayerGui
			wait(2)
			Failed:Destroy()
		end
	end
	wait(2)
end)	

Thank you :slight_smile:

2 Likes

To help with your issue, a debounce would be perfect for this solution!

Debounces will essentially stop any other processes that have been called due to the if statement returning, in this case true/false.
Simply add a if statement along with the debounce inside of the script as shown below!

local debounce = false
script.Parent.MouseClick:Connect(function(player)
    if not debounce then -- Here is the debounce!
        debounce = true
        if player.Data.Beli.Value >= RequiredGold then
            -- code here
        else
            -- code here
        end
        debounce = false -- place is outside of the other function so it can restart the process.
    end
end)
2 Likes

You can create a NumberValue for this, then check the value of it for reference.

Example:

OwnsGold = Instance.new("NumberValue")
		OwnsGold.Name = "Gold"
		OwnsGold.Value = "0"   -- change the value to 1 when they buy the item
		OwnsGold.Parent = player (or wherever you want to store it)

Once they buy the item, change the value to 1. Then if they try to buy again, just write

if OwnsGold.Value == 1 then
end

This can be modified to your liking but just so you get the general idea.
You can also use different types of values but NumberValues are great if you plan on saving the data.

1 Like

Maybe disable the script when finished?

1 Like

I have never needed to disable a script. This is never a proper way to code anything.

2 Likes

You have a few issues in this code. Your debounce seems to be an actual bool object. You should keep your debounce as a variable in a script. It’s more reliable also since the state of the variable can only be altered by the script.

The second issue is you are removing the gold before you are check if they have the item.
image

The third issue is you need the also check the character for the tool because when you equip a tool it’s removed from the backpack.

The forth issue is that you cloning the tool only 1 time outside the purchase function

local RequiredGold = script.Parent.Parent.Parent.Price.Value
local player = game.Players.LocalPlayer
local Backpack = player:WaitForChild("Backpack")
local tool = game.ServerStorage.Shop["Star Sword"]

local debounce = false
script.Parent.MouseClick:Connect(function(player)
	if debounce then return end
	debounce = true
	
	if player.Data.Beli.Value >= RequiredGold then
		if player.Character:FindFirstChild("Star Sword") then return end
		if player.Backpack:FindFirstChild("Star Sword") then return end

		player.Data.Beli.Value -= RequiredGold
		
		local newTool = tool:Clone()
		tool.Parent = player.Backpack
		
		player.Character.Humanoid:UnequipTools()
	end
	
	task.wait(1)
	debounce = true
end)
1 Like

Thank you so much! You’ve been extremely helpful! :heart:

I was just wondering how I could implement a ScreenGui into the code (using the debounce) that tells the player they’ve already purchased the item as well?

I’d recommend using ‘SendNotification’! The documentation for it can be found here!

game:GetService("StarterGui"):SetCore("SendNotification",{
	Title = "Notification Title", -- Required
	Text = "Notification Description", -- Required
	Icon = "rbxassetid://1234567890" -- Optional
})

Example!