Hello, I am working on a shop for a combat system. I would like the player to only be able to equip one weapon at a time, but always have one equipped. I plan on adding extra equipment/tools like power-ups and grenades, so I can’t just clear the player’s backpack. My current script allows players to buy weapons and it clones it from replicatedstorage and brings it to the players backpack. This means that they can buy multiple of the same tool. Only restriction is if they have a sufficient amount of cash to buy the weapon, and if they don’t a GUI pops up asking them to give me their money. How can I add something to detect whether the tool has been purchased before, even if it isn’t in their inventory? (for later on when it isn’t in their inv.)This is even more necessary because I need to be able to toggle off the buy button and toggle on an equip button. Sorry if my wording was a bit off, I can clarify if you need me to.
current code for the purchase handling script:
local player = game.Players.LocalPlayer
local camera = workspace.CurrentCamera
script.Parent.Buy.MouseButton1Click:Connect(function()
if camera.CFrame == workspace.Cameras.Camera2.CFrame and player.leaderstats.Cash.value >= 1000 then
player.leaderstats.Cash.Value = player.leaderstats.Cash.Value - 1000
game.ReplicatedStorage.Sword:Clone().Parent = player:WaitForChild("Backpack")
else if player.leaderstats.Cash.Value < 1000 then
script.Parent.broke.Visible = true
else if camera.CFrame == workspace.Cameras.Camera3.CFrame and player.leaderstats.Cash.value >= 2500 then
player.leaderstats.Cash.Value = player.leaderstats.Cash.Value - 2500
game.ReplicatedStorage.Longsword:Clone().Parent = player:WaitForChild("Backpack")
else if player.leaderstats.Cash.Value < 2500 then
script.Parent.broke.Visible = true
end
end
end
end
end)
i figured it out, and its really simple. Add in a new local value named something like ownedsword = false, and make sure as an if statement requirement it is false. It will be false the first time, then you toggle it true in the function after where it gives the player the cloned sword. They can’t buy it twice now.
So the first issue I see is that your not using remote events to handle the replicating of the object along with purchasing, essentially when you clone things inside of the client it doesn’t show up for other players and same with taking away cash. > Remote Events
Also your code appears to be a little jumbled up. So its a bit hard to read, however I can see that you want to detect if the player is at a certain camera. I would go about that doing something like this and this is not the most secure method so keep that in mind:
--[[
Create a remote event in replicatedstorage named "PurchaseEvent"
]]--
---//Client//--- leave this in your normal local script
local player = game.Players.LocalPlayer
local camera = workspace.CurrentCamera
local cash = player.leaderstats.Cash
local purchase = game.ReplicatedStorage:WaitForChild("PurchaseEvent")
local cameras = workspace.Cameras
script.Parent.Buy.MouseButton1Click:Connect(function()
if camera.CFrame == camera.Camera2.CFrame and cash.Value >= 1000 then
purchase:FireServer(1000, "Sword") -- send through (cash amount, item)
elseif camera.CFrame == camera.Camera3.CFrame and cash.Value >= 2500 then
purchase:FireServer(2500, "longword") -- send through (cash amount, item)
else
spawn(function() -- this just makes it not slow down the clicking
script.Parent.Broke.Visible = true
wait(.5)
script.Parent.Broke.Visible = false
end)
end
end)
---//Server//--- Put into a serverscript inside of serverscriptservice
local purchase = game.ReplicatedStorage:WaitForChild("PurchaseEvent")
purchase.OnServerEvent:connect(function(player, amount, item)
player.leaderstats.Cash.Value = player.leaderstats.Cash.Value - amount
game.ReplicatedStorage:FindFirstChild(item):Clone().Parent = player.Backpack
end)
Let me know if you have any issues understanding, thank you.
Now there is no limit to how many times each item can be bought. I was hoping they could purchase it only once, and then I would have to figure out a way to make it so that the equip button is only visible when their current camera is in the CFrame of an item they own (I guess would be the best approach for it.)
Would it be the same way that I did above? And how can I make it so that I only have to use one button for the whole thing, instead of copying and pasting the same button over and over for different items?
so the way I would do this is like you said not copying and pasting the same code, I would get all of the cameras inside of the cameras folder and then put inside of those cameras a String Value for the name of the item, a Number Value for the cash amount, it would be something like this;
after having done that, inside the script you could do something like this;
This is an example for the client
script.Parent.Buy.MouseButton1Click:Connect(function()
for i, v in pairs(cameras:GetChildren()) do
if camera.CFrame == v.CFrame then
--I would make sure the cash check is not in the client because its not secure
--We will handle the checking through the server so they cant buy it twice
purchase:FireServer(v.Cost.Value, v.Toolname.Value)
end
end
end)
This is an example for the server
local purchase = game.ReplicatedStorage:WaitForChild("PurchaseEvent")
purchase.OnServerEvent:connect(function(player, amount, item)
if player.leaderstats.Cash.Value >= amount and not player.Character:FindFirstChild(item) and not player.Backpack:FindFirstChild(item) then
--Checks their cash amount through the server the make sure its >= the amount
--Checks their character and their backpack to make sure its not there
player.leaderstats.Cash.Value = player.leaderstats.Cash.Value - amount
game.ReplicatedStorage:FindFirstChild(item):Clone().Parent = player.Backpack
end
end)
I am not sure if this clears anything up, just make sure you use remote events because an exploiter can give themselves 100000+ cash and buy everything. Remote events for the most part keep that from happening and are much more secure.
I forgot to add this but if you want to equip or unequip, use an if statement to check if the tool is or isnt inside the player, these are what you would use to unequip or equip tools; player.Character.Humanoid:UnequipTools(player.Character.Sword), player.Character.Humanoid:EquipTool(player.Character.Sword).
make sure to use a remote event for equiping and unequiping because again the other players will not be able to see or be damaged by them.
Just an example from the client:
local Tool = "Sword"
local Equip = true
game.ReplicatedStorage.toolEquipper:FireServer(Tool, Equip)
example from the server
game.ReplicatedStorage.toolEquipper.OnServerEvent:connect(function(player, tool, equip)
if equip then --Equip is true so lets equip the tool
if player.Backpack:FindFirstChild(tool) then -- if the tool is inside the backpack then continue
--lets unequip the other tools
for i, v in pairs(player.Character:GetChildren()) do
if v:IsA("Tool") then
player.Character.Humanoid:UnequipTools(v)
end
end
--this will equip the players tool from their backpack
player.Character.Humanoid:EquipTool(tool)
end
else --They dont want to equip this tool so lets unequip it
--Unequip the tool
for i, v in pairs(player.Character:GetChildren()) do -- since the player can only have 1 tool at a time, we can still use this just to make sure all the tools are unequipped.
if v:IsA("Tool") then
player.Character.Humanoid:UnequipTools(v)
end
end
end
end)
in my case, I want to make sure that it is specifically a weapon that is being unequipped. I would like to have other tools that are not really main weapons like the swords. For instance, a player can equip a sword but also have a health potion in their inventory. Also, how can i make the buy button turn into an equip button? (only using 2 buttons, instead of 2 for each item?)
perhaps I can add a bool value inside of all of the tools and mark it true if it is a weapon and false if it isn’t, or just put it in the weapons and check if it exists before removing them
its a matter of checking inside the player. a robust way of it would be “If the selected weapon is inside of the character then make it unequip it” and vise versa. When a player equips a weapon on the hotbar, it moves it into the character. And when they unselected it from the hotbar, it goes into the backpack.
My current code looks like post 5 from this topic. I came back and I need to be refreshed on what the heck is going on, and here are some notes I made about equipping the item.
Using an if statement, find which camera a player is at and if they own the according item or find which item it is and if they already have it equipped. Toggle visible false for the buy button while at that camera’s CFrame. This is where it needs to be decided whether the equipped text should be displayed or the equip button.
Does this seem reasonable? And to make the code look more like post 6, do I need to add/change things? It looks like you are using a new remote event called toolEquipper, which I don’t have. Just very confused, because obviously I am not good at scripting lol.
Edit: I just thought about it, what if I added a folder to hold the player’s cloned weapons inside of the character/player and moved them each time they equipped a different weapon?
Post #6 should be in a seperate server script with a seperate remote event. The local script should end up looking like this, modified from post #5:
script.Parent.Buy.MouseButton1Click:Connect(function()
for i, v in pairs(cameras:GetChildren()) do
if camera.CFrame == v.CFrame and not player.Backpack:FindFirstChild(v.Toolname.Value) and not player.Character:FindFirstChild(v.Toolname.Value) then
--Add this if statement, because the remote event already make sure that there is an item in the backpack or character this will do anything bad.
purchase:FireServer(v.Cost.Value, v.Toolname.Value)
elseif camera.CFrame == v.CFrame and player.Backpack:FindFirstChild(v.Toolname.Value) or player.Character:FindFirstChild(v.Toolname.Value) then
if script.Parent.Text ~= "Equipped" then
script.Parent.Text = "Equipped"
script.Parent.BackgroundColor3 = BrickColor.Red().Color
game.ReplicatedStorage.toolEquipper:FireServer(v.Toolname, true) -- Equiptool
else
script.Parent.Text = "Equip"
script.Parent.BackgroundColor3 = BrickColor.Green().Color
game.ReplicatedStorage.toolEquipper:FireServer(v.Toolname, false) -- Unequiptool
end
end
end
end)
this should be all the local script needs, I will still be on if you need more help.
Don’t send the cash client sided, hackers can falsely write data like this and get money:
purchase:FireServer(-93837392778393873, nil)
It would be better if the prices get stored in the server, like in a table. And you could only Fire the sword name, and in the server check if the player have the enough cash to buy it, that’s called “Sanity Checks” Thanks for reading.
That is true, I was aware it was unsecured but for the case of examples I made it very robust and simple. More or less an idea of what happening. Thank you anyways though!
toe_s a better way to do this is fire the camera through the server and check for the Amount via server, I should have done that in the first place.
if you could elaborate on what you mean by this that would be great.
On a side note, I made it so a new folder is created under the player called ownedtools which is where the tools will be stored. I also made it so when you buy the weapons, they immediately go there instead of the player’s backpack. So, I now need to add a way for the player to click the equip button, that appears instead of the buy button after purchasing, so that the tool goes into their backpack. I don’t know where to put it because all of this bouncing back and forth between scripts
–[[
Create a remote event in replicatedstorage named “PurchaseEvent”
]]–
—//Client//— leave this in your normal local script
local player = game.Players.LocalPlayer
local camera = workspace.CurrentCamera
local cash = player.leaderstats.Cash
local purchase = game.ReplicatedStorage:WaitForChild(“PurchaseEvent”)
local cameras = workspace.Cameras
LOCAL SCRIPT
script.Parent.BuyButton.MouseButton1Click:Connect(function()
for i, v in pairs(cameras:GetChildren()) do
if camera.CFrame == v.CFrame and not player.Backpack:FindFirstChild(v.Toolname.Value) and not player.Character:FindFirstChild(v.Toolname.Value) then
–Add this if statement, because the remote event already make sure that there is an item in the backpack or character this will do anything bad.
purchase:FireServer(v.Cost.Value, v.Toolname.Value)
script.Parent.BuyButton.Visible = false
script.Parent.Equip.Visible = true
elseif camera.CFrame == v.CFrame and player.Backpack:FindFirstChild(v.Toolname.Value) or player.Character:FindFirstChild(v.Toolname.Value) then
if script.Parent.Equip.Text ~= “Equipped” then
script.Parent.Equip.Text = “Equipped”
script.Parent.Equip.BackgroundColor3 = BrickColor.Red().Color
game.ReplicatedStorage.toolEquipper:FireServer(v.Toolname, true) – Equiptool
else
script.Parent.Equip.Text = “Equip”
script.Parent.BackgroundColor3 = BrickColor.Green().Color
game.ReplicatedStorage.toolEquipper:FireServer(v.Toolname, false) – Unequiptool
end
end
end
end)
SERVERSCRIPT
local purchase = game.ReplicatedStorage:WaitForChild(“PurchaseEvent”)
purchase.OnServerEvent:connect(function(player, amount, item)
if player.leaderstats.Cash.Value >= amount and not player.Character:FindFirstChild(item) and not player.Backpack:FindFirstChild(item) then
–Checks their cash amount through the server the make sure its >= the amount
–Checks their character and their backpack to make sure its not there
player.leaderstats.Cash.Value = player.leaderstats.Cash.Value - amount
game.ReplicatedStorage:FindFirstChild(item):Clone().Parent = player.ownedtools
end
end)
game.Players.PlayerAdded:Connect(function(player)
local ownedtools = Instance.new(“Folder”, player)
ownedtools.Name = “ownedtools”
end)
I apologize about formatting it is acting glitchy for me…
Hmmm, I can understand how your confused
The only other way I could help explain is if you showed me your scripts individually with of course the code block format so its easier to read.
local player = game.Players.LocalPlayer
local camera = workspace.CurrentCamera
local cash = player.leaderstats.Cash
local purchase = game.ReplicatedStorage:WaitForChild("PurchaseEvent")
local cameras = workspace.Cameras
script.Parent.BuyButton.MouseButton1Click:Connect(function()
for i, v in pairs(cameras:GetChildren()) do
if camera.CFrame == v.CFrame and not player.Backpack:FindFirstChild(v.Toolname.Value) and not player.Character:FindFirstChild(v.Toolname.Value) then
purchase:FireServer(v.Cost.Value, v.Toolname.Value)
script.Parent.BuyButton.Visible = false
script.Parent.Equip.Visible = true
elseif camera.CFrame == v.CFrame and player.Backpack:FindFirstChild(v.Toolname.Value) or player.Character:FindFirstChild(v.Toolname.Value) then
if script.Parent.Equip.Text ~= "Equipped" then
script.Parent.Equip.Text = "Equipped"
script.Parent.Equip.BackgroundColor3 = BrickColor.Red().Color
game.ReplicatedStorage.toolEquipper:FireServer(v.Toolname, true)
else
script.Parent.Equip.Text = "Equip"
script.Parent.BackgroundColor3 = BrickColor.Green().Color
game.ReplicatedStorage.toolEquipper:FireServer(v.Toolname, false)
end
end
end
end)