Replacing a function

Everything about mods can be found here.

Moderator: Morax

Replacing a function

Postby armacham01 » 20 Jan 2020, 04:36

How would I go about changing a particular function in a lua file, for a Sim mod?

I've made a mod that changes a blueprint by adding to it/overwriting part of it, without overwriting the entire file. but I'm curious what the code looks like for overwriting a single function. OR, can I not do that?

Can I replace just one function from units.lua or would I need to overwrite the entire "units.lua" file?

I would prefer to overwrite just a single function, if that is possible. It would make my mod probably easier to maintain going forward. Unless you think there is an advantage to overwriting the entire file.

Also, if you could point me to an example of a mod that does this, I could download that and look at it.

Thanks.
armacham01
Avatar-of-War
 
Posts: 232
Joined: 09 Feb 2019, 09:01
Has liked: 54 times
Been liked: 109 times
FAF User Name: arma473

Re: Replacing a function

Postby Uveso » 20 Jan 2020, 07:13

Hello armacham01,

here is a simple example how to hook a function inside a defined class:
https://github.com/Uveso/AI-Uveso/blob/ ... anager.lua

First you need to make a copy of the original class and save it. I use the name "TheOldEngineerManager" for the copy of the original class.
Code: Select all
TheOldEngineerManager = EngineerManager


Then you need to create a new cass and use the orginal class as base.
Because i use the original name "EngineerManager", i will overwrite the original class.
The original class is still present inside "TheOldEngineerManage", so i use this as base for the new one.
Code: Select all
EngineerManager = Class(TheOldEngineerManager)


Now you can overwrite a function inside the "EngineerManager" class
In this case the function is called "LowMass"
Code: Select all
    LowMass = function(self)
        -- Only use this with AI-Uveso
        if not self.Brain.Uveso then
            return TheOldEngineerManager.LowMass(self)
        end
    end,


This function checks if AI-Uveso is active and in case its not, the original function LowMass will be called.
Remember we stored the original class inside "TheOldEngineerManager", so we can call
the original LowMass function like this:
Code: Select all
TheOldEngineerManager.LowMass(self)


I hope this helps a bit.
User avatar
Uveso
Supreme Commander
 
Posts: 1788
Joined: 11 Dec 2015, 20:56
Location: Germany
Has liked: 70 times
Been liked: 291 times
FAF User Name: Uveso

Re: Replacing a function

Postby armacham01 » 20 Jan 2020, 13:00

Thank you. With your advice, I think it is working now.
armacham01
Avatar-of-War
 
Posts: 232
Joined: 09 Feb 2019, 09:01
Has liked: 54 times
Been liked: 109 times
FAF User Name: arma473

Re: Replacing a function

Postby Uveso » 20 Jan 2020, 18:54

You are welcome.
User avatar
Uveso
Supreme Commander
 
Posts: 1788
Joined: 11 Dec 2015, 20:56
Location: Germany
Has liked: 70 times
Been liked: 291 times
FAF User Name: Uveso

Re: Replacing a function

Postby BlackYps » 20 Jan 2020, 22:14

This seems to work only if the hooked funktion is not defined in the same class.
I want to get rid of the additions that the StructureUnit class makes to OnDestroy

When using your method and writing
Code: Select all
local oldStructureUnit = StructureUnit
StructureUnit = Class(oldStructureUnit) {
   OnDestroy = function(self)
      Unit.OnDestroy(self)
   end,
}

I get the error:
Code: Select all
field 'OnDestroy' is ambiguous in class definition

It seems that it doesn't overwrite the new one with the old one but uses both and then the game is confused abot which one to take.
What am I doing wrong?
BlackYps
Avatar-of-War
 
Posts: 74
Joined: 15 Feb 2019, 19:46
Has liked: 7 times
Been liked: 31 times

Re: Replacing a function

Postby Uveso » 20 Jan 2020, 23:12

Code: Select all
local oldStructureUnit = StructureUnit
StructureUnit = Class(oldStructureUnit) {
   OnDestroy = function(self)
      Unit.OnDestroy(self)
   end,
}


Looks good so far; you copied the original function to "oldStructureUnit".
But now you try to access "oldStructureUnit" only with "unit" to get the OnDestroy function.
You need to use the copy of the original:
Code: Select all
oldStructureUnit.OnDestroy(self)


so the function should look like this:
Code: Select all
local oldStructureUnit = StructureUnit
StructureUnit = Class(oldStructureUnit) {
   OnDestroy = function(self)
      oldStructureUnit.OnDestroy(self)
   end,
}
Last edited by Uveso on 20 Jan 2020, 23:42, edited 1 time in total.
User avatar
Uveso
Supreme Commander
 
Posts: 1788
Joined: 11 Dec 2015, 20:56
Location: Germany
Has liked: 70 times
Been liked: 291 times
FAF User Name: Uveso

Re: Replacing a function

Postby Uveso » 20 Jan 2020, 23:41

Well i checked hooking the OnDestroy StructureUnit class and its working.
Just to be sure;
create a file named:
Code: Select all
\Mods\YOURMODNAME\hook\lua\defaultunits.lua

and put this into the empty file:
Code: Select all
local OLDStructureUnit = StructureUnit
StructureUnit = Class(OLDStructureUnit) {
    OnDestroy = function(self)
        LOG('***---*** StructureUnit OnDestroy HOOK')
        Unit.OnDestroy(self)
        local orient = self.TarmacBag.Orientation
        local currentBP = self.TarmacBag.CurrentBP
        self:DestroyTarmac()
        self:CreateTarmac(true, true, true, orient, currentBP, currentBP.DeathLifetime or 300)
    end,
}


Does this work on your side ?
User avatar
Uveso
Supreme Commander
 
Posts: 1788
Joined: 11 Dec 2015, 20:56
Location: Germany
Has liked: 70 times
Been liked: 291 times
FAF User Name: Uveso

Re: Replacing a function

Postby BlackYps » 21 Jan 2020, 00:07

Yes, it works!

There must be a reason why it doesn't work in the other mod...
I will try to find it. But I don't really have an idea what the reason could be.
BlackYps
Avatar-of-War
 
Posts: 74
Joined: 15 Feb 2019, 19:46
Has liked: 7 times
Been liked: 31 times

Re: Replacing a function

Postby Uveso » 21 Jan 2020, 00:08

In case you got stucked there, upload the mod and i will take a look if you want.
User avatar
Uveso
Supreme Commander
 
Posts: 1788
Joined: 11 Dec 2015, 20:56
Location: Germany
Has liked: 70 times
Been liked: 291 times
FAF User Name: Uveso

Re: Replacing a function

Postby BlackYps » 21 Jan 2020, 00:27

I found the root of the problem:
Hooking the structureunit class works well. The problem occurs when I try to propagate the change down to the subclasses.

Apparently this is not the way to go:
Code: Select all
local oldFactoryUnit = FactoryUnit
FactoryUnit = Class(StructureUnit, oldFactoryUnit) {}
BlackYps
Avatar-of-War
 
Posts: 74
Joined: 15 Feb 2019, 19:46
Has liked: 7 times
Been liked: 31 times

Next

Return to Mods & Tools

Who is online

Users browsing this forum: No registered users and 1 guest