Archive

UI Mod Guide - Chapter 1

Updated Thu, Feb 21, 2008 by bpirkle

Krimm's Guide
to World of Warcraft Addon Design

Part 1
The Basics










Part 1 Index

Download Part 1 Example Files!


In Part One, we’ll start with the most fundamental questions, such as “What is an AddOn”.  We’ll look at the most basic pieces common to all AddOns, and see how they fit together.  By the end, we’ll have a trivial but functional AddOn. 

WHAT IS AN AddOn?

Let’s start by defining an AddOn from the perspective of a player.  An AddOn is just a way to modify WoW to your liking.  It may add fancy quickbars, show extra stats, simplify quest journal management, or any number of things.  Take a moment to give Blizzard a big cheer for including AddOns in the game!  They make the game that much better.  Blizzard prevents AddOns from doing anything to the actual game mechanics, so an AddOn can’t double your damage output, make you invulnerable, or perform any other sort of cheating.  In summary, AddOns are a great system for making the game more flexible and customizable in a safe and reversible way.  One final thing:  you may also hear the terms “UI Mod” or “User Interface Modification”.  These are just other terms for “AddOn”.

Now let’s consider an AddOn from the perspective of a programmer.  An AddOn consists of set a of files that you place into a certain location on your computer.  Every AddOn is a collection of three things
- Lua code 
- XML definitions
- a table of contents file
There are some more esoteric things that can show up in AddOns, but we won’t worry about them in this guide.  First, we’ll look at each of the three basic pieces individually.  After that, we’ll see how they are used to create a working AddOn.

WHAT IS Lua?

Lua (pronounced “LOO-ah”) is a general purpose scripting language designed to be embeddable into other software.  For our purposes, the term “scripting language” simply means that you write Lua code, and WoW figures out what to do with it.  This has the advantage that you don’t need to take any extra steps to transform or compile your code into something that WoW can use.  This has the disadvantage that no error checking is performed until WoW actually runs.  So I could write the following, save it as Lua code, and present it to WoW for execution:

Not in the face!

Of course, this isn’t valid Lua code, so it won’t do anything useful.  WoW will trap the error so the game won’t crash or do anything else nasty.  But it won’t do any good either.  Suppose that instead I wrote:

SendChatMessage("Not in the face!", "SAY");

This is valid Lua code, and (presuming everything else about my AddOn was correct) it would cause your character to send a “say” to the chat area with the text “Not in the face!”.  Everyone on your server might think you were strange, but the code would work.

The portion of WoW that reads (parses) Lua code, performs the requested actions, and handles any errors is called an “interpreter”.  Nothing you try to make happen via Lua can occur without going through the interpreter, and the interpreter will only permit things that Blizzard allows.  This is how WoW protects Lua scripts from doing undesirable things (like deleting files on your computer or phoning Antarctica).  So feel free to experiment, knowing that you’re protected from doing anything too tragic.

I won’t attempt to teach you how to code in Lua, but later on I will show you enough working Lua code to make a functional AddOn.  The Lua user’s Wiki has a FAQ with lots of information about Lua:  <http://lua-users.org/wiki/LuaFaq>.  If that doesn’t answer your Lua questions, an Internet search should provide copious amounts of information.  By the way, “Lua” means “moon” in Portuguese.  Somebody must have been working late.  J

WHAT IS XML?

Massive books have been written about XML, full of an alphabet soup of obscure acronyms.  For our purposes, though, XML is pretty simple.  It is just a structured way to represent data.  An example should help.  Suppose I wanted to describe a dog.  I could list the dog’s name, hair color, hair length (long or short) hair type (curly or straight), and weight.  XML lets us present this data in a clean format easily readable by a computer:

<dog>
       <name>Duke</name>
       <hair>
              <color>black</color>
              <length>short</length>
              <type>straight</type>
       </hair>
       <weight>125</weight>
</dog>

Every piece of information, or “element”, begins with an “opening tag” and ends with a “closing tag”.  The “opening tag” is just the element name, surrounded by angle brackets (ex. “<dog>”).  The “closing tag” is the same as the opening tag, but with a slash before the element name (ex. “</dog>”).  Elements can contain values (a piece of text, like “Duke”) or other elements (like “hair” does in the above example).  Our entire XML document is really just a single element (“dog”) which contains other elements.  Okay so far?  It gets a little hairier, but not much.

An “attribute” is information about an element stored directly in the opening tag.  For example, I could record the information about Duke using elements like this:

<dog name="Duke" weight="125">
       <hair color="black" length="short" type="straight">
       </hair>
</dog>

XML defines no rules about when to use elements and when to use attributes.  You just need to be sure that whomever or whatever is reading your XML knows what to expect.  In our case, WoW defines how to use elements and attributes.  So our task is to learn what WoW wants, then structure our XML accordingly.  I’ll show you how a bit later.

There’s only one more rule you need to know.  When an element contains only attributes and no text, you can omit the closing tag.  Instead of a closing tag, you put a slash at the end of the opening tag.  Here is the “Duke” XML rewritten one final time to take advantage of this rule:

       <dog name="Duke" weight="125">
              <hair color="black" length="short" type="straight" />
       </dog>

That’s it.  The XML for creating an AddOn can look complex, but it is really just a combination of the above rules.

WHAT IS A TABLE OF CONTENTS?

A table of contents tells you what’s in something.  Duh.  J  In the context of AddOns, a table of contents (toc) tells WoW what files are part of your AddOn and provides some other necessary information.  Here’s an example:

## Interface: 10900
## Title: TenTonHammer Guide Part 1
## Author:  TenTonHammer.com
## Notes:  Makes your character scream a silly battle cry when combat begins
TthAog1.xml

The “Interface” line gives the version of WoW that your AddOn works with.  The “Title”, “Author”, and “Notes” lines are for documentation.  The last line is the (rather awkward) name of our .xml file.  There are more things that can go in toc files, but the above is enough to create a working AddOn.

WHERE DO AddOns LIVE?

There’s only one more thing we need to know to create a working AddOn:  where to put our files.  If you’re running Windows, look under “C:\Program Files\World of Warcraft” for a folder named “Interface”.  If it doesn’t exist, create it.  Now look under “Interface” for a folder named “AddOns”.  If it isn’t there (and if you just created “Interface” it won’t be) then create this too.  The instructions for a Mac are similar, except that WoW lives in “Macintosh HD/Applications”.  In either case, just make sure you end up with an “AddOns” folder in the correct spot

Each AddOn lives in its own folder underneath the AddOns folder.  If you’re already running some AddOns, you’ll see their folders.  Take a peek into a few and see what’s there.  Feel free to open up the files in your favorite text editor.  A little time browsing through existing AddOns will help make everything we’ve talked about so far make a lot more sense. 

HOW DO AddOns WORK?

A full description of everything AddOns can do is beyond the scope of this guide.  To keep from getting overwhelmed with details, we’ll stick with the core concepts that will apply to every AddOn that you write.  There are three things that you must deal with to write even the simplest AddOn:
            - Functions
            - Events
            - Frames
We’ll take each of these in turn.  When we’re done, we’ll be ready to write a simple AddOn.

WHAT ARE FUNCTIONS?

Functions are blocks of Lua code that makes your AddOn do something of interest.  Functions are defined in the .lua file in your AddOn’s folder.  A function might look something like this:

function TthAog1Event()
  -- send a message to chat
  SendChatMessage("Not in the face!", "SAY");
end

Let’s look at it line-by-line.

function TthAog1Event()

This line begins a function named “TthAog1Event”.  The empty parenthesis means that the function takes no parameters.  In other words, the code that calls this function doesn’t need to pass any extra information to it.

-- send a message to chat 

This line is a comment.  Comments are simply a way for the programmer to add notes to their code.  Write comments.  Lots of ‘em.  It will be an incredible help to you a year down the road when you’re trying to remember what you where thinking when you wrote the code.

SendChatMessage("Not in the face!", "SAY");

We’ve already see this line.  The function SendChatMessage is not part of Lua, and it isn’t a function you write.  It is a function provided by WoW, and it is how your AddOn makes things happen in the game.  There are a massive number of these functions.  See here <http://www.wowwiki.com/World_of_Warcraft_API > for a list.

end

This final line simply ends the function.  ‘Nuff said.

Functions don’t do anything unless they are “called”.  Calling a function simply means that another block of code tells the function to execute.  In the next section, we’ll see one way that functions get called.

WHAT ARE EVENTS?

