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)
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.
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)
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.