Quantcast

-Major update\n

Xruptor [01-17-11 - 16:59]
-Major update\n
-Revamped the entire code
-Added checks for division by zero
-Added a slash command to enable non-canceling auras
-Added checks for non-canceling auras
Filename
XanBuffTimers.lua
XanBuffTimers.toc
diff --git a/XanBuffTimers.lua b/XanBuffTimers.lua
index daa8c93..f4e3837 100644
--- a/XanBuffTimers.lua
+++ b/XanBuffTimers.lua
@@ -1,22 +1,23 @@
---Inspired by TextTimers

 local timers = {}
 local timersFocus = {}
-local timersPlayer = {}
-local math_max = _G.math.max
-local math_min = _G.math.min
 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 f = CreateFrame("frame","XanBuffTimers",UIParent)
+local pointT = {
+	["target"] = "XBT_Anchor",
+	["focus"] = "XBT_FocusAnchor",
+}
+
+local f = CreateFrame("frame","xanBuffTimers",UIParent)
 f:SetScript("OnEvent", function(self, event, ...) if self[event] then return self[event](self, event, ...) end end)

 ----------------------
@@ -27,33 +28,30 @@ function f:PLAYER_LOGIN()

 	if not XBT_DB then XBT_DB = {} end
 	if XBT_DB.scale == nil then XBT_DB.scale = 1 end
-	if XBT_DB.grow == nil then XBT_DB.grow = true 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

-	playerGUID = UnitGUID("player")
-
 	--create our anchors
 	f:CreateAnchor("XBT_Anchor", UIParent)
 	f:CreateAnchor("XBT_FocusAnchor", UIParent)
-	f:CreateAnchor("XBT_PlayerAnchor", UIParent)

 	--create our timers
 	for i=1,MAX_TIMERS do
 		timers[i] = f:CreateBuffTimers()
 		timersFocus[i] = f:CreateBuffTimers()
-		timersPlayer[i] = f:CreateBuffTimers()
 	end

-	--do our growth process for the buff bars (SETPOINT)
-	f:ProcessGrowth()
-
+	f:UnregisterEvent("PLAYER_LOGIN")
+	f.PLAYER_LOGIN = nil
+
 	f:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
 	f:RegisterEvent("PLAYER_TARGET_CHANGED")
 	f:RegisterEvent("PLAYER_FOCUS_CHANGED")
-	f:RegisterEvent("UNIT_AURA")
-
+
 	SLASH_XANBUFFTIMERS1 = "/xanbufftimers"
 	SLASH_XANBUFFTIMERS2 = "/xbt"
-	SLASH_XANBUFFTIMERS3 = "/xanbt"
+	SLASH_XANBUFFTIMERS3 = "/xandt"
 	SlashCmdList["XANBUFFTIMERS"] = function(msg)

 		local a,b,c=strfind(msg, "(%S+)"); --contiguous string of non-space characters
@@ -63,11 +61,9 @@ function f:PLAYER_LOGIN()
 				if XBT_Anchor:IsVisible() then
 					XBT_Anchor:Hide()
 					XBT_FocusAnchor:Hide()
-					XBT_PlayerAnchor:Hide()
 				else
 					XBT_Anchor:Show()
 					XBT_FocusAnchor:Show()
-					XBT_PlayerAnchor:Show()
 				end
 				return true
 			elseif c and c:lower() == "scale" then
@@ -78,47 +74,51 @@ function f:PLAYER_LOGIN()
 						for i=1, MAX_TIMERS do
 							timers[i]:SetScale(tonumber(scalenum))
 							timersFocus[i]:SetScale(tonumber(scalenum))
-							timersPlayer[i]:SetScale(tonumber(scalenum))
 						end
-						DEFAULT_CHAT_FRAME:AddMessage("XanBuffTimers: Scale has been set to ["..tonumber(scalenum).."]")
+						DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Scale has been set to ["..tonumber(scalenum).."]")
 						return true
 					end
 				end
 			elseif c and c:lower() == "grow" then
 				if XBT_DB.grow then
 					XBT_DB.grow = false
-					DEFAULT_CHAT_FRAME:AddMessage("XanBuffTimers: Bars will now grow [|cFF99CC33UP|r]")
+					DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Bars will now grow [|cFF99CC33UP|r]")
 				else
 					XBT_DB.grow = true
