Thread Tools Display Modes
08-27-16, 09:58 AM   #1
Joker119
A Flamescale Wyrmkin
 
Joker119's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2014
Posts: 113
Buff Statusbars

I've been attempting to add statusbars to my buffs and debuffs.
The frames and button skinning is handled by 2 of zork's addons rBuffFrame and rButtonTemplate, I've been able to get as far as adding the statusbars to the buttons, however, I'm not able to get them to update the min/max value or value based on duration or expirationTime, using the code below:

After the rButtonTemplate styles it's aura buttons, I have this hook function to add the statusbars:
Lua Code:
  1. hooksecurefunc("AuraButton_Update", function(self, index, filter)
  2. local buffButtonIndex = 0
  3.     for i = buffButtonIndex, BUFF_MAX_DISPLAY do
  4.         local button = _G["BuffButton"..i]
  5.         BuffStatusBar = CreateFrame("StatusBar", nil, button)
  6.         BuffStatusBar:SetFrameStrata("HIGH")
  7.         BuffStatusBar:SetSize(32, 6)
  8.         BuffStatusBar:SetPoint("BOTTOM", button, 0, -8)
  9.         BuffStatusBar:SetStatusBarTexture("Interface\\AddOns\\Roth_UI\\media\\statusbar3")
  10.         BuffStatusBar:SetStatusBarColor(0,1,0)
  11.        
  12.         local _, _, _, _, _, dur, exps = UnitAura(PlayerFrame.unit, index, filter)
  13.         BuffStatusBar:SetMinMaxValues(dur - exps, exps)
  14.     end
  15. end)
However I get this error:
Code:
30x ...rfaceRoth_UI\embeds\rButtonTemplate\core.lua:335: attempt to perform arithmetic on local 'dur' (a nil value)
...rfaceRoth_UI\embeds\rButtonTemplate\core.lua:335: in function <...rfaceRoth_UI\embeds\rButtonTemplate\core.lua:323>
[C]: in function `AuraButton_Update'
FrameXML\BuffFrame.lua:90: in function `BuffFrame_Update'
FrameXML\PlayerFrame.lua:452: in function `PlayerFrame_ToPlayerArt'
FrameXML\PlayerFrame.lua:213: in function `OnEvent'
FrameXML\UnitFrame.lua:917: in function <FrameXML\UnitFrame.lua:915>

