Monday, April 7, 2014 - 11:17

Welcome to the 6th part of my addon tutorial! Today we'll be taking a look at the core elements in any World of Warcraft UI element, the Frames and their Events! Or put more simply, what happens in the game and how your addon can know about it!

Table of Contents

  1. What is a Frame?
  2. What is an Event?
  3. The Code
  4. The Event Tracer

What is a Frame?

In World of Warcraft, a 'Frame' is a container for special UI items. These 'Frames' can react to happenings in the game, you can use them to display art, or let the user click something in them. They are what the UI is made of. Technically speaking, a Frame is a Lua table. So you can assign methods to it, and it can have 'children'. But don't worry about that for now.

What is an Event?

An 'Event' in World of Warcraft is a message sent by the WoW client to the user interface mostly in reaction to things occurring in the game world. Events are how the addon know what's going on. There are Events for nearly everything. When the player logs in, and Event fires. When you reload the user interface or zone into an instance, an Event fires. Events occur when you die, enter combat, leave combat, gain health or mana, join a battleground, receive a chat message, gain gold, and so on. A full list can be found here!

To track an Event, you need to make a Frame listen for it. You also need to create a script handler telling the Frame what to do when an Event occurs. So let's do that right now.

The Code

What we're going to do today, is to track when your character enters and leaves combat. This is one of the most important things to be aware of, as a lot of abilities like drinking, eating, mounting up and so forth are blocked in combat. There are also a lot of things the UI can't do during combat, like changing visibility and position of existing unitframes and so on. So let's get to it!

The Events we use to watch for combat, isn't what you might think from looking at the Event list on wowpedia. It's not "PLAYER_ENTER_COMBAT", as that only fires when your auto-attack starts. What you instead should listen for is when the out of combat regen starts and stops. That's the true indicator of when you're in combat or not, when abilities like mounting up, eating and drinking are available. The Events are called "PLAYER_REGEN_DISABLED" and "PLAYER_REGEN_ENABLED".

-- create the frame
local frame = CreateFrame("Frame", nil, UIParent)

-- assign the Events to it
frame:RegisterEvent("PLAYER_REGEN_DISABLED")
frame:RegisterEvent("PLAYER_REGEN_ENABLED")

-- create a script handler to react to the Events
frame:SetScript("OnEvent", function(self, event, ...)
   -- we don't need it in this example,
   -- but this is how you retrieve arguments passed along with Events:
   local arg1, arg2, arg3 = ...
   if event == "PLAYER_REGEN_DISABLED" then
      print("You're in combat!")
   elseif event == "PLAYER_REGEN_ENABLED" then
      print("Combat ended, mount up and run!")
   end
end)

You can add this to the addon we made last time, or make a new addon for it. When it's saved properly and the game client restarted, you should now be getting warnings in the default chatframe when you enter and leave combat.

True, not a very useful addon as the UI already does this for you, but the point here wasn't to reinvent the powder, it was to show you how Events work, give you something to play around with!

▲ Go back to the top

The Event Tracer

Blizzard have provided us with a handful of useful debugging tools. One of them is the Event Tracer. Which is exactly what it sounds like, something that traces Events. You can activate it with the following command written into the chatframe inside the game:

/eventtrace

Try it, and then wait for a while. You'll notice all sorts of Events occurring. If you mouse over any of them, you'll get more details about it like the arguments passed along with it. I find the Event Tracer to be one of the most useful tools in learning how the game and the UI works. No theory can beat actually seeing with your own eyes what's going on!

The Event Tracer provides very detailed information about the Events.

So, that was all I had for you today. I recommend that you study the list of Events at wowpedia, as well as checking out what other addon users are doing. A trick to figuring out stuff, is to find an addon that does something you like, then simply search that addon's code for "RegisterEvent" and "OnEvent". You can consider that one of my major secrets, actually. It doesn't seem like much, but it will take you straight to the heart of what's going on. You'll know what the addon is listening for, and what it does when it happens. I've spent countless hours gazing at what others have done, it's simply the best way to learn.

See you all next time!

▲ Go back to the top

▲ Go back to the top

Read More
Sunday, March 30, 2014 - 09:38

This is just a short little tutorial to help people with way too many alts to remove some of those saved setings from gUI3. Because gUI3 doesn't have a "delete"-button, and sometimes the dropdown menu where you select profile to copy, is bigger than the screen. *problem*

Finding your saved settings

The first thing you need to do is to find your saved settings file for gUI3. For gUI3 this is just a single file, so that part of the tutorial will be easy. The important thing here is to NOT be logged into any character in WoW when doing this. Because WoW keeps all the settings in memory while you're logged in, and saves them back to the disk on ever logout or interface reload. So make sure you're logged out!

This is where you'll find your settings: World of Warcraft\WTF\Account\YOUR_ACCOUNT_NAME\SavedVariables\

You should replace "YOUR_ACCOUNT_NAME" with whatever your account name is, because this will be different for everybody. It could be the name you chose for your account in classic WoW if you've played for that long, or it could be a collection of numbers. You might have to look a while until you find the right one.

You need to edit the .lua file, not the .bak file!

Editing the saved settings

Now comes the actual editing. This stage I find to be much easier if you're using a text editor with the option to expand or collapse levels. This is something usually included in editors meant for writing code, like Notepad++ for Windows which I'm currently using. Because as you'll see, the file is big and hard to read without it:

This is what the saved settings looks like at first glance. Chaotic.

To speak a little geek'ish, the gUI3_DB variable, is split into 2 sub-tables, namely gUI3_DB.settings and gUI3_DB.profiles. If you fold the whole thing down, and expand just the top level, you should get something like the following:

Having a text editor that can fold/collapse levels really help!

Yeah, now it's much easier! What you want to do now, is to expand the "settings" table, because that's where our settings for all our characters will be. Once expanded, the first thing you'll see is a list of all the realms you have characters on. I'll go ahead and remove some of those entirely, because I don't need or want them anymore:

Never knew I had characters on this many realms! I blame the beer.
There, now it's much more managable!

Now that I'm happy with what realms I have left, I wish to remove the settings for some alts that no longer exist. I'm clicking my way into the Draenor realm, and get a list of 13 characters. 2 of them has to go!

Some of these have to go!
Voila! Down to the ones that actually exist!

▲ Go back to the top

Testing it

When you're done editing, save your file, and start the game client. When you enter the gUI3 options menu now, and click the "copy from" drowdown in any of the submenus, the list should be much shorter than before, and only consisting of the characters you chose to keep. yay! On a sidenote, in gUI4 you'll get a full profiling system like what you find in Recount, Bartender, and any other addon using the Ace framework. So this will soon be a thing of the past!

▲ Go back to the top

Read More
Sunday, February 2, 2014 - 12:16

Welcome to the 5th part of my WoW addon creation tutorial! Finally it's time to get down to business and start creating addons!

Table of Contents

  1. Making the addon
    1. Creating the files and folders
    2. Testing the addon
  2. Code breakdown

Making the addon

The time has finally come to create your first addon. From here on there'll be a little less conversation, and a little more action! So navigate to your Interface\AddOns directory, and fire up your text editor of choice.

Creating the files and folders

We'll keep this as simple as possible, so for our excercise we'll be needing a single folder, and two text files. First off you should create your addon folder within the Interface\AddOns directory. Let's call our addon "FriendlyTutorialpt2". Not the shortest name, but there should be no risk of naming conflicts at least. I doubt very much you already have an addon with that name installed.

Now go into your text editor, and create a new file. Make sure the file encoding is set to UTF8, and without BOM. In Notepad++ you can set this from the Encoding menu. You should make this a general rule to encode all your text files in WoW addons as UTF8 without BOM. It's a format fully supported by WoW, and it allows you to use letters from pretty much any language on the planet inside the code. This'll come in handy when localizing your addons to languages not using the latin alphabet, like Russian.

Name your new file "FriendlyTutorialpt2.toc" and put it directly inside the addon folder of the same name. Then copy and paste the following code into it, and save it.

## Interface: 50400
## Name: FriendlyTutorialpt2
## Title: |cffffb200friendly|r|cffff7d0adruid|r|cffffb200.com|r |cfffffffftutorial pt 2|r
## Notes: Awesome addon
## Author: Lars Norberg
## Version: 1.0
## DefaultState: Enabled

main.lua

From what you learned earlier about the TOC file, you should be able to see that our addon now require WoW 5.4.x to run, and it will load a file called "main.lua". So let's create that file too! You should have a pretty good idea of what the rest of the code does too, and if not, check out my previous tutorial on the TOC format!

Now, once again create a new file in your text editor, make sure it's encoded in UTF8 without BOM, and copy the code below into it. Save the file directly into the addon folder as "main.lua".

-- our very first addon
local addon, ns = ...

local frame = CreateFrame("Frame", nil, UIParent)
frame:RegisterEvent("ADDON_LOADED")
frame:SetScript("OnEvent", function(self, event, ...)
    local arg1 = ...
       if (arg1 == addon) then
        local version, build, date, tocversion = GetBuildInfo()
        print("Your game client is running WoW version " .. version .. ", build " .. build .. " - " .. date)
        self:UnregisterEvent("ADDON_LOADED")
    end
end)

▲ Go back to the top

Testing the addon

Make sure all the files are saved, then fire up WoW. Once you're at the character selection screen, click the button labeled "AddOns" in the bottom left corner. You should be able to find our newly created addon on the list that appears. Once that is verified, log into the game world!

