GUI Button not working correctly

  1. What do you want to achieve?
  1. I’d like the GUI button to always give the tool to the player when clicked. It only gives the tool once and continues to subtract 10 coins from leaderstats when clicked without actually giving the tool to the player.

  2. The tool is still given to the player even though they don’t actually have enough coins to purchase the item (all items are 10 coins).

  3. I’d like the tool in one player’s hand to also appear for other players in the game. Currently, it only shows the tool for the player who possesses the tool but not the other players. To my knowledge, it’s because the tool is in ReplicatedStorage; however, I’m not sure how to accomplish this goal.

  1. What is the issue?
    Here’s two videos:


  2. What solutions have you tried so far?
    I’ve tried re-writing the code (from the very limited knowledge I have as I’m new to scripting) as well as searching for hours on Reddit, the DevForum, and other resources.

Here’s some more information:
Script in ServiceScriptService for “TakeCash” RemoteEvent (“TakeCash” is in ReplicatedStorage):

game.ReplicatedStorage.TakeCash.OnServerEvent:Connect(function(player)
	if player.leaderstats.Coins.Value >= 10 then
		player.leaderstats.Coins.Value -= 10
	end
end)

Local Scripts within GUI Buttons:

local player = game.Players.LocalPlayer
local folder = game:GetService("ReplicatedStorage"):FindFirstChild("Food")
local subFolder = folder:FindFirstChild("Cafe")
local coffee = game.ReplicatedStorage.Food.Cafe.Coffee
local backpack = player.Backpack

script.Parent.MouseButton1Click:Connect(function()
	coffee:Clone()
	coffee.Parent = backpack
end)
local debounce = false
script.Parent.MouseButton1Click:Connect(function()
	if not debounce then
		debounce = true
		game.ReplicatedStorage.TakeCash:FireServer()
		wait(0.1)
		debounce = false
	end
end)

Let me know if you need any more information!
I would greatly appreciate the help! I’ve just started scripting about a month ago and truly enjoy using the DevForum as a learning resource! :slight_smile:

2 Likes

Hey there,
1.This script will clone the coffee only to you, and it’s always to do that from a server script. [Simply clone the item on the first script you sent above]

2.The second video hasnt loaded yet

Use task.wait() instead of wait [it’s more efficient].

1 Like

Here’s the 2nd video (I hope it works now).

The cloning script is a local script inside of the GUI button—are you saying I should put the code inside a regular script? Or do I remove all of the code written above the code you mentioned?

P.S. Thank you for the task.wait tip, I will see if will fix the problem.

1 Like

After these lines:

if player.leaderstats.Coins.Value >= 10 then
	player.leaderstats.Coins.Value -= 10
  --clone item here, make sure they dont have the item already[optional]
end

You should clone the desired item into the player’s backpack. [if you have multiple gears, you could pass the buttons’ name in the event, and access them from the tools folder on the server]

1 Like

I recommend reading this to understand the server-client barrier

Your code is essentially doing the logic backwards, the local script is cloning the item and asking the server to remove their coins

Instead, you should be asking the server if you have enough coins and if so, it removes the coins and copies the tool into their backpack

1 Like

I see!

I put the cloning code into the ServerScript and the tools into the ServerStorage; however, now the item isn’t being given to the player.

game.ReplicatedStorage.TakeCash.OnServerEvent:Connect(function(player)
	if player.leaderstats.Coins.Value >= 10 then
		player.leaderstats.Coins.Value -= 10
		
		local player = game.Players.LocalPlayer
		local folder = game:GetService("ServerStorage"):FindFirstChild("Food")
		local subFolder = folder:FindFirstChild("Cafe")
		local coffee = game.ServerStorage.Food.Cafe.Coffee
		local backpack = player.Backpack

		script.Parent.MouseButton1Click:Connect(function()
			coffee:Clone()
			coffee.Parent = backpack
		end)
	end
end)

Thanks for explaining! I’ve put the code into the ServerScript; however, now the item from ServerStorage won’t be given to the player after clicking the button.

game.ReplicatedStorage.TakeCash.OnServerEvent:Connect(function(player)
	if player.leaderstats.Coins.Value >= 10 then
		player.leaderstats.Coins.Value -= 10
		
		local player = game.Players.LocalPlayer
		local folder = game:GetService("ServerStorage"):FindFirstChild("Food")
		local subFolder = folder:FindFirstChild("Cafe")
		local coffee = game.ServerStorage.Food.Cafe.Coffee
		local backpack = player.Backpack

		script.Parent.MouseButton1Click:Connect(function()
			coffee:Clone()
			coffee.Parent = backpack
		end)
	end
end)

