I’m a little confused as to why my local script isn’t working on this issue… is there something I’m missing here?
local button = script.Parent
button.MouseButton1Down:Connect(function()
local surfaceGUI = script.Parent.Parent
local doorPart = script.Parent.Parent.Parent
local playerName = game.Players.LocalPlayer.Name
local moneyName = tostring(playerName.."Money")
local moneyValue = game.ReplicatedStorage.PlayerMoney.moneyName.Value
local Cost = script.Parent.Parent.Cost.Value
local MVMC = moneyValue-Cost
print "a"
if not MVMC <= -1 then
print("b")
doorPart.Transparency = 1
doorPart.CanCollide = false
surfaceGUI.Active = false
moneyValue = MVMC
end
end)
Here’s how everything is positioned in the library if it’s any help… The “Cost” IntVal is at 50 right now and the starting money (another IntVal is at 100)
Sorry I’m still rather new to scripting. If there’s any other info you need, please just ask
Doing tostring(playerName .. "Money") is redundant since concatenating strings returns a string.
When you set the moneyValue variable, you need to do PlayerMoney[moneyName].Value since moneyName is a string. If you leave it as you did now, it would essentially be like PlayerMoney."moneyValue".Value which isn’t the correct syntax.
Do not have transactions occur in a Local Script, exploiters can and will change up the code inside of it whenever they are able to. They can unfairly gain access to the door. Therefore, set up a RemoteEvent that fires from the client to the server and the server does the transaction in a Server Script. If the player has enough money, then using the PhysicsServerice, we will set the door and the player’s character uncollidable.
--local script
local remoteEvent = game:GetService("ReplicatedStorage"):WaitForChild("RemoteEvent")
button.MouseButton1Down:Connect(function()
remoteEvent:FireServer()
end)
--server script
local rs = game:GetService("ReplicatedStorage")
local remoteEvent = rs:WaitForChild("RemoteEvent")
local ps = game:GetService("PhysicsService")
local door = workspace:WaitForChild("Doors").Door
ps:CreateCollisionGroup("Door")
ps:SetPartCollisionGroup(door, "Door")
remoteEvent.OnServerEvent:Connect(function(player) --the player parameter is automatically passed from the requesting client
local playerMoney = rs:WaitForChild("PlayerMoney")
local money = playerMoney[player.Name .. "Money"]
local cost = door.SurfaceGui.Cost
if money.Value >= cost.Value then
local char = player.Character or player.CharacterAdded:Wait()
ps:CreateCollisionGroup(player.Name)
--player has enough money!
for i, v in pairs(char:GetChildren()) do
if v:IsA("BasePart") then --any type of body part
ps:SetPartCollisionGroup(v, player.Name)
end
end
ps:CollisionGroupSetCollidable("Door", player.Name, false)
end
end)
I apologize for completely changing your script, but this is the more secure and efficient option. If you have any questions, feel free to DM me!
-- Its best to have all variables at the top of the script for readability
local button = script.Parent
local surfaceGUI = script.Parent.Parent
local doorPart = script.Parent.Parent.Parent
local player = game.Players.LocalPlayer -- its better to have the Player, not the name
local Cost = script.Parent.Parent.Cost.Value
button.MouseButton1Down:Connect(function()
-- check if player has enough money to purchase
if player.leaderstats.Money.Value - Cost >= 0 then
doorPart.Transparency = 1
doorPart.CanCollide = false
surfaceGUI.Active = false
-- player pays for the door
player.leaderstats.Money.Value = player.leaderstats.Money.Value - Cost
end
end)
I changed the way you’re managing the player’s money to use leaderstats because its much easier to use, and will show the player’s money with the default player list. To use leaderstats, put the following code into a Script in ServerScriptStorage
game.Players.PlayerAdded:Connect(function(player)
-- this will add a leaderstats value to the player
local leaderstats = Instance.new("Folder", player)
leaderstats.Name = "leaderstats"
local cash = Instance.new("IntValue", leaderstats)
cash.Name = "Money"
end)
With this, you can also save the player’s money between session using DataStores. I would personally recommend DataStores2 for this.
Just to add on @TheCarbyneUniverse’s suggestion on security, you may want to implement some position checks on the server just in case an exploiter teleports past the door or deletes the door locally.