Thread Tools Display Modes
08-13-14, 02:26 PM   #1
ObbleYeah
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Sep 2008
Posts: 210
checking for buff stacks in C_L_E_U

over the last couple of days me and Lyn have been trying to build a little mod that will display a set of text strings based on whether the player has particular buffs. So far we have this:

https://gist.github.com/anonymous/d23ffb8dfd3124659c46

which, despite obviously being pretty unfinished, is sort-of working. Getting how many stacks a buff has doesn't seem to be working despite best efforts though - the debug print only ever returning a maximum value of 1. Experiments with using UNIT_AURA instead provided the correct # of stacks, but we couldn't get the thing to work otherwise. Doing something wrong here?

Last edited by ObbleYeah : 08-13-14 at 02:34 PM.
  Reply With Quote
08-13-14, 03:00 PM   #2
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
Is there some reason you're trying to use the combat log instead of UNIT_AURA to track a buff on the player?
  Reply With Quote
08-13-14, 03:06 PM   #3
ObbleYeah
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Sep 2008
Posts: 210
Well, tried this too and couldn't get anything at all (though it does pass stacks correctly):

https://gist.github.com/anonymous/55cbe42ae6a68b3de58b

if it's easier/better to use UNIT_AURA then great, just struggling to make it work atm

edit: actually it does seem to be working when brain freeze procs: but not for fingers of frost. hmn

Last edited by ObbleYeah : 08-13-14 at 03:16 PM.
  Reply With Quote
08-13-14, 04:00 PM   #4
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
You're calling self:Hide() for each item in your table, so the only possible time it would be visible is if you have the last buff in the table active.
  Reply With Quote
08-13-14, 04:06 PM   #5
ObbleYeah
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Sep 2008
Posts: 210
neat, that gives me something to work with. Thanks!
  Reply With Quote
08-13-14, 04:32 PM   #6
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
A couple things I would change..
Lua Code:
  1. frame:RegisterEvent("UNIT_AURA")
would be better as
Lua Code:
  1. frame:RegisterUnitEvent("UNIT_AURA", "player")
and
Lua Code:
  1. if UnitBuff("player", buff) then   
  2.     local _, _, _, stacks = UnitBuff("player", buff)
could be replaced with
Lua Code:
  1. local _, _, _, stacks = UnitBuff("player", buff)
  2. if stacks then
  Reply With Quote
08-13-14, 04:42 PM   #7
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
The (probable) reason CLEU didn't work is that UnitAura isn't necessarily updated yet when the aura change is reported in the combat log.

With your current code, I'd recommend using the spellID as the table key, not the name, so it can work in all languages and not just English:

Code:
local spells = {
    [1234] = {
        -- some other data here
    },
    [56789] = {
        -- some other data here
    },
}

-- add name for current locale at runtime:
for id, data in pairs(spells) do
     data.name = GetSpellInfo(id)
end
Then, when you're checking for buffs:
Code:
for id, data in pairs(spells) do
    local _, _, _, stacks = UnitBuff("player", data.name)
    if stacks then
        -- do stuff here
    end
end
Also, don't forget that stacks will be 0 for buffs that don't stack -- if you need to support those, then you'll want to do an additional "if stacks == 0 then stacks = 1 end" in the "do stuff here" area.

Oh, and there's not really any reason to use unpack here, since you know how many values are in the table. This:

Code:
local t = { 128, 128, 255 }
local r, g, b = t[1], t[2], t[3]
... is much faster than this:

Code:
local t = { 128, 128, 255 }
local r, g, b = unpack(t)
Another problem:
Code:
               for i = 1, stacks do
                    string:SetText(spellList[buff].Text)
                end
1) string is a horrible name for a variable, since it will overwrite the global string library in that context. Similarly, you should never name a variable table or math or setmetatable or any other Lua or WoW API global.

