diff --git a/IceCastBar.lua b/IceCastBar.lua index 4ea7e1f..6ac5eda 100644 --- a/IceCastBar.lua +++ b/IceCastBar.lua @@ -3,7 +3,7 @@ IceCastBar = IceCore_CreateClass(IceBarElement) local IceHUD = _G.IceHUD -IceCastBar.Actions = { None = 0, Cast = 1, Channel = 2, Instant = 3, Success = 4, Failure = 5 } +IceCastBar.Actions = { None = 0, Cast = 1, Channel = 2, Instant = 3, Success = 4, Failure = 5, ReverseChannel = 6 } IceCastBar.prototype.action = nil IceCastBar.prototype.actionStartTime = nil @@ -49,6 +49,13 @@ function IceCastBar.prototype:init(name) self:SetDefaultColor("CastChanneling", 242, 242, 10) self:SetDefaultColor("CastSuccess", 242, 242, 70) self:SetDefaultColor("CastFail", 1, 0, 0) + if GetUnitEmpowerMinHoldTime then + self:SetDefaultColor("EmpowerStage0", 165, 165, 165) + self:SetDefaultColor("EmpowerStage1", 242, 42, 10) + self:SetDefaultColor("EmpowerStage2", 242, 142, 10) + self:SetDefaultColor("EmpowerStage3", 242, 242, 10) + self:SetDefaultColor("EmpowerStage4", 242, 242, 242) + end self.unit = "player" self.delay = 0 @@ -109,6 +116,12 @@ function IceCastBar.prototype:Enable(core) self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE", "SpellCastChannelUpdate") -- unit, spell, rank self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP", "SpellCastChannelStop") -- unit, spell, rank + if GetUnitEmpowerHoldAtMaxTime then + self:RegisterEvent("UNIT_SPELLCAST_EMPOWER_START", "SpellCastChannelStart") + self:RegisterEvent("UNIT_SPELLCAST_EMPOWER_UPDATE", "SpellCastChannelUpdate") + self:RegisterEvent("UNIT_SPELLCAST_EMPOWER_STOP", "SpellCastChannelStop") + end + end self:Show(false) end @@ -311,7 +324,13 @@ function IceCastBar.prototype:PositionIcons() self.barFrame.icon:SetHeight(AuraIconHeight * self.moduleSettings.auraIconScale) end +function IceCastBar.prototype:GetRemainingCastTime() + return self.actionStartTime + self.actionDuration - GetTime() +end +function IceCastBar.prototype:GetCurrentCastDurationMs() + return (GetTime() - (self.actionStartTime or GetTime())) * 1000 +end -- OnUpdate handler function IceCastBar.prototype:MyOnUpdate() @@ -322,17 +341,15 @@ function IceCastBar.prototype:MyOnUpdate() return end - local time = GetTime() - self:Update() self:SetTextAlpha() -- handle casting and channeling - if (self.action == IceCastBar.Actions.Cast or self.action == IceCastBar.Actions.Channel) then - local remainingTime = self.actionStartTime + self.actionDuration - time + if (self.action == IceCastBar.Actions.Cast or self.action == IceCastBar.Actions.Channel or self.action == IceCastBar.Actions.ReverseChannel) then + local remainingTime = self:GetRemainingCastTime() local scale = 1 - (self.actionDuration ~= 0 and remainingTime / self.actionDuration or 0) - if (self.moduleSettings.reverseChannel and self.action == IceCastBar.Actions.Channel) then + if self.action == IceCastBar.Actions.ReverseChannel then scale = self.actionDuration ~= 0 and remainingTime / self.actionDuration or 0 end @@ -343,14 +360,22 @@ function IceCastBar.prototype:MyOnUpdate() end local timeString = self.moduleSettings.showCastTime and string.format("%.1fs ", remainingTime) or "" - self:SetBottomText1(timeString .. self.actionMessage) + local empowerString = self.NumStages ~= nil and (L["Stage %d"]):format(self:GetCurrentStage()) or "" + local line1 = timeString .. self.actionMessage + if self.moduleSettings.empowerStageTextDisplay == "TOPLINE" then + line1 = line1 .. " " .. empowerString + end + if self.moduleSettings.empowerStageTextDisplay == "BOTTOMLINE" then + self:SetBottomText2(empowerString) + end + self:SetBottomText1(line1) return end -- stop bar if casting or channeling is done (in theory this should not be needed) - if (self.action == IceCastBar.Actions.Cast or self.action == IceCastBar.Actions.Channel) then + if (self.action == IceCastBar.Actions.Cast or self.action == IceCastBar.Actions.Channel or self.action == IceCastBar.Actions.ReverseChannel) then self:StopBar() return end @@ -361,7 +386,7 @@ function IceCastBar.prototype:MyOnUpdate() self.action == IceCastBar.Actions.Success or self.action == IceCastBar.Actions.Failure) then - local scale = time - self.actionStartTime + local scale = GetTime() - self.actionStartTime if (scale > 1) then self:StopBar() @@ -381,12 +406,60 @@ function IceCastBar.prototype:MyOnUpdate() self:StopBar() end -function IceCastBar.prototype:GetCurrentCastingColor() - local updateColor = "CastCasting" - if self.action == IceCastBar.Actions.Channel then - updateColor = "CastChanneling" +function IceCastBar.prototype:GetStageDuration(stage) + if not GetUnitEmpowerMinHoldTime then + return 0 end - return updateColor + + if stage == 0 then + return GetUnitEmpowerMinHoldTime(self.unit) + end + + return GetUnitEmpowerStageDuration(self.unit, stage); +end + +function IceCastBar.prototype:GetDurationUpToStage(stage) + if stage == nil or stage < 0 then + return 0 + end + + local total = 0 + for i=0,stage-1 do + total = total + self:GetStageDuration(i) + end + + return total +end + +function IceCastBar.prototype:GetCurrentStage() + if not GetUnitEmpowerMinHoldTime then + return 0 + end + + local castDuration = self:GetCurrentCastDurationMs() + for i=1,self.NumStages do + if castDuration < self:GetDurationUpToStage(i) then + return i - 1 + end + end + + return self.NumStages +end + +function IceCastBar.prototype:IsCastingEmpowerSpell() + return self.NumStages ~= nil +end + +function IceCastBar.prototype:GetCurrentCastingColor() + if self:IsCastingEmpowerSpell() then + return ("EmpowerStage%d"):format(self:GetCurrentStage()) + end + + if self.action == IceCastBar.Actions.Channel or self.action == IceCastBar.Actions.ReverseChannel then + return "CastChanneling" + end + + return "CastCasting" end function IceCastBar.prototype:FlashBar(color, alpha, text, textColor) @@ -406,7 +479,7 @@ end function IceCastBar.prototype:StartBar(action, message) - local spell, rank, displayName, icon, startTime, endTime, isTradeSkill + local spell, rank, displayName, icon, startTime, endTime, isTradeSkill, numStages if IceHUD.SpellFunctionsReturnRank then spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitCastingInfo(self.unit) else @@ -416,7 +489,24 @@ function IceCastBar.prototype:StartBar(action, message) if IceHUD.SpellFunctionsReturnRank then spell, rank, displayName, icon, startTime, endTime = UnitChannelInfo(self.unit) else - spell, displayName, icon, startTime, endTime = UnitChannelInfo(self.unit) + spell, displayName, icon, startTime, endTime, isTradeSkill, _, _, _, numStages = UnitChannelInfo(self.unit) + end + end + + local isChargeSpell = numStages and numStages > 0 + if isChargeSpell then + self.NumStages = numStages + endTime = endTime + GetUnitEmpowerHoldAtMaxTime(self.unit) + action = IceCastBar.Actions.ReverseChannel + else + self.NumStages = nil + end + + if self.moduleSettings.reverseChannel then + if action == IceCastBar.Actions.Channel then + action = IceCastBar.Actions.ReverseChannel + elseif action == IceCastBar.Actions.ReverseChannel then + action = IceCastBar.Actions.Channel end end @@ -465,6 +555,7 @@ function IceCastBar.prototype:StopBar() self.actionDuration = nil self:SetBottomText1() + self:SetBottomText2() self:SetScale(0) self:Show(false) end @@ -514,7 +605,8 @@ function IceCastBar.prototype:SpellCastStop(event, unit, castGuid, spellId) if (self.action ~= IceCastBar.Actions.Success and self.action ~= IceCastBar.Actions.Failure and - self.action ~= IceCastBar.Actions.Channel) + self.action ~= IceCastBar.Actions.Channel and + self.action ~= IceCastBar.Actions.ReverseChannel) then self:StopBar() self.current = nil @@ -532,7 +624,7 @@ function IceCastBar.prototype:SpellCastFailed(event, unit, castGuid, spellId) end -- channeled spells will call ChannelStop, not cast failed - if self.action == IceCastBar.Actions.Channel then + if self.action == IceCastBar.Actions.Channel or self.action == IceCastBar.Actions.ReverseChannel then return end @@ -582,7 +674,7 @@ function IceCastBar.prototype:SpellCastSucceeded(event, unit, castGuid, spellId) --IceHUD:Debug("SpellCastSucceeded", unit, castGuid, spellId) -- never show on channeled (why on earth does this event even fire when channeling starts?) - if (self.action == IceCastBar.Actions.Channel) then + if (self.action == IceCastBar.Actions.Channel or self.action == IceCastBar.Actions.ReverseChannel) then return end diff --git a/IceHUD.toc b/IceHUD.toc index e881379..f9b8d5e 100644 --- a/IceHUD.toc +++ b/IceHUD.toc @@ -99,6 +99,7 @@ modules\Stagger.lua modules\PlayerAltMana.lua modules\ArcaneCharges.lua modules\RollTheBones.lua +modules\EssencePower.lua #@do-not-package@ IceHUD_Options\Json.lua diff --git a/changelog.md b/changelog.md index d3e4182..480f8c4 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,8 @@ v1.14.3: - Add Spell ID support for aura tracking. +- Add Evoker support. +- Add Empowered Casting (hold-to-cast levels) support. v1.14.2: diff --git a/modules/CastBar.lua b/modules/CastBar.lua index d230623..26ba9c4 100644 --- a/modules/CastBar.lua +++ b/modules/CastBar.lua @@ -39,6 +39,9 @@ function CastBar.prototype:GetDefaultSettings() settings["rangeColor"] = true settings["bAllowExpand"] = false settings["respectLagTolerance"] = true + settings["lockUpperTextAlpha"] = true + settings["lockLowerTextAlpha"] = true + settings["empowerStageTextDisplay"] = "TOPLINE" return settings end @@ -236,6 +239,7 @@ function CastBar.prototype:GetOptions() end, set = function(info, v) self.moduleSettings.lockUpperTextAlpha = v + self.moduleSettings.lockLowerTextAlpha = v self:Redraw() end, order = 13 @@ -308,7 +312,26 @@ function CastBar.prototype:GetOptions() disabled = function() return not self.moduleSettings.enabled end, - } + }, + + empowerStageText = { + type = 'select', + name = L["Empower stage label display"], + desc = L["How to display the stage of an empowered spell"], + get = function() + return self.moduleSettings.empowerStageTextDisplay + end, + set = function(info, value) + self.moduleSettings.empowerStageTextDisplay = value + end, + values = { NONE = L["Don't show"], TOPLINE = L["After spell name"], BOTTOMLINE = L["Below spell name"] }, + disabled = function() + return not self.moduleSettings.enabled + end, + hidden = function() + return not GetUnitEmpowerMinHoldTime + end, + }, } } diff --git a/modules/ClassPowerCounter.lua b/modules/ClassPowerCounter.lua index a3a33e6..aeda176 100644 --- a/modules/ClassPowerCounter.lua +++ b/modules/ClassPowerCounter.lua @@ -462,10 +462,14 @@ function IceClassPowerCounter.prototype:CheckValidSpec() end end +function IceClassPowerCounter.prototype:GetPowerEvent() + return IceHUD.UnitPowerEvent +end + function IceClassPowerCounter.prototype:DisplayCounter() self:UnregisterEvent("PLAYER_LEVEL_UP") - self:RegisterEvent(IceHUD.UnitPowerEvent, "UpdateRunePower") + self:RegisterEvent(self:GetPowerEvent(), "UpdateRunePower") self:RegisterEvent("UNIT_DISPLAYPOWER", "UpdateRunePower") self:RegisterEvent("PLAYER_ENTERING_WORLD", "EnteringWorld") if IceHUD.EventExistsUnitMaxPower then @@ -493,7 +497,7 @@ function IceClassPowerCounter.prototype:EnteringWorld() end function IceClassPowerCounter.prototype:UpdateRunePower(event, arg1, arg2) - if event and (event == IceHUD.UnitPowerEvent or event == "UNIT_POWER_FREQUENT") and arg1 ~= "player" and arg1 ~= "vehicle" then + if event and (event == self:GetPowerEvent() or event == "UNIT_POWER_FREQUENT") and arg1 ~= "player" and arg1 ~= "vehicle" then return end diff --git a/modules/EssencePower.lua b/modules/EssencePower.lua new file mode 100644 index 0000000..6c8863a --- /dev/null +++ b/modules/EssencePower.lua @@ -0,0 +1,74 @@ +local L = LibStub("AceLocale-3.0"):GetLocale("IceHUD", false) +local EssencePower = IceCore_CreateClass(IceClassPowerCounter) + +local SPELL_POWER_ESSENCE = SPELL_POWER_ESSENCE +if Enum and Enum.PowerType then + SPELL_POWER_ESSENCE = Enum.PowerType.Essence +end + +function EssencePower.prototype:init() + EssencePower.super.prototype.init(self, "EssencePower") + + self:SetDefaultColor("EssencePowerNumeric", 150, 150, 255) + + self.unit = "player" + self.numericColor = "EssencePowerNumeric" + self.unitPower = SPELL_POWER_ESSENCE + self.minLevel = 0 + self.bTreatEmptyAsFull = false + self.runeWidth = self.runeHeight +end + +function EssencePower.prototype:Enable(core) + self.numRunes = UnitPowerMax(self.unit, SPELL_POWER_ESSENCE) + self.runeCoords = { } + for i = 1, self.numRunes do + self:SetupNewRune(i) + end + + EssencePower.super.prototype.Enable(self, core) +end + +function EssencePower.prototype:SetupNewRune(rune) + self.runeCoords[rune] = {0, 1, 0, 1} +end + +function EssencePower.prototype:GetPowerEvent() + return "UNIT_POWER_FREQUENT" +end + +function EssencePower.prototype:GetDefaultSettings() + local defaults = EssencePower.super.prototype.GetDefaultSettings(self) + + defaults["pulseWhenFull"] = false + + return defaults +end + +function EssencePower.prototype:GetOptions() + local opts = EssencePower.super.prototype.GetOptions(self) + + opts.hideBlizz.hidden = function() return true end + + return opts +end + +function EssencePower.prototype:GetRuneAtlas(rune) + return "UF-Essence-Icon" +end + +function EssencePower.prototype:GetShineAtlas(rune) + return "Mage-ArcaneCharge-SmallSpark" +end + +function EssencePower.prototype:ShowBlizz() +end + +function EssencePower.prototype:HideBlizz() +end + +-- Load us up +local _, unitClass = UnitClass("player") +if unitClass == "EVOKER" then + IceHUD.EssencePower = EssencePower:new() +end diff --git a/this_version.md b/this_version.md index 6395e60..59f4b4c 100644 --- a/this_version.md +++ b/this_version.md @@ -3,6 +3,8 @@ v1.14.3: - Add Spell ID support for aura tracking. +- Add Evoker support. +- Add Empowered Casting (hold-to-cast levels) support. v1.14.2: