--<< ====================================================================== >>-- -- Module Setup -- --<< ====================================================================== >>-- AceTimerCast = AceTimer:AddModule() function AceTimerCast:Enable() self.captive = {} self.active = {} self.rank_cache = {} self.iscasting = FALSE self:Hook("UseAction") self:Hook("CastSpell") self:Hook("CastSpellByName") self:Hook("SpellTargetUnit") self:Hook("TargetUnit") self:Hook("SpellStopTargeting") self:Hook("SpellStopCasting") self:HookScript(WorldFrame, "OnMouseDown") self:RegisterEvent("SPELLCAST_FAILED") self:RegisterEvent("SPELLCAST_INTERRUPTED") self:RegisterEvent("SPELLCAST_START") self:RegisterEvent("SPELLCAST_STOP") self:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE") self:RegisterEvent("LEARNED_SPELL_IN_TAB") self:RegisterEvent("PLAYER_DEAD") end function AceTimerCast:Disable() if self.captive then self.captive = nil end if self.active then self.active = nil end if self.iscasting then self.iscasting = nil end if self.rank_cache then self.rank_cache = nil end self:UnregisterAllEvents(self) self:UnhookAllScripts() end --<< ====================================================================== >>-- -- Helpers -- --<< ====================================================================== >>-- function AceTimerCast:LEARNED_SPELL_IN_TAB() for k in self.rank_cache do self.rank_cache[k] = nil end end function AceTimerCast:PLAYER_DEAD() self.active.t = nil; self.active.n = nil; self.active.u = nil; self.active.r = nil self.captive.t = nil; self.captive.n = nil; self.captive.u = nil; self.captive.r = nil self.iscasting = FALSE self:KillBars() end --<< ====================================================================== >>-- -- Catch Spellcast -- --<< ====================================================================== >>-- function AceTimerCast:UseAction(slot, clicked, onself) if not self.iscasting then if self.captive.n then self.captive.t = nil; self.captive.n = nil; self.captive.u = nil; self.captive.r = nil end if not GetActionText(slot) and HasAction(slot) then AceTimerTooltipTextRight1:SetText("") AceTimerTooltip:SetAction(slot) local name = AceTimerTooltipTextLeft1:GetText() local timer = self.timers[ACETIMER.SPELL][name] if timer then local rank = AceTimerTooltipTextRight1:GetText() if not rank then rank = 0 end self:CatchSpellcast(timer, name, rank, onself) end end end return self:CallHook("UseAction", slot, clicked, onself) end function AceTimerCast:CastSpell(index, booktype) if not self.iscasting then if self.captive.n then self.captive.t = nil; self.captive.n = nil; self.captive.u = nil; self.captive.r = nil end local name, rank = GetSpellName(index, booktype) local timer = self.timers[ACETIMER.SPELL][name] if timer then if not rank or rank == "" then rank = 0 end self:CatchSpellcast(timer, name, rank) end end return self:CallHook("CastSpell", index, booktype) end function AceTimerCast:CastSpellByName(text, onself) if not self.iscasting then if self.captive.n then self.captive.t = nil; self.captive.n = nil; self.captive.u = nil; self.captive.r = nil end local _,_, name, rank = string.find(text, "^(.+)%("..ACETIMER.PAT_RANK.."%)%s*$") if not name then _,_, name = string.find(text, "^(.+)%(%)%s*$") end if not name then name = text end local timer = self.timers[ACETIMER.SPELL][name] if timer then self:CatchSpellcast(timer, name, rank and tonumber(rank), oneself) end end return self:CallHook("CastSpellByName", text, onself) end function AceTimerCast:CatchSpellcast(timer, name, rank, onself) if not rank then if self.rank_cache[name] then rank = self.rank_cache[name] else local i, sn, sr = 1 while true do sn, sr = GetSpellName(i, BOOKTYPE_SPELL) if not sn then break elseif sn == name then rank = sr elseif rank then break end i = i + 1 end if not rank or rank == "" then rank = 0 end self.rank_cache[name] = rank end end if type(rank) == "string" then local _,_, found = string.find(rank, ACETIMER.PAT_RANK) rank = found and tonumber(found) or 0 end local unit if timer.k.t then if timer.k.s then if onself and onself == 1 then unit = UnitName("player") elseif UnitExists("target") then if timer.k.g then if UnitIsFriend("player", "target") then unit = UnitName("target") end else if UnitCanAttack("player", "target") then unit = UnitName("target") end end end else if UnitExists("target") then unit = UnitName("target") else return end end else unit = "none" end self.captive.t = timer; self.captive.n = name; self.captive.u = unit; self.captive.r = rank end --<< ====================================================================== >>-- -- Catch Spellcast Target -- --<< ====================================================================== >>-- function AceTimerCast:SpellTargetUnit(unit) if self.captive.n and not self.captive.u then self.captive.u = UnitName(unit) end return self:CallHook("SpellTargetUnit", unit) end function AceTimerCast:TargetUnit(unit) if self.captive.n and not self.captive.u then self.captive.u = UnitName(unit) end return self:CallHook("TargetUnit", unit) end function AceTimerCast:OnMouseDown() if self.captive.n and not self.captive.u and arg1 == "LeftButton" and UnitExists("mouseover") then self.captive.u = UnitName("mouseover") end return self:CallScript(WorldFrame, "OnMouseDown", arg1) end --<< ====================================================================== >>-- -- Complete Spellcast -- --<< ====================================================================== >>-- function AceTimerCast:SPELLCAST_START() self.iscasting = TRUE end function AceTimerCast:SPELLCAST_STOP() self.iscasting = FALSE if self.captive.n then if self.captive.u == "none" then self:StartTimer(self.captive.t, self.captive.n, self.captive.u, self.captive.r) else self.active.t = self.captive.t; self.active.n = self.captive.n; self.active.u = self.captive.u; self.active.r = self.captive.r Timex:AddSchedule("AceTimerCast", 0.5, nil, nil, self.CompleteCast, self) end self.captive.t = nil; self.captive.n = nil; self.captive.u = nil; self.captive.r = nil end end function AceTimerCast:CompleteCast() if self.active.n then self:StartTimer(self.active.t, self.active.n, self.active.u, self.active.r) self.active.t = nil; self.active.n = nil; self.active.u = nil; self.active.r = nil end end --<< ====================================================================== >>-- -- Drop Spellcast -- --<< ====================================================================== >>-- function AceTimerCast:SpellStopCasting() if self.captive.n then self.captive.t = nil; self.captive.n = nil; self.captive.u = nil; self.captive.r = nil end return self:CallHook("SpellStopCasting") end function AceTimerCast:SpellStopTargeting() if self.captive.n and SpellIsTargeting() then self.captive.t = nil; self.captive.n = nil; self.captive.u = nil; self.captive.r = nil end return self:CallHook("SpellStopTargeting") end function AceTimerCast:SPELLCAST_FAILED() if self.captive.n then self.captive.t = nil; self.captive.n = nil; self.captive.u = nil; self.captive.r = nil end self.iscasting = FALSE end function AceTimerCast:SPELLCAST_INTERRUPTED() if self.active.n then self.active.t = nil; self.active.n = nil; self.active.u = nil; self.active.r = nil end end function AceTimerCast:CHAT_MSG_SPELL_SELF_DAMAGE() if not self.active.n then return end if self:FindGlobal(arg1, SPELLDODGEDSELFOTHER) -- "Your %s was dodged by %s." or self:FindGlobal(arg1, SPELLPARRIEDSELFOTHER) -- "Your %s is parried by %s." or self:FindGlobal(arg1, SPELLEVADEDSELFOTHER) -- "Your %s was evaded by %s." or self:FindGlobal(arg1, SPELLMISSSELFOTHER) -- "Your %s missed %s." or self:FindGlobal(arg1, SPELLBLOCKEDSELFOTHER) -- "Your %s was blocked by %s." or self:FindGlobal(arg1, SPELLRESISTSELFOTHER) -- "Your %s was resisted by %s." or self:FindGlobal(arg1, SPELLIMMUNESELFOTHER) -- "Your %s failed. %s is immune." or self:FindGlobal(arg1, SPELLLOGABSORBSELFOTHER) -- "Your %s is absorbed by %s." or self:FindGlobal(arg1, SPELLREFLECTSELFOTHER) -- "Your %s is reflected back by %s." or self:FindGlobal(arg1, SPELLDEFLECTEDSELFOTHER) -- "Your %s was deflected by %s." then if self.gs_captured[1] == self.active.n and self.gs_captured[2] == self.active.u then self.active.t = nil; self.active.n = nil; self.active.u = nil; self.active.r = nil end end end