2) I'm guessing you want to show the given character n times, where n is the number of stacks of the buff, but your current code won't do that; it will just tell the fontstring n times to display one of the character. You probably want to do this instead:
Code:
    myFontString:SetText(string.rep("x", stacks)
Finally, your current method of checking if Tier is 1 or 2 will lead to problems later on if you try to support more spells, since you'll have to do a long else chain to do the positioning correctly. If you want to show the buffs in a specific order, I'd suggest using an indexed table instead of a hash table, so you can use table.sort on it:

Code:
local spells = {
    {
        id = 1234,
        priority = 1,
        -- other data here
    },
    {
        id = 56789,
        priority = 2,
        -- other data here
    },
}
for i = 1, #spells do
    local spell = spells[i]
    spell.name = GetSpellInfo(spell.id)
end

local function sortSpells(a, b)
     -- Show lower priority first, or alphabetically within same priority:
     return a.priority < b.priority or a.priority == b.priority and a.name < b.name
end

-- you can call this again later if you change priorities in-game:
table.sort(spells, sortSpells)
Then:
Code:
local shown = 0
for i = 1, #spells do
    local spell = spells[i]
    local _, _, _, stacks = UnitBuff("player", spell.name)
    if stacks then
        shown = shown + 1
        local fontstring = fontstrings[shown] -- keep them all in another indexed table
        fontstring:SetText(string.rep(spell.text, stacks > 0 and stacks or 1))
        fontstring:SetTextColor(spell.color[1], spell.color[2], spell.color[3])
        if shown > 1 then
            fontstring:SetPoint("TOP", fontstrings[shown - 1], "BOTTOM", 0, -5)
        else
            fontstring:SetPoint("TOP", UIParent, "CENTER")
        end
        fontstring:Show()
    end
    -- hide the unused ones:
    for i = shown + 1, #fontstrings do
        fontstrings[i]:Hide()
    end
end
This will ensure that your spells are always checked and displayed in order without needing to hardcode any checks.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.

Last edited by Phanx : 08-13-14 at 05:11 PM.
  Reply With Quote
08-13-14, 04:54 PM   #8
ObbleYeah
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Sep 2008
Posts: 210
Originally Posted by semlar View Post
A couple things I would change..
Lua Code:
  1. frame:RegisterEvent("UNIT_AURA")
would be better as
Lua Code:
  1. frame:RegisterUnitEvent("UNIT_AURA", "player")
does this mean the removal of

Lua Code:
  1. if unit~="player" then return end

is then possible at the start of the onevent, or is it just for general increased precision so that line doesn't have to keep running on every aura event? Considering recent troubles I've had whittling events down to just the players actions I'm assuming the latter.

Also, how would you suggest hiding the frame once the buff is no longer around? I guess that

Lua Code:
  1. for buff in pairs(spellList) do
  2.     local _, _, _, stacks = UnitBuff("player", buff)
  3.     if stacks then
  4.         -- stuff
  5.         self:Show()
  6.     else
  7.         self:Hide()
  8.     end
  9. end

would cause similar issues (not in an environment to just test at the minute).
  Reply With Quote
08-13-14, 05:03 PM   #9
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
Originally Posted by ObbleYeah View Post
does this mean the removal of
Lua Code:
  1. if unit~="player" then return end
Yeah, it will only fire OnEvent for UNIT_AURA on the player. You won't need to check what unit it fired on.

As for hiding the frame, you could hide it before the buff loop and just show it when one is found.

Last edited by semlar : 08-13-14 at 05:06 PM.
  Reply With Quote
08-13-14, 05:07 PM   #10
ObbleYeah
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Sep 2008
Posts: 210
makes sense, thanks.
  Reply With Quote
08-13-14, 05:12 PM   #11
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Edited my post while you guys were posting, in case you didn't notice the additions.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
08-13-14, 05:37 PM   #12
ObbleYeah
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Sep 2008
Posts: 210
Well that certainly cuts down the amount of time i was expecting for this to eat into my work-day tomorrow. What am i supposed to do now?

Hugely appreciated.
  Reply With Quote
08-14-14, 05:55 AM   #13
ObbleYeah
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Sep 2008
Posts: 210
Is there any way to get these strings to align (i'm already using SetJustifyH and SetPoint to anchor and align) or is this kind of thing just the result of quirks in each typeface symbol + different font sizes?



edit: more noticable in this image maybe
  Reply With Quote
08-14-14, 08:33 AM   #14
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
Which strings?
__________________
Grab your sword and fight the Horde!
  Reply With Quote
08-14-14, 08:42 AM   #15
ObbleYeah
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Sep 2008
Posts: 210
the bullet point, asterisk and em dash in the center.

e: it doesn't matter anyway. I'm happy with them right-aligned now


Last edited by ObbleYeah : 08-14-14 at 09:02 AM.
  Reply With Quote
08-14-14, 09:08 AM   #16
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
If they're anchored to each other's center and center justified there's not much more you can do, no.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
08-14-14, 11:25 AM   #17
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
Originally Posted by ObbleYeah View Post
Is there any way to get these strings to align
Assuming you're using phanx's script, this is what is anchoring your strings
Lua Code:
  1. if shown > 1 then
  2.     fontstring:SetPoint("TOP", fontstrings[shown - 1], "BOTTOM", 0, -5)
  3. else
  4.     fontstring:SetPoint("TOP", UIParent, "CENTER")
  5. end
The second SetPoint anchors the initial font string to the UIParent and the first SetPoint anchors the top of the following strings to the bottom of the previous one. To left align them you would just change their anchor points to "TOPLEFT" and "BOTTOMLEFT" and then anchor the initial string wherever you want.
Lua Code:
  1. if shown > 1 then
  2.     fontstring:SetPoint("TOPLEFT", fontstrings[shown - 1], "BOTTOMLEFT", 0, -5)
  3. else
  4.     fontstring:SetPoint("TOPLEFT", UIParent, "CENTER")
  5. end
This would make the list appear left-aligned with the center of the UIParent.

If you don't keep the relative string anchors the same (they're all "TOPLEFT" in this) then you'll have to call fontstring:ClearAllPoints() first.

Last edited by semlar : 08-14-14 at 11:28 AM.
  Reply With Quote
08-14-14, 08:24 PM   #18
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Actually, it occurred to me that you don't need to do any SetPoint work in the update routine -- you only need to set the point of each font string once, when it's created.

Code:
local lines = setmetatable({}, { __index = function(t, i)
    local line = UIParent:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    if i > 1 then
        line:SetPoint("BOTTOM", lines[i-1], "TOP")
    else
        line:SetPoint("BOTTOM", UIParent, "CENTER")
    end
    -- do other stuff here, add shadow, outline, custom font, whatever
    t[i] = line
    return line
end })
All you need to do in the update routine is either SetText+Show, or Hide.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
08-15-14, 05:02 AM   #19
ObbleYeah
A Cobalt Mageweaver
AddOn Author - Click to view addons
Join Date: Sep 2008
Posts: 210
what do I use as a variable in the event handler for the string i've created using that method?
  Reply With Quote
08-15-14, 06:41 AM   #20
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
local fontstring = fontstrings[shown] => local fontstring = lines[shown]

or just rename "lines" to "fontstrings"

Also, it's a metatable, so you just look up the index you want, and the metatable automatically creates a fontstring object at that index; you don't have to "create" anything by hand.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » checking for buff stacks in C_L_E_U

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off