-					DEFAULT_CHAT_FRAME:AddMessage("XanBuffTimers: Bars will now grow [|cFF99CC33DOWN|r]")
+					DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Bars will now grow [|cFF99CC33DOWN|r]")
+				end
+				return true
+			elseif c and c:lower() == "sort" then
+				if XBT_DB.sort then
+					XBT_DB.sort = false
+					DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Bars sort [|cFF99CC33DESCENDING|r]")
+				else
+					XBT_DB.sort = true
+					DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Bars sort [|cFF99CC33ASCENDING|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]")
+				else
+					XBT_DB.auras = true
+					DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers: Buff Auras [|cFF99CC33ON|r]")
 				end
-				f:ProcessGrowth()
 				return true
 			end
 		end

-		DEFAULT_CHAT_FRAME:AddMessage("XanBuffTimers")
+		DEFAULT_CHAT_FRAME:AddMessage("xanBuffTimers")
 		DEFAULT_CHAT_FRAME:AddMessage("/xbt anchor - toggles a movable anchor")
 		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)")
 	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:UNIT_AURA(event, unit)
-	if not unit then return end
-	if unit == "target" and UnitGUID(unit) and UnitGUID(unit) == targetGUID then
-		f:ProcessBuffs("target", timers)
-	elseif unit == "focus" and UnitGUID(unit) and UnitGUID(unit) == focusGUID then
-		f:ProcessBuffs("focus", timersFocus)
-	elseif unit == "player" and UnitGUID(unit) and UnitGUID(unit) == playerGUID then
-		f:ProcessBuffs("player", timersPlayer)
-	end
+	local ver = tonumber(GetAddOnMetadata("xanBuffTimers","Version")) or 'Unknown'
+	DEFAULT_CHAT_FRAME:AddMessage("|cFF99CC33xanBuffTimers|r [v|cFFDF2B2B"..ver.."|r] loaded: /xbt")
 end

 function f:PLAYER_TARGET_CHANGED()
@@ -141,6 +141,14 @@ function f:PLAYER_FOCUS_CHANGED()
 	end
 end

+local eventSwitch = {
+	["SPELL_AURA_APPLIED"] = true,
+	["SPELL_AURA_REMOVED"] = true,
+	["SPELL_AURA_REFRESH"] = true,
+	["SPELL_AURA_APPLIED_DOSE"] = true,
+	["SPELL_AURA_APPLIED_REMOVED_DOSE"] = true,
+}
+
 function f:COMBAT_LOG_EVENT_UNFILTERED(event, timestamp, eventType, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, spellID, spellName, spellSchool, auraType, amount)

     if eventType == "UNIT_DIED" or eventType == "UNIT_DESTROYED" then
