Thread Tools Display Modes
02-19-14, 05:32 AM   #1
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Misc issues with an addon

Hi, so i've had this little addon issuing a sound for each combo point and then another sound to warn me when i reached 5 (some people use bars on their screen for that, i prefer sounds) but then i decided i wanted to level a paladin and thought, why not make this work for each classes that this kind of "points".

So i came up with this:

Code:
local _, caelUI = ...

caelUI.powersound = caelUI.createModule("PowerSound")

local num, numMax, power, spec

local powers = {
	["MONK"]		=	"CHI",
	["PALADIN"]	=	"HOLY_POWER",
	["PRIEST"]	=	"SHADOW_ORBS",
	["WARLOCK"] = {
		[1]		=	"SOUL_SHARDS",
		[2]		=	"DEMONIC_FURY",
		[3]		=	"BURNING_EMBERS",
	}
}

caelUI.powersound:SetScript("OnEvent", function(self, event, unit, powerType)
	if unit ~= "player" then return end

	if event == "UNIT_COMBO_POINTS" then
		num = GetComboPoints("player", "target")
		numMax = MAX_COMBO_POINTS

		if num ~= 0 and num ~= numMax then
			PlaySoundFile(caelMedia.files.soundCombo, "Master")
		elseif num == numMax then
			PlaySoundFile(caelMedia.files.soundComboMax, "Master")
		end
	end

	if event == "UNIT_POWER" then
		spec = GetSpecialization()

		if powerType ~= powers[caelUI.playerClass] and powerType ~= powers[caelUI.playerClass][spec] then return end

		if caelUI.playerClass == "MONK" then
			num = UnitPower("player", SPELL_POWER_CHI)
			numMax = UnitPowerMax("player", SPELL_POWER_CHI)
		elseif caelUI.playerClass == "PALADIN" then
			num = UnitPower("player", SPELL_POWER_HOLY_POWER)
			numMax = UnitPowerMax("player", SPELL_POWER_HOLY_POWER)
		elseif caelUI.playerClass == "PRIEST" then
			num = UnitPower("player", SPELL_POWER_SHADOW_ORBS)
			numMax = PRIEST_BAR_NUM_ORBS -- UnitPowerMax("player", SPELL_POWER_SHADOW_ORBS)
--[[
		elseif caelUI.playerClass == "WARLOCK" then
			if spec then
				if spec == SPEC_WARLOCK_AFFLICTION then
					num = UnitPower("player", SPELL_POWER_SOUL_SHARDS)
					numMax = UnitPowerMax("player", SPELL_POWER_SOUL_SHARDS)
				elseif spec == SPEC_WARLOCK_DEMONOLOGY then
					num = UnitPower("player", SPELL_POWER_DEMONIC_FURY)
					numMax = UnitPowerMax("player", SPELL_POWER_DEMONIC_FURY)
				elseif spec == SPEC_WARLOCK_DESTRUCTION then
					num = UnitPower("player", SPELL_POWER_BURNING_EMBERS)
					numMax = UnitPowerMax("player", SPELL_POWER_BURNING_EMBERS)
				end
			end
--]]
		end

		if num ~= 0 and num ~= numMax then
			PlaySoundFile(caelMedia.files.soundCombo, "Master")
		elseif num == numMax then
			PlaySoundFile(caelMedia.files.soundComboMax, "Master")
		end
	end
end)

for _, event in next, {
	"UNIT_COMBO_POINTS",
	"UNIT_POWER",
} do
	caelUI.powersound:RegisterEvent(event)
end
Obviously, for combo points it works perfectly, but for other classes not so much.

The issues (that i need help with) are the following:

Paladin: Over time, the Holy power decreases and the problem is that each time i loose one point, it beeps, it shouldn't.
Warlock: This one is the worst, different power source for each spec, the power does decrease over time, burning embers seems to beep for every spell i cast, not just when i gain one ember, in fewer words, warlocks are a mess.

Anyone would have any idea how i could improve this little addon ?
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
02-19-14, 06:14 AM   #2
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
For paladin, compare the new amount of combo points to the previous amount. Only beep if the new amount is greater.
  Reply With Quote