Our new addon in the addon list
Our addon in action!

What you see in the chat output window - and you might have to scroll a bit up to find it if you have many addons installed, should be a message similar to "Your game client is running WoW version 5.4.2, build 17688 - Dec 12 2013". Of course, the actual values here change based on when you run this addon. Every time a patch comes, these values will be different. The output on my screen indicates I was running WoW 5.4.2 build 17688 when I took the screenshot. These values are the same as you see in the bottom left corner of the WoW startup screen.

▲ Go back to the top

Code breakdown

Now that you've succesfully made a very simple addon, let's take a look at what it actually did, line by line.

-- our very first addon
local addon, ns = ...

The first line that starts with "--", is just a comment. Comments are ignored by the client, and are just there for our own reference.

The second line creates 2 local variables, named "addon" and "ns". What "local" means in this context, is that they belong to our current addon, and can't be read by any other addon. You should as a rule ALWAYS make any variable you create a local variable. The only exception is your saved variables, as they need to be global. More on that at a later stage in the tutorial.

Both of our 2 newly created variables get their values from a very special operator called an "ellipsis", which is written as 3 dots. An ellipsis ("..." without the quotes) is a special operator which is only available inside a vararg function, meaning a function that can accept a variable number of arguments.

Every addon in WoW is in reality just a function called by the main UI environment, and by using the ellipsis operator we can access a lot of information sent to the addon by the game. The first 2 of the arguments passed to our addon is the name (directory) of the addon, and it's namespace. A namespace is basically a table, or array available to all the files of a specific addon. Meaning that you can send values between different Lua files within the same addon by using the namespace. This is a better way than using globals (variables available to all addons), as the namespace is local, and local variables are both faster, and you don't risk running into naming conflicts.

local frame = CreateFrame("Frame", nil, UIParent)

What we do here is to use a function native to WoW called "CreateFrame", to create a Frame. A Frame in WoW is a special type of table that represents an UI object. Allmost all objects you see in the UI - like unitframes, actionbuttons, bags, achievememts and so on - are Frame. You see them all the time, you just didn't know what they were until now. You can assign sizes and backdrops to the Frame if you like, or let it remain invisible like we have done. Frames are more than just a way to show graphics, they are also the only way to listen to Events, set up timers and basically make stuff happen. To learn more about the syntax of the CreateFrame() command, click here to visit wowpedia!

frame:RegisterEvent("ADDON_LOADED")

Remember we talked about Events in the previous tutorial on the addon loading process? What we did just now, was to tell our Frame to listen for the ADDON_LOADED Event. This Event fires whenever an addon has been loaded, and it's saved variables are available. This Event fires for all addons for every addon loaded, meaning if you have 30 addons installed, this Event will fire up to 30 times for your newly created Frame.

A frame is as mentioned a table. If an entry in a table is a function, you can call that function as a method of the table itself. This basically means that instead of just calling a function, you are calling a function that is aware of where it is. It knows it lives inside its table, which in our example is the Frame we created. As we stored the location of our frame in our local "frame" variable, this means that what we just did was to run the method "RegisterEvent()" on the Frame stored in "frame", and pass the argument "ADDON_LOADED" to this method. Confusing? Don't worry, it all makes sense. Eventually.

frame:SetScript("OnEvent", function(self, event, ...)


end)

Here we're running another method on our Frame, called "SetScript". Every Frame in WoW comes with a set of script handlers, meaning you can add snippets of Lua code to be run when specific things happen to that Frame. In our case, we defined the "OnEvent" script handler, which will be run every time an Event the frame has registered for fires.

The arguments passed to the script handler - which is always the case for all Event handlers, are "self" which refers to the Frame itself, "event" which is the name of the Event that fired, and the ellipsis "..." which represents all the remaining arguments, regardless of how few or how many they are.

We will be referring the various UI objects (like Frames) in WoW as "Widgets". You can check out all the Widget methods for each Widget type on the Widget API page on wowpedia. You can also study the various Widget Handlers, or script handlers for Widgets if you like, on the Widget Handlers page. If you haven't already, bookmark wowpedia's UI portal! It will be your number one resource for addon development. Soon you won't be needing me at all, you'll simply just find what you need there!

local arg1 = ...

What we do here is to assign the first returned value in the ellipsis to the local variable "arg1". We only want the first argument, because with the ADDON_LOADED Event, this argument is the name of the addon the Event fired for. You can check out the full listing of all the WoW Events and their return values over at wowpedia!

if (arg1 == addon) then


end

