How would i detect something like this?

Sorry for the vague title, dont really know how to explain it
But basically setting up some sort of shop system

And when they purchase the gun i want the button to change to equip instead of purchase again, but currently the only way they see the equip button after purchase is “re-clicking” on the gun’s shop button

Code

Button Script (Local)

local GunGui = script.Parent
local GunModule = require(game.ReplicatedStorage.Modules.GunShop)
local ShopEvent = game.ReplicatedStorage.Events:WaitForChild("ShopEvent")

repeat wait() until #GunGui:GetChildren() > 0 

local function GuiClicked(Gui, Gun)
	if Gui and GunModule[Gun] then
		ShopEvent:Fire(Gun)
	end
end


for i, v in ipairs(GunGui:GetChildren()) do
	if v.ClassName == "TextButton" or v.ClassName == "ImageButton" then
		v.Activated:Connect(function()
			GuiClicked(v, v.Gun.Value)
		end)
	end
end

Selected Gun Script (Local)

local SelGui = script.Parent
local player = game.Players.LocalPlayer
local GunMod = require(game.ReplicatedStorage.Modules.GunShop)
local GunEvent = game.ReplicatedStorage.Events:WaitForChild("ShopEvent")
local PurchaseEvent = game.ReplicatedStorage.Events:WaitForChild("PurchaseEvent")
local Image = SelGui["GunPicture(TEMP)"]
local CostText = SelGui.CostLabel
local ReqText = SelGui.ReqLevelLabel
local PurchaseButton = SelGui.PurchaseButton
local EquipButton = SelGui.EquipButton
local GunSelected = nil

local function BuyGun(Gun)
	if not Gun then return "No Gun Selected" end
	if not GunMod[Gun] then return "NoGun" end
	PurchaseEvent:FireServer(Gun)
end

GunEvent.Event:Connect(function(Gun)
	if Gun == GunSelected then
		GunSelected = nil
		
		Image.Image = 0
		CostText.Text = " "
		ReqText.Text = " "
		PurchaseButton.Visible = false
		EquipButton.Visible = false
	else
		GunSelected = Gun

		Image.Image = if GunMod[Gun].PictureId then "http://www.roblox.com/asset/?id=" .. GunMod[Gun].PictureId else 0
		CostText.Text = GunMod[Gun].Cost .. "$"
		ReqText.Text = GunMod[Gun].LevelReq
		if game.ReplicatedStorage.Temp:FindFirstChild(player.Name .. "DataFolder").OwnedGuns:FindFirstChild(Gun) then
			EquipButton.Visible = true
		else
			PurchaseButton.Visible = true	
		end
	end
end)

PurchaseButton.Activated:Connect(function()
	BuyGun(GunSelected)
end)

Purchase Script (Server)

local PurchaseEvent = game.ReplicatedStorage.Events:WaitForChild("PurchaseEvent")
local GunMod = require(game.ReplicatedStorage.Modules.GunShop)

local function CheckIfCanPurchase(Player, Gun, PlrFolder)
	if not GunMod[Gun] then return false end
	if not PlrFolder then return false end
	if PlrFolder.CashValue.Value < GunMod[Gun].Cost then return false end
	if PlrFolder.OwnedGuns:FindFirstChild(Gun) then return false end
	--if PlrFolder.LevelValue.Value < GunMod[Gun].LevelReq then return false end
	return true
end

local function PurchaseGun(Player, Gun)
	local PlrFolder = game.ReplicatedStorage.Temp:FindFirstChild(Player.Name .. "DataFolder")
	local Check = CheckIfCanPurchase(Player, Gun, PlrFolder)
	
	if Check == true then
		PlrFolder.CashValue.Value -= GunMod[Gun].Cost
		local GunVal = Instance.new("StringValue", PlrFolder.OwnedGuns)
		GunVal.Name = Gun
		print("PlayerBoughtGun")
	else
		print("PlayerDidntBuy")
	end
end

PurchaseEvent.OnServerEvent:Connect(PurchaseGun)
Extra Code

Basically code that may or may not help
Folder Creation (Server)

game.Players.PlayerAdded:Connect(function(plr)
	if game.ReplicatedStorage.Temp:FindFirstChild(plr.Name .. "DataFolder") then return end
	local Folder = Instance.new("Folder", game.ReplicatedStorage.Temp)
	Folder.Name = plr.Name .. "DataFolder"
	
	local CoinVal = Instance.new("NumberValue", Folder)
	CoinVal.Name = "CashValue"
	CoinVal.Value = 0

	local ExpVal = Instance.new("NumberValue", Folder)
	ExpVal.Name = "ExpValue"
	ExpVal.Value = 0
	
	local OwnedGunsFolder = Instance.new("Folder", Folder)
	OwnedGunsFolder.Name = "OwnedGuns"
end)

