09-14-12, 04:48 PM | #1 |
oUF_AuraBars
So I tried modifying/adding some code to this plug in. Essentially I'd like 4 aura blocks, player buffs, player debuffs, target buffs, target debuffs.
It seemed to me there was no easy way to separate buff from debuff other than to write a separate function that only chose buffs, and alter the current function to only choose debuffs. The following is the code that I came up with: http://pastebin.com/V0uFmRGD Code:
Message: Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:271: Usage: UnitDebuff("unit", [index] or ["name", "rank"][, "filter"]) Time: 09/14/12 18:46:54 Count: 1 Stack: [C]: ? [C]: ? Interface\FrameXML\RestrictedFrames.lua:604: in function <Interface\FrameXML\RestrictedFrames.lua:603> Interface\FrameXML\RestrictedFrames.lua:742: in function `CallMethod' [string " local header = self:GetParent()..."]:44: in function <[string " local header = self:GetParent()..."]:1> (tail call): ? [C]: ? Interface\FrameXML\RestrictedExecution.lua:441: in function <Interface\FrameXML\RestrictedExecution.lua:412> Interface\FrameXML\SecureGroupHeaders.lua:108: in function <Interface\FrameXML\SecureGroupHeaders.lua:102> Interface\FrameXML\SecureGroupHeaders.lua:158: in function <Interface\FrameXML\SecureGroupHeaders.lua:115> Interface\FrameXML\SecureGroupHeaders.lua:393: in function <Interface\FrameXML\SecureGroupHeaders.lua:382> [C]: in function `Show' Interface\FrameXML\SecureStateDriver.lua:100: in function <Interface\FrameXML\SecureStateDriver.lua:95> Interface\FrameXML\SecureStateDriver.lua:164: in function <Interface\FrameXML\SecureStateDriver.lua:146> [C]: in function `SetAttribute' Interface\FrameXML\SecureStateDriver.lua:11: in function `RegisterAttributeDriver' Interface\AddOns\oUF\ouf.lua:411: in function `SpawnHeader' Interface\AddOns\oUF_Skaarj\layout.lua:442: in function `func' Interface\AddOns\oUF\factory.lua:13: in function <Interface\AddOns\oUF\factory.lua:10> (tail call): ? Locals: <none> |
|
09-14-12, 06:05 PM | #2 |
This is the problem:
Code:
oUF:AddElement('AuraBars', UpdateBuff, UpdateDebuff, EnableBuff, EnableDebuff, DisableBuff, DisableDeuff) (Also, "DisableDeuff" is misspelled.) If you want separate elements for buffs and debuffs, you need to add them separately: Code:
oUF:AddElement('AuraBarsBuff', UpdateBuff, EnableBuff, DisableBuff) oUF:AddElement('AuraBarsDebuff', UpdateDebuff, EnableDebuff, DisableDebuff) Also, a lot of that code is really inefficient; I'm not sure whether that was in the original module, or part of your changes. Creating 2-82 tables every time the unit's auras change (1-41 in each UpdateBuff and UpdateDebuff) is basically a memory leak, and your module will consume memory like a horde of kids in a candy store. Reuse tables as much as possible, instead of simply discarding them and creating new ones. Consistent indentation, and separating blocks with empty lines, will also help the code be more readable. Compare your UpdateDebuff function with: Code:
local debuffs = {} -- Only create one table, and reuse it. local function UpdateDebuff(self, event, unit) if self.unit ~= unit then return end local auraBarsDebuff = self.AuraBarsDebuff local numDebuffs = 0 for index = 1, 40 do local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellID = UnitDebuff(unit, index) if not name then break end if auraBarsDebuff.filter(self, unit, name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellID) then local t = debuffs[i] or {} -- Reuse tables where possible. t.name = name t.rank = rank t.icon = icon t.count = count t.debuffType = debuffType t.duration = duration t.expirationTime = expirationTime t.unitCaster = unitCaster t.isStealable = isStealable t.noTime = duration == 0 and expirationTime == 0 t.filter = auraBarsDebuff.enemyAuraType t.shouldConsolidate = shouldConsolidate t.spellID = spellID debuffs[i] = t numDebuffs = i end end -- Clear unused debuff slots. for i = numDebuffs + 1, #debuffs do debuffs[i] = nil -- wipe(debuffs[i]) would be better, but then you would need to either: -- (a) accomodate empty tables in your sort function, putting them at the end, -- or (b) introduce a table pool and recycling scheme. end if auraBarsDebuff.sort then table.sort(debuffs, type(auraBarsDebuff.sort) == 'function' and auraBarsDebuff.sort or nil) -- no need to pass the global "sort" end local bars = auraBarsDebuff.bars for index = 1, #debuffs do if auraBarsDebuff:GetWidth() == 0 then break end local frame = bars[index] if not frame then frame = CreateAuraBar(self, index == 1 and auraBarsDebuff or bars[index - 1]) bars[index] = frame end local bar = frame.statusBar frame.index = index local aura = debuffs[index] bar.aura = aura if aura.noTime then -- you already have a local aura, no need to spend an extra table lookup getting it out of bar.aura bar:SetMinMaxValues(0, 1) bar:SetValue(1) else if auraBarsDebuff.scaleTime then local maxvalue = math.min(auraBarsDebuff.scaleTime, bar.aura.duration) bar:SetMinMaxValues(0, maxvalue) bar:SetWidth((maxvalue/auraBarsDebuff.scaleTime)*((auraBarsDebuff.auraBarWidth or auraBarsDebuff:GetWidth())-(bar:GetHeight()+(auraBarsDebuff.gap or 0))))-- icon size + gap else bar:SetMinMaxValues(0, aura.duration) end bar:SetValue(aura.expirationTime - GetTime()) end bar.icon:SetTexture(aura.icon) bar.spellname:SetText(aura.count > 1 and string.format("%s [%d]", bar.aura.name, aura.count) or aura.name) bar.spelltime:SetText(not bar.noTime and FormatTime(aura.expirationTime-GetTime())) local debuffType = aura.debuffType or 'none' r, g, b = DebuffTypeColor[debuffType].r, DebuffTypeColor[debuffType].g, DebuffTypeColor[debuffType].b if auraBarsDebuff.debuffColor then r, g, b = unpack(auraBarsDebuff.debuffColor) end bar:SetStatusBarColor(r, g, b) frame:Show() end for index = #auras + 1, #bars do bars[index]:Hide() end if auraBarsDebuff.PostUpdate then auraBarsDebuff:PostUpdate(event, unit) end end
__________________
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 : 09-14-12 at 06:29 PM. |
|
09-15-12, 10:33 AM | #3 |
First off, thank you for taking the time to fix and optimize my code that you'll never use. That's pretty awesome.
Secondly, I put your suggested code in, but I'm getting this pretty frustrating error. I can't seem to put my finger on what causes it. Sometimes I don't get it for a few minutes, sometimes it's as I start attacking something. Code:
Message: Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:331: attempt to index local 'aura' (a nil value) Time: 09/15/12 19:54:32 Count: 31 Stack: Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:331: in function `func' Interface\AddOns\oUF\events.lua:14: in function <Interface\AddOns\oUF\events.lua:12> (tail call): ? Code:
Message: Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:331: attempt to index local 'aura' (a nil value) Time: 09/15/12 19:54:29 Count: 2 Stack: Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:331: in function `func' Interface\AddOns\oUF\ouf.lua:117: in function <Interface\AddOns\oUF\ouf.lua:110> (tail call): ? [C]: in function `Show' Interface\FrameXML\SecureStateDriver.lua:83: in function <Interface\FrameXML\SecureStateDriver.lua:73> Interface\FrameXML\SecureStateDriver.lua:137: in function <Interface\FrameXML\SecureStateDriver.lua:119> Code:
Message: Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:331: attempt to index local 'aura' (a nil value) Time: 09/15/12 19:55:42 Count: 1 Stack: Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:331: in function `func' Interface\AddOns\oUF\ouf.lua:117: in function <Interface\AddOns\oUF\ouf.lua:110> (tail call): ? [C]: in function `CameraOrSelectOrMoveStop' [string "CAMERAORSELECTORMOVE"]:4: in function <[string "CAMERAORSELECTORMOVE"]:1> Code:
Message: Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:163: attempt to index field 'aura' (a nil value) Time: 09/15/12 19:55:48 Count: 306 Stack: Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:163: in function <Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:150> http://pastebin.com/SK47CrRG Last edited by sirann : 09-15-12 at 05:58 PM. |
|
09-16-12, 01:27 AM | #4 |
Oh, I think I see what the problem is. Try this:
Code:
local debuffs = {} local function UpdateDebuff(self, event, unit) if self.unit ~= unit then return end local DebuffBars = self.DebuffBars local numDebuffs = 0 for i = 1, 40 do local name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellID = UnitDebuff(unit, i) if not name then break end if DebuffBars.filter(self, unit, name, rank, icon, count, debuffType, duration, expirationTime, unitCaster, isStealable, shouldConsolidate, spellID) then numDebuffs = numDebuffs + 1 local t = debuffs[numDebuffs] if not t then t = table_create() debuffs[numDebuffs] = t end t.name = name t.rank = rank t.icon = icon t.count = count t.debuffType = debuffType t.duration = duration t.expirationTime = expirationTime t.unitCaster = unitCaster t.isStealable = isStealable t.noTime = duration == 0 and expirationTime == 0 t.filter = DebuffBars.enemyAuraType t.shouldConsolidate = shouldConsolidate t.spellID = spellID end end for i = #debuffs, numDebuffs + 1, -1 do debuffs[i] = table_delete(debuffs[i]) end table.sort(debuffs, DebuffBars.sort or default_sort) local bars = DebuffBars.bars for i = 1, numDebuffs do if DebuffBars:GetWidth() == 0 then break end local bar = bars[i] if not bar then bar = CreateAuraBar(self, i == 1 and DebuffBars or bars[i - 1]) bars[i] = bar end bar:Show() local statusbar = bar.statusBar local debuff = debuffs[i] bar.aura = debuff if debuff.noTime then -- something weird here statusbar:SetMinMaxValues(0, 1) statusbar:SetValue(1) else if DebuffBars.scaleTime then local maxvalue = math.min(DebuffBars.scaleTime, debuff.duration) statusbar:SetMinMaxValues(0, maxvalue) statusbar:SetWidth((maxvalue/DebuffBars.scaleTime)*((DebuffBars.auraBarWidth or DebuffBars:GetWidth())-(statusbar:GetHeight()+(DebuffBars.gap or 0))))-- icon size + gap else statusbar:SetMinMaxValues(0, debuff.duration) end statusbar:SetValue(debuff.expirationTime - GetTime()) end statusbar.icon:SetTexture(debuff.icon) statusbar.spellname:SetText(debuff.count > 1 and format("%s [%d]", debuff.name, debuff.count) or debuff.name) statusbar.spelltime:SetText(not debuff.noTime and FormatTime(debuff.expirationTime - GetTime())) local r, g, b local color = DebuffBars.debuffColor if color then r, g, b = color[1], color[2], color[3] -- don't use unpack; 3 table lookups is faster than 1 function call else color = DebuffTypeColor[debuff.debuffType or "none"] r, g, b = color.r, color.g, color.b end statusbar:SetStatusBarColor(r, g, b) end for i = numDebuffs + 1, #bars do local bar = bars[i] bar.aura = table_delete(bar.aura) bar:Hide() end end Code:
local table_create, table_delete do local pool = { } local function table_create() local t = next(pool) if t then pool[t] = nil end return t or {} end local function table_delete(t) if type(t) == "table" then for k, v in pairs(t) do t[k] = nil end t[true] = true t[true] = nil pool[t] = true end return nil end end local default_sort = function(a, b) if a.noTime then if b.noTime then -- both timeless, sort by name REVERSE return a.name < b.name else -- a timeless, b not return true end else if b.noTime then -- b timeless, a not return false else -- neither timeless, sort by expiry time return a.expires > b.expires end end end
__________________
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 : 09-16-12 at 10:33 PM. |
|
09-16-12, 11:34 AM | #5 |
Relevant section(s) can be found here:
http://pastebin.com/53q2b56C targeting friendly or non-friendly throws this error: Message: Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:257: attempt to call upvalue 'table_create' (a nil value) |
|
09-16-12, 10:33 PM | #6 |
Code:
local pool = { } local function table_new()
__________________
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. |
|
09-17-12, 05:21 AM | #7 |
I figured that's what it was. I changed it accordingly and still receive the same error.
turning it into "function table_create()" removing the local, throws the following error: Message: Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:163: attempt to index field 'aura' (a nil value), OnUpdate. Last edited by sirann : 09-17-12 at 06:47 AM. |
|
09-17-12, 10:45 AM | #8 |
So if I'm understanding this correctly, we make a table for buffs with: local buffs = {}
We then make a function, for simplicity sake we'll just stick with the buffs. The function is called UpdateBuffs. It only updates when an event fires, which we register with self:RegisterEvent('UNIT_AURA', UpdateBuff). This function is also unit bound, so there can be target buffs, player buffs, focus buff, insert x frame category buffs all shown independently, and they all update independently. IE, when the player gains a buff, it doesn't cause the target buff UpdateBuff function to fire, thus unnecessarily increasing cpu load. Additionally it's set to fire only for HELPFUL aura changes. So it won't update when the unit gains or loses a debuff. Next we set a variable, numBuffs to 0. We then set up our index to start at unit buff 1 get all the information from the UnitBuff api at that position, and store them in local variables set up. It continues to check each buff until it doesn't receive a name back (aka out of buffs to check) and breaks. We create a local t and set it to the individual index of our buffs table created earlier (IE buffs[numBuffs]) so why don't we just use buffs[i] since whatever buff data we just got will be buff number i? We then set up an if statement, Lua Code:
I don't fully understand this, we're checking to see if we have t, or anything in our buffs table. If we don't we create a table? We then set buffs[i].locals to the locals that were set with the UnitBuff api. We now set up a new for statement Lua Code:
so basically we start with the number of buffs in our buffs table and go to the total number of buffs found with numBuffs (isn't that the same as #buffs), and then continue till i = -1? I don't understand the 3 part for loop I guess. We then sort the buffs using either the BuffsBars.sort function or default_sort. Now we make a for loop starting at 1 and going until we run out of buffs. The loop makes a bar for each buff and breaks if the width of the bars is set to 0. We create and set a local bar = to bars[i] which is essentially BuffBars.bars[i]. If it discovers there's no bar made yet, it makes it, and decreases the i by one to redo the loop for that buff. We then show the bar. We create a local statusBar and set it to bar.statusBar which is essentially bars[i].statusBar which is BuffBars.bars[i].statusBar. We also create a local buff and set it to the individual i in our buffs table. Now we set bar.aura = buff. This I don't understand, we say that BuffBars.bars[i].aura = buff or in other words BuffBars.bars[i].aura = buffs[i]. Where did .aura even come from? I think this may be where a lot of issue is coming from. I don't see the .aura set up anywhere else. I don't know, I'm pretty awful at coding so maybe I'm just misreading this |
|
09-17-12, 07:27 PM | #9 | ||||
Please post your current whole file; without it, identifying the cause of any error is pretty much impossible.
So the above code starts with the total number of values in the buffs table, and increments it down by -1 on each iteration, until it reaches the last index we actually used on this pass, and erases all of the unused ones. A simpler version would be to clear all of the indices first: Code:
for i = 1, #buffs do buffs[i] = table_delete(buffs[i]) end Code:
local t = table_create() buffs[numBuffs] = t
Code:
local bar = {} local aura = { name = "Blah" } bar.aura = aura print(bar.aura.name) ==> "Blah"
__________________
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. |
|||||
09-17-12, 09:59 PM | #10 |
Here's my current code that's still throwing the error every frame for trying to index aura:
http://pastebin.com/Prhi0c52 and this is the error: http://pastebin.com/5SJTJFPB I've commented several things in the UpdateBars function as well as in the UpdateBuff function to see if there's a disconnect in the order. This is the if statement the error is in: Lua Code:
Compared to: Lua Code:
|
|
09-18-12, 12:30 AM | #11 |
In your last example:
Code:
local buff = buffs[i] bar.aura = aura --BuffBars.bars[i].aura In your current file, line 305: Code:
local bar = bars[i] --unecessary? se line 267 above Edit: Alright, I just ended up rewriting the whole thing. Tested (as far as the BuffBars element with 2 buffs on a level 12 warlock) and working: http://www.wowace.com/paste/6263/ Example and options in the comment header at the top of the file.
__________________
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 : 09-18-12 at 04:26 AM. |
|
09-18-12, 02:54 PM | #12 |
I'm pretty sure you're going to hate me..
I c/p'd the code from your link /6263. Here's my file of it: http://pastebin.com/53q2b56C I put this code into my oUF_Skaarj layout target function: http://pastebin.com/5BQKvyGL I received this error Code:
Message: Interface\AddOns\oUF_Skaarj\layout.lua:288: attempt to index global 'frame' (a nil value) (basically just changed all the frame to self, except for the frame inside of the filterFunc.) I then received this error: Code:
Message: Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:279: attempt to compare number with nil Lua Code:
So I realized that count must be setting to nil if the buff/debuff doesn't have a stack, ie something like a mount. So I changed the code from Lua Code:
to this Lua Code:
And now I receive this error: Code:
Message: Interface\AddOns\oUF_AuraBars\oUF_AuraBars.lua:292: Usage: <unnamed>:SetMinMaxValues(min, max) Lua Code:
Last edited by sirann : 09-18-12 at 03:00 PM. |
|
09-18-12, 09:36 PM | #13 |
You should really use the entire file I posted; you left half of it out in your paste, and my code was not even remotely designed to be dropped into the middle of some other code. It's a total rewrite from scratch, not just a few changes here and there. If you're using code in your layout based on the example in the file I posted, of course you're going to get endless errors if you're not actually using the file I posted.
__________________
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. |
|
09-19-12, 05:55 AM | #14 |
It took me a few minutes to figure out what you could have been referring to, the original pastebin link I have is invalid. That's not what I have as my file. I have this as my file: http://pastebin.com/nLRdQH6y
I apologize for the mix up in the links I sent out. |
|
09-19-12, 04:38 PM | #15 |
I have no idea why you changed all of the variable names in my code. Variables are not aware of their names, only their values. You only need to pass in the right value from your code. In your code, the frame object is the value of the variable named "self", so you need to pass "self" into the function. It doesn't matter if the function then refers to that value as "frame" or "kazoo". Only the order of arguments matter.
A more efficient solution to the nil count problem is to store nil counts as 1 in the first place, since that's techincally accurate; a buff with no charges effectively has 1 charge. Finally, while I'm not really picky about being credited for stuff, I have put a lot of time into helping you with this, and does seem a little insulting that you would remove the "Rewritten by Phanx" comment from the file, when it being there has absolutely no effect on the functionality of the file because it's in a comment. Fixed count issue: http://www.wowace.com/paste/6276/ Don't change random variable names in the module; just pass the right value from your code: Code:
target = function(self, ...) Shared(self, ...) local BuffBars = CreateFrame("Frame", nil, self) BuffBars:SetPoint("BOTTOMLEFT", self, "TOPLEFT", 20, 10) BuffBars:SetPoint("BOTTOMRIGHT", self, "TOPRIGHT", 0, 10) self.BuffBars = BuffBars BuffBars.barHeight = 15 BuffBars.fontFile = cfg.font BuffBars.fontOutline = "MONOCHROMETHINOUTLINE" BuffBars.nameSize = 8 BuffBars.timeSize = 9 BuffBars.customFilter = function() return true end -- No need to catch incoming arguments and assign them to named variables when you're not using any of them.
__________________
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. |
|
09-19-12, 06:13 PM | #16 |
First let me apologize for the misunderstanding that's seemingly occurred. I never removed your "Rewritten by Phanx" from the beginning instructions. If you look at your first pass at the code, it wasn't there. I must have copied it by mistake and thus it wasn't in my file. I will revise by saying I didn't touch the comment up there, the version I copied (mistakenly) did not have that comment.
Secondly, I want to thank you for the time you've put into writing this addon. It's hard for me to show appreciation, especially when you probably think I'm an idiot who keeps ****ing up your code and posting the oops aftermath. Thirdly, your latest revision, 6276, you added the "or 0" to count. You also have to do this for duration, as timeless buffs/debuffs are set to nil, this messes with your later if statement and throws an error: Lua Code:
Line 46 should read: local format, min, next, pairs, type, sort = format, min, next, pairs, type, sort the type, sort were backwards. I also added if not name then break end to the Update function under the if filterFunc(... Line 81 should read return a.duration > b.duration or maybe a.expirationTime > b.expirationTime. Either way expires won't work. Line 221 was a function calling itself causing a stack overflow I believe: Lua Code:
The commented out code was the line you posted in your latest revision, the t[k] = nil was the line that was in your previous table_delete(t) function. Fourthly, this is working exactly how I wanted it. I don't know what to say besides thank you for making a reality what I've dreamt about for a few years. My final request is to be able to color bars by dispelType, DebuffTypeColor[element.dispelType or "none"] for debuffs but not buffs Last edited by sirann : 09-19-12 at 09:07 PM. |
|
09-20-12, 02:07 AM | #17 | |
UnitAura actually seems to be returning 0 for both count and duration on auras with no charges or duration, respectively, but I've added some more checks just in case.
http://www.wowace.com/paste/6279/
__________________
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. |
||
01-19-15, 01:01 PM | #18 |
Holy mother of necros, but, I'm curious if you think it would be possible to edit either the oUF_AuraBars.lua or my oUF layout to check (on PLAYER_TARGET_CHANGED) if the target is the same unit as one of the boss frames, and if so, hide the debuffbar frame associated with the respective boss..n's frame. All attempts thus far have either, a, caused an LUA error, or b, caused it to hide both target and all said boss' debuffbar frame.
I suppose I could write something in the oUF_AuraBars code that would create a frame, registerevent player_target_changed, and then do an on event script of Lua Code:
Would that last suggestion even work? |
|
01-19-15, 04:46 PM | #19 |
Possible, certainly, but that snippet you posted has a syntax error on almost every line.
1. The proper format is "for ... do" just like "if ... then" -- you are missing the "do" keyword. 2. You have an "if ... else ... end" inside of a "do ... (end)" but you are missing the last "end" keyword. 3. The second and third lines will throw errors about attempting to concatenate nil values. You need to (a) put quotes around the "oUF_TerennaBoss" part to make it a string value and (b) wrap that and the "..i" in a _G[...] lookup to actually get a refererence to the global object. Code:
for i = 1, 5 do if UnitIsUnit('target', 'boss'..i) then _G["oUF_TerennaBoss"..i].DebuffBars:Hide() else _G["oUF_TerennaBoss"..i].DebuffBars:Show() end end
__________________
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. |
|
01-19-15, 05:13 PM | #20 | |
e: where are my manners, thank you very much, as always, Phanx! Last edited by sirann : 01-19-15 at 05:17 PM. |
||
WoWInterface » Featured Projects » oUF (Otravi Unit Frames) » oUF_AuraBars |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Linear Mode |
Switch to Hybrid Mode |
Switch to Threaded Mode |
|
|