mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-23 05:36:23 +00:00
311 lines
16 KiB
C++
311 lines
16 KiB
C++
/*
|
|
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Affero General Public License as published by the
|
|
* Free Software Foundation; either version 3 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 Affero General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef ACORE_SPELLAURAS_H
|
|
#define ACORE_SPELLAURAS_H
|
|
|
|
#include "SpellAuraDefines.h"
|
|
#include "Unit.h"
|
|
|
|
class Unit;
|
|
class SpellInfo;
|
|
struct SpellModifier;
|
|
struct ProcTriggerSpell;
|
|
struct SpellProcEntry;
|
|
|
|
// forward decl
|
|
class AuraEffect;
|
|
class Aura;
|
|
class DynamicObject;
|
|
class AuraScript;
|
|
|
|
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 void Unit::RemoveAura(AuraApplication* aurApp, AuraRemoveMode mode);
|
|
friend AuraApplication* Unit::_CreateAuraApplication(Aura* aura, uint8 effMask);
|
|
private:
|
|
Unit* const _target;
|
|
Aura* const _base;
|
|
AuraRemoveMode _removeMode: 8; // Store info for know remove aura reason
|
|
uint8 _slot; // Aura slot on unit
|
|
uint8 _flags; // Aura info flag
|
|
uint8 _effectsToApply; // Used only at spell hit to determine which effect should be applied
|
|
bool _needClientUpdate: 1;
|
|
|
|
// xinef: stacking
|
|
uint8 _disableMask;
|
|
|
|
explicit AuraApplication(Unit* target, Unit* caster, Aura* base, uint8 effMask);
|
|
void _Remove();
|
|
private:
|
|
void _InitFlags(Unit* caster, uint8 effMask);
|
|
void _HandleEffect(uint8 effIndex, bool apply);
|
|
public:
|
|
Unit* GetTarget() const { return _target; }
|
|
Aura* GetBase() const { return _base; }
|
|
|
|
uint8 GetSlot() const { return _slot; }
|
|
uint8 GetFlags() const { return _flags; }
|
|
uint8 GetEffectMask() const { return _flags & (AFLAG_EFF_INDEX_0 | AFLAG_EFF_INDEX_1 | AFLAG_EFF_INDEX_2); }
|
|
bool HasEffect(uint8 effect) const { ASSERT(effect < MAX_SPELL_EFFECTS); return _flags & (1 << effect); }
|
|
bool IsPositive() const { return _flags & AFLAG_POSITIVE; }
|
|
bool IsSelfcasted() const { return _flags & AFLAG_CASTER; }
|
|
uint8 GetEffectsToApply() const { return _effectsToApply; }
|
|
|
|
void SetRemoveMode(AuraRemoveMode mode) { _removeMode = mode; }
|
|
AuraRemoveMode GetRemoveMode() const {return _removeMode;}
|
|
|
|
void SetNeedClientUpdate() { _needClientUpdate = true;}
|
|
bool IsNeedClientUpdate() const { return _needClientUpdate;}
|
|
void BuildUpdatePacket(ByteBuffer& data, bool remove) const;
|
|
void ClientUpdate(bool remove = false);
|
|
|
|
// xinef: stacking
|
|
bool IsActive(uint8 effIdx) { return ((1 << effIdx) & _disableMask) == 0; }
|
|
void SetDisableMask(uint8 effIdx) { _disableMask |= 1 << effIdx; }
|
|
void RemoveDisableMask(uint8 effIdx) { _disableMask &= ~(1 << effIdx); }
|
|
};
|
|
|
|
class Aura
|
|
{
|
|
friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, bool noPeriodicReset);
|
|
public:
|
|
typedef std::map<ObjectGuid, AuraApplication*> ApplicationMap;
|
|
|
|
static uint8 BuildEffectMaskForOwner(SpellInfo const* spellProto, uint8 avalibleEffectMask, WorldObject* owner);
|
|
static Aura* TryRefreshStackOrCreate(SpellInfo const* spellproto, uint8 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, bool* refresh = nullptr, bool periodicReset = false);
|
|
static Aura* TryCreate(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemGUID = ObjectGuid::Empty);
|
|
static Aura* Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid itemGUID = ObjectGuid::Empty);
|
|
explicit Aura(SpellInfo const* spellproto, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID, ObjectGuid itemGUID = ObjectGuid::Empty);
|
|
void _InitEffects(uint8 effMask, Unit* caster, int32* baseAmount);
|
|
virtual ~Aura();
|
|
|
|
SpellInfo const* GetSpellInfo() const { return m_spellInfo; }
|
|
uint32 GetId() const;
|
|
|
|
ObjectGuid GetCastItemGUID() const { return m_castItemGuid; }
|
|
uint32 GetCastItemEntry() const { return m_castItemEntry; }
|
|
ObjectGuid 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<Unit*, uint8>& 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 CalcMaxDuration() const { return CalcMaxDuration(GetCaster()); }
|
|
int32 CalcMaxDuration(Unit* caster) const;
|
|
int32 GetDuration() const { return m_duration; }
|
|
void SetDuration(int32 duration, bool withMods = false);
|
|
void RefreshDuration(bool withMods = false);
|
|
void RefreshTimers(bool periodicReset = false);
|
|
void RefreshTimersWithMods();
|
|
bool IsExpired() const { return !GetDuration();}
|
|
bool IsPermanent() const { return GetMaxDuration() == -1; }
|
|
|
|
uint8 GetCharges() const { return m_procCharges; }
|
|
void SetCharges(uint8 charges);
|
|
uint8 CalcMaxCharges(Unit* caster) const;
|
|
uint8 CalcMaxCharges() const { return CalcMaxCharges(GetCaster()); }
|
|
bool ModCharges(int32 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
|
|
bool DropCharge(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) { return ModCharges(-1, removeMode); }
|
|
|
|
uint8 GetStackAmount() const { return m_stackAmount; }
|
|
void SetStackAmount(uint8 num);
|
|
bool ModStackAmount(int32 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT, bool periodicReset = false);
|
|
|
|
void RefreshSpellMods();
|
|
|
|
uint8 GetCasterLevel() const { return m_casterLevel; }
|
|
|
|
bool IsArea() const;
|
|
bool IsPassive() const;
|
|
bool IsDeathPersistent() const;
|
|
bool IsRemovedOnShapeLost(Unit* target) const;
|
|
bool CanBeSaved() const;
|
|
bool IsRemoved() const { return m_isRemoved; }
|
|
bool CanBeSentToClient() const;
|
|
// Single cast aura helpers
|
|
bool IsSingleTarget() const {return m_isSingleTarget; }
|
|
bool IsSingleTargetWith(Aura const* aura) const;
|
|
void SetIsSingleTarget(bool val) { m_isSingleTarget = val; }
|
|
void UnregisterSingleTarget();
|
|
int32 CalcDispelChance(Unit* auraTarget, bool offensive) const;
|
|
|
|
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 << i; return effMask; }
|
|
void RecalculateAmountOfEffects();
|
|
void HandleAllEffects(AuraApplication* aurApp, uint8 mode, bool apply);
|
|
|
|
// Helpers for targets
|
|
ApplicationMap const& GetApplicationMap() {return m_applications;}
|
|
void GetApplicationList(std::list<AuraApplication*>& applicationList) const;
|
|
const AuraApplication* GetApplicationOfTarget (ObjectGuid guid) const { ApplicationMap::const_iterator itr = m_applications.find(guid); if (itr != m_applications.end()) return itr->second; return nullptr; }
|
|
AuraApplication* GetApplicationOfTarget (ObjectGuid guid) { ApplicationMap::iterator itr = m_applications.find(guid); if (itr != m_applications.end()) return itr->second; return nullptr; }
|
|
bool IsAppliedOnTarget(ObjectGuid guid) const { return m_applications.find(guid) != m_applications.end(); }
|
|
|
|
void SetNeedClientUpdateForTargets() const;
|
|
void HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, bool apply, bool onReapply);
|
|
bool CanBeAppliedOn(Unit* target);
|
|
bool CheckAreaTarget(Unit* target);
|
|
bool CanStackWith(Aura const* checkAura, bool remove) const;
|
|
bool IsAuraStronger(Aura const* newAura) const;
|
|
|
|
// Proc system
|
|
// this subsystem is not yet in use - the core of it is functional, but still some research has to be done
|
|
// and some dependant problems fixed before it can replace old proc system (for example cooldown handling)
|
|
// currently proc system functionality is implemented in Unit::ProcDamageAndSpell
|
|
bool IsProcOnCooldown() const;
|
|
void AddProcCooldown(uint32 msec);
|
|
bool IsUsingCharges() const { return m_isUsingCharges; }
|
|
void SetUsingCharges(bool val) { m_isUsingCharges = val; }
|
|
void PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo);
|
|
bool IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo) const;
|
|
float CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const;
|
|
void TriggerProcOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo);
|
|
|
|
// AuraScript
|
|
void LoadScripts();
|
|
bool CallScriptCheckAreaTargetHandlers(Unit* target);
|
|
void CallScriptDispel(DispelInfo* dispelInfo);
|
|
void CallScriptAfterDispel(DispelInfo* dispelInfo);
|
|
bool CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode);
|
|
bool CallScriptEffectRemoveHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode);
|
|
void CallScriptAfterEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode);
|
|
void CallScriptAfterEffectRemoveHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode);
|
|
bool CallScriptEffectPeriodicHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp);
|
|
void CallScriptEffectUpdatePeriodicHandlers(AuraEffect* aurEff);
|
|
void CallScriptEffectCalcAmountHandlers(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated);
|
|
void CallScriptEffectCalcPeriodicHandlers(AuraEffect const* aurEff, bool& isPeriodic, int32& amplitude);
|
|
void CallScriptEffectCalcSpellModHandlers(AuraEffect const* aurEff, SpellModifier*& spellMod);
|
|
void CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& defaultPrevented);
|
|
void CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount);
|
|
void CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& defaultPrevented);
|
|
void CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount);
|
|
void CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& splitAmount);
|
|
|
|
// Spell Proc Hooks
|
|
bool CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
|
|
bool CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
|
|
bool CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
|
|
void CallScriptAfterProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
|
|
bool CallScriptEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo);
|
|
void CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo);
|
|
|
|
AuraScript* GetScriptByName(std::string const& scriptName) const;
|
|
|
|
std::list<AuraScript*> m_loadedScripts;
|
|
|
|
void SetTriggeredByAuraSpellInfo(SpellInfo const* triggeredByAuraSpellInfo);
|
|
SpellInfo const* GetTriggeredByAuraSpellInfo() const;
|
|
|
|
private:
|
|
void _DeleteRemovedApplications();
|
|
|
|
protected:
|
|
SpellInfo const* const m_spellInfo;
|
|
ObjectGuid const m_casterGuid;
|
|
ObjectGuid const m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted
|
|
uint32 const m_castItemEntry; // when deleted, we could retrieve some information from template instead
|
|
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
|
|
bool m_isUsingCharges: 1;
|
|
|
|
private:
|
|
Unit::AuraApplicationList m_removedApplications;
|
|
|
|
SpellInfo const* m_triggeredByAuraSpellInfo;
|
|
};
|
|
|
|
class UnitAura : public Aura
|
|
{
|
|
friend Aura* Aura::Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid itemGUID);
|
|
|
|
protected:
|
|
explicit UnitAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid itemGUID = ObjectGuid::Empty);
|
|
|
|
public:
|
|
void _ApplyForTarget(Unit* target, Unit* caster, AuraApplication* aurApp) override;
|
|
void _UnapplyForTarget(Unit* target, Unit* caster, AuraApplication* aurApp) override;
|
|
|
|
void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) override;
|
|
|
|
void FillTargetMap(std::map<Unit*, uint8>& targets, Unit* caster) override;
|
|
|
|
// 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(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid itemGUID);
|
|
|
|
protected:
|
|
explicit DynObjAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid itemGUID = ObjectGuid::Empty);
|
|
|
|
public:
|
|
void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) override;
|
|
|
|
void FillTargetMap(std::map<Unit*, uint8>& targets, Unit* caster) override;
|
|
};
|
|
#endif
|