@@ -155,6 +163,15 @@ function f:COMBAT_LOG_EVENT_UNFILTERED(event, timestamp, eventType, srcGUID, src
 			f:ClearBuffs(timersFocus)
 			focusGUID = 0
 		end
+
+	elseif eventSwitch[eventType] and band(srcFlags, COMBATLOG_OBJECT_AFFILIATION_MINE) ~= 0 then
+		--process the spells based on GUID
+		if dstGUID == targetGUID then
+			f:ProcessBuffs("target", timers)
+		end
+		if dstGUID == focusGUID then
+			f:ProcessBuffs("focus", timersFocus)
+		end
     end
 end

@@ -237,19 +254,21 @@ local TimerOnUpdate = function(self, time)
 		if self.OnUpdateCounter < 0.05 then return end
 		self.OnUpdateCounter = 0

-		local beforeEnd = self.expiryTime - GetTime()
-		local barLength = ceil( string.len(BAR_TEXT) * (beforeEnd / self.durationTime) )
+		--we need to check for noncanceling auras if on
+		local beforeEnd
+		local barLength

-		--self.timeleft = math_max(0, self.timeleft - (GetTime() - self.lastUpdate))
-		--self.lastUpdate = GetTime()
-		--local fraction = math_max(0, math_min(self.timeleft / self.durationTime, 1))
-		--local barwidth = string.len(BAR_TEXT) * fraction
-
-		--correct for buffs with no expiration
-		if self.durationTime == 0 then
+		if XBT_DB.auras and self.durationTime <= 0 then
+			beforeEnd = 0
 			barLength = string.len(BAR_TEXT)
+		else
+			beforeEnd = self.endTime - GetTime()
+			barLength = ceil( string.len(BAR_TEXT) * (beforeEnd / self.durationTime) )
 		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()
@@ -257,18 +276,13 @@ local TimerOnUpdate = function(self, time)
 			return
 		end

-		if self.durationTime == 0 then
-			self.tmpBL = string.len(BAR_TEXT)
-		else
-			self.tmpBL = barLength
-		end
-
+		self.tmpBL = barLength
 		self.Bar:SetText( string.sub(BAR_TEXT, 1, barLength) )
-		self.Bar:SetTextColor(f:getBarColor(self.durationTime, beforeEnd, false))
+		self.Bar:SetTextColor(f:getBarColor(self.durationTime, beforeEnd))
 		if self.stacks > 0 then
 			self.stacktext:SetText(self.stacks)
 		else
-			self.stacktext:SetText('')
+			self.stacktext:SetText(nil)
 		end
 		self.timetext:SetText(f:GetTimeText(ceil(beforeEnd)))
 		f:ArrangeBuffs(true, self.id)
@@ -307,7 +321,7 @@ function f:CreateBuffTimers()
     Frm.timetext:SetPoint("RIGHT", Frm.icon, "LEFT" , -5, 0)

 	Frm.Bar = Frm:CreateFontString(nil, "GameFontNormal")
-	Frm.Bar:SetFont(STANDARD_TEXT_FONT, 14, "OUTLINE")
+	Frm.Bar:SetFont(STANDARD_TEXT_FONT, 14, "OUTLINE, MONOCHROME")
 	Frm.Bar:SetText(BAR_TEXT)
 	Frm.Bar:SetPoint("LEFT", Frm.icon, "RIGHT", 1, 0)

@@ -319,99 +333,85 @@ function f:CreateBuffTimers()

 end

-function f:ProcessGrowth()
-	local adj = 0
-	for i=1,MAX_TIMERS do
-		if XBT_DB.grow then
-			timers[i]:ClearAllPoints()
-			timers[i]:SetPoint("TOPLEFT", "XBT_Anchor", "BOTTOMRIGHT", 0, adj)
-			--FOCUS
-			timersFocus[i]:ClearAllPoints()
-			timersFocus[i]:SetPoint("TOPLEFT", "XBT_FocusAnchor", "BOTTOMRIGHT", 0, adj)
-			--PLAYER
-			timersPlayer[i]:ClearAllPoints()
-			timersPlayer[i]:SetPoint("TOPLEFT", "XBT_PlayerAnchor", "BOTTOMRIGHT", 0, adj)
-		else
-			timers[i]:ClearAllPoints()
-			timers[i]:SetPoint("BOTTOMLEFT", "XBT_Anchor", "TOPRIGHT", 0, (adj * -1))
-			--FOCUS
-			timersFocus[i]:ClearAllPoints()
-			timersFocus[i]:SetPoint("BOTTOMLEFT", "XBT_FocusAnchor", "TOPRIGHT", 0, (adj * -1))
-			--PLAYER
-			timersPlayer[i]:ClearAllPoints()
-			timersPlayer[i]:SetPoint("BOTTOMLEFT", "XBT_PlayerAnchor", "TOPRIGHT", 0, (adj * -1))
-		end
-		adj = adj - BAR_ADJUST
-	end
-end
 ----------------------
 -- Buff Functions --
 ----------------------

 function f:ProcessBuffs(sT, sdTimer)
-	if f.selfProcessingBuffs then return end
-	f.selfProcessingBuffs = true
-
 	--only process for as many timers as we are using
 	local countBuffs = 0
+
 	for i=1, MAX_TIMERS do
-	local name, _, icon, count, _, duration, expiryTime, unitCaster, _, _, spellId = UnitAura(sT, i, 'HELPFUL')
-		if name then
+
+		local name, _, icon, count, _, duration, expTime, unitCaster, _, _, spellId = UnitAura(sT, i, 'HELPFUL|PLAYER')
+		local passChk = false
+
+		--only allow non-cancel auras if the user allowed it
+		if XBT_DB.auras then
+			--auras are on so basically were allowing everything
+			passChk = true
+		elseif not XBT_DB.auras 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 duration <= 0 then expTime = 0 end --just in case for non-cancel auras
 			sdTimer[i].id = sT
 			sdTimer[i].spellName = name
 			sdTimer[i].spellId = spellId
 			sdTimer[i].iconTex = icon
 			sdTimer[i].icon:SetTexture(icon)
-			sdTimer[i].startTime = expiryTime - duration
+			sdTimer[i].startTime = (expTime - duration) or 0
 			sdTimer[i].durationTime = duration or 0
-			sdTimer[i].expiryTime = expiryTime
-			--sdTimer[i].timeleft = expiryTime and math_max(0, expiryTime - GetTime()) or 0
-			--sdTimer[i].lastUpdate = GetTime()
+			sdTimer[i].endTime = expTime or 0
 			sdTimer[i].stacks = count or 0
-
-			local tmpBL = ceil( string.len(BAR_TEXT) * ( (expiryTime - GetTime()) / duration ) )
-
-			if duration == 0 then
-				sdTimer[i].tmpBL = string.len(BAR_TEXT)
-			else
-				sdTimer[i].tmpBL = tmpBL
-			end
-
+				--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[i].tmpBL = tmpBL
 			sdTimer[i].active = true
 			if not sdTimer[i]:IsVisible() then sdTimer[i]:Show() end
 			countBuffs = countBuffs + 1
 		else
-			sdTimer[i].timetext:SetText('')
-			sdTimer[i].Bar:SetText('')
-			sdTimer[i].icon:SetTexture(nil)
 			sdTimer[i].active = false
 			if sdTimer[i]:IsVisible() then sdTimer[i]:Hide() end
 		end
 	end
-
-	f.selfProcessingBuffs = nil
-
 	if countBuffs > 0 then
 		f:ArrangeBuffs(false, sT)
 	end
-
 end

 function f:ClearBuffs(sdTimer)
+	local adj = 0
+
 	for i=1, MAX_TIMERS do
 		if sdTimer[i].active then
 			sdTimer[i].active = false
 		end
-		sdTimer[i].timetext:SetText('')
-		sdTimer[i].Bar:SetText('')
-		sdTimer[i].icon:SetTexture(nil)
+		--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
 	end
+
 end

 function f:ArrangeBuffs(throttle, id)
-	if f.selfProcessingBuffs then return end
-
 	--to prevent spam and reduce CPU use
 	if throttle then
 		if not f.ADT then f.ADT = GetTime() end
@@ -422,48 +422,72 @@ function f:ArrangeBuffs(throttle, id)
 	end

 	local adj = 0
-	local active = {}
-	local pointT
 	local sdTimer

 	if id == "target" then
 		sdTimer = timers
-		pointT = "XBT_Anchor"
 	elseif id == "focus" then
 		sdTimer = timersFocus
-		pointT = "XBT_FocusAnchor"
-	elseif id == "player" then
-		sdTimer = timersPlayer
-		pointT = "XBT_PlayerAnchor"
 	else
 		return
 	end

-    for i=1, MAX_TIMERS do
-        if sdTimer[i].active then
-            table.insert(active, sdTimer[i])
+	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 then
+					return (a.tmpBL < b.tmpBL);
+				end
+				return false;
+			end)
 		else
-			break
-        end
-    end
-
-	--sort by the size of the progressbar... duh
-    table.sort(active, function(a,b)
-		if a.tmpBL > b.tmpBL then
-			return true;
-		elseif a.tmpBL == b.tmpBL then
-			return (a.durationTime < b.durationTime);
+			--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 then
+					return (a.tmpBL > b.tmpBL);
+				end
+				return false;
+			end)
 		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 then
+					return (a.tmpBL > b.tmpBL);
+				end
+				return false;
+			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 then
+					return (a.tmpBL < b.tmpBL);
+				end
+				return false;
+			end)
+		end
+	end

 	--rearrange order
-	for i=1, #active do
+	for i=1, #sdTimer do
 		if XBT_DB.grow then
-			active[i]:ClearAllPoints()
-			active[i]:SetPoint("TOPLEFT", pointT, "BOTTOMRIGHT", 0, adj)
+			sdTimer[i]:ClearAllPoints()
+			sdTimer[i]:SetPoint("TOPLEFT", pointT[sdTimer[i].id], "BOTTOMRIGHT", 0, adj)
 		else
-			active[i]:ClearAllPoints()
-			active[i]:SetPoint("BOTTOMLEFT", pointT, "TOPRIGHT", 0, (adj * -1))
+			sdTimer[i]:ClearAllPoints()
+			sdTimer[i]:SetPoint("BOTTOMLEFT", pointT[sdTimer[i].id], "TOPRIGHT", 0, (adj * -1))
 		end
 		adj = adj - BAR_ADJUST
     end
