Money System Help

I’ve been looking at some tutorials and I decided to try and make my own money system where it would save how much the player has to a text file. But the problem is I can’t get salary’s to work.

[lua]
local ply_meta = FindMetaTable( “Player” );
local money = “PlayerMoney”;

function ply_meta:SteamIDFormat( )

format1 = string.gsub( self:SteamID(), "STEAM", "" ) -- replaces STEAM with nothing
format2 = string.gsub( format1, ":", "" ) -- replaces _ with nothing
format3 = string.gsub( format2, "_", "" )
return format3;

end

function ply_meta:SetMoney( amount )
self:SetPData( money, amount ) – set the players money to amount
self:SetNWInt( money, amount )
end

function ply_meta:AddMoney( amount )

self:SetPData( money, self:GetPData( money ) + amount ) -- Get the players money then add the amount
self:SetNWInt( money, self:GetPData( money ) ) 

end

function ply_meta:SubtractMoney( amount )

self:SetPData( money, self:GetPData( money ) - amount ) 
self:SetNWInt( money, self:GetPData( money ) ) 

end

function ply_meta:GetMoney( amount )

self:GetPData( money ) -- get the players money

end

function ply_meta:HasMoney( amount )

if self:GetPData( money ) >= amount then
	self:SubtractMoney( amount )
else print( "You don't have enough money" )
	
end

end

function ply_meta:SaveMoney( )

file.Write("Money_system_test/".. SteamIDFormat .. ".txt", self:GetMoney() )

end

local function InitialPlayerSpawn( ply )

if file.Exists("money_system_test/" .. SteamIDFormat .. ".txt") then 
	ply:SetPData( money, file.Read("money_system_test/" .. self:SteamIDFormat .. ".txt") )
	
else
	file.Write("Money_system_test/" .. SteamIDFormat .. ".txt", 500)
end

end
hook.Add(“PlayerInitialSpawn”, “MoneyFiles”, InitialPlayerSpawn )

function ply_meta:SetSalary( time, amount)

timer.Create( "PayDayBitches", time, 0, function()
	self:AddMoney( amount )
	self:ChatPrint( "You have received a Paycheck! You now have " .. self:GetMoney( ) );
end)

end

timer.Create( “MoneySave”, 60, 0, function( )
for k, v in pairs( player.GetAll( ) ) do
v:SaveMoney( );
end;
end );
[/lua]

I get this error when i start the gamemode:
gamemodes estgamemode\gamemode\init.lua:41] attempt to call method ‘SetSalary’ (a nil value)(Hook: PlayerLoadout)

Heres my Init.lua
[lua]
function GM:PlayerLoadout( ply )

if ply:Team() == 1 then

	ply:Give( "weapon_physcannon" )
	ply:Give( "weapon_physgun" )
	ply:Give( "gmod_tool" )
	ply:SetSalary( 10, 50) -- Line 41


elseif ply:Team() == 2 then

	ply:Give("weapon_physcannon")
	ply:Give("weapon_physgun")
	ply:Give("gmod_tool")


elseif ply:Team() == 3 then

	ply:Give("weapon_physcannon")
	ply:Give("weapon_physgun")
	ply:Give("gmod_tool")

	
end

end
[/lua]

Any help would be appreciated, I’ve been trying to get this to work for a while now and I don’t know what to do. Also, Merry Christmass!

You have to define SetSalary before you call it.

Post your whole init.lua, or at least up until the PlayerLoadout hook.

First off your first function,
[lua]
function ply_meta:SteamIDFormat( )

format1 = string.gsub( self:SteamID(), "STEAM", "" ) -- replaces STEAM with nothing
format2 = string.gsub( format1, ":", "" ) -- replaces _ with nothing
format3 = string.gsub( format2, "_", "" )
return format3;

end
[/lua]

Is redundant, and instead can be called like this

[lua]
function ply_meta:SteamIDFormat()

return string.gsub( self:SteamID(), ":", "_") -- Replaces psteamid colons (:) with underlines (_)

end
[/lua]

Now you can save to files (Not that I’d recommend doing that, but whatever), and it’s easier on the eyes to read.

Also, your saving and reading will not work, you should be doing
self:SteamIDFormat() instead of SteamIDFormat since it’s a function and not a variable.

A quick fix instead of redoing all that will be putting
[lua]
local SteamIDFormat = self:SteamIDFormat()
[/lua]
at the top of the file underneath the money variable.

That should fix the erroring but in case you haven’t noticed your GetMoney function will only work serverside.

Get rid of the function arguments in ply_meta:GetMoney()
Also replace GetPData() with GetNWInt() because GetPData() is only allowed to be called through the server. NW isn’t. However the SetNW’s and GetNW’s can be expensive. They should only be called when you need to give it to all players. Don’t get overexcited about NW’s, spamming them everywhere for a shortcut. Your FPS will pay for that.

Now, the function should now look something like this now:
[lua]
function ply_meta:GetMoney()

-- Return money using GetNWInt instead so you may use it in HUD's or menus.
return self:GetNWInt( money )

end
[/lua]

There shouldn’t be an error in ply_meta:HasMoney(), but usually coders will not put an error like “You do not have enough money” in a meta function, and save it for a function that actually calls it and stuff, because you do not know 100% what you will use HasMoney() for.
Not only that, but since you are making a money system serverside you would be printing “You do not have enough money” to the server console, and not the player himself.

If you decide to keep the ply_meta:HasMoney( amount ) then at least do something like this:
[lua]

function ply_meta:HasMoney( amount )

if self:GetPData( money ) >= amount then
	-- *sigh*
    self:SubtractMoney( amount )
else 
	-- *sigh*
	self:PrintMessage(HUD_PRINTCONSOLE, "You don't have enough money

" )
end
end
[/lua]

Changed your mind? Great:
[lua]
function ply_meta:HasMoney( amount )

if self:GetPData( money ) >= amount then
	-- Don't take their money!
	-- You do NOT know what you're going to use this for 100%
	-- Return true to say that the player has the money needed.
    return true
else
	-- Return false: Player doesn't have the money needed :(
	return false
end

end
[/lua]

Couple more things:

Your InitialPlayerSpawn( ply ) function, good, it’s local and it should be unless you plan on calling it somewhere else? (You won’t)
If you plan on making a HUD or menu, switch that
ply:SetPData( money, file.Read(“money_system_test/” … SteamIDFormat … “.txt”) )
with
ply:SetNWInt( money, file.Read(“money_system_test/” … SteamIDFormat … “.txt”) )

A big thing too:
When you are creating a timer, the timer is being set for everyone, so if a new player comes the player that was about to get a payday gets the timer reset, or something like that will happen.

Change it to

[lua]
timer.Create( “PayDayBitches_”…ply:UserID(), time, 0, function()
[/lua]

Now the saving timer, how often do you plan on setting players payday timer?
If it’s plan is 60 seconds I would still make it save like every 30 seconds. ( You never now if someone will trade money or spend something or etc)

ALSO 2 more things

1.) I recommend that you add a playerdisconnect save money hook. Something like this:
[lua]
local function PlayerDisconnect_SaveMoney( pl )
– Save the players money when they leave
pl:SaveMoney()
end
– Hook so that the above function works. Yes.
hook.Add(“PlayerDisconnected”, “SaveMoney_PlayerDisconnected”, PlayerDisconnect_SaveMoney)
[/lua]

One last thing, SetPData and GetPData are retrieving from a local SQLite database, and you are using them to save to text files

Whatever, do what you want.

Not necessarily.

Edit:

And merry Christmas to you as well!

Thank you very much, I really appreciate this, it was very informative! I thought I did some things wrong but I wasn’t sure. Thanks again man and Merry Christmas!

If you want some help with lua add me on steam: modegg

Im in a good mood.

In case it wasn’t clear, you can still use the SetPData and GetPData, but it’s kind of redundant to do so.