aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp7
-rw-r--r--src/server/game/Entities/Player/Player.cpp8
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp103
-rw-r--r--src/server/game/Entities/Unit/Unit.h14
-rw-r--r--src/server/game/Spells/Auras/SpellAuraDefines.h44
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h17
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp507
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h114
-rw-r--r--src/server/game/Spells/Spell.cpp64
-rw-r--r--src/server/game/Spells/Spell.h5
-rw-r--r--src/server/game/Spells/SpellEffects.cpp66
-rw-r--r--src/server/game/Spells/SpellScript.cpp21
-rw-r--r--src/server/game/Spells/SpellScript.h2
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp5
-rw-r--r--src/server/scripts/Spells/spell_dh.cpp1
-rw-r--r--src/server/scripts/Spells/spell_paladin.cpp4
17 files changed, 586 insertions, 398 deletions
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 7df230526dc..f7bd8b75bb1 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -1210,7 +1210,12 @@ void Pet::_LoadAuras(uint32 timediff)
AuraLoadEffectInfo& info = effectInfo[key];
ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellInfo->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>());
- if (Aura* aura = Aura::TryCreate(spellInfo, castId, key.EffectMask, this, nullptr, difficulty, info.BaseAmounts.data(), nullptr, casterGuid))
+ AuraCreateInfo createInfo(castId, spellInfo, difficulty, key.EffectMask, this);
+ createInfo
+ .SetCasterGUID(casterGuid)
+ .SetBaseAmount(info.BaseAmounts.data());
+
+ if (Aura* aura = Aura::TryCreate(createInfo))
{
if (!aura->CanBeSaved())
{
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 441b6c8bd4d..bbb4ccf5887 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -18759,7 +18759,13 @@ void Player::_LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effe
AuraLoadEffectInfo& info = effectInfo[key];
ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellInfo->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>());
- if (Aura* aura = Aura::TryCreate(spellInfo, castId, key.EffectMask, this, nullptr, difficulty, info.BaseAmounts.data(), nullptr, casterGuid, itemGuid, castItemId, castItemLevel))
+ AuraCreateInfo createInfo(castId, spellInfo, difficulty, key.EffectMask, this);
+ createInfo
+ .SetCasterGUID(casterGuid)
+ .SetBaseAmount(info.BaseAmounts.data())
+ .SetCastItem(itemGuid, castItemId, castItemLevel);
+
+ if (Aura* aura = Aura::TryCreate(createInfo))
{
if (!aura->CanBeSaved())
{
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index fadd871a970..b75fc274072 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -3255,44 +3255,31 @@ void Unit::DeMorph()
SetDisplayId(GetNativeDisplayId());
}
-Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool resetPeriodicTimer /*= true*/, ObjectGuid castItemGuid /*= ObjectGuid::Empty*/, uint32 castItemId /*= 0*/, int32 castItemLevel /*= -1*/)
+Aura* Unit::_TryStackingOrRefreshingExistingAura(AuraCreateInfo& createInfo)
{
- ASSERT(!casterGUID.IsEmpty() || caster);
+ ASSERT(!createInfo.CasterGUID.IsEmpty() || createInfo.Caster);
// Check if these can stack anyway
- if (!casterGUID && !newAura->IsStackableOnOneSlotWithDifferentCasters())
- casterGUID = caster->GetGUID();
+ if (!createInfo.CasterGUID && !createInfo.GetSpellInfo()->IsStackableOnOneSlotWithDifferentCasters())
+ createInfo.CasterGUID = createInfo.Caster->GetGUID();
// passive and Incanter's Absorption and auras with different type can stack with themselves any number of times
- if (!newAura->IsMultiSlotAura())
+ if (!createInfo.GetSpellInfo()->IsMultiSlotAura())
{
// check if cast item changed
- if (castItem)
- {
- castItemGuid = castItem->GetGUID();
- if (Player* owner = castItem->GetOwner())
- {
- castItemId = castItem->GetEntry();
- castItemLevel = int32(castItem->GetItemLevel(owner));
- }
- else if (castItem->GetOwnerGUID() == caster->GetGUID())
- {
- castItemId = castItem->GetEntry();
- castItemLevel = int32(castItem->GetItemLevel(caster->ToPlayer()));
- }
- }
+ ObjectGuid castItemGUID = createInfo.CastItemGUID;
// find current aura from spell and change it's stackamount, or refresh it's duration
- if (Aura* foundAura = GetOwnedAura(newAura->Id, casterGUID, (newAura->HasAttribute(SPELL_ATTR0_CU_ENCHANT_PROC)) ? castItemGuid : ObjectGuid::Empty, 0))
+ if (Aura* foundAura = GetOwnedAura(createInfo.GetSpellInfo()->Id, createInfo.CasterGUID, createInfo.GetSpellInfo()->HasAttribute(SPELL_ATTR0_CU_ENCHANT_PROC) ? castItemGUID : ObjectGuid::Empty, 0))
{
// effect masks do not match
// extremely rare case
// let's just recreate aura
- if (effMask != foundAura->GetEffectMask())
+ if (createInfo.GetAuraEffectMask() != foundAura->GetEffectMask())
return nullptr;
// update basepoints with new values - effect amount will be recalculated in ModStackAmount
- for (SpellEffectInfo const* effect : newAura->GetEffects())
+ for (SpellEffectInfo const* effect : createInfo.GetSpellInfo()->GetEffects())
{
if (!effect)
continue;
@@ -3301,9 +3288,9 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint3
if (!eff)
continue;
- int bp;
- if (baseAmount)
- bp = *(baseAmount + effect->EffectIndex);
+ int32 bp;
+ if (createInfo.BaseAmount)
+ bp = *(createInfo.BaseAmount + effect->EffectIndex);
else
bp = effect->BasePoints;
@@ -3312,18 +3299,18 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint3
}
// correct cast item guid if needed
- if (castItemGuid != foundAura->GetCastItemGUID())
+ if (castItemGUID != foundAura->GetCastItemGUID())
{
ObjectGuid* oldGUID = const_cast<ObjectGuid*>(&foundAura->m_castItemGuid);
- *oldGUID = castItemGuid;
+ *oldGUID = castItemGUID;
uint32* oldItemId = const_cast<uint32*>(&foundAura->m_castItemId);
- *oldItemId = castItemId;
+ *oldItemId = createInfo.CastItemId;
int32* oldItemLevel = const_cast<int32*>(&foundAura->m_castItemLevel);
- *oldItemLevel = castItemLevel;
+ *oldItemLevel = createInfo.CastItemLevel;
}
// try to increase stack amount
- foundAura->ModStackAmount(1, AURA_REMOVE_BY_DEFAULT, resetPeriodicTimer);
+ foundAura->ModStackAmount(1, AURA_REMOVE_BY_DEFAULT, createInfo.ResetPeriodicTimer);
return foundAura;
}
}
@@ -3334,7 +3321,7 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint3
void Unit::_AddAura(UnitAura* aura, Unit* caster)
{
ASSERT(!m_cleanupDone);
- m_ownedAuras.insert(AuraMap::value_type(aura->GetId(), aura));
+ m_ownedAuras.emplace(aura->GetId(), aura);
_RemoveNoStackAurasDueToAura(aura);
@@ -3371,7 +3358,7 @@ void Unit::_AddAura(UnitAura* aura, Unit* caster)
// creates aura application instance and registers it in lists
// aura application effects are handled separately to prevent aura list corruption
-AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint32 effMask)
+AuraApplication* Unit::_CreateAuraApplication(Aura* aura, uint32 effMask)
{
// can't apply aura on unit which is going to be deleted - to not create a memory leak
ASSERT(!m_cleanupDone);
@@ -3421,7 +3408,7 @@ void Unit::_ApplyAuraEffect(Aura* aura, uint8 effIndex)
// handles effects of aura application
// should be done after registering aura in lists
-void Unit::_ApplyAura(AuraApplication * aurApp, uint32 effMask)
+void Unit::_ApplyAura(AuraApplication* aurApp, uint32 effMask)
{
Aura* aura = aurApp->GetBase();
@@ -3464,7 +3451,7 @@ void Unit::_ApplyAura(AuraApplication * aurApp, uint32 effMask)
}
// removes aura application from lists and unapplies effects
-void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode)
+void Unit::_UnapplyAura(AuraApplicationMap::iterator& i, AuraRemoveMode removeMode)
{
AuraApplication * aurApp = i->second;
ASSERT(aurApp);
@@ -3552,7 +3539,7 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMo
i = m_appliedAuras.begin();
}
-void Unit::_UnapplyAura(AuraApplication * aurApp, AuraRemoveMode removeMode)
+void Unit::_UnapplyAura(AuraApplication* aurApp, AuraRemoveMode removeMode)
{
// aura can be removed from unit only if it's applied on it, shouldn't happen
ASSERT(aurApp->GetBase()->GetApplicationOfTarget(GetGUID()) == aurApp);
@@ -3621,8 +3608,8 @@ void Unit::_RegisterAuraEffect(AuraEffect* aurEff, bool apply)
m_modAuras[aurEff->GetAuraType()].remove(aurEff);
}
-// All aura base removes should go threw this function!
-void Unit::RemoveOwnedAura(AuraMap::iterator &i, AuraRemoveMode removeMode)
+// All aura base removes should go through this function!
+void Unit::RemoveOwnedAura(AuraMap::iterator& i, AuraRemoveMode removeMode)
{
Aura* aura = i->second;
ASSERT(!aura->IsRemoved());
@@ -3952,7 +3939,12 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, U
if (aura->IsSingleTarget())
aura->UnregisterSingleTarget();
- if (Aura* newAura = Aura::TryRefreshStackOrCreate(aura->GetSpellInfo(), aura->GetCastGUID(), effMask, stealer, nullptr, aura->GetCastDifficulty(), &baseDamage[0], nullptr, aura->GetCasterGUID()))
+ AuraCreateInfo createInfo(aura->GetCastGUID(), aura->GetSpellInfo(), aura->GetCastDifficulty(), effMask, stealer);
+ createInfo
+ .SetCasterGUID(aura->GetCasterGUID())
+ .SetBaseAmount(baseDamage);
+
+ if (Aura* newAura = Aura::TryRefreshStackOrCreate(createInfo))
{
// created aura must not be single target aura,, so stealer won't loose it on recast
if (newAura->IsSingleTarget())
@@ -12315,12 +12307,19 @@ Aura* Unit::AddAura(SpellInfo const* spellInfo, uint32 effMask, Unit* target)
{
if (!(effMask & (1 << i)))
continue;
+
if (target->IsImmunedToSpellEffect(spellInfo, i, this))
effMask &= ~(1 << i);
}
+ if (!effMask)
+ return nullptr;
+
ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellInfo->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>());
- if (Aura* aura = Aura::TryRefreshStackOrCreate(spellInfo, castId, effMask, target, this, GetMap()->GetDifficultyID()))
+ AuraCreateInfo createInfo(castId, spellInfo, GetMap()->GetDifficultyID(), effMask, target);
+ createInfo.SetCaster(this);
+
+ if (Aura* aura = Aura::TryRefreshStackOrCreate(createInfo))
{
aura->ApplyForTargets();
return aura;
@@ -12769,18 +12768,25 @@ void Unit::HandleSpellClick(Unit* clicker, int8 seatId /*= -1*/)
{
CastSpellExtraArgs args(flags);
args.OriginalCaster = origCasterGUID;
- args.AddSpellMod(SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId+1);
+ args.AddSpellMod(SpellValueMod(SPELLVALUE_BASE_POINT0 + i), seatId + 1);
caster->CastSpell(target, clickPair.second.spellId, args);
}
else // This can happen during Player::_LoadAuras
{
- int32 bp0[MAX_SPELL_EFFECTS];
+ int32 bp[MAX_SPELL_EFFECTS] = { };
for (SpellEffectInfo const* effect : spellEntry->GetEffects())
if (effect)
- bp0[effect->EffectIndex] = effect->BasePoints;
+ bp[effect->EffectIndex] = effect->BasePoints;
+
+ bp[i] = seatId;
- bp0[i] = seatId;
- Aura::TryRefreshStackOrCreate(spellEntry, ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellEntry->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()), MAX_EFFECT_MASK, this, clicker, GetMap()->GetDifficultyID(), bp0, nullptr, origCasterGUID);
+ AuraCreateInfo createInfo(ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellEntry->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()), spellEntry, GetMap()->GetDifficultyID(), MAX_EFFECT_MASK, this);
+ createInfo
+ .SetCaster(clicker)
+ .SetBaseAmount(bp)
+ .SetCasterGUID(origCasterGUID);
+
+ Aura::TryRefreshStackOrCreate(createInfo);
}
}
else
@@ -12788,7 +12794,14 @@ void Unit::HandleSpellClick(Unit* clicker, int8 seatId /*= -1*/)
if (IsInMap(caster))
caster->CastSpell(target, spellEntry->Id, CastSpellExtraArgs().SetOriginalCaster(origCasterGUID));
else
- Aura::TryRefreshStackOrCreate(spellEntry, ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellEntry->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()), MAX_EFFECT_MASK, this, clicker, GetMap()->GetDifficultyID(), nullptr, nullptr, origCasterGUID);
+ {
+ AuraCreateInfo createInfo(ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellEntry->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()), spellEntry, GetMap()->GetDifficultyID(), MAX_EFFECT_MASK, this);
+ createInfo
+ .SetCaster(clicker)
+ .SetCasterGUID(origCasterGUID);
+
+ Aura::TryRefreshStackOrCreate(createInfo);
+ }
}
spellClickHandled = true;
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index a2bb7f1a301..ff5c76a1bb5 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -762,7 +762,7 @@ class TC_GAME_API Unit : public WorldObject
typedef std::list<AuraEffect*> AuraEffectList;
typedef std::list<Aura*> AuraList;
- typedef std::list<AuraApplication *> AuraApplicationList;
+ typedef std::list<AuraApplication*> AuraApplicationList;
typedef std::array<DiminishingReturn, DIMINISHING_MAX> Diminishing;
typedef std::vector<std::pair<uint32 /*procEffectMask*/, AuraApplication*>> AuraApplicationProcContainer;
@@ -1337,13 +1337,13 @@ class TC_GAME_API Unit : public WorldObject
bool InitTamedPet(Pet* pet, uint8 level, uint32 spell_id);
// aura apply/remove helpers - you should better not use these
- Aura* _TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, bool resetPeriodicTimer = true, ObjectGuid castItemGuid = ObjectGuid::Empty, uint32 castItemId = 0, int32 castItemLevel = -1);
+ Aura* _TryStackingOrRefreshingExistingAura(AuraCreateInfo& createInfo);
void _AddAura(UnitAura* aura, Unit* caster);
- AuraApplication * _CreateAuraApplication(Aura* aura, uint32 effMask);
+ AuraApplication* _CreateAuraApplication(Aura* aura, uint32 effMask);
void _ApplyAuraEffect(Aura* aura, uint8 effIndex);
- void _ApplyAura(AuraApplication * aurApp, uint32 effMask);
- void _UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode);
- void _UnapplyAura(AuraApplication * aurApp, AuraRemoveMode removeMode);
+ void _ApplyAura(AuraApplication* aurApp, uint32 effMask);
+ void _UnapplyAura(AuraApplicationMap::iterator& i, AuraRemoveMode removeMode);
+ void _UnapplyAura(AuraApplication* aurApp, AuraRemoveMode removeMode);
void _RemoveNoStackAurasDueToAura(Aura* aura);
void _RegisterAuraEffect(AuraEffect* aurEff, bool apply);
@@ -1351,7 +1351,7 @@ class TC_GAME_API Unit : public WorldObject
AuraMap & GetOwnedAuras() { return m_ownedAuras; }
AuraMap const& GetOwnedAuras() const { return m_ownedAuras; }
- void RemoveOwnedAura(AuraMap::iterator &i, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
+ void RemoveOwnedAura(AuraMap::iterator& i, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
void RemoveOwnedAura(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, uint32 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
void RemoveOwnedAura(Aura* aura, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h
index 0706e3709e1..60b7475c978 100644
--- a/src/server/game/Spells/Auras/SpellAuraDefines.h
+++ b/src/server/game/Spells/Auras/SpellAuraDefines.h
@@ -18,6 +18,13 @@
#define TRINITY_SPELLAURADEFINES_H
#include "Define.h"
+#include "ObjectGuid.h"
+
+class Item;
+class SpellInfo;
+class Unit;
+class WorldObject;
+enum Difficulty : uint8;
#define MAX_AURAS 255
@@ -641,4 +648,41 @@ enum ShapeshiftForm
FORM_FORGEBORNE_REVERIES = 42
};
+struct TC_GAME_API AuraCreateInfo
+{
+ friend class Aura;
+ friend class UnitAura;
+ friend class DynObjAura;
+
+ AuraCreateInfo(ObjectGuid castId, SpellInfo const* spellInfo, Difficulty castDifficulty, uint32 auraEffMask, WorldObject* owner);
+
+ AuraCreateInfo& SetCasterGUID(ObjectGuid const& guid) { CasterGUID = guid; return *this; }
+ AuraCreateInfo& SetCaster(Unit* caster) { Caster = caster; return *this; }
+ AuraCreateInfo& SetBaseAmount(int32 const* bp) { BaseAmount = bp; return *this; }
+ AuraCreateInfo& SetCastItem(ObjectGuid const& guid, uint32 itemId, int32 itemLevel) { CastItemGUID = guid; CastItemId = itemId; CastItemLevel = itemLevel; return *this; }
+ AuraCreateInfo& SetPeriodicReset(bool reset) { ResetPeriodicTimer = reset; return *this; }
+ AuraCreateInfo& SetOwnerEffectMask(uint32 effMask) { _targetEffectMask = effMask; return *this; }
+
+ SpellInfo const* GetSpellInfo() const { return _spellInfo; }
+ uint32 GetAuraEffectMask() const { return _auraEffectMask; }
+
+ ObjectGuid CasterGUID;
+ Unit* Caster = nullptr;
+ int32 const* BaseAmount = nullptr;
+ ObjectGuid CastItemGUID;
+ uint32 CastItemId = 0;
+ int32 CastItemLevel = -1;
+ bool* IsRefresh = nullptr;
+ bool ResetPeriodicTimer = true;
+
+private:
+ ObjectGuid _castId;
+ SpellInfo const* _spellInfo = nullptr;
+ Difficulty _castDifficulty = Difficulty(0);
+ uint32 _auraEffectMask = 0;
+ WorldObject* _owner = nullptr;
+
+ uint32 _targetEffectMask = 0;
+};
+
#endif
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index abc447b79b9..159a153ab1f 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -575,7 +575,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNULL, //503 SPELL_AURA_MOD_PLAYER_CHOICE_REROLLS
};
-AuraEffect::AuraEffect(Aura* base, SpellEffectInfo const* spellEfffectInfo, int32 *baseAmount, Unit* caster) :
+AuraEffect::AuraEffect(Aura* base, SpellEffectInfo const* spellEfffectInfo, int32 const* baseAmount, Unit* caster) :
m_base(base), m_spellInfo(base->GetSpellInfo()), m_effectInfo(spellEfffectInfo), m_spellmod(nullptr),
m_baseAmount(baseAmount ? *baseAmount : spellEfffectInfo->CalcBaseValue(caster, base->GetType() == UNIT_AURA_TYPE ? base->GetOwner()->ToUnit() : nullptr, base->GetCastItemId(), base->GetCastItemLevel())),
_amount(), _periodicTimer(0), _period(0), _ticksDone(0),
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index bf8c4bc9ab7..1a96b81ea68 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -18,23 +18,24 @@
#ifndef TRINITY_SPELLAURAEFFECTS_H
#define TRINITY_SPELLAURAEFFECTS_H
-class Unit;
-class AuraEffect;
-class Aura;
-
#include "SpellAuras.h"
+class AuraEffect;
+class Unit;
+
typedef void(AuraEffect::*pAuraEffectHandler)(AuraApplication const* aurApp, uint8 mode, bool apply) const;
class TC_GAME_API AuraEffect
{
- friend void Aura::_InitEffects(uint32 effMask, Unit* caster, int32* baseAmount);
- friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, bool resetPeriodicTimer, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
+ friend void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 const* baseAmount);
friend Aura::~Aura();
+ friend class Unit;
- public:
+ private:
~AuraEffect();
- AuraEffect(Aura* base, SpellEffectInfo const* spellEfffectInfo, int32 *baseAmount, Unit* caster);
+ explicit AuraEffect(Aura* base, SpellEffectInfo const* spellEfffectInfo, int32 const* baseAmount, Unit* caster);
+
+ public:
Unit* GetCaster() const { return GetBase()->GetCaster(); }
ObjectGuid GetCasterGUID() const { return GetBase()->GetCasterGUID(); }
Aura* GetBase() const { return m_base; }
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 2ecd3c29e38..7ea0658e916 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -38,7 +38,33 @@
#include "Vehicle.h"
#include "World.h"
-AuraApplication::AuraApplication(Unit* target, Unit* caster, Aura* aura, uint32 effMask):
+class ChargeDropEvent : public BasicEvent
+{
+public:
+ ChargeDropEvent(Aura* base, AuraRemoveMode mode) : _base(base), _mode(mode) { }
+ bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override
+ {
+ // _base is always valid (look in Aura::_Remove())
+ _base->ModChargesDelayed(-1, _mode);
+ return true;
+ }
+
+private:
+ Aura* _base;
+ AuraRemoveMode _mode;
+};
+
+AuraCreateInfo::AuraCreateInfo(ObjectGuid castId, SpellInfo const* spellInfo, Difficulty castDifficulty, uint32 auraEffMask, WorldObject* owner) :
+ _castId(castId), _spellInfo(spellInfo), _castDifficulty(castDifficulty), _auraEffectMask(auraEffMask), _owner(owner)
+{
+ ASSERT(spellInfo);
+ ASSERT(auraEffMask);
+ ASSERT(owner);
+
+ ASSERT(auraEffMask <= MAX_EFFECT_MASK);
+}
+
+AuraApplication::AuraApplication(Unit* target, Unit* caster, Aura* aura, uint32 effMask) :
_target(target), _base(aura), _removeMode(AURA_REMOVE_NONE), _slot(MAX_AURAS),
_flags(AFLAG_NONE), _effectsToApply(effMask), _needClientUpdate(false), _effectMask(0)
{
@@ -154,6 +180,37 @@ void AuraApplication::_HandleEffect(uint8 effIndex, bool apply)
SetNeedClientUpdate();
}
+void AuraApplication::UpdateApplyEffectMask(uint32 newEffMask)
+{
+ if (_effectsToApply == newEffMask)
+ return;
+
+ uint32 removeEffMask = (_effectsToApply ^ newEffMask) & (~newEffMask);
+ uint32 addEffMask = (_effectsToApply ^ newEffMask) & (~_effectsToApply);
+
+ // quick check, removes application completely
+ if (removeEffMask == _effectsToApply && !addEffMask)
+ {
+ _target->_UnapplyAura(this, AURA_REMOVE_BY_DEFAULT);
+ return;
+ }
+
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ // update real effects only if they were applied already
+ if (!(_effectMask & (1 << i)))
+ continue;
+
+ if (removeEffMask & (1 << i))
+ _HandleEffect(i, false);
+
+ if (addEffMask & (1 << i))
+ _HandleEffect(i, true);
+ }
+
+ _effectsToApply = newEffMask;
+}
+
void AuraApplication::SetNeedClientUpdate()
{
if (_needClientUpdate || GetRemoveMode() != AURA_REMOVE_NONE)
@@ -264,101 +321,130 @@ uint32 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 availab
return effMask & availableEffectMask;
}
-Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool* refresh /*= nullptr*/, bool resetPeriodicTimer /*= true*/, ObjectGuid castItemGuid /*= ObjectGuid::Empty*/, uint32 castItemId /*= 0*/, int32 castItemLevel /*= -1*/)
+Aura* Aura::TryRefreshStackOrCreate(AuraCreateInfo& createInfo)
{
- ASSERT(spellproto);
- ASSERT(owner);
- ASSERT(caster || !casterGUID.IsEmpty());
- ASSERT(tryEffMask <= MAX_EFFECT_MASK);
- if (refresh)
- *refresh = false;
+ ASSERT(createInfo.Caster || !createInfo.CasterGUID.IsEmpty());
+
+ if (createInfo.IsRefresh)
+ *createInfo.IsRefresh = false;
+
+ createInfo._auraEffectMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, createInfo._auraEffectMask, createInfo._owner);
+ createInfo._targetEffectMask &= createInfo._auraEffectMask;
+
+ uint32 effMask = createInfo._auraEffectMask;
+ if (createInfo._targetEffectMask)
+ effMask = createInfo._targetEffectMask;
- uint32 effMask = Aura::BuildEffectMaskForOwner(spellproto, tryEffMask, owner);
if (!effMask)
return nullptr;
- if (Aura* foundAura = owner->ToUnit()->_TryStackingOrRefreshingExistingAura(spellproto, effMask, caster, baseAmount, castItem, casterGUID, resetPeriodicTimer, castItemGuid, castItemLevel))
+ if (Aura* foundAura = createInfo._owner->ToUnit()->_TryStackingOrRefreshingExistingAura(createInfo))
{
// we've here aura, which script triggered removal after modding stack amount
// check the state here, so we won't create new Aura object
if (foundAura->IsRemoved())
return nullptr;
- if (refresh)
- *refresh = true;
+ if (createInfo.IsRefresh)
+ *createInfo.IsRefresh = true;
+ // add owner
+ Unit* unit = createInfo._owner->ToUnit();
+
+ // check effmask on owner application (if existing)
+ if (AuraApplication* aurApp = foundAura->GetApplicationOfTarget(unit->GetGUID()))
+ aurApp->UpdateApplyEffectMask(effMask);
return foundAura;
}
else
- return Create(spellproto, castId, effMask, owner, caster, castDifficulty, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
+ return Create(createInfo);
}
-Aura* Aura::TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, ObjectGuid castItemGuid /*= ObjectGuid::Empty*/, uint32 castItemId /*= 0*/, int32 castItemLevel /*= -1*/)
+Aura* Aura::TryCreate(AuraCreateInfo& createInfo)
{
- ASSERT(spellproto);
- ASSERT(owner);
- ASSERT(caster || !casterGUID.IsEmpty());
- ASSERT(tryEffMask <= MAX_EFFECT_MASK);
- uint32 effMask = Aura::BuildEffectMaskForOwner(spellproto, tryEffMask, owner);
+ ASSERT(createInfo.Caster || !createInfo.CasterGUID.IsEmpty());
+
+ uint32 effMask = createInfo._auraEffectMask;
+ if (createInfo._targetEffectMask)
+ effMask = createInfo._targetEffectMask;
+
+ effMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, effMask, createInfo._owner);
if (!effMask)
return nullptr;
- return Create(spellproto, castId, effMask, owner, caster, castDifficulty, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
+ return Create(createInfo);
}
-Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel)
+Aura* Aura::Create(AuraCreateInfo& createInfo)
{
- ASSERT(effMask);
- ASSERT(spellproto);
- ASSERT(owner);
- ASSERT(caster || !casterGUID.IsEmpty());
- ASSERT(effMask <= MAX_EFFECT_MASK);
+ ASSERT(createInfo.Caster || !createInfo.CasterGUID.IsEmpty());
+
// try to get caster of aura
- if (!casterGUID.IsEmpty())
+ if (!createInfo.CasterGUID.IsEmpty())
{
- if (owner->GetGUID() == casterGUID)
- caster = owner->ToUnit();
+ if (createInfo._owner->GetGUID() == createInfo.CasterGUID)
+ createInfo.Caster = createInfo._owner->ToUnit();
else
- caster = ObjectAccessor::GetUnit(*owner, casterGUID);
+ createInfo.Caster = ObjectAccessor::GetUnit(*createInfo._owner, createInfo.CasterGUID);
}
else
- casterGUID = caster->GetGUID();
+ createInfo.CasterGUID = createInfo.Caster->GetGUID();
// check if aura can be owned by owner
- if (owner->isType(TYPEMASK_UNIT))
- if (!owner->IsInWorld() || ((Unit*)owner)->IsDuringRemoveFromWorld())
+ if (createInfo._owner->isType(TYPEMASK_UNIT))
+ if (!createInfo._owner->IsInWorld() || createInfo._owner->ToUnit()->IsDuringRemoveFromWorld())
// owner not in world so don't allow to own not self cast single target auras
- if (casterGUID != owner->GetGUID() && spellproto->IsSingleTarget())
+ if (createInfo.CasterGUID != createInfo._owner->GetGUID() && createInfo._spellInfo->IsSingleTarget())
return nullptr;
Aura* aura = nullptr;
- switch (owner->GetTypeId())
+ switch (createInfo._owner->GetTypeId())
{
case TYPEID_UNIT:
case TYPEID_PLAYER:
- aura = new UnitAura(spellproto, castId, effMask, owner, caster, castDifficulty, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
+ {
+ aura = new UnitAura(createInfo);
+
+ // aura can be removed in Unit::_AddAura call
+ if (aura->IsRemoved())
+ return nullptr;
+
+ // add owner
+ uint32 effMask = createInfo._auraEffectMask;
+ if (createInfo._targetEffectMask)
+ effMask = createInfo._targetEffectMask;
+
+ effMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, effMask, createInfo._owner);
+ ASSERT(effMask);
+
+ Unit* unit = createInfo._owner->ToUnit();
+ aura->ToUnitAura()->AddStaticApplication(unit, effMask);
break;
+ }
case TYPEID_DYNAMICOBJECT:
- aura = new DynObjAura(spellproto, castId, effMask, owner, caster, castDifficulty, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
+ createInfo._auraEffectMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, createInfo._auraEffectMask, createInfo._owner);
+ ASSERT(createInfo._auraEffectMask);
+
+ aura = new DynObjAura(createInfo);
break;
default:
ABORT();
return nullptr;
}
- // aura can be removed in Unit::_AddAura call
+ // scripts, etc.
if (aura->IsRemoved())
return nullptr;
+
return aura;
}
-Aura::Aura(SpellInfo const* spellproto, ObjectGuid castId, WorldObject* owner, Unit* caster, Difficulty castDifficulty,
- Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel) :
-m_spellInfo(spellproto), m_castDifficulty(castDifficulty), m_castGuid(castId), m_casterGuid(!casterGUID.IsEmpty() ? casterGUID : caster->GetGUID()),
-m_castItemGuid(castItem ? castItem->GetGUID() : castItemGuid), m_castItemId(castItem ? castItem->GetEntry() : castItemId),
-m_castItemLevel(castItemLevel), m_spellVisual({ caster ? caster->GetCastSpellXSpellVisualId(spellproto) : spellproto->GetSpellXSpellVisualId(), 0 }),
-m_applyTime(GameTime::GetGameTime()), m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0),
-m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1),
+Aura::Aura(AuraCreateInfo const& createInfo) :
+m_spellInfo(createInfo._spellInfo), m_castDifficulty(createInfo._castDifficulty), m_castGuid(createInfo._castId), m_casterGuid(createInfo.CasterGUID.IsEmpty() ? createInfo.Caster->GetGUID() : createInfo.CasterGUID),
+m_castItemGuid(createInfo.CastItemGUID), m_castItemId(createInfo.CastItemId),
+m_castItemLevel(createInfo.CastItemLevel), m_spellVisual({ createInfo.Caster ? createInfo.Caster->GetCastSpellXSpellVisualId(createInfo._spellInfo) : createInfo._spellInfo->GetSpellXSpellVisualId(), 0 }),
+m_applyTime(GameTime::GetGameTime()), m_owner(createInfo._owner), m_timeCla(0), m_updateTargetMapInterval(0),
+m_casterLevel(createInfo.Caster ? createInfo.Caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1),
m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr),
m_procCooldown(std::chrono::steady_clock::time_point::min()),
m_lastProcAttemptTime(std::chrono::steady_clock::now() - Seconds(10)), m_lastProcSuccessTime(std::chrono::steady_clock::now() - Seconds(120))
@@ -370,9 +456,9 @@ m_lastProcAttemptTime(std::chrono::steady_clock::now() - Seconds(10)), m_lastPro
if (!m_periodicCosts.empty())
m_timeCla = 1 * IN_MILLISECONDS;
- m_maxDuration = CalcMaxDuration(caster);
+ m_maxDuration = CalcMaxDuration(createInfo.Caster);
m_duration = m_maxDuration;
- m_procCharges = CalcMaxCharges(caster);
+ m_procCharges = CalcMaxCharges(createInfo.Caster);
m_isUsingCharges = m_procCharges != 0;
// m_casterLevel = cast item level/caster level, caster level should be saved to db, confirmed with sniffs
}
@@ -385,7 +471,7 @@ AuraScript* Aura::GetScriptByName(std::string const& scriptName) const
return nullptr;
}
-void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount)
+void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 const* baseAmount)
{
// shouldn't be in constructor - functions in AuraEffect::AuraEffect use polymorphism
_effects.resize(GetSpellInfo()->GetEffects().size());
@@ -434,7 +520,7 @@ AuraObjectType Aura::GetType() const
return (m_owner->GetTypeId() == TYPEID_DYNAMICOBJECT) ? DYNOBJ_AURA_TYPE : UNIT_AURA_TYPE;
}
-void Aura::_ApplyForTarget(Unit* target, Unit* caster, AuraApplication * auraApp)
+void Aura::_ApplyForTarget(Unit* target, Unit* caster, AuraApplication* auraApp)
{
ASSERT(target);
ASSERT(auraApp);
@@ -454,7 +540,7 @@ void Aura::_ApplyForTarget(Unit* target, Unit* caster, AuraApplication * auraApp
}
}
-void Aura::_UnapplyForTarget(Unit* target, Unit* caster, AuraApplication * auraApp)
+void Aura::_UnapplyForTarget(Unit* target, Unit* caster, AuraApplication* auraApp)
{
ASSERT(target);
ASSERT(auraApp->GetRemoveMode());
@@ -474,7 +560,7 @@ void Aura::_UnapplyForTarget(Unit* target, Unit* caster, AuraApplication * auraA
ASSERT(itr->second == auraApp);
m_applications.erase(itr);
- m_removedApplications.push_back(auraApp);
+ _removedApplications.push_back(auraApp);
// reset cooldown state for spells
if (caster && GetSpellInfo()->IsCooldownStartedOnEvent())
@@ -517,61 +603,45 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
FillTargetMap(targets, caster);
- std::deque<Unit*> targetsToRemove;
+ std::vector<Unit*> targetsToRemove;
// mark all auras as ready to remove
- for (ApplicationMap::iterator appIter = m_applications.begin(); appIter != m_applications.end();++appIter)
+ for (auto const& applicationPair : m_applications)
{
- auto itr = targets.find(appIter->second->GetTarget());
+ auto itr = targets.find(applicationPair.second->GetTarget());
// not found in current area - remove the aura
if (itr == targets.end())
- targetsToRemove.push_back(appIter->second->GetTarget());
+ targetsToRemove.push_back(applicationPair.second->GetTarget());
else
{
// needs readding - remove now, will be applied in next update cycle
// (dbcs do not have auras which apply on same type of targets but have different radius, so this is not really needed)
- if (appIter->second->GetEffectMask() != itr->second || !CanBeAppliedOn(itr->first))
- targetsToRemove.push_back(appIter->second->GetTarget());
- // nothing todo - aura already applied
+ if (!CanBeAppliedOn(itr->first))
+ {
+ targetsToRemove.push_back(applicationPair.second->GetTarget());
+ continue;
+ }
+
+ // needs to add/remove effects from application, don't remove from map so it gets updated
+ if (applicationPair.second->GetEffectMask() != itr->second)
+ continue;
+
+ // nothing to do - aura already applied
// remove from auras to register list
targets.erase(itr);
}
}
// register auras for units
- for (auto itr = targets.begin(); itr!= targets.end();)
+ for (auto itr = targets.begin(); itr != targets.end();)
{
- // aura mustn't be already applied on target
- if (AuraApplication* aurApp = GetApplicationOfTarget(itr->first->GetGUID()))
- {
- // the core created 2 different units with same guid
- // this is a major failue, which i can't fix right now
- // let's remove one unit from aura list
- // this may cause area aura "bouncing" between 2 units after each update
- // but because we know the reason of a crash we can remove the assertion for now
- if (aurApp->GetTarget() != itr->first)
- {
- // remove from auras to register list
- itr = targets.erase(itr);
- continue;
- }
- else
- {
- // ok, we have one unit twice in target map (impossible, but...)
- ABORT();
- }
- }
-
bool addUnit = true;
// check target immunities
for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
- {
if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), effIndex, caster))
itr->second &= ~(1 << effIndex);
- }
- if (!itr->second
- || itr->first->IsImmunedToSpell(GetSpellInfo(), caster)
- || !CanBeAppliedOn(itr->first))
+
+ if (!itr->second || itr->first->IsImmunedToSpell(GetSpellInfo(), caster) || !CanBeAppliedOn(itr->first))
addUnit = false;
if (addUnit && !itr->first->IsHighestExclusiveAura(this, true))
@@ -605,6 +675,7 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
}
}
}
+
if (!addUnit)
itr = targets.erase(itr);
else
@@ -618,6 +689,13 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
itr->first->GetName().c_str(), itr->first->IsInWorld() ? itr->first->GetMap()->GetId() : uint32(-1));
ABORT();
}
+
+ if (AuraApplication* aurApp = GetApplicationOfTarget(itr->first->GetGUID()))
+ {
+ // aura is already applied, this means we need to update effects of current application
+ itr->first->_UnapplyAura(aurApp, AURA_REMOVE_BY_DEFAULT);
+ }
+
itr->first->_CreateAuraApplication(this, itr->second);
++itr;
}
@@ -913,20 +991,20 @@ void Aura::SetStackAmount(uint8 stackAmount)
m_stackAmount = stackAmount;
Unit* caster = GetCaster();
- std::list<AuraApplication*> applications;
- GetApplicationList(applications);
+ std::vector<AuraApplication*> applications;
+ GetApplicationVector(applications);
- for (std::list<AuraApplication*>::const_iterator apptItr = applications.begin(); apptItr != applications.end(); ++apptItr)
- if (!(*apptItr)->GetRemoveMode())
- HandleAuraSpecificMods(*apptItr, caster, false, true);
+ for (AuraApplication* aurApp : applications)
+ if (!aurApp->GetRemoveMode())
+ HandleAuraSpecificMods(aurApp, caster, false, true);
- for (AuraEffect* effect : GetAuraEffects())
- if (effect)
- effect->ChangeAmount(effect->CalculateAmount(caster), false, true);
+ for (AuraEffect* aurEff : GetAuraEffects())
+ if (aurEff)
+ aurEff->ChangeAmount(aurEff->CalculateAmount(caster), false, true);
- for (std::list<AuraApplication*>::const_iterator apptItr = applications.begin(); apptItr != applications.end(); ++apptItr)
- if (!(*apptItr)->GetRemoveMode())
- HandleAuraSpecificMods(*apptItr, caster, true, true);
+ for (AuraApplication* aurApp : applications)
+ if (!aurApp->GetRemoveMode())
+ HandleAuraSpecificMods(aurApp, caster, true, true);
SetNeedClientUpdateForTargets();
}
@@ -1013,6 +1091,14 @@ bool Aura::IsDeathPersistent() const
return GetSpellInfo()->IsDeathPersistent();
}
+bool Aura::IsRemovedOnShapeLost(Unit* target) const
+{
+ return GetCasterGUID() == target->GetGUID()
+ && m_spellInfo->Stances
+ && !m_spellInfo->HasAttribute(SPELL_ATTR2_NOT_NEED_SHAPESHIFT)
+ && !m_spellInfo->HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFT);
+}
+
bool Aura::CanBeSaved() const
{
if (IsPassive())
@@ -1191,18 +1277,20 @@ void Aura::HandleAllEffects(AuraApplication * aurApp, uint8 mode, bool apply)
uint32 Aura::GetEffectMask() const
{
uint32 effMask = 0;
- for (AuraEffect* effect : GetAuraEffects())
- if (effect)
- effMask |= 1 << effect->GetEffIndex();
+ for (AuraEffect* aurEff : GetAuraEffects())
+ if (aurEff)
+ effMask |= 1 << aurEff->GetEffIndex();
return effMask;
}
-void Aura::GetApplicationList(Unit::AuraApplicationList& applicationList) const
+void Aura::GetApplicationVector(std::vector<AuraApplication*>& applicationList) const
{
- for (Aura::ApplicationMap::const_iterator appIter = m_applications.begin(); appIter != m_applications.end(); ++appIter)
+ for (auto const& applicationPair : m_applications)
{
- if (appIter->second->GetEffectMask())
- applicationList.push_back(appIter->second);
+ if (!applicationPair.second->GetEffectMask())
+ continue;
+
+ applicationList.push_back(applicationPair.second);
}
}
@@ -1828,11 +1916,10 @@ float Aura::CalcPPMProcChance(Unit* actor) const
void Aura::_DeleteRemovedApplications()
{
- while (!m_removedApplications.empty())
- {
- delete m_removedApplications.front();
- m_removedApplications.pop_front();
- }
+ for (AuraApplication* aurApp : _removedApplications)
+ delete aurApp;
+
+ _removedApplications.clear();
}
void Aura::LoadScripts()
@@ -1987,7 +2074,7 @@ void Aura::CallScriptEffectUpdatePeriodicHandlers(AuraEffect* aurEff)
}
}
-void Aura::CallScriptEffectCalcAmountHandlers(AuraEffect const* aurEff, int32 & amount, bool & canBeRecalculated)
+void Aura::CallScriptEffectCalcAmountHandlers(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated)
{
for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
@@ -2001,7 +2088,7 @@ void Aura::CallScriptEffectCalcAmountHandlers(AuraEffect const* aurEff, int32 &
}
}
-void Aura::CallScriptEffectCalcPeriodicHandlers(AuraEffect const* aurEff, bool & isPeriodic, int32 & amplitude)
+void Aura::CallScriptEffectCalcPeriodicHandlers(AuraEffect const* aurEff, bool& isPeriodic, int32& amplitude)
{
for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
@@ -2015,7 +2102,7 @@ void Aura::CallScriptEffectCalcPeriodicHandlers(AuraEffect const* aurEff, bool &
}
}
-void Aura::CallScriptEffectCalcSpellModHandlers(AuraEffect const* aurEff, SpellModifier* & spellMod)
+void Aura::CallScriptEffectCalcSpellModHandlers(AuraEffect const* aurEff, SpellModifier*& spellMod)
{
for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
@@ -2042,7 +2129,7 @@ void Aura::CallScriptEffectCalcCritChanceHandlers(AuraEffect const* aurEff, Aura
}
}
-void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool& defaultPrevented)
+void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& defaultPrevented)
{
for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
@@ -2060,7 +2147,7 @@ void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication co
}
}
-void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount)
+void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount)
{
for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
@@ -2074,7 +2161,7 @@ void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplicati
}
}
-void Aura::CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool & /*defaultPrevented*/)
+void Aura::CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& /*defaultPrevented*/)
{
for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
@@ -2088,7 +2175,7 @@ void Aura::CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplicatio
}
}
-void Aura::CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount)
+void Aura::CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount)
{
for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
@@ -2102,7 +2189,7 @@ void Aura::CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraAppli
}
}
-void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & splitAmount)
+void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& splitAmount)
{
for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
@@ -2243,17 +2330,16 @@ void Aura::CallScriptAfterEffectProcHandlers(AuraEffect* aurEff, AuraApplication
}
}
-UnitAura::UnitAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty,
- int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel)
- : Aura(spellproto, castId, owner, caster, castDifficulty, castItem, casterGUID, castItemGuid, castItemId, castItemLevel)
+UnitAura::UnitAura(AuraCreateInfo const& createInfo)
+ : Aura(createInfo)
{
m_AuraDRGroup = DIMINISHING_NONE;
LoadScripts();
- _InitEffects(effMask, caster, baseAmount);
- GetUnitOwner()->_AddAura(this, caster);
+ _InitEffects(createInfo._auraEffectMask, createInfo.Caster, createInfo.BaseAmount);
+ GetUnitOwner()->_AddAura(this, createInfo.Caster);
}
-void UnitAura::_ApplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp)
+void UnitAura::_ApplyForTarget(Unit* target, Unit* caster, AuraApplication* aurApp)
{
Aura::_ApplyForTarget(target, caster, aurApp);
@@ -2262,7 +2348,7 @@ void UnitAura::_ApplyForTarget(Unit* target, Unit* caster, AuraApplication * aur
target->ApplyDiminishingAura(group, true);
}
-void UnitAura::_UnapplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp)
+void UnitAura::_UnapplyForTarget(Unit* target, Unit* caster, AuraApplication* aurApp)
{
Aura::_UnapplyForTarget(target, caster, aurApp);
@@ -2284,115 +2370,118 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c
if (!ref)
ref = GetUnitOwner();
+ // add non area aura targets
+ // static applications go through spell system first, so we assume they meet conditions
+ for (auto const& targetPair : _staticApplications)
+ if (Unit* target = ObjectAccessor::GetUnit(*GetUnitOwner(), targetPair.first))
+ targets.emplace(target, targetPair.second);
+
for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects())
{
if (!effect || !HasEffect(effect->EffectIndex))
continue;
- std::vector<Unit*> units;
- ConditionContainer* condList = effect->ImplicitTargetConditions;
- // non-area aura
+ // area auras only
if (effect->Effect == SPELL_EFFECT_APPLY_AURA)
- {
- if (!condList || sConditionMgr->IsObjectMeetToConditions(GetUnitOwner(), ref, *condList))
- units.push_back(GetUnitOwner());
- }
- else
- {
- // skip area update if owner is not in world!
- if (!GetUnitOwner()->IsInWorld())
- continue;
+ continue;
- if (GetUnitOwner()->HasUnitState(UNIT_STATE_ISOLATED))
- continue;
+ // skip area update if owner is not in world!
+ if (!GetUnitOwner()->IsInWorld())
+ continue;
- float radius = effect->CalcRadius(caster);
- SpellTargetCheckTypes selectionType = TARGET_CHECK_DEFAULT;
- switch (effect->Effect)
- {
- case SPELL_EFFECT_APPLY_AREA_AURA_PARTY:
- case SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM:
- selectionType = TARGET_CHECK_PARTY;
- break;
- case SPELL_EFFECT_APPLY_AREA_AURA_RAID:
- selectionType = TARGET_CHECK_RAID;
- break;
- case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
- selectionType = TARGET_CHECK_ALLY;
- break;
- case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
- selectionType = TARGET_CHECK_ENEMY;
- break;
- case SPELL_EFFECT_APPLY_AREA_AURA_PET:
- if (!condList || sConditionMgr->IsObjectMeetToConditions(GetUnitOwner(), ref, *condList))
- units.push_back(GetUnitOwner());
- /* fallthrough */
- case SPELL_EFFECT_APPLY_AREA_AURA_OWNER:
- {
- if (Unit* owner = GetUnitOwner()->GetCharmerOrOwner())
- if (GetUnitOwner()->IsWithinDistInMap(owner, radius))
- if (!condList || sConditionMgr->IsObjectMeetToConditions(owner, ref, *condList))
- units.push_back(owner);
- break;
- }
- case SPELL_EFFECT_APPLY_AURA_ON_PET:
- {
- if (Unit* pet = ObjectAccessor::GetUnit(*GetUnitOwner(), GetUnitOwner()->GetPetGUID()))
- if (!condList || sConditionMgr->IsObjectMeetToConditions(pet, ref, *condList))
- units.push_back(pet);
- break;
- }
- case SPELL_EFFECT_APPLY_AREA_AURA_SUMMONS:
- {
- if (!condList || sConditionMgr->IsObjectMeetToConditions(GetUnitOwner(), ref, *condList))
- units.push_back(GetUnitOwner());
+ if (GetUnitOwner()->HasUnitState(UNIT_STATE_ISOLATED))
+ continue;
- selectionType = TARGET_CHECK_SUMMONED;
- break;
- }
- }
+ std::vector<Unit*> units;
+ ConditionContainer* condList = effect->ImplicitTargetConditions;
- if (selectionType != TARGET_CHECK_DEFAULT)
+ float radius = effect->CalcRadius(ref);
+ SpellTargetCheckTypes selectionType = TARGET_CHECK_DEFAULT;
+ switch (effect->Effect)
+ {
+ case SPELL_EFFECT_APPLY_AREA_AURA_PARTY:
+ case SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM:
+ selectionType = TARGET_CHECK_PARTY;
+ break;
+ case SPELL_EFFECT_APPLY_AREA_AURA_RAID:
+ selectionType = TARGET_CHECK_RAID;
+ break;
+ case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
+ selectionType = TARGET_CHECK_ALLY;
+ break;
+ case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
+ selectionType = TARGET_CHECK_ENEMY;
+ break;
+ case SPELL_EFFECT_APPLY_AREA_AURA_PET:
+ if (!condList || sConditionMgr->IsObjectMeetToConditions(GetUnitOwner(), ref, *condList))
+ units.push_back(GetUnitOwner());
+ /* fallthrough */
+ case SPELL_EFFECT_APPLY_AREA_AURA_OWNER:
{
- Trinity::WorldObjectSpellAreaTargetCheck check(radius, GetUnitOwner(), ref, GetUnitOwner(), m_spellInfo, selectionType, condList, TARGET_OBJECT_TYPE_UNIT);
- Trinity::UnitListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> searcher(GetUnitOwner(), units, check);
- Cell::VisitAllObjects(GetUnitOwner(), searcher, radius);
+ if (Unit* owner = GetUnitOwner()->GetCharmerOrOwner())
+ if (GetUnitOwner()->IsWithinDistInMap(owner, radius))
+ if (!condList || sConditionMgr->IsObjectMeetToConditions(owner, ref, *condList))
+ units.push_back(owner);
+ break;
+ }
+ case SPELL_EFFECT_APPLY_AURA_ON_PET:
+ {
+ if (Unit* pet = ObjectAccessor::GetUnit(*GetUnitOwner(), GetUnitOwner()->GetPetGUID()))
+ if (!condList || sConditionMgr->IsObjectMeetToConditions(pet, ref, *condList))
+ units.push_back(pet);
+ break;
+ }
+ case SPELL_EFFECT_APPLY_AREA_AURA_SUMMONS:
+ {
+ if (!condList || sConditionMgr->IsObjectMeetToConditions(GetUnitOwner(), ref, *condList))
+ units.push_back(GetUnitOwner());
- // by design WorldObjectSpellAreaTargetCheck allows not-in-world units (for spells) but for auras it is not acceptable
- units.erase(std::remove_if(units.begin(), units.end(), [this](Unit* unit) { return !unit->IsSelfOrInSameMap(GetUnitOwner()); }), units.end());
+ selectionType = TARGET_CHECK_SUMMONED;
+ break;
}
}
- for (Unit* unit : units)
+ if (selectionType != TARGET_CHECK_DEFAULT)
{
- auto itr = targets.find(unit);
- if (itr != targets.end())
- itr->second |= 1 << effect->EffectIndex;
- else
- targets[unit] = 1 << effect->EffectIndex;
+ Trinity::WorldObjectSpellAreaTargetCheck check(radius, GetUnitOwner(), ref, GetUnitOwner(), m_spellInfo, selectionType, condList, TARGET_OBJECT_TYPE_UNIT);
+ Trinity::UnitListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> searcher(GetUnitOwner(), units, check);
+ Cell::VisitAllObjects(GetUnitOwner(), searcher, radius);
+
+ // by design WorldObjectSpellAreaTargetCheck allows not-in-world units (for spells) but for auras it is not acceptable
+ units.erase(std::remove_if(units.begin(), units.end(), [this](Unit* unit) { return !unit->IsSelfOrInSameMap(GetUnitOwner()); }), units.end());
}
+
+ for (Unit* unit : units)
+ targets[unit] |= 1 << effect->EffectIndex;
}
}
-DynObjAura::DynObjAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty,
- int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel)
- : Aura(spellproto, castId, owner, caster, castDifficulty, castItem, casterGUID, castItemGuid, castItemId, castItemLevel)
+void UnitAura::AddStaticApplication(Unit* target, uint32 effMask)
+{
+ // only valid for non-area auras
+ for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffects())
+ {
+ if (effect && (effMask & (1 << effect->EffectIndex)) && effect->Effect != SPELL_EFFECT_APPLY_AURA)
+ effMask &= ~(1 << effect->EffectIndex);
+ }
+
+ if (!effMask)
+ return;
+
+ _staticApplications[target->GetGUID()] |= effMask;
+}
+
+DynObjAura::DynObjAura(AuraCreateInfo const& createInfo)
+ : Aura(createInfo)
{
LoadScripts();
ASSERT(GetDynobjOwner());
ASSERT(GetDynobjOwner()->IsInWorld());
- ASSERT(GetDynobjOwner()->GetMap() == caster->GetMap());
- _InitEffects(effMask, caster, baseAmount);
+ ASSERT(GetDynobjOwner()->GetMap() == createInfo.Caster->GetMap());
+ _InitEffects(createInfo._auraEffectMask, createInfo.Caster, createInfo.BaseAmount);
GetDynobjOwner()->SetAura(this);
}
-bool ChargeDropEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
-{
- // _base is always valid (look in Aura::_Remove())
- _base->ModChargesDelayed(-1, _mode);
- return true;
-}
-
void DynObjAura::Remove(AuraRemoveMode removeMode)
{
if (IsRemoved())
@@ -2426,12 +2515,6 @@ void DynObjAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit*
units.erase(std::remove_if(units.begin(), units.end(), [this](Unit* unit) { return !unit->IsSelfOrInSameMap(GetDynobjOwner()); }), units.end());
for (Unit* unit : units)
- {
- auto itr = targets.find(unit);
- if (itr != targets.end())
- itr->second |= 1 << effect->EffectIndex;
- else
- targets[unit] = 1 << effect->EffectIndex;
- }
+ targets[unit] |= 1 << effect->EffectIndex;
}
}
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index 38ac5b41c38..189b65a7d1d 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -20,7 +20,6 @@
#include "SpellAuraDefines.h"
#include "SpellInfo.h"
-#include "Unit.h"
class SpellInfo;
struct SpellModifier;
@@ -36,23 +35,25 @@ namespace WorldPackets
}
// forward decl
-class AuraEffect;
class Aura;
-class DynamicObject;
+class AuraEffect;
class AuraScript;
-class ProcInfo;
+class DamageInfo;
+class DispelInfo;
+class DynObjAura;
class ChargeDropEvent;
+class DynamicObject;
+class ProcEventInfo;
+class Unit;
+class UnitAura;
// update aura target map every 500 ms instead of every update - reduce amount of grid searcher calls
#define UPDATE_TARGET_MAP_INTERVAL 500
class TC_GAME_API AuraApplication
{
- friend void Unit::_ApplyAura(AuraApplication * aurApp, uint32 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, uint32 effMask);
+ friend class Unit;
+
private:
Unit* const _target;
Aura* const _base;
@@ -65,21 +66,23 @@ class TC_GAME_API AuraApplication
explicit AuraApplication(Unit* target, Unit* caster, Aura* base, uint32 effMask);
void _Remove();
- private:
+
void _InitFlags(Unit* caster, uint32 effMask);
void _HandleEffect(uint8 effIndex, bool apply);
- public:
+ public:
Unit* GetTarget() const { return _target; }
Aura* GetBase() const { return _base; }
uint8 GetSlot() const { return _slot; }
uint16 GetFlags() const { return _flags; }
uint32 GetEffectMask() const { return _effectMask; }
- bool HasEffect(uint8 effect) const { ASSERT(effect < MAX_SPELL_EFFECTS); return (_effectMask & (1 << effect)) != 0; }
+ bool HasEffect(uint8 effect) const { ASSERT(effect < MAX_SPELL_EFFECTS); return (_effectMask & (1 << effect)) != 0; }
bool IsPositive() const { return (_flags & AFLAG_POSITIVE) != 0; }
bool IsSelfcast() const { return (_flags & AFLAG_NOCASTER) != 0; }
+
uint32 GetEffectsToApply() const { return _effectsToApply; }
+ void UpdateApplyEffectMask(uint32 newEffMask);
void SetRemoveMode(AuraRemoveMode mode) { _removeMode = mode; }
AuraRemoveMode GetRemoveMode() const { return _removeMode; }
@@ -114,16 +117,18 @@ struct AuraLoadEffectInfo
class TC_GAME_API Aura
{
- friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, bool resetPeriodicTimer, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
+ friend class Unit;
+
public:
- typedef std::map<ObjectGuid, AuraApplication*> ApplicationMap;
+ typedef std::unordered_map<ObjectGuid, AuraApplication*> ApplicationMap;
static uint32 BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 availableEffectMask, WorldObject* owner);
- static Aura* TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, bool* refresh = nullptr, bool resetPeriodicTimer = true, ObjectGuid castItemGuid = ObjectGuid::Empty, uint32 castItemId = 0, int32 castItemLevel = -1);
- static Aura* TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid castItemGuid = ObjectGuid::Empty, uint32 castItemId = 0, int32 castItemLevel = -1);
- static Aura* Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32* baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
- Aura(SpellInfo const* spellproto, ObjectGuid castId, WorldObject* owner, Unit* caster, Difficulty castDifficulty, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
- void _InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount);
+ static Aura* TryRefreshStackOrCreate(AuraCreateInfo& createInfo);
+ static Aura* TryCreate(AuraCreateInfo& createInfo);
+ static Aura* Create(AuraCreateInfo& createInfo);
+ explicit Aura(AuraCreateInfo const& createInfo);
+ void _InitEffects(uint32 effMask, Unit* caster, int32 const* baseAmount);
+ void SaveCasterInfo(Unit* caster);
virtual ~Aura();
SpellInfo const* GetSpellInfo() const { return m_spellInfo; }
@@ -138,8 +143,8 @@ class TC_GAME_API Aura
SpellCastVisual GetSpellVisual() const { return m_spellVisual; }
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; }
+ Unit* GetUnitOwner() const { ASSERT(GetType() == UNIT_AURA_TYPE); return m_owner->ToUnit(); }
+ DynamicObject* GetDynobjOwner() const { ASSERT(GetType() == DYNOBJ_AURA_TYPE); return m_owner->ToDynObject(); }
AuraObjectType GetType() const;
@@ -151,8 +156,8 @@ class TC_GAME_API Aura
virtual void FillTargetMap(std::unordered_map<Unit*, uint32>& 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 _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);
@@ -192,13 +197,7 @@ class TC_GAME_API Aura
bool IsPassive() const;
bool IsDeathPersistent() const;
- bool IsRemovedOnShapeLost(Unit* target) const
- {
- return GetCasterGUID() == target->GetGUID()
- && m_spellInfo->Stances
- && !m_spellInfo->HasAttribute(SPELL_ATTR2_NOT_NEED_SHAPESHIFT)
- && !m_spellInfo->HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFT);
- }
+ bool IsRemovedOnShapeLost(Unit* target) const;
bool CanBeSaved() const;
bool IsRemoved() const { return m_isRemoved; }
@@ -231,7 +230,7 @@ class TC_GAME_API Aura
// Helpers for targets
ApplicationMap const& GetApplicationMap() { return m_applications; }
- void GetApplicationList(Unit::AuraApplicationList& applicationList) const;
+ void GetApplicationVector(std::vector<AuraApplication*>& applicationVector) const;
AuraApplication const* 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(); }
@@ -265,15 +264,15 @@ class TC_GAME_API Aura
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 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 CallScriptEffectCalcCritChanceHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, Unit const* victim, float& critChance);
- 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);
+ 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);
void CallScriptEnterLeaveCombatHandlers(AuraApplication const* aurApp, bool isNowInCombat);
// Spell Proc Hooks
bool CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
@@ -284,6 +283,12 @@ class TC_GAME_API Aura
bool CallScriptEffectProcHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo);
void CallScriptAfterEffectProcHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo);
+ UnitAura* ToUnitAura() { if (GetType() == UNIT_AURA_TYPE) return reinterpret_cast<UnitAura*>(this); else return nullptr; }
+ UnitAura const* ToUnitAura() const { if (GetType() == UNIT_AURA_TYPE) return reinterpret_cast<UnitAura const*>(this); else return nullptr; }
+
+ DynObjAura* ToDynObjAura() { if (GetType() == DYNOBJ_AURA_TYPE) return reinterpret_cast<DynObjAura*>(this); else return nullptr; }
+ DynObjAura const* ToDynObjAura() const { if (GetType() == DYNOBJ_AURA_TYPE) return reinterpret_cast<DynObjAura const*>(this); else return nullptr; }
+
template <class Script>
Script* GetScript(std::string const& scriptName) const
{
@@ -333,19 +338,19 @@ class TC_GAME_API Aura
std::chrono::steady_clock::time_point m_lastProcSuccessTime;
private:
- Unit::AuraApplicationList m_removedApplications;
+ std::vector<AuraApplication*> _removedApplications;
AuraEffectVector _effects;
};
class TC_GAME_API UnitAura : public Aura
{
- friend Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
+ friend Aura* Aura::Create(AuraCreateInfo& createInfo);
+ protected:
+ explicit UnitAura(AuraCreateInfo const& createInfo);
public:
- UnitAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
-
- void _ApplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp) override;
- void _UnapplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp) override;
+ 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;
@@ -355,13 +360,18 @@ class TC_GAME_API UnitAura : public Aura
void SetDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; }
DiminishingGroup GetDiminishGroup() const { return m_AuraDRGroup; }
+ void AddStaticApplication(Unit* target, uint32 effMask);
+
private:
DiminishingGroup m_AuraDRGroup; // Diminishing
+ std::unordered_map<ObjectGuid, uint32> _staticApplications; // non-area auras
};
class TC_GAME_API DynObjAura : public Aura
{
- friend Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
+ friend Aura* Aura::Create(AuraCreateInfo& createInfo);
+ protected:
+ explicit DynObjAura(AuraCreateInfo const& createInfo);
public:
DynObjAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, Difficulty castDifficulty, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint32 castItemId, int32 castItemLevel);
@@ -370,16 +380,4 @@ class TC_GAME_API DynObjAura : public Aura
void FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* caster) override;
};
-class TC_GAME_API ChargeDropEvent : public BasicEvent
-{
- friend class Aura;
- protected:
- ChargeDropEvent(Aura* base, AuraRemoveMode mode) : _base(base), _mode(mode) { }
- bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override;
-
- private:
- Aura* _base;
- AuraRemoveMode _mode;
-};
-
#endif
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index cfb0e4703e9..209a1de6d28 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -597,7 +597,8 @@ m_spellValue(new SpellValue(m_spellInfo, caster)), _spellEvent(nullptr)
memset(m_misc.Raw.Data, 0, sizeof(m_misc.Raw.Data));
m_SpellVisual.SpellXSpellVisualID = caster->GetCastSpellXSpellVisualId(m_spellInfo);
m_triggeredByAuraSpell = nullptr;
- m_spellAura = nullptr;
+ _spellAura = nullptr;
+ _dynObjAura = nullptr;
//Auto Shot & Shoot (wand)
m_autoRepeat = m_spellInfo->IsAutoRepeatRangedSpell();
@@ -2457,9 +2458,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
uint32 procVictim = m_procVictim;
uint32 hitMask = PROC_HIT_NONE;
- m_spellAura = nullptr; // Set aura to null for every target-make sure that pointer is not used for unit without aura applied
-
- // Spells with this flag cannot trigger if effect is cast on self
+ // Spells with this flag cannot trigger if effect is cast on self
bool const canEffectTrigger = !m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_PROC) && unitTarget->CanProc() && (CanExecuteTriggersOnHit(mask) || missInfo == SPELL_MISS_IMMUNE || missInfo == SPELL_MISS_IMMUNE2);
Unit* spellHitTarget = nullptr;
@@ -2744,13 +2743,10 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
}
}
- uint32 aura_effmask = 0;
- for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
- if (effect && (effectMask & (1 << effect->EffectIndex) && effect->IsUnitOwnedAuraEffect()))
- aura_effmask |= 1 << effect->EffectIndex;
+ uint32 aura_effmask = Aura::BuildEffectMaskForOwner(m_spellInfo, effectMask, unit);
// Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add
- DiminishingGroup const diminishGroup = m_spellInfo->GetDiminishingReturnsGroupForSpell();
+ DiminishingGroup diminishGroup = m_spellInfo->GetDiminishingReturnsGroupForSpell();
DiminishingLevels diminishLevel = DIMINISHING_LEVEL_1;
if (diminishGroup && aura_effmask)
@@ -2774,19 +2770,36 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
auraSpellEffect->CalcBaseValue(m_originalCaster, unit, m_castItemEntry, m_castItemLevel);
bool refresh = false;
- bool const resetPeriodicTimer = !(_triggeredCastFlags & TRIGGERED_DONT_RESET_PERIODIC_TIMER);
- m_spellAura = Aura::TryRefreshStackOrCreate(m_spellInfo, m_castId, effectMask, unit,
- m_originalCaster, GetCastDifficulty(), basePoints,
- m_CastItem, ObjectGuid::Empty, &refresh, resetPeriodicTimer, ObjectGuid::Empty, m_castItemEntry, m_castItemLevel);
- if (m_spellAura)
+
+ if (!_spellAura)
+ {
+ bool const resetPeriodicTimer = !(_triggeredCastFlags & TRIGGERED_DONT_RESET_PERIODIC_TIMER);
+ uint32 const allAuraEffectMask = Aura::BuildEffectMaskForOwner(m_spellInfo, MAX_EFFECT_MASK, unit);
+
+ AuraCreateInfo createInfo(m_castId, m_spellInfo, GetCastDifficulty(), allAuraEffectMask, unit);
+ createInfo
+ .SetCaster(m_originalCaster)
+ .SetBaseAmount(basePoints)
+ .SetCastItem(m_castItemGUID, m_castItemEntry, m_castItemLevel)
+ .SetPeriodicReset(resetPeriodicTimer)
+ .SetOwnerEffectMask(aura_effmask)
+ .IsRefresh = &refresh;
+
+ if (Aura* aura = Aura::TryRefreshStackOrCreate(createInfo))
+ _spellAura = aura->ToUnitAura();
+ }
+ else
+ _spellAura->AddStaticApplication(unit, aura_effmask);
+
+ if (_spellAura)
{
// Set aura stack amount to desired value
if (m_spellValue->AuraStackAmount > 1)
{
if (!refresh)
- m_spellAura->SetStackAmount(m_spellValue->AuraStackAmount);
+ _spellAura->SetStackAmount(m_spellValue->AuraStackAmount);
else
- m_spellAura->ModStackAmount(m_spellValue->AuraStackAmount);
+ _spellAura->ModStackAmount(m_spellValue->AuraStackAmount);
}
// Now Reduce spell duration using data received at spell hit
@@ -2805,12 +2818,14 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
}
}
- int32 duration = m_spellAura->GetMaxDuration();
+ int32 duration = _spellAura->GetMaxDuration();
// unit is immune to aura if it was diminished to 0 duration
if (!positive && !unit->ApplyDiminishingToDuration(m_spellInfo, duration, m_originalCaster, diminishLevel))
{
- m_spellAura->Remove();
+ _spellAura->Remove();
+ _spellAura = nullptr;
+
bool found = false;
for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect && (effectMask & (1 << effect->EffectIndex) && effect->Effect != SPELL_EFFECT_APPLY_AURA))
@@ -2820,7 +2835,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
}
else
{
- static_cast<UnitAura*>(m_spellAura)->SetDiminishGroup(diminishGroup);
+ _spellAura->SetDiminishGroup(diminishGroup);
duration = m_originalCaster->ModSpellDuration(m_spellInfo, unit, duration, positive, effectMask);
@@ -2837,7 +2852,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
duration = 0;
for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
if (effect)
- if (AuraEffect const* eff = m_spellAura->GetEffect(effect->EffectIndex))
+ if (AuraEffect const* eff = _spellAura->GetEffect(effect->EffectIndex))
if (int32 period = eff->GetPeriod()) // period is hastened by UNIT_MOD_CAST_SPEED
duration = std::max(std::max(origDuration / period, 1) * period, duration);
@@ -2847,12 +2862,11 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
}
}
- if (duration != m_spellAura->GetMaxDuration())
+ if (duration != _spellAura->GetMaxDuration())
{
- m_spellAura->SetMaxDuration(duration);
- m_spellAura->SetDuration(duration);
+ _spellAura->SetMaxDuration(duration);
+ _spellAura->SetDuration(duration);
}
- m_spellAura->_RegisterForTargets();
}
}
}
@@ -3692,8 +3706,6 @@ uint64 Spell::handle_delayed(uint64 t_offset)
void Spell::_handle_immediate_phase()
{
- m_spellAura = nullptr;
-
// handle some immediate features of the spell here
HandleThreatSpells();
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index adaa408b65c..cb34bb00c0c 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -42,6 +42,7 @@ class AuraEffect;
class BasicEvent;
class Corpse;
class DynamicObject;
+class DynObjAura;
class GameObject;
class Item;
class Object;
@@ -53,6 +54,7 @@ class SpellImplicitTargetInfo;
class SpellInfo;
class SpellScript;
class Unit;
+class UnitAura;
class WorldObject;
struct SpellPowerCost;
struct SummonPropertiesEntry;
@@ -769,7 +771,8 @@ class TC_GAME_API Spell
SpellEffectHandleMode effectHandleMode;
SpellEffectInfo const* effectInfo;
// used in effects handlers
- Aura* m_spellAura;
+ UnitAura* _spellAura;
+ DynObjAura* _dynObjAura;
// -------------------------------------------
GameObject* focusObject;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 63319f25b84..0a135d782ad 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -1023,10 +1023,10 @@ void Spell::EffectApplyAura(SpellEffIndex effIndex)
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
return;
- if (!m_spellAura || !unitTarget)
+ if (!_spellAura || !unitTarget)
return;
- ASSERT(unitTarget == m_spellAura->GetOwner());
- m_spellAura->_ApplyEffectForTargets(effIndex);
+
+ _spellAura->_ApplyEffectForTargets(effIndex);
}
void Spell::EffectApplyAreaAura(SpellEffIndex effIndex)
@@ -1034,10 +1034,10 @@ void Spell::EffectApplyAreaAura(SpellEffIndex effIndex)
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
return;
- if (!m_spellAura || !unitTarget)
+ if (!_spellAura || !unitTarget)
return;
- ASSERT (unitTarget == m_spellAura->GetOwner());
- m_spellAura->_ApplyEffectForTargets(effIndex);
+
+ _spellAura->_ApplyEffectForTargets(effIndex);
}
void Spell::EffectUnlearnSpecialization(SpellEffIndex /*effIndex*/)
@@ -1446,32 +1446,44 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex)
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
return;
- if (!m_spellAura)
+ // only handle at last effect
+ for (uint8 i = effIndex + 1; i < MAX_SPELL_EFFECTS; ++i)
+ if (SpellEffectInfo const* otherEffect = m_spellInfo->GetEffect(i))
+ if (otherEffect && otherEffect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA))
+ return;
+
+ ASSERT(!_dynObjAura);
+
+ Unit* caster = m_caster->GetEntry() == WORLD_TRIGGER ? m_originalCaster : m_caster;
+ float radius = effectInfo->CalcRadius(caster);
+
+ // Caster not in world, might be spell triggered from aura removal
+ if (!caster->IsInWorld())
+ return;
+
+ DynamicObject* dynObj = new DynamicObject(false);
+ if (!dynObj->CreateDynamicObject(caster->GetMap()->GenerateLowGuid<HighGuid::DynamicObject>(), caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL, m_SpellVisual))
{
- Unit* caster = m_caster->GetEntry() == WORLD_TRIGGER ? m_originalCaster : m_caster;
- float radius = effectInfo->CalcRadius(caster);
+ delete dynObj;
+ return;
+ }
- // Caster not in world, might be spell triggered from aura removal
- if (!caster->IsInWorld())
- return;
- DynamicObject* dynObj = new DynamicObject(false);
- if (!dynObj->CreateDynamicObject(caster->GetMap()->GenerateLowGuid<HighGuid::DynamicObject>(), caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL, m_SpellVisual))
- {
- delete dynObj;
- return;
- }
+ AuraCreateInfo createInfo(m_castId, m_spellInfo, GetCastDifficulty(), MAX_EFFECT_MASK, dynObj);
+ createInfo
+ .SetCaster(caster)
+ .SetBaseAmount(m_spellValue->EffectBasePoints)
+ .SetCastItem(m_castItemGUID, m_castItemEntry, m_castItemLevel);
- if (Aura* aura = Aura::TryCreate(m_spellInfo, m_castId, MAX_EFFECT_MASK, dynObj, caster, GetCastDifficulty(), &m_spellValue->EffectBasePoints[0], nullptr, ObjectGuid::Empty, ObjectGuid::Empty, m_castItemEntry, m_castItemLevel))
- {
- m_spellAura = aura;
- m_spellAura->_RegisterForTargets();
- }
- else
- return;
+ if (Aura* aura = Aura::TryCreate(createInfo))
+ {
+ _dynObjAura = aura->ToDynObjAura();
+ _dynObjAura->_RegisterForTargets();
}
+ else
+ return;
- ASSERT(m_spellAura->GetDynobjOwner());
- m_spellAura->_ApplyEffectForTargets(effIndex);
+ ASSERT(_dynObjAura->GetDynobjOwner());
+ _dynObjAura->_ApplyEffectForTargets(effIndex);
}
void Spell::EffectEnergize(SpellEffIndex /*effIndex*/)
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 7213776011f..577273d4ff7 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -21,6 +21,7 @@
#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "SpellMgr.h"
+#include "Unit.h"
#include <sstream>
#include <string>
@@ -648,18 +649,22 @@ void SpellScript::SetHitHeal(int32 heal)
m_spell->m_healing = heal;
}
-Aura* SpellScript::GetHitAura() const
+Aura* SpellScript::GetHitAura(bool dynObjAura /*= false*/) const
{
if (!IsInTargetHook())
{
TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::GetHitAura was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
return nullptr;
}
- if (!m_spell->m_spellAura)
- return nullptr;
- if (m_spell->m_spellAura->IsRemoved())
+
+ Aura* aura = m_spell->_spellAura;
+ if (dynObjAura)
+ aura = m_spell->_dynObjAura;
+
+ if (!aura || aura->IsRemoved())
return nullptr;
- return m_spell->m_spellAura;
+
+ return aura;
}
void SpellScript::PreventHitAura()
@@ -669,8 +674,10 @@ void SpellScript::PreventHitAura()
TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::PreventHitAura was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
return;
}
- if (m_spell->m_spellAura)
- m_spell->m_spellAura->Remove();
+ if (UnitAura* aura = m_spell->_spellAura)
+ aura->Remove();
+ if (DynObjAura* aura = m_spell->_dynObjAura)
+ aura->Remove();
}
void SpellScript::PreventHitEffect(SpellEffIndex effIndex)
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 5e5e5285e49..575e5721bbe 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -473,7 +473,7 @@ class TC_GAME_API SpellScript : public _SpellScript
void PreventHitHeal() { SetHitHeal(0); }
Spell* GetSpell() const { return m_spell; }
// returns current spell hit target aura
- Aura* GetHitAura() const;
+ Aura* GetHitAura(bool dynObjAura = false) const;
// prevents applying aura on current spell hit target
void PreventHitAura();
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 95dcf69e05d..b96b66c0229 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -323,7 +323,10 @@ public:
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, target->GetMap()->GetDifficultyID()))
{
ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, target->GetMapId(), spellId, target->GetMap()->GenerateLowGuid<HighGuid::Cast>());
- Aura::TryRefreshStackOrCreate(spellInfo, castId, MAX_EFFECT_MASK, target, target, target->GetMap()->GetDifficultyID());
+ AuraCreateInfo createInfo(castId, spellInfo, target->GetMap()->GetDifficultyID(), MAX_EFFECT_MASK, target);
+ createInfo.SetCaster(target);
+
+ Aura::TryRefreshStackOrCreate(createInfo);
}
return true;
diff --git a/src/server/scripts/Spells/spell_dh.cpp b/src/server/scripts/Spells/spell_dh.cpp
index 406456513e8..e76618661fc 100644
--- a/src/server/scripts/Spells/spell_dh.cpp
+++ b/src/server/scripts/Spells/spell_dh.cpp
@@ -25,6 +25,7 @@
#include "SpellAuraEffects.h"
#include "SpellMgr.h"
#include "SpellScript.h"
+#include "Unit.h"
enum DemonHunterSpells
{
diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp
index 59eea2cc385..b7bf9fbbdbd 100644
--- a/src/server/scripts/Spells/spell_paladin.cpp
+++ b/src/server/scripts/Spells/spell_paladin.cpp
@@ -813,8 +813,8 @@ class spell_pal_light_s_beacon : public SpellScriptLoader
{
if ((*itr)->GetId() == SPELL_PALADIN_BEACON_OF_LIGHT)
{
- std::list<AuraApplication*> applications;
- (*itr)->GetApplicationList(applications);
+ std::vector<AuraApplication*> applications;
+ (*itr)->GetApplicationVector(applications);
if (!applications.empty())
{
CastSpellExtraArgs args(aurEff);