1. Post #1
    Gold Member
    I Fail At Lua's Avatar
    December 2009
    716 Posts
    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.

    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 );
    

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

    Heres my Init.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
    

    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!

  2. Post #2
    shadowndacorner's Avatar
    May 2011
    195 Posts
    You have to define SetSalary before you call it.

    Post your whole init.lua, or at least up until the PlayerLoadout hook.
    Reply With Quote Edit / Delete Reply Windows 7 United States Show Events Winner Winner x 1 (list)

  3. Post #3
    Derek_SM's Avatar
    January 2011
    330 Posts
    First off your first function,
    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
    

    Is redundant, and instead can be called like this

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

    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
    local SteamIDFormat = self:SteamIDFormat()
    
    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:
    function ply_meta:GetMoney()
     
    	-- Return money using GetNWInt instead so you may use it in HUD's or menus.
        return self:GetNWInt( money )
     
    end
    

    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:
    
    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\n" )   
        end
    end
    

    Changed your mind? Great:
    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
    



    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

    timer.Create( "PayDayBitches_"..ply:UserID(), time, 0, function()
    

    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:
    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)
    

    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.


    You have to define SetSalary before you call it.

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




    Edit:

    And merry Christmas to you as well!
    Reply With Quote Edit / Delete Reply Windows 7 United States Show Events Friendly Friendly x 1Informative Informative x 1 (list)

  4. Post #4
    Gold Member
    I Fail At Lua's Avatar
    December 2009
    716 Posts
    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!

  5. Post #5
    L33T Lau Coder
    Science's Avatar
    April 2011
    1,813 Posts
    If you want some help with lua add me on steam: modegg

    Im in a good mood.

  6. Post #6
    Derek_SM's Avatar
    January 2011
    330 Posts
    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!
    In case it wasn't clear, you can still use the SetPData and GetPData, but it's kind of redundant to do so.