Best practice for overriding a local function

DaanVanYperenDaanVanYperen The Netherlands Join Date: 2013-06-16 Member: 185580Members, NS2 Playtester, Squad Five Blue, Reinforced - Shadow
Working on the Skulks WIth Shotguns mod, going great so far. I'm new to lua and ns2 modding though so having some trouble with the basics.

What would you suggest to be the best method for overriding a local function?

Specifically AssignPlayerToEgg, in AlienTeam.lua.

My best solution is overriding AlienTeam:Update (which calls AssignPlayerToEgg) in a mod file, but that leads to a lot of local functions having to end up in my mod file as well. I figure I might be overlooking some basic method of achieving just a single local function override.

Thanks!

Comments

  • Soul_RiderSoul_Rider Mod Bean Join Date: 2004-06-19 Member: 29388Members, Constellation, Squad Five Blue
    If you can specify what you are trying to achieve, we can possibly advise on a way to do it. Why would you not just edit the function, rather than override it?


    If you could supply more info, I am sure we can help :)

    Oh and good luck with the programming, Howser told me you had finally bitten the NS2 bullet. As you have programming experience, you should find this lua coding pretty easy :D
  • DaanVanYperenDaanVanYperen The Netherlands Join Date: 2013-06-16 Member: 185580Members, NS2 Playtester, Squad Five Blue, Reinforced - Shadow
    The typical way to do this seems to be supplying my own AlienTeam.lua file copy with just small bits changed, which will make the mod more fragile and harder to maintain. I rather just replace a single local function from my own source files, but I can't seem to do that without also copying over the calling class functions.

    I saw there is a way of injecting local variables into a class method, is there some way to inject local functions? (Specifically AssignPlayerToEgg into AlienTeam:Update).
  • FehaFeha Join Date: 2006-11-16 Member: 58633Members
    edited January 2014
    How I usually do it:
    local oldOnDestroy
    oldOnDestroy = Class_ReplaceMethod( "Player", "OnDestroy",
    function(self)
    if Client and self.waterCinematic then
    Client.DestroyCinematic(self.waterCinematic)
    self.waterCinematic = nil
    end

    oldOnDestroy(self)
    end
    )

    EDIT:
    Oh, didnt read carefully enough and missed that you were talkign about *local* functions.
    Class_ReplaceMethod obviously replaces a class-method, not local ones. Person8880 points to the correct function to use in your case (further down this page).
  • Soul_RiderSoul_Rider Mod Bean Join Date: 2004-06-19 Member: 29388Members, Constellation, Squad Five Blue
    Best to use the hooking system for that. I don't have any experience, as I've always made full game mods rather than simply hooking files, but that will provide you with everything you need.
  • GhoulofGSG9GhoulofGSG9 Join Date: 2013-03-31 Member: 184566Members, Super Administrators, Forum Admins, Forum Moderators, NS2 Developer, NS2 Playtester, Squad Five Blue, Squad Five Silver, Reinforced - Supporter, WC 2013 - Supporter, Pistachionauts
    edited January 2014
    First i think i would go another way to change eegclass. Look into Hive:UpdateSpawnEgg() ;)

    Edit: Ok i memorized the function of ReplaceLocals( Function, TableOfLocals ) in a wrong way. Person8880 is totally right.
  • RioRio Join Date: 2005-01-28 Member: 38716Members
    You could copy the whole AlienTeam.lua and change the local functions into non-local functions which you then can override. The downside is, that you have to replace your AlienTeam.lua everytime there is an update for NS2.
  • Person8880Person8880 Join Date: 2013-01-02 Member: 177167Members, Squad Five Blue
    You can override local functions. In fact, there's a premade function in core/lua/Class.lua that does it very easily.
    ReplaceLocals( Function, TableOfLocals )
    

    So in your case,
    ReplaceLocals( AlienTeam.Update, { AssignPlayerToEgg = YourReplacementHere } )
    
  • McGlaspieMcGlaspie www.team156.com Join Date: 2010-07-26 Member: 73044Members, Super Administrators, Forum Admins, NS2 Developer, NS2 Playtester, Squad Five Blue, Squad Five Silver, Squad Five Gold, Reinforced - Onos, WC 2013 - Gold, Subnautica Playtester
    Pay attention to what Lua VM you're replacing those in. If the original function is declared in Server VM scope only, calling ReplaceLocals in the Client VM scope will toss errors.

    If you're really using the modding framework, then your files are almost certainly mixed vm scopes. So, to make it easier, just wrap a "if Client" or "if Server" , etc. conditional block around the ReplaceLocals call.
  • DaanVanYperenDaanVanYperen The Netherlands Join Date: 2013-06-16 Member: 185580Members, NS2 Playtester, Squad Five Blue, Reinforced - Shadow
    Ohhh thanks a lot guys! That'll clean things up right quick!
  • MCMLXXXIVMCMLXXXIV Join Date: 2010-04-14 Member: 71400Members
    Wow, that override locals function would have been so handy for us! Better than the method which I'd suggest and which we used in Xenoswarm/Combat.
  • DaanVanYperenDaanVanYperen The Netherlands Join Date: 2013-06-16 Member: 185580Members, NS2 Playtester, Squad Five Blue, Reinforced - Shadow
    edited January 2014
    Just a quick addition for anyone needing to get a reference for a nested local function.

    Iin my case, I needed to replace local function AssignPlayerToEgg, called by local function updateAlienSpectators, called by class method AlienTeam.Update.

    Added the function GetLocalFunction to get a reference to updateAlienSpectators
    -- Retrieve called local function
    -- Useful if you need to override a local function in a local function with ReplaceLocals but lack a reference to it.
    function GetLocalFunction(originalFunction, localFunctionName)
    
        local index = 1
        while true do
            
            local n, v = debug.getupvalue(originalFunction, index)
            if not n then
               break
            end
                
            if n == localFunctionName then
                return v
            end
                
            index = index + 1
                
        end
        
        return nil
        
    end
    

    After that just a question of calling ReplaceLocals.
    local updateAlienSpectators = GetLocalFunction(AlienTeam.Update, 'UpdateAlienSpectators')
    ReplaceLocals( updateAlienSpectators, { AssignPlayerToEgg = AssignPlayerToEgg } )
    

    Not sure this is the best way, but it works for me!
  • GhoulofGSG9GhoulofGSG9 Join Date: 2013-03-31 Member: 184566Members, Super Administrators, Forum Admins, Forum Moderators, NS2 Developer, NS2 Playtester, Squad Five Blue, Squad Five Silver, Reinforced - Supporter, WC 2013 - Supporter, Pistachionauts
    Just a quick addition for anyone needing to get a reference for a nested local function.

    Iin my case, I needed to replace local function AssignPlayerToEgg, called by local function updateAlienSpectators, called by class method AlienTeam.Update.

    Added the function GetLocalFunction to get a reference to updateAlienSpectators
    -- Retrieve called local function
    -- Useful if you need to override a local function in a local function with ReplaceLocals but lack a reference to it.
    function GetLocalFunction(originalFunction, localFunctionName)
    
        local index = 1
        while true do
            
            local n, v = debug.getupvalue(originalFunction, index)
            if not n then
               break
            end
                
            if n == localFunctionName then
                return v
            end
                
            index = index + 1
                
        end
        
        return nil
        
    end
    

    After that just a question of calling ReplaceLocals.
    local updateAlienSpectators = GetLocalFunction(AlienTeam.Update, 'UpdateAlienSpectators')
    ReplaceLocals( updateAlienSpectators, { AssignPlayerToEgg = AssignPlayerToEgg } )
    

    Not sure this is the best way, but it works for me!

    Hmm GetLocalFunction reminds me of Shine.GetUpValue. But BTT yes this is probably the same way i would do it.
  • DaanVanYperenDaanVanYperen The Netherlands Join Date: 2013-06-16 Member: 185580Members, NS2 Playtester, Squad Five Blue, Reinforced - Shadow
    @GhoulofGSG9 Yeah it's basically a stripped version of ReplaceLocals that just fetches the requested Upvalue.

    I saw you post about Shine before. I'm simply too fresh in the whole modding process to be knowledgeable about the optional frameworks out there. One week in, still finding my way around Lua and vanilla NS2 code. I already have enough rope to hang myself with ;)

    Don't get me wrong. Some of the mods out there have been great study material. Xenoswarm's code for example is elegantly written and easy to learn from. It just addresses really common issues, I wouldn't have known what to search for with the upvalue fetching thing.
  • GhoulofGSG9GhoulofGSG9 Join Date: 2013-03-31 Member: 184566Members, Super Administrators, Forum Admins, Forum Moderators, NS2 Developer, NS2 Playtester, Squad Five Blue, Squad Five Silver, Reinforced - Supporter, WC 2013 - Supporter, Pistachionauts
    edited January 2014
    Ah you're fine, using sewleks framework as you do is the best way to go for a new gamemode, which "just" wants to changes some of the basic ns2 gameplay but keep alot ns2 stuff.
Sign In or Register to comment.