Here we're running a conditional statement. Meaning everything between the "if" and the corresponding "end", will only be run if the conditional following the "if" statement is true. The "==" operator in Lua is used to compare 2 values. We previously stored the name of the addon the ADDON_LOADED Event fired for in the "arg1" variable. At the start of our addon, we stored the name of our addon in the "addon" variable. So what we're doing is to simply compare those 2 names, to see if it indeed was our addon the ADDON_LOADED Event fired for.

local version, build, date, tocversion = GetBuildInfo()

The GetBuildInfo() function allows you retrieve various information about the game client version. You can read the full description of this function over at wowpedia.

print("Your game client is running WoW version " .. version .. ", build " .. build .. " - " .. date)

The command "print" simply displays the text you pass to it in the main chat window inside of WoW. Only you can see this text, it's not sent to anybody else. In Lua, quotes are used to encompass strings, meaning normal text. You can tie various strings together with the concatenation operator, which in Lua is written as 2 dots. So we basically just print to the screen the info we retrieved in the previous statement, and the result will be what we saw in the screenshot.

self:UnregisterEvent("ADDON_LOADED")

This last unregisters the Event "ADDON_LOADED" from our Frame, and it will no longer listen for it. We're doing this because we don't need it anymore. Neither will the Event fire again for our addon, nor would we wish to print the version info to the screen again even if it did. So we unregister the Event from our Frame, to sort of clean the room before we leave.

You might notice that we use "self:UnregisterEvent", while we registered the Event using "frame:RegisterEvent". We could have used the "frame" variable to unregister the Event instead of the "self" variable if we wanted to, but as the frame reference is passed to the function through the "self" variable, "self" will be faster and better to use.

Think of it this way; every time you start a new loop, or a new conditional statement, or a new function, you create a new namespace. You nest. When you look up a variable that isn't local to the current namespace, the client has to search all the variables of the parent namespace to find it, and if it's not there, it has to search the parent of that again, and so on. This slows down the addon, as the farther out the client has to go to find a variable, the more time it spends doing it. This is one of the main reasons you should always use local variables, because they are simply faster. We'll be covering this in detail at a much later stage in the tutorial, when we talk about optimizing your code. For now, just now that "the more local it is, the better"!

▲ Go back to the top

Last words

So that's it for now. Hopefully you managed to set up a working addon, and get a slight idea of how the addon environment in WoW works. In the upcoming parts of our tutorial, we will be taking a closer look at how Frames work, and also get a basic understanding of the Lua programming language. If you want to "skip ahead", feel free to check out the Lua Tutorial over at CoronaDocs. It's awesome. Boring, but awesome. The faster you learn to master Lua, the faster you can start focusing on all the cool things WoW addons alone can do instead!

Until next time, cheerio!

▲ Go back to the top

Read More
Saturday, February 1, 2014 - 18:00

Welcome to part 4 of my addon creation tutorial. We'll be taking a look at the addon loading process this time, to get an understanding of how and when the addon is loaded, and when various information will become available to it. Ready?

Table of Contents

  1. Events
  2. Addon Loading Process
    1. Order of events fired during loading
      1. ADDON_LOADED
      2. SAVED_VARIABLES_TOO_LARGE
      3. SPELLS_CHANGED
      4. PLAYER_LOGIN
      5. PLAYER_ENTERING_WORLD
    2. Load On Demand behavior

Events

Before we start, it is important that you understand what an Event in World of Warcraft is. In short Events are messages sent by the WoW client to the user interface mostly in reaction to things occurring in the game world. Events are how the addon know what's going on. To understand the loading process, you need to know when various Events fire off, and what this means for the user interface.

We'll be looking at how to read and respond to the Events at a later stage in the tutorial, for now you just need to know they exist, and what they mean.

Addon Loading Process

  1. When the client first starts, Interface\AddOns directory is scanned, and a list of files and addon dependencies are built.
  2. Addon code is executed after the player selects a character and presses 'Enter World'.
  3. After all addon code has been loaded, the saved variables are executed. The event ADDON_LOADED fires after each addon's saved variables have been loaded.

Order of events fired during loading