02-19-14, 07:36 AM   #3
Oppugno
A Fallenroot Satyr
Join Date: Sep 2012
Posts: 22
As Haleth suggested the same can be done for warlocks with a slight adjustment. The only difference being that Warlock resources (possibly with the exception of Soul Shards) are generated fractionally. It takes 10 Ember Bits to fill a Burning Ember and 1000 Demonic Fury to fill the bar (I've no idea about Soul Shards as I've never played Affliction).

Dividing by 10 on Burning Ember power will tell you how many Burning Embers you have. I don't know how you'd want to handle Demonic Fury as that's not really a combo point system (perhaps every 250?).

Although you asked for improvements I'm not sure you meant efficiency/superfluous code issues. There are a few but they could just be individual to me.. e.g. using RegisterEvent() instead of RegisterUnitEvent(), registering events for classes that don't need them, UnitMaxPower() variants on each UNIT_POWER even though most of them are constant (and those that aren't fire an event for it), etc.

Last edited by Oppugno : 02-19-14 at 08:54 AM. Reason: I meant divide not modulus..
  Reply With Quote
02-19-14, 07:47 AM   #4
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
Originally Posted by Oppugno View Post
As Haleth suggested the same can be done for warlocks with a slight adjustment. The only difference being that Warlock resources (possibly with the exception of Soul Shards) are generated fractionally. It takes 10 Ember Bits to fill a Burning Ember and 1000 Demonic Fury to fill the bar (I've no idea about Soul Shards as I've never played Affliction).

Using a modulus of 10 on Burning Ember power will tell you how many Burning Embers you have. I don't know how you'd want to handle Demonic Fury as that's not really a combo point system (perhaps every 250?).
I know all that, the issue is to write it, or else i wouldn't ask here
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
02-19-14, 08:50 AM   #5
Oppugno
A Fallenroot Satyr
Join Date: Sep 2012
Posts: 22
I didn't realise you wanted a solution and not a hint (which is a good thing as I meant divide by 10 not modulo by it).

With changing as little as possible:

Lua Code:
  1. local numPrevious = 0
  2.  
  3. caelUI.powersound:SetScript("OnEvent", function(self, event, unit, powerType)
  4.     ...
  5.     if event == "UNIT_POWER" then
  6.         ...
  7.         elseif caelUI.playerClass == "WARLOCK" then
  8.             if spec then
  9.                 if spec == SPEC_WARLOCK_AFFLICTION then
  10.                     num = UnitPower("player", SPELL_POWER_SOUL_SHARDS)
  11.                     numMax = UnitPowerMax("player", SPELL_POWER_SOUL_SHARDS)
  12.                 elseif spec == SPEC_WARLOCK_DEMONOLOGY then
  13.                     num = math.floor(UnitPower("player", SPELL_POWER_DEMONIC_FURY) / 250)
  14.                     numMax = UnitPowerMax("player", SPELL_POWER_DEMONIC_FURY) / 250
  15.                 elseif spec == SPEC_WARLOCK_DESTRUCTION then
  16.                     num = UnitPower("player", SPELL_POWER_BURNING_EMBERS)
  17.                     numMax = UnitPowerMax("player", SPELL_POWER_BURNING_EMBERS)
  18.                 end        
  19.             end
  20.         end
  21.  
  22.         if num > numPrevious then
  23.             if num ~= 0 and num ~= numMax then
  24.                 PlaySoundFile(caelMedia.files.soundCombo, "Master")
  25.             elseif num == numMax then
  26.                 PlaySoundFile(caelMedia.files.soundComboMax, "Master")
  27.             end
  28.         end
  29.         numPrevious = num
  30.     end
  31. end

Last edited by Oppugno : 02-19-14 at 09:20 AM. Reason: UnitPower("player", SPELL_POWER_BURNING_EMBERS) returns full embers not partials.
  Reply With Quote
02-19-14, 08:55 AM   #6
Caellian
A Frostmaul Preserver
 
Caellian's Avatar
Join Date: May 2006
Posts: 281
There we go, i wasn't resetting "numPrevious"...

Now let's try.
__________________
if (sizeof(workload) > sizeof(brain_capacity)) { die('System Overload'); }
  Reply With Quote
02-19-14, 09:19 AM   #7
Oppugno
A Fallenroot Satyr
Join Date: Sep 2012
Posts: 22
It seems UnitPower("player", SPELL_POWER_BURNING_EMBERS) returns a count of only full embers not total ember bits. Updated code.
  Reply With Quote
02-19-14, 09:26 AM   #8
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
In the interests of reducing code duplication, and reducing the number of function calls and global lookups (checking the class and spec on every power update is quite wasteful) I would rewrite that like so:

Lua Code:
  1. caelUI.powersound = caelUI.createModule("PowerSound")
  2.  
  3. -- Use RegisterUnitEvent, not RegisterEvent, to filter out irrelevant events.
  4. caelUI.powersound:RegisterUnitEvent("UNIT_COMBO_POINTS", "player")
  5. caelUI.powersound:RegisterUnitEvent("UNIT_POWER", "player")
  6.  
  7. -- Look these things up once at load; they're not going to change mid-session.
  8. local POWER_TYPE, POWER_DIVISOR
  9. if caelUI.playerClass == "MONK" then
  10.     POWER_TYPE = "CHI"
  11. elseif caelUI.playerClass == "PALADIN" then
  12.     POWER_TYPE = "HOLY_POWER"
  13. elseif caelUI.playerClass == "PRIEST" then
  14.     POWER_TYPE = "SHADOW_ORBS"
  15.     MAX_POWER = PRIEST_BAR_NUM_ORBS
  16. elseif caelUI.playerClass == "WARLOCK" then
  17.     -- Only register these events on a class that needs it.
  18.     caelUI.powersound:RegisterEvent("PLAYER_LOGIN")
  19.     caelUI.powersound:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
  20. end
  21.  
  22. local lastCount = 0
  23. caelUI.powersound:SetScript("OnEvent", function(self, event, unit, powerType)
  24.     -- This will quickly get out of irrelevant power updates, which are the most frequent case.
  25.     if event == "UNIT_POWER" and powerType ~= POWER_TYPE then return end
  26.  
  27.     -- This is the least frequent case, but the other events share code, so check for this one first.
  28.     if event == "PLAYER_SPECIALIZATION_CHANGED" then
  29.         local spec = GetSpecialization()
  30.         if spec == SPEC_WARLOCK_AFFLICTION then
  31.             POWER_TYPE = "SOUL_SHARDS"
  32.             POWER_DIVISOR = 1
  33.         elseif spec == SPEC_WARLOCK_DEMONOLOGY then
  34.             POWER_TYPE = "DEMONIC_FURY"
  35.             POWER_DIVISOR = 250
  36.         elseif spec == SPEC_WARLOCK_DESTRUCTION then
  37.             POWER_TYPE = "BURNING_EMBERS"
  38.             POWER_DIVISOR = 10
  39.         end
  40.         return
  41.     end
  42.  
  43.     local count, maxCount
  44.     if event == "UNIT_COMBO_POINTS" then
  45.         count = UnitComboPoints("player", "target")
  46.         maxCount = MAX_COMBO_POINTS
  47.     elseif POWER_DIVISOR then
  48.         -- Only use this code path for warlocks to avoid the 2 function calls if they're not needed.
  49.         count = floor(UnitPower(unit, powerType) / POWER_DIVISOR)
  50.         maxCount = MAX_POWER or floor(UnitPowerMax(unit, powerType) / POWER_DIVISOR)
  51.     else
  52.         count = UnitPower(unit, powerType)
  53.         maxCount = MAX_POWER or UnitPowerMax(unit, powerType)
  54.     end
  55.  
  56.     if count > lastCount then
  57.         -- count can't be < 0, so neither can lastCount, and 0 is not > 0, so no need to check count > 0
  58.         if count == maxCount then
  59.             -- Check this first so you can just "else" straight into the other thing.
  60.             PlaySoundFile(caelMedia.files.soundComboMax, "Master")
  61.         else
  62.             PlaySoundFile(caelMedia.files.soundCombo, "Master")
  63.         end
  64.     end
  65.  
  66.     lastCount = count
  67. end)

Also you may want to upvalue UnitPower, UnitPowerMax, and math.floor to speed things up.
__________________
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.

Last edited by Phanx : 02-19-14 at 03:37 PM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Misc issues with an 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