Thread Tools Display Modes
09-10-13, 10:12 PM   #1
siweia
A Flamescale Wyrmkin
 
siweia's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2011
Posts: 126
Need some help on totembar please

I tried to add a timer on the ouf_totembar, but the problem is that I can't make it update itself well,
and when I destroyed the totem, the timer would stop at the time it left instead of disppear.
Please help!

Code:
local _, ns = ...
local oUF = ns.oUF or oUF

if not oUF then return end

local _, pClass = UnitClass("player")
local total = 0
local delay = 0.01

-- In the order, fire, earth, water, air
local colors = {
	[1] = {.58,.23,.10},
	[2] = {.23,.45,.13},		
	[3] = {.19,.48,.60},
	[4] = {.42,.18,.74},	
}

local GetTotemInfo, SetValue, GetTime = GetTotemInfo, SetValue, GetTime
local Timer
	
local Abbrev = function(name)	
	return (string.len(name) > 10) and string.gsub(name, "%s*(.)%S*%s*", "%1. ") or name
end
local function TotemOnClick(self,...)
	local id = self.ID
	local mouse = ...
	if IsShiftKeyDown() then
		for j = 1,4 do 
			DestroyTotem(j)
		end 
	else 
		DestroyTotem(id) 
	end
end
	
local function InitDestroy(self)
	local totem = self.TotemBar
	for i = 1 , 4 do
		local Destroy = CreateFrame("Button",nil, totem[i])
		Destroy:SetAllPoints(totem[i])
		Destroy:RegisterForClicks("LeftButtonUp", "RightButtonUp")
		Destroy.ID = i
		Destroy:SetScript("OnClick", TotemOnClick)
	end
end
	
local function UpdateSlot(self, slot)
	local totem = self.TotemBar

	local haveTotem, name, startTime, duration, totemIcon = GetTotemInfo(slot)

	totem[slot]:SetStatusBarColor(unpack(totem.colors[slot]))
	totem[slot]:SetValue(0)
	totem[slot].Time = totem[slot]:CreateFontString(nil, "OVERLAY")
	totem[slot].Time:SetPoint('CENTER', totem[slot], 'CENTER', 0, 1)
	totem[slot].Time:SetFont(NAMEPLATE_FONT, 14, "THINOUTLINE")
	-- Multipliers
	if (totem[slot].bg.multiplier) then
		local mu = totem[slot].bg.multiplier
		local r, g, b = totem[slot]:GetStatusBarColor()
		r, g, b = r*mu, g*mu, b*mu
		totem[slot].bg:SetVertexColor(r, g, b) 
	end
	
	totem[slot].ID = slot
	-- If we have a totem then set his value 
	if(haveTotem) then
		if totem[slot].Name then
			totem[slot].Name:SetText(Abbrev(name))
		end					
		if(duration >= 0) then
			if duration == 0 then
				totem[slot]:SetValue(0)
			else
				totem[slot]:SetValue(1 - ((GetTime() - startTime) / duration))
			end
			-- Status bar update
			totem[slot]:SetScript("OnUpdate", function(self,elapsed)
				total = total + elapsed
				if total >= delay then
					total = 0
					haveTotem, name, startTime, duration, totemIcon = GetTotemInfo(self.ID)
					if ((GetTime() - startTime) == 0) or (duration == 0) then
						self:SetValue(0)
					else
						self:SetValue(1 - ((GetTime() - startTime) / duration))
					end
				end
				Timer = startTime + duration - GetTime()
				if haveTotem then
					if Timer > 0 then
						self.Time:SetFormattedText("%d", Timer)
					else
						self.Time:SetText(" ")
					end
				else
					self.Time:SetText(" ")
				end
			end)
		else
			-- There's no need to update because it doesn't have any duration
			totem[slot]:SetScript("OnUpdate",nil)
			totem[slot]:SetValue(0)
		end
	else
		-- No totem = no time
		if totem[slot].Name then
			totem[slot].Name:SetText(" ")
		end
		totem[slot]:SetValue(0)
	end
end

local function Update(self, unit)
	-- Update every slot on login, still have issues with it
	for i = 1, 4 do 
		UpdateSlot(self, i)
	end
end

local function Event(self,event,...)
	if event == "PLAYER_TOTEM_UPDATE" then
		UpdateSlot(self, ...)
	end
end

local function Enable(self, unit)
	local totem = self.TotemBar
	
	if(totem) then
		self:RegisterEvent("PLAYER_TOTEM_UPDATE" , Event, true)
		totem.colors = setmetatable(totem.colors or {}, {__index = colors})
		delay = totem.delay or delay
		if totem.Destroy then
			InitDestroy(self)
		end		
		TotemFrame:UnregisterAllEvents()
		return true
	end	
end

local function Disable(self,unit)
	local totem = self.TotemBar
	if(totem) then
		self:UnregisterEvent("PLAYER_TOTEM_UPDATE", Event)
		
		TotemFrame:Show()
	end
end
			
oUF:AddElement("TotemBar",Update,Enable,Disable)
  Reply With Quote
09-10-13, 10:54 PM   #2
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
I'm not at home and can't review your code in detail at the moment, but:

1) DestroyTotem has been a protected function for several major patches now -- addons and macros can't call it, and trying to do so, even using a secure button or macro, will result in an "action blocked" error -- and is now in the same category of "completely off-limits" as CastSpellByName etc. You should remove your OnClick script, as it cannot be made to work.

2) Why are you trying to create your own totem bars element instead of using the totem bars element that is already included in oUF?
__________________
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.
  Reply With Quote
09-11-13, 02:08 AM   #3
siweia
A Flamescale Wyrmkin
 
siweia's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2011
Posts: 126
Originally Posted by Phanx View Post
I'm not at home and can't review your code in detail at the moment, but:

1) DestroyTotem has been a protected function for several major patches now -- addons and macros can't call it, and trying to do so, even using a secure button or macro, will result in an "action blocked" error -- and is now in the same category of "completely off-limits" as CastSpellByName etc. You should remove your OnClick script, as it cannot be made to work.

2) Why are you trying to create your own totem bars element instead of using the totem bars element that is already included in oUF?
The onclick code was not used in the unitframes currently. I'm using ouf_qulight, and these code is used by the author instead of the original version.

Did the totem bar in ouf have the timer thing for totem?

Last edited by siweia : 09-11-13 at 04:01 AM.
  Reply With Quote
09-12-13, 11:53 PM   #4
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by siweia View Post
Did the totem bar in ouf have the timer thing for totem?
By default, no, but it's trivial to add your own OnUpdate script, which you need to do anyway if you want a moving statusbar.

Outside your spawn function:
Code:
local TOTEM_COLORS = {
	[1] = { 0.6, 1,   0.2 }, -- Earth
	[2] = { 1,   0.6, 0.2 }, -- Fire
	[3] = { 0.2, 0.8, 1   }, -- Water
	[4] = { 0.8, 0.4, 1   }, -- Air
}

local function Totem_OnUpdate(bar, elapsed)
	local duration = bar.duration - elapsed
	bar.duration = timeLeft
	if duration > 0 then
		bar:SetValue(duration)
		bar.value:SetFormattedText(SecondsToTimeAbbrev(duration))
	end
end

local function Totems_PostUpdate(element, id, _, name, start, duration, icon)
	local bar = element[id]
	bar.duration = duration

	local color = TOTEM_COLORS[id]
	bar:SetStatusBarColor(color[1], color[2], color[3])

	if duration > 0 then
		bar:SetAlpha(1)
		bar:SetMinMaxValues(0, duration)
		bar:SetScript("OnUpdate", Totem_OnUpdate)
	else
		bar:SetAlpha(0.25)
		bar:SetMinMaxValues(0, 1)
		bar:SetScript("OnUpdate", nil)
		bar:SetValue(1)
		bar.value:SetText("")
	end
end
Inside your spawn function:
Code:
local Totems = {}
for i = 1, MAX_TOTEMS do
	local bar = CreateFrame("StatusBar", nil, self)
	bar:SetWidth(50)
	bar:SetHeight(10)
	bar:SetPoint("BOTTOMLEFT", self, "TOPLEFT", i * 50, 10)
	bar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
	
	local value = bar:CreateFontString(nil, "OVERLAY", "TextStatusBarText")
	value:SetPoint("CENTER")
	bar.value = value

	Totems[i] = bar
end
Totems.PostUpdate = Totems_PostUpdate
self.Totems = Totems
This will create 4 timer bars in a horizontal row above your unit frame, each with a text time in the middle. Obviously, you'll want to adjust the appearance and position of the bars to match your layout, and you can add other visual features (icons, etc.) if you want.
__________________
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.
  Reply With Quote
