Thread Tools Display Modes
09-23-12, 12:59 PM   #1
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Post Help with my addon

Hello WoWinterface!

Recently I have been trying to "learn" LUA, to modify addons to ensure my UI ran as smooth as I'd like. I finally took the jump to make my own addon! I've run into quite a snag though >.<

The addon works great, after the first login, and reloading of my UI, but when I login I am prompted with this error:

Code:
Message: Interface\AddOns\ClamHolyPower\core.lua:67: attempt to index field '?' (a nil value)
Time: 09/23/12 14:54:03
Count: 2
Stack: Interface\AddOns\ClamHolyPower\core.lua:67: in function <Interface\AddOns\ClamHolyPower\core.lua:64>

Locals: p = 0
(for index) = 1
(for limit) = 5
(for step) = 1
i = 1
(*temporary) = nil
(*temporary) = nil
(*temporary) = "1"
(*temporary) = "attempt to index field '?' (a nil value)"
_G = <table> {
 ContainerFrame5Item7 = ContainerFrame5Item7 {
 }
 MultiCastActionButton6Cooldown = MultiCastActionButton6Cooldown {
 }
 MerchantItem9ItemButtonStock = MerchantItem9ItemButtonStock {
 }
 GetTrainerServiceTypeFilter = <function> defined =[C]:-1
 UNIT_NAMES_COMBATLOG_TOOLTIP = "Color unit names."
 UNIT_NAMEPLATES_TYPE_TOOLTIP_3 = "This method avoids overlapping nameplates by spreading them out horizontally and vertically."
 SetTrainerServiceTypeFilter = <function> defined =[C]:-1
 EventTraceFrameButton7HideButton = EventTraceFrameButton7HideButton {
 }
 SPELL_FAILED_CUSTOM_ERROR_71 = "This partygoer wants to dance with you."
 CompactUnitFrameProfilesGeneralOptionsFrameHealthTextDropdownButtonNormalTexture = CompactUnitFrameProfilesGeneralOptionsFrameHealthTextDropdownButtonNormalTexture {
 }
 TutorialFrameLeft19 = TutorialFrameLeft19 {
 }
 MultiCastActionButton2Cooldown = MultiCastActionButton2Cooldown {
 }
 ERR_TRADE_EQUIPPED_BAG = "You can't trade equipped bags."
 PVP_RANK_6_1 = "Corporal"
 BOOKTYPE_PROFESSION = "professions"
 OPTION_TOOLTIP_SHOW_MULTIBAR4 = "Toggles an additional optional actionbar on the right side of the screen."
 InterfaceOptionsDisplayPanelShowAggroPercentageText = InterfaceOptionsDisplayPanelShowAggroPercentageText {
 }
 VideoOptionsFrameCategoryFrameButton17ToggleHighlightTexture = VideoOptionsFrameCategoryFrameButton17ToggleHighlightTexture {
 }
 MerchantItem3AltCurrencyFrameItem1Text = MerchantItem3AltCurrencyFrameItem1Text {
 }
 OPTION_TOOLTIP_ACTION_BUTTON_USE_KEY_DOWN = "Action button keybinds will respond on key down, rather than on key up."
 BINDING_NAME_NAMEPLATES = "Show Enemy Name Plates"
 CHAT_HEADER_SUFFIX = ": "
 IsReferAFriendLinked = <function> defined =[C]:-1
 RaidTray_Buff_OnUpdate = <function> defined @Interface\FrameXML\BuffFrame.lua:149
 QuestDetailBotLeftCorner = QuestDetailBotLeftCorner {
 }
 ItemTextFrameInsetInsetTopRightCorner = ItemTextFrameInsetInsetTopRightCorner {
 }
 CALENDAR_RAID_RESET_DESCRIPTION = "%1$s resets at %2$s."
 CHAT_CONFIG_OTHER_COMBAT = <table> {
 }
 CONSOLIDATED_BUFFS_PER_ROW = 4
 TutorialFrameRight19 = TutorialFrameRight19 {
 }
 MoneyFrame_OnEvent = <function> defined @Interface\FrameXML\MoneyFrame.lua:233
 BN_UNABLE_TO_RESOLVE_NAME = "Unable to whisper '%s'. Battle.net may be unavailable."
 WatchFrameItem_OnEvent = <function> defined @Interface\FrameXML\WatchFrame.lua:1367
 InterfaceOptionsCombatTextPanelFCTDropDown_OnClick = <function> defined @Interface\FrameXML\InterfaceOptionsPanels.lua:1419
 LFGTeleport = <function> defined =[C]:-1
 SpellButton6Cooldown = SpellButton6Cooldown {
 }
 ToggleEncounterJournal = <function> defined @Interface\FrameXML\UIParent.lua:617
 Graphics_QualityText = Graphics_QualityText {
 }
 TalentMicroButtonAlertShadowTopLeft = TalentMicroButtonAlertShadowTopLeft {
 }
 ROGUE_COMBAT_CORE_ABILITY_4 = "Use for damage when you have 5 combo points. Primary finishing move."
 Advanced_GraphicsAPIDropDownButtonHighlightTexture = Advanced_GraphicsAPIDropDownButtonHighlightTexture {
 }
 CompactUnitFrameProfilesSaveButton = CompactUnitFrameProfilesSaveButton {
 }
 BankFrameItem17SearchOverlay = BankFrameItem17SearchOverlay {
 }
 ACTION_SPELL_MISSED_POSSESSIVE = "1"
 ChannelMemberButton10SpeakerFrameOn = ChannelMemberButton10SpeakerFrameOn {
 }
 EventTraceFrameTitleButton = EventTraceFrameTitleButton {
 }
 Is64BitClient = <function> defined =[C]:-1
 SecureCmdItemParse = <function> defined @Interface\FrameXML\ChatFrame.lua:1047
 SLASH_STOPATTACK1 = "/stopattack"
 MultiCastActionButton4HotKey = MultiCastActionButton4HotK
My addon code is listed below:

Lua Code:
  1. --Disable ClamHolyPower if player is not a paladin.
  2. if select(2, UnitClass("player")) ~= "PALADIN" then
  3.     return DisableAddOn("ClamHolyPower")
  4. end
  5.  
  6. -------------------
  7. -- CONFIGURATION --
  8. -------------------
  9.  
  10. -- Background Configuration --
  11. local bkr = 0 -- Background color: Red
  12. local bkg = 0 -- Background color: Green
  13. local bkb = 0 -- Background color: Blue
  14. local bka = 0.60 -- Background alpha: 0 = Transparent    1 = Opaque
  15. local hwe = false -- Hide the background when holy power is empty.
  16.  
  17. -- Indicator Configuration --
  18. local itex = "Interface\\AddOns\\ClamHolyPower\\flatsmooth"  -- Path pointing to the texture used for the indicator.
  19. local ir = 1 -- Indicator color: Red
  20. local ig = 0.8 -- Indicator color: Green
  21. local ib = 0 -- Indicator color: Blue
  22.  
  23. -- Frame Configuration --
  24. local fposx = -193.25 -- Frame position: X
  25. local fposy = -243 -- Frame position: Y
  26. local fwidth = 231 -- Frame width.
  27. local fheight = 11 -- Frame height.
  28.  
  29. -----------------------
  30. -- END CONFIGURATION --
  31. -----------------------
  32.  
  33. -- Pertinent Variables
  34. local _G=_G
  35. local maxhp = UnitPowerMax("player", 9)
  36. local vedges = (maxhp+1) -- Defines the amount of vertical 1px borders there will be.  Defined as maximum holy power + 1
  37.  
  38. -- Create ClamHolyPowerFrame
  39. local f = CreateFrame("Frame", "ClamHolyPowerFrame", UIParent)
  40. f:SetFrameStrata("BACKGROUND")
  41. f:SetPoint("CENTER",fposx,fposy)
  42. f:SetWidth(fwidth)
  43. f:SetHeight(fheight)
  44.  
  45. -- Create Background Frame --
  46. local bk = f:CreateTexture(nil, "BACKGROUND")
  47. bk:SetTexture(bkr,bkg,bkb,bka)
  48. bk:SetAllPoints(f)
  49. f.texture = bk
  50.  
  51. -- Create Indicator Frames --
  52. local iwidth = floor(((fwidth-vedges)/maxhp)) -- Attempt to use the frame width to dictate the width of each indicator.  May need to floor/ciel/tweak
  53. local iheight = (fheight-2) -- Attempt to use the frame height to dictate the height of each indicator.  Should need no tweaking
  54. for i=1, maxhp do
  55.     _G["ind"..i] = f:CreateTexture(nil, "HIGH")
  56.     _G["ind"..i]:SetTexture(itex)
  57.     _G["ind"..i]:SetPoint("LEFT",floor(((((((fwidth)/maxhp)*i)-(fwidth)/maxhp)+1))), 0)
  58.     _G["ind"..i]:SetWidth(iwidth)
  59.     _G["ind"..i]:SetHeight(iheight)
  60.     _G["ind"..i]:SetVertexColor(ir,ig,ib)
  61.     f.texture = _G["ind"..i]
  62. end
  63.  
  64. function init()
  65.     local p = UnitPower("player", 9)
  66.     for i = 1, 5 do
  67.         _G["ind"..i]:Hide()
  68.     end
  69.     if p == 0 and hwe == false then
  70.         f:Show()
  71.     else
  72.         f:Hide()
  73.     end
  74.     if p > 0 then
  75.         f:Show()
  76.         for i = 1, p do
  77.             _G["ind"..i]:Show()
  78.         end
  79.     end
  80. end
  81.  
  82. local run = CreateFrame("FRAME")
  83. run:RegisterEvent("UNIT_POWER")
  84. run:RegisterEvent("PLAYER_LOGIN")
  85. run:SetScript("OnEvent", init)

I really can not understand why my addon is throwing errors on the first login, but works 100% fine after I reload the UI.

Thank you very much for the time and help!
  Reply With Quote
09-23-12, 01:18 PM   #2
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
It is possible that you are asking for some information about your character too early when first logging in. There are a few things that are not available right away on first login, but will be when reloading. (When you reload your UI, your character does not exit and re-enter the world.) Add print() statements to your code at various places to help debug.

For instance, after line 35 add:
Code:
print(maxhp)
to see if you get what you are expecting there.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
09-23-12, 01:20 PM   #3
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
I was in the middle of editing my post, when I figured I'd give ONE more refresh!

That is it!

UnitPowerMax("player", 9) is not returning a value upon logging in, setting Maxhp to 5 manually solves the issue.

Thank you so much for your time anyways, Seerah!
  Reply With Quote
09-23-12, 01:22 PM   #4
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,360
You have local maxhp = UnitPowerMax("player", 9) at file scope, meaning it tries to run immediately upon the client reading your addon file.

It's possible that information is not available to the client yet.

It's best if you do all your initialization at the PLAYER_LOGIN event (including registering the rest of the events you want to monitor)
  Reply With Quote
09-23-12, 01:27 PM   #5
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Learning these things one step at a time heh.

I really appreciate the help Seerah and Dridzt.

I will look at registering "UNIT_POWER" after "PLAYER_LOGIN" as well. Going to do some reorganizing =]
  Reply With Quote