GunModule (Module)

local module = {
	
	["Ak47"] = {["Cost"] = 150, ["LevelReq"] = 0, ["CanBePurchased"] = true, ["PictureId"] = 6776562111} -- Temp Picture Id
	
}

return module

There are a couple ways you could do this, an easier but definitely not cleaner method would be to have either a purchased BoolValue or purchased intValue for each weapon in the game.

You could either check the Value in a while loop, or wait a second or two for your whole purchase script to finish before checking the boolean when you click the purchase button.

The harder but cleaner method would be to fire a remote event that updates the purchased weapon’s purchase button after the purchase script notes that a player bought a gun.

For the easier but more dirty method you would add to your “Folder Creation” something along these lines

local isPurchased = Instance.new("Folder", plr)
isPurchased.Name = "isPurchased"

local Ak47 = Instance.new("IntValue", isPurchased)
Ak47.Name = "Ak47"
Ak47.Value = 0

--add other values for other guns etc.

Then for checking if it’s been purchased

local plr = game.Players.LocalPlayer

while wait() do

if plr:WaitForChild("isPurchased").Ak47.Value == 1 then
(purchasebutton).Visible = false --Change "purchasebutton" to wherever the path to the button is.
(equipbutton).Visible = true --Change "equipbutton" to wherever the path to the button is
else
(purchasebutton).Visible = true --Surely you know what to do.
(equipbutton).Visible = false
end

For the remote event method
Insert a remote event into ReplicatedStorage
Fire the remote event to the client when the purchase goes through
Change the buttons Visibility or destroy them whatever you want to do.

couldn’t i do something like find if the value of the gun is already in the owned guns folder?

Kinda like here and check for it?
And just use the while wait() loop to check if it exists?

Yes, you could. You would run a while wait() loop, and just check if either the value exists or if it’s or a part or something you could just check if it’s ~= nil. There are lots of ways to do it I just outlined two ways. Do whatever you think is easiest and will work in the long term the longest.

Why not create a .ChildAdded event for the data folder, check if the selected gun is equal to the name of the new child, and then update the button’s visibility if it is equal?

local dataFolder = path.to.folder -- player's data folder

dataFolder.ChildAdded:Connect(function(child)
    if child.Name == selectedGun then
        equip.Visible = true
        purchase.Visible = false
    end
end)

@snowwolf1234567890, there are a few issues with your method:

1- You are creating a new value for every single item, even if they don’t own it. This will be a burden to add the new object every time OP wants to add a new item. Especially if they want to add multiple guns at one time. Mental factors aside, it’s also bad practice when it comes to data save size. You are creating values for items that might be unobtainable, or the player doesn’t own yet. This is bad because this still takes up space and contributes to the 4kb save size limit when the save size could be seriously reduced if items were only added once needed. You should always assume the item is not owned (the value does not exist) unless the value exists. And in that case, make the modifications to the UI.

2- Unfortunately with a while-true-do loop, you have to create a new thread or script for each item. This is bad when it comes to memory and CPU usage, especially when Roblox offers events that will yield the thread until needed/call functions only when needed. You will also notice the button’s visibility will update every 0.03 seconds whereas with events, it will update instantly. wait() has also been superseded by task.wait().

3- Also with a remote event, you’re sending unnecessary data to the client which isn’t a huge deal but Roblox handles replication for you so this may not be the best option when it comes back to using remotes as-needed and never more. More data that needs to be sent from the server to the client and vice versa means longer delay (higher ping).

For 1, as I said it’s not a clean method. Just a generally easy method of going about something like this.
For 2, Unfortunately while loops are expensive, but they do need to be used sometimes (not required here just a quick and simple method of checking).
For 3, You’re right unnecessary data is being sent to the client, but it generally shouldn’t be enough to impact ping in a large way especially if you’re just firing it on purchase.

Overall, is your method the best? Most likely. Would your method work? Most Likely.
Would my methods work? Most likely.
Should you strive for cleanliness, and low processing power? Of Course!

The real takeback here is that there are multiple methods to do (almost) everything. All with some sort of pros and cons which you must weigh when designing and building your game. You must then decide based on these pro’s and con’s what works best in your particular situation. :grinning:

1 Like