I come from a C#/Java background and have never touched Lua before.
I want the addon to show a message (default message window) that prints out the class of the target whenever I click on and target another player, and ONLY when I target a player. I have two files, SpeccySpecs.lua (contains the functions needed to handle the event) and SpeccySpecs.xml (contains the frame to run the function). Whenever I run the addon ingame, I am getting nil errors because my Core.lua file is returning nil when requiring the .xml file and my .xml file returns a nil from the OnTarget()
function in SpeccySpecs.lua.
I have tried to solve this in multiple ways, one of which was by creating a local table and requiring it in Core.lua, where I'd eventually call the function inside the table, but it also returned nil. I've been using sites such as:
https://wowpedia.fandom.com/wiki/Events
https://wowwiki-archive.fandom.com/wiki/Event_API
But what I've tried simply hasn't worked, and I assume I'm forgetting something small in the Lua code.
SpeccySpecs.lua
local function getPlayerClass()
local playerClassName = nil;
local playerClassFilename = nil;
local playerClassId = nil;
if UnitClass("target") ~= nil
then
playerClassName, playerClassFilename, playerClassId = UnitClass("target");
if playerClassName == 1 -- Warrior
then message ("It's a warrior")
elseif playerClassId == 2 -- Paladin
then message ("It's a paladin")
elseif playerClassId == 3 -- Hunter
then message ("It's a hunter")
elseif playerClassId == 4 -- Rogue
then message ("It's a rogue")
elseif playerClassId == 5 -- Priest
then message ("It's a priest")
elseif playerClassId == 6 -- Death Knight
then message ("It's a death knight")
elseif playerClassId == 7 -- Shaman
then message ("It's a shaman")
elseif playerClassId == 8 -- Mage
then message ("It's a mage")
elseif playerClassId == 9 -- Warlock
then message ("It's a warlock")
elseif playerClassId == 10 -- Monk
then message ("It's a monk")
elseif playerClassId == 11 -- Druid
then message ("It's a druid")
elseif playerClassId == 12 -- Demon Hunter
then message ("It's a demon hunter")
else message ("That class does not exist")
end
else message ("Please target a player")
end
end
function OnTarget(self, event, ...)
print(event)
return getPlayerClass()
end
SpeccySpecs.xml
<UI>
<Script file="SpeccySpecs.lua"/>
<Frame name="SpeccyFrame">
<Scripts>
<OnEvent function="OnTarget"/>
</Scripts>
</Frame>
</UI>
Core.lua
PlayerClassFrame = require "SpeccySpecs.xml";
return PlayerClassFrame
Thanks in advance for the help, everyone.
Goes like this:
make frame (yours is in xml) > OnLoad event handler > register for events > event fired > handle events
1) You don't need the require or the core.lua:
WoW has its own explicit ordered loading process that uses toc files and includes in xml.
Your toc file probably looks like:
# some stuff
MyAddon.xml
Then your MyAddon.xml loads:
<UI>
<Script file="MyAddon.lua"/>
<Frame name="MyAddonFrame">
Which then loads the .lua file first, so that all the things in the .lua file are available to be referenced as the frame xml loads.
2) You are missing registering for a specific event:
For example:
<OnLoad> self:RegisterEvent("PLAYER_ENTERING_WORLD") </OnLoad>
So that you end up with something like:
<OnLoad> self:RegisterEvent("PLAYER_ENTERING_WORLD") </OnLoad>
<OnEvent> print("Event name " .. event) </OnEvent>
You need to go find a specific event that deals with when something is targeted that comes as close as possible to fitting what you need.
3) You need to pass the telemetry from the event to the handler function:
<OnEvent> MyAddon:OnEvent(self, event, ...) </OnEvent>
The self is the current frame, event is given to you hind the scenes as OnEvent here just becomes compiled into a regular Lua function and gets event passed to it, and ... is a Lua type of list used for unnamed parameters, which you can break out into Lua variables later.
4) You need a repeatable way to expose your Lua code across files
This needs to be in a way that does not clash with WoW or other addons.
MyAddon = {}
Is one way. This makes a single Lua table with a global unique name that you can stick functions in so they can be found elsewhere outside that one file.
Anything in WoW that is not 'local' goes into a single environment Lua global name space across all addons and wow.
5) You need to accept the parameters for telemetry from the event:
And process the telemetry to eek out what you more specifically need
function MyAddon:OnEvent(frame, event, ...)
if event == "SOME_EVENT_NAME" then
local _, name = ...
if is this some player then
MyAddon:SomePlayerDidSomething(name)
end
elseif event == "SOME_EVENT_NAME" then
end
end
This should get you started for the basic addon process.
After all that is working, then you need a way to make the business end more data driven, which will in theory make it more code-size and speed efficient.
6) Add a table to lookup strings for ids:
MyAddon.classNames = {
[1] = "warrior",
[2] = "paladin",
[3] = "hunter",
}
See https://www.lua.org/pil/3.6.html
Which will allow you to construct code more like this:
local className = self.classNames[playerClassId]
if className then
message("It's a " .. className .. ".")
end
This should get you started overall. It's hard to find the right resource often to get you off the ground at the very beginning. You got pretty far.