Locals:
self = "BuffButton"
index = 1
filter = "HELPFUL"
buffButtonIndex = 0
(for index) = 0
(for limit) = 32
(for step) = 1
i = 0
button = nil
_ = nil
_ = nil
_ = nil
_ = nil
_ = nil
dur = nil
exps = nil
(*temporary) = <function> defined =[C]:-1
(*temporary) = <unnamed> {
 0 = <userdata>
}
(*temporary) = nil
(*temporary) = nil
(*temporary) = "attempt to perform arithmetic on local 'dur' (a nil value)"
Entire addon here:
Lua Code:
  1. -- rButtonTemplate: core
  2. -- zork, 2016
  3.  
  4. -----------------------------
  5. -- Variables
  6. -----------------------------
  7. local ns = ...
  8. local A, L = ...
  9.  
  10. -----------------------------
  11. -- rButtonTemplate Global
  12. -----------------------------
  13.  
  14. rButtonTemplate = {}
  15. rButtonTemplate.addonName = A
  16.  
  17. -----------------------------
  18. -- Init
  19. -----------------------------
  20.  
  21. local function CallButtonFunctionByName(button, func, ...)
  22.   if button and func and button[func] then
  23.     button[func](button, ...)
  24.   end
  25. end
  26.  
  27. local function ResetNormalTexture(self, file)
  28.   if not self.__normalTextureFile then return end
  29.   if file == self.__normalTextureFile then return end
  30.   self:SetNormalTexture(self.__normalTextureFile)
  31. end
  32.  
  33. local function ResetTexture(self, file)
  34.   if not self.__textureFile then return end
  35.   if file == self.__textureFile then return end
  36.   self:SetTexture(self.__textureFile)
  37. end
  38.  
  39. local function ResetVertexColor(self,r,g,b,a)
  40.   if not self.__vertexColor then return end
  41.   local r2,g2,b2,a2 = unpack(self.__vertexColor)
  42.   if not a2 then a2 = 1 end
  43.   if r ~= r2 or g ~= g2 or b ~= b2 or a ~= a2 then
  44.     self:SetVertexColor(r2,g2,b2,a2)
  45.   end
  46. end
  47.  
  48. local function ApplyPoints(self, points)
  49.   if not points then return end
  50.   self:ClearAllPoints()
  51.   for i, point in next, points do
  52.     self:SetPoint(unpack(point))
  53.   end
  54. end
  55.  
  56. local function ApplyTexCoord(texture,texCoord)
  57.   if not texCoord then return end
  58.   texture:SetTexCoord(unpack(texCoord))
  59. end
  60.  
  61. local function ApplyVertexColor(texture,color)
  62.   if not color then return end
  63.   texture.__vertexColor = color
  64.   texture:SetVertexColor(unpack(color))
  65.   hooksecurefunc(texture, "SetVertexColor", ResetVertexColor)
  66. end
  67.  
  68. local function ApplyAlpha(region,alpha)
  69.   if not alpha then return end
  70.   region:SetAlpha(alpha)
  71. end
  72.  
  73. local function ApplyFont(fontString,font)
  74.   if not font then return end
  75.   fontString:SetFont(unpack(font))
  76. end
  77.  
  78. local function ApplyTexture(texture,file)
  79.   if not file then return end
  80.   texture.__textureFile = file
  81.   texture:SetTexture(file)
  82.   hooksecurefunc(texture, "SetTexture", ResetTexture)
  83. end
  84.  
  85. local function ApplyNormalTexture(button,file)
  86.   if not file then return end
  87.   button.__normalTextureFile = file
  88.   button:SetNormalTexture(file)
  89.   hooksecurefunc(button, "SetNormalTexture", ResetNormalTexture)
  90. end
  91.  
  92. local function SetupTexture(texture,cfg,func,button)
  93.   if not texture or not cfg then return end
  94.   ApplyTexCoord(texture,cfg.texCoord)
  95.   ApplyPoints(texture,cfg.points)
  96.   ApplyVertexColor(texture,cfg.color)
  97.   ApplyAlpha(texture,cfg.alpha)
  98.   if func == "SetTexture" then
  99.     ApplyTexture(texture,cfg.file)
  100.   elseif func == "SetNormalTexture" then
  101.     ApplyNormalTexture(button,cfg.file)
  102.   elseif cfg.file then
  103.     CallButtonFunctionByName(button,func,cfg.file)
  104.   end
  105. end
  106.  
  107. local function SetupFontString(fontString,cfg)
  108.   if not fontString or not cfg then return end
  109.   ApplyPoints(fontString, cfg.points)
  110.   ApplyFont(fontString,cfg.font)
  111.   ApplyAlpha(fontString,cfg.alpha)
  112. end
  113.  
  114. local function SetupCooldown(cooldown,cfg)
  115.   if not cooldown or not cfg then return end
  116.   ApplyPoints(cooldown, cfg.points)
  117. end
  118.  
  119. local function SetupBackdrop(button,backdrop)
  120.   if not backdrop then return end
  121.   local bg = CreateFrame("Frame", nil, button)
  122.   ApplyPoints(bg, backdrop.points)
  123.   bg:SetFrameLevel(button:GetFrameLevel()-1)
  124.   bg:SetBackdrop(backdrop)
  125.   if backdrop.backgroundColor then
  126.     bg:SetBackdropColor(unpack(backdrop.backgroundColor))
  127.   end
  128.   if backdrop.borderColor then
  129.     bg:SetBackdropBorderColor(unpack(backdrop.borderColor))
  130.   end
  131. end
  132.  
  133. function rButtonTemplate:StyleActionButton(button, cfg)
  134.   if not button then return end
  135.   if button.__styled then return end
  136.  
  137.   local buttonName = button:GetName()
  138.   local icon = _G[buttonName.."Icon"]
  139.   local flash = _G[buttonName.."Flash"]
  140.   local flyoutBorder = _G[buttonName.."FlyoutBorder"]
  141.   local flyoutBorderShadow = _G[buttonName.."FlyoutBorderShadow"]
  142.   local flyoutArrow = _G[buttonName.."FlyoutArrow"]
  143.   local hotkey = _G[buttonName.."HotKey"]
  144.   local count = _G[buttonName.."Count"]
  145.   local name = _G[buttonName.."Name"]
  146.   local border = _G[buttonName.."Border"]
  147.   local NewActionTexture = button.NewActionTexture
  148.   local cooldown = _G[buttonName.."Cooldown"]
  149.   local normalTexture = button:GetNormalTexture()
  150.   local pushedTexture = button:GetPushedTexture()
  151.   local highlightTexture = button:GetHighlightTexture()
  152.   local checkedTexture = button:GetCheckedTexture()
  153.   local floatingBG = _G[buttonName.."FloatingBG"]
  154.  
  155.   --hide stuff
  156.   if floatingBG then floatingBG:Hide() end
  157.  
  158.   --backdrop
  159.   SetupBackdrop(button,cfg.backdrop)
  160.  
  161.   --textures
  162.   SetupTexture(icon,cfg.icon,"SetTexture",icon)
  163.   SetupTexture(flash,cfg.flash,"SetTexture",flash)
  164.   SetupTexture(flyoutBorder,cfg.flyoutBorder,"SetTexture",flyoutBorder)
  165.   SetupTexture(flyoutBorderShadow,cfg.flyoutBorderShadow,"SetTexture",flyoutBorderShadow)
  166.   SetupTexture(border,cfg.border,"SetTexture",border)
  167.   SetupTexture(normalTexture,cfg.normalTexture,"SetNormalTexture",button)
  168.   SetupTexture(pushedTexture,cfg.pushedTexture,"SetPushedTexture",button)
  169.   SetupTexture(highlightTexture,cfg.highlightTexture,"SetHighlightTexture",button)
  170.   SetupTexture(checkedTexture,cfg.checkedTexture,"SetCheckedTexture",button)
  171.  
  172.   --cooldown
  173.   SetupCooldown(cooldown,cfg.cooldown)
  174.  
  175.   --hotkey+count+name
  176.   SetupFontString(hotkey,cfg.hotkey)
  177.   SetupFontString(count,cfg.count)
  178.   SetupFontString(name,cfg.name)
  179.  
  180.   button.__styled = true
  181. end
  182.  
  183. function rButtonTemplate:StyleExtraActionButton(cfg)
  184.  
  185.   local button = ExtraActionButton1
  186.  
  187.   if button.__styled then return end
  188.  
  189.   local buttonName = button:GetName()
  190.  
  191.   local icon = _G[buttonName.."Icon"]
  192.   --local flash = _G[buttonName.."Flash"] --wierd the template has two textures of the same name
  193.   local hotkey = _G[buttonName.."HotKey"]
  194.   local count = _G[buttonName.."Count"]
  195.   local buttonstyle = button.style --artwork around the button
  196.   local cooldown = _G[buttonName.."Cooldown"]
  197.  
  198.   local normalTexture = button:GetNormalTexture()
  199.   local pushedTexture = button:GetPushedTexture()
  200.   local highlightTexture = button:GetHighlightTexture()
  201.   local checkedTexture = button:GetCheckedTexture()
  202.  
  203.   --backdrop
  204.   SetupBackdrop(button,cfg.backdrop)
  205.  
  206.   --textures
  207.   SetupTexture(icon,cfg.icon,"SetTexture",icon)
  208.   SetupTexture(buttonstyle,cfg.buttonstyle,"SetTexture",buttonstyle)
  209.   SetupTexture(normalTexture,cfg.normalTexture,"SetNormalTexture",button)
  210.   SetupTexture(pushedTexture,cfg.pushedTexture,"SetPushedTexture",button)
  211.   SetupTexture(highlightTexture,cfg.highlightTexture,"SetHighlightTexture",button)
  212.   SetupTexture(checkedTexture,cfg.checkedTexture,"SetCheckedTexture",button)
  213.  
  214.   --cooldown
  215.   SetupCooldown(cooldown,cfg.cooldown)
  216.  
  217.   --hotkey, count
  218.   SetupFontString(hotkey,cfg.hotkey)
  219.   SetupFontString(count,cfg.count)
  220.  
  221.   button.__styled = true
  222. end
  223.  
  224. function rButtonTemplate:StyleItemButton(button,cfg)
  225.  
  226.   if not button then return end
  227.   if button.__styled then return end
  228.  
  229.   local buttonName = button:GetName()
  230.   local icon = _G[buttonName.."IconTexture"]
  231.   local count = _G[buttonName.."Count"]
  232.   local stock = _G[buttonName.."Stock"]
  233.   local searchOverlay = _G[buttonName.."SearchOverlay"]
  234.   local border = button.IconBorder
  235.   local normalTexture = button:GetNormalTexture()
  236.   local pushedTexture = button:GetPushedTexture()
  237.   local highlightTexture = button:GetHighlightTexture()
  238.   local checkedTexture = button:GetCheckedTexture()
  239.  
  240.   --backdrop
  241.   SetupBackdrop(button,cfg.backdrop)
  242.  
  243.   --textures
  244.   SetupTexture(icon,cfg.icon,"SetTexture",icon)
  245.   SetupTexture(searchOverlay,cfg.searchOverlay,"SetTexture",searchOverlay)
  246.   SetupTexture(border,cfg.border,"SetTexture",border)
  247.   SetupTexture(normalTexture,cfg.normalTexture,"SetNormalTexture",button)
  248.   SetupTexture(pushedTexture,cfg.pushedTexture,"SetPushedTexture",button)
  249.   SetupTexture(highlightTexture,cfg.highlightTexture,"SetHighlightTexture",button)
  250.   SetupTexture(checkedTexture,cfg.checkedTexture,"SetCheckedTexture",button)
  251.  
  252.   --count+stock
  253.   SetupFontString(count,cfg.count)
  254.   SetupFontString(stock,cfg.stock)
  255.  
  256.   button.__styled = true
  257.  
  258. end
  259.  
  260. function rButtonTemplate:StyleAllActionButtons(cfg)
  261.   for i = 1, NUM_ACTIONBAR_BUTTONS do
  262.     rButtonTemplate:StyleActionButton(_G["ActionButton"..i],cfg)
  263.     rButtonTemplate:StyleActionButton(_G["MultiBarBottomLeftButton"..i],cfg)
  264.     rButtonTemplate:StyleActionButton(_G["MultiBarBottomRightButton"..i],cfg)
  265.     rButtonTemplate:StyleActionButton(_G["MultiBarRightButton"..i],cfg)
  266.     rButtonTemplate:StyleActionButton(_G["MultiBarLeftButton"..i],cfg)
  267.   end
  268.   for i = 1, 6 do
  269.     rButtonTemplate:StyleActionButton(_G["OverrideActionBarButton"..i],cfg)
  270.   end
  271.   --petbar buttons
  272.   for i=1, NUM_PET_ACTION_SLOTS do
  273.     rButtonTemplate:StyleActionButton(_G["PetActionButton"..i],cfg)
  274.   end
  275.   --stancebar buttons
  276.   for i=1, NUM_STANCE_SLOTS do
  277.     rButtonTemplate:StyleActionButton(_G["StanceButton"..i],cfg)
  278.   end
  279.   --possess buttons
  280.   for i=1, NUM_POSSESS_SLOTS do
  281.     rButtonTemplate:StyleActionButton(_G["PossessButton"..i],cfg)
  282.   end
  283. end
  284.  
  285. function rButtonTemplate:StyleAuraButton(button, cfg)
  286.   if not button then return end
  287.   if button.__styled then return end
  288.  
  289.   local buttonName = button:GetName()
  290.   local icon = _G[buttonName.."Icon"]
  291.   local count = _G[buttonName.."Count"]
  292.   local duration = _G[buttonName.."Duration"]
  293.   local expires = _G[buttonName.."Expires"]
  294.   local border = _G[buttonName.."Border"]
  295.   local symbol = button.symbol
  296.   local timer = 0
  297.  
  298.   --backdrop
  299.   SetupBackdrop(button,cfg.backdrop)
  300.  
  301.   --textures
  302.   SetupTexture(icon,cfg.icon,"SetTexture",icon)
  303.   SetupTexture(border,cfg.border,"SetTexture",border)
  304.  
  305.   --create a normal texture on the aura button
  306.   if cfg.normalTexture and cfg.normalTexture.file then
  307.     button:SetNormalTexture(cfg.normalTexture.file)
  308.     local normalTexture = button:GetNormalTexture()
  309.     SetupTexture(normalTexture,cfg.normalTexture,"SetNormalTexture",button)
  310.   end
  311.    
  312.  
  313.   --count,duration,symbol
  314.   SetupFontString(count,cfg.count)
  315.   SetupFontString(duration,cfg.duration)
  316.   SetupFontString(symbol,cfg.symbol)
  317.  
  318.   button.__styled = true
  319. end
  320.  
  321.  
  322. hooksecurefunc("AuraButton_Update", function(self, index, filter)
  323. local buffButtonIndex = 0
  324.     for i = buffButtonIndex, BUFF_MAX_DISPLAY do
  325.         local button = _G["BuffButton"..i]
  326.         BuffStatusBar = CreateFrame("StatusBar", nil, button)
  327.         BuffStatusBar:SetFrameStrata("HIGH")
  328.         BuffStatusBar:SetSize(32, 6)
  329.         BuffStatusBar:SetPoint("BOTTOM", button, 0, -8)
  330.         BuffStatusBar:SetStatusBarTexture("Interface\\AddOns\\Roth_UI\\media\\statusbar3")
  331.         BuffStatusBar:SetStatusBarColor(0,1,0)
  332.        
  333.         local _, _, _, _, _, dur, exps = UnitAura(PlayerFrame.unit, index, filter)
  334.         BuffStatusBar:SetMinMaxValues(dur - exps, exps)
  335.     end
  336. end)
  337.  
  338.  
  339.  
  340.  
  341. --style player BuffFrame buff buttons
  342. local buffButtonIndex = 1
  343. function rButtonTemplate:StyleBuffButtons(cfg)
  344.   local function UpdateBuffButtons()
  345.     if buffButtonIndex > BUFF_MAX_DISPLAY then return end
  346.     for i = buffButtonIndex, BUFF_MAX_DISPLAY do
  347.       local button = _G["BuffButton"..i]
  348.       if not button then break end
  349.       rButtonTemplate:StyleAuraButton(button, cfg)
  350.       if button.__styled then buffButtonIndex = i+1 end
  351.     end
  352.   end
  353.   hooksecurefunc("BuffFrame_UpdateAllBuffAnchors", UpdateBuffButtons)
  354. end
  355.  
  356.  
  357.  
  358. --style player BuffFrame debuff buttons
  359. function rButtonTemplate:StyleDebuffButtons(cfg)
  360.   local function UpdateDebuffButton(buttonName, i)
  361.     local button = _G["DebuffButton"..i]
  362.     rButtonTemplate:StyleAuraButton(button, cfg)
  363.   end
  364.   hooksecurefunc("DebuffButton_UpdateAnchors", UpdateDebuffButton)
  365. end
  366.  
  367. --style player TempEnchant buttons
  368. function rButtonTemplate:StyleTempEnchants(cfg)
  369.   rButtonTemplate:StyleAuraButton(TempEnchant1, cfg)
  370.   rButtonTemplate:StyleAuraButton(TempEnchant2, cfg)
  371.   rButtonTemplate:StyleAuraButton(TempEnchant3, cfg)
  372. end
  373.  
  374. --style all aura buttons
  375. function rButtonTemplate:StyleAllAuraButtons(cfg)
  376.   rButtonTemplate:StyleBuffButtons(cfg)
  377.   rButtonTemplate:StyleDebuffButtons(cfg)
  378.   rButtonTemplate:StyleTempEnchants(cfg)
  379. end
  Reply With Quote
08-27-16, 11:58 AM   #2
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
First and foremost. You can do this in a seperate addon. There is no need to interfere with any other addon. All you need is an addon that hooks the function where aura duration is set.

Secondly you are again making frames (statusbars) without checking if you already created them...in a function that is probably triggered on UNIT_AURA. Don't do that. On top of that I think your statusbar is global?

The error is because the variable "dur" is nil. But my guess is that the buff just does not exist. Make sure that UnitAura(unit, index, filter) actually returns an aura by checking for the name variable.
https://github.com/tomrus88/Blizzard...Frame.lua#L117

I will put together some code. Give me a second.

Lua Code:
  1. local function CreateBar(button)
  2.   local bar = CreateFrame("StatusBar", nil, button)
  3.   bar:SetMinMaxValues(0,1)
  4.   bar:SetValue(0)
  5.   --position/size the bar
  6.   bar:SetPoint("BOTTOMLEFT")
  7.   bar:SetPoint("BOTTOMRIGHT")
  8.   bar:SetHeight(10)
  9.   return bar
  10. end
  11.  
  12. local function UpdateDuration(button, timeleft)
  13.  
  14.   if not button then return end
  15.   button.durationBar = button.durationBar or CreateBar(button)
  16.  
  17.   --set statusbar value
  18.   print(button:GetID(),button.unit,button.filter,button.timeMod,button.expirationTime,timeLeft,GetTime())
  19.   --calculate the value
  20.   --hmm it may be possible that we do need the buff duration, if so we need to get it via unit_aura
  21.   local name, rank, texture, count, debuffType, duration, expirationTime, _, _, _, spellId, _, _, _, _, timeMod = UnitAura(button.unit, button:GetID(), button.filter)
  22.   --exipirationTime-duration = minValue
  23.   --expirationTime = maxValue
  24.   --GetTime() = value
  25.   button.durationBar:SetMinMaxValues(exipirationTime-duration, exipirationTime)
  26.   button.durationBar:SetValue(GetTime())
  27.  
  28. end
  29.  
  30. hooksecurefunc("AuraButton_UpdateDuration", UpdateDuration)
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 08-27-16 at 12:37 PM.
  Reply With Quote
