3

I can see that similar questions has been asked, however I'm not really that familiar with lua coding. I'm trying to fix an old World of Warcraft vanilla addon, to run in the Classic client.

The code is as follows:

    function FHH_OnLoad()

    this:RegisterEvent("PLAYER_ENTERING_WORLD");
    this:RegisterEvent("UPDATE_MOUSEOVER_UNIT");

    -- Register Slash Commands
    SLASH_FHH1 = "/huntershelper";
    SLASH_FHH2 = "/hh";
    SlashCmdList["FHH"] = function(msg)
        FHH_ChatCommandHandler(msg);
    end
    
    local version = GetAddOnMetadata("GFW_HuntersHelper", "Version");
    GFWUtils.Print("Fizzwidget Hunter's Helper "..version.." initialized!");
    
end

And it throws the following errors;

Message: Interface\AddOns\GFW_HuntersHelper\HuntersHelper.lua:27: attempt to index global 'this' (a nil value)
Time: Tue Jun 30 09:25:14 2020
Count: 1
Stack: Interface\AddOns\GFW_HuntersHelper\HuntersHelper.lua:27: attempt to index global 'this' (a nil value)
Interface\AddOns\GFW_HuntersHelper\HuntersHelper.lua:27: in function `FHH_OnLoad'
[string "*:OnLoad"]:1: in function <[string "*:OnLoad"]:1>

Locals: (*temporary) = nil
(*temporary) = nil
(*temporary) = nil
(*temporary) = nil
(*temporary) = nil
(*temporary) = "attempt to index global 'this' (a nil value)"

I've tried playing around with the "this" statement but I'm not really sure what to do, and thought I'd see if anyone of you bright people in here would know what's going on

Egor Skriptunoff
  • 23,359
  • 2
  • 34
  • 64
Dude85
  • 41
  • 1
  • 5
  • 2
    "Frameworks" like the WoW Add-On Framework often bring a new flavour to the language, so my comment may be wrong in your case. The reference to the current object in Lua ist called `self`. When you call a function with `:` instead of `.`, the object you're calling this function on is implicitly passed as the first parameter. If you define a function as `something:yourfunction()` instead of `something.yourfunction()` the first parameter is implicitly named `self`. The function definition `function something:yourfunction() [...] end` is equal to `function something.yourfunction(self) [...] end` – Felix Jun 30 '20 at 07:47
  • And what would line `27` be in your script? – DarkWiiPlayer Jun 30 '20 at 08:53
  • Line 27 is the onload; this:RegisterEvent("PLAYER_ENTERING_WORLD"); and I guess it would be the same for the next line, as it's an identical function – Dude85 Jun 30 '20 at 08:57
  • It really depends on what is happening and what approach the original developer took. At some point in the past, Blizz moved from various global variables to locals. Check where FHH_OnLoad is actually used (name suggests it's somewhere in an XML). The `` passes a single argument `self` to its content, which could be then passed to `FHH_OnLoad`. – Aki Jun 30 '20 at 11:46
  • You're right, it is in an XML file. I think I may have taken my mouth too full, im a hobby C# coder, and thought I may be able to search my way through fixing this addon but looks like its more complicated than I anticipated. @green though you're right, the FHH_OnLoad is there in the xml, there's just no arguments; ` FHH_OnLoad(); FHH_OnEvent(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); ` – Dude85 Jun 30 '20 at 12:37
  • You can edit the xml content into question as it's quite big part of it. Plus it looks bad in comment. – Aki Jun 30 '20 at 13:17

1 Answers1

4

If the addon in question is quite old, then at some point in the past (2010?) the Addon API has moved from global variables to locals.

Frames are defined in XML files, like the one you posted in the comment:

<Frame name="HuntersHelperFrame">
   <Scripts>
      <OnLoad>FHH_OnLoad();</OnLoad>
      <OnEvent>
         FHH_OnEvent(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); 
      </OnEvent>
   </Scripts>
</Frame>

The elements in <Scripts> are actually called as functions with their content as function body. They are called with some arguments. You can find out what arguments using World of Warcraft API as a reference. It's not official, but it's the closest thing to reference manual there is.

For now, you are interested in Widget handlers.

Now then, the first steps you should take are:

  1. Change the XML:
    <Frame name="HuntersHelperFrame">
       <Scripts>
          <OnLoad>FHH_OnLoad(self)</OnLoad>
          <OnEvent>
             FHH_OnEvent(self, event, ...) 
          </OnEvent>
       </Scripts>
    </Frame>
    
  2. Change the lua to reflect that:
    function FHH_OnLoad(self)
       self:RegisterEvent("PLAYER_ENTERING_WORLD")
       -- and so on, change all occurrences of `this` to `self`
       -- or simply name the first argument `this` instead of `self`:
       -- function FHH_OnLoad(this)
    end
    
    -- Change all of the functions:
    function FHH_OnEvent(self, event, ...)
       -- function body
    end
    

Depending on the size of the addon it might become a big chunk of work. Sadly, that's not the end to it; be wary as the script could rely directly on the presence of global variables and do some tricks.

I guess you could try to work around it with tricks like local this = self and similar, but that might not be applicable in all cases, and may cause some problems due to how framework may parse the XML.

One final note; the API changed a lot over the years and you will most likely run into even more problems. Good luck!

Aki
  • 2,818
  • 1
  • 15
  • 23
  • Thank you a bunch. With your hints I was able to get the addon working. Much appreciated! No more errors, now I need to figure out why it isn't printing abilities into tooltips :) – Dude85 Jun 30 '20 at 13:47