Quantcast

Completely new way to read and display the bars. Using one OnUpdate. Though I may rewrite this again LOL.

Xruptor [07-31-16 - 03:05]
Completely new way to read and display the bars.  Using one OnUpdate.  Though I may rewrite this again LOL.
Filename
XanDebuffTimers.lua
diff --git a/XanDebuffTimers.lua b/XanDebuffTimers.lua
index e85f6f9..d99b51d 100644
--- a/XanDebuffTimers.lua
+++ b/XanDebuffTimers.lua
@@ -27,6 +27,9 @@ local function Debug(...)
     if debugf then debugf:AddMessage(string.join(", ", tostringall(...))) end
 end

+timers.data = {}
+timersFocus.data = {}
+
 ----------------------
 --      Enable      --
 ----------------------
@@ -41,6 +44,9 @@ function f:PLAYER_LOGIN()
 	--create our anchors
 	f:CreateAnchor("XDT_Anchor", UIParent, "xanDebuffTimers: Target Anchor")
 	f:CreateAnchor("XDT_FocusAnchor", UIParent, "xanDebuffTimers: Focus Anchor")
+
+	--create our bars
+	f:generateBars()

 	f:UnregisterEvent("PLAYER_LOGIN")
 	f.PLAYER_LOGIN = nil
@@ -256,65 +262,11 @@ 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
-
-		local beforeEnd = self.endTime - GetTime()
-		local percentTotal = (beforeEnd / self.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 = (self.endTime - self.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)
-		--local testBar = ((percentFinal / 100) / 2.5) * 100
-
-		--Debug("(2) Spell("..self.spellName..") totalDuration: "..tostring(ceil(totalDuration)).."  |  totalBarSegment: "..tostring(ceil(totalBarSegment)).."  |  totalBarLength: "..tostring(ceil(totalBarLength)).."  |  barPercent: "..tostring(ceil(barPercent)))
-
-		--Debug("(3) Spell("..self.spellName..") Time: "..tostring(GetTime()).."  |  percentTotal: "..tostring(ceil(percentTotal)).."  |  PercentFinal: "..tostring(percentFinal).."  |  tmpBL: "..tostring(tmpBL).."  |  TextTime: "..tostring(ceil(beforeEnd)))
-
-		--Debug("(4) Spell("..self.spellName..") Time: "..tostring(GetTime()).."  |  beforeEnd: "..tostring(ceil(beforeEnd)).."  |  tmpBL: "..tostring(tmpBL).."  |  Testing: "..tostring(testing))
-
-		if barPercent <= 0 or beforeEnd <= 0 or totalBarLength <= 0 then
-			self.active = false
-			self:Hide()
-			f:ArrangeDebuffs(true, self.id)
-			return
-		end
-
-		self.percent = barPercent
-		self.tmpBL = totalBarLength
-		self.beforeEnd = beforeEnd
-
-		self.Bar:SetText( string.sub(BAR_TEXT, 1, totalBarLength).." | "..barLength.." | ".. totalBarLength)
-		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:ArrangeDebuffs(true, self.id)
-
-	end
-
-end
-
 function f:CreateDebuffTimers()

     local Frm = CreateFrame("Frame", nil, UIParent)

+	Frm.data = {}
     Frm.active = false
     Frm:SetWidth(ICON_SIZE)
     Frm:SetHeight(ICON_SIZE)
@@ -345,28 +297,107 @@ function f:CreateDebuffTimers()
 	Frm.Bar:SetFont(STANDARD_TEXT_FONT, 14, "OUTLINE, MONOCHROME")
 	Frm.Bar:SetText(BAR_TEXT)
 	Frm.Bar:SetPoint("LEFT", Frm.icon, "RIGHT", 1, 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
+		timers[i] = f:CreateDebuffTimers()
+		timersFocus[i] = f:CreateDebuffTimers()
+		if not timers.data[i] then timers.data[i] = {} end
+		if not timersFocus.data[i] then timersFocus.data[i] = {} end
+	end
+
+	--rearrange order
+	for i=1, MAX_TIMERS do
+		if XDT_DB.grow then
+			timers[i]:ClearAllPoints()
+			timers[i]:SetPoint("TOPLEFT", XDT_Anchor, "BOTTOMRIGHT", 0, adj)
+			timersFocus[i]:ClearAllPoints()
+			timersFocus[i]:SetPoint("TOPLEFT", XDT_FocusAnchor, "BOTTOMRIGHT", 0, adj)
+		else
+			timers[i]:ClearAllPoints()
+			timers[i]:SetPoint("BOTTOMLEFT", XDT_Anchor, "TOPRIGHT", 0, (adj * -1))
+			timersFocus[i]:ClearAllPoints()
+			timersFocus[i]:SetPoint("BOTTOMLEFT", XDT_FocusAnchor, "TOPRIGHT", 0, (adj * -1))
+		end
+		adj = adj - BAR_ADJUST
+    end
+
+end
+
+function f:ProcessDebuffBar(data)
+	if not data.active then return end --just in case
+
+	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)
+	--local testBar = ((percentFinal / 100) / 2.5) * 100
+
+	--Debug("(2) Spell("..data.spellName..") totalDuration: "..tostring(ceil(totalDuration)).."  |  totalBarSegment: "..tostring(ceil(totalBarSegment)).."  |  totalBarLength: "..tostring(ceil(totalBarLength)).."  |  barPercent: "..tostring(ceil(barPercent)))
+
+	--Debug("(3) Spell("..data.spellName..") Time: "..tostring(GetTime()).."  |  percentTotal: "..tostring(ceil(percentTotal)).."  |  PercentFinal: "..tostring(percentFinal).."  |  totalBarLength: "..tostring(totalBarLength).."  |  TextTime: "..tostring(ceil(beforeEnd)))
+
+	--Debug("(4) Spell("..data.spellName..") Time: "..tostring(GetTime()).."  |  beforeEnd: "..tostring(ceil(beforeEnd)).."  |  totalBarLength: "..tostring(totalBarLength).."  |  Testing: "..tostring(testing))
+
+	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
+
 ----------------------
 -- Debuff Functions --
 ----------------------

+--lets use one global OnUpdate instead of individual ones for each debuff 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
+
+	for i=1, MAX_TIMERS do
+		if timers.data[i].active then
+			self:ProcessDebuffBar(timers.data[i])
+		end
+		if timersFocus.data[i].active then
+			self:ProcessDebuffBar(timersFocus.data[i])
+		end
+	end
+	f:ArrangeDebuffs("target")
+	f:ArrangeDebuffs("focus")
+
+end)
+
 function f:ProcessDebuffs(sT, sdTimer)
 	--only process for as many timers as we are using
