[WoW] Tracking Buff Power With WeakAuras2 Progress Bars


NOTE: this was written in 2015, so it's probably out of date now.


Several classes in World of Warcraft have a buff or debuff they can apply, of which it would be useful to know the power. For example, fire mages have their Ignite debuff, which determines how much damage Combustion will do when cast, so it's important to keep track of the current Ignite damage in order to make best use of Combustion.

Possibly there are dedicated addons for tracking this, but I'd already done some experimenting with WeakAuras2 anyway on my blood spec death knight, to track Blood Shield, so I decided to make an Ignite tracker using that addon.

Note: This involves some quite advanced use of WeakAuras, so I'll try to keep each step simple, and explain what's going on. I'll also be skipping most of the simpler stuff, primarily what's on the Display tab.

TL;DR

If you just want the WeakAuras2 import string for the Ignite bar, here it is:

dyKsuaGivXLePKrrIofP0SaHBHiSlPu1WuvoMuYYifpJeMMu01ejBdK8neyCisNtvQwNuQ08qOs3dG2NiL6GsPSqqkpeKQyIikxer0gfP6JGuLojcALaAMiuXnbPYoLe)eHQgkiv1srO8uHPc0vbWxfPqgRuQyUiK2RYFrunyQoSOwSQKhdQjlIltSzj1NjPrlfonLETQuMTuDBs1UP43Q0WvvTCKEUkMo01Ly7ssFxKIgpcX5brRxKcUVifQ9J61AGlYdC4IZcnT)R9V3(3xOVizrYaxqeIVU(i4sNusHQPgfq9obkuObkfnvSAs0KGfqs811hbx6KivkcGsX3xZuKcfbAAPi1QjrZMlosVg6FTgCb0iEqqIh6ioKmDWfur1EnGq(lluP3Y)ctrhKAvvf6zvATWMSGqvJfLf9BozGlO3UmWf6LoAh4WHlWCxm4axOx6ODGdhUGMHLbUqV0r7ahoC4cHi)ztIKmOnCb8axLwdCHf(A2Rf1xdMEpREwq8aasCiScjx8ktHEU9lDGRIMLobqP5DO0qauFn)AL69VwRMePAoCr)Mtg4cm3fdoWf6LoAh4WHlG75ZzGlowJAxwaDTb9sYHlkhHC4E(Cg0wqZWYaxOx6ODGdhUOCeYp)c8G2IZVapWfhRrTlRIMHlkhHC4R(RmoOTGE7YaxOx6ODGdhoCbvuTxdiK)YICHMFLPlqHiyHklsNEp4cuicM(1GlIBHclShzZHDOp9UOyqQvvvOdCbC5Gx9f1fdmAVg2vQLbYo7SZE)cN7SNzhq2bWyrYKxL6ALpyMQk4deS)qOQXIYJwgi7SZo7ublud7z2beq2n2odumjdxKyp)9mKGcrqIJuJlypTmlYgREgTxZaxuBn2tJbU4NkhbxuNtKfiK)YIFQCeC4Wfi1QQk0bUaH8xwaxo4vFbC5GxDYBytKfOvxswaxo4vNCeYFzXbZy5SqQkg8SaGkecsEBaqS2waxo4vNScnJ2RzrDXaJ2RrPwgi7SZo79lCUZE1CViSdi7hPlWOYwPGGDamwKm5vPUw5dMPQc(ab7peQASO8Ovl7xk7Fmq2zND2PcwOg2RM7fbc2j977dc2rAryGIjzbC5Gx9kzDzrDXaJ2RrPwgi7SZo79lCUZo8vxphYp7aYEDXaJ2RHDLv1YazND2zND2zN9(fo3z)WoGSJ3dsTgvLv1YazND2zND2zNDQGfQH9t7sLQc9ik12UQNYlLpktRK0kjTs0(aXtA1cIhTTlvQk0JOuB7QEkVu(WPXq8ab7ppAzGSZo7SlMegi7SZo7mq2zND27x4CN9Q5Eryhq2psxGrLTsbb7aySizYRsDTYhmtvf8bc2Fiu1yr5rRw2Vu2)yGSZo7StfSqnSdF11ZH8RSAUxeTmqXKSaUCWR(I6IbgTxd7k1YazND2zNkyHAyhPfHbkMegi7SZo7mq2zND2zGSZo7SZazND2zNbYaxa3qGFBHuvm4WfneRAdCv08T41LMi0bTfVU0eHsYevzb0620qAittyh6PrgzhALxV6YIxxAIqHwg(Te69FrLRrw86steAytdYQOrZctrhKAvvf6zvATWMSGqvJff2FLPlstBc2yvu89TaT6cDVgUkAg4c4B)sh4Q0CPN6Ds1OGasv0uJMwVtaPPwnjsLA4IIbPwvvHoWfWLdE1xuxmWO9AyxPwgi7SZo79lCUZEMDazhaJfjtEvQRv(GzQQGpqW(dHQglkpAzGSZo7StfSqnSNzhqaz3y7mqXKmCbvuTxdiK)YcuicwOYIxDXKaD3ezrBKr2cuicwOYI4x69drbjz7acaXizquOjzDYt3sfIjjlSjliu1yrH9Uuv6S3Ar2y1ZO9Ag4IdMP4axGq(ll(PYrWf)u5i4ItdQ182Wf1wJ90yGlqi)Lf)u5i4IFQCeCrDorgoCbsTQQcDGlqi)LfWLdE1xaxo4vN8g2ezbA1LKfWLdE1dmd)2zXc4YbV6lQlgy0EnSRuldKD2zN9(fo3zVAUxe2bK9J0fyuzRuqWoaglsM8QuxR8bZuvbFGG9hcvnwuE0QL9lL9pgi7SZo7ublud7vZ9IWEAZ(hdumjlKQIbplaOcHGK3gaeRTfWLdE1jhH8xwCWmwolGBiWVTqQkgC4I00MGnwffFAApuFk(0qGIMkii1IAAwxcKMX8QOzHPOdsTQQc9SkTw0qSQnWLEtcGQvRMFkGQ17PuOH0MRMenHAr)Mtg4c6TldCHEPJ2boC4cm3fdoWf6LoAh4WHlOzyzGl0lD0oWHdhoCvumWfur1EnGq(llqHiyHklE1ftc0DtKfTrgzlqHiyHklIFP3pefKKTdiaeJKbrHMK1jpDlviMKSaPwvvHoWfiK)Yc4YbV6lGlh8QtEdBISaT6sYc4YbV6bMHF7SGbYaxivfdEwaqfcbjVnaiwBlGlh8Qtoc5VS4GzSCwa3qGFBHuvm4c4YbV6lQlgy0EnSRuldKD2zN9(fo3zVAUxe2bK9J0fyuzRuqWoaglsM8QuxR8bZuvbFGG9hcvnwuE0QL9lL9pgi7SZo7ublud7vZ9IWEAdi7A(((yGIjz4c4B)sh4Q0CPN6Ds1OGasv0uJMwVtaPPwnjsLA4ISXQNr71mWfhmtXbU4NkhbxCAqTM3wGq(ll(PYrWHlQTg7PXax8tLJGlQZjYceYFzXpvocoC4cBYccvnwuyVlvLo7AwutZ6sG0mMxfnlstBc2yvu8PP9q9P4tdbkAQGGulmfDqQvvvONvP1IgIvTbU0HIasjLusB9UcnksPiLcfRMenHAr)Mtg4cAgwg4c9shTdC4WfyUlgCGl0lD0oWHdxqVDzGl0lD0oWHdhUOyqQvvvOdCbC5Gx9f1fdmAVg2vQLbYo7SZE)cN7SNzhq2bWyrYKxL6ALpyMQk4deS)qOQXIYJwgi7SZo79lCUZE1CViSdi7hPlWOYwPGGDamwKm5vPUw5dMPQc(ab7peQASO8Ovl7xk7Fmq2zND2zGSZo7StfSqnSNzhqaz3y7SFPSxn3lc7ex21899XaftYWHRsZbUOyqQvvvOdCbC5Gx9f1fdmAVg2vQLbYo7SZE)cN7SNzhq2bWyrYKxL6ALpyMQk4deS)qOQXIYJwgi7SZo79lCUZE1CViSdi7hPlWOYwPGGDamwKm5vPUw5dMPQc(ab7peQASO8Ovl7xk7Fmq2zND2zGSZo7StfSqnSNzhqaz3y7SFPSxn3lc7ex2B(99XaftYWfur1EnGq(llqHiyHklE1ftc0DtKfTrgzlqHiyHklIFP3pefKKTdiaeJKbrHMK1jpDlviMKSWMSGqvJff27svPZUIfW3(LoWvP5sNusvOPzRuPG6dkfFAiO5QjrQMdxKnw9mAVMbU4GzkoWfiK)YIFQCeCXpvocU40GAnVnCrT1ypng4ceYFzXpvocU4NkhbxuNtKHdxGuRQQqh4ceYFzbC5Gx9fWLdE1jVHnrwGwDjzbC5Gx9aZWVDwWazGlGlh8QVOUyGr71WUsTmq2zND27x4CN9Q5Eryhq2psxGrLTsbb7aySizYRsDTYhmtvf8bc2Fiu1yr5rRw2Vu2)yGSZo7StfSqnSxn3lc7PnGS3877JbkMKfsvXGNfauHqqYBdaI12c4YbV6KJq(lloyglNfWne43wivfdoCrnnRlbsZyEv0SinTjyJvrXNM2d1NIpneOOPccsTWu0bPwvvHEwLwlAiw1g4sNunV)9(37k(s1IaO(uOy1KOjul63CYaxqVDzGl0lD0oWHdxG5UyWbUqV0r7ahoCbndldCHEPJ2boC4WHRsQbUOyqQvvvOdCbC5Gx9f1fdmAVg2vQLbYo7SZE)cN7SNzhq2bWyrYKxL6ALpyMQk4deS)qOQXIYJwgi7SZo79lCUZE1CViSdi7hPlWOYwPGGDamwKm5vPUw5dMPQc(ab7peQASO8Ovl7xk7Fmq2zND2zGSZo7StfSqnSNzhqaz3y7SFPSxn3lc7ex2H677JbkMKHlOIQ9AaH8xwGcrWcvw8QlMeO7MilAJmYwaF7x6axLMlDsjvHMMTsLcQpOu8PHGMRMePAoCrggTxZzGloyMIdCX5wmjli0GcTodleTTKeI3CiAAKKFRTcnFik0jj2mrJBXKCik4Lc3O9xv1fjxYp3IjzqB4WfOqeSqLfXV07hIcsY2beaIrYGOqtY6KNULketswGuRQQqh4ceYFzbC5Gx9fWLdE1jVHnrwGwDjzbC5Gx9aZWVDwWazGlKQIbplaOcHGK3gaeRTfWLdE1jhH8xwCWmwolGBiWVTqQkgCbC5Gx9f1fdmAVg2vQLbYo7SZE)cN7Sxn3lc7aY(r6cmQSvkiyhaJfjtEvQRv(GzQQGpqW(dHQglkpA1Y(LY(hdKD2zNDQGfQH9Q5ErypTbKDO(((yGIjz4ISXQNr71mWfhmtXbU4NkhbxCAqTM3wGq(ll(PYrWHl0ZwZax8tLJGlY9)gzOFPFKfiK)YIFQCeC4IARXEAmWf)u5i4I6CISaH8xw8tLJGdhUWMSGqvJff27svPZEZf10SUeinJ5vrZctrhKAvvf6zvATinTjyJvrXNM2d1NIpneOOPccsTOHyvBGlDsFhkOivdPTiqdbe0srkcwnjAc1I(nNmWf0mSmWf6LoAh4WHlWCxm4axOx6ODGdhUGE7YaxOx6ODGdhoC4WfvxLwn18nCd  

Initial setup

Bring up the WeakAuras settings panel by typing /wa, then click New in the left column and choose Progress Bar on the right. You'll now have a default WeakAuras bar right in the middle of your screen. For now just move it somewhere it's not going to be in the way, as we'll concentrate on getting the basic functionality working first; spit and polish can come later.

Select the Trigger tab. This is where we set up things like when to show and hide the bar and, most importantly, how its 'progress' is controlled.

To gain full control over these things, change the Type dropdown to Custom, then change the Event Type dropdown to Status. Change the Check On... dropdown to Every Frame. This is perhaps a little inefficient, but let's keep things simple for now – the other option is to only check when certain events are emitted by the game client.

WeakAuras2 custom triggers enabled

You'll now see, like in the image above, a whole bunch of small text boxes below with names like Custom Trigger, Duration Info etc., with an Expand Text Editor button next to each. This is where the magic happens.

Activation and deactivation

WeakAuras triggers are specified by writing Lua code, and our Custom Trigger (i.e. what activates the bar) is a super simple one. Click Expand Text Editor next to the text box and paste this text into the big text box that appears:

function()  
    local debuffName = UnitDebuff("target", "Ignite")
    return debuffName ~= nil
end  

It might seem odd to get the name of a debuff back from a function that takes the debuff name as parameter, but it's useful because if the debuff is not on the target, the return value is nil. The strange ~= pair of symbols means 'not equal to' in Lua, so the this function returns true if the debuff is on the target.

If Ignite drops off the target (or a new, Ignite-less target is selected), the check will return false, but the bar won't be hidden automatically! When using a custom trigger of the Status event type, you also need to specify what should happen when the trigger check fails, with a Custom Untrigger function. A post on WoWAce explains it in more detail, but basically it'll be the opposite of the trigger check:

function()  
    local debuffName = UnitDebuff("target", "Ignite")
    return debuffName == nil
end  

If this function returns false the bar will be hidden, otherwise it will remain visible.

'Duration' info: the important part

Now it's time to define the core functionality of our bar. Normally, progress bars in WeakAuras are used to track durations of things: how long left on a damage-over-time spell, the time remaining on a cooldown, things like that.

However, WeakAuras' Duration Info box allows us to use anything we like, so long as we tell it what the current and a maximum values are. Here's the function we'll use for Ignite:

function()  
    local value = select(15, UnitDebuff("target", "Ignite")) or 0
    local _, intellect = UnitStat("player", 4)
    return value, intellect * 2, true
end  

There's some extra things going on here that are worth explaining. First off, although earlier I said that UnitDebuff returns the spell name (or nil), it's actually more complex than that: Lua functions can return more than one value at a time, and UnitDebuff returns up to 17 of them, the problem being the numerical value of the debuff is number 15 in the list. One way to just get the number we're interested in is to do something like this:

local _, _, _, _, _, _, _, _, _, _, _, _, _, _, value = UnitDebuff("target", "Ignite")  

Basically, using dummy variable names (_ is a valid variable name in Lua) for 'padding'. This is fine when we're interested in the 2nd or 3rd value, perhaps, but a bit tedious if we want the 15th, and so Lua has a handy function called select that lets us just extract the single number we're interested in.

You'll notice, too, that we include or 0 on the end of the first line – this is because if Ignite isn't on the target, the value we get from UnitDebuff will be nil, and WeakAuras won't like us using a non-numeric value for the 'progress' part we give it. So, we're simply saying 'if the value we get from UnitDebuff is nil, make value 0 instead'.

Finally, we have the return value, and you can see here how we're returning multiple values: value, which specifies the 'progress' of the var, intellect * 2 so the bar scales properly as we gear up or happen to get a nice intellect proc, and true.

That last true is important, as it tells WeakAuras that we're creating a 'static' bar, meaning the values we're returning are indeed the 'current' and 'maximum'. Without the true, WeakAuras assumes the values mean something else, namely 'duration' and 'expiration time'. Since this isn't a time-based bar, we need to use 'static' mode.

Showing the bar's value

The last bit we're interested in here is how to display the numerical value of our Ignite on the bar. The easy way to do this is to just use %p for the Left Text (or Right Text) value on the Display tab. There is, however, another option that gives us full control over the value displayed.

The progress value is just a simple number, which is converted automatically to a string when shown on the bar. This is fine if it's a small number, but when you reach 5 or more digits it starts get a bit hard to read (and with time values, it's a number with lots of decimal places). To fix this, we can use thousands separators, so a number like 512234 is displayed as 512,234. In order to do this, we change the Left Text value to %c, and in the new text box that appears, we put this code:

function()  
    local commaSep = function (v)
        local s = tostring(v)
        return s:reverse():gsub("(%d%d%d)","%1,"):reverse():gsub("^,", "")
    end

    local value = select(15, UnitDebuff("target", "Ignite")) or 0
    return commaSep(value)
end  

This looks pretty complicated, but the gist of it is:

  • definte a new commaSep function to convert a number to a thousands-separated string:
    • convert the given number to a string
    • reverse it (so 123456 becomes 654321)
    • replace each group of 3 digits with those digits plus a comma (so 654321 becomes 654,321,, and 4321 becomes 432,1)
    • reverse this string back to normal
    • remove the comma at the start (if there is one)
  • return the debuff value after runing it through our commaSep function

The trickiest part here is the use of regular expressions in the gsub function. Unfortunately regular expressions are nasty complicated things, beyond the scope of this guide, but in a nutshell, gsub("%d", "%1,") means 'globally substitute every digit (the %d part) with itself (the %1 part) followed by a comma'. The ^ in the second gsub means 'at the start of the string'.

Other ways you can format numbers are by converting them to shorthand:

return string.format("Ignite strength: %.2f", value/1000) .. "k"  

Here we're using Lua's built-in format function, which uses the fairly standard 'printf' formatting codes to mix values into strings in various ways. In this example, the %.2f means 'display with two decimal places (the .2 part) a number in normal decimal notation' (the f part; an alternative is e for scientific notation). The .. "k" part means 'add the string "k" to the result of the format function'.

Of course, if you don't care about formatting and just want the raw number (say if it's a small number, like the number of stacks of something), you can of course just use %p in the Left/Right Text box.

Here's one I made earlier

If you don't want to enter all this stuff yourself, you could try importing this example Ignite string:

dyKsuaGivXLePKrrIofP0SaHBHiSlPu1WuvoMuYYifpJeMMu01ejBdK8neyCisNtvQwNuQ08qOs3dG2NiL6GsPSqqkpeKQyIikxer0gfP6JGuLojcALaAMiuXnbPYoLe)eHQgkiv1srO8uHPc0vbWxfPqgRuQyUiK2RYFrunyQoSOwSQKhdQjlIltSzj1NjPrlfonLETQuMTuDBs1UP43Q0WvvTCKEUkMo01Ly7ssFxKIgpcX5brRxKcUVifQ9J61AGlYdC4IZcnT)R9V3(3xOVizrYaxqeIVU(i4sNusHQPgfq9obkuObkfnvSAs0KGfqs811hbx6KivkcGsX3xZuKcfbAAPi1QjrZMlosVg6FTgCb0iEqqIh6ioKmDWfur1EnGq(lluP3Y)ctrhKAvvf6zvATWMSGqvJfLf9BozGlO3UmWf6LoAh4WHlWCxm4axOx6ODGdhUGMHLbUqV0r7ahoC4cHi)ztIKmOnCb8axLwdCHf(A2Rf1xdMEpREwq8aasCiScjx8ktHEU9lDGRIMLobqP5DO0qauFn)AL69VwRMePAoCr)Mtg4cm3fdoWf6LoAh4WHlG75ZzGlowJAxwaDTb9sYHlkhHC4E(Cg0wqZWYaxOx6ODGdhUOCeYp)c8G2IZVapWfhRrTlRIMHlkhHC4R(RmoOTGE7YaxOx6ODGdhoCbvuTxdiK)YICHMFLPlqHiyHklsNEp4cuicM(1GlIBHclShzZHDOp9UOyqQvvvOdCbC5Gx9f1fdmAVg2vQLbYo7SZE)cN7SNzhq2bWyrYKxL6ALpyMQk4deS)qOQXIYJwgi7SZo7ublud7z2beq2n2odumjdxKyp)9mKGcrqIJuJlypTmlYgREgTxZaxuBn2tJbU4NkhbxuNtKfiK)YIFQCeC4Wfi1QQk0bUaH8xwaxo4vFbC5GxDYBytKfOvxswaxo4vNCeYFzXbZy5SqQkg8SaGkecsEBaqS2waxo4vNScnJ2RzrDXaJ2RrPwgi7SZo79lCUZE1CViSdi7hPlWOYwPGGDamwKm5vPUw5dMPQc(ab7peQASO8Ovl7xk7Fmq2zND2PcwOg2RM7fbc2j977dc2rAryGIjzbC5Gx9kzDzrDXaJ2RrPwgi7SZo79lCUZo8vxphYp7aYEDXaJ2RHDLv1YazND2zND2zN9(fo3z)WoGSJ3dsTgvLv1YazND2zND2zNDQGfQH9t7sLQc9ik12UQNYlLpktRK0kjTs0(aXtA1cIhTTlvQk0JOuB7QEkVu(WPXq8ab7ppAzGSZo7SlMegi7SZo7mq2zND27x4CN9Q5Eryhq2psxGrLTsbb7aySizYRsDTYhmtvf8bc2Fiu1yr5rRw2Vu2)yGSZo7StfSqnSdF11ZH8RSAUxeTmqXKSaUCWR(I6IbgTxd7k1YazND2zNkyHAyhPfHbkMegi7SZo7mq2zND2zGSZo7SZazND2zNbYaxa3qGFBHuvm4WfneRAdCv08T41LMi0bTfVU0eHsYevzb0620qAittyh6PrgzhALxV6YIxxAIqHwg(Te69FrLRrw86steAytdYQOrZctrhKAvvf6zvATWMSGqvJff2FLPlstBc2yvu89TaT6cDVgUkAg4c4B)sh4Q0CPN6Ds1OGasv0uJMwVtaPPwnjsLA4IIbPwvvHoWfWLdE1xuxmWO9AyxPwgi7SZo79lCUZEMDazhaJfjtEvQRv(GzQQGpqW(dHQglkpAzGSZo7StfSqnSNzhqaz3y7mqXKmCbvuTxdiK)YcuicwOYIxDXKaD3ezrBKr2cuicwOYI4x69drbjz7acaXizquOjzDYt3sfIjjlSjliu1yrH9Uuv6S3Ar2y1ZO9Ag4IdMP4axGq(ll(PYrWf)u5i4ItdQ182Wf1wJ90yGlqi)Lf)u5i4IFQCeCrDorgoCbsTQQcDGlqi)LfWLdE1xaxo4vN8g2ezbA1LKfWLdE1dmd)2zXc4YbV6lQlgy0EnSRuldKD2zN9(fo3zVAUxe2bK9J0fyuzRuqWoaglsM8QuxR8bZuvbFGG9hcvnwuE0QL9lL9pgi7SZo7ublud7vZ9IWEAZ(hdumjlKQIbplaOcHGK3gaeRTfWLdE1jhH8xwCWmwolGBiWVTqQkgC4I00MGnwffFAApuFk(0qGIMkii1IAAwxcKMX8QOzHPOdsTQQc9SkTw0qSQnWLEtcGQvRMFkGQ17PuOH0MRMenHAr)Mtg4c6TldCHEPJ2boC4cm3fdoWf6LoAh4WHlOzyzGl0lD0oWHdhoCvumWfur1EnGq(llqHiyHklE1ftc0DtKfTrgzlqHiyHklIFP3pefKKTdiaeJKbrHMK1jpDlviMKSaPwvvHoWfiK)Yc4YbV6lGlh8QtEdBISaT6sYc4YbV6bMHF7SGbYaxivfdEwaqfcbjVnaiwBlGlh8Qtoc5VS4GzSCwa3qGFBHuvm4c4YbV6lQlgy0EnSRuldKD2zN9(fo3zVAUxe2bK9J0fyuzRuqWoaglsM8QuxR8bZuvbFGG9hcvnwuE0QL9lL9pgi7SZo7ublud7vZ9IWEAdi7A(((yGIjz4c4B)sh4Q0CPN6Ds1OGasv0uJMwVtaPPwnjsLA4ISXQNr71mWfhmtXbU4NkhbxCAqTM3wGq(ll(PYrWHlQTg7PXax8tLJGlQZjYceYFzXpvocoC4cBYccvnwuyVlvLo7AwutZ6sG0mMxfnlstBc2yvu8PP9q9P4tdbkAQGGulmfDqQvvvONvP1IgIvTbU0HIasjLusB9UcnksPiLcfRMenHAr)Mtg4cAgwg4c9shTdC4WfyUlgCGl0lD0oWHdxqVDzGl0lD0oWHdhUOyqQvvvOdCbC5Gx9f1fdmAVg2vQLbYo7SZE)cN7SNzhq2bWyrYKxL6ALpyMQk4deS)qOQXIYJwgi7SZo79lCUZE1CViSdi7hPlWOYwPGGDamwKm5vPUw5dMPQc(ab7peQASO8Ovl7xk7Fmq2zND2zGSZo7StfSqnSNzhqaz3y7SFPSxn3lc7ex21899XaftYWHRsZbUOyqQvvvOdCbC5Gx9f1fdmAVg2vQLbYo7SZE)cN7SNzhq2bWyrYKxL6ALpyMQk4deS)qOQXIYJwgi7SZo79lCUZE1CViSdi7hPlWOYwPGGDamwKm5vPUw5dMPQc(ab7peQASO8Ovl7xk7Fmq2zND2zGSZo7StfSqnSNzhqaz3y7SFPSxn3lc7ex2B(99XaftYWfur1EnGq(llqHiyHklE1ftc0DtKfTrgzlqHiyHklIFP3pefKKTdiaeJKbrHMK1jpDlviMKSWMSGqvJff27svPZUIfW3(LoWvP5sNusvOPzRuPG6dkfFAiO5QjrQMdxKnw9mAVMbU4GzkoWfiK)YIFQCeCXpvocU40GAnVnCrT1ypng4ceYFzXpvocU4NkhbxuNtKHdxGuRQQqh4ceYFzbC5Gx9fWLdE1jVHnrwGwDjzbC5Gx9aZWVDwWazGlGlh8QVOUyGr71WUsTmq2zND27x4CN9Q5Eryhq2psxGrLTsbb7aySizYRsDTYhmtvf8bc2Fiu1yr5rRw2Vu2)yGSZo7StfSqnSxn3lc7PnGS3877JbkMKfsvXGNfauHqqYBdaI12c4YbV6KJq(lloyglNfWne43wivfdoCrnnRlbsZyEv0SinTjyJvrXNM2d1NIpneOOPccsTWu0bPwvvHEwLwlAiw1g4sNunV)9(37k(s1IaO(uOy1KOjul63CYaxqVDzGl0lD0oWHdxG5UyWbUqV0r7ahoCbndldCHEPJ2boC4WHRsQbUOyqQvvvOdCbC5Gx9f1fdmAVg2vQLbYo7SZE)cN7SNzhq2bWyrYKxL6ALpyMQk4deS)qOQXIYJwgi7SZo79lCUZE1CViSdi7hPlWOYwPGGDamwKm5vPUw5dMPQc(ab7peQASO8Ovl7xk7Fmq2zND2zGSZo7StfSqnSNzhqaz3y7SFPSxn3lc7ex2H677JbkMKHlOIQ9AaH8xwGcrWcvw8QlMeO7MilAJmYwaF7x6axLMlDsjvHMMTsLcQpOu8PHGMRMePAoCrggTxZzGloyMIdCX5wmjli0GcTodleTTKeI3CiAAKKFRTcnFik0jj2mrJBXKCik4Lc3O9xv1fjxYp3IjzqB4WfOqeSqLfXV07hIcsY2beaIrYGOqtY6KNULketswGuRQQqh4ceYFzbC5Gx9fWLdE1jVHnrwGwDjzbC5Gx9aZWVDwWazGlKQIbplaOcHGK3gaeRTfWLdE1jhH8xwCWmwolGBiWVTqQkgCbC5Gx9f1fdmAVg2vQLbYo7SZE)cN7Sxn3lc7aY(r6cmQSvkiyhaJfjtEvQRv(GzQQGpqW(dHQglkpA1Y(LY(hdKD2zNDQGfQH9Q5ErypTbKDO(((yGIjz4ISXQNr71mWfhmtXbU4NkhbxCAqTM3wGq(ll(PYrWHl0ZwZax8tLJGlY9)gzOFPFKfiK)YIFQCeC4IARXEAmWf)u5i4I6CISaH8xw8tLJGdhUWMSGqvJff27svPZEZf10SUeinJ5vrZctrhKAvvf6zvATinTjyJvrXNM2d1NIpneOOPccsTOHyvBGlDsFhkOivdPTiqdbe0srkcwnjAc1I(nNmWf0mSmWf6LoAh4WHlWCxm4axOx6ODGdhUGE7YaxOx6ODGdhoC4WfvxLwn18nCd

It looks like this:

ignite bar screenshot

As you can see, I've fancied it up a bit with a flames texture that gets more prominent the higher the bar goes.

Update, 18th March 2015

I made another bar, this time for my Unholy Death Knight, to track my ghoul's Shadow Infusion stacks, and then when Dark Transformation is active, that buff's duration.

The important bit is the Duration function:

function()  
    local buff = {UnitBuff("pet", "Dark Transformation")}
    local value, max
    if buff[7] then -- buff has an expiry time
        value = math.floor((buff[7] - GetTime()) * 10) / 10
        max = buff[6] -- buff duration
    else
        buff = {UnitBuff("pet", "Shadow Infusion")}
        value = buff[4] or 0 -- current stacks
        max = 5 -- total stacks
    end

    return value, max, true
end  

The tricky bit here is the second line, where I've wrapped the UnitBuff() call in { curly braces }. This simply gathers all the return values into an array, so rather than repeatedly calling select() on the function and potentially introducing performance issues, you can just retrieve the existing values, as shown in the 4th line, via for example buff[7]; the 7th value in this case is the number of stacks – see the documentation for info about the other values.

Custom colouring

One thing I wasn't aware of when I first wrote this guide is that you could use a Lua function to set the colour of the bar, so for example I could have made the Ignite bar start off dark red, then gradually change to orange then yellow as it increased.

For the Dark Transformation/Shadow Infusion bar, I made use of a handy feature of WeakAuras2: the parameters it passes to the functions you define.

First off, to tell WA2 you want to use a custom function for the bar's colour, you need to go to the Animation tab and set the Main section up like this:

WeakAuras2 main animation setup

Then in the Custom Function text box, insert this:

function(progress, r1, g1, b1, a1, r2, g2, b2, a2)  
    local buff = select(15, UnitBuff("pet", "Shadow Infusion"))

    if buff then
        return r1, g1, b1, a1
    else
        return r2, g2, b2, a2
    end
end  

The *1 parameters here are the red, green, blue and alpha components of the bar's normal colour, defined on the Display tab, while the *2 parameters are the components of the secondary colour defined in this section (a pale green, in this screenshot).

Obviously you're not limited to returning just these values – you could apply some mathematical adjustments to them based on the value of progress, or you could get the number of stacks of a buff and adjust the colour based on that, whatever you can imagine really.

If you'd like to try out the bar I made, here's the WA2 string:

duK9kaGiGmkb6ucyvaGmlOYTaj7cQk)caWWuPoMOAzIINbOPrrUgi2MkX3ujnof05GQCpb5GaOwia9qkitKcQlcvvTrOuFKcWibG6KkHwjs9saGMjaOUjfO2ju8tkGwkaKNIyQa1vPq9wrjDxrj2lQ)cszWshwOftr9yKmzf6Yq2SI(ScmALOtRIxRemBL62kPDtPFtLHlOwUiphutxvxNQ2ouY3bPA8uiNxuQ1dG8EOQY9Paz)K5CgmtwzYitgzWmXidCoHrpJ5gF3335dbMFdX0LHxHWKSnW5eg9mgOaoectMo7J9ooaMjgOXGbGxed(ZeZXKHCBxIbZyYzSVabOPlanDfcqtaXdIPBEcfeGmMmm2xmLz4LlxVEde4qGxVaKNqbXeJbiJ5gFxZKd5YWlzUAcYnEd5NjBxCKbZKpUr2NbZe4JDWgXyYVzYQF)hgmJj)MbKF(zcCyefdMjWh7GnIXaKFMmEMZdLF)zZGzYQF)hgm)8ZKuKcXGzYQF)hgm)8ZepmcAWHrumGmHAhHHzWmb(yhSrmXW4padgadaIzrdaadMFM4HrqJAhHHzazsYTrmyMS63)HbZp)8ZKeAWXzbNDyetI(u0CmXKJ98qJYTgEJE0iJjNjpYO3Nqmb7Z8xcZKhz0JTZ(mXqBumPsIwyvdgnE8Rm5pROe2o7ZedTrXKkjAHvny04XVYKhz0Bi32LyWmgtm24DFFnFiEqWl)(IjixVWtOGyIFM4TF6myakXGzcLh(DRmz6Tu)Xzdgq0QQQQBhvCRgvdPAS98a6NZGGcJEq4ubrwghDqxDr70dFCwqbeTQQQAc9(KvnQgkKQ9SfnYoYptI2ZA8poldMjRXJLbZek32Laqm2qUm8Yq8gcesg8WdiqGz4juqaYKp7WiMq5HF3ktGPIBKrmMCMq52UeaZyYzIhgbnk32LyazsChEzKXCZeJym3mjBgZntOCBxcC2HrmHYd)UvMq52UKbWypmdW787RqGyciWC8UaHNqbbitOCBxcqgBtxVmes(1mqYa5gp8aELNqbbitOCBxcBVLIjj07tw1P3s9hNny4KBqcbdJtnLJtDqoovZ54uJ54utzWPoidovZzWPgZeq0QQQQBhvCRA2pNQHuHrBe1hmhcovJTNhq)Cgeuy0dcNkiYY4Od6QlANE4JZckqarRQQQkAvvv1Zu1SFov)LiROvvvvvvvvtO3NSQPCCQdYXPAohNAmx0QQQQOnms0QQQQQQQQj07tw1ugCQdYGt1CgCQXmIwvvvfzhfTQQQQOr2rMKCF8rmMBMatf3OSzm5mz0NI)XzzYn(aYp)m5tNbdqjgmt(SdJycLh(DRmHYd)UvYhPwaMjtVL6poBWaIwvvvD7OIBvSIBpsnKkmAJO(GxXPAS98a6NZGGcJEq4ubz4yAbvWPOfE6sRX)4SGceq0QQQQNPkwXThPQgkKQQ9Sv)LiROvvvvvvvvXkU9i1qQWOnI6dAcNQX2ZdOFodckm6bHtfezzC0bD1fTtp8XzbfiGQlPElAvvvv0ggjAvvvvvvvvSIBpsnKQ9SfTQQQkYokAvvvvrRQQQMqVpzvXkU9irJSJmHYd)Uvd7tX)4Smz6Tu)Xzdgq0QQQQBhvCRA2pNQHuXpJTNhq)Cgeuy0dcNkidhtlOcofTWtxAn(hNfuads0QQQQBhvCRUgns0QQQQNPQz)CM1Rzrv9xISIwvvvvvvvfR42JudPUg)L4BUDUuWGM9ZzwVMfvOuna0d(SIcgiGkaKA(Davaa18BrRQQQQQQQUgnsnKQz)CM1lzrfkOun7Nt1)SIeTQQQkAdJeTQQQQQQQQz)CQgsf)m2EEa9ZzqqHrpiCQGilJJoORUOD6HpolOagKOvvvvvvvvXkU9i1qQM9ZzwnLfvxs9wfkOuP8PeY(QWFKAbyrRQQQQQQQUgnsnKkevOGs9DFCRc)rQfGfTQQQkYokAvvvvrRQQQMqVpzvXkU9iCQRrJWP(jps0i7itO8WVBftCfXKP3s9hNnyarRQQQUDuXTQz)CQgsf)m2EEa9ZzqqHrpiCQGmCmTGk4u0cpDP14FCwqbmirRQQQUDuXTkwXThPgs1SFoZAEweTQQQ6zQIvC7rQQHcPQApB1FjYkAvvvvvvvvSIBpsnKkmAJO(G54un2EEa9ZzqqHrpiCQGilJJoORUOD6HpolOabuDj1BrRQQQISJIwvvvv0QQQQj07twvSIBps0i7OOfTOfntO8WVBLjtVL6poBWaIwvvvvvnHEFYQ(jps0i7OOzcLh(DRq7ZomIjWF89WmHAjIAbM4dpgFetqyHSpmtmgZIGHgaBmacGzcLh(DRqB5zeXK)SIg5NjpYONnZKLOZGLpJ9qtMmbe4nE3qUG3qG3d5juMWJjMDPruIbKjMDPruc)hhGycG7dabqX0OQHpXTBatG)i1cWy7Sptm0gftQKOfw1GrJh)ktouolBMjMDPrucWi1cJjxyMGXzrmX6xbNodgGsWmMCM8iJEYbGqmM8BMCgzczzC0bD1fTtp8XzzYFwrjYbGqmMCimb6NXFjJnK7CGxhEdb4WHqYbcmdpHYKjMy2Lgrjd52UedMXyIXKZp)mbMjzWxo(UXxotWIXKBkto)mda

OCOLOY Week 5   ·   OCOLOY Week 6