local core = LibStub("AceAddon-3.0"):GetAddon("AllTheLittleThings") local mod = core:NewModule("Spellcast", "AceEvent-3.0", "AceTimer-3.0") local db local defaults = { anchor = { x = 500, y = 500, locked = false, }, buttonSize = 40, textSize = 10, spacing = 5, } local options = { locked = { name = "Locked", type = 'toggle', order = 1, get = function() return db.anchor.locked end, set = function(_, val) db.anchor.locked = val mod:SetLocked(val) end, }, } local spellWatch = { -- Polymorph [118] = "Polymorph", [61305] = "Polymorph", [28272] = "Polymorph", [61721] = "Polymorph", [61780] = "Polymorph", [28271] = "Polymorph", -- Counterspell [2139] = "Counterspell", -- Deep Freeze [44572] = "Deep Freeze", -- Frostbolt [116] = "Frostbolt", } local auras = { ["Polymorph"] = true, } local durations = { ["Polymorph"] = 8, ["Deep Freeze"] = 30, ["Counterspell"] = 24, ["Ice Lance"] = 10, } local validZones = { -- Battlegrounds ["Alterac Valley"] = true, ["Arathi Basin"] = true, ["Eye of the Storm"] = true, ["Isle of Conquest"] = true, ["Strand of the Ancients"] = true, ["The Battle for Gilneas"] = true, ["Twin Peaks"] = true, ["Warsong Gulch"] = true, -- Arenas ["Blade's Edge Arena"] = true, ["Dalaran Arena"] = true, ["Nagrand Arena"] = true, ["Ruins of Lordaeron"] = true, ["The Ring of Valor"] = true, -- Testing -- ["Stormwind City"] = true, } local combatEvents = { ["SPELL_AURA_APPLIED"] = true, ["SPELL_AURA_REFRESHED"] = true, ["SPELL_AURA_REMOVED"] = true, } local icons = {} local lastAvailable = {} local anchor, enabled, updateTimer function mod:OnInitialize() self:RegisterOptions(options, defaults, function(d) db = d end) end function mod:OnEnable() self:SetupIcons() self:RegisterEvent("ZONE_CHANGED_NEW_AREA") self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED") -- This doesn't always fire on load self:ZONE_CHANGED_NEW_AREA() end function mod:SetLocked(val) if val then anchor:Hide() else anchor:Show() end end function mod:ZONE_CHANGED_NEW_AREA() local before = enabled enabled = not not validZones[GetRealZoneText() or ""] if before ~= enabled then -- wipe last table so that we don't have an accumulated time wipe(lastAvailable) self:UpdateDisplay() end if not enabled then self:CancelTimer(updateTimer, true) updateTimer = nil end if enabled and not updateTimer then updateTimer = self:ScheduleRepeatingTimer("UpdateDisplay", 0.1) end end function mod:COMBAT_LOG_EVENT_UNFILTERED(_, _, event, _, ...) if not enabled or not combatEvents[event] then return end local srcGUID, dstGUID, spellId, _ if select(4, GetBuildInfo()) > 40100 then srcGUID, _, _, _, dstGUID, _, _, _, spellId = ... else srcGUID, _, _, dstGUID, _, _, spellId = ... end -- source is player if UnitGUID("player") ~= srcGUID then return end local category = spellWatch[spellId] if category then -- only handling auras here if auras[category] then if event == "SPELL_AURA_APPLIED" then local endTime = select(7, UnitDebuff(self:FindGUID(dstGUID), GetSpellInfo(spellId))) or (durations[category] or 0)+GetTime() self:SpellStart(category, endTime) elseif event == "SPELL_AURA_REMOVED" then self:SpellStop(category) end end end end function mod:UNIT_SPELLCAST_SUCCEEDED(_, unit, _, _, _, spellId) if not enabled or UnitGUID(unit) ~= UnitGUID("player") then return end local category = spellWatch[spellId] if category then -- self:Print("UNIT_SPELLCAST_SUCCEEDED", category, spellId) if not auras[category] then local duration = durations[category] if not duration then -- no duration means it has no cooldown, so we just start the timer self:SpellStop(category, true) else self:SpellStart(category, duration+GetTime()) end end end end function mod:SpellStart(category, endTime) local icon = icons[category] local time = GetTime() if not icon or endTime