Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Override Lua instance function

I’m trying to change the behavior of a Lua function, by adding code to the start or end of it. Because this is a mod for a game, I can’t edit the function directly, so I have to override it instead. I accomplish this by storing a reference to the original function in a local variable, then redefining the function with my own, which calls the original one along with any prefix or postfix code I need to add, like so:

local base_exampleFunction = ExampleBaseGameClass.exampleFunction

function ExampleBaseGameClass.exampleFunction(param1, param2)

    --Prefix code goes here

    base_exampleFunction(param1, param2);

    --Postfix code goes here
    
end

This works fine for functions defined with the ClassName.functionName syntax, but some functions use ClassName:functionName instead, which from what I understand, are functions that pass a reference to the class instance as the first parameter. I can’t figure out how to prefix/postfix these functions, as I get the following error when declaring a variable to hold the original function if I try the same approach:

attempted index: exampleFunction of non-table: null

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Is there a way to make this work?

>Solution :

: functions are just scary ways of saying "the first argument is self".

So, ExampleBaseGameClass:exampleFunction(param2) is equivelent to ExampleBaseGameClass:exampleFunction(ExampleBaseGameClass, param2)! It’s just got self at the beginning, and functions declared with : will have an invisible self variable appear out of nowhere.

local a = {}
function a.b(self)
    print(self)
end
function a:c()
    print(self)
end

-- a.c(a) == a:c()
-- a:b() == a.b(a)
-- a:b() == a:c()

Using this idea, we can simply prepend an argument (it does not have to be called "self", it just has to be the first argument).

This should work, unless there is a part of your Lua environment (eg, funky metatables) which would prevent such a thing:

local base_exampleFunction = ExampleBaseGameClass.exampleFunction

function ExampleBaseGameClass.exampleFunction(self, param1, param2)

    --Prefix code goes here

    base_exampleFunction(self, param1, param2);

    --Postfix code goes here
    
end

The lua library takes advantage of the first argument being the calling object for it’s string library. Notice how ("hello"):gsub() works–by passing the string itself as the first argument!

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading