Cant get LocalPlayer from a server script

I am making a tool shop gui and I have used a remote event to fire the clone but I cant get the local player to change the amount of money the player, and I cant put the clone in the players backpack. Any help would be appreciated :slight_smile:

This is my code

local shiv = game.Players.LocalPlayer.Cash.Pounds.Value >= 30

if shiv then
		local clonedShiv = game.ReplicatedStorage.Shiv:Clone()
		clonedShiv.Parent = game.Players.LocalPlayer.Backpack
		game.Players.LocalPlayer.Cash.Pounds.Value -=30
end

end)```

Hello!

Local Players are only for local scripts, with this script specifically you would need to do a Remote Event For example:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")

remoteEvent.OnServerEvent:Connect(function(player)
	local shiv = player.Cash.Pounds.Value >= 30
	
	if shiv then 
		local clonedShiv = game.ReplicatedStorage.Shiv:Clone()
		clonedShiv.Parent = player.Backpack
		player.Cash.Pounds.Value -= 30
	end
end)

i tried it but when i press my purchase gui it dosent do anything, no errors either

You would need to fire the remote event to the server!

yeah i fired it when gui is clicked with a local script script.Parent.Activated:Connect(function() game.ReplicatedStorage.CloneTool:FireServer() end)

It would be

script.Parent.MouseButton1Click:Connect(function() 
game.ReplicatedStorage.CloneTool:FireServer() 
end)

it still dosent work idk why like nothing is happening no errrors, nothing

Perhaps printing the code that I have provided

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChild("RemoteEvent")

remoteEvent.OnServerEvent:Connect(function(player)
	local shiv = player.Cash.Pounds.Value >= 30

	if shiv then 
		local clonedShiv = game.ReplicatedStorage.Shiv:Clone()
		clonedShiv.Parent = player.Backpack
		player.Cash.Pounds.Value -= 30
		print("Purchased")
		
	elseif  player.Cash.Pounds.Value <= 30 then
		print("You have no pounds to spend")
	
	else
		print("There isn't a stat called that")
	end
end)


im getting the you have no pounds to spend message so i assume there is something wrong with the arithmetical operators

I am glad to help you figure out your issue!

That means you just need to give yourself some pounds to try it out :smiley:

i earned some pounds in game and i had over 30 and nothing happened when i tried buying

Did anything pop up on the prints

it came up with the “no pounds to spend” message even when i had enough

Did you give pounds locally or server sided?

The client shouldn’t handle purchases because that is vulnerable to exploiters. Instead it should request the server to check if the client has enough money, and complete the purchase.

In other posts you’ve stated that this doesn’t work, but that doesn’t mean that the client should suddenly get control.

Here’s my take:

--client
local remote = --your remote
remote:FireServer("nameofitemyouwanttobuy")
--server
local replicated_storage = game:GetService "ReplicatedStorage"
local remote = --your remote

--maybe to get the cost add like a table of strings/prices.

remote.OnServerEvent:Connect(function(plr: Player, tool_name: string)
   if typeof(tool_name) ~= "string" then return end
   local tool =  replicated_storage:FindFirstChild(tool_name)--or your folder where you store the tools, you should probably put these in server storage.

  if not tool then return end
  local pounds = plr.Cash.Pounds

  if pounds.Value < --here add the cost 
  then return end

  pounds.Value -= --your cost
  tool:Clone().Parent = plr.BackPack
end)

Hope this helps.

i think any normal dev would js copy this and paste in into their game but i wanna actually learn but im afraid i dont understand this

What do you not understand? The code ? Or the part where exploiters can access anything on the client and therefore purchases should be validated by the server?

I’ll explain the code,

local remote = --your remote
--these are your dependencies of the client script,
--you're supposed to put a reference to a Remote Event here,
--eg: local remote = game.ReplicatedStorage.PurchaseRemote
--this is the call that will trigger validation on the server for the purchase, of the tool with the given name.
remote:FireServer "nameofitemyouwanttobuy"
--this is supposed to go inside of a button handler, eg:

--yourtoolbuybutton.Activated:Connect(function()
--remote:FireServer "yourtoolname"
--end

Now we go to the other side of the network, the server:

--These are the dependencies of the server, a reference to replicated storage, 
--and a reference to your remote, refer to the client script as to what should go there.
local replicated_storage = game:GetService "ReplicatedStorage"
local remote = --your remote
--this is the function that will handle the incoming request from the client
--it accepts a parameter called 'plr', expected to be of type 'Player' as shown by the type annotation.
--it also accepts a parameter called 'tool_name', expected to be of type 'string', again, the type annotation shows this.
remote.OnServerEvent:Connect(function(plr: Player, tool_name: string)
--this is a type check, to secure this remote from exploiters that pass objects of invalid type to remotes to error the server, 
--and have it possibly do complex computations to slow it down.
--it checks if the data provided by the client is of the expected type.
    if typeof(tool_name) ~= "string" then return end
--if it isn't, the request is not handled.
--the player argument doesn't need to be checked, because it is provided by Roblox, not the client.

--this fetches an instance from replicated storage, with the provided name. 
--This is because from your code, it seems like your tool is stored there.
--if not, replace with the actual location of your tool
    local tool = replicated_storage:FindFirstChild(tool_name)
--it then assigns the result to the variable called 'tool'

--it proceeds to check if the tool exists, and returns early if it doesn't
if not tool then return end

--it gets the pound NumberValue from the player, from your previous code, that seems to be how you handle money.
local pounds = plr.Cash.Pounds--we can assume this always exists, so no check
--it is assigned to 'pounds'

--this checks if the player has enough money to complete the purchase.
--if they don't, the function returns early.
    if pounds.Value <  then return end
--replace the empty space with your price, you might put those in an array like so:
--[[
local prices = {
      ["Shiv"] = 30
}
]]
--and then retrieve the price like so
--if pounds.Value < prices[tool_name] then return end

--if we haven't returned at this point, we know the player has enough money, and the tool exists.
--so we subtract the price of the player's current pounds using -= which is minus equals or short for x = x - y
--replace the empty space with your actual price,
   pounds.Value -= 
--you might retrieve it like so:
--pounds.Value -= prices[tool_name]
--finally, it clones the tool we previously found and assigned to 'tool', and it puts it in the player's backpack.
    tool:Clone().Parent = plr.BackPack
--the purchase has been completed.
end)

hope this helps!