From 102f89565e2f439eeb84b68ee53ba34bdc43956a Mon Sep 17 00:00:00 2001 From: Xruptor Date: Wed, 18 Apr 2012 10:44:01 -0400 Subject: [PATCH] -Added player buff display -Added "/xbt target" to toggle display of target buffs -Added "/xbt focus" to toggle display of focus buffs -Added "/xbt player" to toggle display of player buffs -Added "/xbt infinite" to toggle display of buffs with no duration/timers. (Infinite buffs) -Added "/xbt icon" to toggle display of buff icons -Added "/xbt spellname" to toggle display of spell names -Created a new player anchor for the new player buff display -Added a new function to clean and refresh the buffs -Updated the slash command listing -Changed the way that infinite auras are processed and displayed. Now infinite auras will be slightly transparent compared to those with actual timers. -Changed the layout of the bar creation scheme to support new spellnames. -Updated the way buffs are processed to reflect the icon, spellname, and infinite auras changes. -Changed the way that stacks are displayed based on if icon is visible -Completely redid the sorting algorithum to support the new infinite auras. They will always be displayed first or last depending on the user grow bars option. -Updated the RestoreLayout and SaveLayout routines. I will be doing this for all my addons. -Inifnite auras will always be a light shade of blue. This is to distinguish it from other buffs with timers. --- XanBuffTimers.lua | 312 +++++++++++++++++++++++++++++++++++------------------ XanBuffTimers.toc | 4 +- 2 files changed, 209 insertions(+), 107 deletions(-) diff --git a/XanBuffTimers.lua b/XanBuffTimers.lua index ab2fd16..bcfd5dc 100644 --- a/XanBuffTimers.lua +++ b/XanBuffTimers.lua @@ -1,22 +1,24 @@ -local timers = {} +local timersTarget = {} local timersFocus = {} +local timersPlayer = {} local MAX_TIMERS = 15 local ICON_SIZE = 20 local BAR_ADJUST = 25 local BAR_TEXT = "llllllllllllllllllllllllllllllllllllllll" local band = bit.band - local targetGUID = 0 local focusGUID = 0 +local playerGUID = 0 local UnitAura = UnitAura local UnitIsUnit = UnitIsUnit local UnitGUID = UnitGUID local UnitName = UnitName local pointT = { - ["target"] = "XBT_Anchor", + ["target"] = "XBT_TargetAnchor", ["focus"] = "XBT_FocusAnchor", + ["player"] = "XBT_PlayerAnchor", } local f = CreateFrame("frame","xanBuffTimers",UIParent) @@ -32,15 +34,20 @@ function f:PLAYER_LOGIN() if XBT_DB.scale == nil then XBT_DB.scale = 1 end if XBT_DB.grow == nil then XBT_DB.grow = false end if XBT_DB.sort == nil then XBT_DB.sort = false end - if XBT_DB.auras == nil then XBT_DB.auras = false end - if XBT_DB.onlyFocus == nil then XBT_DB.onlyFocus = false end + if XBT_DB.showTarget == nil then XBT_DB.showTarget = true end + if XBT_DB.showFocus == nil then XBT_DB.showFocus = true end + if XBT_DB.showPlayer == nil then XBT_DB.showPlayer = true end + if XBT_DB.showInfinite == nil then XBT_DB.showInfinite = false end + if XBT_DB.showIcon == nil then XBT_DB.showIcon = true end + if XBT_DB.showSpellName == nil then XBT_DB.showSpellName = false end --create our anchors - f:CreateAnchor("XBT_Anchor", UIParent, "xanBuffTimers: Target Anchor") + f:CreateAnchor("XBT_TargetAnchor", UIParent, "xanBuffTimers: Target Anchor") f:CreateAnchor("XBT_FocusAnchor", UIParent, "xanBuffTimers: Focus Anchor") + f:CreateAnchor("XBT_PlayerAnchor", UIParent, "xanBuffTimers: Player Anchor") - f:UnregisterEvent("PLAYER_LOGIN") - f.PLAYER_LOGIN = nil + playerGUID = UnitGUID("player") + f:ProcessBuffs("player", timersPlayer) f:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") f:RegisterEvent("PLAYER_TARGET_CHANGED") @@ -54,12 +61,14 @@ function f:PLAYER_LOGIN() if a then if c and c:lower() == "anchor" then - if XBT_Anchor:IsVisible() then - XBT_Anchor:Hide() + if XBT_TargetAnchor:IsVisible() then + XBT_TargetAnchor:Hide() XBT_FocusAnchor:Hide() + XBT_PlayerAnchor:Hide() else - XBT_Anchor:Show() + XBT_TargetAnchor:Show() XBT_FocusAnchor:Show() + XBT_PlayerAnchor:Show() end return true elseif c and c:lower() == "scale" then @@ -67,13 +76,14 @@ function f:PLAYER_LOGIN() local scalenum = strsub(msg, b+2) if scalenum and scalenum ~= "" and tonumber(scalenum) then XBT_DB.scale = tonumber(scalenum) - for i=1, MAX_TIMERS do - if timers[i] then - timers[i]:SetScale(tonumber(scalenum)) - end - if timersFocus[i] then - timersFocus[i]:SetScale(tonumber(scalenum)) - end + for i=1, #timersTarget do + timersTarget[i]:SetScale(tonumber(scalenum)) + end + for i=1, #timersFocus do + timersFocus[i]:SetScale(tonumber(scalenum)) + end + for i=1, #timersPlayer do + timersPlayer[i]:SetScale(tonumber(scalenum)) end DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Scale has been set to ["..tonumber(scalenum).."]") return true @@ -97,32 +107,68 @@ function f:PLAYER_LOGIN() DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Bars sort [|cFF99CC33ASCENDING|r]") end return true + elseif c and c:lower() == "target" then + if XBT_DB.showTarget then + XBT_DB.showTarget = false + f:ClearBuffs(timersTarget) + DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show target tracking [|cFF99CC33OFF|r]") + else + XBT_DB.showTarget = true + f:ProcessBuffs("target", timersTarget) + DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show target tracking [|cFF99CC33ON|r]") + end + return true elseif c and c:lower() == "focus" then - if XBT_DB.onlyFocus then - XBT_DB.onlyFocus = false - DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show only focus target buffs [|cFF99CC33OFF|r]") + if XBT_DB.showFocus then + XBT_DB.showFocus = false + f:ClearBuffs(timersFocus) + DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show focus tracking [|cFF99CC33OFF|r]") else - XBT_DB.onlyFocus = true - DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show only focus target buffs [|cFF99CC33ON|r]") + XBT_DB.showFocus = true + f:ProcessBuffs("focus", timersFocus) + DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show focus tracking [|cFF99CC33ON|r]") end return true - elseif c and c:lower() == "auras" then - if XBT_DB.auras then - XBT_DB.auras = false - DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Buff Auras [|cFF99CC33OFF|r]") + elseif c and c:lower() == "player" then + if XBT_DB.showPlayer then + XBT_DB.showPlayer = false + f:ClearBuffs(timersPlayer) + DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show player tracking [|cFF99CC33OFF|r]") else - XBT_DB.auras = true - DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Buff Auras [|cFF99CC33ON|r]") + XBT_DB.showPlayer = true + f:ProcessBuffs("player", timersPlayer) + DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show player tracking [|cFF99CC33ON|r]") end - --update the buff display - if UnitName("target") and UnitGUID("target") then - targetGUID = UnitGUID("target") - f:ProcessBuffs("target", timers) + return true + elseif c and c:lower() == "infinite" then + if XBT_DB.showInfinite then + XBT_DB.showInfinite = false + DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show buffs whom have no durations/timers (Infinite) [|cFF99CC33OFF|r]") + else + XBT_DB.showInfinite = true + DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show buffs whom have no durations/timers (Infinite) [|cFF99CC33ON|r]") end - if UnitName("focus") and UnitGUID("focus") then - focusGUID = UnitGUID("focus") - f:ProcessBuffs("focus", timersFocus) + f:ReloadBuffs() + return true + elseif c and c:lower() == "icon" then + if XBT_DB.showIcon then + XBT_DB.showIcon = false + DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show buff icons [|cFF99CC33OFF|r]") + else + XBT_DB.showIcon = true + DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show buff icons [|cFF99CC33ON|r]") + end + f:ReloadBuffs() + return true + elseif c and c:lower() == "spellname" then + if XBT_DB.showSpellName then + XBT_DB.showSpellName = false + DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show buff spell names [|cFF99CC33OFF|r]") + else + XBT_DB.showSpellName = true + DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show buff spell names [|cFF99CC33ON|r]") end + f:ReloadBuffs() return true end end @@ -132,26 +178,34 @@ function f:PLAYER_LOGIN() DEFAULT_CHAT_FRAME:AddMessage("/xbt scale # - sets the scale size of the bars") DEFAULT_CHAT_FRAME:AddMessage("/xbt grow - changes the direction in which the bars grow (UP/DOWN)") DEFAULT_CHAT_FRAME:AddMessage("/xbt sort - changes the sorting of the bars. (ASCENDING/DESCENDING)") - DEFAULT_CHAT_FRAME:AddMessage("/xbt auras - toggles the display of permenate/non-cancel auras (ON/OFF)") - DEFAULT_CHAT_FRAME:AddMessage("/xbt focus - toggles buffs only to be displayed for focus target (ON/OFF)") + DEFAULT_CHAT_FRAME:AddMessage("/xbt target - toggles target tracking (ON/OFF)") + DEFAULT_CHAT_FRAME:AddMessage("/xbt focus - toggles focus tracking (ON/OFF)") + DEFAULT_CHAT_FRAME:AddMessage("/xbt player - toggles player tracking (ON/OFF)") + DEFAULT_CHAT_FRAME:AddMessage("/xbt infinite - toggles displaying buffs whom have no duration/timers (ON/OFF)") + DEFAULT_CHAT_FRAME:AddMessage("/xbt icon - toggles displaying of buff icons (ON/OFF)") + DEFAULT_CHAT_FRAME:AddMessage("/xbt spellname - toggles displaying of buff spell names (ON/OFF)") end local ver = tonumber(GetAddOnMetadata("xanBuffTimers","Version")) or 'Unknown' DEFAULT_CHAT_FRAME:AddMessage("|cFF99CC33xanBuffTimers|r [v|cFFDF2B2B"..ver.."|r] loaded: /xbt") + + f:UnregisterEvent("PLAYER_LOGIN") + f.PLAYER_LOGIN = nil end function f:PLAYER_TARGET_CHANGED() - if XBT_DB.onlyFocus then return end + if not XBT_DB.showTarget then return end if UnitName("target") and UnitGUID("target") then targetGUID = UnitGUID("target") - f:ProcessBuffs("target", timers) + f:ProcessBuffs("target", timersTarget) else - f:ClearBuffs(timers) + f:ClearBuffs(timersTarget) targetGUID = 0 end end function f:PLAYER_FOCUS_CHANGED() + if not XBT_DB.showFocus then return end if UnitName("focus") and UnitGUID("focus") then focusGUID = UnitGUID("focus") f:ProcessBuffs("focus", timersFocus) @@ -187,23 +241,29 @@ function f:COMBAT_LOG_EVENT_UNFILTERED(event, timestamp, eventType, hideCaster, --clear the buffs if the unit died --NOTE the reason an elseif isn't used is because some dorks may have --their current target as their focus as well - if dstGUID == targetGUID and not XBT_DB.onlyFocus then - f:ClearBuffs(timers) + if dstGUID == targetGUID and XBT_DB.showTarget then + f:ClearBuffs(timersTarget) targetGUID = 0 end - if dstGUID == focusGUID then + if dstGUID == focusGUID and XBT_DB.showFocus then f:ClearBuffs(timersFocus) focusGUID = 0 end + if dstGUID == playerGUID and XBT_DB.showPlayer then + f:ClearBuffs(timersPlayer) + end elseif eventSwitch[eventType] and band(srcFlags, COMBATLOG_OBJECT_AFFILIATION_MINE) ~= 0 then --process the spells based on GUID - if dstGUID == targetGUID and not XBT_DB.onlyFocus then - f:ProcessBuffs("target", timers) + if dstGUID == targetGUID and XBT_DB.showTarget then + f:ProcessBuffs("target", timersTarget) end - if dstGUID == focusGUID then + if dstGUID == focusGUID and XBT_DB.showFocus then f:ProcessBuffs("focus", timersFocus) end + if dstGUID == playerGUID and XBT_DB.showPlayer then + f:ProcessBuffs("player", timersPlayer) + end end end @@ -293,12 +353,15 @@ local TimerOnUpdate = function(self, time) local beforeEnd local barLength - if XBT_DB.auras and self.durationTime <= 0 then + --this is in case of auras with everlasting buffs (Infinite) + if XBT_DB and XBT_DB.showInfinite and self.durationTime <= 0 then beforeEnd = 0 barLength = string.len(BAR_TEXT) + self:SetAlpha(0.5) else beforeEnd = self.endTime - GetTime() barLength = ceil( string.len(BAR_TEXT) * (beforeEnd / self.durationTime) ) + self:SetAlpha(1) end --check the string length JUST in case for errors @@ -353,12 +416,24 @@ function f:CreateBuffTimers() Frm.timetext = Frm:CreateFontString(nil, "OVERLAY"); Frm.timetext:SetFont("Fonts\\FRIZQT__.TTF",10,"OUTLINE") Frm.timetext:SetJustifyH("RIGHT") - Frm.timetext:SetPoint("RIGHT", Frm.icon, "LEFT" , -5, 0) - + Frm.timetext:SetPoint("LEFT", Frm.icon, "RIGHT", 5, 0) + + Frm.spellText = Frm:CreateFontString(nil, "OVERLAY"); + Frm.spellText:SetFont("Fonts\\FRIZQT__.TTF",10,"OUTLINE") + Frm.spellText:SetTextColor(0,183/255,239/255) + Frm.spellText:SetJustifyH("RIGHT") + Frm.spellText:SetPoint("RIGHT", Frm.icon, "LEFT" , -5, 0) + + Frm.spellText2 = Frm:CreateFontString(nil, "OVERLAY"); + Frm.spellText2:SetFont("Fonts\\FRIZQT__.TTF",10,"OUTLINE") + Frm.spellText2:SetTextColor(0,183/255,239/255) + Frm.spellText2:SetJustifyH("RIGHT") + Frm.spellText2:SetPoint("RIGHT", Frm.icon, "LEFT" , 20, 0) + Frm.Bar = Frm:CreateFontString(nil, "GameFontNormal") Frm.Bar:SetFont(STANDARD_TEXT_FONT, 14, "OUTLINE, MONOCHROME") Frm.Bar:SetText(BAR_TEXT) - Frm.Bar:SetPoint("LEFT", Frm.icon, "RIGHT", 1, 0) + Frm.Bar:SetPoint("LEFT", Frm.icon, "RIGHT", 30, 0) Frm:SetScript("OnUpdate", TimerOnUpdate) @@ -381,30 +456,55 @@ function f:ProcessBuffs(sT, sdTimer) if not name then break end local passChk = false + --only allow non-cancel auras if the user allowed it - if XBT_DB.auras then + if XBT_DB.showInfinite then --auras are on so basically were allowing everything passChk = true - elseif not XBT_DB.auras and duration and duration > 0 then + elseif not XBT_DB.showInfinite and duration and duration > 0 then --auras are not on but the duration is greater then zero, so allow passChk = true end - --UnitIsUnit is used JUST IN CASE (you never know lol) - if passChk and name and unitCaster and UnitIsUnit(unitCaster, "player") then + if passChk and name and unitCaster and unitCaster == "player" then --get the next timer slot we can use slotNum = slotNum + 1 if not sdTimer[slotNum] then sdTimer[slotNum] = f:CreateBuffTimers() end --create the timer if it doesn't exist - if not duration or duration <= 0 then expTime = 0 end --just in case for non-cancel auras + if not duration or duration <= 0 then + sdTimer[slotNum].isInfinite = true + expTime = 0 + else + sdTimer[slotNum].isInfinite = false + end sdTimer[slotNum].id = sT sdTimer[slotNum].spellName = name sdTimer[slotNum].spellId = spellId - sdTimer[slotNum].iconTex = icon - sdTimer[slotNum].icon:SetTexture(icon) + + --change the timer text according if we have icon or not and wether we are displaying spell name or not + if XBT_DB.showIcon then + sdTimer[slotNum].iconTex = icon + sdTimer[slotNum].icon:SetTexture(icon) + sdTimer[slotNum].showIcon = true + sdTimer[slotNum].spellText2:SetText("") + sdTimer[slotNum].stacks = count or 0 + if XBT_DB.showSpellName then + sdTimer[slotNum].spellText:SetText(name) + else + sdTimer[slotNum].spellText:SetText("") + sdTimer[slotNum].spellText2:SetText("") + end + else + sdTimer[slotNum].iconTex = icon + sdTimer[slotNum].icon:SetTexture(nil) + sdTimer[slotNum].showIcon = false + sdTimer[slotNum].spellText:SetText("") + sdTimer[slotNum].stacks = 0 + sdTimer[slotNum].spellText2:SetText(name) + end + sdTimer[slotNum].startTime = (expTime - duration) or 0 sdTimer[slotNum].durationTime = duration or 0 sdTimer[slotNum].endTime = expTime or 0 - sdTimer[slotNum].stacks = count or 0 --this has to check for duration=0 because we cannot divide by zero local tmpBL if duration > 0 then @@ -452,6 +552,15 @@ function f:ClearBuffs(sdTimer) end +function f:ReloadBuffs() + f:ClearBuffs(timersTarget) + f:ClearBuffs(timersFocus) + f:ClearBuffs(timersPlayer) + f:ProcessBuffs("target", timersTarget) + f:ProcessBuffs("focus", timersFocus) + f:ProcessBuffs("player", timersPlayer) +end + function f:ArrangeBuffs(throttle, id) --to prevent spam and reduce CPU use if throttle then @@ -466,9 +575,11 @@ function f:ArrangeBuffs(throttle, id) local sdTimer if id == "target" then - sdTimer = timers + sdTimer = timersTarget elseif id == "focus" then sdTimer = timersFocus + elseif id == "player" then + sdTimer = timersPlayer else return end @@ -480,7 +591,9 @@ function f:ArrangeBuffs(throttle, id) table.sort(sdTimer, function(a,b) if a.active == true and b.active == false then return true; - elseif a.active and b.active then + elseif a.active and b.active and b.isInfinite then + return false; + elseif a.active and b.active and not b.isInfinite then return (a.tmpBL < b.tmpBL); end return false; @@ -490,7 +603,9 @@ function f:ArrangeBuffs(throttle, id) table.sort(sdTimer, function(a,b) if a.active == true and b.active == false then return true; - elseif a.active and b.active then + elseif a.active and b.active and a.isInfinite then + return true; + elseif a.active and b.active and not a.isInfinite then return (a.tmpBL > b.tmpBL); end return false; @@ -503,7 +618,9 @@ function f:ArrangeBuffs(throttle, id) table.sort(sdTimer, function(a,b) if a.active == true and b.active == false then return true; - elseif a.active and b.active then + elseif a.active and b.active and a.isInfinite then + return true; + elseif a.active and b.active and not a.isInfinite then return (a.tmpBL > b.tmpBL); end return false; @@ -513,7 +630,9 @@ function f:ArrangeBuffs(throttle, id) table.sort(sdTimer, function(a,b) if a.active == true and b.active == false then return true; - elseif a.active and b.active then + elseif a.active and b.active and b.isInfinite then + return false; + elseif a.active and b.active and not b.isInfinite then return (a.tmpBL < b.tmpBL); end return false; @@ -540,71 +659,54 @@ end ---------------------- function f:SaveLayout(frame) - + if type(frame) ~= "string" then return end + if not _G[frame] then return end if not XBT_DB then XBT_DB = {} end + + local opt = XBT_DB[frame] or nil - local opt = XBT_DB[frame] or nil; - - if opt == nil then + if not opt then XBT_DB[frame] = { ["point"] = "CENTER", ["relativePoint"] = "CENTER", - ["PosX"] = 0, - ["PosY"] = 0, + ["xOfs"] = 0, + ["yOfs"] = 0, } - opt = XBT_DB[frame]; + opt = XBT_DB[frame] + return end - local f = getglobal(frame); - local scale = f:GetEffectiveScale(); - opt.PosX = f:GetLeft() * scale; - opt.PosY = f:GetTop() * scale; - + local point, relativeTo, relativePoint, xOfs, yOfs = _G[frame]:GetPoint() + opt.point = point + opt.relativePoint = relativePoint + opt.xOfs = xOfs + opt.yOfs = yOfs end function f:RestoreLayout(frame) - + if type(frame) ~= "string" then return end + if not _G[frame] then return end if not XBT_DB then XBT_DB = {} end - - local f = getglobal(frame); - local opt = XBT_DB[frame] or nil; - if opt == nil then + local opt = XBT_DB[frame] or nil + + if not opt then XBT_DB[frame] = { ["point"] = "CENTER", ["relativePoint"] = "CENTER", - ["PosX"] = 0, - ["PosY"] = 0, - ["firsttime"] = true, + ["xOfs"] = 0, + ["yOfs"] = 0, } opt = XBT_DB[frame] end - local x = opt.PosX; - local y = opt.PosY; - local s = f:GetEffectiveScale() - - if opt.firsttime then - f:ClearAllPoints() - f:SetPoint("CENTER", UIParent, "CENTER", 0, 0) - if opt.firsttime then opt.firsttime = nil end - return - end - - --calculate the scale - x,y = x/s, y/s - - --set the location - f:ClearAllPoints() - f:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", x, y) - + _G[frame]:ClearAllPoints() + _G[frame]:SetPoint(opt.point, UIParent, opt.relativePoint, opt.xOfs, opt.yOfs) end function f:getBarColor(dur, expR) if dur <= 0 then - --this will make the bar green - dur = 1 - expR = 1 + return 0, 183/255, 239/255 end local r local g = 1 diff --git a/XanBuffTimers.toc b/XanBuffTimers.toc index 677706f..c91d4ae 100644 --- a/XanBuffTimers.toc +++ b/XanBuffTimers.toc @@ -1,8 +1,8 @@ ## Interface: 40300 ## Title: xanBuffTimers -## Notes: A small text based progress bar system for target buffs. +## Notes: A small text based progress bar system for target/focus/player buffs. ## Author: Xruptor -## Version: 2.2 +## Version: 3.0 ## SavedVariablesPerCharacter: XBT_DB xanBuffTimers.lua -- 1.7.9.5