After the addon code has been loaded, the loading process can be followed by registering for various events, listed here in order of firing. This information is very important because many addons rely on information that is not available when addons first load, such as buffs, spells, talents, quests, pets, pvp information, etc. By monitoring one of the following events with a blank frame, you can trigger the appropriate "OnEvent" handler and execute code that is dependent on that information as soon as it is available.

  1. ADDON_LOADED
    • This event fires whenever an addon has finished loading and the SavedVariables for that addon have been loaded from their file.
  2. SAVED_VARIABLES_TOO_LARGE (Error Condition)
    • Generally will not fire. This event indicates an error state where the SavedVariables of an addon failed to load due to an out-of-memory error. (The old error state was a client crash!)
    • The upshot here is that your addon could be in a state where the saved variables did not load. This event's purpose is to indicate that you are in this error state.
    • If you are in this state your addon's SavedVariables will NOT be saved back to disk at the next logout. This was done with the reasoning that it will prevent valid data from accidentally being wiped by defaults.
    • It is possible for an addon's account wide SavedVariables to load, but for the character specific SavedVariables to fail, or vice versa. There is no way to detect the difference between no variables loaded and some.
  3. SPELLS_CHANGED
    • This event fires shortly before the PLAYER_LOGIN event and signals that information on the user's spells has been loaded and is available to the UI.
  4. PLAYER_LOGIN
    • This event fires immediately before PLAYER_ENTERING_WORLD.
    • Most information about the game world should now be available to the UI.
    • All sizing and positioning of frames is supposed to be completed before this event fires.
    • Addons that want to do one-time initialization procedures once the player has "entered the world" should use this event instead of PLAYER_ENTERING_WORLD.
  5. PLAYER_ENTERING_WORLD
    • This event fires immediately after PLAYER_LOGIN
    • Most information about the game world should now be available to the UI. If this is an interface reload rather than a fresh log in, talent information should also be available.
    • All sizing and positioning of frames is supposed to be completed before this event fires.
    • This event also fires whenever the player enters/leaves an instance and generally whenever the player sees a loading screen

Since Patch 3.0.2, VARIABLES_LOADED has not been a reliable part of the addon loading process. It is now fired only in response to CVars, Keybindings and other associated "Blizzard" variables being loaded, and may therefore be delayed until after PLAYER_ENTERING_WORLD. The event may still be useful to override positioning data stored in layout-cache.txt.

Somewhere around Patch 5.4.0, PLAYER_ALIVE stopped being fired on login. It now only fires when a player is resurrected (before releasing spirit) or when a player releases spirit. Previously, PLAYER_ALIVE was used to by addons to signal that quest and talent information were available because it was the last event to fire (fired after PLAYER_ENTERING_WORLD), but this is no longer accurate.

Load On Demand behavior

Load on Demand addons cannot rely on most of the event sequence being fired for them; only ADDON_LOADED is a reliable indication that the saved variables for your LoD addon have been loaded.

Last words

That's it for this time. Even though you haven't written a single line of addon code yet, you should already begin to get an understanding of how the World of Warcraft addon environment works. By tracking the correct Events, you can make your addon respond to almost anything that happens in the game. If you like you can take a look at the full list of available Events over at wowpedia. Don't let the massive amount of Events scare you, as you don't need to remember them all. That's what we have wowpedia's UI portal for!

Next time we'll be creating our very first addon!

▲ Go back to the top

Read More
13:55

Greeings fellow UI lovers, and welcome to part 3 of my addon creation tutorial! This time we'll be taking a look at the format of the required TOC file. Let's get to it!

Table of Contents

  1. The TOC format
    1. Syntax
      1. Tags
      2. Comments
      3. Files
    2. Official tags
      1. Interface
      2. Title
      3. Notes
      4. Author
      5. Version
      6. RequiredDeps, Dependencies, or any word beginning with "Dep"
      7. OptionalDeps
      8. LoadOnDemand
      9. LoadWith
      10. LoadManagers
      11. SavedVariables
      12. SavedVariablesPerCharacter
      13. DefaultState
      14. Secure
  2. Custom/metadata tags
  3. Example TOC file

The TOC format

.toc (Table of Contents) files contain information about a particular addon (such as its name, description, saved variables, etc), as well as instructions on how the addon should be loaded by the client (for example, the order in which lua and xml files should be loaded). The file must be present, and have the same name (plus extension) as its parent folder for the addon to be recognized by the client.

While most other files are reread on every client reload and thus can be changed while the game is running, the .toc file is only read once during the initial startup process. This means that any changes to the .toc file require a full game restart to take effect.

TOC files mainly consist of three types of objects; tags, comments and file references. Each new line is considered a new object(or command, if you prefer to call them that). It is ok to include blank lines, as any extra whitespace is ignored.

Syntax

Tags

Tags are the bread and butter of a TOC file. They tell the game which client version they were designed for, whether or not they require another addon to be present, and many other things. The format is as follows:

## TagName: Value

Comments

It's possible to enter comments into TOC files. Comments are skipped by the client, but can be useful for development purposes, and sometimes for 3rd party service like CurseForge.

### This is a comment, which is skipped by the client

Files

Anything not starting with a hashtag, is considered a file. You can include directory names here, and the path is relative to the current folder. You can only load XML and Lua files from within the TOC file. No media files can be listed here, as media can only be loaded through Lua commands from within Lua or XML files.

libs/myLib.xml
Bindings.xml
main.lua

▲ Go back to the top

Official tags

Interface