Events are how WoW tells your AddOn what is happening in the game.  Just about everything that happens in WoW generates an event.  When an event occurs, WoW checks to see if any AddOns have asked to be notified.  If so, WoW notifies the AddOn that the event has occurred.  The AddOn can then do whatever it needs to.

The way that an AddOn tells WoW that it wants to know when an event occurs is by “registering” for the event.  You do this by adding an element something like this to the AddOn’s XML file:

<OnLoad>TthAog1Load();</OnLoad>

And a function like this to your AddOn’s Lua  file:

function TthAog1Load()
  this:RegisterEvent("PLAYER_REGEN_DISABLED");
end

The “OnLoad” element contains a little snippet of Lua code.  WoW knows to run this snippet of code when your AddOn loads.  The code snippet simply calls the “TthAog1Load” function.  Taken together, the “OnLoad” element and the “TthAog1Load” function say that the AddOn needs to know when the “PLAYER_REGEN_DISABLED” event occurs. 

Many different AddOns can register for the same event.  And they probably will.  Also, your AddOn can register for many different events.  And it probably will.  By the way, the “PLAYER_REGEN_DISABLED” event occurs (more or less) when combat begins.  There are a huge number of different events.  See here <http://www.wowwiki.com/Events_%28API%29 > for a list.

Just registering for an event isn’t enough.  Your AddOn must also say what should happen when the event occurs.  This works much like “OnLoad” does above.  Your XML file will contain something like this:

<OnEvent>TthAog1Event();</OnEvent>

We’ve already seen the “TthAog1Event” function.  Now you know how it gets called.  To review, here are steps required for you AddOn to respond to an event:

1)  Add an OnLoad element to your XML
2)  Write a Lua function to be called by the OnLoad element.
3)  Add an OnEvent element to your XML
4)  Write a Lua function to be called by the OnEvent element.

By doing these four steps, we have defined the internal plumbing by which control is passed from WoW to our event-handling function at the appropriate times.  Much of this is “boilerplate” code, meaning that it is mostly cut-and-paste.  It doesn’t change much from one AddOn to the next.  The really interesting part is the event handling function.  This is where the real logic of your AddOn resides.

Note that instead of just a function call, you could put big blocks of Lua code into the OnLoad and OnEvent elements.  Don’t.  Mixing your XML and your Lua makes both parts hard to read and maintain.  You will read your code many, many more times than you will write it.  Keep everything nice, clean, and separated, and your AddOn will be easier to fix and improve.

WHAT ARE FRAMES?

Frames are the foundation of the WoW user interface.  Internally, the WoW user interface itself consists of a number of frames.  Every window within WoW involves a frame, but frames don’t have to be visible.  One purpose of frames is to manage events.  In our example AddOn, we use a  frame that exists only for event management.  Frames are defined within the XML portion of AddOns.  Heres the XML for our frame:

<Frame name="TthAog1Core">
       <Scripts>
              <OnLoad>TthAog1Load();</OnLoad>
              <OnEvent>TthAog1Event();</OnEvent>
       </Scripts>
</Frame>

We’ve seen most of this before, when we looked at events.  The new parts are the “Frame” and “Scripts” elements.  The “Scripts” element is the event-handling portion of the frame, and holds the two lines of XML that we’ve already seen.  The “Frame” element contains all elements belonging to the frame, and also names the frame (via an attribute).  You’ll see in Part Seven why I ended our frame name with “Core”.  For now, just know that this is a descriptive name that no other AddOn is likely to pick.

CAN WE WRITE AN AddOn ALREADY?

Yes, we finally can.  And we’ve already seen almost all the code.  Recall that there are three main parts to an AddOn:
- a table of contents file
- XML definitions
- Lua code

You’ve already seen the full contents of the toc file.  Here it is again:

 
## Interface: 11000
## Title: TenTonHammer Guide Part 1
## Author:  TenTonHammer.com
## Notes:  Makes your character scream a silly battle cry when combat begins
TthAog1.xml

Using your favorite text editor (Notepad works fine in Windows), place the above into a file and save it to

C:\Program Files\World of Warcraft\Interface\AddOns\TthAog1\TthAog1.toc

Of course, if you have WoW installed to a different drive than C: you should substitute the correct drive letter.  Or if you’re on a Mac:

Macintosh HD/Applications/World of Warcraft/Interface/AddOns/TthAog1/TthAog1.toc

That’s it for the toc file.

You’ve also seen almost everything from the XML file.  Here is the full file:

