How would I check if a player owns a tool?

Hi there, I am working on a shop Gui and my goal is to make it so that the buy button in a template (which the template is cloned for every tool in a folder inside replicatedstorage) displays “OWNED” when bought. The issue that I can’t seem to get around my head is how would I do this with a template that clones for every tool in the folder and then change the text individually of the buy button without changing it for every other clone too.

I’ve left most of the scripts just so you know a bit of background context.

Localscript for cloning the template:

local folder = game.ReplicatedStorage:WaitForChild("Tools")
local frame = script.Parent
local template = frame.shoptemplate

template.Visible = false

for _, tool in pairs(folder:GetChildren()) do
	local newTemplate = template:Clone()
	local button = newTemplate.Buy
	newTemplate.Parent = frame
	newTemplate.Visible = true
	newTemplate.Name = tool.Name
	newTemplate.TextLabel.Text = tool.Name
	newTemplate.Buy.Text = "$"..tool.Cost.Value
	
	button.MouseButton1Click:Connect(function()
		local result = game.ReplicatedStorage.BuyItem:InvokeServer(tool.Name)

		if result == true then
			--
		else
			--
		end
	end)
end

Serverscript for handling the remote of the buy function:

game.ReplicatedStorage.BuyItem.OnServerInvoke = function(player,toolName)
	
	local tool = game.ReplicatedStorage.Tools:FindFirstChild(toolName)
	
	if tool and not player.StarterGear:FindFirstChild(toolName) then
		
		if tool:FindFirstChild("Cost") then
			
			if tool.Cost.Value <= player.leaderstats.Coins.Value then
				
				player.leaderstats.Coins.Value -= tool.Cost.Value
				
				local newTool = tool:Clone()
				
				newTool.Parent = player.Backpack
				
				
				local newTool = tool:Clone()
				
				newTool.Parent = player.StarterGear
			
				
				return true
			end
		end
	end
end

everytime someone either open the gui or buy something update all the buttons if they “own” the item and you can check if they own something by using Player.Backpack:FindFirstChild(tool name here) it would return nil if it doesn’t exist, you can do it like this

--your update script
if player.Backpack:FindFirstChild("BloxyCola") then
    button.Text = "OWNED"
end

this is a one time item and resets when you die right? if you want something that saves you will need to use data store and then check if that item is in the datastore, the one i showed above is just to check if a player has an item in their backpack

Is there a way I can do this with every item, but also keep them individual (as in one only changes instead of all of the buttons)?

Oh, it already saves so it’s a permanent item.

what do you mean? if you put this script a local script and parent it to the specific item button and change ‘BloxyCola’ to what item name you want then it should work

I mean like, instead of copy pasting that script for every item in the folder, can’t I just for every tool check if it is bought, and then if it one of it’s bought then that cloned template will have the buy button saying that it’s owned?

long sentence sorry

yes you can do that, but it will be harder to explain if we can’t see your explorer

Alright, that’s fine I’ll just use that then.

oh wait lmao i’m sorry i didn’t see the explorer ss in the orginal post, wait

Also, how would I index “player”?

game.Players.LocalPlayer since its in a localscript

Alright.

You could create a little update() function, which would go through each button in your GUI and check if you own it, if so, change the text for that GUI to owned, else, leave it be.

You can achieve this with the same method you’re using.

function update()
    for _,shopItem in pairs(frame:GetChildren())do -- search frame for the shop items
        if player.Backpack:FindFirstChild(shopItem.Name) then --You've named the frame to match the tools name, so we can do this
            shopItem.Buy.Text = "OWNED" -- this will only affect the shopItem you're looking at
        else
            print("You don't own "..shopItem.Name)
        end
    end
end

call update whenever the purchase button is clicked, this will go through each frame, check if your player has the item in their backpack and set the text to “OWNED” if they do

If you want to implement sanity checks then you can just run this on the server and return the results to the client.

1 Like

Hm, the script didn’t seem to work. Am I doing something wrong?