Specifies which client interface version the addon was made for. If the value of this tag does not match the client interface version, the addon is loaded only if the "Load out of date addons" option is enabled. The fastest way to get the current build and interface version of WoW is by typing "/run print(GetBuildInfo())" without the quotes in any WoW chat window, followed by the Enter key. This tag is required.

## Interface: 50400

Title

The value of this tag is displayed in the AddOns list. Localized versions can be included by appending a hyphen followed by the client locale name; the client automatically chooses a localized version if one is available. The value may also contain UI escape sequences, such as for example colors.

## Title: Waiting for Lars ## Title-frFR: En attendant Lars

Notes

Addon description that appears when the user hovers over the addon entry in the addons list. Like Title, this tag can be localized by appending a hyphen followed by locale name, and contain UI escape sequences.

Author

The AddOn author's name.

Version

The AddOn version. Some automatic updating tools may prefer that this string begins with a numeric version number, but you can enter pretty much anything you like.

RequiredDeps, Dependencies, or any word beginning with "Dep"

A comma-separated list of addon (directory) names that must be loaded before this addon can be loaded. If one or more are missing, the addon will not load at all.

OptionalDeps

A comma-separated list of addon (directory) names that should be loaded before this addon if they can be loaded. In this field you would typically put addons that when loaded affect the decisions made by your addon, or libraries that are embedded in your addon but also work as standalones.

LoadOnDemand

If this value of this tag is "1", the addon is not loaded when the user first logs in, but can be loaded by another addon at a later point. This can be used to avoid loading situational addons.

LoadWith

A comma-separated list of addon (directory) names that, when loaded, will cause the client to load this LoadOnDemand addon as well. Unlike RequiredDeps, this option also requires the listed addons to be LoadOnDemand. An example would be if you created an addon that required one of Blizzard's LoadOnDemand addons like the achievement UI to be loaded first. You would then use "Blizzard_AchievementUI " as the value for this field.

LoadManagers

A comma-separated list of addon (directory) names; if no addons on this list are loaded, the client will load your addon when the user logs in; if at least one addon on this list is loaded, your addon is treated as LoadOnDemand and the loading of it left to the specified LoadManager(s).

SavedVariables

A comma-separated list of variable names in the global environment that will be saved to disk when the client exits, and placed back into the global environment when your addon is loaded; the variables are not available before the ADDON_LOADED event fires for your addon. This is the only way to save anything between sessions, as addons are unable to write to the disc directly. Use caution when choosing variable names, as these are global and available to all other addons. Avoid simple or common names. I usually use the addon (directory) name with a "_DB" suffix to it.

SavedVariablesPerCharacter

A comma-separated list of variable names in the global environment that will be saved to disk when the client exits, and placed back into the global environment when your addon is loaded for a particular character. Note that PerCharacter saved variables are only loaded for the character for which they were saved.

DefaultState

This can have either the value "enabled"(default) or "disabled". If you set this to "disabled", your addon will be deactived/unchecked in the addon listing when first installed, and the user has to manually enable it. Addon packages like Deadly Boss Mods often use this for optional modules that most users don't want enabled by default.

Secure

If its value is set to 1, and it's an addon digitally signed by Blizzard, it's code is considered "secure". What this means is that it has unrestricted access any and all parts of the UI even during combat, which is something 3rd party addons can't. This option is only available to Blizzard addons, and not something you can enable for your own. We're listing it here only for reference purposes, as you're likely to come across it when studying the Blizzard interface code later on.

▲ Go back to the top

Custom/metadata tags

It is possible for addons to query values of any tags with a "X-" prefix. You can put pretty much anything you like here, though some apps like the Curse Client use the metadata tags to store extra information about each addon, like a list of embedded libraries, or the internal curse package version of the addon. All addons downloaded through either curse.com or the Curse Client includes custom tags.

Custom tags, and some official tags like "Title", "Notes" and "Version" can be retrieved from within the addons with the GetAddOnMetadata() command:

local value = GetAddOnMetadata("addon", "field")

In this example "addon" refers to the directory name of the addon, and "field" to the tagname you wish to read. The value is returned as a string.

▲ Go back to the top

Example TOC file

Here's the (more or less) current TOC file for the addon gUI3, as of WoW patch 5.4.2:

## Interface: 50400
## Name: gUI-v3
## Title: |cFFFF7D0Ag|r|cFFFFBB00UI|r|cFFFFFFFF3|r |cFF00FF96MoP|r
## Notes: Minimalistic UI replacement.
## Author: Lars Norberg
## Version: 1.0
## DefaultState: Enabled
## SavedVariables: gUI3_DB
## OptionalDeps: SharedMedia, LibSharedMedia-3.0, Bartender4, Dominos, RazerAnansi, RazerNaga, ElkBuffBars, SatrinaBuffFrame, AdiBags, ArkInventory, Bagnon, Baggins, BaudBag, cargBags_Nivaya, cargBags_Simplicity, Combuctor, famBags, OneBag3, OneBank3, TBag, Quartz, Chatter, Prat-3.0, ag_UnitFrames, PitBull4, ShadowedUnitFrames, XPerl, Aloft, DocsUI_Nameplates, Healium, Healers-Have-To-Die, Headline, knameplates, Kui_Nameplates, mNameplates, StarTip, TidyPlates, TinyTip, TipTac, AuctionLite, Auc-Advanced, Recount, Postal, DBM-Core, Omen, Skada, MikScrollingBattleText, Carbonite
## X-eMail: goldpaw@friendlydruid.com
## X-Website: http://www.friendlydruid.com

gUI-v3.xml

From this you should be able to see that gUI3 requires WoW 5.4.x to function, that it saves all its settings in a global file, and that it has a lot of optional dependencies that all will be loaded prior to gUI3. You should also see from this file that the TOC file only loads a single file, namely the gUI-v3.xml file. In reality gUI3 loads close to a hundred files, but they are all listed in various XML files, not the TOC file. More on that later!

I've also used custom tags here, listing a contact email and website. As mentioned these have no impact on WoW itself, and the client completely ignores them. They can however be retrieved with GetAddOnMetaData() from within the addon, and I like to have them there as reference for other addon authors.

The title/display name of the addon also uses color coding. Not that you'll be using this right now, but here's the format of that:

|caarrggbb...text...|r

In text printed to the screen in WoW, the | symbol indicates an escape sequence. What this means is that it "escapes" from the written text to perform one or more commands to modify the output. The |c escape sequence in WoW refers to a color modification. What follows is the alpha value, and the red, green and blue components of the color code. These are all hexadecimal values, so a value of FF0000FF would mean a fully opaque pure blue color, and all the text between the color code and the closing |r sequence would then be blue. You can't change the alpha value of text displayed in the addon listing though, so regardless of what you type in the alpha field, the text will be displayed fully opaque, as if the value was FF.

On a slight sidenote, the orange color used by both the "g" in the gUI text and the gUI logo, is the color #FF7D0A, which is the orange Blizzard uses for the Druid class color. And legendary quality items. So I didn't choose it on random!

Last words

That's it for this time. Next we'll be looking at the addon loading process, to get an understanding of how and when the addons are loaded, and when various info becomes available to them. Stay tuned, and until then, cheerio!

▲ Go back to the top

Read More
Friday, January 31, 2014 - 09:18

Welcome to the 2nd part of my WoW addon creation tutorial! Today we'll be looking at the file- and folder structure of WoW addons, as well as taking a look at the supported file- and media formats.

Table of Contents

  1. Addon file- and folder structure
  2. Supported file formats
    1. Table of Contents (.toc)
    2. UI definitions (.xml)
    3. Addon code (.lua)
    4. Images (.blp, .tga)
    5. Fonts (.ttf)
    6. Sounds (.mp3, .ogg)
      1. Can I make an in-game music player?

Addon file- and folder structure

Addons live inside the Interface\AddOns directory found within your World of Warcraft installation. This directory isn't created when the game is initially installed, but rather the first time you log into World of Warcraft on a computer. If you're unsure where your game installation is, the most common placements are:

Windows game client path:

  • either: C:\Program Files\World of Warcraft\Interface\AddOns
  • or: C:\users\public\games\World of Warcraft\Interface\AddOns (since Windows Vista)

Mac game client path:

  • /Applications/World of Warcraft/Interface/AddOns

Each addon has its own folder within the Addons directory, and the name of the addon's folder represents the internal name of the addon. If you created a folder named "MyAddon", the name WoW recognized your addon by would then be "MyAddon". This is case sensitive. In order to be recognized by the game client, an addon requires a folder, and a .toc file with the exact same name as the folder (plus the .toc extension) placed directly inside the addon folder.

Apart from this, you are free to place any number of subdirectiories and files within your addon folder.

▲ Go back to the top

Supported file formats

World of Warcraft addons accept a number of file formats. Addons can include fonts, images, sounds, defined UI elements through XML files, and Lua code. You can put whatever else you like into an addon folder, like pdf files and executables, but the game will ignore them and all other unsupported files completely. No executable will ever be run by WoW, and thus all addons are by definition "safe".

WoW only scans the AddOns directory once during startup, and any files not present then won't be recognized by the game. To discover new files, you need to completely restart the game. This is important to keep in mind when developing addons, and even when updating the addons you use. If you don't completely exit the game when updating addons, any new directories and files won't be discovered at all.

Changes to existing media-, Lua and XML files are however registered on every reload of the user interface. Keep that in mind when creating your own addons or modifying existing ones later on. Reloading is our most precious tool!