<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/">
       <Script file="TthAog1.lua"/>
       <Frame name="TthAog1Core">
              <Scripts>
                     <OnLoad>TthAog1Load();</OnLoad>
                     <OnEvent>TthAog1Event();</OnEvent>
              </Scripts>
       </Frame>
</Ui>

You can use any text editor to work with XML, just like you did with the .toc file.  The XML should go into a file named “TthAog1.xml” in the same folder as TthAog1.toc.  The only new things in the file are the “Ui” element and the “Script” element. 

While the “Ui” element may look intimidating, it is just boilerplate XML.  Its attributes are there for a reason, but at this point you don’t have to know or care what that reason is.  Just paste them in and your AddOns will be fine.

The “Script” element tells WoW which file contains your Lua code.  We’re putting our Lua code into a file with the same name as our AddOn.

Finally, we have the Lua file containing the code itself.  You’ve already seen the complete contents of this file:

function TthAog1Load()
  this:RegisterEvent("PLAYER_REGEN_DISABLED");
end

function TthAog1Event()
  -- send a message to chat
  SendChatMessage("Not in the face!", "SAY");
end

Use your text editor again to save this to a file named “TthAog1.lua”, in the same folder as your TthAog1.toc and TthAog1.xml files.

IT’S DONE.  WHAT DOES IT DO?

Now you have a folder for your AddOn with three files in it.  If you’re not already running WoW, start it.  Your AddOn will be automatically active.  If you are running WoW, type “/console reloadui” to activate your AddOn.  Depending on the speed of your computer, this command may make WoW appear to freeze for anywhere from a few seconds to around a minute while everything is reloaded.  Your character continues to exist in the game world during this time, so be sure you’re somewhere safe.  Otherwise, you might find yourself dead when the interface finishes reloading.  Yes, I speak from experience. J

Now, go get in a fight.  If everything is correct, your character should say “Not in the face!” when combat starts.  Okay, it isn’t the most heroic battle cry, but I never said we’d be writing a good AddOn in Part One of this guide, did I? J  Feel free to change the battle cry to one of your choice by changing it in your TthAog1.lua file.  Also in that same file, you can change “SAY” to “PARTY” if you’d prefer to announce your battle cry just to your party members. 

What actually occurs is that entering combat causes the PLAYER_REGEN_DISABLED event to fire.  Because the AddOn has registered for this event, WoW runs the Lua snippet in the OnEvent element of our XML.  This snippet calls the TthAog1Event function in our Lua code.  This function calls the SendChatMessage function provided by WoW, passing parameters that detail what the character should say, and in which channel. 

If things don’t work as expected, check Appendix One of this guide for some debugging suggestions.

Let me add a quick disclaimer:  there may be a dozen better battle cry AddOns out there.  I haven’t checked.  I thought of this idea independently when considering what would best serve as an example AddOn for this guide.  If you wrote a battle cry AddOn that happens to use similar techniques, I didn’t steal your idea or your code.  If your AddOn also makes your character scream “Not in the face!”, find a good psychiatrist’s office.  And give me their number, maybe they’ll give us a group discount.  J

I’ll also add a quick warning:  we’re developing this AddOn as an example, not as something that is terribly useful on its own merits.  Filling the chat channel with silly battle cries might not make you any friends, so be careful about when and where you use it.  In future installments, we’ll add the capability for you to set the battle cry, turn it on and off, etc.  That way you can experiment without annoying anyone.

That concludes Part One of the guide.  When you’re ready, move on to Part Two and we’ll make some much-needed improvements to our little AddOn.


Go to Part 2 - Slash Commands!


WarlockWallpaper.jpg
Five classes that would be excellent additions to World of Warcraft.
Features
Fri, Jun 20, 2014
Mem
HotSAlphaLoad.jpg
Five things players should expect during the Alpha test of Warlords of Draenor.
Features
Fri, Jun 13, 2014
Mem
GG_25_02

I really don't understand racism in the real world. People are what people are, regardless of skin pigmentation or where their ancestors came from. There's really only one real-world race - the Human Race - and I loathe everyone equally.

Opinions
Mon, Jun 09, 2014
gunky
GarrisonTownHall.jpg
A basic guide to Garrisons in Warlords of Draenor.
Basics, Features, Guides
Fri, Jun 06, 2014
Mem

News from around the 'Net