local folder = game.ReplicatedStorage:WaitForChild("Tools")
local frame = script.Parent
local template = frame.shoptemplate
local Players = game:GetService("Players")
local player = Players.LocalPlayer

template.Visible = false

for _, tool in pairs(folder:GetChildren()) do
	local newTemplate = template:Clone()
	local button = newTemplate.Buy
	newTemplate.Parent = frame
	newTemplate.Visible = true
	newTemplate.Name = tool.Name
	newTemplate.TextLabel.Text = tool.Name
	newTemplate.Buy.Text = "$"..tool.Cost.Value
	local button = script.Parent
	
	if player.Backpack:FindFirstChild("BloxyCola") then
		button.Text = "OWNED"
	
	button.MouseButton1Click:Connect(function()
		local result = game.ReplicatedStorage.BuyItem:InvokeServer(tool.Name)

			if result == true then
			--
			else
			--
			end
		end)
	end
end

can you try doing this instead,

local folder = game.ReplicatedStorage:WaitForChild("Tools")
local frame = script.Parent
local template = frame.shoptemplate
local Players = game:GetService("Players")
local player = Players.LocalPlayer

template.Visible = false

for _, tool in pairs(folder:GetChildren()) do
	local newTemplate = template:Clone()
	local button = newTemplate.Buy
	newTemplate.Parent = frame
	newTemplate.Visible = true
	newTemplate.Name = tool.Name
	newTemplate.TextLabel.Text = tool.Name
	newTemplate.Buy.Text = "$"..tool.Cost.Value
	local button = script.Parent
	
	if player.Backpack:FindFirstChild(tool.Name) then
		button.Text = "OWNED"
	
	button.MouseButton1Click:Connect(function()
		local result = game.ReplicatedStorage.BuyItem:InvokeServer(tool.Name)

			if result == true then
			--
			else
			--
			end
		end)
	end
end

Still doesn’t show as “OWNED”. I even removed the variable you added in of local button = script.Parent since there was already one.

Also, I already have the BloxyCola in my inventory.

Example of the update function in use, bear in mind it’s not the most efficient

local folder = game.ReplicatedStorage:WaitForChild("Tools")
local frame = script.Parent
local template = frame.shoptemplate
local Players = game:GetService("Players")
local player = Players.LocalPlayer

template.Visible = false

function update()
	for _,shopItem in pairs(frame:GetChildren())do -- search frame for the shop items
		if player:WaitForChild("Backpack"):FindFirstChild(shopItem.Name) then --You've named the frame to  match the tools name, so we can do this
			shopItem.Buy.Text = "OWNED" -- this will only affect the shopItem you're looking at
		else
			print("You don't own "..shopItem.Name)
		end
	end
end

for _, tool in pairs(folder:GetChildren()) do
	local newTemplate = template:Clone()
	local button = newTemplate.Buy
	newTemplate.Parent = frame
	newTemplate.Visible = true
	newTemplate.Name = tool.Name
	newTemplate.TextLabel.Text = tool.Name
	newTemplate.Buy.Text = "$"..tool.Cost.Value
	local button = script.Parent

	button.MouseButton1Click:Connect(function()
		local result = game.ReplicatedStorage.BuyItem:InvokeServer(tool.Name)
		if result then
			update() 
		else
			print("purchase failed.")
		end
	end)
end

However, even the update function seems unnecessary, are you sure you can’t just set the text to “OWNED” if result is true?, remember this click function only affects the GUI it’s highlighted over (so, if you bought the bloxy cola only the Cola UI would be affected by that)

But wouldn’t that mean that’s it’s checking if the remote is true, rather than if it was in your inventory? Wouldn’t that mean if you clicked the button, the text would just change to “OWNED” even if you don’t have the item?

(I know you’re confused with what I’m saying, I think what I’m saying is incorrect.)

Yeah, I think I was correct in the comment above. I think what is wrong here is that you’re updating the text if the remote function was true and rather not the inventory. Could you do something like this, but with inventory (not really asking for a script)?