-	local slotNum = 0
 	for i=1, MAX_TIMERS do
-		local name, _, icon, count, _, duration, expTime, unitCaster, _, _, spellId = UnitAura(sT, i, 'HARMFUL|PLAYER')
-		if not name then break end
-		--UnitIsUnit is used JUST IN CASE (you never know lol)
+		local name, _, icon, count, _, duration, expTime, unitCaster, _, _, spellId = UnitAura(sT, i, 'PLAYER|HARMFUL')
 		--check for duration > 0 for the evil DIVIDE BY ZERO
-		if name and unitCaster and unitCaster == "player" and duration and duration > 0 then
+		if name and duration and duration > 0 then
 			local beforeEnd = expTime - GetTime()
 			local startTime = (expTime - duration)
 			local totalDuration = (expTime - startTime) --total duration of the spell
@@ -375,75 +406,61 @@ function f:ProcessDebuffs(sT, sdTimer)
 			local barPercent = (totalBarLength / string.len(BAR_TEXT)) * 100

 			if barPercent > 0 or beforeEnd > 0 or totalBarLength > 0 then
-				--get the next timer slot we can use
-				slotNum = slotNum + 1
-				if not sdTimer[slotNum] then sdTimer[slotNum] = f:CreateDebuffTimers() end --create the timer if it doesn't exist
-				sdTimer[slotNum].id = sT
-				sdTimer[slotNum].spellName = name
-				sdTimer[slotNum].spellId = spellId
-				sdTimer[slotNum].iconTex = icon
-				sdTimer[slotNum].icon:SetTexture(icon)
-				sdTimer[slotNum].startTime = startTime
-				sdTimer[slotNum].durationTime = duration
-				sdTimer[slotNum].beforeEnd = beforeEnd
-				sdTimer[slotNum].endTime = expTime
-				sdTimer[slotNum].tmpBL = totalBarLength
-				sdTimer[slotNum].stacks = count or 0
-				sdTimer[slotNum].percent = barPercent
-				sdTimer[slotNum].active = true
-				if not sdTimer[slotNum]:IsVisible() then sdTimer[slotNum]:Show() end
+				--data
+				sdTimer.data[i].id = sT
+				sdTimer.data[i].spellName = name
+				sdTimer.data[i].spellId = spellId
+				sdTimer.data[i].iconTex = icon
+				sdTimer.data[i].startTime = startTime
+				sdTimer.data[i].durationTime = duration
+				sdTimer.data[i].beforeEnd = beforeEnd
+				sdTimer.data[i].endTime = expTime
+				sdTimer.data[i].totalBarLength = totalBarLength
+				sdTimer.data[i].stacks = count or 0
+				sdTimer.data[i].percent = barPercent
+				sdTimer.data[i].active = true
+
 				--Debug("(1) Time: "..tostring(GetTime()).."  |  Start: "..tostring(expTime - duration).."  |  Duration: "..tostring(duration).."  |  Expiration: "..tostring(expTime))
 				--Debug("<Percentage> "..tostring(sdTimer[slotNum].percent) )
 			end
