diff --git a/IceCastBar.lua b/IceCastBar.lua index e210b2c..ec70c34 100644 --- a/IceCastBar.lua +++ b/IceCastBar.lua @@ -1,573 +1,573 @@ -local L = LibStub("AceLocale-3.0"):GetLocale("IceHUD", false) -IceCastBar = IceCore_CreateClass(IceBarElement) - -local IceHUD = _G.IceHUD - -IceCastBar.Actions = { None = 0, Cast = 1, Channel = 2, Instant = 3, Success = 4, Failure = 5 } - -IceCastBar.prototype.action = nil -IceCastBar.prototype.actionStartTime = nil -IceCastBar.prototype.actionDuration = nil -IceCastBar.prototype.actionMessage = nil -IceCastBar.prototype.unit = nil -IceCastBar.prototype.current = nil - -local AuraIconWidth = 20 -local AuraIconHeight = 20 - --- Constructor -- -function IceCastBar.prototype:init(name) - IceCastBar.super.prototype.init(self, name) - - self:SetDefaultColor("CastCasting", 242, 242, 10) - self:SetDefaultColor("CastChanneling", 242, 242, 10) - self:SetDefaultColor("CastSuccess", 242, 242, 70) - self:SetDefaultColor("CastFail", 1, 0, 0) - self.unit = "player" - - self.delay = 0 - self.action = IceCastBar.Actions.None -end - - --- 'Public' methods ----------------------------------------------------------- - -function IceCastBar.prototype:Enable(core) - IceCastBar.super.prototype.Enable(self, core) - - self:RegisterEvent("UNIT_SPELLCAST_SENT", "SpellCastSent") -- "player", spell, rank, target - self:RegisterEvent("CURRENT_SPELL_CAST_CHANGED", "SpellCastChanged") - self:RegisterEvent("UNIT_SPELLCAST_START", "SpellCastStart") -- unit, spell, rank - self:RegisterEvent("UNIT_SPELLCAST_STOP", "SpellCastStop") -- unit, spell, rank - - self:RegisterEvent("UNIT_SPELLCAST_FAILED", "SpellCastFailed") -- unit, spell, rank - self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED", "SpellCastInterrupted") -- unit, spell, rank - - self:RegisterEvent("UNIT_SPELLCAST_DELAYED", "SpellCastDelayed") -- unit, spell, rank - self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED", "SpellCastSucceeded") -- "player", spell, rank - - self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START", "SpellCastChannelStart") -- unit, spell, rank - self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE", "SpellCastChannelUpdate") -- unit, spell, rank - self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP", "SpellCastChannelStop") -- unit, spell, rank - - self:Show(false) -end - -function IceCastBar.prototype:GetDefaultSettings() - local settings = IceCastBar.super.prototype.GetDefaultSettings(self) - - settings["showSpellRank"] = true - settings["showCastTime"] = true - settings["displayAuraIcon"] = false - settings["auraIconXOffset"] = 40 - settings["auraIconYOffset"] = 0 - settings["auraIconScale"] = 1 - settings["reverseChannel"] = true - - return settings -end - -function IceCastBar.prototype:GetOptions() - local opts = IceCastBar.super.prototype.GetOptions(self) - - opts["showCastTime"] = - { - type = 'toggle', - name = L["Show spell cast time"], - desc = L["Whether or not to show the remaining cast time of a spell being cast."], - get = function() - return self.moduleSettings.showCastTime - end, - set = function(info, value) - self.moduleSettings.showCastTime = value - end, - disabled = function() - return not self.moduleSettings.enabled - end, - order = 39.998 - } - - opts["showSpellRank"] = - { - type = 'toggle', - name = L["Show spell rank"], - desc = L["Whether or not to show the rank of a spell being cast."], - get = function() - return self.moduleSettings.showSpellRank - end, - set = function(info, value) - self.moduleSettings.showSpellRank = value - end, - disabled = function() - return not self.moduleSettings.enabled - end, - order = 39.999 - } - - opts["iconSettings"] = { - type = 'group', - name = "|c"..self.configColor..L["Icon Settings"].."|r", - args = { - displayAuraIcon = { - type = 'toggle', - name = L["Display aura icon"], - desc = L["Whether or not to display an icon for the aura that this bar is tracking"], - get = function() - return self.moduleSettings.displayAuraIcon - end, - set = function(info, v) - self.moduleSettings.displayAuraIcon = v - if self.barFrame.icon then - if v then - self.barFrame.icon:Show() - else - self.barFrame.icon:Hide() - end - end - end, - disabled = function() - return not self.moduleSettings.enabled - end, - order = 51, - }, - - auraIconXOffset = { - type = 'range', - min = -250, - max = 250, - step = 1, - name = L["Aura icon horizontal offset"], - desc = L["Adjust the horizontal position of the aura icon"], - get = function() - return self.moduleSettings.auraIconXOffset - end, - set = function(info, v) - self.moduleSettings.auraIconXOffset = v - self:PositionIcons() - end, - disabled = function() - return not self.moduleSettings.enabled or not self.moduleSettings.displayAuraIcon - end, - order = 52, - }, - - auraIconYOffset = { - type = 'range', - min = -250, - max = 250, - step = 1, - name = L["Aura icon vertical offset"], - desc = L["Adjust the vertical position of the aura icon"], - get = function() - return self.moduleSettings.auraIconYOffset - end, - set = function(info, v) - self.moduleSettings.auraIconYOffset = v - self:PositionIcons() - end, - disabled = function() - return not self.moduleSettings.enabled or not self.moduleSettings.displayAuraIcon - end, - order = 53, - }, - - auraIconScale = { - type = 'range', - min = 0.1, - max = 3.0, - step = 0.05, - name = L["Aura icon scale"], - desc = L["Adjusts the size of the aura icon for this bar"], - get = function() - return self.moduleSettings.auraIconScale - end, - set = function(info, v) - self.moduleSettings.auraIconScale = v - self:PositionIcons() - end, - disabled = function() - return not self.moduleSettings.enabled or not self.moduleSettings.displayAuraIcon - end, - order = 54, - }, - }, - } - - opts["reverseChannel"] = { - type = 'toggle', - name = L["Reverse channeling"], - desc = L["Whether or not to reverse the direction of the cast bar when a spell is being channeled. For example, if a normal cast causes this bar to fill up, then checking this option will cause a channeled spell to empty the bar instead."], - get = function() - return self.moduleSettings.reverseChannel - end, - set = function(info, v) - self.moduleSettings.reverseChannel = v - end, - disabled = function() - return not self.moduleSettings.enabled - end, - order = 32.5, - } - - return opts -end - -function IceCastBar.prototype:IsFull(scale) - local retval = IceCastBar.super.prototype.IsFull(self, scale) - if retval then - if self.action and self.action ~= IceCastBar.Actions.None then - return false - end - end - return retval -end - --- 'Protected' methods -------------------------------------------------------- - --- OVERRIDE -function IceCastBar.prototype:CreateFrame() - IceCastBar.super.prototype.CreateFrame(self) - - self.frame.bottomUpperText:SetWidth(self.settings.gap + 30) - - if not self.barFrame.icon then - self.barFrame.icon = self.masterFrame:CreateTexture(nil, "OVERLAY") - -- default texture so that 'config mode' can work without activating the bar first - self.barFrame.icon:SetTexture("Interface\\Icons\\Spell_Frost_Frost") - -- this cuts off the border around the buff icon - self.barFrame.icon:SetTexCoord(0.1, 0.9, 0.1, 0.9) - end - self:PositionIcons() -end - -function IceCastBar.prototype:PositionIcons() - if not self.barFrame or not self.barFrame.icon then - return - end - - self.barFrame.icon:ClearAllPoints() - self.barFrame.icon:SetPoint("TOPLEFT", self.frame, "TOPLEFT", self.moduleSettings.auraIconXOffset, self.moduleSettings.auraIconYOffset) - self.barFrame.icon:SetWidth(AuraIconWidth * self.moduleSettings.auraIconScale) - self.barFrame.icon:SetHeight(AuraIconHeight * self.moduleSettings.auraIconScale) -end - - - --- OnUpdate handler -function IceCastBar.prototype:MyOnUpdate() - -- safety catch - if (self.action == IceCastBar.Actions.None) then - --IceHUD:Debug("Stopping action ", self.action) - self:StopBar() - 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 - local scale = 1 - (self.actionDuration ~= 0 and remainingTime / self.actionDuration or 0) - - if (self.moduleSettings.reverseChannel and self.action == IceCastBar.Actions.Channel) then - scale = self.actionDuration ~= 0 and remainingTime / self.actionDuration or 0 - end - - self:UpdateBar(IceHUD:Clamp(scale, 0, 1), self:GetCurrentCastingColor()) - - if (remainingTime <= 0) then - self:StopBar() - end - - local timeString = self.moduleSettings.showCastTime and string.format("%.1fs ", remainingTime) or "" - self:SetBottomText1(timeString .. self.actionMessage) - - 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 - self:StopBar() - return - end - - - -- handle bar flashes - if (self.action == IceCastBar.Actions.Instant or - self.action == IceCastBar.Actions.Success or - self.action == IceCastBar.Actions.Failure) - then - local scale = time - self.actionStartTime - - if (scale > 1) then - self:StopBar() - return - end - - if (self.action == IceCastBar.Actions.Failure) then - self:FlashBar("CastFail", 1-scale, self.actionMessage, "CastFail") - else - self:FlashBar("CastSuccess", 1-scale, self.actionMessage) - end - return - end - - -- something went wrong - IceHUD:Debug("OnUpdate error ", self.action, " -- ", self.actionStartTime, self.actionDuration, self.actionMessage) - self:StopBar() -end - -function IceCastBar.prototype:GetCurrentCastingColor() - local updateColor = "CastCasting" - if self.action == IceCastBar.Actions.Channel then - updateColor = "CastChanneling" - end - return updateColor -end - -function IceCastBar.prototype:FlashBar(color, alpha, text, textColor) - self.frame:SetAlpha(alpha) - - local r, g, b = self.settings.backgroundColor.r, self.settings.backgroundColor.g, self.settings.backgroundColor.b - if (self.settings.backgroundToggle) then - r, g, b = self:GetColor(color) - end - - self.frame.bg:SetVertexColor(r, g, b, 0.3) - self.barFrame.bar:SetVertexColor(self:GetColor(color, 0.8)) - - self:SetScale(1) - self:SetBottomText1(text, textColor or "Text") -end - - -function IceCastBar.prototype:StartBar(action, message) - local spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitCastingInfo(self.unit) - if not (spell) then - spell, rank, displayName, icon, startTime, endTime = UnitChannelInfo(self.unit) - end - - if not spell then - return - end - - if icon ~= nil then - self.barFrame.icon:SetTexture(icon) - end - - if IceHUD.IceCore:IsInConfigMode() or self.moduleSettings.displayAuraIcon then - self.barFrame.icon:Show() - else - self.barFrame.icon:Hide() - end - - self.action = action - self.actionStartTime = GetTime() - self.actionMessage = message - - if (startTime and endTime) then - self.actionDuration = (endTime - startTime) / 1000 - - -- set start time here in case we start to monitor a cast that is underway already - self.actionStartTime = startTime / 1000 - else - self.actionDuration = 1 -- instants/failures - end - - if not (message) then - self.actionMessage = spell .. (self.moduleSettings.showSpellRank and self:GetShortRank(rank) or "") - end - - self:Show(true) - self:ConditionalSetupUpdate() -end - - -function IceCastBar.prototype:StopBar() - self.action = IceCastBar.Actions.None - self.actionStartTime = nil - self.actionDuration = nil - - self:SetBottomText1() - self:SetScale(0) - self:Show(false) -end - -function IceCastBar.prototype:GetShortRank(rank) - if (rank) then - local _, _, sRank = string.find(rank, "(%d+)") - if (sRank) then - return " (" .. sRank .. ")" - end - end - return "" -end - - - -------------------------------------------------------------------------------- --- NORMAL SPELLS -- -------------------------------------------------------------------------------- - -function IceCastBar.prototype:SpellCastSent(event, unit, spell, rank, target) - if (unit ~= self.unit) then return end - IceHUD:Debug("SpellCastSent", unit, spell, rank, target) -end - -function IceCastBar.prototype:SpellCastChanged(event, arg1) - IceHUD:Debug("SpellCastChanged", arg1) -end - -function IceCastBar.prototype:SpellCastStart(event, unit, spell, rank) - if (unit ~= self.unit) then return end - IceHUD:Debug("SpellCastStart", unit, spell, rank) - --UnitCastingInfo(unit) - - self:StartBar(IceCastBar.Actions.Cast) - self.current = spell -end - -function IceCastBar.prototype:SpellCastStop(event, unit, spell, rank) - if (unit ~= self.unit) then return end - IceHUD:Debug("SpellCastStop", unit, spell, self.current) - - -- ignore if not coming from current spell - if (self.current and spell and self.current ~= spell) then - return - end - - if (self.action ~= IceCastBar.Actions.Success and - self.action ~= IceCastBar.Actions.Failure and - self.action ~= IceCastBar.Actions.Channel) - then - self:StopBar() - self.current = nil - end -end - - -function IceCastBar.prototype:SpellCastFailed(event, unit, spell, rank) - if (unit ~= self.unit) then return end - IceHUD:Debug("SpellCastFailed", unit, self.current) - - -- ignore if not coming from current spell - if (self.current and spell and self.current ~= spell) then - return - end - - -- channeled spells will call ChannelStop, not cast failed - if self.action == IceCastBar.Actions.Channel then - return - end - - self.current = nil - - -- determine if we want to show failed casts - if (self.moduleSettings.flashFailures == "Never") then - return - elseif (self.moduleSettings.flashFailures == "Caster") then - if (UnitPowerType("player") ~= SPELL_POWER_MANA) then - return - end - end - - self:StartBar(IceCastBar.Actions.Failure, "Failed") -end - -function IceCastBar.prototype:SpellCastInterrupted(event, unit, spell, rank) - if (unit ~= self.unit) then return end - IceHUD:Debug("SpellCastInterrupted", unit, self.current) - - -- ignore if not coming from current spell - if (self.current and spell and self.current ~= spell) then - return - end - - self.current = nil - - self:StartBar(IceCastBar.Actions.Failure, "Interrupted") -end - -function IceCastBar.prototype:SpellCastDelayed(event, unit, delay) - if (unit ~= self.unit) then return end - --IceHUD:Debug("SpellCastDelayed", unit, UnitCastingInfo(unit)) - - local spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitCastingInfo(self.unit) - - if (endTime and self.actionStartTime) then - -- apparently this check is needed, got nils during a horrible lag spike - self.actionDuration = endTime/1000 - self.actionStartTime - end -end - - -function IceCastBar.prototype:SpellCastSucceeded(event, unit, spell, rank) - if (unit ~= self.unit) then return end - --IceHUD:Debug("SpellCastSucceeded", unit, spell, rank) - - -- never show on channeled (why on earth does this event even fire when channeling starts?) - if (self.action == IceCastBar.Actions.Channel) then - return - end - - -- ignore if not coming from current spell - if (self.current and self.current ~= spell) then - return - end - - -- show after normal successfull cast - if (self.action == IceCastBar.Actions.Cast) then - self:StartBar(IceCastBar.Actions.Success, spell.. self:GetShortRank(rank)) - return - end - - -- determine if we want to show instant casts - if (self.moduleSettings.flashInstants == "Never") then - return - elseif (self.moduleSettings.flashInstants == "Caster") then - if (UnitPowerType("player") ~= SPELL_POWER_MANA) then - return - end - end - - self:StartBar(IceCastBar.Actions.Success, spell.. self:GetShortRank(rank)) -end - - - -------------------------------------------------------------------------------- --- CHANNELING SPELLS -- -------------------------------------------------------------------------------- - -function IceCastBar.prototype:SpellCastChannelStart(event, unit) - if (unit ~= self.unit) then return end - --IceHUD:Debug("SpellCastChannelStart", unit) - - self:StartBar(IceCastBar.Actions.Channel) -end - -function IceCastBar.prototype:SpellCastChannelUpdate(event, unit) - if (unit ~= self.unit or not self.actionStartTime) then return end - --IceHUD:Debug("SpellCastChannelUpdate", unit, UnitChannelInfo(unit)) - - local spell, rank, displayName, icon, startTime, endTime = UnitChannelInfo(unit) - if not spell then - self.actionDuration = 0 - else - self.actionDuration = endTime/1000 - self.actionStartTime - end -end - -function IceCastBar.prototype:SpellCastChannelStop(event, unit) - if (unit ~= self.unit) then return end - --IceHUD:Debug("SpellCastChannelStop", unit) - - self:StopBar() -end - - - +local L = LibStub("AceLocale-3.0"):GetLocale("IceHUD", false) +IceCastBar = IceCore_CreateClass(IceBarElement) + +local IceHUD = _G.IceHUD + +IceCastBar.Actions = { None = 0, Cast = 1, Channel = 2, Instant = 3, Success = 4, Failure = 5 } + +IceCastBar.prototype.action = nil +IceCastBar.prototype.actionStartTime = nil +IceCastBar.prototype.actionDuration = nil +IceCastBar.prototype.actionMessage = nil +IceCastBar.prototype.unit = nil +IceCastBar.prototype.current = nil + +local AuraIconWidth = 20 +local AuraIconHeight = 20 + +-- Constructor -- +function IceCastBar.prototype:init(name) + IceCastBar.super.prototype.init(self, name) + + self:SetDefaultColor("CastCasting", 242, 242, 10) + self:SetDefaultColor("CastChanneling", 242, 242, 10) + self:SetDefaultColor("CastSuccess", 242, 242, 70) + self:SetDefaultColor("CastFail", 1, 0, 0) + self.unit = "player" + + self.delay = 0 + self.action = IceCastBar.Actions.None +end + + +-- 'Public' methods ----------------------------------------------------------- + +function IceCastBar.prototype:Enable(core) + IceCastBar.super.prototype.Enable(self, core) + + self:RegisterEvent("UNIT_SPELLCAST_SENT", "SpellCastSent") -- "player", spell, rank, target + self:RegisterEvent("CURRENT_SPELL_CAST_CHANGED", "SpellCastChanged") + self:RegisterEvent("UNIT_SPELLCAST_START", "SpellCastStart") -- unit, spell, rank + self:RegisterEvent("UNIT_SPELLCAST_STOP", "SpellCastStop") -- unit, spell, rank + + self:RegisterEvent("UNIT_SPELLCAST_FAILED", "SpellCastFailed") -- unit, spell, rank + self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED", "SpellCastInterrupted") -- unit, spell, rank + + self:RegisterEvent("UNIT_SPELLCAST_DELAYED", "SpellCastDelayed") -- unit, spell, rank + self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED", "SpellCastSucceeded") -- "player", spell, rank + + self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START", "SpellCastChannelStart") -- unit, spell, rank + self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE", "SpellCastChannelUpdate") -- unit, spell, rank + self:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP", "SpellCastChannelStop") -- unit, spell, rank + + self:Show(false) +end + +function IceCastBar.prototype:GetDefaultSettings() + local settings = IceCastBar.super.prototype.GetDefaultSettings(self) + + settings["showSpellRank"] = true + settings["showCastTime"] = true + settings["displayAuraIcon"] = false + settings["auraIconXOffset"] = 40 + settings["auraIconYOffset"] = 0 + settings["auraIconScale"] = 1 + settings["reverseChannel"] = true + + return settings +end + +function IceCastBar.prototype:GetOptions() + local opts = IceCastBar.super.prototype.GetOptions(self) + + opts["showCastTime"] = + { + type = 'toggle', + name = L["Show spell cast time"], + desc = L["Whether or not to show the remaining cast time of a spell being cast."], + get = function() + return self.moduleSettings.showCastTime + end, + set = function(info, value) + self.moduleSettings.showCastTime = value + end, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 39.998 + } + + opts["showSpellRank"] = + { + type = 'toggle', + name = L["Show spell rank"], + desc = L["Whether or not to show the rank of a spell being cast."], + get = function() + return self.moduleSettings.showSpellRank + end, + set = function(info, value) + self.moduleSettings.showSpellRank = value + end, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 39.999 + } + + opts["iconSettings"] = { + type = 'group', + name = "|c"..self.configColor..L["Icon Settings"].."|r", + args = { + displayAuraIcon = { + type = 'toggle', + name = L["Display aura icon"], + desc = L["Whether or not to display an icon for the aura that this bar is tracking"], + get = function() + return self.moduleSettings.displayAuraIcon + end, + set = function(info, v) + self.moduleSettings.displayAuraIcon = v + if self.barFrame.icon then + if v then + self.barFrame.icon:Show() + else + self.barFrame.icon:Hide() + end + end + end, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 51, + }, + + auraIconXOffset = { + type = 'range', + min = -250, + max = 250, + step = 1, + name = L["Aura icon horizontal offset"], + desc = L["Adjust the horizontal position of the aura icon"], + get = function() + return self.moduleSettings.auraIconXOffset + end, + set = function(info, v) + self.moduleSettings.auraIconXOffset = v + self:PositionIcons() + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.displayAuraIcon + end, + order = 52, + }, + + auraIconYOffset = { + type = 'range', + min = -250, + max = 250, + step = 1, + name = L["Aura icon vertical offset"], + desc = L["Adjust the vertical position of the aura icon"], + get = function() + return self.moduleSettings.auraIconYOffset + end, + set = function(info, v) + self.moduleSettings.auraIconYOffset = v + self:PositionIcons() + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.displayAuraIcon + end, + order = 53, + }, + + auraIconScale = { + type = 'range', + min = 0.1, + max = 3.0, + step = 0.05, + name = L["Aura icon scale"], + desc = L["Adjusts the size of the aura icon for this bar"], + get = function() + return self.moduleSettings.auraIconScale + end, + set = function(info, v) + self.moduleSettings.auraIconScale = v + self:PositionIcons() + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.displayAuraIcon + end, + order = 54, + }, + }, + } + + opts["reverseChannel"] = { + type = 'toggle', + name = L["Reverse channeling"], + desc = L["Whether or not to reverse the direction of the cast bar when a spell is being channeled. For example, if a normal cast causes this bar to fill up, then checking this option will cause a channeled spell to empty the bar instead."], + get = function() + return self.moduleSettings.reverseChannel + end, + set = function(info, v) + self.moduleSettings.reverseChannel = v + end, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 32.5, + } + + return opts +end + +function IceCastBar.prototype:IsFull(scale) + local retval = IceCastBar.super.prototype.IsFull(self, scale) + if retval then + if self.action and self.action ~= IceCastBar.Actions.None then + return false + end + end + return retval +end + +-- 'Protected' methods -------------------------------------------------------- + +-- OVERRIDE +function IceCastBar.prototype:CreateFrame() + IceCastBar.super.prototype.CreateFrame(self) + + self.frame.bottomUpperText:SetWidth(self.settings.gap + 30) + + if not self.barFrame.icon then + self.barFrame.icon = self.masterFrame:CreateTexture(nil, "OVERLAY") + -- default texture so that 'config mode' can work without activating the bar first + self.barFrame.icon:SetTexture("Interface\\Icons\\Spell_Frost_Frost") + -- this cuts off the border around the buff icon + self.barFrame.icon:SetTexCoord(0.1, 0.9, 0.1, 0.9) + end + self:PositionIcons() +end + +function IceCastBar.prototype:PositionIcons() + if not self.barFrame or not self.barFrame.icon then + return + end + + self.barFrame.icon:ClearAllPoints() + self.barFrame.icon:SetPoint("TOPLEFT", self.frame, "TOPLEFT", self.moduleSettings.auraIconXOffset, self.moduleSettings.auraIconYOffset) + self.barFrame.icon:SetWidth(AuraIconWidth * self.moduleSettings.auraIconScale) + self.barFrame.icon:SetHeight(AuraIconHeight * self.moduleSettings.auraIconScale) +end + + + +-- OnUpdate handler +function IceCastBar.prototype:MyOnUpdate() + -- safety catch + if (self.action == IceCastBar.Actions.None) then + --IceHUD:Debug("Stopping action ", self.action) + self:StopBar() + 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 + local scale = 1 - (self.actionDuration ~= 0 and remainingTime / self.actionDuration or 0) + + if (self.moduleSettings.reverseChannel and self.action == IceCastBar.Actions.Channel) then + scale = self.actionDuration ~= 0 and remainingTime / self.actionDuration or 0 + end + + self:UpdateBar(IceHUD:Clamp(scale, 0, 1), self:GetCurrentCastingColor()) + + if (remainingTime <= 0) then + self:StopBar() + end + + local timeString = self.moduleSettings.showCastTime and string.format("%.1fs ", remainingTime) or "" + self:SetBottomText1(timeString .. self.actionMessage) + + 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 + self:StopBar() + return + end + + + -- handle bar flashes + if (self.action == IceCastBar.Actions.Instant or + self.action == IceCastBar.Actions.Success or + self.action == IceCastBar.Actions.Failure) + then + local scale = time - self.actionStartTime + + if (scale > 1) then + self:StopBar() + return + end + + if (self.action == IceCastBar.Actions.Failure) then + self:FlashBar("CastFail", 1-scale, self.actionMessage, "CastFail") + else + self:FlashBar("CastSuccess", 1-scale, self.actionMessage) + end + return + end + + -- something went wrong + IceHUD:Debug("OnUpdate error ", self.action, " -- ", self.actionStartTime, self.actionDuration, self.actionMessage) + self:StopBar() +end + +function IceCastBar.prototype:GetCurrentCastingColor() + local updateColor = "CastCasting" + if self.action == IceCastBar.Actions.Channel then + updateColor = "CastChanneling" + end + return updateColor +end + +function IceCastBar.prototype:FlashBar(color, alpha, text, textColor) + self.frame:SetAlpha(alpha) + + local r, g, b = self.settings.backgroundColor.r, self.settings.backgroundColor.g, self.settings.backgroundColor.b + if (self.settings.backgroundToggle) then + r, g, b = self:GetColor(color) + end + + self.frame.bg:SetVertexColor(r, g, b, 0.3) + self.barFrame.bar:SetVertexColor(self:GetColor(color, 0.8)) + + self:SetScale(1) + self:SetBottomText1(text, textColor or "Text") +end + + +function IceCastBar.prototype:StartBar(action, message) + local spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitCastingInfo(self.unit) + if not (spell) then + spell, rank, displayName, icon, startTime, endTime = UnitChannelInfo(self.unit) + end + + if not spell then + return + end + + if icon ~= nil then + self.barFrame.icon:SetTexture(icon) + end + + if IceHUD.IceCore:IsInConfigMode() or self.moduleSettings.displayAuraIcon then + self.barFrame.icon:Show() + else + self.barFrame.icon:Hide() + end + + self.action = action + self.actionStartTime = GetTime() + self.actionMessage = message + + if (startTime and endTime) then + self.actionDuration = (endTime - startTime) / 1000 + + -- set start time here in case we start to monitor a cast that is underway already + self.actionStartTime = startTime / 1000 + else + self.actionDuration = 1 -- instants/failures + end + + if not (message) then + self.actionMessage = spell .. (self.moduleSettings.showSpellRank and self:GetShortRank(rank) or "") + end + + self:Show(true) + self:ConditionalSetupUpdate() +end + + +function IceCastBar.prototype:StopBar() + self.action = IceCastBar.Actions.None + self.actionStartTime = nil + self.actionDuration = nil + + self:SetBottomText1() + self:SetScale(0) + self:Show(false) +end + +function IceCastBar.prototype:GetShortRank(rank) + if (rank) then + local _, _, sRank = string.find(rank, "(%d+)") + if (sRank) then + return " (" .. sRank .. ")" + end + end + return "" +end + + + +------------------------------------------------------------------------------- +-- NORMAL SPELLS -- +------------------------------------------------------------------------------- + +function IceCastBar.prototype:SpellCastSent(event, unit, spell, rank, target, lineId) + if (unit ~= self.unit) then return end + IceHUD:Debug("SpellCastSent", unit, spell, rank, target, lineId) +end + +function IceCastBar.prototype:SpellCastChanged(event, arg1) + IceHUD:Debug("SpellCastChanged", arg1) +end + +function IceCastBar.prototype:SpellCastStart(event, unit, spell, rank, lineId, spellId) + if (unit ~= self.unit) then return end + IceHUD:Debug("SpellCastStart", unit, spell, rank, lineId, spellId) + --UnitCastingInfo(unit) + + self:StartBar(IceCastBar.Actions.Cast) + self.current = lineId +end + +function IceCastBar.prototype:SpellCastStop(event, unit, spell, rank, lineId, spellId) + if (unit ~= self.unit) then return end + IceHUD:Debug("SpellCastStop", unit, spell, self.current, rank, lineId, spellId) + + -- ignore if not coming from current spell + if (self.current and lineId and self.current ~= lineId) then + return + end + + if (self.action ~= IceCastBar.Actions.Success and + self.action ~= IceCastBar.Actions.Failure and + self.action ~= IceCastBar.Actions.Channel) + then + self:StopBar() + self.current = nil + end +end + + +function IceCastBar.prototype:SpellCastFailed(event, unit, spell, rank, lineId, spellId) + if (unit ~= self.unit) then return end + IceHUD:Debug("SpellCastFailed", unit, self.current, lineId, spellId) + + -- ignore if not coming from current spell + if (self.current and lineId and self.current ~= lineId) then + return + end + + -- channeled spells will call ChannelStop, not cast failed + if self.action == IceCastBar.Actions.Channel then + return + end + + self.current = nil + + -- determine if we want to show failed casts + if (self.moduleSettings.flashFailures == "Never") then + return + elseif (self.moduleSettings.flashFailures == "Caster") then + if (UnitPowerType("player") ~= SPELL_POWER_MANA) then + return + end + end + + self:StartBar(IceCastBar.Actions.Failure, "Failed") +end + +function IceCastBar.prototype:SpellCastInterrupted(event, unit, spell, rank, lineId, spellId) + if (unit ~= self.unit) then return end + IceHUD:Debug("SpellCastInterrupted", unit, self.current, lineId, spellId) + + -- ignore if not coming from current spell + if (self.current and lineId and self.current ~= lineId) then + return + end + + self.current = nil + + self:StartBar(IceCastBar.Actions.Failure, "Interrupted") +end + +function IceCastBar.prototype:SpellCastDelayed(event, unit, delay) + if (unit ~= self.unit) then return end + --IceHUD:Debug("SpellCastDelayed", unit, UnitCastingInfo(unit)) + + local spell, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitCastingInfo(self.unit) + + if (endTime and self.actionStartTime) then + -- apparently this check is needed, got nils during a horrible lag spike + self.actionDuration = endTime/1000 - self.actionStartTime + end +end + + +function IceCastBar.prototype:SpellCastSucceeded(event, unit, spell, rank, lineId, spellId) + if (unit ~= self.unit) then return end + --IceHUD:Debug("SpellCastSucceeded", unit, spell, rank) + + -- never show on channeled (why on earth does this event even fire when channeling starts?) + if (self.action == IceCastBar.Actions.Channel) then + return + end + + -- ignore if not coming from current spell + if (self.current and self.current ~= lineId) then + return + end + + -- show after normal successfull cast + if (self.action == IceCastBar.Actions.Cast) then + self:StartBar(IceCastBar.Actions.Success, spell.. self:GetShortRank(rank)) + return + end + + -- determine if we want to show instant casts + if (self.moduleSettings.flashInstants == "Never") then + return + elseif (self.moduleSettings.flashInstants == "Caster") then + if (UnitPowerType("player") ~= SPELL_POWER_MANA) then + return + end + end + + self:StartBar(IceCastBar.Actions.Success, spell.. self:GetShortRank(rank)) +end + + + +------------------------------------------------------------------------------- +-- CHANNELING SPELLS -- +------------------------------------------------------------------------------- + +function IceCastBar.prototype:SpellCastChannelStart(event, unit) + if (unit ~= self.unit) then return end + --IceHUD:Debug("SpellCastChannelStart", unit) + + self:StartBar(IceCastBar.Actions.Channel) +end + +function IceCastBar.prototype:SpellCastChannelUpdate(event, unit) + if (unit ~= self.unit or not self.actionStartTime) then return end + --IceHUD:Debug("SpellCastChannelUpdate", unit, UnitChannelInfo(unit)) + + local spell, rank, displayName, icon, startTime, endTime = UnitChannelInfo(unit) + if not spell then + self.actionDuration = 0 + else + self.actionDuration = endTime/1000 - self.actionStartTime + end +end + +function IceCastBar.prototype:SpellCastChannelStop(event, unit) + if (unit ~= self.unit) then return end + --IceHUD:Debug("SpellCastChannelStop", unit) + + self:StopBar() +end + + + diff --git a/modules/CastBar.lua b/modules/CastBar.lua index 3708cf0..ed0deb1 100644 --- a/modules/CastBar.lua +++ b/modules/CastBar.lua @@ -1,506 +1,506 @@ -local L = LibStub("AceLocale-3.0"):GetLocale("IceHUD", false) -local CastBar = IceCore_CreateClass(IceCastBar) - -local IceHUD = _G.IceHUD - -CastBar.prototype.spellCastSent = nil -CastBar.prototype.sentSpell = nil - --- Constructor -- -function CastBar.prototype:init() - CastBar.super.prototype.init(self, "CastBar") - - self:SetDefaultColor("CastLag", 255, 0, 0) - self:SetDefaultColor("CastNotInRange", 200, 200, 200) - - self.unit = "player" -end - - --- 'Public' methods ----------------------------------------------------------- - --- OVERRIDE -function CastBar.prototype:GetDefaultSettings() - local settings = CastBar.super.prototype.GetDefaultSettings(self) - - settings["side"] = IceCore.Side.Left - settings["offset"] = 0 - settings["flashInstants"] = "Caster" - settings["flashFailures"] = "Caster" - settings["lagAlpha"] = 0.7 - settings["showBlizzCast"] = false - settings["shouldAnimate"] = false - settings["hideAnimationSettings"] = true - settings["usesDogTagStrings"] = false - settings["rangeColor"] = true - settings["bAllowExpand"] = false - settings["respectLagTolerance"] = true - - return settings -end - - --- OVERRIDE -function CastBar.prototype:GetOptions() - local opts = CastBar.super.prototype.GetOptions(self) - - opts["flashInstants"] = - { - type = 'select', - name = L["Flash Instant Spells"], - desc = L["Defines when cast bar should flash on instant spells"], - get = function(info) - return IceHUD:GetSelectValue(info, self.moduleSettings.flashInstants) - end, - set = function(info, value) - self.moduleSettings.flashInstants = info.option.values[value] - end, - values = { "Always", "Caster", "Never" }, - disabled = function() - return not self.moduleSettings.enabled - end, - order = 40 - } - - opts["flashFailures"] = - { - type = 'select', - name = L["Flash on Spell Failures"], - desc = L["Defines when cast bar should flash on failed spells"], - get = function(info) - return IceHUD:GetSelectValue(info, self.moduleSettings.flashFailures) - end, - set = function(info, value) - self.moduleSettings.flashFailures = info.option.values[value] - end, - disabled = function() - return not self.moduleSettings.enabled - end, - values = { "Always", "Caster", "Never" }, - order = 41 - } - - opts["lagAlpha"] = - { - type = 'range', - name = L["Lag Indicator alpha"], - desc = L["Lag indicator alpha (0 is disabled)"], - min = 0, - max = 1, - step = 0.1, - get = function() - return self.moduleSettings.lagAlpha - end, - set = function(info, value) - self.moduleSettings.lagAlpha = value - self:Redraw() - end, - disabled = function() - return not self.moduleSettings.enabled - end, - order = 42 - } - - opts["showBlizzCast"] = - { - type = 'toggle', - name = L["Show default cast bar"], - desc = L["Whether or not to show the default cast bar."], - get = function() - return self.moduleSettings.showBlizzCast - end, - set = function(info, value) - self.moduleSettings.showBlizzCast = value - self:ToggleBlizzCast(self.moduleSettings.showBlizzCast) - end, - disabled = function() - return not self.moduleSettings.enabled - end, - order = 43 - } - - opts["respectLagTolerance"] = - { - type = 'toggle', - name = L["Respect lag tolerance"], - desc = L["When checked, if a 'Custom Lag Tolerance' is set in the game's Combat options, the lag indicator will always use that tolerance value. Otherwise, it uses the computed latency."], - get = function() - return self.moduleSettings.respectLagTolerance - end, - set = function(info, value) - self.moduleSettings.respectLagTolerance = value - self:CVarUpdate() - end, - disabled = function() - return not self.moduleSettings.enabled or GetCVar("reducedLagTolerance") == "0" - end, - order = 42.1, - } - - opts["barVisible"] = { - type = 'toggle', - name = L["Bar visible"], - desc = L["Toggle bar visibility"], - get = function() - return self.moduleSettings.barVisible['bar'] - end, - set = function(info, v) - self.moduleSettings.barVisible['bar'] = v - if v then - self.barFrame:Show() - else - self.barFrame:Hide() - end - end, - disabled = function() - return not self.moduleSettings.enabled - end, - order = 28 - } - - opts["bgVisible"] = { - type = 'toggle', - name = L["Bar background visible"], - desc = L["Toggle bar background visibility"], - get = function() - return self.moduleSettings.barVisible['bg'] - end, - set = function(info, v) - self.moduleSettings.barVisible['bg'] = v - if v then - self.frame.bg:Show() - else - self.frame.bg:Hide() - end - end, - disabled = function() - return not self.moduleSettings.enabled - end, - order = 29 - } - - opts["rangeColor"] = { - type = 'toggle', - name = L["Change color when not in range"], - desc = L["Changes the bar color to the CastNotInRange color when the target goes out of range for the current spell."], - width = 'double', - get = function() - return self.moduleSettings.rangeColor - end, - set = function(info, v) - self.moduleSettings.rangeColor = v - end, - disabled = function() - return not self.moduleSettings.enabled - end, - order = 30 - } - - opts["textSettings"] = - { - type = 'group', - name = "|c"..self.configColor..L["Text Settings"].."|r", - desc = L["Settings related to texts"], - order = 32, - disabled = function() - return not self.moduleSettings.enabled - end, - args = { - fontsize = { - type = 'range', - name = L["Bar Font Size"], - desc = L["Bar Font Size"], - get = function() - return self.moduleSettings.barFontSize - end, - set = function(info, v) - self.moduleSettings.barFontSize = v - self:Redraw() - end, - min = 8, - max = 20, - step = 1, - order = 11 - }, - - lockFontAlpha = { - type = "toggle", - name = L["Lock Bar Text Alpha"], - desc = L["Locks text alpha to 100%"], - get = function() - return self.moduleSettings.lockUpperTextAlpha - end, - set = function(info, v) - self.moduleSettings.lockUpperTextAlpha = v - self:Redraw() - end, - order = 13 - }, - - upperTextVisible = { - type = 'toggle', - name = L["Spell cast text visible"], - desc = L["Toggle spell cast text visibility"], - get = function() - return self.moduleSettings.textVisible['upper'] - end, - set = function(info, v) - self.moduleSettings.textVisible['upper'] = v - self:Redraw() - end, - order = 14 - }, - - textVerticalOffset = { - type = 'range', - name = L["Text Vertical Offset"], - desc = L["Offset of the text from the bar vertically (negative is farther below)"], - min = -250, - max = 350, - step = 1, - get = function() - return self.moduleSettings.textVerticalOffset - end, - set = function(info, v) - self.moduleSettings.textVerticalOffset = v - self:Redraw() - end, - disabled = function() - return not self.moduleSettings.enabled - end - }, - - textHorizontalOffset = { - type = 'range', - name = L["Text Horizontal Offset"], - desc = L["Offset of the text from the bar horizontally"], - min = -350, - max = 350, - step = 1, - get = function() - return self.moduleSettings.textHorizontalOffset - end, - set = function(info, v) - self.moduleSettings.textHorizontalOffset = v - self:Redraw() - end, - disabled = function() - return not self.moduleSettings.enabled - end - }, - - forceJustifyText = { - type = 'select', - name = L["Force Text Justification"], - desc = L["This sets the alignment for the text on this bar"], - get = function() - return self.moduleSettings.forceJustifyText - end, - set = function(info, value) - self.moduleSettings.forceJustifyText = value - self:Redraw() - end, - values = { NONE = "None", LEFT = "Left", RIGHT = "Right" }, - disabled = function() - return not self.moduleSettings.enabled - end, - } - } - } - - return opts -end - -function CastBar.prototype:Enable(core) - CastBar.super.prototype.Enable(self, core) - - self:RegisterEvent("UNIT_ENTERED_VEHICLE", "EnteringVehicle") - self:RegisterEvent("UNIT_EXITED_VEHICLE", "ExitingVehicle") - self:RegisterEvent("PLAYER_ENTERING_WORLD", "CheckVehicle") - - self:RegisterEvent("CVAR_UPDATE", "CVarUpdate") - - self:CVarUpdate() - - if self.moduleSettings.enabled and not self.moduleSettings.showBlizzCast then - self:ToggleBlizzCast(false) - end - - if self.moduleSettings.shouldAnimate then - self.moduleSettings.shouldAnimate = false - end -end - - -function CastBar.prototype:EnteringVehicle(event, unit, arg2) - if (self.unit == "player" and IceHUD:ShouldSwapToVehicle(unit, arg2)) then - self.unit = "vehicle" - self:Update(self.unit) - end -end - - -function CastBar.prototype:ExitingVehicle(event, unit) - if (unit == "player" and self.unit == "vehicle") then - self.unit = "player" - self:Update(self.unit) - end -end - - -function CastBar.prototype:CheckVehicle() - if UnitHasVehicleUI("player") then - self:EnteringVehicle(nil, "player", true) - else - self:ExitingVehicle(nil, "player") - end -end - -function CastBar.prototype:CVarUpdate(...) - self.useFixedLatency = self.moduleSettings.respectLagTolerance and GetCVar("reducedLagTolerance") == "1" - self.fixedLatency = tonumber(GetCVar("maxSpellStartRecoveryoffset")) / 1000 -end - -function CastBar.prototype:Disable(core) - CastBar.super.prototype.Disable(self, core) - - if self.moduleSettings.showBlizzCast then - self:ToggleBlizzCast(true) - end -end - -function CastBar.prototype:ToggleBlizzCast(on) - if on then - -- restore blizz cast bar - CastingBarFrame:GetScript("OnLoad")(CastingBarFrame) - PetCastingBarFrame:GetScript("OnLoad")(PetCastingBarFrame) - else - -- remove blizz cast bar - CastingBarFrame:UnregisterAllEvents() - PetCastingBarFrame:UnregisterAllEvents() - end -end - - --- OVERRIDE -function CastBar.prototype:CreateFrame() - CastBar.super.prototype.CreateFrame(self) - - self:CreateLagBar() -end - - -function CastBar.prototype:CreateLagBar() - self.lagBar = self:BarFactory(self.lagBar, "LOW", "OVERLAY") - - local r, g, b = self:GetColor("CastLag") - if (self.settings.backgroundToggle) then - r, g, b = self:GetColor("CastCasting") - end - - self.lagBar.bar:SetVertexColor(r, g, b, self.moduleSettings.lagAlpha) - self.lagBar.bar:Hide() -end - - --- OVERRIDE -function CastBar.prototype:SpellCastSent(event, unit, spell, rank, target) - CastBar.super.prototype.SpellCastSent(self, event, unit, spell, rank, target) - if (unit ~= self.unit) then return end - - if IceHUD.WowVer < 70000 then - self.spellCastSent = GetTime() - end - self.sentSpell = spell -end - --- OVERRIDE -function CastBar.prototype:SpellCastChanged(event, arg1) - CastBar.super.prototype.SpellCastChanged(self, event, arg1) - if IceHUD.WowVer >= 70000 then - self.spellCastSent = GetTime() - end -end - --- OVERRIDE -function CastBar.prototype:SpellCastStart(event, unit, spell, rank) - CastBar.super.prototype.SpellCastStart(self, event, unit, spell, rank) - if (unit ~= self.unit) then return end - - if not self:IsVisible() or not self.actionDuration then - return - end - - if self.sentSpell ~= spell then - self.spellCastSent = nil - end - - local scale - if self.unit == "vehicle" then - scale = 0 - elseif self.useFixedLatency then - scale = IceHUD:Clamp(self.fixedLatency / self.actionDuration, 0, 1) - else - local now = GetTime() - local lag = now - (self.spellCastSent or now) - scale = IceHUD:Clamp(lag / self.actionDuration, 0, 1) - end - - self:SetBarCoord(self.lagBar, scale, true, true) - - self.spellCastSent = nil -end - - --- OVERRIDE -function CastBar.prototype:SpellCastChannelStart(event, unit) - CastBar.super.prototype.SpellCastChannelStart(self, event, unit) - if (unit ~= self.unit) then return end - - if not self:IsVisible() or not self.actionDuration then - return - end - - local scale - if self.unit == "vehicle" then - scale = 0 - elseif self.useFixedLatency then - scale = IceHUD:Clamp(self.fixedLatency / self.actionDuration, 0, 1) - else - local now = GetTime() - local lag = now - (self.spellCastSent or now) - scale = IceHUD:Clamp(lag / self.actionDuration, 0, 1) - end - - local top = not self.moduleSettings.reverseChannel - - self:SetBarCoord(self.lagBar, scale, top, true) - - self.spellCastSent = nil -end - - -function CastBar.prototype:UpdateBar(scale, color, alpha) - local bCheckRange = true - local inRange - - if not self.moduleSettings.rangeColor or not self.current or not self.action or not UnitExists("target") then - bCheckRange = false - else - inRange = IsSpellInRange(self.current, "target") - if inRange == nil then - bCheckRange = false - end - end - - if bCheckRange and inRange == 0 then - color = "CastNotInRange" - end - - CastBar.super.prototype.UpdateBar(self, scale, color, alpha) -end - -------------------------------------------------------------------------------- - --- Load us up -IceHUD.PlayerCast = CastBar:new() +local L = LibStub("AceLocale-3.0"):GetLocale("IceHUD", false) +local CastBar = IceCore_CreateClass(IceCastBar) + +local IceHUD = _G.IceHUD + +CastBar.prototype.spellCastSent = nil +CastBar.prototype.sentSpell = nil + +-- Constructor -- +function CastBar.prototype:init() + CastBar.super.prototype.init(self, "CastBar") + + self:SetDefaultColor("CastLag", 255, 0, 0) + self:SetDefaultColor("CastNotInRange", 200, 200, 200) + + self.unit = "player" +end + + +-- 'Public' methods ----------------------------------------------------------- + +-- OVERRIDE +function CastBar.prototype:GetDefaultSettings() + local settings = CastBar.super.prototype.GetDefaultSettings(self) + + settings["side"] = IceCore.Side.Left + settings["offset"] = 0 + settings["flashInstants"] = "Caster" + settings["flashFailures"] = "Caster" + settings["lagAlpha"] = 0.7 + settings["showBlizzCast"] = false + settings["shouldAnimate"] = false + settings["hideAnimationSettings"] = true + settings["usesDogTagStrings"] = false + settings["rangeColor"] = true + settings["bAllowExpand"] = false + settings["respectLagTolerance"] = true + + return settings +end + + +-- OVERRIDE +function CastBar.prototype:GetOptions() + local opts = CastBar.super.prototype.GetOptions(self) + + opts["flashInstants"] = + { + type = 'select', + name = L["Flash Instant Spells"], + desc = L["Defines when cast bar should flash on instant spells"], + get = function(info) + return IceHUD:GetSelectValue(info, self.moduleSettings.flashInstants) + end, + set = function(info, value) + self.moduleSettings.flashInstants = info.option.values[value] + end, + values = { "Always", "Caster", "Never" }, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 40 + } + + opts["flashFailures"] = + { + type = 'select', + name = L["Flash on Spell Failures"], + desc = L["Defines when cast bar should flash on failed spells"], + get = function(info) + return IceHUD:GetSelectValue(info, self.moduleSettings.flashFailures) + end, + set = function(info, value) + self.moduleSettings.flashFailures = info.option.values[value] + end, + disabled = function() + return not self.moduleSettings.enabled + end, + values = { "Always", "Caster", "Never" }, + order = 41 + } + + opts["lagAlpha"] = + { + type = 'range', + name = L["Lag Indicator alpha"], + desc = L["Lag indicator alpha (0 is disabled)"], + min = 0, + max = 1, + step = 0.1, + get = function() + return self.moduleSettings.lagAlpha + end, + set = function(info, value) + self.moduleSettings.lagAlpha = value + self:Redraw() + end, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 42 + } + + opts["showBlizzCast"] = + { + type = 'toggle', + name = L["Show default cast bar"], + desc = L["Whether or not to show the default cast bar."], + get = function() + return self.moduleSettings.showBlizzCast + end, + set = function(info, value) + self.moduleSettings.showBlizzCast = value + self:ToggleBlizzCast(self.moduleSettings.showBlizzCast) + end, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 43 + } + + opts["respectLagTolerance"] = + { + type = 'toggle', + name = L["Respect lag tolerance"], + desc = L["When checked, if a 'Custom Lag Tolerance' is set in the game's Combat options, the lag indicator will always use that tolerance value. Otherwise, it uses the computed latency."], + get = function() + return self.moduleSettings.respectLagTolerance + end, + set = function(info, value) + self.moduleSettings.respectLagTolerance = value + self:CVarUpdate() + end, + disabled = function() + return not self.moduleSettings.enabled or GetCVar("reducedLagTolerance") == "0" + end, + order = 42.1, + } + + opts["barVisible"] = { + type = 'toggle', + name = L["Bar visible"], + desc = L["Toggle bar visibility"], + get = function() + return self.moduleSettings.barVisible['bar'] + end, + set = function(info, v) + self.moduleSettings.barVisible['bar'] = v + if v then + self.barFrame:Show() + else + self.barFrame:Hide() + end + end, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 28 + } + + opts["bgVisible"] = { + type = 'toggle', + name = L["Bar background visible"], + desc = L["Toggle bar background visibility"], + get = function() + return self.moduleSettings.barVisible['bg'] + end, + set = function(info, v) + self.moduleSettings.barVisible['bg'] = v + if v then + self.frame.bg:Show() + else + self.frame.bg:Hide() + end + end, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 29 + } + + opts["rangeColor"] = { + type = 'toggle', + name = L["Change color when not in range"], + desc = L["Changes the bar color to the CastNotInRange color when the target goes out of range for the current spell."], + width = 'double', + get = function() + return self.moduleSettings.rangeColor + end, + set = function(info, v) + self.moduleSettings.rangeColor = v + end, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 30 + } + + opts["textSettings"] = + { + type = 'group', + name = "|c"..self.configColor..L["Text Settings"].."|r", + desc = L["Settings related to texts"], + order = 32, + disabled = function() + return not self.moduleSettings.enabled + end, + args = { + fontsize = { + type = 'range', + name = L["Bar Font Size"], + desc = L["Bar Font Size"], + get = function() + return self.moduleSettings.barFontSize + end, + set = function(info, v) + self.moduleSettings.barFontSize = v + self:Redraw() + end, + min = 8, + max = 20, + step = 1, + order = 11 + }, + + lockFontAlpha = { + type = "toggle", + name = L["Lock Bar Text Alpha"], + desc = L["Locks text alpha to 100%"], + get = function() + return self.moduleSettings.lockUpperTextAlpha + end, + set = function(info, v) + self.moduleSettings.lockUpperTextAlpha = v + self:Redraw() + end, + order = 13 + }, + + upperTextVisible = { + type = 'toggle', + name = L["Spell cast text visible"], + desc = L["Toggle spell cast text visibility"], + get = function() + return self.moduleSettings.textVisible['upper'] + end, + set = function(info, v) + self.moduleSettings.textVisible['upper'] = v + self:Redraw() + end, + order = 14 + }, + + textVerticalOffset = { + type = 'range', + name = L["Text Vertical Offset"], + desc = L["Offset of the text from the bar vertically (negative is farther below)"], + min = -250, + max = 350, + step = 1, + get = function() + return self.moduleSettings.textVerticalOffset + end, + set = function(info, v) + self.moduleSettings.textVerticalOffset = v + self:Redraw() + end, + disabled = function() + return not self.moduleSettings.enabled + end + }, + + textHorizontalOffset = { + type = 'range', + name = L["Text Horizontal Offset"], + desc = L["Offset of the text from the bar horizontally"], + min = -350, + max = 350, + step = 1, + get = function() + return self.moduleSettings.textHorizontalOffset + end, + set = function(info, v) + self.moduleSettings.textHorizontalOffset = v + self:Redraw() + end, + disabled = function() + return not self.moduleSettings.enabled + end + }, + + forceJustifyText = { + type = 'select', + name = L["Force Text Justification"], + desc = L["This sets the alignment for the text on this bar"], + get = function() + return self.moduleSettings.forceJustifyText + end, + set = function(info, value) + self.moduleSettings.forceJustifyText = value + self:Redraw() + end, + values = { NONE = "None", LEFT = "Left", RIGHT = "Right" }, + disabled = function() + return not self.moduleSettings.enabled + end, + } + } + } + + return opts +end + +function CastBar.prototype:Enable(core) + CastBar.super.prototype.Enable(self, core) + + self:RegisterEvent("UNIT_ENTERED_VEHICLE", "EnteringVehicle") + self:RegisterEvent("UNIT_EXITED_VEHICLE", "ExitingVehicle") + self:RegisterEvent("PLAYER_ENTERING_WORLD", "CheckVehicle") + + self:RegisterEvent("CVAR_UPDATE", "CVarUpdate") + + self:CVarUpdate() + + if self.moduleSettings.enabled and not self.moduleSettings.showBlizzCast then + self:ToggleBlizzCast(false) + end + + if self.moduleSettings.shouldAnimate then + self.moduleSettings.shouldAnimate = false + end +end + + +function CastBar.prototype:EnteringVehicle(event, unit, arg2) + if (self.unit == "player" and IceHUD:ShouldSwapToVehicle(unit, arg2)) then + self.unit = "vehicle" + self:Update(self.unit) + end +end + + +function CastBar.prototype:ExitingVehicle(event, unit) + if (unit == "player" and self.unit == "vehicle") then + self.unit = "player" + self:Update(self.unit) + end +end + + +function CastBar.prototype:CheckVehicle() + if UnitHasVehicleUI("player") then + self:EnteringVehicle(nil, "player", true) + else + self:ExitingVehicle(nil, "player") + end +end + +function CastBar.prototype:CVarUpdate(...) + self.useFixedLatency = self.moduleSettings.respectLagTolerance and GetCVar("reducedLagTolerance") == "1" + self.fixedLatency = tonumber(GetCVar("maxSpellStartRecoveryoffset")) / 1000 +end + +function CastBar.prototype:Disable(core) + CastBar.super.prototype.Disable(self, core) + + if self.moduleSettings.showBlizzCast then + self:ToggleBlizzCast(true) + end +end + +function CastBar.prototype:ToggleBlizzCast(on) + if on then + -- restore blizz cast bar + CastingBarFrame:GetScript("OnLoad")(CastingBarFrame) + PetCastingBarFrame:GetScript("OnLoad")(PetCastingBarFrame) + else + -- remove blizz cast bar + CastingBarFrame:UnregisterAllEvents() + PetCastingBarFrame:UnregisterAllEvents() + end +end + + +-- OVERRIDE +function CastBar.prototype:CreateFrame() + CastBar.super.prototype.CreateFrame(self) + + self:CreateLagBar() +end + + +function CastBar.prototype:CreateLagBar() + self.lagBar = self:BarFactory(self.lagBar, "LOW", "OVERLAY") + + local r, g, b = self:GetColor("CastLag") + if (self.settings.backgroundToggle) then + r, g, b = self:GetColor("CastCasting") + end + + self.lagBar.bar:SetVertexColor(r, g, b, self.moduleSettings.lagAlpha) + self.lagBar.bar:Hide() +end + + +-- OVERRIDE +function CastBar.prototype:SpellCastSent(event, unit, spell, rank, target, lineId) + CastBar.super.prototype.SpellCastSent(self, event, unit, spell, rank, target, lineId) + if (unit ~= self.unit) then return end + + if IceHUD.WowVer < 70000 then + self.spellCastSent = GetTime() + end + self.sentSpell = lineId +end + +-- OVERRIDE +function CastBar.prototype:SpellCastChanged(event, arg1) + CastBar.super.prototype.SpellCastChanged(self, event, arg1) + if IceHUD.WowVer >= 70000 then + self.spellCastSent = GetTime() + end +end + +-- OVERRIDE +function CastBar.prototype:SpellCastStart(event, unit, spell, rank, lineId, spellId) + CastBar.super.prototype.SpellCastStart(self, event, unit, spell, rank, lineId, spellId) + if (unit ~= self.unit) then return end + + if not self:IsVisible() or not self.actionDuration then + return + end + + if self.sentSpell ~= lineId then + self.spellCastSent = nil + end + + local scale + if self.unit == "vehicle" then + scale = 0 + elseif self.useFixedLatency then + scale = IceHUD:Clamp(self.fixedLatency / self.actionDuration, 0, 1) + else + local now = GetTime() + local lag = now - (self.spellCastSent or now) + scale = IceHUD:Clamp(lag / self.actionDuration, 0, 1) + end + + self:SetBarCoord(self.lagBar, scale, true, true) + + self.spellCastSent = nil +end + + +-- OVERRIDE +function CastBar.prototype:SpellCastChannelStart(event, unit) + CastBar.super.prototype.SpellCastChannelStart(self, event, unit) + if (unit ~= self.unit) then return end + + if not self:IsVisible() or not self.actionDuration then + return + end + + local scale + if self.unit == "vehicle" then + scale = 0 + elseif self.useFixedLatency then + scale = IceHUD:Clamp(self.fixedLatency / self.actionDuration, 0, 1) + else + local now = GetTime() + local lag = now - (self.spellCastSent or now) + scale = IceHUD:Clamp(lag / self.actionDuration, 0, 1) + end + + local top = not self.moduleSettings.reverseChannel + + self:SetBarCoord(self.lagBar, scale, top, true) + + self.spellCastSent = nil +end + + +function CastBar.prototype:UpdateBar(scale, color, alpha) + local bCheckRange = true + local inRange + + if not self.moduleSettings.rangeColor or not self.current or not self.action or not UnitExists("target") then + bCheckRange = false + else + inRange = IsSpellInRange(self.current, "target") + if inRange == nil then + bCheckRange = false + end + end + + if bCheckRange and inRange == 0 then + color = "CastNotInRange" + end + + CastBar.super.prototype.UpdateBar(self, scale, color, alpha) +end + +------------------------------------------------------------------------------- + +-- Load us up +IceHUD.PlayerCast = CastBar:new()