Trying to replace local function in included file


Recommended Posts

 

I've been away from Lua for a while, so forgive me if I've forgotten something basic.

I'm trying to overwrite the refreshHudValues function in client/hud.lua to display power out to the first decimal place.  I grabbed a mod I was working on before and added a file named hud_changes.lua with the following code:

 

==================================================

local hud = include( "client/hud" )

function hud.refreshHudValues( self )
    local pcPlayer = self._game.simCore:getPC()
    if pcPlayer then
        self._screen.binder.resourcePnl.binder.cpuNum:setText(util.sformat( STRINGS.FORMATS.PWR ,string.format("%.1f/%.1f", pcPlayer:getCpus(), pcPlayer:getMaxCpus() )))    
        self._screen.binder.resourcePnl.binder.credits:setText( util.sformat(STRINGS.FORMATS.CREDITS,tostring(pcPlayer:getCredits()) ) )
    else
        self._screen.binder.resourcePnl.binder.cpuNum:setText("-")
        self._screen.binder.resourcePnl.binder.credits:setText("???")
    end
end

==================================================

 

I've tried variations on this but nothing works.  I know the mod as a whole is working because other changes made by it work.  And I know my tweak to refreshHudValues works because I tested it in the game's base code.  But I can't seem to change it from a mod.  What am I doing wrong?

 

EDIT: Holy Hell, do NOT try to use code tags in this forum.

Link to comment
Share on other sites

Replacing anything in hud.lua is a bit tricky, it used to take me a while to do it. Normally, when you want to replace something that is local, you have to replace anything that uses that local something. So in this case you have to change hud:refreshHud() and hud:onSimEvent( ev ) since those are the functions that call refreshHudValues.

Those are quite big functions, so it's best to add the code at the end since your replaced function should override the old one. That is also better for compability with other mods. Like this:

--local hud = include( "client/hud" )
local hud = include( "hud/hud" )

local oldRefreshHud = hud.refreshHud
local oldOnSimEvent = hud.onSimEvent

function hud:refreshHud()
	oldRefreshHud( self )
	customRefreshHudValues( self )
end

function hud:onSimEvent( ev )
	oldOnSimEvent( self, ev )
	if ev.eventType == simdefs.EV_CREDITS_REFRESH then
		customRefreshHudValues( self )
	end
end

That's what you would normally do when replacing a local function. However, hud.lua is special. It is deceiving because it's layout is similar to many other files in this game, until you look at the bottom of the file.

local function createHud( ... )
    return hud( ... )
end

return
{
	createHud = createHud
}

This is the troublemaker. We don't actually have direct access to hud, only the function that creates hud. I have no idea why they decided to do this. It isn't any simpler to write hud.createHud() rather than hud() and in no other game file is this done, but it's there, and here's how to circumvent it:

--local hud = include( "client/hud" )
local hud = include( "hud/hud" )
local oldCreateHud = hud.createHud

hud.createHud = function( ... )
    local hudObject = oldCreateHud( ... )

    local oldRefreshHud = hudObject.refreshHud
    local oldOnSimEvent = hudObject.onSimEvent

    function hudObject:refreshHud()
        oldRefreshHud( self )
        customRefreshHudValues( self )
    end

    function hudObject:onSimEvent( ev )
        oldOnSimEvent( self, ev )
        if ev.eventType == simdefs.EV_CREDITS_REFRESH then
            customRefreshHudValues( self )
        end
    end

    return hudObject
end

I prefer helping people write their own code over writing the code for them, but I know it took me a while for me to figure this out so I leave it here in the hope that it helps anyone who needs to change anything in hud.lua in the future. Cheers!

Edit: What is so troublesome with code tags? Just use the gui to insert tags if it doesn't work for you.

Link to comment
Share on other sites

>> " What is so troublesome with code tags? "

The spacing in the code block messed up, and when I went to fix I couldn't seem to edit the block's contents.  It had also deleted the part of my post that came after it.  I spent a couple of minutes trying to fix the message before anyone read it.

It might have been my fault, though.  I used square brackets for the tags when, looking at the GUI, it seems it might have wanted greater/less than signs.  I'll try this again through the GUI and hopefully the later parts of my post won't get nuked again.

Anyway, I appreciate the help but something's still wrong.  This is the part of refreshHudValues that I need to run again:

 

if pcPlayer then
	self._screen.binder.resourcePnl.binder.cpuNum:setText(util.sformat( STRINGS.FORMATS.PWR ,string.format("%.1f/%.1f", pcPlayer:getCpus(), pcPlayer:getMaxCpus() )))
