diff --git a/XanBuffTimers.lua b/XanBuffTimers.lua
index c694f6d..78caa73 100644
--- a/XanBuffTimers.lua
+++ b/XanBuffTimers.lua
@@ -7,6 +7,8 @@ local ICON_SIZE = 20
local BAR_ADJUST = 25
local BAR_TEXT = "llllllllllllllllllllllllllllllllllllllll"
local band = bit.band
+local locked = false
+
local targetGUID = 0
local focusGUID = 0
local playerGUID = 0
@@ -16,14 +18,30 @@ local UnitGUID = UnitGUID
local UnitName = UnitName
local pointT = {
- ["target"] = "XBT_TargetAnchor",
+ ["target"] = "XBT_Anchor",
["focus"] = "XBT_FocusAnchor",
["player"] = "XBT_PlayerAnchor",
}
+local timerList = {
+ ["target"] = timersTarget,
+ ["focus"] = timersFocus,
+ ["player"] = timersPlayer,
+}
+
local f = CreateFrame("frame","xanBuffTimers",UIParent)
f:SetScript("OnEvent", function(self, event, ...) if self[event] then return self[event](self, event, ...) end end)
+local debugf = tekDebug and tekDebug:GetFrame("xanBuffTimers")
+local function Debug(...)
+ if debugf then debugf:AddMessage(string.join(", ", tostringall(...))) end
+end
+
+--buff arrays
+timersTarget.buffs = {}
+timersFocus.buffs = {}
+timersPlayer.buffs = {}
+
----------------------
-- Enable --
----------------------
@@ -40,14 +58,22 @@ function f:PLAYER_LOGIN()
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
-
+ if XBT_DB.healersOnly == nil then XBT_DB.healersOnly = false end
+
+
--create our anchors
- f:CreateAnchor("XBT_TargetAnchor", UIParent, "xanBuffTimers: Target Anchor")
+ f:CreateAnchor("XBT_Anchor", UIParent, "xanBuffTimers: Target Anchor")
f:CreateAnchor("XBT_FocusAnchor", UIParent, "xanBuffTimers: Focus Anchor")
f:CreateAnchor("XBT_PlayerAnchor", UIParent, "xanBuffTimers: Player Anchor")
-
+
+ --
playerGUID = UnitGUID("player")
- f:ProcessBuffs("player", timersPlayer)
+
+ --create our bars
+ f:generateBars()
+
+ f:UnregisterEvent("PLAYER_LOGIN")
+ f.PLAYER_LOGIN = nil
f:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
f:RegisterEvent("PLAYER_TARGET_CHANGED")
@@ -55,18 +81,19 @@ function f:PLAYER_LOGIN()
SLASH_XANBUFFTIMERS1 = "/xanbufftimers"
SLASH_XANBUFFTIMERS2 = "/xbt"
+ SLASH_XANBUFFTIMERS3 = "/xanbt"
SlashCmdList["XANBUFFTIMERS"] = function(msg)
local a,b,c=strfind(msg, "(%S+)"); --contiguous string of non-space characters
if a then
if c and c:lower() == "anchor" then
- if XBT_TargetAnchor:IsVisible() then
- XBT_TargetAnchor:Hide()
+ if XBT_Anchor:IsVisible() then
+ XBT_Anchor:Hide()
XBT_FocusAnchor:Hide()
XBT_PlayerAnchor:Hide()
else
- XBT_TargetAnchor:Show()
+ XBT_Anchor:Show()
XBT_FocusAnchor:Show()
XBT_PlayerAnchor:Show()
end
@@ -76,14 +103,16 @@ 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, #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))
+ for i=1, MAX_TIMERS do
+ if timersTarget[i] then
+ timersTarget[i]:SetScale(tonumber(scalenum))
+ end
+ if timersFocus[i] then
+ timersFocus[i]:SetScale(tonumber(scalenum))
+ end
+ if timersPlayer[i] then
+ timersPlayer[i]:SetScale(tonumber(scalenum))
+ end
end
DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Scale has been set to ["..tonumber(scalenum).."]")
return true
@@ -97,6 +126,7 @@ function f:PLAYER_LOGIN()
XBT_DB.grow = true
DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Bars will now grow [|cFF99CC33DOWN|r]")
end
+ f:adjustBars()
return true
elseif c and c:lower() == "sort" then
if XBT_DB.sort then
@@ -110,35 +140,32 @@ function f:PLAYER_LOGIN()
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
+ f:ReloadBuffs()
return true
elseif c and c:lower() == "focus" then
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.showFocus = true
- f:ProcessBuffs("focus", timersFocus)
DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show focus tracking [|cFF99CC33ON|r]")
end
+ f:ReloadBuffs()
return true
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.showPlayer = true
- f:ProcessBuffs("player", timersPlayer)
DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show player tracking [|cFF99CC33ON|r]")
end
+ f:ReloadBuffs()
return true
elseif c and c:lower() == "infinite" then
if XBT_DB.showInfinite then
@@ -170,6 +197,19 @@ function f:PLAYER_LOGIN()
end
f:ReloadBuffs()
return true
+ elseif c and c:lower() == "healers" then
+ if XBT_DB.healersOnly then
+ XBT_DB.healersOnly = false
+ DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show for healers only [|cFF99CC33OFF|r]")
+ else
+ XBT_DB.healersOnly = true
+ DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Show for healers only [|cFF99CC33ON|r]")
+ end
+ f:ReloadBuffs()
+ return true
+ elseif c and c:lower() == "reload" then
+ f:ReloadBuffs()
+ return true
end
end
@@ -184,22 +224,22 @@ function f:PLAYER_LOGIN()
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)")
+ DEFAULT_CHAT_FRAME:AddMessage("/xbt healers - toggles displaying of buff bars for only healing classes (ON/OFF)")
+ DEFAULT_CHAT_FRAME:AddMessage("/xbt reload - reload all the buff bars")
+
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 not XBT_DB.showTarget then return end
if UnitName("target") and UnitGUID("target") then
targetGUID = UnitGUID("target")
- f:ProcessBuffs("target", timersTarget)
+ f:ProcessBuffs("target")
else
- f:ClearBuffs(timersTarget)
+ f:ClearBuffs("target")
targetGUID = 0
end
end
@@ -208,9 +248,9 @@ 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)
+ f:ProcessBuffs("focus")
else
- f:ClearBuffs(timersFocus)
+ f:ClearBuffs("focus")
focusGUID = 0
end
end
@@ -233,6 +273,13 @@ local eventSwitch = {
["SPELL_HEAL"] = true,
["SPELL_DAMAGE"] = true,
["SPELL_PERIODIC_DAMAGE"] = true,
+ --added new
+ ["SPELL_DRAIN"] = true,
+ ["SPELL_LEECH"] = true,
+ ["SPELL_PERIODIC_DRAIN"] = true,
+ ["SPELL_PERIODIC_LEECH"] = true,
+ ["DAMAGE_SHIELD"] = true,
+ ["DAMAGE_SPLIT"] = true,
}
function f:COMBAT_LOG_EVENT_UNFILTERED(event, timestamp, eventType, hideCaster, sourceGUID, sourceName, srcFlags, sourceRaidFlags, dstGUID, destName, destFlags, destRaidFlags, spellID, spellName, spellSchool, auraType, amount)
@@ -242,27 +289,27 @@ function f:COMBAT_LOG_EVENT_UNFILTERED(event, timestamp, eventType, hideCaster,
--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 XBT_DB.showTarget then
- f:ClearBuffs(timersTarget)
+ f:ClearBuffs("target")
targetGUID = 0
end
if dstGUID == focusGUID and XBT_DB.showFocus then
- f:ClearBuffs(timersFocus)
+ f:ClearBuffs("focus")
focusGUID = 0
end
if dstGUID == playerGUID and XBT_DB.showPlayer then
- f:ClearBuffs(timersPlayer)
+ f:ClearBuffs("player")
end
elseif eventSwitch[eventType] and band(srcFlags, COMBATLOG_OBJECT_AFFILIATION_MINE) ~= 0 then
--process the spells based on GUID
if dstGUID == targetGUID and XBT_DB.showTarget then
- f:ProcessBuffs("target", timersTarget)
+ f:ProcessBuffs("target")
end
if dstGUID == focusGUID and XBT_DB.showFocus then
- f:ProcessBuffs("focus", timersFocus)
+ f:ProcessBuffs("focus")
end
if dstGUID == playerGUID and XBT_DB.showPlayer then
- f:ProcessBuffs("player", timersPlayer)
+ f:ProcessBuffs("player")
end
end
end
@@ -294,8 +341,8 @@ function f:CreateAnchor(name, parent, desc)
edgeSize = 16,
insets = { left = 5, right = 5, top = 5, bottom = 5 }
})
- frameAnchor:SetBackdropColor(0,183/255,239/255,1)
- frameAnchor:SetBackdropBorderColor(0,183/255,239/255,1)
+ frameAnchor:SetBackdropColor(0.75,0,0,1)
+ frameAnchor:SetBackdropBorderColor(0.75,0,0,1)
frameAnchor:SetScript("OnLeave",function(self)
GameTooltip:Hide()
@@ -342,57 +389,10 @@ function f:CreateAnchor(name, parent, desc)
f:RestoreLayout(name)
end
-local TimerOnUpdate = function(self, time)
-
- if self.active then
- self.OnUpdateCounter = (self.OnUpdateCounter or 0) + time
- if self.OnUpdateCounter < 0.05 then return end
- self.OnUpdateCounter = 0
-
- --we need to check for noncanceling auras if on
- local beforeEnd
- local barLength
-
- --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
- if barLength > string.len(BAR_TEXT) then barLength = string.len(BAR_TEXT) end
-
- if barLength <= 0 then
- self.active = false
- self:Hide()
- f:ArrangeBuffs(true, self.id)
- return
- end
-
- self.tmpBL = barLength
- self.Bar:SetText( string.sub(BAR_TEXT, 1, barLength) )
- self.Bar:SetTextColor(f:getBarColor(self.durationTime, beforeEnd))
- if self.stacks > 0 then
- self.stacktext:SetText(self.stacks)
- else
- self.stacktext:SetText(nil)
- end
- self.timetext:SetText(f:GetTimeText(ceil(beforeEnd)))
- f:ArrangeBuffs(true, self.id)
- end
-
-end
-
function f:CreateBuffTimers()
local Frm = CreateFrame("Frame", nil, UIParent)
-
- Frm.active = false
+
Frm:SetWidth(ICON_SIZE)
Frm:SetHeight(ICON_SIZE)
Frm:SetFrameStrata("LOW")
@@ -417,7 +417,7 @@ function f:CreateBuffTimers()
Frm.timetext:SetFont("Fonts\\FRIZQT__.TTF",10,"OUTLINE")
Frm.timetext:SetJustifyH("RIGHT")
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)
@@ -434,146 +434,257 @@ function f:CreateBuffTimers()
Frm.Bar:SetFont(STANDARD_TEXT_FONT, 14, "OUTLINE, MONOCHROME")
Frm.Bar:SetText(BAR_TEXT)
Frm.Bar:SetPoint("LEFT", Frm.icon, "RIGHT", 30, 0)
-
- Frm:SetScript("OnUpdate", TimerOnUpdate)
-
+
Frm:Hide()
return Frm
+
+end
+
+function f:generateBars()
+ local adj = 0
+ --lets create the max bars to use on screen for future sorting
+ for i=1, MAX_TIMERS do
+ timersTarget[i] = f:CreateBuffTimers()
+ timersFocus[i] = f:CreateBuffTimers()
+ timersPlayer[i] = f:CreateBuffTimers()
+ if not timersTarget.buffs[i] then timersTarget.buffs[i] = {} end
+ if not timersFocus.buffs[i] then timersFocus.buffs[i] = {} end
+ if not timersPlayer.buffs[i] then timersPlayer.buffs[i] = {} end
+ end
+
+ --rearrange order
+ for i=1, MAX_TIMERS do
+ if XBT_DB.grow then
+ timersTarget[i]:ClearAllPoints()
+ timersTarget[i]:SetPoint("TOPLEFT", XBT_Anchor, "BOTTOMRIGHT", 0, adj)
+ timersFocus[i]:ClearAllPoints()
+ timersFocus[i]:SetPoint("TOPLEFT", XBT_FocusAnchor, "BOTTOMRIGHT", 0, adj)
+ timersPlayer[i]:ClearAllPoints()
+ timersPlayer[i]:SetPoint("TOPLEFT", XBT_PlayerAnchor, "BOTTOMRIGHT", 0, adj)
+ else
+ timersTarget[i]:ClearAllPoints()
+ timersTarget[i]:SetPoint("BOTTOMLEFT", XBT_Anchor, "TOPRIGHT", 0, (adj * -1))
+ timersFocus[i]:ClearAllPoints()
+ timersFocus[i]:SetPoint("BOTTOMLEFT", XBT_FocusAnchor, "TOPRIGHT", 0, (adj * -1))
+ timersPlayer[i]:ClearAllPoints()
+ timersPlayer[i]:SetPoint("BOTTOMLEFT", XBT_PlayerAnchor, "TOPRIGHT", 0, (adj * -1))
+ end
+ adj = adj - BAR_ADJUST
+ end
+
end
+function f:adjustBars()
+ local adj = 0
+ for i=1, MAX_TIMERS do
+ if XBT_DB.grow then
+ timersTarget[i]:ClearAllPoints()
+ timersTarget[i]:SetPoint("TOPLEFT", XBT_Anchor, "BOTTOMRIGHT", 0, adj)
+ timersFocus[i]:ClearAllPoints()
+ timersFocus[i]:SetPoint("TOPLEFT", XBT_FocusAnchor, "BOTTOMRIGHT", 0, adj)
+ timersPlayer[i]:ClearAllPoints()
+ timersPlayer[i]:SetPoint("TOPLEFT", XBT_PlayerAnchor, "BOTTOMRIGHT", 0, adj)
+ else
+ timersTarget[i]:ClearAllPoints()
+ timersTarget[i]:SetPoint("BOTTOMLEFT", XBT_Anchor, "TOPRIGHT", 0, (adj * -1))
+ timersFocus[i]:ClearAllPoints()
+ timersFocus[i]:SetPoint("BOTTOMLEFT", XBT_FocusAnchor, "TOPRIGHT", 0, (adj * -1))
+ timersPlayer[i]:ClearAllPoints()
+ timersPlayer[i]:SetPoint("BOTTOMLEFT", XBT_PlayerAnchor, "TOPRIGHT", 0, (adj * -1))
+ end
+ adj = adj - BAR_ADJUST
+ end
+end
+
+function f:ProcessBuffBar(data)
+ if data.isInfinite then return end --dont do any calculations on infinite
+
+ local beforeEnd = data.endTime - GetTime()
+ -- local percentTotal = (beforeEnd / data.durationTime)
+ -- local percentFinal = ceil(percentTotal * 100)
+ -- local barLength = ceil( string.len(BAR_TEXT) * percentTotal )
+
+ --calculate the individual bar segments and make the appropriate calculations
+ local totalDuration = (data.endTime - data.startTime) --total duration of the spell
+ local totalBarSegment = (string.len(BAR_TEXT) / totalDuration) --lets get how much each segment of the bar string would value up to 100%
+ local totalBarLength = totalBarSegment * beforeEnd --now get the individual bar segment value and multiply it with current duration
+ local barPercent = (totalBarLength / string.len(BAR_TEXT)) * 100
+
+ --100/40 means each segment is 2.5 for 100%
+ --example for 50% 50/100 = 0.5 0.5 / 2.5 = 0.2 (50% divided by segment count) 0.2 * 100 = 20 (which is half of the bar of 40)
+
+ if barPercent <= 0 or beforeEnd <= 0 or totalBarLength <= 0 then
+ data.active = false
+ return
+ end
+
+ data.percent = barPercent
+ data.totalBarLength = totalBarLength
+ data.beforeEnd = beforeEnd
+
+end
+
----------------------
-- Buff Functions --
----------------------
-function f:ProcessBuffs(sT, sdTimer)
- --only process for as many timers as we are using
- local slotNum = 0
+--lets use one global OnUpdate instead of individual ones for each buff bar
+f:SetScript("OnUpdate", function(self, elapsed)
+ self.OnUpdateCounter = (self.OnUpdateCounter or 0) + elapsed
+ if self.OnUpdateCounter < 0.05 then return end
+ self.OnUpdateCounter = 0
+
+ local tCount = 0
+ local fCount = 0
+ local pCount = 0
for i=1, MAX_TIMERS do
- local name, _, icon, count, _, duration, expTime, unitCaster, _, _, spellId = UnitAura(sT, i, 'HELPFUL|PLAYER')
- if not name then break end
+ if timersTarget.buffs[i].active then
+ self:ProcessBuffBar(timersTarget.buffs[i])
+ tCount = tCount + 1
+ end
+ if timersFocus.buffs[i].active then
+ self:ProcessBuffBar(timersFocus.buffs[i])
+ fCount = fCount + 1
+ end
+ if timersPlayer.buffs[i].active then
+ self:ProcessBuffBar(timersPlayer.buffs[i])
+ pCount = pCount + 1
+ end
+ end
+
+ --no need to arrange the bars if there is nothing to work with, uncessary if no target or focus
+ if tCount > 0 then
+ f:ShowBuffs("target")
+ end
+ if fCount > 0 then
+ f:ShowBuffs("focus")
+ end
+ if pCount > 0 then
+ f:ShowBuffs("player")
+ end
+
+end)
+
+function f:ProcessBuffs(id)
+ local sdTimer = timerList[id] --makes things easier to read
+
+ for i=1, MAX_TIMERS do
+ local name, _, icon, count, _, duration, expTime, unitCaster, _, _, spellId = UnitAura(id, i, 'PLAYER|HELPFUL')
local passChk = false
+ local isInfinite = false
--only allow non-cancel auras if the user allowed it
if XBT_DB.showInfinite then
--auras are on so basically were allowing everything
passChk = true
+ if not duration or duration <= 0 then
+ isInfinite = true
+ end
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
- 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
- sdTimer[slotNum].isInfinite = true
+ --check for duration > 0 for the evil DIVIDE BY ZERO
+ if name and passChk then
+ local beforeEnd = 0
+ local startTime = 0
+ local totalDuration = 0
+ local totalBarSegment = 0
+ local totalBarLength = 0
+ local barPercent = 0
+
+ if isInfinite then
+ barPercent = 200 --anything higher than 100 will get pushed to top of list, so lets make it 200
+ duration = 0
expTime = 0
+ totalBarLength = string.len(BAR_TEXT)
else
- sdTimer[slotNum].isInfinite = false
+ beforeEnd = expTime - GetTime()
+ startTime = (expTime - duration)
+ totalDuration = (expTime - startTime) --total duration of the spell
+ totalBarSegment = (string.len(BAR_TEXT) / totalDuration) --lets get how much each segment of the bar string would value up to 100%
+ totalBarLength = totalBarSegment * beforeEnd --now get the individual bar segment value and multiply it with current duration
+ barPercent = (totalBarLength / string.len(BAR_TEXT)) * 100
end
- sdTimer[slotNum].id = sT
- sdTimer[slotNum].spellName = name
- sdTimer[slotNum].spellId = spellId
-
- --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)
+
+ if barPercent > 0 or beforeEnd > 0 or totalBarLength > 0 then
+ --buffs
+ sdTimer.buffs[i].id = id
+ sdTimer.buffs[i].spellName = name
+ sdTimer.buffs[i].spellId = spellId
+ sdTimer.buffs[i].iconTex = icon
+ sdTimer.buffs[i].startTime = startTime
+ sdTimer.buffs[i].durationTime = duration
+ sdTimer.buffs[i].beforeEnd = beforeEnd
+ sdTimer.buffs[i].endTime = expTime
+ sdTimer.buffs[i].totalBarLength = totalBarLength
+ sdTimer.buffs[i].stacks = count or 0
+ sdTimer.buffs[i].percent = barPercent
+ sdTimer.buffs[i].active = true
+ sdTimer.buffs[i].isInfinite = isInfinite
end
-
- sdTimer[slotNum].startTime = (expTime - duration) or 0
- sdTimer[slotNum].durationTime = duration or 0
- sdTimer[slotNum].endTime = expTime or 0
- --this has to check for duration=0 because we cannot divide by zero
- local tmpBL
- if duration > 0 then
- tmpBL = ceil( string.len(BAR_TEXT) * ( (expTime - GetTime()) / duration ) )
- elseif duration <= 0 then
- tmpBL = string.len(BAR_TEXT)
- end
- if tmpBL > string.len(BAR_TEXT) then tmpBL = string.len(BAR_TEXT) end
- sdTimer[slotNum].tmpBL = tmpBL
- sdTimer[slotNum].active = true
- if not sdTimer[slotNum]:IsVisible() then sdTimer[slotNum]:Show() end
- end
- end
- --clear everything else
- for i=(slotNum+1), #sdTimer do
- if sdTimer[i] then
- sdTimer[i].active = false
- if sdTimer[i]:IsVisible() then sdTimer[i]:Hide() end
+ else
+ sdTimer.buffs[i].active = false
end
end
- if slotNum > 0 then
- f:ArrangeBuffs(false, sT)
- end
+
+ f:ShowBuffs(id)
end
-function f:ClearBuffs(sdTimer)
+function f:ClearBuffs(id)
+ local sdTimer = timerList[id] --makes things easier to read
local adj = 0
- for i=1, #sdTimer do
- if sdTimer[i].active then
- sdTimer[i].active = false
- end
- --reset the order
- if XBT_DB.grow then
- sdTimer[i]:ClearAllPoints()
- sdTimer[i]:SetPoint("TOPLEFT", pointT[sdTimer[i].id], "BOTTOMRIGHT", 0, adj)
- else
- sdTimer[i]:ClearAllPoints()
- sdTimer[i]:SetPoint("BOTTOMLEFT", pointT[sdTimer[i].id], "TOPRIGHT", 0, (adj * -1))
- end
- adj = adj - BAR_ADJUST
-
- if sdTimer[i]:IsVisible() then sdTimer[i]:Hide() end
+ for i=1, MAX_TIMERS do
+ sdTimer.buffs[i].active = false
+ sdTimer[i]:Hide()
end
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)
+ local class = select(2, UnitClass("player"))
+
+ local healers = {
+ ["DRUID"] = true,
+ ["SHAMAN"] = true,
+ ["MONK"] = true,
+ ["PRIEST"] = true,
+ ["PALADIN"] = true,
+ }
+
+ f:ClearBuffs("target")
+ f:ClearBuffs("focus")
+ f:ClearBuffs("player")
+
+ if XBT_DB.healersOnly and not healers[class] then
+ return
+ end
+
+ if XBT_DB.showTarget then
+ f:ProcessBuffs("target")
+ end
+ if XBT_DB.showFocus then
+ f:ProcessBuffs("focus")
+ end
+ if XBT_DB.showPlayer then
+ f:ProcessBuffs("player")
+ end
end
-function f:ArrangeBuffs(throttle, id)
- --to prevent spam and reduce CPU use
- if throttle then
- if not f.ADT then f.ADT = GetTime() end
- if (GetTime() - f.ADT) < 0.1 then
- return
- end
- f.ADT = GetTime()
- end
+function f:ShowBuffs(id)
- local adj = 0
- local sdTimer
+ if locked then return end
+ locked = true
+ local sdTimer
+ local tmpList = {}
+
if id == "target" then
sdTimer = timersTarget
elseif id == "focus" then
@@ -581,83 +692,90 @@ function f:ArrangeBuffs(throttle, id)
elseif id == "player" then
sdTimer = timersPlayer
else
+ locked = false
return
end
+ for i=1, MAX_TIMERS do
+ if sdTimer.buffs[i].active then
+ table.insert(tmpList, sdTimer.buffs[i])
+ end
+ end
+
if XBT_DB.grow then
--bars will grow down
if XBT_DB.sort then
--sort from shortest to longest
- table.sort(sdTimer, function(a,b)
- if a.active == true and b.active == false then
- return true;
- 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;
- end)
+ table.sort(tmpList, function(a,b) return (a.percent < b.percent) end)
+
else
--sort from longest to shortest
- table.sort(sdTimer, function(a,b)
- if a.active == true and b.active == false then
- return true;
- 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;
- end)
+ table.sort(tmpList, function(a,b) return (a.percent > b.percent) end)
+
end
else
--bars will grow up
if XBT_DB.sort then
--sort from shortest to longest
- table.sort(sdTimer, function(a,b)
- if a.active == true and b.active == false then
- return true;
- 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;
- end)
+ table.sort(tmpList, function(a,b) return (a.percent > b.percent) end)
+
else
--sort from longest to shortest
- table.sort(sdTimer, function(a,b)
- if a.active == true and b.active == false then
- return true;
- 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;
- end)
+ table.sort(tmpList, function(a,b) return (a.percent < b.percent) end)
end
end
-
- --rearrange order
- for i=1, #sdTimer do
- if XBT_DB.grow then
- sdTimer[i]:ClearAllPoints()
- sdTimer[i]:SetPoint("TOPLEFT", pointT[sdTimer[i].id], "BOTTOMRIGHT", 0, adj)
+
+ for i=1, MAX_TIMERS do
+ if tmpList[i] then
+ --display the information
+ ---------------------------------------
+ sdTimer[i].Bar:SetText( string.sub(BAR_TEXT, 1, tmpList[i].totalBarLength) )
+ sdTimer[i].Bar:SetTextColor(f:getBarColor(tmpList[i].durationTime, tmpList[i].beforeEnd))
+ if XBT_DB.showIcon then
+ sdTimer[i].icon:SetTexture(tmpList[i].iconTex)
+ sdTimer[i].spellText2:SetText("")
+ if XBT_DB.showSpellName then
+ sdTimer[i].spellText:SetText(tmpList[i].spellName)
+ else
+ sdTimer[i].spellText:SetText("")
+ end
+ if tmpList[i].stacks > 0 then
+ sdTimer[i].stacktext:SetText(tmpList[i].stacks)
+ else
+ sdTimer[i].stacktext:SetText(nil)
+ end
+ else
+ sdTimer[i].icon:SetTexture(nil)
+ sdTimer[i].spellText:SetText("")
+ sdTimer[i].stacktext:SetText(nil)
+ if tmpList[i].stacks > 0 then
+ sdTimer[i].spellText2:SetText(tmpList[i].spellName.." ["..tmpList[i].stacks.."]")
+ else
+ sdTimer[i].spellText2:SetText(tmpList[i].spellName)
+ end
+ end
+ if tmpList[i].isInfinite then
+ sdTimer[i].timetext:SetText("∞")
+ else
+ sdTimer[i].timetext:SetText(f:GetTimeText(ceil(tmpList[i].beforeEnd)))
+ end
+ ---------------------------------------
+
+ sdTimer[i]:Show()
else
- sdTimer[i]:ClearAllPoints()
- sdTimer[i]:SetPoint("BOTTOMLEFT", pointT[sdTimer[i].id], "TOPRIGHT", 0, (adj * -1))
+ sdTimer.buffs[i].active = false --just in case
+ sdTimer[i]:Hide()
end
- adj = adj - BAR_ADJUST
end
-
+
+ locked = false
end
----------------------
-- Local Functions --
----------------------
+
function f:SaveLayout(frame)
if type(frame) ~= "string" then return end
if not _G[frame] then return end
@@ -720,7 +838,7 @@ end
function f:GetTimeText(timeLeft)
if timeLeft <= 0 then return nil end
-
+
local hours, minutes, seconds = 0, 0, 0
if( timeLeft >= 3600 ) then
hours = ceil(timeLeft / 3600)
@@ -744,5 +862,5 @@ function f:GetTimeText(timeLeft)
return nil
end
end
-
+
if IsLoggedIn() then f:PLAYER_LOGIN() else f:RegisterEvent("PLAYER_LOGIN") end
diff --git a/XanBuffTimers.toc b/XanBuffTimers.toc
index 39ae91d..d1200af 100644
--- a/XanBuffTimers.toc
+++ b/XanBuffTimers.toc
@@ -2,7 +2,7 @@
## Title: xanBuffTimers
## Notes: A small text based progress bar system for target/focus/player buffs.
## Author: Xruptor
-## Version: 3.3
+## Version: 3.4
## SavedVariablesPerCharacter: XBT_DB
xanBuffTimers.lua