TrinityCore
Loading...
Searching...
No Matches
SpellAuras.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Common.h"
19#include "CellImpl.h"
20#include "Config.h"
21#include "DynamicObject.h"
22#include "GridNotifiersImpl.h"
23#include "Item.h"
24#include "Log.h"
25#include "ObjectAccessor.h"
26#include "ObjectMgr.h"
27#include "Opcodes.h"
28#include "Player.h"
29#include "ScriptMgr.h"
30#include "Spell.h"
31#include "SpellAuraEffects.h"
32#include "SpellHistory.h"
33#include "SpellMgr.h"
34#include "SpellScript.h"
35#include "Unit.h"
36#include "Util.h"
37#include "Vehicle.h"
38#include "World.h"
39#include "WorldPacket.h"
40
41AuraCreateInfo::AuraCreateInfo(SpellInfo const* spellInfo, uint8 auraEffMask, WorldObject* owner) :
42 _spellInfo(spellInfo), _auraEffectMask(auraEffMask), _owner(owner)
43{
44 ASSERT(spellInfo);
45 ASSERT(auraEffMask);
46 ASSERT(owner);
47
48 ASSERT(auraEffMask <= MAX_EFFECT_MASK);
49}
50
51AuraApplication::AuraApplication(Unit* target, Unit* caster, Aura* aura, uint8 effMask) :
52_target(target), _base(aura), _removeMode(AURA_REMOVE_NONE), _slot(MAX_AURAS),
53_flags(AFLAG_NONE), _effectsToApply(effMask), _needClientUpdate(false)
54{
55 ASSERT(GetTarget() && GetBase());
56
57 if (GetBase()->CanBeSentToClient())
58 {
59 // Try find slot for aura
60 uint8 slot = MAX_AURAS;
61 // Lookup for auras already applied from spell
62 if (AuraApplication * foundAura = GetTarget()->GetAuraApplication(GetBase()->GetId(), GetBase()->GetCasterGUID(), GetBase()->GetCastItemGUID()))
63 {
64 // allow use single slot only by auras from same caster
65 slot = foundAura->GetSlot();
66 }
67 else
68 {
69 Unit::VisibleAuraMap const& visibleAuras = GetTarget()->GetVisibleAuras();
70 // lookup for free slots in units visibleAuras
71 Unit::VisibleAuraMap::const_iterator itr = visibleAuras.find(0);
72 for (uint32 freeSlot = 0; freeSlot < MAX_AURAS; ++itr, ++freeSlot)
73 {
74 if (itr == visibleAuras.end() || itr->first != freeSlot)
75 {
76 slot = freeSlot;
77 break;
78 }
79 }
80 }
81
82 // Register Visible Aura
83 if (slot < MAX_AURAS)
84 {
85 _slot = slot;
86 GetTarget()->SetVisibleAura(slot, this);
88 TC_LOG_DEBUG("spells", "Aura: {} Effect: {} put to unit visible auras slot: {}", GetBase()->GetId(), GetEffectMask(), slot);
89 }
90 else
91 TC_LOG_ERROR("spells", "Aura: {} Effect: {} could not find empty unit visible slot", GetBase()->GetId(), GetEffectMask());
92 }
93
94 _InitFlags(caster, effMask);
95}
96
98{
99 uint8 slot = GetSlot();
100
101 if (slot >= MAX_AURAS)
102 return;
103
104 if (AuraApplication * foundAura = _target->GetAuraApplication(GetBase()->GetId(), GetBase()->GetCasterGUID(), GetBase()->GetCastItemGUID()))
105 {
106 // Reuse visible aura slot by aura which is still applied - prevent storing dead pointers
107 if (slot == foundAura->GetSlot())
108 {
109 if (GetTarget()->GetVisibleAura(slot) == this)
110 {
111 GetTarget()->SetVisibleAura(slot, foundAura);
112 foundAura->SetNeedClientUpdate();
113 }
114 // set not valid slot for aura - prevent removing other visible aura
115 slot = MAX_AURAS;
116 }
117 }
118
119 // update for out of range group members
120 if (slot < MAX_AURAS)
121 {
123 ClientUpdate(true);
124 }
125}
126
128{
129 // mark as selfcast if needed
131
132 // aura is cast by self or an enemy
133 // one negative effect and we know aura is negative
134 if (IsSelfcast() || !caster || !caster->IsFriendlyTo(GetTarget()))
135 {
136 bool negativeFound = false;
137 for (uint8 i = 0; i < GetBase()->GetSpellInfo()->GetEffects().size(); ++i)
138 {
139 if (((1 << i) & effMask) && !GetBase()->GetSpellInfo()->IsPositiveEffect(i))
140 {
141 negativeFound = true;
142 break;
143 }
144 }
145 _flags |= negativeFound ? AFLAG_NEGATIVE : AFLAG_POSITIVE;
146 }
147 // aura is cast by friend
148 // one positive effect and we know aura is positive
149 else
150 {
151 bool positiveFound = false;
152 for (uint8 i = 0; i < GetBase()->GetSpellInfo()->GetEffects().size(); ++i)
153 {
154 if (((1 << i) & effMask) && GetBase()->GetSpellInfo()->IsPositiveEffect(i))
155 {
156 positiveFound = true;
157 break;
158 }
159 }
160 _flags |= positiveFound ? AFLAG_POSITIVE : AFLAG_NEGATIVE;
161 }
162}
163
164void AuraApplication::_HandleEffect(uint8 effIndex, bool apply)
165{
166 AuraEffect* aurEff = GetBase()->GetEffect(effIndex);
167 ASSERT(aurEff);
168 ASSERT(HasEffect(effIndex) == (!apply));
169 ASSERT((1<<effIndex) & _effectsToApply);
170 TC_LOG_DEBUG("spells", "AuraApplication::_HandleEffect: {}, apply: {}: amount: {}", aurEff->GetAuraType(), apply, aurEff->GetAmount());
171
172 if (apply)
173 {
174 ASSERT(!(_flags & (1<<effIndex)));
175 _flags |= 1<<effIndex;
176 aurEff->HandleEffect(this, AURA_EFFECT_HANDLE_REAL, true);
177 }
178 else
179 {
180 ASSERT(_flags & (1<<effIndex));
181 _flags &= ~(1<<effIndex);
182 aurEff->HandleEffect(this, AURA_EFFECT_HANDLE_REAL, false);
183
184 // Remove all triggered by aura spells vs unlimited duration
186 }
188}
189
190void AuraApplication::UpdateApplyEffectMask(uint8 newEffMask, bool canHandleNewEffects)
191{
192 if (_effectsToApply == newEffMask)
193 return;
194
195 uint8 removeEffMask = (_effectsToApply ^ newEffMask) & (~newEffMask);
196 uint8 addEffMask = (_effectsToApply ^ newEffMask) & (~_effectsToApply);
197
198 // quick check, removes application completely
199 if (removeEffMask == _effectsToApply && !addEffMask)
200 {
202 return;
203 }
204
205 // update real effects only if they were applied already
206 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
207 if (HasEffect(i) && (removeEffMask & (1 << i)))
208 _HandleEffect(i, false);
209
210 _effectsToApply = newEffMask;
211
212 if (canHandleNewEffects)
213 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
214 if (addEffMask & (1 << i))
215 _HandleEffect(i, true);
216}
217
218void AuraApplication::BuildUpdatePacket(ByteBuffer& data, bool remove) const
219{
220 data << uint8(_slot);
221
222 if (remove)
223 {
225 data << uint32(0);
226 return;
227 }
229
230 Aura const* aura = GetBase();
231 data << uint32(aura->GetId());
235 data << uint8(flags);
236 data << uint8(aura->GetCasterLevel());
237 // send stack amount for aura which could be stacked (never 0 - causes incorrect display) or charges
238 // stack amount has priority over charges (checked on retail with spell 50262)
239 data << uint8(aura->GetSpellInfo()->StackAmount ? aura->GetStackAmount() : aura->GetCharges());
240
241 if (!(flags & AFLAG_CASTER))
242 data << aura->GetCasterGUID().WriteAsPacked();
243
244 if (flags & AFLAG_DURATION)
245 {
246 data << uint32(aura->GetMaxDuration());
247 data << uint32(aura->GetDuration());
248 }
249}
250
252{
253 _needClientUpdate = false;
254
256 data << GetTarget()->GetPackGUID();
257 BuildUpdatePacket(data, remove);
258
259 _target->SendMessageToSet(&data, true);
260}
261
263{
264 std::stringstream sstr;
265 sstr << "Base: " << (GetBase() ? GetBase()->GetDebugInfo() : "NULL")
266 << "\nTarget: " << (GetTarget() ? GetTarget()->GetDebugInfo() : "NULL");
267 return sstr.str();
268}
269
270uint8 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint8 availableEffectMask, WorldObject* owner)
271{
272 ASSERT_NODEBUGINFO(spellProto);
273 ASSERT_NODEBUGINFO(owner);
274 uint8 effMask = 0;
275 switch (owner->GetTypeId())
276 {
277 case TYPEID_UNIT:
278 case TYPEID_PLAYER:
279 for (SpellEffectInfo const& spellEffectInfo : spellProto->GetEffects())
280 {
281 if (spellEffectInfo.IsUnitOwnedAuraEffect())
282 effMask |= 1 << spellEffectInfo.EffectIndex;
283 }
284 break;
286 for (SpellEffectInfo const& spellEffectInfo : spellProto->GetEffects())
287 {
288 if (spellEffectInfo.IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA))
289 effMask |= 1 << spellEffectInfo.EffectIndex;
290 }
291 break;
292 default:
293 ABORT();
294 break;
295 }
296
297 return effMask & availableEffectMask;
298}
299
300Aura* Aura::TryRefreshStackOrCreate(AuraCreateInfo& createInfo, bool updateEffectMask)
301{
302 ASSERT_NODEBUGINFO(createInfo.Caster || !createInfo.CasterGUID.IsEmpty());
303
304 if (createInfo.IsRefresh)
305 *createInfo.IsRefresh = false;
306
307 createInfo._auraEffectMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, createInfo._auraEffectMask, createInfo._owner);
308 createInfo._targetEffectMask &= createInfo._auraEffectMask;
309
310 uint8 effMask = createInfo._auraEffectMask;
311 if (createInfo._targetEffectMask)
312 effMask = createInfo._targetEffectMask;
313
314 if (!effMask)
315 return nullptr;
316
317 if (Aura* foundAura = createInfo._owner->ToUnit()->_TryStackingOrRefreshingExistingAura(createInfo))
318 {
319 // we've here aura, which script triggered removal after modding stack amount
320 // check the state here, so we won't create new Aura object
321 if (foundAura->IsRemoved())
322 return nullptr;
323
324 if (createInfo.IsRefresh)
325 *createInfo.IsRefresh = true;
326
327 // add owner
328 Unit* unit = createInfo._owner->ToUnit();
329
330 // check effmask on owner application (if existing)
331 if (updateEffectMask)
332 if (AuraApplication* aurApp = foundAura->GetApplicationOfTarget(unit->GetGUID()))
333 aurApp->UpdateApplyEffectMask(effMask, false);
334 return foundAura;
335 }
336 else
337 return Create(createInfo);
338}
339
341{
342 uint8 effMask = createInfo._auraEffectMask;
343 if (createInfo._targetEffectMask)
344 effMask = createInfo._targetEffectMask;
345
346 effMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, effMask, createInfo._owner);
347 if (!effMask)
348 return nullptr;
349
350 return Create(createInfo);
351}
352
354{
355 // try to get caster of aura
356 if (!createInfo.CasterGUID.IsEmpty())
357 {
358 // world gameobjects can't own auras and they send empty casterguid
359 // checked on sniffs with spell 22247
360 if (createInfo.CasterGUID.IsGameObject())
361 {
362 createInfo.Caster = nullptr;
363 createInfo.CasterGUID.Clear();
364 }
365 else
366 {
367 if (createInfo._owner->GetGUID() == createInfo.CasterGUID)
368 createInfo.Caster = createInfo._owner->ToUnit();
369 else
370 createInfo.Caster = ObjectAccessor::GetUnit(*createInfo._owner, createInfo.CasterGUID);
371 }
372 }
373 else if (createInfo.Caster)
374 createInfo.CasterGUID = createInfo.Caster->GetGUID();
375
376 // check if aura can be owned by owner
377 if (Unit* ownerUnit = createInfo._owner->ToUnit())
378 if (!ownerUnit->IsInWorld() || ownerUnit->IsDuringRemoveFromWorld())
379 // owner not in world so don't allow to own not self cast single target auras
380 if (createInfo.CasterGUID != ownerUnit->GetGUID() && createInfo._spellInfo->IsSingleTarget())
381 return nullptr;
382
383 Aura* aura = nullptr;
384 switch (createInfo._owner->GetTypeId())
385 {
386 case TYPEID_UNIT:
387 case TYPEID_PLAYER:
388 {
389 aura = new UnitAura(createInfo);
390
391 // aura can be removed in Unit::_AddAura call
392 if (aura->IsRemoved())
393 return nullptr;
394
395 // add owner
396 uint8 effMask = createInfo._auraEffectMask;
397 if (createInfo._targetEffectMask)
398 effMask = createInfo._targetEffectMask;
399
400 effMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, effMask, createInfo._owner);
401 ASSERT_NODEBUGINFO(effMask);
402
403 Unit* unit = createInfo._owner->ToUnit();
404 aura->ToUnitAura()->AddStaticApplication(unit, effMask);
405 break;
406 }
408 createInfo._auraEffectMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, createInfo._auraEffectMask, createInfo._owner);
410
411 aura = new DynObjAura(createInfo);
412 break;
413 default:
414 ABORT();
415 return nullptr;
416 }
417
418 // scripts, etc.
419 if (aura->IsRemoved())
420 return nullptr;
421
422 return aura;
423}
424
425Aura::Aura(AuraCreateInfo const& createInfo) :
426m_spellInfo(createInfo._spellInfo), m_casterGuid(createInfo.CasterGUID),
427m_castItemGuid(createInfo.CastItemGUID), m_applyTime(GameTime::GetGameTime()),
428m_owner(createInfo._owner), m_timeCla(0), m_updateTargetMapInterval(0),
429_casterInfo(), m_procCharges(0), m_stackAmount(1),
430m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr),
431m_procCooldown(TimePoint::min()), m_scriptRef(this, NoopAuraDeleter())
432{
435
438 m_procCharges = CalcMaxCharges(createInfo.Caster);
440 memset(m_effects, 0, sizeof(m_effects));
441
442 // m_casterLevel = cast item level/caster level, caster level should be saved to db, confirmed with sniffs
444 if (createInfo.Caster)
445 {
446 _casterInfo.Level = createInfo.Caster->GetLevel();
448 SaveCasterInfo(createInfo.Caster);
449 }
450}
451
452AuraScript* Aura::GetScriptByName(std::string const& scriptName) const
453{
454 for (auto itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
455 if ((*itr)->_GetScriptName()->compare(scriptName) == 0)
456 return *itr;
457 return nullptr;
458}
459
460void Aura::_InitEffects(uint8 effMask, Unit* caster, int32 const* baseAmount)
461{
462 // shouldn't be in constructor - functions in AuraEffect::AuraEffect use polymorphism
463 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
464 if (effMask & (uint8(1) << spellEffectInfo.EffectIndex))
465 m_effects[spellEffectInfo.EffectIndex] = new AuraEffect(this, spellEffectInfo, baseAmount ? baseAmount + spellEffectInfo.EffectIndex : nullptr, caster);
466}
467
468bool Aura::CanPeriodicTickCrit(Unit const* caster) const
469{
470 if (GetSpellInfo()->HasAttribute(SPELL_ATTR2_CANT_CRIT))
471 return false;
472
474 return true;
475
476 // Rupture - since 3.3.3 can crit
477 if (GetSpellInfo()->SpellIconID == 500 && GetSpellInfo()->SpellFamilyName == SPELLFAMILY_ROGUE)
478 return true;
479
480 return false;
481}
482
483float Aura::CalcPeriodicCritChance(Unit const* caster) const
484{
485 Player* modOwner = caster->GetSpellModOwner();
486 if (!modOwner || !CanPeriodicTickCrit(modOwner))
487 return 0.f;
488
489 float critChance = modOwner->SpellCritChanceDone(GetSpellInfo(), GetSpellInfo()->GetSchoolMask(), GetSpellInfo()->GetAttackType(), true);
490 return std::max(0.f, critChance);
491}
492
494{
496
497 if (GetType() == UNIT_AURA_TYPE)
498 {
499 /*
500 * Get critical chance from last effect type (damage or healing)
501 * this could potentialy be wrong if any spell has both damage and heal periodics
502 * The only two spells in 3.3.5 with those conditions are 17484 and 50344
503 * which shouldn't be allowed to crit, so we're fine
504 */
505 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
506 {
507 switch (spellEffectInfo.ApplyAuraName)
508 {
511 break;
515 break;
516 default:
517 break;
518 }
519 }
520 }
521}
522
524{
525 // unload scripts
526 for (auto itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
527 {
528 (*itr)->_Unload();
529 delete (*itr);
530 }
531
532 // free effects memory
533 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
534 delete m_effects[i];
535
536 ASSERT(m_applications.empty());
538}
539
541{
542 if (GetOwner()->GetGUID() == GetCasterGUID())
543 return GetUnitOwner();
544
546}
547
552
553void Aura::_ApplyForTarget(Unit* target, Unit* caster, AuraApplication* auraApp)
554{
555 ASSERT(target);
556 ASSERT(auraApp);
557 // aura mustn't be already applied on target
558 ASSERT (!IsAppliedOnTarget(target->GetGUID()) && "Aura::_ApplyForTarget: aura musn't be already applied on target");
559
560 m_applications[target->GetGUID()] = auraApp;
561
562 // set infinity cooldown state for spells
563 if (caster && caster->GetTypeId() == TYPEID_PLAYER)
564 {
566 {
567 Item* castItem = !m_castItemGuid.IsEmpty() ? caster->ToPlayer()->GetItemByGuid(m_castItemGuid) : nullptr;
568 caster->GetSpellHistory()->StartCooldown(m_spellInfo, castItem ? castItem->GetEntry() : 0, nullptr, true);
569 }
570 }
571}
572
573void Aura::_UnapplyForTarget(Unit* target, Unit* caster, AuraApplication* auraApp)
574{
575 ASSERT(target);
576 ASSERT(auraApp->GetRemoveMode());
577 ASSERT(auraApp);
578
579 ApplicationMap::iterator itr = m_applications.find(target->GetGUID());
580
582 if (itr == m_applications.end())
583 {
584 TC_LOG_ERROR("spells", "Aura::_UnapplyForTarget, target: {}, caster: {}, spell:{} was not found in owners application map!",
585 target->GetGUID().ToString(), caster ? caster->GetGUID().ToString() : "Empty", auraApp->GetBase()->GetSpellInfo()->Id);
586 ABORT();
587 }
588
589 // aura has to be already applied
590 ASSERT(itr->second == auraApp);
591 m_applications.erase(itr);
592
593 _removedApplications.push_back(auraApp);
594
595 // reset cooldown state for spells
596 if (caster && GetSpellInfo()->IsCooldownStartedOnEvent())
597 // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
599}
600
601// removes aura from all targets
602// and marks aura as removed
604{
606 m_isRemoved = true;
607 ApplicationMap::iterator appItr = m_applications.begin();
608 for (appItr = m_applications.begin(); appItr != m_applications.end();)
609 {
610 AuraApplication * aurApp = appItr->second;
611 Unit* target = aurApp->GetTarget();
612 target->_UnapplyAura(aurApp, removeMode);
613 appItr = m_applications.begin();
614 }
615
616 if (m_dropEvent)
617 {
619 m_dropEvent = nullptr;
620 }
621
622 m_scriptRef = nullptr;
623}
624
625void Aura::UpdateTargetMap(Unit* caster, bool apply)
626{
627 if (IsRemoved())
628 return;
629
631
632 // fill up to date target list
633 // target, effMask
634 std::unordered_map<Unit*, uint8> targets;
635 FillTargetMap(targets, caster);
636
637 std::vector<Unit*> targetsToRemove;
638
639 // mark all auras as ready to remove
640 for (auto const& applicationPair : m_applications)
641 {
642 auto itr = targets.find(applicationPair.second->GetTarget());
643 // not found in current area - remove the aura
644 if (itr == targets.end())
645 targetsToRemove.push_back(applicationPair.second->GetTarget());
646 else
647 {
648 // needs readding - remove now, will be applied in next update cycle
649 // (dbcs do not have auras which apply on same type of targets but have different radius, so this is not really needed)
650 if (itr->first->IsImmunedToSpell(GetSpellInfo(), caster, true) || !CanBeAppliedOn(itr->first))
651 {
652 targetsToRemove.push_back(applicationPair.second->GetTarget());
653 continue;
654 }
655
656 // check target immunities (for existing targets)
657 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
658 if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster, true))
659 itr->second &= ~(1 << spellEffectInfo.EffectIndex);
660
661 // needs to add/remove effects from application, don't remove from map so it gets updated
662 if (applicationPair.second->GetEffectMask() != itr->second)
663 continue;
664
665 // nothing to do - aura already applied
666 // remove from auras to register list
667 targets.erase(itr);
668 }
669 }
670
671 // register auras for units
672 for (auto itr = targets.begin(); itr != targets.end();)
673 {
674 bool addUnit = true;
675 AuraApplication* aurApp = GetApplicationOfTarget(itr->first->GetGUID());
676 if (!aurApp)
677 {
678 // check target immunities (for new targets)
679 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
680 if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster))
681 itr->second &= ~(1 << spellEffectInfo.EffectIndex);
682
683 if (!itr->second || itr->first->IsImmunedToSpell(GetSpellInfo(), caster) || !CanBeAppliedOn(itr->first))
684 addUnit = false;
685 }
686
687 if (addUnit && !itr->first->IsHighestExclusiveAura(this, true))
688 addUnit = false;
689
690 // Dynobj auras don't hit flying targets
691 if (GetType() == DYNOBJ_AURA_TYPE && itr->first->IsInFlight())
692 addUnit = false;
693
694 // Do not apply aura if it cannot stack with existing auras
695 if (addUnit)
696 {
697 // Allow to remove by stack when aura is going to be applied on owner
698 if (itr->first != GetOwner())
699 {
700 // check if not stacking aura already on target
701 // this one prevents unwanted usefull buff loss because of stacking and prevents overriding auras periodicaly by 2 near area aura owners
702 for (Unit::AuraApplicationMap::iterator iter = itr->first->GetAppliedAuras().begin(); iter != itr->first->GetAppliedAuras().end(); ++iter)
703 {
704 Aura const* aura = iter->second->GetBase();
705 if (!CanStackWith(aura))
706 {
707 addUnit = false;
708 break;
709 }
710 }
711 }
712 }
713
714 if (!addUnit)
715 itr = targets.erase(itr);
716 else
717 {
718 // owner has to be in world, or effect has to be applied to self
719 if (!GetOwner()->IsSelfOrInSameMap(itr->first))
720 {
722 TC_LOG_FATAL("spells", "Aura {}: Owner {} (map {}) is not in the same map as target {} (map {}).", GetSpellInfo()->Id,
723 GetOwner()->GetName(), GetOwner()->IsInWorld() ? GetOwner()->GetMap()->GetId() : uint32(-1),
724 itr->first->GetName(), itr->first->IsInWorld() ? itr->first->GetMap()->GetId() : uint32(-1));
725 ABORT();
726 }
727
728 if (aurApp)
729 {
730 aurApp->UpdateApplyEffectMask(itr->second, true); // aura is already applied, this means we need to update effects of current application
731 itr = targets.erase(itr);
732 }
733 else
734 {
735 itr->first->_CreateAuraApplication(this, itr->second);
736 ++itr;
737 }
738 }
739 }
740
741 // remove auras from units no longer needing them
742 for (Unit* unit : targetsToRemove)
743 if (AuraApplication* aurApp = GetApplicationOfTarget(unit->GetGUID()))
744 unit->_UnapplyAura(aurApp, AURA_REMOVE_BY_DEFAULT);
745
746 if (!apply)
747 return;
748
749 // apply aura effects for units
750 for (auto itr = targets.begin(); itr!= targets.end(); ++itr)
751 {
752 if (AuraApplication* aurApp = GetApplicationOfTarget(itr->first->GetGUID()))
753 {
754 // owner has to be in world, or effect has to be applied to self
755 ASSERT((!GetOwner()->IsInWorld() && GetOwner() == itr->first) || GetOwner()->IsInMap(itr->first));
756 itr->first->_ApplyAura(aurApp, itr->second);
757 }
758 }
759}
760
761// targets have to be registered and not have effect applied yet to use this function
763{
764 // prepare list of aura targets
765 UnitList targetList;
766 for (ApplicationMap::iterator appIter = m_applications.begin(); appIter != m_applications.end(); ++appIter)
767 {
768 if ((appIter->second->GetEffectsToApply() & (1<<effIndex)) && !appIter->second->HasEffect(effIndex))
769 targetList.push_back(appIter->second->GetTarget());
770 }
771
772 // apply effect to targets
773 for (UnitList::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
774 {
775 if (GetApplicationOfTarget((*itr)->GetGUID()))
776 {
777 // owner has to be in world, or effect has to be applied to self
778 ASSERT((!GetOwner()->IsInWorld() && GetOwner() == *itr) || GetOwner()->IsInMap(*itr));
779 (*itr)->_ApplyAuraEffect(this, effIndex);
780 }
781 }
782}
784{
785 ASSERT(owner == m_owner);
786
787 Unit* caster = GetCaster();
788 // Apply spellmods for channeled auras
789 // used for example when triggered spell of spell:10 is modded
790 Spell* modSpell = nullptr;
791 Player* modOwner = nullptr;
792 if (caster)
793 {
794 modOwner = caster->GetSpellModOwner();
795 if (modOwner)
796 {
797 modSpell = modOwner->FindCurrentSpellBySpellId(GetId());
798 if (modSpell)
799 modOwner->SetSpellModTakingSpell(modSpell, true);
800 }
801 }
802
803 Update(diff, caster);
804
805 if (m_updateTargetMapInterval <= int32(diff))
806 UpdateTargetMap(caster);
807 else
809
810 // update aura effects
811 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
812 if (m_effects[i])
813 m_effects[i]->Update(diff, caster);
814
815 // remove spellmods after effects update
816 if (modSpell)
817 modOwner->SetSpellModTakingSpell(modSpell, false);
818
820}
821
822void Aura::Update(uint32 diff, Unit* caster)
823{
824 if (m_duration > 0)
825 {
826 m_duration -= diff;
827 if (m_duration < 0)
828 m_duration = 0;
829
830 // handle manaPerSecond/manaPerSecondPerLevel
831 if (m_timeCla)
832 {
833 if (m_timeCla > int32(diff))
834 m_timeCla -= diff;
835 else if (caster)
836 {
837 if (int32 manaPerSecond = m_spellInfo->ManaPerSecond + m_spellInfo->ManaPerSecondPerLevel * caster->GetLevel())
838 {
839 m_timeCla += 1000 - diff;
840
841 Powers powertype = Powers(m_spellInfo->PowerType);
842 if (powertype == POWER_HEALTH)
843 {
844 if (int32(caster->GetHealth()) > manaPerSecond)
845 caster->ModifyHealth(-manaPerSecond);
846 else
847 Remove();
848 }
849 else if (int32(caster->GetPower(powertype)) >= manaPerSecond)
850 caster->ModifyPower(powertype, -manaPerSecond);
851 else
852 Remove();
853 }
854 }
855 }
856 }
857}
858
860{
861 return Aura::CalcMaxDuration(GetSpellInfo(), caster);
862}
863
864/*static*/ int32 Aura::CalcMaxDuration(SpellInfo const* spellInfo, WorldObject* caster)
865{
866 Player* modOwner = nullptr;
867 int32 maxDuration;
868
869 if (caster)
870 {
871 modOwner = caster->GetSpellModOwner();
872 maxDuration = caster->CalcSpellDuration(spellInfo);
873 }
874 else
875 maxDuration = spellInfo->GetDuration();
876
877 if (spellInfo->IsPassive() && !spellInfo->DurationEntry)
878 maxDuration = -1;
879
880 // IsPermanent() checks max duration (which we are supposed to calculate here)
881 if (maxDuration != -1 && modOwner)
882 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_DURATION, maxDuration);
883
884 return maxDuration;
885}
886
887void Aura::SetDuration(int32 duration, bool withMods)
888{
889 if (withMods)
890 if (Unit* caster = GetCaster())
891 if (Player* modOwner = caster->GetSpellModOwner())
892 modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, duration);
893
894 m_duration = duration;
896}
897
898void Aura::RefreshDuration(bool withMods)
899{
900 Unit* caster = GetCaster();
901 if (withMods && caster)
902 {
903 int32 duration = m_spellInfo->GetMaxDuration();
904 // Calculate duration of periodics affected by haste.
906 duration = int32(duration * caster->GetFloatValue(UNIT_MOD_CAST_SPEED));
907
908 SetMaxDuration(duration);
909 SetDuration(duration);
910 }
911 else
913
916
917 // also reset periodic counters
918 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
919 if (AuraEffect* aurEff = m_effects[i])
920 aurEff->ResetTicks();
921}
922
923void Aura::RefreshTimers(bool resetPeriodicTimer)
924{
927
928 Unit* caster = GetCaster();
929 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
930 if (AuraEffect* aurEff = m_effects[i])
931 aurEff->CalculatePeriodic(caster, resetPeriodicTimer, false);
932}
933
935{
936 if (m_procCharges == charges)
937 return;
938
939 m_procCharges = charges;
942}
943
945{
946 uint32 maxProcCharges = m_spellInfo->ProcCharges;
947 if (SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetId()))
948 maxProcCharges = procEntry->Charges;
949
950 if (caster)
951 if (Player* modOwner = caster->GetSpellModOwner())
952 modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, maxProcCharges);
953
954 return uint8(maxProcCharges);
955}
956
958{
959 if (IsUsingCharges())
960 {
961 int32 charges = m_procCharges + num;
962 int32 maxCharges = CalcMaxCharges();
963
964 // limit charges (only on charges increase, charges may be changed manually)
965 if ((num > 0) && (charges > int32(maxCharges)))
966 charges = maxCharges;
967 // we're out of charges, remove
968 else if (charges <= 0)
969 {
970 Remove(removeMode);
971 return true;
972 }
973
974 SetCharges(charges);
975 }
976
977 return false;
978}
979
981{
982 m_dropEvent = nullptr;
983 ModCharges(num, removeMode);
984}
985
987{
988 // aura is already during delayed charge drop
989 if (m_dropEvent)
990 return;
991 // only units have events
992 Unit* owner = m_owner->ToUnit();
993 if (!owner)
994 return;
995
996 m_dropEvent = new ChargeDropEvent(this, removeMode);
998}
999
1001{
1002 m_stackAmount = stackAmount;
1003 Unit* caster = GetCaster();
1004
1005 std::vector<AuraApplication*> applications;
1006 GetApplicationVector(applications);
1007
1008 for (AuraApplication* aurApp : applications)
1009 if (!aurApp->GetRemoveMode())
1010 HandleAuraSpecificMods(aurApp, caster, false, true);
1011
1012 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
1013 if (AuraEffect* aurEff = GetEffect(i))
1014 aurEff->ChangeAmount(aurEff->CalculateAmount(caster), false, true);
1015
1016 for (AuraApplication* aurApp : applications)
1017 if (!aurApp->GetRemoveMode())
1018 HandleAuraSpecificMods(aurApp, caster, true, true);
1019
1021}
1022
1023bool Aura::ModStackAmount(int32 num, AuraRemoveMode removeMode /*= AURA_REMOVE_BY_DEFAULT*/, bool resetPeriodicTimer /*= true*/)
1024{
1025 int32 stackAmount = m_stackAmount + num;
1026
1027 // limit the stack amount (only on stack increase, stack amount may be changed manually)
1028 if ((num > 0) && (stackAmount > int32(m_spellInfo->StackAmount)))
1029 {
1030 // not stackable aura - set stack amount to 1
1032 stackAmount = 1;
1033 else
1034 stackAmount = m_spellInfo->StackAmount;
1035 }
1036 // we're out of stacks, remove
1037 else if (stackAmount <= 0)
1038 {
1039 Remove(removeMode);
1040 return true;
1041 }
1042
1044
1045 // Update stack amount
1046 SetStackAmount(stackAmount);
1047
1048 if (refresh)
1049 {
1050 RefreshTimers(resetPeriodicTimer);
1051
1052 // reset charges
1054 }
1055
1057 return false;
1058}
1059
1061{
1062 uint32 count = 0;
1063 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1064 if (HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.ApplyAuraName == auraType)
1065 ++count;
1066
1067 return count > 1;
1068}
1069
1070bool Aura::IsArea() const
1071{
1072 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1073 if (HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.IsAreaAuraEffect())
1074 return true;
1075
1076 return false;
1077}
1078
1080{
1081 return GetSpellInfo()->IsPassive();
1082}
1083
1085{
1086 return GetSpellInfo()->IsDeathPersistent();
1087}
1088
1096
1098{
1099 if (IsPassive())
1100 return false;
1101
1102 if (GetSpellInfo()->IsChanneled())
1103 return false;
1104
1105 // Check if aura is single target, not only spell info
1106 if (GetCasterGUID() != GetOwner()->GetGUID())
1107 {
1108 // owner == caster for area auras, check for possible bad data in DB
1109 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1110 {
1111 if (!spellEffectInfo.IsEffect())
1112 continue;
1113
1114 if (spellEffectInfo.IsTargetingArea() || spellEffectInfo.IsAreaAuraEffect())
1115 return false;
1116 }
1117
1119 return false;
1120 }
1121
1123 return false;
1124
1125 // don't save auras removed by proc system
1126 if (IsUsingCharges() && !GetCharges())
1127 return false;
1128
1129 // don't save permanent auras triggered by items, they'll be recasted on login if necessary
1130 if (!GetCastItemGUID().IsEmpty() && IsPermanent())
1131 return false;
1132
1133 return true;
1134}
1135
1140
1141bool Aura::IsSingleTargetWith(Aura const* aura) const
1142{
1143 // Same spell?
1144 if (GetSpellInfo()->IsRankOf(aura->GetSpellInfo()))
1145 return true;
1146
1148 // spell with single target specific types
1149 switch (spec)
1150 {
1153 if (aura->GetSpellInfo()->GetSpellSpecific() == spec)
1154 return true;
1155 break;
1156 default:
1157 break;
1158 }
1159
1160 return false;
1161}
1162
1164{
1166 Unit* caster = GetCaster();
1167 ASSERT(caster);
1168 caster->GetSingleCastAuras().remove(this);
1169 SetIsSingleTarget(false);
1170}
1171
1172int32 Aura::CalcDispelChance(Unit const* auraTarget, bool offensive) const
1173{
1174 // we assume that aura dispel chance is 100% on start
1175 // need formula for level difference based chance
1176 int32 resistChance = 0;
1177
1178 // Apply dispel mod from aura caster
1179 if (Unit* caster = GetCaster())
1180 if (Player* modOwner = caster->GetSpellModOwner())
1181 modOwner->ApplySpellMod(GetId(), SPELLMOD_RESIST_DISPEL_CHANCE, resistChance);
1182
1183 // Dispel resistance from target SPELL_AURA_MOD_DISPEL_RESIST
1184 // Only affects offensive dispels
1185 if (offensive && auraTarget)
1186 resistChance += auraTarget->GetTotalAuraModifier(SPELL_AURA_MOD_DISPEL_RESIST);
1187
1188 RoundToInterval(resistChance, 0, 100);
1189 return 100 - resistChance;
1190}
1191
1192void Aura::SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, float critChance, bool applyResilience, int32* amount)
1193{
1194 m_maxDuration = maxduration;
1195 m_duration = duration;
1196 m_procCharges = charges;
1198 m_stackAmount = stackamount;
1199 SetCritChance(critChance);
1200 SetCanApplyResilience(applyResilience);
1201 Unit* caster = GetCaster();
1202 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
1203 {
1204 if (AuraEffect* aurEff = m_effects[i])
1205 {
1206 aurEff->SetAmount(amount[i]);
1207 aurEff->SetCanBeRecalculated((recalculateMask & (1 << i)) != 0);
1208 aurEff->CalculatePeriodic(caster, false, true);
1209 aurEff->CalculateSpellMod();
1210 aurEff->RecalculateAmount(caster);
1211 }
1212 }
1213}
1214
1216{
1217 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
1218 {
1219 if (HasEffect(i) && m_effects[i]->GetAuraType() == type)
1220 return true;
1221 }
1222 return false;
1223}
1224
1226{
1227 ASSERT (!IsRemoved());
1228 Unit* caster = GetCaster();
1229 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
1230 if (HasEffect(i))
1231 m_effects[i]->RecalculateAmount(caster);
1232}
1233
1234void Aura::HandleAllEffects(AuraApplication * aurApp, uint8 mode, bool apply)
1235{
1236 ASSERT (!IsRemoved());
1237 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
1238 if (m_effects[i] && !IsRemoved())
1239 m_effects[i]->HandleEffect(aurApp, mode, apply);
1240}
1241
1242void Aura::GetApplicationVector(std::vector<AuraApplication*>& applicationList) const
1243{
1244 for (auto const& applicationPair : m_applications)
1245 {
1246 if (!applicationPair.second->GetEffectMask())
1247 continue;
1248
1249 applicationList.push_back(applicationPair.second);
1250 }
1251}
1252
1254{
1255 for (ApplicationMap::const_iterator appIter = m_applications.begin(); appIter != m_applications.end(); ++appIter)
1256 appIter->second->SetNeedClientUpdate();
1257}
1258
1259// trigger effects on real aura apply/remove
1260void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, bool apply, bool onReapply)
1261{
1262 Unit* target = aurApp->GetTarget();
1263 AuraRemoveMode removeMode = aurApp->GetRemoveMode();
1264 // handle spell_area table
1265 SpellAreaForAreaMapBounds saBounds = sSpellMgr->GetSpellAreaForAuraMapBounds(GetId());
1266 if (saBounds.first != saBounds.second)
1267 {
1268 uint32 zone, area;
1269 target->GetZoneAndAreaId(zone, area);
1270
1271 for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
1272 {
1273 // some auras remove at aura remove
1274 if (!itr->second->IsFitToRequirements(target->ToPlayer(), zone, area))
1275 target->RemoveAurasDueToSpell(itr->second->spellId);
1276 // some auras applied at aura apply
1277 else if (itr->second->autocast)
1278 {
1279 if (!target->HasAura(itr->second->spellId))
1280 target->CastSpell(target, itr->second->spellId, true);
1281 }
1282 }
1283 }
1284
1285 // handle spell_linked_spell table
1286 if (!onReapply)
1287 {
1288 // apply linked auras
1289 if (apply)
1290 {
1291 if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(GetId() + SPELL_LINK_AURA))
1292 {
1293 for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
1294 {
1295 if (*itr < 0)
1296 target->ApplySpellImmune(GetId(), IMMUNITY_ID, -(*itr), true);
1297 else if (caster)
1298 caster->AddAura(*itr, target);
1299 }
1300 }
1301 }
1302 else
1303 {
1304 // remove linked auras
1305 if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(-(int32)GetId()))
1306 {
1307 for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
1308 {
1309 if (*itr < 0)
1310 target->RemoveAurasDueToSpell(-(*itr));
1311 else if (removeMode != AURA_REMOVE_BY_DEATH)
1312 target->CastSpell(target, *itr, GetCasterGUID());
1313 }
1314 }
1315 if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(GetId() + SPELL_LINK_AURA))
1316 {
1317 for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
1318 {
1319 if (*itr < 0)
1320 target->ApplySpellImmune(GetId(), IMMUNITY_ID, -(*itr), false);
1321 else
1322 target->RemoveAura(*itr, GetCasterGUID(), 0, removeMode);
1323 }
1324 }
1325 }
1326 }
1327 else if (apply)
1328 {
1329 // modify stack amount of linked auras
1330 if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(GetId() + SPELL_LINK_AURA))
1331 {
1332 for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
1333 if (*itr > 0)
1334 if (Aura* triggeredAura = target->GetAura(*itr, GetCasterGUID()))
1335 triggeredAura->ModStackAmount(GetStackAmount() - triggeredAura->GetStackAmount());
1336 }
1337 }
1338
1339 // mods at aura apply
1340 if (apply)
1341 {
1342 switch (GetSpellInfo()->SpellFamilyName)
1343 {
1345 switch (GetId())
1346 {
1347 case 50836: //Petrifying Grip, becomes stoned
1348 if (GetStackAmount() >= 5 && !target->HasAura(50812))
1349 target->CastSpell(target, 50812, true);
1350 break;
1351 case 60970: // Heroic Fury (remove Intercept cooldown)
1352 if (target->GetTypeId() == TYPEID_PLAYER)
1353 target->GetSpellHistory()->ResetCooldown(20252, true);
1354 break;
1355 }
1356 break;
1357 case SPELLFAMILY_DRUID:
1358 if (!caster)
1359 break;
1360 // Rejuvenation
1361 if (GetSpellInfo()->SpellFamilyFlags[0] & 0x10 && GetEffect(EFFECT_0))
1362 {
1363 // Druid T8 Restoration 4P Bonus
1364 if (caster->HasAura(64760))
1365 {
1368 caster->CastSpell(target, 64801, args);
1369 }
1370 }
1371 break;
1372 case SPELLFAMILY_MAGE:
1373 if (!caster)
1374 break;
1375 if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00000001 && GetSpellInfo()->SpellFamilyFlags[2] & 0x00000008)
1376 {
1377 // Glyph of Fireball
1378 if (caster->HasAura(56368))
1379 SetDuration(0);
1380 }
1381 else if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00000020 && GetSpellInfo()->SpellVisual[0] == 13)
1382 {
1383 // Glyph of Frostbolt
1384 if (caster->HasAura(56370))
1385 SetDuration(0);
1386 }
1388 else if (GetSpellInfo()->SpellFamilyFlags[0] & 0x01000000)
1389 {
1390 // Polymorph Sound - Sheep && Penguin
1391 if (GetSpellInfo()->SpellIconID == 82 && GetSpellInfo()->SpellVisual[0] == 12978)
1392 {
1393 // Glyph of the Penguin
1394 if (caster->HasAura(52648))
1395 caster->CastSpell(target, 61635, true);
1396 else
1397 caster->CastSpell(target, 61634, true);
1398 }
1399 }
1400 switch (GetId())
1401 {
1402 case 44544: // Fingers of Frost
1403 {
1404 // Refresh or add visual aura
1406 args.AddSpellMod(SPELLVALUE_AURA_STACK, sSpellMgr->AssertSpellInfo(74396)->StackAmount);
1407 target->CastSpell(nullptr, 74396, args);
1408 break;
1409 }
1410 default:
1411 break;
1412 }
1413 break;
1414 case SPELLFAMILY_PRIEST:
1415 if (!caster)
1416 break;
1417
1418 // Devouring Plague
1419 if (GetSpellInfo()->SpellFamilyFlags[0] & 0x02000000)
1420 {
1421 AuraEffect const* devouringPlague = GetEffect(EFFECT_0);
1422 if (!devouringPlague)
1423 break;
1424
1425 // Improved Devouring Plague
1426 if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 3790, 1))
1427 {
1428 int32 damage = devouringPlague->GetAmount();
1429 damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT);
1430
1431 CastSpellExtraArgs args(devouringPlague), args2(devouringPlague);
1432 int32 basepoints0 = CalculatePct(devouringPlague->GetTotalTicks() * static_cast<int32>(damage), aurEff->GetAmount());
1433 args.AddSpellMod(SPELLVALUE_BASE_POINT0, basepoints0);
1434 args2.AddSpellMod(SPELLVALUE_BASE_POINT0, CalculatePct(basepoints0, 15));
1435 caster->CastSpell(target, 63675, args);
1436 caster->CastSpell(nullptr, 75999, args2);
1437 }
1438 }
1439 // Power Word: Shield
1440 else if (m_spellInfo->SpellFamilyFlags[0] & 0x1 && m_spellInfo->SpellFamilyFlags[2] & 0x400 && GetEffect(0))
1441 {
1442 // Glyph of Power Word: Shield
1443 if (AuraEffect* glyph = caster->GetAuraEffect(55672, 0))
1444 {
1445 // instantly heal m_amount% of the absorb-value
1446 int32 heal = glyph->GetAmount() * GetEffect(0)->GetAmount()/100;
1449 caster->CastSpell(GetUnitOwner(), 56160, args);
1450 }
1451 }
1452 break;
1453 case SPELLFAMILY_ROGUE:
1454 // Sprint (skip non player cast spells by category)
1455 if (GetSpellInfo()->SpellFamilyFlags[0] & 0x40 && GetSpellInfo()->GetCategory() == 44)
1456 // in official maybe there is only one icon?
1457 if (target->HasAura(58039)) // Glyph of Blurred Speed
1458 target->CastSpell(target, 61922, true); // Sprint (waterwalk)
1459 break;
1461 if (!caster)
1462 break;
1463 // Frost Fever and Blood Plague
1464 if (GetSpellInfo()->SpellFamilyFlags[2] & 0x2)
1465 {
1466 // Can't proc on self
1467 if (GetCasterGUID() == target->GetGUID())
1468 break;
1469
1470 AuraEffect* aurEff = nullptr;
1471 // Ebon Plaguebringer / Crypt Fever
1473 for (Unit::AuraEffectList::const_iterator itr = TalentAuras.begin(); itr != TalentAuras.end(); ++itr)
1474 {
1475 if ((*itr)->GetMiscValue() == 7282)
1476 {
1477 aurEff = *itr;
1478 // Ebon Plaguebringer - end search if found
1479 if ((*itr)->GetSpellInfo()->SpellIconID == 1766)
1480 break;
1481 }
1482 }
1483 if (aurEff)
1484 {
1485 uint32 spellId = 0;
1486 switch (aurEff->GetId())
1487 {
1488 // Ebon Plague
1489 case 51161: spellId = 51735; break;
1490 case 51160: spellId = 51734; break;
1491 case 51099: spellId = 51726; break;
1492 // Crypt Fever
1493 case 49632: spellId = 50510; break;
1494 case 49631: spellId = 50509; break;
1495 case 49032: spellId = 50508; break;
1496 default:
1497 TC_LOG_ERROR("spells", "Aura::HandleAuraSpecificMods: Unknown rank of Crypt Fever/Ebon Plague ({}) found", aurEff->GetId());
1498 }
1499 caster->CastSpell(target, spellId, GetEffect(0));
1500 }
1501 }
1502 break;
1503 }
1504 }
1505 // mods at aura remove
1506 else
1507 {
1508 switch (GetSpellInfo()->SpellFamilyName)
1509 {
1511 switch (GetId())
1512 {
1513 case 61987: // Avenging Wrath
1514 // Remove the immunity shield marker on Avenging Wrath removal if Forbearance is not present
1515 if (target->HasAura(61988) && !target->HasAura(25771))
1516 target->RemoveAura(61988);
1517 break;
1518 default:
1519 break;
1520 }
1521 break;
1522 case SPELLFAMILY_MAGE:
1523 switch (GetId())
1524 {
1525 case 66: // Invisibility
1526 if (removeMode != AURA_REMOVE_BY_EXPIRE)
1527 break;
1528 target->CastSpell(target, 32612, GetEffect(1));
1529 break;
1530 default:
1531 break;
1532 }
1533 break;
1535 if (!caster)
1536 break;
1537 // Spell Reflection
1538 if (GetSpellInfo()->SpellFamilyFlags[1] & 0x2)
1539 {
1540 if (removeMode != AURA_REMOVE_BY_DEFAULT)
1541 {
1542 // Improved Spell Reflection
1543 if (caster->GetDummyAuraEffect(SPELLFAMILY_WARRIOR, 1935, 1))
1544 {
1545 // aura remove - remove auras from all party members
1546 std::list<Unit*> PartyMembers;
1547 target->GetPartyMembers(PartyMembers);
1548 for (std::list<Unit*>::iterator itr = PartyMembers.begin(); itr != PartyMembers.end(); ++itr)
1549 {
1550 if ((*itr)!= target)
1551 (*itr)->RemoveAurasWithFamily(SPELLFAMILY_WARRIOR, flag96(0, 0x2, 0), GetCasterGUID());
1552 }
1553 }
1554 }
1555 }
1556 break;
1558 if (!caster)
1559 break;
1560 // Improved Fear
1561 if (GetSpellInfo()->SpellFamilyFlags[1] & 0x00000400)
1562 {
1563 if (AuraEffect* aurEff = caster->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_WARLOCK, 98, 0))
1564 {
1565 uint32 spellId = 0;
1566 switch (aurEff->GetId())
1567 {
1568 case 53759: spellId = 60947; break;
1569 case 53754: spellId = 60946; break;
1570 default:
1571 TC_LOG_ERROR("spells", "Aura::HandleAuraSpecificMods: Unknown rank of Improved Fear ({}) found", aurEff->GetId());
1572 }
1573 if (spellId)
1574 caster->CastSpell(target, spellId, true);
1575 }
1576 }
1577 break;
1578 case SPELLFAMILY_PRIEST:
1579 if (!caster)
1580 break;
1581 // Shadow word: Pain // Vampiric Touch
1582 if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && (GetSpellInfo()->SpellFamilyFlags[0] & 0x00008000 || GetSpellInfo()->SpellFamilyFlags[1] & 0x00000400))
1583 {
1584 // Shadow Affinity
1585 if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 178, 1))
1586 {
1587 int32 basepoints0 = aurEff->GetAmount() * caster->GetCreateMana() / 100;
1589 args.AddSpellMod(SPELLVALUE_BASE_POINT0, basepoints0);
1590 caster->CastSpell(caster, 64103, args);
1591 }
1592 }
1593 // Power word: shield
1594 else if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && GetSpellInfo()->SpellFamilyFlags[0] & 0x00000001)
1595 {
1596 // Rapture
1597 if (Aura const* aura = caster->GetAuraOfRankedSpell(47535))
1598 {
1599 // check cooldown
1600 if (caster->GetTypeId() == TYPEID_PLAYER)
1601 {
1602 if (caster->GetSpellHistory()->HasCooldown(aura->GetId()))
1603 {
1604 // This additional check is needed to add a minimal delay before cooldown in in effect
1605 // to allow all bubbles broken by a single damage source proc mana return
1606 if (caster->GetSpellHistory()->GetRemainingCooldown(aura->GetSpellInfo()) <= 11 * IN_MILLISECONDS)
1607 break;
1608 }
1609 else // and add if needed
1610 caster->GetSpellHistory()->AddCooldown(aura->GetId(), 0, std::chrono::seconds(12));
1611 }
1612
1613 // effect on caster
1614 if (AuraEffect const* aurEff = aura->GetEffect(0))
1615 {
1616 float multiplier = (float)aurEff->GetAmount();
1617 if (aurEff->GetId() == 47535)
1618 multiplier -= 0.5f;
1619 else if (aurEff->GetId() == 47537)
1620 multiplier += 0.5f;
1621
1623 args.AddSpellBP0(CalculatePct(caster->GetMaxPower(POWER_MANA), multiplier));
1624 caster->CastSpell(caster, 47755, args);
1625 }
1626 // effect on aura target
1627 if (AuraEffect const* aurEff = aura->GetEffect(1))
1628 {
1629 if (!roll_chance_i(aurEff->GetAmount()))
1630 break;
1631
1632 int32 triggeredSpellId = 0;
1633 switch (target->GetPowerType())
1634 {
1635 case POWER_MANA:
1636 {
1639 caster->CastSpell(target, 63654, args);
1640 break;
1641 }
1642 case POWER_RAGE: triggeredSpellId = 63653; break;
1643 case POWER_ENERGY: triggeredSpellId = 63655; break;
1644 case POWER_RUNIC_POWER: triggeredSpellId = 63652; break;
1645 default:
1646 break;
1647 }
1648 if (triggeredSpellId)
1649 caster->CastSpell(target, triggeredSpellId, true);
1650 }
1651 }
1652 }
1653 switch (GetId())
1654 {
1655 case 47788: // Guardian Spirit
1656 if (removeMode != AURA_REMOVE_BY_EXPIRE)
1657 break;
1658 if (caster->GetTypeId() != TYPEID_PLAYER)
1659 break;
1660
1661 Player* player = caster->ToPlayer();
1662 // Glyph of Guardian Spirit
1663 if (AuraEffect* aurEff = player->GetAuraEffect(63231, 0))
1664 {
1665 if (!player->GetSpellHistory()->HasCooldown(47788))
1666 break;
1667
1668 player->GetSpellHistory()->ResetCooldown(GetSpellInfo()->Id, true);
1669 player->GetSpellHistory()->AddCooldown(GetSpellInfo()->Id, 0, std::chrono::seconds(aurEff->GetAmount()));
1670
1671 WorldPacket data;
1672 player->GetSpellHistory()->BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, GetSpellInfo()->Id, aurEff->GetAmount() * IN_MILLISECONDS);
1673 player->SendDirectMessage(&data);
1674 }
1675 break;
1676 }
1677 break;
1678 case SPELLFAMILY_ROGUE:
1679 // Remove Vanish on stealth remove
1680 if (GetId() == 1784)
1681 target->RemoveAurasWithFamily(SPELLFAMILY_ROGUE, flag96(0x0000800, 0, 0), target->GetGUID());
1682 break;
1684 // Remove the immunity shield marker on Forbearance removal if AW marker is not present
1685 if (GetId() == 25771 && target->HasAura(61988) && !target->HasAura(61987))
1686 target->RemoveAura(61988);
1687 break;
1689 // Blood of the North
1690 // Reaping
1691 // Death Rune Mastery
1692 if (GetSpellInfo()->SpellIconID == 3041 || GetSpellInfo()->SpellIconID == 22 || GetSpellInfo()->SpellIconID == 2622)
1693 {
1694 if (!GetEffect(0) || GetEffect(0)->GetAuraType() != SPELL_AURA_PERIODIC_DUMMY)
1695 break;
1696 if (target->GetTypeId() != TYPEID_PLAYER)
1697 break;
1698 if (target->ToPlayer()->GetClass() != CLASS_DEATH_KNIGHT)
1699 break;
1700
1701 // aura removed - remove death runes
1703 }
1704 break;
1705 case SPELLFAMILY_HUNTER:
1706 // Glyph of Freezing Trap
1707 if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00000008)
1708 if (caster && caster->HasAura(56845))
1709 target->CastSpell(target, 61394, true);
1710 break;
1711 }
1712 }
1713
1714 // mods at aura apply or remove
1715 switch (GetSpellInfo()->SpellFamilyName)
1716 {
1717 case SPELLFAMILY_ROGUE:
1718 // Stealth
1719 if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00400000)
1720 {
1721 // Master of subtlety
1722 if (AuraEffect const* aurEff = target->GetAuraEffectOfRankedSpell(31221, 0))
1723 {
1724 if (!apply)
1725 target->CastSpell(target, 31666, true);
1726 else
1727 {
1728 // Remove counter aura
1729 target->RemoveAurasDueToSpell(31666);
1730
1732 args.AddSpellBP0(aurEff->GetAmount());
1733 target->CastSpell(target, 31665, args);
1734 }
1735 }
1736 // Overkill
1737 if (target->HasAura(58426))
1738 {
1739 if (!apply)
1740 target->CastSpell(target, 58428, true);
1741 else
1742 {
1743 // Remove counter aura
1744 target->RemoveAurasDueToSpell(58428);
1745
1746 target->CastSpell(target, 58427, true);
1747 }
1748 }
1749 break;
1750 }
1751 break;
1752 case SPELLFAMILY_HUNTER:
1753 switch (GetId())
1754 {
1755 case 19574: // Bestial Wrath
1756 // The Beast Within cast on owner if talent present
1757 if (Unit* owner = target->GetOwner())
1758 {
1759 // Search talent
1760 if (owner->HasAura(34692))
1761 {
1762 if (apply)
1763 owner->CastSpell(owner, 34471, GetEffect(0));
1764 else
1765 owner->RemoveAurasDueToSpell(34471);
1766 }
1767 }
1768 break;
1769 }
1770 break;
1772 switch (GetId())
1773 {
1774 case 31842: // Divine Illumination
1775 // Item - Paladin T10 Holy 2P Bonus
1776 if (target->HasAura(70755))
1777 {
1778 if (apply)
1779 target->CastSpell(target, 71166, true);
1780 else
1781 target->RemoveAurasDueToSpell(71166);
1782 }
1783 break;
1784 }
1785 break;
1786 }
1787
1788 if (apply)
1789 {
1790 if (Creature* creature = target->ToCreature())
1791 if (CreatureAI* ai = creature->AI())
1792 ai->OnAuraApplied(aurApp);
1793 }
1794 else
1795 {
1796 if (Creature* creature = target->ToCreature())
1797 if (CreatureAI* ai = creature->AI())
1798 ai->OnAuraRemoved(aurApp);
1799 }
1800}
1801
1803{
1804 // unit not in world or during remove from world
1805 if (!target->IsInWorld() || target->IsDuringRemoveFromWorld())
1806 {
1807 // area auras mustn't be applied
1808 if (GetOwner() != target)
1809 return false;
1810 // do not apply non-selfcast single target auras
1811 if (GetCasterGUID() != GetOwner()->GetGUID() && GetSpellInfo()->IsSingleTarget())
1812 return false;
1813 return true;
1814 }
1815 else
1816 return CheckAreaTarget(target);
1817}
1818
1820{
1821 return CallScriptCheckAreaTargetHandlers(target);
1822}
1823
1824bool Aura::CanStackWith(Aura const* existingAura) const
1825{
1826 // Can stack with self
1827 if (this == existingAura)
1828 return true;
1829
1830 bool sameCaster = GetCasterGUID() == existingAura->GetCasterGUID();
1831 SpellInfo const* existingSpellInfo = existingAura->GetSpellInfo();
1832
1833 // Dynobj auras do not stack when they come from the same spell cast by the same caster
1834 if (GetType() == DYNOBJ_AURA_TYPE || existingAura->GetType() == DYNOBJ_AURA_TYPE)
1835 {
1836 if (sameCaster && m_spellInfo->Id == existingSpellInfo->Id)
1837 return false;
1838 return true;
1839 }
1840
1841 // passive auras don't stack with another rank of the spell cast by same caster
1842 if (IsPassive() && sameCaster && (m_spellInfo->IsDifferentRankOf(existingSpellInfo) || (m_spellInfo->Id == existingSpellInfo->Id && m_castItemGuid.IsEmpty())))
1843 return false;
1844
1845 for (SpellEffectInfo const& spellEffectInfo : existingSpellInfo->GetEffects())
1846 {
1847 // prevent remove triggering aura by triggered aura
1848 if (spellEffectInfo.TriggerSpell == GetId())
1849 return true;
1850 }
1851
1852 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1853 {
1854 // prevent remove triggered aura by triggering aura refresh
1855 if (spellEffectInfo.TriggerSpell == existingAura->GetId())
1856 return true;
1857 }
1858
1859 // Check for custom server setting to allow tracking both Herbs and Minerals
1860 // Note: The following are client limitations and cannot be coded for:
1861 // * The minimap tracking icon will display whichever skill is activated second
1862 // * The minimap tracking list will only show a check mark next to the last skill activated
1863 // Sometimes this bugs out and doesn't switch the check mark. It has no effect on the actual tracking though.
1864 // * The minimap dots are yellow for both resources
1866 return sWorld->getBoolConfig(CONFIG_ALLOW_TRACK_BOTH_RESOURCES);
1867
1868 // check spell specific stack rules
1869 if (m_spellInfo->IsAuraExclusiveBySpecificWith(existingSpellInfo)
1870 || (sameCaster && m_spellInfo->IsAuraExclusiveBySpecificPerCasterWith(existingSpellInfo)))
1871 return false;
1872
1873 // check spell group stack rules
1874 switch (sSpellMgr->CheckSpellGroupStackRules(m_spellInfo, existingSpellInfo))
1875 {
1877 case SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST: // if it reaches this point, existing aura is lower/equal
1878 return false;
1880 if (sameCaster)
1881 return false;
1882 break;
1885 default:
1886 break;
1887 }
1888
1889 if (m_spellInfo->SpellFamilyName != existingSpellInfo->SpellFamilyName)
1890 return true;
1891
1892 if (!sameCaster)
1893 {
1894 // Channeled auras can stack if not forbidden by db or aura type
1895 if (existingAura->GetSpellInfo()->IsChanneled())
1896 return true;
1897
1899 return true;
1900
1901 // check same periodic auras
1902 auto hasPeriodicNonAreaEffect = [](SpellInfo const* spellInfo)
1903 {
1904 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
1905 {
1906 switch (spellEffectInfo.ApplyAuraName)
1907 {
1908 // DOT or HOT from different casters will stack
1920 // periodic auras which target areas are not allowed to stack this way (replenishment for example)
1921 if (spellEffectInfo.IsTargetingArea())
1922 return false;
1923 return true;
1924 default:
1925 break;
1926 }
1927 }
1928 return false;
1929 };
1930
1931 if (hasPeriodicNonAreaEffect(m_spellInfo) && hasPeriodicNonAreaEffect(existingSpellInfo))
1932 return true;
1933 }
1934
1936 {
1937 Vehicle* veh = nullptr;
1938 if (GetOwner()->ToUnit())
1939 veh = GetOwner()->ToUnit()->GetVehicleKit();
1940
1941 if (!veh) // We should probably just let it stack. Vehicle system will prevent undefined behaviour later
1942 return true;
1943
1944 if (!veh->GetAvailableSeatCount())
1945 return false; // No empty seat available
1946
1947 return true; // Empty seat available (skip rest)
1948 }
1949
1950 // spell of same spell rank chain
1951 if (m_spellInfo->IsRankOf(existingSpellInfo))
1952 {
1953 // don't allow passive area auras to stack
1954 if (m_spellInfo->IsMultiSlotAura() && !IsArea())
1955 return true;
1956 if (!GetCastItemGUID().IsEmpty() && !existingAura->GetCastItemGUID().IsEmpty())
1958 return true;
1959 // same spell with same caster should not stack
1960 return false;
1961 }
1962
1963 return true;
1964}
1965
1967{
1968 return m_procCooldown > now;
1969}
1970
1972{
1973 m_procCooldown = cooldownEnd;
1974}
1975
1977{
1978 m_procCooldown = std::chrono::steady_clock::now();
1979}
1980
1982{
1983 bool prepare = CallScriptPrepareProcHandlers(aurApp, eventInfo);
1984 if (!prepare)
1985 return;
1986
1987 // take one charge, aura expiration will be handled in Aura::TriggerProcOnEvent (if needed)
1989 {
1990 --m_procCharges;
1992 }
1993
1994 SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetId());
1995 ASSERT(procEntry);
1996
1997 // cooldowns should be added to the whole aura (see 51698 area aura)
1998 AddProcCooldown(now + procEntry->Cooldown);
1999}
2000
2002{
2003 SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetId());
2004 // only auras with spell proc entry can trigger proc
2005 if (!procEntry)
2006 return 0;
2007
2008 // check spell triggering us
2009 if (Spell const* spell = eventInfo.GetProcSpell())
2010 {
2011 // Do not allow auras to proc from effect triggered from itself
2012 if (spell->IsTriggeredByAura(m_spellInfo))
2013 return 0;
2014
2015 // check if aura can proc when spell is triggered (exception for hunter auto shot & wands)
2017 if (spell->IsTriggered() && !spell->GetSpellInfo()->HasAttribute(SPELL_ATTR3_NOT_A_PROC))
2018 return 0;
2019
2020 if (spell->m_CastItem && (procEntry->AttributesMask & PROC_ATTR_CANT_PROC_FROM_ITEM_CAST))
2021 return 0;
2022 }
2023
2024 // check don't break stealth attr present
2026 {
2027 if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo())
2028 if (spellInfo->HasAttribute(SPELL_ATTR0_CU_DONT_BREAK_STEALTH))
2029 return 0;
2030 }
2031
2032 // check if we have charges to proc with
2033 if (IsUsingCharges())
2034 {
2035 if (!GetCharges())
2036 return 0;
2037
2038 if (procEntry->AttributesMask & PROC_ATTR_REQ_SPELLMOD)
2039 if (Spell const* spell = eventInfo.GetProcSpell())
2040 if (!spell->m_appliedMods.count(const_cast<Aura*>(this)))
2041 return 0;
2042 }
2043
2044 // check proc cooldown
2045 if (IsProcOnCooldown(now))
2046 return 0;
2047
2048 // do checks against db data
2049 if (!SpellMgr::CanSpellTriggerProcOnEvent(*procEntry, eventInfo))
2050 return 0;
2051
2052 // do checks using conditions table
2053 if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_SPELL_PROC, GetId(), eventInfo.GetActor(), eventInfo.GetActionTarget()))
2054 return 0;
2055
2056 // AuraScript Hook
2057 bool check = const_cast<Aura*>(this)->CallScriptCheckProcHandlers(aurApp, eventInfo);
2058 if (!check)
2059 return 0;
2060
2061 // At least one effect has to pass checks to proc aura
2062 uint8 procEffectMask = aurApp->GetEffectMask();
2063 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
2064 if (procEffectMask & (1u << i))
2065 if ((procEntry->DisableEffectsMask & (1u << i)) || !GetEffect(i)->CheckEffectProc(aurApp, eventInfo))
2066 procEffectMask &= ~(1u << i);
2067
2068 if (!procEffectMask)
2069 return 0;
2070
2072 // do allow additional requirements for procs
2073 // this is needed because this is the last moment in which you can prevent aura charge drop on proc
2074 // and possibly a way to prevent default checks (if there're going to be any)
2075
2076 // Check if current equipment meets aura requirements
2077 // do that only for passive spells
2079 Unit* target = aurApp->GetTarget();
2080 if (IsPassive() && target->GetTypeId() == TYPEID_PLAYER && GetSpellInfo()->EquippedItemClass != -1)
2081 {
2083 {
2084 Item* item = nullptr;
2086 {
2087 if (target->ToPlayer()->IsInFeralForm())
2088 return 0;
2089
2090 if (DamageInfo const* damageInfo = eventInfo.GetDamageInfo())
2091 {
2092 switch (damageInfo->GetAttackType())
2093 {
2094 case BASE_ATTACK:
2096 break;
2097 case OFF_ATTACK:
2099 break;
2100 default:
2102 break;
2103 }
2104 }
2105 }
2107 {
2108 // Check if player is wearing shield
2110 }
2111
2112 if (!item || item->IsBroken() || !item->IsFitToSpellRequirements(GetSpellInfo()))
2113 return 0;
2114 }
2115 }
2116
2117 if (roll_chance_f(CalcProcChance(*procEntry, eventInfo)))
2118 return procEffectMask;
2119
2120 return 0;
2121}
2122
2123float Aura::CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const
2124{
2125 float chance = procEntry.Chance;
2126 // calculate chances depending on unit with caster's data
2127 // so talents modifying chances and judgements will have properly calculated proc chance
2128 if (Unit* caster = GetCaster())
2129 {
2130 // calculate ppm chance if present and we're using weapon
2131 if (eventInfo.GetDamageInfo() && procEntry.ProcsPerMinute != 0)
2132 {
2133 uint32 WeaponSpeed = caster->GetAttackTime(eventInfo.GetDamageInfo()->GetAttackType());
2134 chance = caster->GetPPMProcChance(WeaponSpeed, procEntry.ProcsPerMinute, GetSpellInfo());
2135 }
2136 // apply chance modifer aura, applies also to ppm chance (see improved judgement of light spell)
2137 if (Player* modOwner = caster->GetSpellModOwner())
2138 modOwner->ApplySpellMod(GetId(), SPELLMOD_CHANCE_OF_SUCCESS, chance);
2139 }
2140
2141 // proc chance is reduced by an additional 3.333% per level past 60
2142 if ((procEntry.AttributesMask & PROC_ATTR_REDUCE_PROC_60) && eventInfo.GetActor()->GetLevel() > 60)
2143 chance = std::max(0.f, (1.f - ((eventInfo.GetActor()->GetLevel() - 60) * 1.f / 30.f)) * chance);
2144
2145 return chance;
2146}
2147
2148void Aura::TriggerProcOnEvent(uint8 procEffectMask, AuraApplication* aurApp, ProcEventInfo& eventInfo)
2149{
2150 bool prevented = CallScriptProcHandlers(aurApp, eventInfo);
2151 if (!prevented)
2152 {
2153 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
2154 {
2155 if (!(procEffectMask & (1 << i)))
2156 continue;
2157
2158 // OnEffectProc / AfterEffectProc hooks handled in AuraEffect::HandleProc()
2159 if (aurApp->HasEffect(i))
2160 GetEffect(i)->HandleProc(aurApp, eventInfo);
2161 }
2162
2163 CallScriptAfterProcHandlers(aurApp, eventInfo);
2164 }
2165
2166 // Remove aura if we've used last charge to proc
2167 if (IsUsingCharges() && !GetCharges())
2168 Remove();
2169}
2170
2172{
2174 delete aurApp;
2175
2176 _removedApplications.clear();
2177}
2178
2180{
2181 sScriptMgr->CreateAuraScripts(m_spellInfo->Id, m_loadedScripts, this);
2182 for (auto itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
2183 {
2184 TC_LOG_DEBUG("spells", "Aura::LoadScripts: Script `{}` for aura `{}` is loaded now", (*itr)->_GetScriptName()->c_str(), m_spellInfo->Id);
2185 (*itr)->Register();
2186 }
2187}
2188
2190{
2191 bool result = true;
2192 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2193 {
2194 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_AREA_TARGET);
2195 auto hookItrEnd = (*scritr)->DoCheckAreaTarget.end(), hookItr = (*scritr)->DoCheckAreaTarget.begin();
2196 for (; hookItr != hookItrEnd; ++hookItr)
2197 result &= hookItr->Call(*scritr, target);
2198
2199 (*scritr)->_FinishScriptCall();
2200 }
2201 return result;
2202}
2203
2205{
2206 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2207 {
2208 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_DISPEL);
2209 auto hookItrEnd = (*scritr)->OnDispel.end(), hookItr = (*scritr)->OnDispel.begin();
2210 for (; hookItr != hookItrEnd; ++hookItr)
2211 hookItr->Call(*scritr, dispelInfo);
2212
2213 (*scritr)->_FinishScriptCall();
2214 }
2215}
2216
2218{
2219 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2220 {
2221 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_DISPEL);
2222 auto hookItrEnd = (*scritr)->AfterDispel.end(), hookItr = (*scritr)->AfterDispel.begin();
2223 for (; hookItr != hookItrEnd; ++hookItr)
2224 hookItr->Call(*scritr, dispelInfo);
2225
2226 (*scritr)->_FinishScriptCall();
2227 }
2228}
2229
2231{
2232 bool preventDefault = false;
2233 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2234 {
2235 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_APPLY, aurApp);
2236 auto effEndItr = (*scritr)->OnEffectApply.end(), effItr = (*scritr)->OnEffectApply.begin();
2237 for (; effItr != effEndItr; ++effItr)
2238 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2239 effItr->Call(*scritr, aurEff, mode);
2240
2241 if (!preventDefault)
2242 preventDefault = (*scritr)->_IsDefaultActionPrevented();
2243
2244 (*scritr)->_FinishScriptCall();
2245 }
2246
2247 return preventDefault;
2248}
2249
2251{
2252 bool preventDefault = false;
2253 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2254 {
2255 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_REMOVE, aurApp);
2256 auto effEndItr = (*scritr)->OnEffectRemove.end(), effItr = (*scritr)->OnEffectRemove.begin();
2257 for (; effItr != effEndItr; ++effItr)
2258 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2259 effItr->Call(*scritr, aurEff, mode);
2260
2261 if (!preventDefault)
2262 preventDefault = (*scritr)->_IsDefaultActionPrevented();
2263
2264 (*scritr)->_FinishScriptCall();
2265 }
2266 return preventDefault;
2267}
2268
2270{
2271 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2272 {
2273 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_APPLY, aurApp);
2274 auto effEndItr = (*scritr)->AfterEffectApply.end(), effItr = (*scritr)->AfterEffectApply.begin();
2275 for (; effItr != effEndItr; ++effItr)
2276 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2277 effItr->Call(*scritr, aurEff, mode);
2278
2279 (*scritr)->_FinishScriptCall();
2280 }
2281}
2282
2284{
2285 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2286 {
2287 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_REMOVE, aurApp);
2288 auto effEndItr = (*scritr)->AfterEffectRemove.end(), effItr = (*scritr)->AfterEffectRemove.begin();
2289 for (; effItr != effEndItr; ++effItr)
2290 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2291 effItr->Call(*scritr, aurEff, mode);
2292
2293 (*scritr)->_FinishScriptCall();
2294 }
2295}
2296
2298{
2299 bool preventDefault = false;
2300 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2301 {
2302 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PERIODIC, aurApp);
2303 auto effEndItr = (*scritr)->OnEffectPeriodic.end(), effItr = (*scritr)->OnEffectPeriodic.begin();
2304 for (; effItr != effEndItr; ++effItr)
2305 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2306 effItr->Call(*scritr, aurEff);
2307
2308 if (!preventDefault)
2309 preventDefault = (*scritr)->_IsDefaultActionPrevented();
2310
2311 (*scritr)->_FinishScriptCall();
2312 }
2313
2314 return preventDefault;
2315}
2316
2318{
2319 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2320 {
2321 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_UPDATE_PERIODIC);
2322 auto effEndItr = (*scritr)->OnEffectUpdatePeriodic.end(), effItr = (*scritr)->OnEffectUpdatePeriodic.begin();
2323 for (; effItr != effEndItr; ++effItr)
2324 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2325 effItr->Call(*scritr, aurEff);
2326
2327 (*scritr)->_FinishScriptCall();
2328 }
2329}
2330
2331void Aura::CallScriptEffectCalcAmountHandlers(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated)
2332{
2333 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2334 {
2335 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT);
2336 auto effEndItr = (*scritr)->DoEffectCalcAmount.end(), effItr = (*scritr)->DoEffectCalcAmount.begin();
2337 for (; effItr != effEndItr; ++effItr)
2338 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2339 effItr->Call(*scritr, aurEff, amount, canBeRecalculated);
2340
2341 (*scritr)->_FinishScriptCall();
2342 }
2343}
2344
2345void Aura::CallScriptEffectCalcPeriodicHandlers(AuraEffect const* aurEff, bool& isPeriodic, int32& amplitude)
2346{
2347 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2348 {
2349 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC);
2350 auto effEndItr = (*scritr)->DoEffectCalcPeriodic.end(), effItr = (*scritr)->DoEffectCalcPeriodic.begin();
2351 for (; effItr != effEndItr; ++effItr)
2352 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2353 effItr->Call(*scritr, aurEff, isPeriodic, amplitude);
2354
2355 (*scritr)->_FinishScriptCall();
2356 }
2357}
2358
2360{
2361 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2362 {
2363 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD);
2364 auto effEndItr = (*scritr)->DoEffectCalcSpellMod.end(), effItr = (*scritr)->DoEffectCalcSpellMod.begin();
2365 for (; effItr != effEndItr; ++effItr)
2366 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2367 effItr->Call(*scritr, aurEff, spellMod);
2368
2369 (*scritr)->_FinishScriptCall();
2370 }
2371}
2372
2373void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& defaultPrevented)
2374{
2375 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2376 {
2377 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp);
2378 auto effEndItr = (*scritr)->OnEffectAbsorb.end(), effItr = (*scritr)->OnEffectAbsorb.begin();
2379 for (; effItr != effEndItr; ++effItr)
2380
2381 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2382 effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount);
2383
2384 if (!defaultPrevented)
2385 defaultPrevented = (*scritr)->_IsDefaultActionPrevented();
2386
2387 (*scritr)->_FinishScriptCall();
2388 }
2389}
2390
2391void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount)
2392{
2393 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2394 {
2395 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp);
2396 auto effEndItr = (*scritr)->AfterEffectAbsorb.end(), effItr = (*scritr)->AfterEffectAbsorb.begin();
2397 for (; effItr != effEndItr; ++effItr)
2398 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2399 effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount);
2400
2401 (*scritr)->_FinishScriptCall();
2402 }
2403}
2404
2405void Aura::CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& /*defaultPrevented*/)
2406{
2407 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2408 {
2409 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_MANASHIELD, aurApp);
2410 auto effEndItr = (*scritr)->OnEffectManaShield.end(), effItr = (*scritr)->OnEffectManaShield.begin();
2411 for (; effItr != effEndItr; ++effItr)
2412 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2413 effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount);
2414
2415 (*scritr)->_FinishScriptCall();
2416 }
2417}
2418
2420{
2421 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2422 {
2423 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD, aurApp);
2424 auto effEndItr = (*scritr)->AfterEffectManaShield.end(), effItr = (*scritr)->AfterEffectManaShield.begin();
2425 for (; effItr != effEndItr; ++effItr)
2426 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2427 effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount);
2428
2429 (*scritr)->_FinishScriptCall();
2430 }
2431}
2432
2433void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& splitAmount)
2434{
2435 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2436 {
2437 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_SPLIT, aurApp);
2438 auto effEndItr = (*scritr)->OnEffectSplit.end(), effItr = (*scritr)->OnEffectSplit.begin();
2439 for (; effItr != effEndItr; ++effItr)
2440 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2441 effItr->Call(*scritr, aurEff, dmgInfo, splitAmount);
2442
2443 (*scritr)->_FinishScriptCall();
2444 }
2445}
2446
2448{
2449 bool result = true;
2450 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2451 {
2452 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_PROC, aurApp);
2453 auto hookItrEnd = (*scritr)->DoCheckProc.end(), hookItr = (*scritr)->DoCheckProc.begin();
2454 for (; hookItr != hookItrEnd; ++hookItr)
2455 result &= hookItr->Call(*scritr, eventInfo);
2456
2457 (*scritr)->_FinishScriptCall();
2458 }
2459
2460 return result;
2461}
2462
2464{
2465 bool prepare = true;
2466 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2467 {
2468 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PREPARE_PROC, aurApp);
2469 auto effEndItr = (*scritr)->DoPrepareProc.end(), effItr = (*scritr)->DoPrepareProc.begin();
2470 for (; effItr != effEndItr; ++effItr)
2471 effItr->Call(*scritr, eventInfo);
2472
2473 if (prepare)
2474 prepare = !(*scritr)->_IsDefaultActionPrevented();
2475
2476 (*scritr)->_FinishScriptCall();
2477 }
2478
2479 return prepare;
2480}
2481
2483{
2484 bool handled = false;
2485 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2486 {
2487 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PROC, aurApp);
2488 auto hookItrEnd = (*scritr)->OnProc.end(), hookItr = (*scritr)->OnProc.begin();
2489 for (; hookItr != hookItrEnd; ++hookItr)
2490 hookItr->Call(*scritr, eventInfo);
2491
2492 handled |= (*scritr)->_IsDefaultActionPrevented();
2493 (*scritr)->_FinishScriptCall();
2494 }
2495
2496 return handled;
2497}
2498
2500{
2501 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2502 {
2503 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_PROC, aurApp);
2504 auto hookItrEnd = (*scritr)->AfterProc.end(), hookItr = (*scritr)->AfterProc.begin();
2505 for (; hookItr != hookItrEnd; ++hookItr)
2506 hookItr->Call(*scritr, eventInfo);
2507
2508 (*scritr)->_FinishScriptCall();
2509 }
2510}
2511
2513{
2514 bool result = true;
2515 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2516 {
2517 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_EFFECT_PROC, aurApp);
2518 auto hookItrEnd = (*scritr)->DoCheckEffectProc.end(), hookItr = (*scritr)->DoCheckEffectProc.begin();
2519 for (; hookItr != hookItrEnd; ++hookItr)
2520 if (hookItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2521 result &= hookItr->Call(*scritr, aurEff, eventInfo);
2522
2523 (*scritr)->_FinishScriptCall();
2524 }
2525
2526 return result;
2527}
2528
2530{
2531 bool preventDefault = false;
2532 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2533 {
2534 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PROC, aurApp);
2535 auto effEndItr = (*scritr)->OnEffectProc.end(), effItr = (*scritr)->OnEffectProc.begin();
2536 for (; effItr != effEndItr; ++effItr)
2537 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2538 effItr->Call(*scritr, aurEff, eventInfo);
2539
2540 if (!preventDefault)
2541 preventDefault = (*scritr)->_IsDefaultActionPrevented();
2542
2543 (*scritr)->_FinishScriptCall();
2544 }
2545 return preventDefault;
2546}
2547
2549{
2550 for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
2551 {
2552 (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC, aurApp);
2553 auto effEndItr = (*scritr)->AfterEffectProc.end(), effItr = (*scritr)->AfterEffectProc.begin();
2554 for (; effItr != effEndItr; ++effItr)
2555 if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2556 effItr->Call(*scritr, aurEff, eventInfo);
2557
2558 (*scritr)->_FinishScriptCall();
2559 }
2560}
2561
2562std::string Aura::GetDebugInfo() const
2563{
2564 std::stringstream sstr;
2565 sstr << std::boolalpha
2566 << "Id: " << GetId() << " Name: '" << GetSpellInfo()->SpellName[sWorld->GetDefaultDbcLocale()] << "' Caster: " << GetCasterGUID().ToString()
2567 << "\nOwner: " << (GetOwner() ? GetOwner()->GetDebugInfo() : "NULL");
2568 return sstr.str();
2569}
2570
2572 : Aura(createInfo)
2573{
2575 LoadScripts();
2576 _InitEffects(createInfo._auraEffectMask, createInfo.Caster, createInfo.BaseAmount);
2577 GetUnitOwner()->_AddAura(this, createInfo.Caster);
2578}
2579
2581{
2582 Aura::_ApplyForTarget(target, caster, aurApp);
2583
2584 // register aura diminishing on apply
2585 if (DiminishingGroup group = GetDiminishGroup())
2586 target->ApplyDiminishingAura(group, true);
2587}
2588
2590{
2591 Aura::_UnapplyForTarget(target, caster, aurApp);
2592
2593 // unregister aura diminishing (and store last time)
2594 if (DiminishingGroup group = GetDiminishGroup())
2595 target->ApplyDiminishingAura(group, false);
2596}
2597
2599{
2600 if (IsRemoved())
2601 return;
2602 GetUnitOwner()->RemoveOwnedAura(this, removeMode);
2603}
2604
2605void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint8>& targets, Unit* caster)
2606{
2607 if (GetSpellInfo()->HasAttribute(SPELL_ATTR7_DISABLE_AURA_WHILE_DEAD) && !GetUnitOwner()->IsAlive())
2608 return;
2609
2610 Unit* ref = caster;
2611 if (!ref)
2612 ref = GetUnitOwner();
2613
2614 // add non area aura targets
2615 // static applications go through spell system first, so we assume they meet conditions
2616 for (auto const& targetPair : _staticApplications)
2617 {
2618 Unit* target = ObjectAccessor::GetUnit(*GetUnitOwner(), targetPair.first);
2619 if (!target && targetPair.first == GetUnitOwner()->GetGUID())
2620 target = GetUnitOwner();
2621
2622 if (target)
2623 targets.emplace(target, targetPair.second);
2624 }
2625
2626 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
2627 {
2628 if (!HasEffect(spellEffectInfo.EffectIndex))
2629 continue;
2630
2631 // area auras only
2632 if (spellEffectInfo.Effect == SPELL_EFFECT_APPLY_AURA)
2633 continue;
2634
2635 // skip area update if owner is not in world!
2636 if (!GetUnitOwner()->IsInWorld())
2637 continue;
2638
2640 continue;
2641
2642 std::vector<Unit*> units;
2643 ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions;
2644
2645 float radius = spellEffectInfo.CalcRadius(ref);
2646 float extraSearchRadius = 0.0f;
2647
2649 switch (spellEffectInfo.Effect)
2650 {
2652 selectionType = TARGET_CHECK_PARTY;
2653 break;
2655 selectionType = TARGET_CHECK_RAID;
2656 break;
2658 selectionType = TARGET_CHECK_ALLY;
2659 break;
2661 selectionType = TARGET_CHECK_ENEMY;
2662 extraSearchRadius = radius > 0.0f ? EXTRA_CELL_SEARCH_RADIUS : 0.0f;
2663 break;
2665 if (!condList || sConditionMgr->IsObjectMeetToConditions(GetUnitOwner(), ref, *condList))
2666 units.push_back(GetUnitOwner());
2667 [[fallthrough]];
2669 {
2670 if (Unit* owner = GetUnitOwner()->GetCharmerOrOwner())
2671 if (GetUnitOwner()->IsWithinDistInMap(owner, radius))
2672 if (!condList || sConditionMgr->IsObjectMeetToConditions(owner, ref, *condList))
2673 units.push_back(owner);
2674 break;
2675 }
2676 default:
2677 break;
2678 }
2679
2680 if (selectionType != TARGET_CHECK_DEFAULT)
2681 {
2682 Trinity::WorldObjectSpellAreaTargetCheck check(radius, GetUnitOwner(), ref, GetUnitOwner(), m_spellInfo, selectionType, condList);
2684 Cell::VisitAllObjects(GetUnitOwner(), searcher, radius + extraSearchRadius);
2685 }
2686
2687 for (Unit* unit : units)
2688 targets[unit] |= 1 << spellEffectInfo.EffectIndex;
2689 }
2690}
2691
2693{
2694 // only valid for non-area auras
2695 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
2696 {
2697 if ((effMask & (1 << spellEffectInfo.EffectIndex)) && !spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA))
2698 effMask &= ~(1 << spellEffectInfo.EffectIndex);
2699 }
2700
2701 if (!effMask)
2702 return;
2703
2704 _staticApplications[target->GetGUID()] |= effMask;
2705}
2706
2708 : Aura(createInfo)
2709{
2710 LoadScripts();
2712 ASSERT(GetDynobjOwner()->IsInWorld());
2713 ASSERT(createInfo.Caster);
2714 ASSERT(GetDynobjOwner()->GetMap() == createInfo.Caster->GetMap());
2715 _InitEffects(createInfo._auraEffectMask, createInfo.Caster, createInfo.BaseAmount);
2716 GetDynobjOwner()->SetAura(this);
2717}
2718
2720{
2721 if (IsRemoved())
2722 return;
2723 _Remove(removeMode);
2724}
2725
2726void DynObjAura::FillTargetMap(std::unordered_map<Unit*, uint8>& targets, Unit* /*caster*/)
2727{
2728 Unit* dynObjOwnerCaster = GetDynobjOwner()->GetCaster();
2729 float radius = GetDynobjOwner()->GetRadius();
2730
2731 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
2732 {
2733 if (!HasEffect(spellEffectInfo.EffectIndex))
2734 continue;
2735
2736 // we can't use effect type like area auras to determine check type, check targets
2737 SpellTargetCheckTypes selectionType = spellEffectInfo.TargetA.GetCheckType();
2738 if (spellEffectInfo.TargetB.GetReferenceType() == TARGET_REFERENCE_TYPE_DEST)
2739 selectionType = spellEffectInfo.TargetB.GetCheckType();
2740
2741 std::vector<Unit*> units;
2742 ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions;
2743
2744 Trinity::WorldObjectSpellAreaTargetCheck check(radius, GetDynobjOwner(), dynObjOwnerCaster, dynObjOwnerCaster, m_spellInfo, selectionType, condList);
2746 Cell::VisitAllObjects(GetDynobjOwner(), searcher, radius);
2747
2748 for (Unit* unit : units)
2749 targets[unit] |= 1 << spellEffectInfo.EffectIndex;
2750 }
2751}
2752
2753bool ChargeDropEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
2754{
2755 // _base is always valid (look in Aura::_Remove())
2757 return true;
2758}
@ IN_MILLISECONDS
Definition Common.h:35
#define sConditionMgr
@ CONDITION_SOURCE_TYPE_SPELL_PROC
std::vector< Condition * > ConditionContainer
#define MAX_EFFECT_MASK
Definition DBCEnums.h:389
#define MAX_SPELL_EFFECTS
Definition DBCEnums.h:388
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint64_t uint64
Definition Define.h:132
uint32_t uint32
Definition Define.h:133
uint16 flags
std::chrono::steady_clock::time_point TimePoint
time_point shorthand typedefs
Definition Duration.h:36
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
#define ABORT
Definition Errors.h:74
#define ASSERT_NODEBUGINFO
Definition Errors.h:69
#define ASSERT
Definition Errors.h:68
@ ITEM_CLASS_ARMOR
@ ITEM_CLASS_WEAPON
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define TC_LOG_FATAL(filterType__,...)
Definition Log.h:168
#define EXTRA_CELL_SEARCH_RADIUS
@ TYPEID_DYNAMICOBJECT
Definition ObjectGuid.h:41
@ TYPEID_UNIT
Definition ObjectGuid.h:38
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
@ EQUIPMENT_SLOT_MAINHAND
Definition Player.h:567
@ EQUIPMENT_SLOT_OFFHAND
Definition Player.h:568
@ EQUIPMENT_SLOT_RANGED
Definition Player.h:569
#define INVENTORY_SLOT_BAG_0
Definition Player.h:547
bool roll_chance_f(float chance)
Definition Random.h:53
bool roll_chance_i(int chance)
Definition Random.h:59
#define sScriptMgr
Definition ScriptMgr.h:1168
@ EFFECT_0
@ SPELL_ATTR7_DISABLE_AURA_WHILE_DEAD
@ 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_PERSISTENT_AREA_AURA
@ SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
@ SPELL_EFFECT_APPLY_AURA
@ SPELL_EFFECT_APPLY_AREA_AURA_OWNER
@ SPELL_ATTR5_HASTE_AFFECT_DURATION
@ SPELL_ATTR5_HIDE_DURATION
@ SPELL_ATTR2_CANT_CRIT
@ SPELL_ATTR2_NOT_NEED_SHAPESHIFT
@ SPELL_ATTR1_DONT_REFRESH_DURATION_ON_RECAST
@ SPELL_ATTR3_NOT_A_PROC
@ SPELL_ATTR3_STACK_FOR_DIFF_CASTERS
@ SPELL_ATTR3_CAN_PROC_FROM_PROCS
@ SPELL_ATTR3_IGNORE_PROC_SUBCLASS_MASK
@ OFF_ATTACK
@ BASE_ATTACK
@ CLASS_DEATH_KNIGHT
@ IMMUNITY_ID
@ SPELLFAMILY_PRIEST
@ SPELLFAMILY_WARLOCK
@ SPELLFAMILY_MAGE
@ SPELLFAMILY_GENERIC
@ SPELLFAMILY_WARRIOR
@ SPELLFAMILY_PALADIN
@ SPELLFAMILY_HUNTER
@ SPELLFAMILY_ROGUE
@ SPELLFAMILY_DRUID
@ SPELLFAMILY_DEATHKNIGHT
Powers
@ POWER_RAGE
@ POWER_HEALTH
@ POWER_RUNIC_POWER
@ POWER_ENERGY
@ POWER_MANA
@ SPELL_ATTR0_NOT_SHAPESHIFT
DiminishingGroup
@ DIMINISHING_NONE
@ SPELL_ATTR6_DONT_CONSUME_PROC_CHARGES
#define MAX_AURAS
AuraRemoveMode
@ AURA_REMOVE_NONE
@ AURA_REMOVE_BY_DEFAULT
@ AURA_REMOVE_BY_DEATH
@ AURA_REMOVE_BY_EXPIRE
@ AURA_REMOVE_BY_ENEMY_SPELL
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_PERIODIC_DAMAGE
@ SPELL_AURA_PERIODIC_HASTE
@ SPELL_AURA_TRACK_RESOURCES
@ SPELL_AURA_ABILITY_IGNORE_AURASTATE
@ SPELL_AURA_OBS_MOD_HEALTH
@ SPELL_AURA_PERIODIC_MANA_LEECH
@ SPELL_AURA_OBS_MOD_POWER
@ SPELL_AURA_CONTROL_VEHICLE
@ SPELL_AURA_PERIODIC_HEAL
@ SPELL_AURA_DUMMY
@ SPELL_AURA_ABILITY_PERIODIC_CRIT
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE
@ SPELL_AURA_PERIODIC_ENERGIZE
@ SPELL_AURA_PERIODIC_LEECH
@ SPELL_AURA_POWER_BURN
@ SPELL_AURA_PERIODIC_DUMMY
@ SPELL_AURA_MOD_STEALTH
@ SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL
@ SPELL_AURA_MOD_DISPEL_RESIST
@ AFLAG_POSITIVE
@ AFLAG_NONE
@ AFLAG_NEGATIVE
@ AFLAG_CASTER
@ AFLAG_DURATION
AuraObjectType
@ DYNOBJ_AURA_TYPE
@ UNIT_AURA_TYPE
#define UPDATE_TARGET_MAP_INTERVAL
Definition SpellAuras.h:44
@ SPELLMOD_CHANCE_OF_SUCCESS
@ SPELLMOD_DURATION
@ SPELLMOD_CHARGES
@ SPELLMOD_RESIST_DISPEL_CHANCE
@ TRIGGERED_FULL_MASK
Will return SPELL_FAILED_DONT_REPORT in CheckCast functions.
@ SPELLVALUE_AURA_STACK
@ SPELLVALUE_BASE_POINT0
@ SPELL_COOLDOWN_FLAG_NONE
SpellTargetCheckTypes
Definition SpellInfo.h:78
@ TARGET_CHECK_PARTY
Definition SpellInfo.h:83
@ TARGET_CHECK_ENEMY
Definition SpellInfo.h:81
@ TARGET_CHECK_DEFAULT
Definition SpellInfo.h:79
@ TARGET_CHECK_ALLY
Definition SpellInfo.h:82
@ TARGET_CHECK_RAID
Definition SpellInfo.h:84
@ SPELL_ATTR0_CU_ENCHANT_PROC
Definition SpellInfo.h:141
@ SPELL_ATTR0_CU_DONT_BREAK_STEALTH
Definition SpellInfo.h:147
@ SPELL_ATTR0_CU_AURA_CANNOT_BE_SAVED
Definition SpellInfo.h:165
SpellSpecificType
Definition SpellInfo.h:113
@ SPELL_SPECIFIC_JUDGEMENT
Definition SpellInfo.h:125
@ SPELL_SPECIFIC_MAGE_POLYMORPH
Definition SpellInfo.h:124
@ TARGET_REFERENCE_TYPE_DEST
Definition SpellInfo.h:58
std::pair< SpellAreaForAreaMap::const_iterator, SpellAreaForAreaMap::const_iterator > SpellAreaForAreaMapBounds
Definition SpellMgr.h:493
@ PROC_ATTR_CANT_PROC_FROM_ITEM_CAST
Definition SpellMgr.h:244
@ PROC_ATTR_REDUCE_PROC_60
Definition SpellMgr.h:243
@ PROC_ATTR_TRIGGERED_CAN_PROC
Definition SpellMgr.h:240
@ PROC_ATTR_REQ_SPELLMOD
Definition SpellMgr.h:242
@ SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER
Definition SpellMgr.h:328
@ SPELL_GROUP_STACK_RULE_EXCLUSIVE
Definition SpellMgr.h:327
@ SPELL_GROUP_STACK_RULE_DEFAULT
Definition SpellMgr.h:326
@ SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT
Definition SpellMgr.h:329
@ SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST
Definition SpellMgr.h:330
#define sSpellMgr
Definition SpellMgr.h:738
@ SPELL_LINK_AURA
Definition SpellMgr.h:106
@ AUTO_ATTACK_PROC_FLAG_MASK
Definition SpellMgr.h:154
@ AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC
@ AURA_SCRIPT_HOOK_CHECK_EFFECT_PROC
@ AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT
@ AURA_SCRIPT_HOOK_EFFECT_REMOVE
@ AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD
@ AURA_SCRIPT_HOOK_PREPARE_PROC
@ AURA_SCRIPT_HOOK_EFFECT_AFTER_APPLY
@ AURA_SCRIPT_HOOK_EFFECT_AFTER_REMOVE
@ AURA_SCRIPT_HOOK_AFTER_PROC
@ AURA_SCRIPT_HOOK_CHECK_AREA_TARGET
@ AURA_SCRIPT_HOOK_EFFECT_MANASHIELD
@ AURA_SCRIPT_HOOK_PROC
@ AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB
@ AURA_SCRIPT_HOOK_DISPEL
@ AURA_SCRIPT_HOOK_EFFECT_APPLY
@ AURA_SCRIPT_HOOK_EFFECT_PERIODIC
@ AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC
@ AURA_SCRIPT_HOOK_EFFECT_ABSORB
@ AURA_SCRIPT_HOOK_EFFECT_PROC
@ AURA_SCRIPT_HOOK_EFFECT_SPLIT
@ AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD
@ AURA_SCRIPT_HOOK_AFTER_DISPEL
@ AURA_SCRIPT_HOOK_CHECK_PROC
@ AURA_SCRIPT_HOOK_EFFECT_UPDATE_PERIODIC
@ UNIT_STATE_ISOLATED
Definition Unit.h:233
@ DOT
Definition Unit.h:355
std::list< Unit * > UnitList
Definition Unit.h:105
@ UNIT_MOD_CAST_SPEED
T RoundToInterval(T &num, T floor, T ceil)
Definition Util.h:89
T CalculatePct(T base, U pct)
Definition Util.h:71
Unit * GetTarget() const
Definition SpellAuras.h:66
std::string GetDebugInfo() const
void ClientUpdate(bool remove=false)
void BuildUpdatePacket(ByteBuffer &data, bool remove) const
uint8 _effectsToApply
Definition SpellAuras.h:56
bool _needClientUpdate
Definition SpellAuras.h:57
uint8 GetEffectMask() const
Definition SpellAuras.h:71
void _HandleEffect(uint8 effIndex, bool apply)
void _InitFlags(Unit *caster, uint8 effMask)
void UpdateApplyEffectMask(uint8 newEffMask, bool canHandleNewEffects)
Aura * GetBase() const
Definition SpellAuras.h:67
uint8 GetSlot() const
Definition SpellAuras.h:69
AuraApplication(Unit *target, Unit *caster, Aura *base, uint8 effMask)
void SetNeedClientUpdate()
Definition SpellAuras.h:82
bool IsSelfcast() const
Definition SpellAuras.h:74
AuraRemoveMode GetRemoveMode() const
Definition SpellAuras.h:80
bool HasEffect(uint8 effect) const
Definition SpellAuras.h:72
Unit *const _target
Definition SpellAuras.h:51
AuraType GetAuraType() const
SpellEffIndex GetEffIndex() const
void Update(uint32 diff, Unit *caster)
uint32 GetId() const
void HandleEffect(AuraApplication *aurApp, uint8 mode, bool apply)
uint32 GetTotalTicks() const
void CleanupTriggeredSpells(Unit *target)
void HandleProc(AuraApplication *aurApp, ProcEventInfo &eventInfo)
void RecalculateAmount()
bool CheckEffectProc(AuraApplication *aurApp, ProcEventInfo &eventInfo) const
int32 GetAmount() const
void HandleAllEffects(AuraApplication *aurApp, uint8 mode, bool apply)
bool HasMoreThanOneEffectForType(AuraType auraType) const
UnitAura * ToUnitAura()
Definition SpellAuras.h:257
void ResetProcCooldown()
virtual void _UnapplyForTarget(Unit *target, Unit *caster, AuraApplication *auraApp)
void GetApplicationVector(std::vector< AuraApplication * > &applicationVector) const
bool CanBeSaved() const
static Aura * Create(AuraCreateInfo &createInfo)
bool CheckAreaTarget(Unit *target)
bool IsArea() const
int32 GetMaxDuration() const
Definition SpellAuras.h:143
void CallScriptEffectAbsorbHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, DamageInfo &dmgInfo, uint32 &absorbAmount, bool &defaultPrevented)
virtual std::string GetDebugInfo() const
Trinity::unique_trackable_ptr< Aura > m_scriptRef
Definition SpellAuras.h:316
AuraEffect * m_effects[MAX_SPELL_EFFECTS]
Definition SpellAuras.h:301
void DropChargeDelayed(uint32 delay, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
static Aura * TryCreate(AuraCreateInfo &createInfo)
void CallScriptDispel(DispelInfo *dispelInfo)
static Aura * TryRefreshStackOrCreate(AuraCreateInfo &createInfo, bool updateEffectMask=true)
void SetCritChance(float val)
Definition SpellAuras.h:172
void SetStackAmount(uint8 num)
void CallScriptEffectCalcSpellModHandlers(AuraEffect const *aurEff, SpellModifier *&spellMod)
int32 m_maxDuration
Definition SpellAuras.h:292
Unit * GetUnitOwner() const
Definition SpellAuras.h:122
AuraApplication const * GetApplicationOfTarget(ObjectGuid guid) const
Definition SpellAuras.h:209
void RefreshDuration(bool withMods=false)
bool CanBeSentToClient() const
DynamicObject * GetDynobjOwner() const
Definition SpellAuras.h:123
bool CallScriptCheckAreaTargetHandlers(Unit *target)
bool CallScriptEffectRemoveHandlers(AuraEffect const *aurEff, AuraApplication const *aurApp, AuraEffectHandleModes mode)
void CallScriptEffectCalcAmountHandlers(AuraEffect const *aurEff, int32 &amount, bool &canBeRecalculated)
bool CallScriptEffectPeriodicHandlers(AuraEffect const *aurEff, AuraApplication const *aurApp)
void CallScriptAfterProcHandlers(AuraApplication const *aurApp, ProcEventInfo &eventInfo)
uint8 m_stackAmount
Definition SpellAuras.h:299
ObjectGuid GetCasterGUID() const
Definition SpellAuras.h:119
bool HasEffect(uint8 effIndex) const
Definition SpellAuras.h:199
int32 m_duration
Definition SpellAuras.h:293
void RefreshTimers(bool resetPeriodicTimer)
bool IsRemoved() const
Definition SpellAuras.h:184
void PrepareProcToTrigger(AuraApplication *aurApp, ProcEventInfo &eventInfo, TimePoint now)
std::vector< AuraApplication * > _removedApplications
Definition SpellAuras.h:313
void Update(uint32 diff, Unit *caster)
uint8 GetCasterLevel() const
Definition SpellAuras.h:170
void TriggerProcOnEvent(uint8 procEffectMask, AuraApplication *aurApp, ProcEventInfo &eventInfo)
WorldObject * GetOwner() const
Definition SpellAuras.h:121
uint8 GetProcEffectMask(AuraApplication *aurApp, ProcEventInfo &eventInfo, TimePoint now) const
bool IsSingleTargetWith(Aura const *aura) const
bool ModCharges(int32 num, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
bool CanStackWith(Aura const *existingAura) const
uint32 GetId() const
Definition SpellAuras.h:116
int32 CalcDispelChance(Unit const *auraTarget, bool offensive) const
void SaveCasterInfo(Unit *caster)
TimePoint m_procCooldown
Definition SpellAuras.h:310
void SetCanApplyResilience(bool val)
Definition SpellAuras.h:169
bool IsAppliedOnTarget(ObjectGuid guid) const
Definition SpellAuras.h:211
ApplicationMap m_applications
Definition SpellAuras.h:302
int32 GetDuration() const
Definition SpellAuras.h:148
bool IsUsingCharges() const
Definition SpellAuras.h:222
void UpdateOwner(uint32 diff, WorldObject *owner)
void UnregisterSingleTarget()
bool IsDeathPersistent() const
bool CallScriptPrepareProcHandlers(AuraApplication const *aurApp, ProcEventInfo &eventInfo)
bool HasEffectType(AuraType type) const
AuraEffect * GetEffect(uint8 effIndex) const
Definition SpellAuras.h:201
Unit * GetCaster() const
ObjectGuid const m_castItemGuid
Definition SpellAuras.h:288
void CallScriptAfterEffectApplyHandlers(AuraEffect const *aurEff, AuraApplication const *aurApp, AuraEffectHandleModes mode)
float CalcPeriodicCritChance(Unit const *caster) const
int32 m_timeCla
Definition SpellAuras.h:294
void SetCharges(uint8 charges)
bool CallScriptCheckProcHandlers(AuraApplication const *aurApp, ProcEventInfo &eventInfo)
bool CallScriptEffectApplyHandlers(AuraEffect const *aurEff, AuraApplication const *aurApp, AuraEffectHandleModes mode)
void CallScriptAfterEffectRemoveHandlers(AuraEffect const *aurEff, AuraApplication const *aurApp, AuraEffectHandleModes mode)
std::vector< AuraScript * > m_loadedScripts
Definition SpellAuras.h:269
void UpdateTargetMap(Unit *caster, bool apply=true)
void SetNeedClientUpdateForTargets() const
bool ModStackAmount(int32 num, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT, bool resetPeriodicTimer=true)
bool CallScriptEffectProcHandlers(AuraEffect const *aurEff, AuraApplication const *aurApp, ProcEventInfo &eventInfo)
void CallScriptAfterEffectProcHandlers(AuraEffect const *aurEff, AuraApplication const *aurApp, ProcEventInfo &eventInfo)
int32 CalcMaxDuration() const
Definition SpellAuras.h:145
void _InitEffects(uint8 effMask, Unit *caster, int32 const *baseAmount)
void SetDuration(int32 duration, bool withMods=false)
bool CallScriptProcHandlers(AuraApplication const *aurApp, ProcEventInfo &eventInfo)
void LoadScripts()
void AddProcCooldown(TimePoint cooldownEnd)
float CalcProcChance(SpellProcEntry const &procEntry, ProcEventInfo &eventInfo) const
void CallScriptEffectAfterAbsorbHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, DamageInfo &dmgInfo, uint32 &absorbAmount)
void CallScriptEffectManaShieldHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, DamageInfo &dmgInfo, uint32 &absorbAmount, bool &defaultPrevented)
SpellInfo const *const m_spellInfo
Definition SpellAuras.h:286
void CallScriptEffectSplitHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, DamageInfo &dmgInfo, uint32 &splitAmount)
AuraObjectType GetType() const
uint8 GetStackAmount() const
Definition SpellAuras.h:164
void _ApplyEffectForTargets(uint8 effIndex)
AuraScript * GetScriptByName(std::string const &scriptName) const
uint8 GetCharges() const
Definition SpellAuras.h:155
WorldObject *const m_owner
Definition SpellAuras.h:290
SpellInfo const * GetSpellInfo() const
Definition SpellAuras.h:115
ObjectGuid GetCastItemGUID() const
Definition SpellAuras.h:118
bool IsRemovedOnShapeLost(Unit *target) const
void CallScriptEffectCalcPeriodicHandlers(AuraEffect const *aurEff, bool &isPeriodic, int32 &amplitude)
CasterInfo _casterInfo
Definition SpellAuras.h:297
void SetMaxDuration(int32 duration)
Definition SpellAuras.h:144
bool CanBeAppliedOn(Unit *target)
void HandleAuraSpecificMods(AuraApplication const *aurApp, Unit *caster, bool apply, bool onReapply)
virtual ~Aura()
bool IsProcOnCooldown(TimePoint now) const
void SetIsSingleTarget(bool val)
Definition SpellAuras.h:189
void _DeleteRemovedApplications()
virtual void _ApplyForTarget(Unit *target, Unit *caster, AuraApplication *auraApp)
bool CallScriptCheckEffectProcHandlers(AuraEffect const *aurEff, AuraApplication const *aurApp, ProcEventInfo &eventInfo)
void ModChargesDelayed(int32 num, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
uint8 CalcMaxCharges() const
Definition SpellAuras.h:158
bool m_isUsingCharges
Definition SpellAuras.h:306
void CallScriptEffectUpdatePeriodicHandlers(AuraEffect *aurEff)
void RecalculateAmountOfEffects()
bool CanPeriodicTickCrit(Unit const *caster) const
virtual void FillTargetMap(std::unordered_map< Unit *, uint8 > &targets, Unit *caster)=0
bool IsPassive() const
bool m_isRemoved
Definition SpellAuras.h:304
Aura(AuraCreateInfo const &createInfo)
static uint8 BuildEffectMaskForOwner(SpellInfo const *spellProto, uint8 availableEffectMask, WorldObject *owner)
int32 m_updateTargetMapInterval
Definition SpellAuras.h:295
void SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, float critChance, bool applyResilience, int32 *amount)
void CallScriptEffectAfterManaShieldHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, DamageInfo &dmgInfo, uint32 &absorbAmount)
bool m_isSingleTarget
Definition SpellAuras.h:305
uint8 m_procCharges
Definition SpellAuras.h:298
bool IsPermanent() const
Definition SpellAuras.h:153
ChargeDropEvent * m_dropEvent
Definition SpellAuras.h:308
virtual void Remove(AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)=0
void CallScriptAfterDispel(DispelInfo *dispelInfo)
void _Remove(AuraRemoveMode removeMode)
bool IsSingleTarget() const
Definition SpellAuras.h:187
void ScheduleAbort()
AuraRemoveMode _mode
Definition SpellAuras.h:363
bool Execute(uint64, uint32) override
WeaponAttackType GetAttackType() const
Definition Unit.h:463
void FillTargetMap(std::unordered_map< Unit *, uint8 > &targets, Unit *caster) override
DynObjAura(AuraCreateInfo const &createInfo)
void Remove(AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT) override
void SetAura(Aura *aura)
Unit * GetCaster() const
float GetRadius() const
void AddEvent(BasicEvent *event, Milliseconds e_time, bool set_addtime=true)
Milliseconds CalculateTime(Milliseconds t_offset) const
Definition Item.h:62
bool IsBroken() const
Definition Item.h:105
bool IsFitToSpellRequirements(SpellInfo const *spellInfo) const
Definition Item.cpp:847
bool IsEmpty() const
Definition ObjectGuid.h:172
PackedGuidWriter WriteAsPacked() const
Definition ObjectGuid.h:152
std::string ToString() const
bool IsGameObject() const
Definition ObjectGuid.h:182
void Clear()
Definition ObjectGuid.h:150
static Creature * ToCreature(Object *o)
Definition Object.h:186
PackedGuid const & GetPackGUID() const
Definition Object.h:80
static Unit * ToUnit(Object *o)
Definition Object.h:192
bool IsInWorld() const
Definition Object.h:73
TypeID GetTypeId() const
Definition Object.h:93
float GetFloatValue(uint16 index) const
Definition Object.cpp:261
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
static Player * ToPlayer(Object *o)
Definition Object.h:180
void SetSpellModTakingSpell(Spell *spell, bool apply)
Definition Player.cpp:20934
void RemoveRunesByAuraEffect(AuraEffect const *aura)
Definition Player.cpp:24392
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6161
Item * GetUseableItemByPos(uint8 bag, uint8 slot) const
Definition Player.cpp:9569
void ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell *spell=nullptr) const
Definition Player.cpp:20807
Item * GetItemByGuid(ObjectGuid guid) const
Definition Player.cpp:9518
Unit * GetActionTarget() const
Definition Unit.h:509
Spell const * GetProcSpell() const
Definition Unit.h:522
uint32 GetTypeMask() const
Definition Unit.h:511
SpellInfo const * GetSpellInfo() const
Definition Unit.cpp:268
Unit * GetActor()
Definition Unit.h:508
DamageInfo * GetDamageInfo() const
Definition Unit.h:519
void SendCooldownEvent(SpellInfo const *spellInfo, uint32 itemId=0, Spell *spell=nullptr, bool startCooldown=true)
void ResetCooldown(uint32 spellId, bool update=false)
void AddCooldown(uint32 spellId, uint32 itemId, std::chrono::duration< Type, Period > cooldownDuration)
uint32 GetRemainingCooldown(SpellInfo const *spellInfo) const
bool HasCooldown(SpellInfo const *spellInfo, uint32 itemId=0, bool ignoreCategoryCooldown=false) const
void StartCooldown(SpellInfo const *spellInfo, uint32 itemId, Spell *spell=nullptr, bool onHold=false)
void BuildCooldownPacket(WorldPacket &data, uint8 flags, uint32 spellId, uint32 cooldown) const
uint32 SpellLevel
Definition SpellInfo.h:329
bool IsRankOf(SpellInfo const *spellInfo) const
flag96 SpellFamilyFlags
Definition SpellInfo.h:357
bool IsAuraExclusiveBySpecificPerCasterWith(SpellInfo const *spellInfo) const
uint32 ManaPerSecondPerLevel
Definition SpellInfo.h:335
bool IsDeathPersistent() const
bool IsCooldownStartedOnEvent() const
uint64 Stances
Definition SpellInfo.h:302
bool IsPassive() const
uint32 StackAmount
Definition SpellInfo.h:340
bool IsAuraExclusiveBySpecificWith(SpellInfo const *spellInfo) const
uint32 Id
Definition SpellInfo.h:289
uint32 ProcCharges
Definition SpellInfo.h:326
SpellSpecificType GetSpellSpecific() const
Powers PowerType
Definition SpellInfo.h:331
bool IsMultiSlotAura() const
int32 GetMaxDuration() const
int32 EquippedItemClass
Definition SpellInfo.h:344
uint32 ManaPerSecond
Definition SpellInfo.h:334
bool IsChanneled() const
bool HasAttribute(SpellAttr0 attribute) const
Definition SpellInfo.h:375
SpellDurationEntry const * DurationEntry
Definition SpellInfo.h:330
int32 GetDuration() const
bool HasAreaAuraEffect() const
bool IsDifferentRankOf(SpellInfo const *spellInfo) const
bool HasAura(AuraType aura) const
std::array< SpellEffectInfo, MAX_SPELL_EFFECTS > const & GetEffects() const
Definition SpellInfo.h:482
uint32 SpellFamilyName
Definition SpellInfo.h:356
std::array< char const *, 16 > SpellName
Definition SpellInfo.h:352
bool IsPositiveEffect(uint8 effIndex) const
bool IsSingleTarget() const
static bool CanSpellTriggerProcOnEvent(SpellProcEntry const &procEntry, ProcEventInfo &eventInfo)
Definition SpellMgr.cpp:501
Definition Spell.h:152
void AddStaticApplication(Unit *target, uint8 effMask)
void Remove(AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT) override
void FillTargetMap(std::unordered_map< Unit *, uint8 > &targets, Unit *caster) override
DiminishingGroup m_AuraDRGroup
Definition SpellAuras.h:339
DiminishingGroup GetDiminishGroup() const
Definition SpellAuras.h:334
void _ApplyForTarget(Unit *target, Unit *caster, AuraApplication *aurApp) override
std::unordered_map< ObjectGuid, uint8 > _staticApplications
Definition SpellAuras.h:340
UnitAura(AuraCreateInfo const &createInfo)
void _UnapplyForTarget(Unit *target, Unit *caster, AuraApplication *aurApp) override
Definition Unit.h:769
int32 ModifyHealth(int32 val)
Definition Unit.cpp:8381
int32 ModifyPower(Powers power, int32 val, bool withPowerUpdate=true)
Definition Unit.cpp:8439
void RemoveOwnedAura(AuraMap::iterator &i, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3561
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1384
Aura * GetAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4439
AuraApplication * GetVisibleAura(uint8 slot) const
Definition Unit.cpp:640
Aura * GetAuraOfRankedSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4457
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3638
void _UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode)
Definition Unit.cpp:3421
uint8 GetClass() const
Definition Unit.h:895
Spell * FindCurrentSpellBySpellId(uint32 spell_id) const
Definition Unit.cpp:3108
AuraApplication * GetAuraApplication(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraApplication *except=nullptr) const
Definition Unit.cpp:4420
Powers GetPowerType() const
Definition Unit.h:931
void RemoveVisibleAura(uint8 slot)
Definition Unit.cpp:654
void RemoveAurasWithFamily(SpellFamilyNames family, flag96 const &familyFlag, ObjectGuid casterGUID)
Definition Unit.cpp:4051
Aura * AddAura(uint32 spellId, Unit *target)
Definition Unit.cpp:11964
AuraEffect * GetAuraEffect(uint32 spellId, uint8 effIndex, ObjectGuid casterGUID=ObjectGuid::Empty) const
Definition Unit.cpp:4359
float SpellDamagePctDone(Unit *victim, SpellInfo const *spellProto, DamageEffectType damagetype) const
Definition Unit.cpp:6593
std::string GetDebugInfo() const override
Definition Unit.cpp:13950
virtual bool CanApplyResilience() const
Definition Unit.cpp:12027
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4535
std::map< uint8, AuraApplication * > VisibleAuraMap
Definition Unit.h:794
float SpellCritChanceDone(SpellInfo const *spellInfo, SpellSchoolMask schoolMask, WeaponAttackType attackType=BASE_ATTACK, bool isPeriodic=false) const
Definition Unit.cpp:7015
bool IsDuringRemoveFromWorld() const
Definition Unit.h:1786
Unit * GetCharmerOrOwner() const
Definition Unit.h:1265
uint32 GetMaxPower(Powers power) const
Definition Unit.h:936
void _AddAura(UnitAura *aura, Unit *caster)
Definition Unit.cpp:3275
uint32 GetHealth() const
Definition Unit.h:913
AuraEffect * GetAuraEffectOfRankedSpell(uint32 spellId, uint8 effIndex, ObjectGuid casterGUID=ObjectGuid::Empty) const
Definition Unit.cpp:4373
VisibleAuraMap const & GetVisibleAuras() const
Definition Unit.h:1571
int32 GetTotalAuraModifier(AuraType auraType) const
Definition Unit.cpp:4792
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply)
Definition Unit.cpp:8142
bool IsInFeralForm() const
Definition Unit.cpp:8969
void SetVisibleAura(uint8 slot, AuraApplication *aurApp)
Definition Unit.cpp:648
SpellHistory * GetSpellHistory()
Definition Unit.h:1484
float SpellHealingPctDone(Unit *victim, SpellInfo const *spellProto) const
Definition Unit.cpp:7478
AuraEffect * GetDummyAuraEffect(SpellFamilyNames name, uint32 iconId, uint8 effIndex) const
Definition Unit.cpp:4415
void GetPartyMembers(std::list< Unit * > &units)
Definition Unit.cpp:11911
uint32 GetPower(Powers power) const
Definition Unit.h:934
bool HasAuraTypeWithAffectMask(AuraType auraType, SpellInfo const *affectedSpell) const
Definition Unit.cpp:4564
std::list< AuraEffect * > AuraEffectList
Definition Unit.h:787
uint32 GetCreateMana() const
Definition Unit.h:1452
void ApplyDiminishingAura(DiminishingGroup group, bool apply)
Definition Unit.cpp:8917
AuraList & GetSingleCastAuras()
Definition Unit.h:1386
Vehicle * GetVehicleKit() const
Definition Unit.h:1735
uint8 GetLevel() const
Definition Unit.h:889
Aura * _TryStackingOrRefreshingExistingAura(AuraCreateInfo &createInfo)
Definition Unit.cpp:3213
uint32 SpellDamageBonusTaken(Unit *caster, SpellInfo const *spellProto, uint32 pdamage, DamageEffectType damagetype) const
Definition Unit.cpp:6910
uint8 GetAvailableSeatCount() const
Gets the available seat count.
Definition Vehicle.cpp:689
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
Definition Object.cpp:1783
Map * GetMap() const
Definition Object.h:449
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
std::string GetDebugInfo() const override
Definition Object.cpp:3614
Unit * GetOwner() const
Definition Object.cpp:2180
bool IsSelfOrInSameMap(WorldObject const *obj) const
Definition Object.cpp:1153
int32 CalcSpellDuration(SpellInfo const *spellInfo) const
Definition Object.cpp:2302
Player * GetSpellModOwner() const
Definition Object.cpp:2223
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:1192
EventProcessor m_Events
Definition Object.h:591
void GetZoneAndAreaId(uint32 &zoneid, uint32 &areaid) const
Definition Object.h:375
bool IsFriendlyTo(WorldObject const *target) const
Definition Object.cpp:2801
Definition Util.h:412
@ SMSG_AURA_UPDATE
Definition Opcodes.h:1203
#define sWorld
Definition World.h:900
@ CONFIG_ALLOW_TRACK_BOTH_RESOURCES
Definition World.h:162
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
SpellInfo const * _spellInfo
ObjectGuid CasterGUID
int32 const * BaseAmount
AuraCreateInfo(SpellInfo const *spellInfo, uint8 auraEffMask, WorldObject *owner)
WorldObject * _owner
CastSpellExtraArgs & AddSpellBP0(int32 val)
CastSpellExtraArgs & AddSpellMod(SpellValueMod mod, int32 val)
uint8 Level
Definition SpellAuras.h:95
float CritChance
Definition SpellAuras.h:93
float BonusDonePct
Definition SpellAuras.h:94
bool ApplyResilience
Definition SpellAuras.h:96
static void VisitAllObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:192
float ProcsPerMinute
Definition SpellMgr.h:258
Milliseconds Cooldown
Definition SpellMgr.h:260
uint32 AttributesMask
Definition SpellMgr.h:256
uint32 DisableEffectsMask
Definition SpellMgr.h:257