end

 

...So I inserted it into your code where you indicated, like so:

 


local hud = include( "client/hud" )
local oldCreateHud = hud.createHud

hud.createHud = function( ... )
	local hudObject = oldCreateHud( ... )

	local oldRefreshHud = hudObject.refreshHud
    local oldOnSimEvent = hudObject.onSimEvent

    function hudObject:refreshHud()
        oldRefreshHud( self )
		if pcPlayer then
			self._screen.binder.resourcePnl.binder.cpuNum:setText(util.sformat( STRINGS.FORMATS.PWR ,string.format("%.1f/%.1f", pcPlayer:getCpus(), pcPlayer:getMaxCpus() )))
		end
    end

    function hudObject:onSimEvent( ev )
        oldOnSimEvent( self, ev )
        if ev.eventType == simdefs.EV_CREDITS_REFRESH then
			if pcPlayer then
				self._screen.binder.resourcePnl.binder.cpuNum:setText(util.sformat( STRINGS.FORMATS.PWR ,string.format("%.1f/%.1f", pcPlayer:getCpus(), pcPlayer:getMaxCpus() )))
			end
        end
    end
end

 

..But the PWR display still isn't showing the decimal portion.

Link to comment
Share on other sites

Right, I forgot I had to redeclare that locally.

But that wasn't the only problem, as it's still not working.  Here's the code as it stands now:

 

local hud = include( "client/hud" )
local oldCreateHud = hud.createHud

hud.createHud = function( ... )
	local hudObject = oldCreateHud( ... )

	local oldRefreshHud = hudObject.refreshHud
    local oldOnSimEvent = hudObject.onSimEvent

    function hudObject:refreshHud()
        oldRefreshHud( self )
        local pcPlayer = self._game.simCore:getPC()
		if pcPlayer then
			self._screen.binder.resourcePnl.binder.cpuNum:setText(util.sformat( STRINGS.FORMATS.PWR ,string.format("%.1f/%.1f", pcPlayer:getCpus(), pcPlayer:getMaxCpus() )))
		end
    end

    function hudObject:onSimEvent( ev )
        oldOnSimEvent( self, ev )
        if ev.eventType == simdefs.EV_CREDITS_REFRESH then
        	local pcPlayer = self._game.simCore:getPC()
			if pcPlayer then
				self._screen.binder.resourcePnl.binder.cpuNum:setText(util.sformat( STRINGS.FORMATS.PWR ,string.format("%.1f/%.1f", pcPlayer:getCpus(), pcPlayer:getMaxCpus() )))
			end
        end
    end
end

 

Link to comment
Share on other sites

Wrong include. Use 

include( "hud/hud" )

Also you didn't import util

local util = include( "client_util" )

 

To debug your problems you can check log file located at "C:\Users\<username>\Documents\Klei\InvisibleInc\logs\invisibleinc.txt"

log:write("Hello World!") will wring to this file

Link to comment
Share on other sites

Okay, you know how I said I threw the new hud_changes script into an old mod?  And how I've been away from this for months and might have forgotten something basic?  Yeah, turns out I forgot to add hud_changes to modinit.lua!

Sigh.

That said, now that the new script is actually being loaded I'm still having problems.  The previous version was causing a crash on launch.  Including "hud/hud" and "client_util" instead lets the game work up until I start a mission, but as soon as I try to beam in I crash to desktop.  Here's what kills the game according to the log:

 

Jul 22 07:22:56 -- ### ABORTING: FATAL SCRIPT ERROR ###
game/client/states/state-game.lua:880: attempt to index field 'hud' (a nil value)

stack traceback:
	[C] in function 'traceback'
	game/client/state-manager.lua:31 in function <game/client/state-manager.lua:30>
	game/client/states/state-game.lua:880 in function 'updateSound'
	game/client/states/state-game.lua:925 in function 'onUpdate'
	game/client/states/state-campaigngame.lua:93 in function 'onUpdate'
	game/client/state-manager.lua:40 in function <game/client/state-manager.lua:35>
	[C] in function 'xpcall'
	game/client/state-manager.lua:69 in function <game/client/state-manager.lua:62>

 

Here are the relevant files:

invisibleinc.txt

hud_changes.lua

modinit.lua

 

Link to comment
Share on other sites

>> "return hudObject"

And that just about did it.  The game was griping because I also needed to include simdefs, but that was easy to catch and fix.  And now it's working.  Many thanks, both of you.

Cyberboy, I notice that the Sim Constructor mod can change the interface.  Does that only apply to graphical elements, or can it handle text elements like the power and credit readouts?

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.