09-23-12, 02:26 PM   #6
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,326
Originally Posted by Clamsoda View Post
Code:
_G["ind"..i] = f:CreateTexture(nil, "HIGH")
This line should be throwing an error too since HIGH is not a valid DrawLayer. It might not be doing so now since the code as-is isn't even running the line right now because of issues already posted above.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
09-23-12, 09:24 PM   #7
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
@SDPhantom: There are no further errors. The code ran "fine", after I sorted out the call to a nil value (Unit Power Max isn't defined on startup, hence the error, manually defining it or calling it after Player_Login works). The code has yet to error during normal use (instances and the like).

I'll make sure to change it to ARTWORK. Thank you very much for your input!

EDIT: Also, anyone who is reading this, I wanted to inquire about my function for drawing the indicators. Like I said, other than editing blatantly obvious aspects of popular addons, I have less than three full days of LUA experience. When I was trying to come up with a way to draw all the indicators with one function, I stumbled upon a website describing dynamic variables ( _G["ind"..i] in my case). Someone on that website mentioned that this is not the best way to create them, and results in a memory leak?

Is this true, false? Can anyone offer some insight?

Thank you everyone for your help, it is helping immensely.

Last edited by Clamsoda : 09-23-12 at 09:32 PM.
  Reply With Quote
09-23-12, 10:07 PM   #8
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
It's not a memory leak, but it's also one of worst possible methods. First, you're putting things in the global namespace (the area shared by all addons and the default UI) that don't need to be there (they should be local to your addon). Second, you're putting things in the global namespace with completely generic names like "ind4". If you need to put something in the global namespace (many addons put their main addon object there, for example) you should give it a name that both describes its function, and identifies its origin, like "ClamsodaAddonIndicator4". In this case, though, these objects should not be global.

A better way is to store the objects in an indexed table, and access them that way.

Here is your original code, with all of the initialization stuff moved into the PLAYER_LOGIN event handler, the indicators moved into a table, the UNIT_POWER event handler rewritten more efficiently, and a few other minor changes.

Code:
--Disable ClamHolyPower if player is not a paladin.
if select(2, UnitClass("player")) ~= "PALADIN" then
    return DisableAddOn("ClamHolyPower")
end

-------------------
-- CONFIGURATION --
-------------------

-- Background Configuration --
local bkr = 0 -- Background color: Red
local bkg = 0 -- Background color: Green
local bkb = 0 -- Background color: Blue
local bka = 0.60 -- Background alpha: 0 = Transparent    1 = Opaque
local hwe = false -- Hide the background when holy power is empty.

-- Indicator Configuration --
local itex = "Interface\\AddOns\\ClamHolyPower\\flatsmooth"  -- Path pointing to the texture used for the indicator.
local ir = 1 -- Indicator color: Red
local ig = 0.8 -- Indicator color: Green
local ib = 0 -- Indicator color: Blue

-- Frame Configuration --
local fposx = -193.25 -- Frame position: X
local fposy = -243 -- Frame position: Y
local fwidth = 231 -- Frame width.
local fheight = 11 -- Frame height.

-----------------------
-- END CONFIGURATION --
-----------------------

-- Pertinent Variables
local maxhp
local vedges

-- Create ClamHolyPowerFrame
local f = CreateFrame("Frame", "ClamHolyPowerFrame", UIParent)
f:SetScript("OnEvent", function(self, event, ...) return self[event](self, event, ...) end)
f:RegisterEvent("PLAYER_LOGIN")

function f:PLAYER_LOGIN()
	-- set these values here instead of at runtime
	maxhp = UnitPowerMax("player", 9)
	vedges = maxhp + 1 -- Defines the amount of vertical 1px borders there will be.  Defined as maximum holy power + 1

	self:SetFrameStrata("BACKGROUND")
	self:SetPoint("CENTER",fposx,fposy)
	self:SetWidth(fwidth)
	self:SetHeight(fheight)

	-- Create Background Frame --
	local bk = self:CreateTexture(nil, "BACKGROUND")
	bk:SetTexture(bkr, bkg, bkb, bka)
	bk:SetAllPoints(true)
	self.background = bk

	-- Create Indicator Frames --
	local iwidth = floor((fwidth - vedges) / maxhp) -- Attempt to use the frame width to dictate the width of each indicator.  May need to floor/ciel/tweak
	local iheight = fheight - 2 -- Attempt to use the frame height to dictate the height of each indicator.  Should need no tweaking

	self.indicators = {}
	for i = 1, maxhp do
		local ind = self:CreateTexture(nil, "HIGH")
		ind:SetTexture(itex)
		-- Just anchor each indicator relative to the previous one, instead of doing math.
		if i == 1 then
			ind:SetPoint("LEFT", self.indicators[i-1], "RIGHT", 1, 0)
		else
			ind:SetPoint("LEFT", f, 1, 0)
		end
		ind:SetWidth(iwidth)
		ind:SetHeight(iheight)
		ind:SetVertexColor(ir, ig, ib)
		self.indicators[i] = ind
	end

	self:UnregisterEvent("PLAYER_LOGIN")
	-- only register UNIT_POWER for the player unit
	self:RegisterUnitEvent("UNIT_POWER", "player")
end

function f:UNIT_POWER(event, unit, powerType)
	if powerType ~= HOLY_POWER" then
		-- Don't waste time updating if holy power didn't change.
		return
	end

	local p = UnitPower("player", 9)
	if p > 0 then
		for i = 1, #self.indicators do
			if i > p then
				self.indicators[i]:Hide()
			else
				self.indicators[i]:Show()
			end
		end
		self:Show()
	else
		self:Hide()
	end
end
__________________
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-23-12, 10:31 PM   #9
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Very very interesting insight. I can understand how my method could be a pollutant.

I copied your pasted code verbatim, and it doesn't work. I fixed the un-finished string on line 84, and it still doesn't work as intended. It isn't erroring, but, is not producing the correct results, and admittedly I am overwhelmed by a lot of your changes (though greatly inspired!)

The most obvious change, other than the initialization changes, is the change to my create indicator function. I love how simple you made it, and I love that you got rid of my ever-so-clunky math >.>

If you could help me troubleshoot the code you wrote, that'd be very helpful. I feel like I am in a foreign land without a map!
  Reply With Quote
09-23-12, 10:41 PM   #10
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,360
Well depending what UnitPowerMax() returns in PLAYER_LOGIN there's a good chance not enough frames (or none at all) for hopo are initialized.

Also doesn't paladin (don't play one) have some talent that can increase the number, re-talenting or re-speccing should also be taken into account (OR in the UNIT_POWER handler the current hopo returned checked against the existence of sufficient frames and fill in any missing)