08-27-16, 12:47 PM   #3
Joker119
A Flamescale Wyrmkin
 
Joker119's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2014
Posts: 113
I actually had the idea of doing it as a seperate addon aswell, but wasn't sure where to start.

The reason for not checking if they were created is I assumed doing it in a for i function would only create the statusbar once for each buff on the frame?
Perhaps this still isn't sufficient.

I will get to work applying the code and get it working! thanks!
  Reply With Quote
08-27-16, 01:11 PM   #4
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
When you create the bar you can add this script

Lua Code:
  1. button.duration:HookScript("OnShow",bar.Show)
  2. button.duration:HookScript("OnHide",bar.Hide)
  3. bar:Hide()

That way the bar shows/hides itself based on the duration fontstring.
On top of that you can still hide the duration fontstring itself by setting its alpha value to 0 if you want to.
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)
  Reply With Quote
08-28-16, 07:04 AM   #5
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
The same problem/feature is also addressed in this thread:
https://www.wowinterface.com/forums/...ad.php?t=54269

There may be some useful code in there to get you started.
__________________
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-28-16, 08:01 AM   #6
Joker119
A Flamescale Wyrmkin
 
Joker119's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2014
Posts: 113
Originally Posted by Phanx View Post
The same problem/feature is also addressed in this thread:
https://www.wowinterface.com/forums/...ad.php?t=54269

There may be some useful code in there to get you started.
That's originally where I started, infact, but oddly I wasn't able to adapt it, kept having errors with
Code:
local _, _, _, _, _, dur, exps = UnitAura(PlayerFrame.unit, index, filter)
    if dur > 0 and exps then
it kept throwing "attempt to compare number to nil" errors.

I finally settled on embeding ShinyBuffs in place of rBuffFrame and disabling rButtonTemplate's aurabutton styling. (embeded with Seerah's permission, of course)
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Buff Statusbars


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