/* * Copyright (C) 2005-2009 MaNGOS * * Copyright (C) 2008-2010 Trinity * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef TRINITY_SPELLAURAS_H #define TRINITY_SPELLAURAS_H #include "SpellAuraDefines.h" class Unit; struct SpellEntry; struct SpellModifier; struct ProcTriggerSpell; // forward decl class AuraEffect; class Aura; class DynamicObject; // update aura target map every 500 ms instead of every update - reduce amount of grid searcher calls #define UPDATE_TARGET_MAP_INTERVAL 500 class AuraApplication { friend void Unit::_ApplyAura(AuraApplication * aurApp, uint8 effMask); friend void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode); friend void Unit::_ApplyAuraEffect(Aura * aura, uint8 effIndex); friend AuraApplication * Unit::_CreateAuraApplication(Aura * aura, uint8 effMask); private: Unit * const m_target; Aura * const m_base; uint8 m_slot; // Aura slot on unit uint8 m_flags; // Aura info flag uint8 m_effectsToApply; // Used only at spell hit to determine which effect should be applied AuraRemoveMode m_removeMode:8; // Store info for know remove aura reason bool m_needClientUpdate:1; bool m_isNeedManyNegativeEffects:1; explicit AuraApplication(Unit * target, Unit * caster, Aura * base, uint8 effMask); void _Remove(); private: bool _CheckPositive(Unit * caster) const; void _HandleEffect(uint8 effIndex, bool apply); public: Unit * GetTarget() const { return m_target; } Aura * GetBase() const { return m_base; } uint8 GetSlot() const { return m_slot; } uint8 GetFlags() const { return m_flags; } uint8 GetEffectMask() const { return m_flags & (AFLAG_EFF_INDEX_0 | AFLAG_EFF_INDEX_1 | AFLAG_EFF_INDEX_2); } bool HasEffect(uint8 effect) const { assert(effect < MAX_SPELL_EFFECTS); return m_flags & (1< ApplicationMap; static Aura * TryCreate(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount = NULL, Item * castItem = NULL, uint64 casterGUID = 0); static Aura * TryCreate(SpellEntry const* spellproto, WorldObject * owner, Unit * caster, int32 *baseAmount = NULL, Item * castItem = NULL, uint64 casterGUID = 0); static Aura * Create(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount = NULL, Item * castItem = NULL, uint64 casterGUID = 0); explicit Aura(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID); ~Aura(); SpellEntry const* GetSpellProto() const { return m_spellProto; } uint32 GetId() const{ return GetSpellProto()->Id; } uint64 GetCastItemGUID() const { return m_castItemGuid; } uint64 const& GetCasterGUID() const { return m_casterGuid; } Unit* GetCaster() const; WorldObject * GetOwner() const { return m_owner; } Unit * GetUnitOwner() const { assert(GetType() == UNIT_AURA_TYPE); return (Unit*)m_owner; } DynamicObject * GetDynobjOwner() const { assert(GetType() == DYNOBJ_AURA_TYPE); return (DynamicObject*)m_owner; } AuraObjectType GetType() const; virtual void _ApplyForTarget(Unit * target, Unit * caster, AuraApplication * auraApp); virtual void _UnapplyForTarget(Unit * target, Unit * caster, AuraApplication * auraApp); void _Remove(AuraRemoveMode removeMode); virtual void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) = 0; virtual void FillTargetMap(std::map & targets, Unit * caster) = 0; void UpdateTargetMap(Unit * caster, bool apply = true); void _RegisterForTargets() {Unit * caster = GetCaster(); UpdateTargetMap(caster, false);} void ApplyForTargets() {Unit * caster = GetCaster(); UpdateTargetMap(caster, true);} void _ApplyEffectForTargets(uint8 effIndex); void UpdateOwner(uint32 diff, WorldObject * owner); void Update(uint32 diff, Unit * caster); time_t GetApplyTime() const { return m_applyTime; } int32 GetMaxDuration() const { return m_maxDuration; } void SetMaxDuration(int32 duration) { m_maxDuration = duration; } int32 GetDuration() const { return m_duration; } void SetDuration(int32 duration, bool withMods = false); void RefreshDuration(); bool IsExpired() const { return !GetDuration();} bool IsPermanent() const { return GetMaxDuration() == -1; } uint8 GetCharges() const { return m_procCharges; } void SetCharges(uint8 charges); bool DropCharge(); uint8 GetStackAmount() const { return m_stackAmount; } void SetStackAmount(uint8 num, bool applied = true); bool ModStackAmount(int32 num); // return true if last charge dropped uint8 GetCasterLevel() const { return m_casterLevel; } bool IsPassive() const; bool IsDeathPersistent() const; bool IsRemovedOnShapeLost(Unit * target) const { return (GetCasterGUID() == target->GetGUID() && m_spellProto->Stances && !(m_spellProto->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) && !(m_spellProto->Attributes & SPELL_ATTR_NOT_SHAPESHIFT)); } bool CanBeSaved() const; bool IsRemoved() const { return m_isRemoved; } bool IsVisible() const; // Single cast aura helpers bool IsSingleTarget() const {return m_isSingleTarget;} void SetIsSingleTarget(bool val) { m_isSingleTarget = val;} void UnregisterSingleTarget(); void SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 * amount); // helpers for aura effects bool HasEffect(uint8 effIndex) const { return bool(GetEffect(effIndex)); } bool HasEffectType(AuraType type) const; AuraEffect * GetEffect (uint8 effIndex) const { assert (effIndex < MAX_SPELL_EFFECTS); return m_effects[effIndex]; } uint8 GetEffectMask() const { uint8 effMask = 0; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (m_effects[i]) effMask |= 1<second; return NULL; } AuraApplication * GetApplicationOfTarget (uint64 const & guid) { ApplicationMap::iterator itr = m_applications.find(guid); if (itr != m_applications.end()) return itr->second; return NULL; } bool IsAppliedOnTarget (uint64 const & guid) const { return m_applications.find(guid) != m_applications.end(); } void SetNeedClientUpdateForTargets() const; void HandleAuraSpecificMods(AuraApplication const * aurApp, Unit * caster, bool apply); bool CheckTarget(Unit *target); private: void _DeleteRemovedApplications(); protected: SpellEntry const * const m_spellProto; uint64 const m_casterGuid; uint64 const m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted time_t const m_applyTime; WorldObject * const m_owner; // int32 m_maxDuration; // Max aura duration int32 m_duration; // Current time int32 m_timeCla; // Timer for power per sec calcultion int32 m_updateTargetMapInterval; // Timer for UpdateTargetMapOfEffect uint8 const m_casterLevel; // Aura level (store caster level for correct show level dep amount) uint8 m_procCharges; // Aura charges (0 for infinite) uint8 m_stackAmount; // Aura stack amount AuraEffect * m_effects[3]; ApplicationMap m_applications; bool m_isRemoved:1; bool m_isSingleTarget:1; // true if it's a single target spell and registered at caster - can change at spell steal for example private: Unit::AuraApplicationList m_removedApplications; }; class UnitAura : public Aura { friend Aura * Aura::Create(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID); protected: explicit UnitAura(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID); public: void _ApplyForTarget(Unit * target, Unit * caster, AuraApplication * aurApp); void _UnapplyForTarget(Unit * target, Unit * caster, AuraApplication * aurApp); void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); void FillTargetMap(std::map & targets, Unit * caster); // Allow Apply Aura Handler to modify and access m_AuraDRGroup void SetDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; } DiminishingGroup GetDiminishGroup() const { return m_AuraDRGroup; } private: DiminishingGroup m_AuraDRGroup:8; // Diminishing }; class DynObjAura : public Aura { friend Aura * Aura::Create(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID); protected: explicit DynObjAura(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID); public: void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); void FillTargetMap(std::map & targets, Unit * caster); }; #endif