Last edited by Dridzt : 09-23-12 at 10:48 PM.
  Reply With Quote
09-23-12, 10:45 PM   #11
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Well, here is how it is operating (ignore the hide when empty condition):

0 holy power - background is hidden
1 holy power - background shows (no indicators)
2 holy power - 1st indicator shows (positioned correctly)

all subsequent holy power does NOT create a new indicator.

Like I said, I am very lost in Phanx's code - so I am trying to wrap my head around the syntax, AND the logic.

EDIT: Dridzt, holy power max does change, yes. The way I wrote my addon, it checked for UnitMaxPower, and generated enough indicators to match that, at appropriate widths. Unfortunately, UnitMaxPower isn't initializing properly in MY code, do to a value not returning on PLAYER_LOGIN, so I am using a static value of 5 for testing.

EDIT: I was able to achieve proper functionality by replacing:

Lua Code:
  1. if i == 1 then
  2.     ind:SetPoint("LEFT", self.indicators[i-1], "RIGHT", 1, 0)
  3. else
  4.     ind:SetPoint("LEFT", f, 1, 0)
  5. end

With my old, math heavy function.

One-thousandth Edit >.>: I am only one step removed from getting my addon to work perfectly with the majority of Phanx's changes. I am noticing the frame doesn't update after a reload of the UI, or if I login with holy power, until the UNIT_POWER event fires. I pasted the code from f:UNIT_POWER into f:PLAYER_LOGIN(), and it works great, but obviously I don't want the exact same code in two places. I can't seem to get f:PLAYER_LOGIN() to run f:UNIT_POWER() one time, just to force an update, seeing as the function is event driven.

