Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
SpellAuras.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "CellImpl.h"
7#include "Common.h"
8#include "DynamicObject.h"
9#include "GridNotifiers.h"
10#include "GridNotifiersImpl.h"
11#include "Log.h"
12#include "ObjectAccessor.h"
13#include "ObjectMgr.h"
14#include "Opcodes.h"
15#include "Player.h"
16#include "ScriptMgr.h"
17#include "Spell.h"
18#include "SpellAuraEffects.h"
19#include "SpellMgr.h"
20#include "SpellScript.h"
21#include "Unit.h"
22#include "Util.h"
23#include "Vehicle.h"
24#include "WorldPacket.h"
25
26AuraApplication::AuraApplication(Unit* target, Unit* caster, Aura* aura, uint32 effMask) :
29{
30 ASSERT(GetTarget() && GetBase());
31
32 if (GetBase()->CanBeSentToClient())
33 {
34 // Try find slot for aura
35 uint8 slot = MAX_AURAS;
36 // Lookup for auras already applied from spell
37 if (AuraApplication* foundAura = GetTarget()->GetAuraApplication(GetBase()->GetId(), GetBase()->GetCasterGUID(), GetBase()->GetCastItemGUID()))
38 {
39 // allow use single slot only by auras from same caster
40 slot = foundAura->GetSlot();
41 }
42 else
43 {
44 Unit::VisibleAuraMap const* visibleAuras = GetTarget()->GetVisibleAuras();
45 // lookup for free slots in units visibleAuras
46 Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(0);
47 for (uint32 freeSlot = 0; freeSlot < MAX_AURAS; ++itr, ++freeSlot)
48 {
49 if (itr == visibleAuras->end() || itr->first != freeSlot)
50 {
51 slot = freeSlot;
52 break;
53 }
54 }
55 }
56
57 // Register Visible Aura
58 if (slot < MAX_AURAS)
59 {
60 _slot = slot;
61 GetTarget()->SetVisibleAura(slot, this);
63 SF_LOG_DEBUG("spells", "Aura: %u Effect: %d put to unit visible auras slot: %u", GetBase()->GetId(), GetEffectMask(), slot);
64 }
65 else
66 SF_LOG_DEBUG("spells", "Aura: %u Effect: %d could not find empty unit visible slot", GetBase()->GetId(), GetEffectMask());
67 }
68
69 _InitFlags(caster, effMask);
70}
71
72Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= NULL*/, Item* castItem /*= NULL*/, uint64 casterGUID /*= 0*/, bool* refresh /*= NULL*/)
73{
74 ASSERT(spellproto);
75 ASSERT(owner);
76 ASSERT(caster || casterGUID);
77 ASSERT(tryEffMask <= MAX_EFFECT_MASK);
78 if (refresh)
79 *refresh = false;
80 uint32 effMask = Aura::BuildEffectMaskForOwner(spellproto, tryEffMask, owner);
81 if (!effMask)
82 return NULL;
83 if (Aura* foundAura = owner->ToUnit()->_TryStackingOrRefreshingExistingAura(spellproto, effMask, caster, baseAmount, castItem, casterGUID))
84 {
85 // we've here aura, which script triggered removal after modding stack amount
86 // check the state here, so we won't create new Aura object
87 if (foundAura->IsRemoved())
88 return NULL;
89
90 if (refresh)
91 *refresh = true;
92 return foundAura;
93 }
94 else
95 return Create(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID);
96}
97
98Aura* Aura::TryCreate(SpellInfo const* spellproto, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= NULL*/, Item* castItem /*= NULL*/, uint64 casterGUID /*= 0*/)
99{
100 ASSERT(spellproto);
101 ASSERT(owner);
102 ASSERT(caster || casterGUID);
103 ASSERT(tryEffMask <= MAX_EFFECT_MASK);
104 uint32 effMask = Aura::BuildEffectMaskForOwner(spellproto, tryEffMask, owner);
105 if (!effMask)
106 return NULL;
107 return Create(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID);
108}
109
110Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, uint64 casterGUID)
111{
112 ASSERT(effMask);
113 ASSERT(spellproto);
114 ASSERT(owner);
115 ASSERT(caster || casterGUID);
116 ASSERT(effMask <= MAX_EFFECT_MASK);
117 // try to get caster of aura
118 if (casterGUID)
119 {
120 if (owner->GetGUID() == casterGUID)
121 caster = owner->ToUnit();
122 else
123 caster = ObjectAccessor::GetUnit(*owner, casterGUID);
124 }
125 else
126 casterGUID = caster->GetGUID();
127
128 // check if aura can be owned by owner
129 if (owner->isType(TYPEMASK_UNIT))
130 if (!owner->IsInWorld() || ((Unit*)owner)->IsDuringRemoveFromWorld())
131 // owner not in world so don't allow to own not self casted single target auras
132 if (casterGUID != owner->GetGUID() && spellproto->IsSingleTarget())
133 return NULL;
134
135 Aura* aura = NULL;
136 switch (owner->GetTypeId())
137 {
140 aura = new UnitAura(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID);
141 break;
143 aura = new DynObjAura(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID);
144 break;
145 default:
146 ASSERT(false);
147 return NULL;
148 }
149 // aura can be removed in Unit::_AddAura call
150 if (aura->IsRemoved())
151 return NULL;
152 return aura;
153}
154
155Aura::Aura(SpellInfo const* spellproto, WorldObject* owner, Unit* caster, Item* castItem, uint64 casterGUID) :
156 m_spellInfo(spellproto), m_casterGuid(casterGUID ? casterGUID : caster->GetGUID()),
157 m_castItemGuid(castItem ? castItem->GetGUID() : 0), m_applyTime(time(NULL)),
159 m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1),
160 m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false)
161{
166 // m_casterLevel = cast item level/caster level, caster level should be saved to db, confirmed with sniffs
167}
168
169AuraScript* Aura::GetScriptByName(std::string const& scriptName) const
170{
171 for (std::list<AuraScript*>::const_iterator itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
172 if ((*itr)->_GetScriptName()->compare(scriptName) == 0)
173 return *itr;
174 return NULL;
175}
176
178{
179 // unload scripts
180 while (!m_loadedScripts.empty())
181 {
182 std::list<AuraScript*>::iterator itr = m_loadedScripts.begin();
183 (*itr)->_Unload();
184 delete (*itr);
185 m_loadedScripts.erase(itr);
186 }
187
188 // free effects memory
189 for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
190 delete m_effects[i];
191
192 ASSERT(m_applications.empty());
194}
195
197{
198 if (GetOwner()->GetGUID() == GetCasterGUID())
199 return GetUnitOwner();
201 return aurApp->GetTarget();
202
204}
205
210
211UnitAura::UnitAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, uint64 casterGUID)
212 : Aura(spellproto, owner, caster, castItem, casterGUID), m_AuraDRGroup(DiminishingGroup::DIMINISHING_NONE)
213{
214 LoadScripts();
215 _InitEffects(effMask, caster, baseAmount);
216 GetUnitOwner()->_AddAura(this, caster);
217}
218
219void UnitAura::_ApplyForTarget(Unit* target, Unit* caster, AuraApplication* aurApp)
220{
221 Aura::_ApplyForTarget(target, caster, aurApp);
222
223 // register aura diminishing on apply
226 target->ApplyDiminishingAura(group, true);
227}
228
230{
231 Aura::_UnapplyForTarget(target, caster, aurApp);
232
233 // unregister aura diminishing (and store last time)
236 target->ApplyDiminishingAura(group, false);
237}
238
240{
241 if (IsRemoved())
242 return;
243 GetUnitOwner()->RemoveOwnedAura(this, removeMode);
244}
245
246void UnitAura::FillTargetMap(std::map<Unit*, uint32>& targets, Unit* caster)
247{
248 for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
249 {
250 if (!HasEffect(effIndex))
251 continue;
252 UnitList targetList;
253 // non-area aura
254 if (GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_APPLY_AURA)
255 {
256 targetList.push_back(GetUnitOwner());
257 }
258 else
259 {
260 float radius = GetSpellInfo()->Effects[effIndex].CalcRadius(caster);
261
262 if (!GetUnitOwner()->HasUnitState(UNIT_STATE_ISOLATED))
263 {
264 switch (GetSpellInfo()->Effects[effIndex].Effect)
265 {
268 {
269 targetList.push_back(GetUnitOwner());
272 GetUnitOwner()->VisitNearbyObject(radius, searcher);
273 break;
274 }
276 {
277 targetList.push_back(GetUnitOwner());
280 GetUnitOwner()->VisitNearbyObject(radius, searcher);
281 break;
282 }
284 {
285 Skyfire::AnyAoETargetUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius); // No GetCharmer in searcher
287 GetUnitOwner()->VisitNearbyObject(radius, searcher);
288 break;
289 }
291 targetList.push_back(GetUnitOwner());
292 // no break
294 {
295 if (Unit* owner = GetUnitOwner()->GetCharmerOrOwner())
296 if (GetUnitOwner()->IsWithinDistInMap(owner, radius))
297 targetList.push_back(owner);
298 break;
299 }
300 }
301 }
302 }
303
304 for (UnitList::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
305 {
306 std::map<Unit*, uint32>::iterator existing = targets.find(*itr);
307 if (existing != targets.end())
308 existing->second |= 1 << effIndex;
309 else
310 targets[*itr] = 1 << effIndex;
311 }
312 }
313}
314
315DynObjAura::DynObjAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, uint64 casterGUID)
316 : Aura(spellproto, owner, caster, castItem, casterGUID)
317{
318 LoadScripts();
320 ASSERT(GetDynobjOwner()->IsInWorld());
321 ASSERT(GetDynobjOwner()->GetMap() == caster->GetMap());
322 _InitEffects(effMask, caster, baseAmount);
323 GetDynobjOwner()->SetAura(this);
324}
325
327{
328 if (IsRemoved())
329 return;
330 _Remove(removeMode);
331}
332
333void DynObjAura::FillTargetMap(std::map<Unit*, uint32>& targets, Unit* /*caster*/)
334{
335 Unit* dynObjOwnerCaster = GetDynobjOwner()->GetCaster();
336 float radius = GetDynobjOwner()->GetRadius();
337
338 for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
339 {
340 if (!HasEffect(effIndex))
341 continue;
342 UnitList targetList;
343 if (GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == TARGET_DEST_DYNOBJ_ALLY
344 || GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == TARGET_UNIT_DEST_AREA_ALLY)
345 {
346 Skyfire::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius);
348 GetDynobjOwner()->VisitNearbyObject(radius, searcher);
349 }
350 else
351 {
352 Skyfire::AnyAoETargetUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius);
354 GetDynobjOwner()->VisitNearbyObject(radius, searcher);
355 }
356
357 for (UnitList::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
358 {
359 std::map<Unit*, uint32>::iterator existing = targets.find(*itr);
360 if (existing != targets.end())
361 existing->second |= 1 << effIndex;
362 else
363 targets[*itr] = 1 << effIndex;
364 }
365 }
366}
#define MAX_EFFECT_MASK
#define MAX_SPELL_EFFECTS
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
#define ASSERT
Definition Errors.h:29
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
@ TYPEID_PLAYER
Definition Object.h:55
@ TYPEID_DYNAMICOBJECT
Definition Object.h:57
@ TYPEID_UNIT
Definition Object.h:54
@ TYPEMASK_UNIT
Definition Object.h:40
DiminishingGroup
@ SPELL_EFFECT_APPLY_AREA_AURA_PARTY
@ SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
@ SPELL_EFFECT_APPLY_AREA_AURA_PET
@ SPELL_EFFECT_APPLY_AREA_AURA_RAID
@ SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
@ SPELL_EFFECT_APPLY_AURA
@ SPELL_EFFECT_APPLY_AREA_AURA_OWNER
@ TARGET_UNIT_DEST_AREA_ALLY
@ TARGET_DEST_DYNOBJ_ALLY
#define MAX_AURAS
@ AFLAG_NONE
AuraObjectType
@ DYNOBJ_AURA_TYPE
@ UNIT_AURA_TYPE
AuraRemoveMode
Definition Unit.h:405
@ AURA_REMOVE_NONE
Definition Unit.h:406
std::list< Unit * > UnitList
Definition Unit.h:370
@ UNIT_STATE_ISOLATED
Definition Unit.h:525
Unit * GetTarget() const
Definition SpellAuras.h:54
uint32 _effectsToApply
Definition SpellAuras.h:41
bool _needClientUpdate
Definition SpellAuras.h:44
Aura *const _base
Definition SpellAuras.h:37
void _InitFlags(Unit *caster, uint32 effMask)
AuraApplication(Unit *target, Unit *caster, Aura *base, uint32 effMask)
Aura * GetBase() const
Definition SpellAuras.h:55
void SetNeedClientUpdate()
Definition SpellAuras.h:68
uint32 GetEffectMask() const
Definition SpellAuras.h:59
Unit *const _target
Definition SpellAuras.h:36
AuraRemoveMode _removeMode
Definition SpellAuras.h:38
virtual void _UnapplyForTarget(Unit *target, Unit *caster, AuraApplication *auraApp)
uint64 GetCasterGUID() const
Definition SpellAuras.h:91
const AuraApplication * GetApplicationOfTarget(uint64 guid) const
Definition SpellAuras.h:176
AuraEffect * m_effects[MAX_SPELL_EFFECTS]
Definition SpellAuras.h:246
int32 m_maxDuration
Definition SpellAuras.h:238
Unit * GetUnitOwner() const
Definition SpellAuras.h:94
time_t const m_applyTime
Definition SpellAuras.h:235
std::list< AuraScript * > m_loadedScripts
Definition SpellAuras.h:228
DynamicObject * GetDynobjOwner() const
Definition SpellAuras.h:95
uint8 m_stackAmount
Definition SpellAuras.h:244
bool HasEffect(uint8 effIndex) const
Definition SpellAuras.h:166
int32 m_duration
Definition SpellAuras.h:239
bool IsRemoved() const
Definition SpellAuras.h:154
WorldObject * GetOwner() const
Definition SpellAuras.h:93
static Aura * TryCreate(SpellInfo const *spellproto, uint32 effMask, WorldObject *owner, Unit *caster, int32 *baseAmount=NULL, Item *castItem=NULL, uint64 casterGUID=0)
ApplicationMap m_applications
Definition SpellAuras.h:247
Unit * GetCaster() const
uint64 const m_casterGuid
Definition SpellAuras.h:233
static Aura * TryRefreshStackOrCreate(SpellInfo const *spellproto, uint32 tryEffMask, WorldObject *owner, Unit *caster, int32 *baseAmount=NULL, Item *castItem=NULL, uint64 casterGUID=0, bool *refresh=NULL)
static Aura * Create(SpellInfo const *spellproto, uint32 effMask, WorldObject *owner, Unit *caster, int32 *baseAmount, Item *castItem, uint64 casterGUID)
void _InitEffects(uint32 effMask, Unit *caster, int32 *baseAmount)
int32 CalcMaxDuration() const
Definition SpellAuras.h:117
SpellInfo const *const m_spellInfo
Definition SpellAuras.h:232
AuraObjectType GetType() const
AuraScript * GetScriptByName(std::string const &scriptName) const
WorldObject *const m_owner
Definition SpellAuras.h:236
SpellInfo const * GetSpellInfo() const
Definition SpellAuras.h:87
uint64 const m_castItemGuid
Definition SpellAuras.h:234
uint8 const m_casterLevel
Definition SpellAuras.h:242
virtual ~Aura()
void _DeleteRemovedApplications()
Aura(SpellInfo const *spellproto, WorldObject *owner, Unit *caster, Item *castItem, uint64 casterGUID)
virtual void _ApplyForTarget(Unit *target, Unit *caster, AuraApplication *auraApp)
uint8 CalcMaxCharges() const
Definition SpellAuras.h:129
bool m_isUsingCharges
Definition SpellAuras.h:251
static uint32 BuildEffectMaskForOwner(SpellInfo const *spellProto, uint32 avalibleEffectMask, WorldObject *owner)
bool m_isRemoved
Definition SpellAuras.h:249
int32 m_updateTargetMapInterval
Definition SpellAuras.h:240
bool m_isSingleTarget
Definition SpellAuras.h:250
uint8 m_procCharges
Definition SpellAuras.h:243
void _Remove(AuraRemoveMode removeMode)
DynObjAura(SpellInfo const *spellproto, uint32 effMask, WorldObject *owner, Unit *caster, int32 *baseAmount, Item *castItem, uint64 casterGUID)
void Remove(AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
void FillTargetMap(std::map< Unit *, uint32 > &targets, Unit *caster)
void SetAura(Aura *aura)
Unit * GetCaster() const
float GetRadius() const
Definition Item.h:202
static Unit * GetUnit(WorldObject const &, uint64 guid)
uint64 GetGUID() const
Definition Object.h:119
bool IsInWorld() const
Definition Object.h:114
TypeID GetTypeId() const
Definition Object.h:131
bool isType(uint16 mask) const
Definition Object.h:132
Unit * ToUnit()
Definition Object.h:210
float CalcRadius(Unit *caster=NULL, Spell *=NULL) const
SpellEffectInfo Effects[MAX_SPELL_EFFECTS]
Definition SpellInfo.h:255
bool IsSingleTarget() const
void Remove(AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
DiminishingGroup m_AuraDRGroup
Definition SpellAuras.h:275
void _ApplyForTarget(Unit *target, Unit *caster, AuraApplication *aurApp)
DiminishingGroup GetDiminishGroup() const
Definition SpellAuras.h:272
void FillTargetMap(std::map< Unit *, uint32 > &targets, Unit *caster)
void _UnapplyForTarget(Unit *target, Unit *caster, AuraApplication *aurApp)
UnitAura(SpellInfo const *spellproto, uint32 effMask, WorldObject *owner, Unit *caster, int32 *baseAmount, Item *castItem, uint64 casterGUID)
Definition Unit.h:1367
void RemoveOwnedAura(AuraMap::iterator &i, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Aura * _TryStackingOrRefreshingExistingAura(SpellInfo const *newAura, uint32 effMask, Unit *caster, int32 *baseAmount=NULL, Item *castItem=NULL, uint64 casterGUID=0)
std::map< uint8, AuraApplication * > VisibleAuraMap
Definition Unit.h:1389
void _AddAura(UnitAura *aura, Unit *caster)
void SetVisibleAura(uint8 slot, AuraApplication *aur)
Definition Unit.cpp:500
VisibleAuraMap const * GetVisibleAuras()
Definition Unit.h:2471
void ApplyDiminishingAura(DiminishingGroup group, bool apply)
Map * GetMap() const
Definition Object.h:740
void VisitNearbyObject(float const &radius, NOTIFIER &notifier) const
Definition Object.h:782