@@ -484,8 +508,8 @@ function f:SaveLayout(frame)
 		XBT_DB[frame] = {
 			["point"] = "CENTER",
 			["relativePoint"] = "CENTER",
-			["xOfs"] = 0,
-			["yOfs"] = 0,
+			["PosX"] = 0,
+			["PosY"] = 0,
 		}
 		opt = XBT_DB[frame];
 	end
@@ -494,6 +518,7 @@ function f:SaveLayout(frame)
 	local scale = f:GetEffectiveScale();
 	opt.PosX = f:GetLeft() * scale;
 	opt.PosY = f:GetTop() * scale;
+
 end

 function f:RestoreLayout(frame)
@@ -507,54 +532,52 @@ function f:RestoreLayout(frame)
 		XBT_DB[frame] = {
 			["point"] = "CENTER",
 			["relativePoint"] = "CENTER",
-			["xOfs"] = 0,
-			["yOfs"] = 0,
+			["PosX"] = 0,
+			["PosY"] = 0,
+			["firsttime"] = true,
 		}
-		opt = XBT_DB[frame];
+		opt = XBT_DB[frame]
 	end

 	local x = opt.PosX;
 	local y = opt.PosY;
-	local s = f:GetEffectiveScale();
+	local s = f:GetEffectiveScale()

-	    if not x or not y then
-		f:ClearAllPoints();
-		f:SetPoint("CENTER", UIParent, "CENTER", 0, 0);
+	if not x or not y or opt.firsttime then
+		f:ClearAllPoints()
+		f:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
+		if opt.firsttime then opt.firsttime = nil end
 		return
-	    end
+	end

 	--calculate the scale
-	x,y = x/s,y/s;
+	x,y = x/s, y/s

 	--set the location
-	f:ClearAllPoints();
-	f:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", x, y);
+	f:ClearAllPoints()
+	f:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", x, y)

 end

-function f:getBarColor(dur, expR, reverse)
-	--check for buffs that don't expire
-	if dur == 0 then
-		return 153/255, 217/255, 234/255
+function f:getBarColor(dur, expR)
+	if dur <= 0 then
+		--this will make the bar green
+		dur = 1
+		expR = 1
 	end
-
 	local r
 	local g = 1
 	local cur = 2 * expR/dur
 	if cur > 1 then
-		r = 2 - cur
+		return 2 - cur, 1, 0
 	else
-		r = 1
-		g = cur
-	end
-	if reverse then
-		return g, r, 0
-	else
-		return r, g, 0
+		return 1, cur, 0
 	end
 end

 function f:GetTimeText(timeLeft)
+	if timeLeft <= 0 then return nil end
+
 	local hours, minutes, seconds = 0, 0, 0
 	if( timeLeft >= 3600 ) then
 		hours = floor(timeLeft / 3600)
diff --git a/XanBuffTimers.toc b/XanBuffTimers.toc
index 04531ca..d3bcd56 100644
--- a/XanBuffTimers.toc
+++ b/XanBuffTimers.toc
@@ -1,8 +1,8 @@
-## Interface: 30300
-## Title: XanBuffTimers
-## Notes: A small text based progress bar system for tracking buffs (player/target/focus)
-## Author: Xanthos
-## Version: 1.1
+## Interface: 40000
+## Title: xanBuffTimers
+## Notes: A small text based progress bar system for target buffs.
+## Author: Xruptor
+## Version: 1.0
 ## SavedVariablesPerCharacter: XBT_DB

-XanBuffTimers.lua
+xanBuffTimers.lua