Last edited by Clamsoda : 09-23-12 at 11:13 PM.
  Reply With Quote
09-23-12, 11:23 PM   #12
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Gave her a go around, Dridzt.

Code:
Message: Interface\AddOns\ClamHolyPower\core.lua:79: attempt to index local 'self' (a nil value)
Time: 09/24/12 01:19:25
Count: 1
Stack: Interface\AddOns\ClamHolyPower\core.lua:79: in function `?'
Interface\AddOns\ClamHolyPower\core.lua:40: in function <Interface\AddOns\ClamHolyPower\core.lua:39>

Locals: self = nil
bk = <unnamed> {
 0 = <userdata>
}
(*temporary) = <function> defined =[C]:-1
(*temporary) = <unnamed> {
 0 = <userdata>
}
(*temporary) = true
(*temporary) = <userdata>
(*temporary) = 0
(*temporary) = 0.6
(*temporary) = "attempt to index local 'self' (a nil value)"
maxhp = 5
vedges = 6
f = ClamHolyPowerFrame {
 CreateIndicators = <function> defined @Interface\AddOns\ClamHolyPower\core.lua:45
 UNIT_POWER = <function> defined @Interface\AddOns\ClamHolyPower\core.lua:94
 PLAYER_LOGIN = <function> defined @Interface\AddOns\ClamHolyPower\core.lua:65
 UNIT_MAXPOWER = <function> defined @Interface\AddOns\ClamHolyPower\core.lua:116
 0 = <userdata>
 OnEvent = <function> defined @Interface\AddOns\ClamHolyPower\core.lua:39
}
fposx = -193.25
fposy = -243
fwidth = 231
fheight = 11
bkr = 0
bkg = 0
bkb = 0
bka = 0.6
Tables aren't my thing as you guys can tell from the original code, So I have NO idea how to trouble shoot your code haha. I am very close to having Phanx's changes functioning. I like your idea of updating maxhp after a respec or leveling, so I'll try to work that in as well.

As for your code, might you explain to me some of your changes? As you guys know I am lost and lost and lost

Trying to keep up though guys, I appreciate every single response!
  Reply With Quote
09-23-12, 11:29 PM   #13
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,360
Code:
--Disable ClamHolyPower if player is not a paladin.
if select(2, UnitClass("player")) ~= "PALADIN" then
  return DisableAddOn("ClamHolyPower")
end

-------------------
-- CONFIGURATION --
-------------------

-- Background Configuration --
local bkr = 0 -- Background color: Red
local bkg = 0 -- Background color: Green
local bkb = 0 -- Background color: Blue
local bka = 0.60 -- Background alpha: 0 = Transparent  1 = Opaque
local hwe = false -- Hide the background when holy power is empty.

-- Indicator Configuration --
local itex = "Interface\\AddOns\\ClamHolyPower\\flatsmooth"  -- Path pointing to the texture used for the indicator.
local ir = 1 -- Indicator color: Red
local ig = 0.8 -- Indicator color: Green
local ib = 0 -- Indicator color: Blue

-- Frame Configuration --
local fposx = -193.25 -- Frame position: X
local fposy = -243 -- Frame position: Y
local fwidth = 231 -- Frame width.
local fheight = 11 -- Frame height.

-----------------------
-- END CONFIGURATION --
-----------------------

-- Pertinent Variables
local maxhp
local vedges

-- Create ClamHolyPowerFrame
local f = CreateFrame("Frame", "ClamHolyPowerFrame", UIParent)
f.OnEvent = function(self,event,...)
  return self[event] and self[event](...)
end
f:SetScript("OnEvent", f.OnEvent)
f:RegisterEvent("PLAYER_LOGIN")

function f.CreateIndicators(maxhp)
  if not maxhp or maxhp <=0 then return end
  
  vedges = maxhp + 1 -- Defines the amount of vertical 1px borders there will be.  Defined as maximum holy power + 1
  local iwidth = floor((fwidth - vedges) / maxhp) -- Attempt to use the frame width to dictate the width of each indicator.  May need to floor/ciel/tweak
  local iheight = fheight - 2 -- Attempt to use the frame height to dictate the height of each indicator.  Should need no tweaking

  for i=1,maxhp do
    if not f.indicators[i] then
      local ind = f:CreateTexture(nil, "OVERLAY")
      ind:SetTexture(itex)
      -- Just anchor each indicator relative to the previous one, instead of doing math.
      if i == 1 then
        ind:SetPoint("LEFT", f, 1, 0)
      else
        ind:SetPoint("LEFT", f.indicators[i-1], "RIGHT", 1, 0)
      end
      ind:SetWidth(iwidth)
      ind:SetHeight(iheight)
      ind:SetVertexColor(ir, ig, ib)
      f.indicators[i] = ind
      f.indicators[i]:Hide()
    end
  end
  
end

function f.PLAYER_LOGIN()
  -- set these values here instead of at runtime
  maxhp = UnitPowerMax("player", SPELL_POWER_HOLY_POWER)

  f:SetFrameStrata("BACKGROUND")
  f:SetPoint("CENTER",fposx,fposy)
  f:SetWidth(fwidth)
  f:SetHeight(fheight)
  if hwe then f:Hide() end

  -- Create Background Frame --
  local bk = f:CreateTexture(nil, "BACKGROUND")
  bk:SetTexture(bkr, bkg, bkb, bka)
  bk:SetAllPoints(true)
  f.background = bk

  f.indicators = {}
  f.CreateIndicators(maxhp)

  f:UnregisterEvent("PLAYER_LOGIN")
  -- only register UNIT_POWER|MAXPOWER for the player unit
  f:RegisterUnitEvent("UNIT_POWER", "player")
  f:RegisterUnitEvent("UNIT_MAXPOWER", "player")
end

function f.UNIT_POWER(...)
  local _, powerType = ...
  if powerType ~= "HOLY_POWER" then
  -- Don't waste time updating if holy power didn't change.
    return
  end

  local p = UnitPower("player", SPELL_POWER_HOLY_POWER)
  if p then
    for i = 1, #f.indicators do
      if i > p then
        f.indicators[i]:Hide()
      else
        f.indicators[i]:Show()
      end
    end
    if p > 0 then
      f:Show()
    else
      if hwe then f:Hide() end
    end
  end
  
end

function f.UNIT_MAXPOWER(...)
  local _, powerType = ...
  if powerType ~= "HOLY_POWER" then
    return
  end
  
  local maxhp = UnitPowerMax("player", SPELL_POWER_HOLY_POWER)
  f.CreateIndicators(maxhp)
end
Ignore my previous post I hadn't read through it all.

Edit: And grrr.. another in-place edit, didn't notice the event functions were called with : notation.
(f:EVENT(...) means the first parameter is the frame itself, f.EVENT(...) means the first parameter is the event's arg1, the way I did the OnEvent function the . notation is the correct one since I'm only passing the event arguments - the self[event](...) part)

Last edited by Dridzt : 09-24-12 at 12:12 AM.
  Reply With Quote
09-23-12, 11:37 PM   #14
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Dridzt, I tired your revised code, the background and all 5 indicators are present, at all times, and that does not change.

I was able to use your indicator SetPoint function where Phanx's did not work, to successfully replace my math heavy function. Thanks much for that!

Edit for your edit: I tried that code, works fairly well. When logging in or reloading the UI, the background and all 5 indicators are present, but as soon as UNIT_POWER fires, it works flawlessly!

Last edited by Clamsoda : 09-23-12 at 11:40 PM.
  Reply With Quote
09-23-12, 11:44 PM   #15
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,360
Try the last revision, I just added a
f.indicators[i]:Hide()
in the CreateIndicators() function so they start out hidden by default and visibility is controlled by UNIT_POWER as it should.

You can do f:Hide() in your PLAYER_LOGIN as well to hide the background at the beginning if you want that as well.

Last edited by Dridzt : 09-23-12 at 11:46 PM.
  Reply With Quote
09-23-12, 11:52 PM   #16
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Well, that is what I am working on right now. Your code is working great, but I want to use the Hide When Empty(hwe) variable to allow the player to hide, or not hide the background when holy power is empty.

I am trying to integrate that logic into your code, with little success.
  Reply With Quote
09-23-12, 11:59 PM   #17
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,360
I changed it a little again, try that one.

Btw, the whole thing can be written in less lines of code and in a sense simplified, but I thought better keep it relatively verbose and simple before diving into metatables and such (and I'm assuming Phanx opted for verbosity for the same reason) since it's meant to be a learning experience.

Last edited by Dridzt : 09-24-12 at 12:02 AM.
  Reply With Quote
09-24-12, 12:02 AM   #18
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
It doesn't like what you changed at all haha. It is funny, looking at your code, I made the EXACT same implementations for HWE's logic, and got the same failed result:

It works perfectly when hwe is set to true, but when it it set to false, it add's HP and doesn't remove it. Perhaps we need to update the indicators, so they hide and not the background?

I tried forcing f.indicators:Hide(), but they aren't going away!

Last edited by Clamsoda : 09-24-12 at 12:05 AM.
  Reply With Quote
09-24-12, 12:12 AM   #19
Dridzt
A Pyroguard Emberseer
 
Dridzt's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2005
Posts: 1,360
How about edit 'I ve lost count' ?
  Reply With Quote
09-24-12, 12:16 AM   #20
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Hahaha, it works great Dridzt.

I can't thank you, Phanx, SDPhantom, and Seerah enough for helping me.

You guys have made my foray into addon making such a fun one. I apologize that I wasn't able to produce any solutions to the problems in your code, Dridzt - but I appreciate you sticking around to see it through =].

I am open to any information, suggestions, potential improvements to the code, it is all a learning experience!
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Help with my addon


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