You should definitely take a look into best practices related to doing something like this, but I’ll go ahead and tell you what would work. So when a button is clicked, you should be telling the server what kind of tool the player is trying to buy. So for example, something like this:

local toolName = "Coffee"

local isProcessing = false
script.Parent.Activated:Connect(function()
	if not isProcessing then
		isProcessing = true
		game.ReplicatedStorage.TakeCash:FireServer(toolName)
		task.wait(.5)
		isProcessing = false
	end
end)

You should also be using a more specific remote, like one called “PurchaseTool” instead of “TakeCash”. And once you implement something like that, you can put all your tools in a generic tool folder. With that done, you could then do something like this for the server script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local purchaseToolRemote = ReplicatedStorage:FindFirstChild("PurchaseTool")
local toolFolder = ReplicatedStorage:FindFirstChild("Tools")

purchaseToolRemote.OnServerEvent:Connect(function(player, toolName)
	assert(typeof(toolName)=="string", "toolName must be a string!")
	
	local foundTool = toolFolder:FindFirstChild(toolName)
	if foundTool then
		local playerCoins = player.leaderstats.Coins
		if playerCoins.Value >= 10 then
			playerCoins.Value -= 10
			
			local newTool = foundTool:Clone()
			newTool.Parent = player:FindFirstChild("Backpack")
		end
	else
		warn("Tool with the name '"..toolName.."'' does not exist inside the tool folder!")
	end
end)

By passing along the name of the tool the player is trying to buy, the server can find its tool if it exists. It can then check if the player has enough coins to buy the tool. If the player has enough coins, it’ll take away the required amount (aka, the price) and give the tool to the player.

And if you wanted to have specific prices for specific tools, there’s a few ways you could do that. I personally would use attributes on folders for something like that.

1 Like

Okay! I created a “Tools” folder in replicated storage and put the Coffee tool in the folder and replaced the “TakeCash” R.E. with “PurchaseTool”.

I removed all the scripts in the GUI button and replaced it with the first script. (In the script you wrote, I replaced the “TakeCash” with “PurchaseTool” since I deleted the “TakeCash” R.E. from Rep.Storage).

local itemName = "Coffee"

local isProcessing = false
script.Parent.Activated:Connect(function()
	if not isProcessing then
		isProcessing = true
		game.ReplicatedStorage.PurchaseTool:FireServer(itemName)
		task.wait(.5)
		isProcessing = false
	end
end)

Then I replaced the current ServerScript with the script you wrote.
(Quick Question: itemName =/ toolName, correct?)

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local purchaseToolRemote = ReplicatedStorage:FindFirstChild("PurchaseTool")
local toolFolder = ReplicatedStorage:FindFirstChild("Tools")

purchaseToolRemote.OnServerEvent:Connect(function(player, toolName)
	assert(typeof(toolName)=="string", "itemName must be a string!")
	
	local foundTool = toolFolder:FindFirstChild(toolName)
	if foundTool then
		local playerCoins = player.leaderstats.Coins
		if playerCoins.Value >= 10 then
			playerCoins.Value -= 10
			
			local newTool = foundTool:Clone()
			newTool.Parent = player:FindFirstChild("Backpack")
		end
	else
		warn("Tool with the name '"..toolName.."'' does not exist inside the tool folder!")
	end
end)

However, now when I click the GUI button it doesn’t remove coins or give me the tool.

I noticed you wrote, “itemName must be a string!” and I’m wondering what that means and how it’s related to the tool. Am I supposed to put a string somewhere in the localscript? I’m really sorry for being such a noob :sweat_smile:

I swapped itemName to toolName in the server script snippet, but I forgot to change it everywhere. In other words itemName = toolName.

Everything seems correct, but I can’t say for sure where your issue stems from. You could try adding a few print statements to see where the issue arises. If I had to guess, there could potentially be something wrong with the button’s properties. You should double check and make sure the button’s Active property is set to true.

The reason why I think the Active property is the problem is because you were previously using MouseButton1Click, which will fire the event even if the Active property is set to false. However, Activated is what my snippet uses and that event respects the Active property. This means that the Activated event won’t fire if the Active property is set to false. Since you’re saying nothing happens when you click the button, I’m guessing that the Active property is sinking your input.

1 Like