Shrinking a macro

What are macros?
Macros are user-defined shortcuts that automates certain actions in World of Warcraft. For more information, see HOWTO:_Make_a_Macro

Who is this HOWTO for?
This HOWTO is for people that want to know how to shrink, or compress, their macros so they can have more space for extra actions in them.

It is aimed at the beginning macro-maker.

Introduction
This howto will teach you certain techniques that will allow you to make macros take up less characters. This is mostly useful if you want to have enough space so that you can modify the macros further.

Note that these techniques tend to make the macros less easy to understand for a human being.

Important info
Always save your original macro.

Always test your macro after modifying with each technique so you haven't forgotten anything.

You can test for simple "lua-compatibility" (that is, no missing paranthesis, end:s and so on) by saving the macro to a file then using the lua compiler on the file. The compilers can be found at this nice wiki page:

Basic techniques
These techniques are made for two purposes:
 * Decreasing character-size of macros
 * Preserving functionality of original macro

Note that there often are ways to make something in a different way, which may turn out to use less characters than the current way of doing this. This often requires Lua and WoW API knowledge, though, and as such is beyond the scope of this HOWTO.

Slash commands
/run and /script are the same command, so use /run instead of /script. Duh. :) Only 3 bytes saved here, but since it's 3 bytes in every scripted macro...

Macros are read by the computer
Because macros should - in the end - only be read by the computer, you can leave out a lot.

First up is the semi-colon, ;. It can be completely left out. However, you should leave a space between most "words".

Second to the executions is the  (newline) character. Yes, each new line takes up valuable space. Write it all in one big line. The Computer does not care if it looks like crap (you will, though).

You can remove spaces around operators, such as -, +, /, *, >, <, >=, <=, =, ~= and ==. while a == b may look prettier than a==b, they both work the same way. While it may not be obvious at first, parentheses, quotes, etc. are also technically operators. For example:

/run CastSpellByName("Charge") SpellStopCasting CastShapeshiftForm(3)

can be shortened to (among other optimizations):

/run CastSpellByName("Charge")SpellStopCastingCastShapeshiftForm(3)

Several /script commands in one macro
Just put it all in one big line. Do it for the Widow's Son. Once again, the amount of readability will decrease, but you'll shave off some characters.

Make it small, not good-looking
Do not use paranthesis in flow-control statements (if, for, while...) unless totally necessary.

Once again, it may look pretty:

/script if ( qwerty == yuiop ) then asdf; end

... but it can be made to be small: /run if qwerty==yuiop then asdfend

Spells that always are cast
Do not use CastSpellByName for these ones. If the spell is always cast, use /cast instead. Less bytes, and even easier to understand. :) Plus, it really is the same. No, really, it is!

/script CastSpellByName("Volley");

becomes

/cast Volley

In fact, this is one of the few techniques that actually makes stuff smaller without it being less readable.


 * Note: CastSpellByName is PROTECTED (since patch 2.0.1), and can only be called from Blizzard code. Thus, having to use /cast is inevitable.

Advanced techniques
These can be a bit harder to apply.

Different conditionals causing the same result
If you see that a macro does the same thing dependent on several conditions, you can bunch them together.

Basically, this means that if you see:

if A then X elseif B then X elseif C then X elseif D then Y end

you can compress it to the following form

if A or B or C then X elseif D then Y end

You might also be able to use slightly different conditions to achieve the same result. For example a macro with 4 different commands based on modifier keys:

/use [modifier:shift,modifier:alt]act4;[modifier:alt]act3;[modifier]act2;act1

becomes

/use [nomodifier]act1;[nomodifier:alt]act2;[nomodifier:shift]act3;act4

Using shorter conditionals
You can shorten following the conditionals since 2.3:

modifier -> mod, button -> btn, actionbar -> bar, equipped -> worn, stance -> form

so the above becomes

/use [nomod]act1;[nomod:alt]act2;[nomod:shift]act3;act4

And the original was actually just 2 characters longer

/use [mod:shift,mod:alt]act4;[mod:alt]act3;[mod]act2;act1

Items
Use item IDs instead of Item names.

/use Reins of the Veridian Netherwing Drake

is a lot longer than

/use item:32861

Making aliases
If the macro uses a long name for something you can make an alias for it.

