Best Practices 1323
The WoW Environment
Thelast part of this appendix deals speciﬁcallywith constructs andprocedures
unique to World of Warcraft.
Use What You’re Given
By now, it should be second nature to look for APIs and widget methods to
help with your day-to-day tasks. However, many other built-in features go
neglected.For instance, authors often write their own functions to convert the
to indicate cross-realm
players. Granted, this is a rather trivial task, but WoW already provides such
at the end of
Obviously, we do not expect you to familiarize yourself with the entirety
of FrameXML code as you’re starting out, but it is always a good idea to
look in ﬁles that may be related to your addon, both to see how things are
done in the default UI and to ﬁnd functions to take advantage of yourself. For
example, if you are writing an alternative quest frame, you should look over
before you begin work on your addon.
from the beginning of this appendix could actually be
improved slightly. Rather than
for bag = 0, 4 do
is a prime
example of a magic number, you can deﬁne a constant for the number
of bags. However, Blizzard has saved you the trouble. Near the top of
is the constant
sents the number of bags besides the backpack. Using the Blizzard-deﬁned
constant adds a bit of future-prooﬁng to your code. If they ever increase the
numberofbags a playercan carry,theywill bump
to the new
count and your function will be instantly compatible.
Localize with Global Strings
Virtually every display string in the UI is stored in a constant in
.This ﬁle is translated to every language WoW supports.
By using the constants in this ﬁle for various aspects of your addon, you will
be automatically localizing certain parts of it, which is of great beneﬁt to your
Error messages, button text, combat log strings, and many others are there
enough to recognize. You will also see strings for the various races, genders,
classes, and other commonly used terms. Whenever you are looking into
localization for your addon, open
and do a preliminary
search for the terms you want.
Even ifyoudonotseethe exactphrase you’relookingfor,thesearchmaystill
help.Ifyouare trying to do localization yourself, youmaybe abletoﬁgure out
1324 Part V
the basic structure of the phrase in the target language but not how some par-
ticular termtranslates.You can ﬁnd
from other locales on
some addon sites and compare the phrases to come up with the missing term.
Avoid Deprecated Systems
The World of Warcraft UI code has gone through many evolutionary and
revolutionary changes as new needs for the game and from the addon com-
munity have come to light. New systems are constantly being added and
tweaked to take better advantage of Lua design patterns, improve efﬁciency,
and implement new game features.
Unfortunately, the time invested in the older systems is signiﬁcant enough
that many of them are still around in some form or another. Through the
patch cycle, though, the default UI is being slowly reworked to use the newer
methods and, atsome pointin time,the old ways may no longerbe supported.
Throughout this book we have purposefully omitted coverage of these past
practices. If you use the code for the default UI or other addons as research
material for your own addon, translate any usage of the constructs discussed
in the following sections into the newer method.
Rather than listing all deprecated systems in this section, speciﬁc events,
APIs, and so forth that should no longer be used are marked as deprecated in their
reference entries (see Part IV).
Global Widget Handler Arguments
The widget handler system you saw in Chapter 12 is new as of patch 2.0.
Instead of calling your handler with a
parameter and other related data
,and so on), the old system
useda global variable called
and several global argumentvariables(
,and so on).
There were a few problems with this approach. Using global variables for a
parameterized systemdoes notmake muchsense conceptually,nottomention
their impact on performance. Also, the generic
variables go against the
very ﬁrst pointer in this appendix. The only way for you to know the meaning
of the argument when reading old code is to look at a reference for the given
handler or hope you can infer its meaning from what the code does with it.
Following are two somewhat useless functions to illustrate the difference.
If you use
to assign them to an
script, they will
if arg3 == “LeftButton“ then
this.link = arg1
print(“You clicked on “..arg2)
Best Practices 1325
function MyAddon_OnHyperlinkClick(self, link, text, button)
if button == “LeftButton“ then
self.link = link
print(“You clicked on “..text)
As you can see,
.With the exception of
will always match the parameter list
of the given handler. In this way, you can use the widget handler reference
in Chapter 31 to determine the meanings of the global arguments in any
legacy code. The only difference with
always had its
, in this case, correspond to the parameters passed
bag and slot Attributes on item Type Action Buttons
Another change in 2.1 is the simpliﬁcation of secure action buttons with a
. Previously, the
attribute could only be
used to activate an item by name. To use an item in your inventory would
attribute; to use an item in your bags required
attributes. Now the
attribute works the same way as the
macro command. It accepts an itemname, item ID (in the form
slot number, or bag and slot numbers separated by a space (for example,
Again, for backward compatibility, the
still supported. However, you should no longer use them; as a comment in
says, ‘‘Backward compatibility code, depre-
cated but still handled for now.’’ [Emphasis mine.]
Avoiding Common Mistakes
Addon authors can make dozens of common mistakes as they develop their
addons. Many of them have been covered throughout the book, but the
following deserve to be mentioned here, as well.
Adding Files While WoW Is Running
When World of Warcraft loads, it scans the ﬁle system and builds a table of
ﬁles that can be loaded during that session. If you add ﬁles while the game is
open, they won’t be part of that table and cannot be loaded or recognized by
the game. A related common mistake is adding a new ﬁle to your addon and
the Table of Contents ﬁle without fully exiting the game.
If you add ﬁles to the ﬁle system, make sure that you fully exit and restart
the game so that the changes will be fully registered.
1326 Part V
Entering | into the Chat Edit Box
Because World of Warcraft uses the
character in its color codes and
hyperlinks, any that are entered in the edit box are automatically escaped
to a double
.This can be problematic when running Lua scripts with the
commands. You can substitute thesequence
the actual character to get around this limitation.
When youcreate a frame in youraddon youexpectit tobe visible. If you can’t
ﬁnd your frame, it may be missing due to not meeting one of the following
Theframemusthave some visualcomponent,such asa texture,backdrop,
or text element.
Theframemustnotbe set ashidden in theXMLﬁle,orthe frame’s
method must have been called to explicitly show the frame.
Each frame that is aparentofthe frame must alsobeshown.Thisincludes
the frame’s parent, the parent’s parent, and so on.
The frame mustbe anchoredsomewhere within the bounds ofthe screen.
It’s easy to spend time digging through your code only to ﬁnd later that
you’ve forgotten to place the frame on the screen.
When working on XML,therearetwoplaces tocheck to ensure theﬁleis being
parsed and validatedproperly:
Loadtheﬁleinsomeprogramthatcanindicatethatthe ﬁleis well-formed.
This could include most web browsers or a more complex XML edi-
ﬁle to ensure there weren’t any errors
parsing the ﬁle.
Not Checking API Returns
There are times when the Blizzard API functions may return something
other than what you’d expect. For example, there’s a small period of time
when you’d expect a class name to be
returned. If you use these function returns in some othercomputation, such as
indexing a table or calling another function, you may get an error somewhere
along the line.
Best Practices 1327
In many cases, you can ﬁx the problem by supplying default values in the
following way or by throwing an explicit error with the
local class = UnitClass(unit) or “Warrior“
Even if the class is wrong, you can be sure you won’t have an unexpected
Requesting Data Before PLAYER_LOGIN
As stated in the earlier chapters, a number of functions don’t return the
correct results until the
event has ﬁred. This can be remedied
by delaying the call until that point, but you should be aware when getting
unexpected results that the information may not be available in the client at
Conﬂicting or Existing Anchor Points
Each frame can have multiple anchor points that help deﬁne the place-
ment or size of the frame. When adjusting anchor points, make certain that
you’ve cleared any that should no longer be set. When in doubt, run the
method to ensure that a frame has no anchors before
adding your own anchor points.
Documents you may be interested
Documents you may be interested