09-13-13, 09:42 AM   #5
siweia
A Flamescale Wyrmkin
 
siweia's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2011
Posts: 126
Originally Posted by Phanx View Post
By default, no, but it's trivial to add your own OnUpdate script, which you need to do anyway if you want a moving statusbar.
......
Thanks a lot, I would have a try.

Code:
local _, ns = ...
local oUF = ns.oUF or oUF

if not oUF then return end
local total = 0
local delay = 0.01

-- In the order, fire, earth, water, air
local colors = {
	[1] = {.58,.23,.10},
	[2] = {.23,.45,.13},		
	[3] = {.19,.48,.60},
	[4] = {.42,.18,.74},	
}

local GetTotemInfo, SetValue, GetTime = GetTotemInfo, SetValue, GetTime
local Timer
	
local function UpdateSlot(self, slot)
	local totem = self.TotemBar

	local haveTotem, name, startTime, duration, totemIcon = GetTotemInfo(slot)

	totem[slot]:SetStatusBarColor(unpack(totem.colors[slot]))
	totem[slot]:SetValue(0)
	totem[slot].Time = totem[slot]:CreateFontString(nil, "OVERLAY")
	totem[slot].Time:SetPoint('CENTER', totem[slot], 'CENTER', 0, 1)
	totem[slot].Time:SetFont(NAMEPLATE_FONT, 14, "THINOUTLINE")
	
	-- If we have a totem then set his value				
	if duration > 0 then
		-- Status bar update
		totem[slot]:SetAlpha(1)
		totem[slot]:SetMinMaxValues(0, duration)
		totem[slot]:SetScript("OnUpdate", function(self,elapsed)
			Timer = startTime + duration - GetTime()
			if Timer > 0 then
				self:SetValue(Timer)
				self.Time:SetFormattedText(SecondsToTimeAbbrev(Timer))
			end
		end)
	else
		-- There's no need to update because it doesn't have any duration
		totem[slot]:SetAlpha(0.25)
		totem[slot]:SetMinMaxValues(0, 1)
		totem[slot]:SetScript("OnUpdate",nil)
		totem[slot]:SetValue(1)
		totem[slot].Time:SetText("")
	end
end

local function Update(self, unit)
	-- Update every slot on login, still have issues with it
	for i = 1, 4 do 
		UpdateSlot(self, i)
	end
end

local function Event(self,event,...)
	if event == "PLAYER_TOTEM_UPDATE" then
		UpdateSlot(self, ...)
	end
end

local function Enable(self, unit)
	local totem = self.TotemBar
	
	if(totem) then
		self:RegisterEvent("PLAYER_TOTEM_UPDATE" , Event, true)
		totem.colors = setmetatable(totem.colors or {}, {__index = colors})
		delay = totem.delay or delay
		TotemFrame:UnregisterAllEvents()
		return true
	end	
end

local function Disable(self,unit)
	local totem = self.TotemBar
	if(totem) then
		self:UnregisterEvent("PLAYER_TOTEM_UPDATE", Event)
		
		TotemFrame:Show()
	end
end
			
oUF:AddElement("TotemBar",Update,Enable,Disable)
I am not good at coding, so I still not quite clear about how to use your code.
This is what I can do on the original code, but the timer would still remain when totem disable.
As in the picture, the old timer didn't disapper when the new timer of new totem came out.

Last edited by siweia : 09-13-13 at 12:46 PM.
  Reply With Quote
09-13-13, 01:29 PM   #6
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Don't move the creation of functions, fontstrings, etc. into a function that is called repeatedly -- your code will re-create the same function and create an additional font string every time a totem is cast or destroyed. Both are complete wastes of system resources, and the latter will result in tons of overlapping visible fontstrings that no longer update. Just use the code I gave you. The first section goes directly in your file, outside of any functions, and before your layout's spawn function, so it is loaded exactly one time. The second section goes inside your layout's spawn function, so it is loaded once per frame created, and should be surrounded by a check to make sure it only runs when the frame being created belongs to the player unit. You do not need Enable/Disable functions or any other code, since the code I posted uses oUF's native totem element, and does not create a new element.
__________________
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.
  Reply With Quote

WoWInterface » Featured Projects » oUF (Otravi Unit Frames) » Need some help on totembar please


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off