DGM

Trying to replace local function in included file

Recommended Posts

DGM    13
Posted (edited)

 

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.

Edited by DGM

Share this post


Link to post
Share on other sites
DGM    13

You know what?  Even after fixing the damage the code tags caused that looks terrible.  Let me just attach the lua file: hud_changes.lua

Share this post


Link to post
Share on other sites
Cyberboy2000    367
Posted (edited)

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.

Edited by Cyberboy2000

Share this post


Link to post
Share on other sites
DGM    13

>> " 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.

Share this post


Link to post
Share on other sites
Cyberboy2000    367
Posted (edited)

You haven't defined pcPlayer. Therefore 

if pcPlayer then

always fails. You need this code:

local pcPlayer = self._game.simCore:getPC()

 

Edited by Cyberboy2000

Share this post


Link to post
Share on other sites
DGM    13

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

 

Share this post


Link to post
Share on other sites
Strelock    10
Posted (edited)

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

Edited by Strelock

Share this post


Link to post
Share on other sites
DGM    13

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

 

Share this post


Link to post
Share on other sites
DGM    13

>> "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?

Share this post


Link to post
Share on other sites
Cyberboy2000    367
Posted (edited)

What exactly is it you are trying to do? You can do just about anything with enough effort, Sim Constructor is just something I made so that others can take little shortcuts.

Edited by Cyberboy2000

Share this post


Link to post
Share on other sites
DGM    13

Nothing else with interfaces, for the moment.  But I'm sure I'll want to eventually and I was wondering if Sim Constructor could make it easier next time.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now