Hello!
I have a pretty nifty shop purchase script, but I want to streamline it further to put more of the work on the Server as opposed to the Client/Local. I've created a few Remote Events that seem to be working fine, but I'm not sure I'm utilizing them properly for max efficiency. Essentially, my goal here is to make sure the shop purchase script works properly, and never over/double charges the player, or sends their Coins into the negative. I'd had that happen previously, randomly, when I was relying entirely on the Client/Local doing the function, and that is not ideal for the player experience.
Here are my Remote Events inside the Script under ServerScriptStorage:
--//Get Services local ReplicatedStorage = game:GetService("ReplicatedStorage") --//EventFolder local Events = ReplicatedStorage:WaitForChild("Events") --//Remote Events local CoinsPurchase = Events:WaitForChild("CoinsPurchase") local ItemOwned = Events:WaitForChild("ItemOwned") local CanAffordItem = Events:WaitForChild("CanAffordItem") -- PURCHASE WITH COINS -- CoinsPurchase.OnServerEvent:Connect(function(Player, Value, Amount) if Player.leaderstats.Coins.Value >= Amount then print('Server says player has enough Coins for the purchase.') Player.leaderstats.Coins.Value = Player.leaderstats.Coins.Value - Amount print(Value) Value.Value = true else print("Player does not have enough Coins for the purchase.") end end) --CHECK IF ITEM OWNED -- ItemOwned.OnServerEvent:Connect(function(Player,Value) if Value.Value == false then print('Player does not own this item.') else print('Player does own item') end end) --CHECK IF PLAYER CAN AFFORD ITEM -- CanAffordItem.OnServerEvent:Connect(function(Player,Value, Amount) if Player.leaderstats.Coins.Value >= Amount then print('Player CAN afford Item') else print('Player Can NOT afford Item') end end)
And this is a slightly abbreviated version of my shop purchase Local Script. When the Item01 button is clicked, it makes visible the BuyButton script and fills in the variables:
--//Get Services local RS = game:GetService("ReplicatedStorage") local Players = game:GetService("Players") local Player = Players.LocalPlayer local currencyCOINS = Player.leaderstats.Coins --//EventFolder local Events = RS:WaitForChild("Events") --//Events local ToolPurchase = Events:WaitForChild("ToolPurchase") local CoinsPurchase = Events:WaitForChild("CoinsPurchase") local ItemOwned = Events:WaitForChild("ItemOwned") local CanAffordItem = Events:WaitForChild("CanAffordItem") --//SHOP FRAME local PurchaseFrame = Frame.PurchaseFrame local BuyButton = PurchaseFrame.BuyButton local ItemDesc = PurchaseFrame.ItemDesc local Price = PurchaseFrame.Price local ItemTrackName = RS:WaitForChild("ItemTrackNameShop") local ItemPurchased = RS:WaitForChild("ItemPurchased") local ItemPriceAmount = RS:WaitForChild("ItemPriceAmount") BuyButton.MouseButton1Click:Connect(function() MenuClickSound:Play() local amount = Cost local Value = ItemPurchased.Value ItemDesc.Text = 'Purchase '..ItemTrackName.Value..'?' Price.Text = ItemPriceAmount.Value ItemOwned:FireServer(Player.Inventory[Value]) -- Checks if the Item is owned. CanAffordItem:FireServer(Player.Inventory[Value], amount) -- Checks if the Player can afford the Item. if Player.Inventory[Value].Value == true then ItemDesc.Text = 'You have already purchased this Item!' wait(3) else if Player.leaderstats.Coins.Value >= amount then CoinsPurchase:FireServer(Player.Inventory[Value], amount) wait(1) PurchaseClickSound:Play() ItemDesc.Text = 'Purchase Complete for '..ItemTrackName.Value..'! Equip this Item from your Inventory!' wait(3) PurchaseFrame.Visible = false ItemDesc.Text = 'Purchase '..ItemTrackName.Value..'?' wait(1) else local coinsrequired = amount - currencyCOINS.Value ItemDesc.Text = 'You need '.. coinsrequired ..' more Coins to buy this item!' wait(2) ItemDesc.Text = 'Purchase '..ItemTrackName.Value..'?' wait(5) PurchaseFrame.Visible = false end end end)--Closes Purchase Frame Item01.MouseButton1Click:Connect(function() PurchaseFrame.Visible = true ItemTrackName.Value = 'Item01' ItemDesc.Text = 'Purchase Item01?' ItemPurchased.Value = 'Item01' Cost = 10 ItemPriceAmount.Value = Cost end)
As you can see in the shop purchase script above, I first run the Remote Events to see if the Player already owns the item, and then if they can afford the item, before following it up with the local/client determining the same thing, and then the Remote Event fires that actually grants the Item, and deducts the amount/cost of the Item.
Am I using the Remote Events correctly here? Can I improve upon it further?
Thank you!
This can easily be exploited which isn't a good thing. A simple change I did in my script was make it where you need to have the GUI open in order to make a purchase. Not only that you can't get a certain weapon with a certain price. It has its own event for each item. before you say it's too much work, think about what will happen with no exploiter for about a few more minutes of work to a few minutes but you have a ton of exploiters in your game. This is what I did for me event.
Local Script in GUI
script.Parent.MouseButton1Down:connect(function() local plr = game.Players.LocalPlayer local money = plr.stats.Money --Checks it if money.value >= Price then GunShop.Glock:FireServer(plr) script.Parent.Parent.Parent.Information.Price.Text = "Thank you for your purchase!" wait(3) if script.Parent.Parent.Parent.Information.Price.Text == "Thank you for your purchase!" then script.Parent.Parent.Parent.Information.Price.Text = Price else end end end)
Script in ServerScriptStorage.
GunShop.Glock.OnServerEvent:connect(function(plr) local Cost = 500 --What ever the price is-- if plr.IsLTCOwner.value == true then --Checks if they own a license just something in my game-- if plr.PlayerGui.Shop then --Checks for the GUI-- if plr.stats.Money.Value >= Cost then --Checks for money-- local Weapon = game.ServerStorage.GunShop:FindFirstChild("Glock") local Cash = plr.stats.Money Cash.Value = Cash.value - Cost --Bye bye money-- local Cloned = Weapon:Clone() Cloned.Parent = plr.Backpack --Now they have it-- end end end end)
Its good to learn to do this so people are not able to exploit your game. They can spawn anything but need money and the GUI so there is almost no point.
Hope this helped you out a bit.