+		else
+			sdTimer.data[i].active = false
 		end
 	end

-	--clear everything else
-	for i=(slotNum+1), #sdTimer do
-		if sdTimer[i] then
-			sdTimer[i].active = false
-			sdTimer[i]:Hide()
-		end
-	end
-	if slotNum > 0 then
-		f:ArrangeDebuffs(false, sT)
-	end
+	f:ArrangeDebuffs(sT)
 end

 function f:ClearDebuffs(sdTimer)
 	local adj = 0

-	for i=1, #sdTimer do
-		if sdTimer[i].active then
-			sdTimer[i].active = false
-		end
-		--reset the order
-		if XDT_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
-
+	for i=1, MAX_TIMERS do
+		sdTimer.data[i].active = false
 		sdTimer[i]:Hide()
 	end

 end

-function f:ArrangeDebuffs(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
+local function deepcopy(orig)
+    local orig_type = type(orig)
+    local copy
+    if orig_type == 'table' then
+        copy = {}
+        for orig_key, orig_value in next, orig, nil do
+            copy[deepcopy(orig_key)] = deepcopy(orig_value)
+        end
+        setmetatable(copy, deepcopy(getmetatable(orig)))
+    else -- number, string, boolean, etc
+        copy = orig
+    end
+    return copy
+end
+
+function f:ArrangeDebuffs(id)

 	local adj = 0
 	local sdTimer
+	local tmpList = {}

 	if id == "target" then
 		sdTimer = timers
@@ -453,74 +470,57 @@ function f:ArrangeDebuffs(throttle, id)
 		return
 	end

-	--hides
-	for i=1, #sdTimer do
-		if not sdTimer[i].active then
-			sdTimer[i]:Hide()
+	for i=1, MAX_TIMERS do
+		if sdTimer.data[i].active then
+			table.insert(tmpList, deepcopy(sdTimer.data[i]))
+			--Debug(i)
 		end
-
 	end
-
+
 	if XDT_DB.grow then
 		--bars will grow down
 		if XDT_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.percent < b.percent);
-				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 then
-					return (a.percent > b.percent);
-				end
-				return false;
-			end)
+			table.sort(tmpList, function(a,b) return (a.percent > b.percent) end)
+
 		end
 	else
 		--bars will grow up
 		if XDT_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.percent > b.percent);
-				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 then
-					return (a.percent < b.percent);
-				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 XDT_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
+			sdTimer.data[i] = tmpList[i]
+
+			sdTimer[i].Bar:SetText( string.sub(BAR_TEXT, 1, sdTimer.data[i].totalBarLength) )
+			sdTimer[i].Bar:SetTextColor(f:getBarColor(sdTimer.data[i].durationTime, sdTimer.data[i].beforeEnd))
+			sdTimer[i].icon:SetTexture(sdTimer.data[i].iconTex)
+			if sdTimer.data[i].stacks > 0 then
+				sdTimer[i].stacktext:SetText(sdTimer.data[i].stacks)
+			else
+				sdTimer[i].stacktext:SetText(nil)
+			end
+			sdTimer[i].timetext:SetText(f:GetTimeText(ceil(sdTimer.data[i].beforeEnd)))
+
+			sdTimer[i]:Show()
 		else
-			sdTimer[i]:ClearAllPoints()
-			sdTimer[i]:SetPoint("BOTTOMLEFT", pointT[sdTimer[i].id], "TOPRIGHT", 0, (adj * -1))
+			sdTimer.data[i].active = false
+			sdTimer[i]:Hide()
 		end
-		adj = adj - BAR_ADJUST
     end
-
+
 end

 ----------------------
@@ -609,5 +609,5 @@ function f:GetTimeText(timeLeft)
 		return nil
 	end
 end
-
+
 if IsLoggedIn() then f:PLAYER_LOGIN() else f:RegisterEvent("PLAYER_LOGIN") end