For instance check out this macro: /script if not UnitExists("pet") then CastSpellByName("Revive Pet"); else if UnitIsDead("pet") then CastSpellByName("Revive Pet");else CastSpellByName("Mend Pet");end;end

Shrunk with this method alone: /script c=CastSpellByName if not UnitExists("pet") then c("Revive Pet"); else if UnitIsDead("pet") then c("Revive Pet");else c("Mend Pet");end;end

Quite a difference. We'll see how this macro can be shrunk even further.

Another example from my mage "Eat,Drink and Be Mary" macro /script if ( UnitHealthMax("player") - UnitHealth("player") > 50 ) then UseContainerItem(0, 1); end if ( UnitManaMax("player") - UnitMana("player") > 100 ) then UseContainerItem(0, 2); end

/script p="player" if ( UnitHealthMax(p) - UnitHealth(p) > 50 ) then UseContainerItem(0, 1); end if ( UnitManaMax(p) - UnitMana(p) > 100 ) then UseContainerItem(0, 2); end

Substituting and/or for if-then
If you have an if-then expression where both branches do the same thing with slightly different values, consider getting rid of the if-then, and using a condition expression (known to C programmers as a ternary operator). This is based on the Lua idiom that a and b or c will evaluate to b, if a is anything but nil or false. Otherwise, the expression will evaluate to c. We can extend this to cond1 and val1 or cond2 and val2 or ... condN and valN or valLast

For instance check out this macro: /script if not UnitExists("pet") then CastSpellByName("Revive Pet"); else if UnitIsDead("pet") then CastSpellByName("Revive Pet");else CastSpellByName("Mend Pet");end;end

Shrunk with this method alone: /script c=CastSpellByName if not UnitExists("pet") then c("Revive Pet"); else if UnitIsDead("pet") then c("Revive Pet");else c("Mend Pet");end;end

Examples
Examples of macros being shrunk down using the techniques above.

Hunter Macros
Let's look at a few examples (originally from the LazyFAQ / Hunter Macro thread):

This macro does the following : if your pet is dead, Revive Pet. Otherwise, if it's alive, Mend Pet. /script if not UnitExists("pet") then CastSpellByName("Revive Pet"); else if UnitIsDead("pet") then CastSpellByName("Revive Pet");else CastSpellByName("Mend Pet");end;end

Shrunk version: /run CastSpellByName((not UnitExsists("pet")or UnitIsDead("pet"))and "Revive Pet" or "Mend Pet")

Feed Pet macro - it checks if you're in combat or not. Then it looks for the item in Slot Y in Bag No. X and feeds your pet the food. If there's nothing there, the bag will open prompting for attention. Replace X = Your Bag slot, starting with "0", reads from Right to Left. Replace Y = Your Item Slot in your bag, starting with "1", reads from Left to Right, top to bottom row.

/script if (not PlayerFrame.inCombat) then if (not GetContainerItemLink(X,Y)) then OpenBag(X); else CastSpellByName("Feed Pet"); PickupContainerItem(X,Y); end end

Shrunk: /run if not UnitAffectingCombat("player") then if not GetContainerItemLink(X,Y) then OpenBag(X) else CastSpellByName("Feed Pet") PickupContainerItem(X,Y) end end

Note that not PlayerFrame.inCombat is not a totally sure way of checking if you are in combat anymore. Use not UnitAffectingCombat("player") instead.

Generic macros
From my mage "Eat,Drink and Be Mary" macro /script if ( UnitHealthMax("player") - UnitHealth("player") > 50 ) then UseContainerItem(0, 1); end if ( UnitManaMax("player") - UnitMana("player") > 100 ) then UseContainerItem(0, 2); end

Shrunk: /run p="player" if UnitHealthMax(p)-UnitHealth(p)>50 then UseContainerItem(0,1) end if UnitManaMax(p)-UnitMana(p)>100 then UseContainerItem(0,2) end

In closing
These techniques are meant to work as patterns for macros. Please add your own techniques to the list!

Remember that, if you post macros, most people who use them will have the 255 character limit. Consider throwing in the original macro and adding the shrunk version.

Most freely available macros can be shrunk. Note that there is no need to shrink a macro unless you want to expand on it and if you have the built-in limit of 255 characters. I personally find it a challenge to compress and shrink macros - but I'm a weird person. Sarf