Table of Contents (.toc)

.toc (Table of Contents) files contain information about a particular addon (such as its name, description, saved variables, etc), as well as instructions on how the addon should be loaded by the client (for example, the order in which lua and xml files should be loaded). The file must be present, and have the same name (plus extension) as its parent folder for the addon to be recognized by the client.

While most other files are reread on every client reload and thus can be changed while the game is running, the .toc file is only read once during the initial startup process. This means that any changes to the .toc file require a full game restart to take effect.

We'll go deeper into the contents and format of the .toc file next time.

UI definitions (.xml)

All UI elements like graphic, textures, animations, fonts and sounds can be defined in special XML files. Any keybinds used by your addon is also defined using a special XML file called Bindings.xml, which must be place in the root of your addon directory. XML files can also be used to load other XML- or Lua files, and they can also include Lua code directly. XML files are strictly speaking not required, but they do hold certain benefits, like the ability to create templates.

We'll be covering XML files thoroughly at a later stage, but not today.

Addon code (.lua)

Do you remember these?

Most of the addon code run by WoW is stored in Lua files with the .lua extension. "Lua" (pronounced LOO-ah) means "Moon" in Portuguese. As such, it is neither an acronym nor an abbreviation, but a noun. More specifically, "Lua" is a name, the name of the Earth's moon and the name of the language. Like most names, it should be written in lower case with an initial capital, that is, "Lua". Not "LUA" in other words, as that's just wrong.

Lua is a powerful, fast, lightweight, embeddable scripting language. The entire Lua engine only occupies about 250KiB compressed and 960KiB uncompressed. This is so small that it would actually fit on an old 3.5" floppy disk, making it ideal for embedding in games and applications. Lua is used for UI scripting in several known programs and games such as Adobe Photoshop Lightroom and Warhammer Online and Rift.

Images (.blp, .tga)

World of Warcraft accept images in both Blizzard's own .blp-format, as well as standard .tga files. Transparency is supported. There are no advantages to using the .blp format in your own images, so I suggest you simply steer clear of this.

Even though WoW supports transparency in TGA images, actually creating this can be quite the hassle if done incorrectly. When exporting an image to TGA format from a program like Photoshop, the transparency is removed. You have to jump through hoops to make this work, so I found it much easier to simply export them as PNG, then use XnView to convert them to TGA with transparency later. XnView can also be used to view existing blp images, which is quite useful when browsing through the existing blizzard artwork.

The Internet is packed with cool images, art and illustrations. But just because you can freely download something doesn't mean you can freely redistribute it. Whenever you upload an addon to the Internet, it suddenly becomes a commercial product, regardless of how free it is. Make sure you only use public domain images, or images that have a licence that allows unlimited commercial redistribution.

Fonts (.ttf)

Pretty much any TrueType font in the world can be used in World of Warcraft. As in all other things though, make sure that you're actually allowed to use the font in your addon. Remember that even if you're not making any money from this, an addon is still regarded a commercial product, and anything you distribute along with the addon is therefore distributed commercially. So you can't simply include any fonts you like.

There are several pages on the web dedicated to font hosting. My personal favorite is dafont.com, as its selection is very big and diverse. As of writing this, the dafont database includes no less than a whopping 22881 fonts! It also allows you to search by both genre and licence type, the latter of great interest to somebody like me who uploads addons on a regular basis. Unless you're willing to pay for a commercial license that allows unlimited redistribution, the fonts you should be looking for are those listed as "Public Domain", and nothing but.

Sounds (.mp3, .ogg)

World of Warcraft accepts music and sound effects in either ogg or mp3 format. Just don't forget about the copyright laws, folks. I know this is probably starting to annoy you by now, but I just can't stress this enough. I know in these days of sharing most people don't think twice about what they share with friends or download from the Internet, since it really isn't that big a deal. But when it comes to commercial redistribution, sharing the wrong thing is a crime on a whole other level than downloading an mp3 for personal use. So make sure you are allowed to include what you include!

Can I make an in-game music player?

Even though World of Warcraft allows you to play mp3 sounds, this does not mean you can create a media player from within the game. There are several reasons for this.

First off, you can't pause music. You can only choose between playing, and not playing it. Also, as mentioned earlier addons can only access files from within the WoW folders, and they only recognize files that are present at the game startup. Also, you can't request a directory listing, you need to know the name and location of the file you wish to access. So if you feel like manually entering the names of the 5000+ songs in your mp3 library, go ahead. But I recommend that you simply... don't.

Last words

With this you should have a pretty good knowledge of the file- and folder structure in World of Warcraft addons. Next time we'll be diving into the TOC format, and learn how to properly set it up for your addon to work. Until then, cheerio!

▲ Go back to the top

Read More