local Tinkr, Bastion = ... -- Create a new Spell class local Spell = { CastableIfFunc = false, PreCastFunc = false, OnCastFunc = false, wasLooking = false, lastCastAt = 0, conditions = {}, target = false, } local usableExcludes = { [18562] = true, } function Spell:__index(k) local response = Bastion.ClassMagic:Resolve(Spell, k) if response == nil then response = rawget(self, k) end if response == nil then error("Spell:__index: " .. k .. " does not exist") end return response end -- tostring function Spell:__tostring() return "Bastion.__Spell(" .. self:GetID() .. ")" .. " - " .. self:GetName() end -- Constructor function Spell:New(id) local self = setmetatable({}, Spell) self.spellID = id return self end -- Get the spells id function Spell:GetID() return self.spellID end -- Get the spells name function Spell:GetName() return GetSpellInfo(self:GetID()) end -- Get the spells icon function Spell:GetIcon() return select(3, GetSpellInfo(self:GetID())) end -- Get the spells cooldown function Spell:GetCooldown() return select(2, GetSpellCooldown(self:GetID())) end -- Return the castable function function Spell:GetCastableFunction() return self.CastableIfFunc end -- Return the precast function function Spell:GetPreCastFunction() return self.PreCastFunc end -- Get the on cast func function Spell:GetOnCastFunction() return self.OnCastFunc end -- Get the spells cooldown remaining function Spell:GetCooldownRemaining() local start, duration = GetSpellCooldown(self:GetID()) return start + duration - GetTime() end -- Cast the spell function Spell:Cast(unit, condition) if condition and not self:EvaluateCondition(condition) then return false end if not self:Castable() then return false end -- Call pre cast function if self:GetPreCastFunction() then self:GetPreCastFunction()(self) end -- Check if the mouse was looking self.wasLooking = IsMouselooking() -- Cast the spell CastSpellByName(self:GetName(), unit.unit) Bastion:Debug("Casting", self) -- Set the last cast time self.lastCastAt = GetTime() -- Call post cast function if self:GetOnCastFunction() then self:GetOnCastFunction()(self) end end -- Check if the spell is known function Spell:IsKnown() local isKnown = IsSpellKnown(self:GetID()) local isPlayerSpell = IsPlayerSpell(self:GetID()) return isKnown or isPlayerSpell end -- Check if the spell is on cooldown function Spell:IsOnCooldown() return select(2, GetSpellCooldown(self:GetID())) > 0 end -- Check if the spell is usable function Spell:IsUsable() local usable, noMana = IsUsableSpell(self:GetID()) return usable or usableExcludes[self:GetID()] end -- Check if the spell is castable function Spell:IsKnownAndUsable() return self:IsKnown() and not self:IsOnCooldown() and self:IsUsable() end -- Check if the spell is castable function Spell:Castable() if self:GetCastableFunction() then return self:GetCastableFunction()(self) end return self:IsKnownAndUsable() end -- Set a script to check if the spell is castable function Spell:CastableIf(func) self.CastableIfFunc = func return self end -- Set a script to run before the spell has been cast function Spell:PreCast(func) self.PreCastFunc = func return self end -- Set a script to run after the spell has been cast function Spell:OnCast(func) self.OnCastFunc = func return self end -- Get was looking function Spell:GetWasLooking() return self.wasLooking end -- Click the spell function Spell:Click(x, y, z) if type(x) == 'table' then x, y, z = x.x, x.y, x.z end if IsSpellPending() == 64 then MouselookStop() Click(x, y, z) if self:GetWasLooking() then MouselookStart() end return true end return false end -- Check if the spell is castable and cast it function Spell:Call(unit) if self:Castable() then self:Cast(unit) return true end return false end -- Check if the spell is in range of the unit function Spell:IsInRange(unit) local name, rank, icon, castTime, spellmin, spellmax, spellID = GetSpellInfo(self:GetID()) local them = Object(unit.unit) local tx, ty, tz = ObjectPosition(unit.unit) local px, py, pz = ObjectPosition('player') if not them then return false end if tx == 0 and ty == 0 and tz == 0 then return true end local combatReach = ObjectCombatReach("player") local themCombatReach = ObjectCombatReach(unit.unit) if Bastion.UnitManager['player']:InMelee(unit) and spellmin == 0 then return true end local distance = FastDistance(px, py, pz, tx, ty, tz) if spellmax and distance >= spellmin and distance <= combatReach + themCombatReach + spellmax then return true end return false end -- Get the last cast time function Spell:GetLastCastTime() return self.lastCastAt end -- Get time since last cast function Spell:GetTimeSinceLastCast() if not self:GetLastCastTime() then return math.huge end return GetTime() - self:GetLastCastTime() end -- Get the spells charges function Spell:GetCharges() return GetSpellCharges(self:GetID()) end -- Get the spells charges remaining function Spell:GetChargesRemaining() local charges, maxCharges, start, duration = GetSpellCharges(self:GetID()) return charges end -- Create a condition for the spell function Spell:Condition(name, func) self.conditions[name] = { func = func } return self end -- Get a condition for the spell function Spell:GetCondition(name) local condition = self.conditions[name] if condition then return condition end return nil end -- Evaluate a condition for the spell function Spell:EvaluateCondition(name) local condition = self:GetCondition(name) if condition then return condition.func(self) end return false end -- Check if the spell has a condition function Spell:HasCondition(name) local condition = self:GetCondition(name) if condition then return true end return false end -- Set the spells target function Spell:SetTarget(unit) self.target = unit return self end -- Get the spells target function Spell:GetTarget() return self.target end -- IsMagicDispel function Spell:IsMagicDispel() return ({ [88423] = true })[self:GetID()] end -- IsCurseDispel function Spell:IsCurseDispel() return ({ [88423] = true })[self:GetID()] end -- IsPoisonDispel function Spell:IsPoisonDispel() return ({ [88423] = true })[self:GetID()] end -- IsDiseaseDispel function Spell:IsDiseaseDispel() return ({ })[self:GetID()] end function Spell:IsSpell(spell) return self:GetID() == spell:GetID() end return Spell