I'm trying to create a simple addon for vanilla wow with Lua, the very first task - is to initialise some UI and to call a function for initial configuration.
MyAddonName.xml
<Ui xmlns="http://www.blizzard.com/wow/ui/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.blizzard.com/wow/ui/ https://raw.githubusercontent.com/Gethe/wow-ui-source/live/Interface/AddOns/Blizzard_SharedXML/UI.xsd">
<Frame name="MyAddonName" parent="UIParent">
<Size x="384" y="512" />
<Anchors>
<Anchor point="CENTER" relativePoint="CENTER"
relativeTo="UIParent" />
</Anchors>
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parent_Portrait" parentKey="portrait"
file="Interface\Icons\INV_Misc_EngGizmos_30">
<Size x="60" y="60" />
<Anchors>
<Anchor point="TOPLEFT">
<Offset x="7" y="-6" />
</Anchor>
</Anchors>
</Texture>
</Layer>
</Layers>
<Scripts>
<OnLoad function="MyAddonName_OnLoad" />
</Scripts>
</Frame>
</Ui>
MyAddonName.lua
function Print(msg, r, g, b)
DEFAULT_CHAT_FRAME:AddMessage("|c0033ffccMyAddonName|r "..msg.."", r, g, b)
end
function MyAddonName_OnLoad(self)
Print("loaded"..tostring(self), 0, 1, 0) // <- self exists
self.items = {}
end
function MyAddonName_TestFunct()
Print(MyAddonName.items) or Print(self.items) // <- not exists, attempt to index field 'items' (a nil value)
end
MyAddonName_TestFunct
will be called later, for test purpose I just called this from
/run MyAddonName_TestFunct()
/run MyAddonName_TestFunct()
I assumed that MyAddonName_OnLoad
with self will be called after addon is loaded from xml part where self is a table that represent instance of addon, and later on some event I can call MyAddonName_TestFunct
with some initial value stored in a table accessible via self
.
I checked other addons (for example BetterCharacterStats) and there is a similar code, for example
function BCS:OnLoad() // `BCS:` means that self passed implicitly
I also noticed that table BSC created explicitly, but thus I have
self
during check - this is not needed for me.
----
Here is a more complete example that I tested (with more code) - I'm trying to follow some tutorial, result now a bit different
And this is result of prints
Can anyone suggest where I'm wrong?
The issue you're encountering with self being nil during the OnLoad
event is a common problem in World of Warcraft UI scripting, especially for custom frames. This typically happens because when the OnLoad
script is fired, the reference to self is not automatically passed in the way you'd expect it to be, especially when it's a custom frame or button.
Here's why:
In WoW, the self
parameter is typically passed in automatically by the system when you use the OnLoad
event in combination with a frame
or button
. However, if the OnLoad
event is handled within XML
, the frame
might not have been fully initialized when the event fires, or the XML
setup might not be correctly linked to the Lua function.
The Root Cause
The OnLoad
event is generally triggered when the frame has been loaded, but in some cases (depending on the context), self might not reference the frame as expected.
Reference the Frame Directly in Lua
If you don’t want to change the XML
, you can modify the Lua function to get a reference to the frame directly, even if self is nil. You can achieve this by referencing the frame
by name within the MyAddonName_OnLoad
function.
fix:
local frame = self or MyAddonName -- Fallback to MyAddonName if self is nil