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 "SpellAuras.h"
19#include "CellImpl.h"
20#include "Common.h"
21#include "Containers.h"
22#include "CreatureAI.h"
23#include "DynamicObject.h"
24#include "GridNotifiersImpl.h"
25#include "Item.h"
26#include "ListUtils.h"
27#include "Log.h"
28#include "MapUtils.h"
29#include "ObjectAccessor.h"
30#include "ObjectMgr.h"
31#include "PhasingHandler.h"
32#include "Player.h"
33#include "ScriptMgr.h"
34#include "Spell.h"
35#include "SpellAuraEffects.h"
36#include "SpellHistory.h"
37#include "SpellMgr.h"
38#include "SpellPackets.h"
39#include "SpellScript.h"
40#include "Unit.h"
41#include "Util.h"
42#include "Vehicle.h"
43#include "World.h"
44#include <sstream>
45
47{
48public:
49 ChargeDropEvent(Aura* base, AuraRemoveMode mode) : _base(base), _mode(mode) { }
50 bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override
51 {
52 // _base is always valid (look in Aura::_Remove())
54 return true;
55 }
56
57private:
60};
61
62AuraCreateInfo::AuraCreateInfo(ObjectGuid castId, SpellInfo const* spellInfo, Difficulty castDifficulty, uint32 auraEffMask, WorldObject* owner) :
63 _castId(castId), _spellInfo(spellInfo), _castDifficulty(castDifficulty), _auraEffectMask(auraEffMask), _owner(owner)
64{
65 ASSERT(spellInfo);
66 ASSERT(auraEffMask);
67 ASSERT(owner);
68
69 ASSERT(auraEffMask <= MAX_EFFECT_MASK);
70}
71
72AuraApplication::AuraApplication(Unit* target, Unit* caster, Aura* aura, uint32 effMask) :
73_target(target), _base(aura), _removeMode(AURA_REMOVE_NONE), _slot(MAX_AURAS),
74_flags(AFLAG_NONE), _effectsToApply(effMask), _needClientUpdate(false), _effectMask(0)
75{
76 ASSERT(GetTarget() && GetBase());
77
78 // Try find slot for aura
79 uint16 slot = 0;
80 // lookup for free slots in units visibleAuras
81 for (AuraApplication* visibleAura : GetTarget()->GetVisibleAuras())
82 {
83 if (slot < visibleAura->GetSlot())
84 break;
85
86 ++slot;
87 }
88
89 // Register Visible Aura
90 if (slot < MAX_AURAS)
91 {
92 _slot = slot;
94 _needClientUpdate = true;
95 TC_LOG_DEBUG("spells", "Aura: {} Effect: {} put to unit visible auras slot: {}", GetBase()->GetId(), GetEffectMask(), slot);
96 }
97 else
98 TC_LOG_ERROR("spells", "Aura: {} Effect: {} could not find empty unit visible slot", GetBase()->GetId(), GetEffectMask());
99
100 _InitFlags(caster, effMask);
101}
102
104{
105 // update for out of range group members
106 if (GetSlot() < MAX_AURAS)
107 {
109 ClientUpdate(true);
110 }
111}
112
114{
115 // mark as selfcast if needed
117
118 // aura is cast by self or an enemy
119 // one negative effect and we know aura is negative
120 if (IsSelfcast() || !caster || !caster->IsFriendlyTo(GetTarget()))
121 {
122 bool negativeFound = false;
123 for (uint8 i = 0; i < GetBase()->GetAuraEffectCount(); ++i)
124 {
125 if (((1 << i) & effMask) && !GetBase()->GetSpellInfo()->IsPositiveEffect(i))
126 {
127 negativeFound = true;
128 break;
129 }
130 }
131 _flags |= negativeFound ? AFLAG_NEGATIVE : AFLAG_POSITIVE;
132 }
133 // aura is cast by friend
134 // one positive effect and we know aura is positive
135 else
136 {
137 bool positiveFound = false;
138 for (uint8 i = 0; i < GetBase()->GetAuraEffectCount(); ++i)
139 {
140 if (((1 << i) & effMask) && GetBase()->GetSpellInfo()->IsPositiveEffect(i))
141 {
142 positiveFound = true;
143 break;
144 }
145 }
146 _flags |= positiveFound ? AFLAG_POSITIVE : AFLAG_NEGATIVE;
147 }
148
149 auto effectNeedsAmount = [this](AuraEffect const* effect)
150 {
151 return GetEffectsToApply() & (1 << effect->GetEffIndex()) && Aura::EffectTypeNeedsSendingAmount(effect->GetAuraType());
152 };
153
155 || std::ranges::any_of(GetBase()->GetAuraEffects(), effectNeedsAmount))
157}
158
159void AuraApplication::_HandleEffect(uint8 effIndex, bool apply)
160{
161 AuraEffect* aurEff = GetBase()->GetEffect(effIndex);
162 if (!aurEff)
163 {
164 TC_LOG_ERROR("spells", "Aura {} has no effect at effectIndex {} but _HandleEffect was called", GetBase()->GetSpellInfo()->Id, uint32(effIndex));
165 return;
166 }
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(!(_effectMask & (1<<effIndex)));
175 _effectMask |= 1<<effIndex;
176 aurEff->HandleEffect(this, AURA_EFFECT_HANDLE_REAL, true);
177 }
178 else
179 {
180 ASSERT(_effectMask & (1<<effIndex));
181 _effectMask &= ~(1<<effIndex);
182 aurEff->HandleEffect(this, AURA_EFFECT_HANDLE_REAL, false);
183 }
184
186}
187
188void AuraApplication::UpdateApplyEffectMask(uint32 newEffMask, bool canHandleNewEffects)
189{
190 if (_effectsToApply == newEffMask)
191 return;
192
193 uint32 removeEffMask = (_effectsToApply ^ newEffMask) & (~newEffMask);
194 uint32 addEffMask = (_effectsToApply ^ newEffMask) & (~_effectsToApply);
195
196 // quick check, removes application completely
197 if (removeEffMask == _effectsToApply && !addEffMask)
198 {
200 return;
201 }
202
203 // update real effects only if they were applied already
204 for (std::size_t i = 0; i < GetBase()->GetAuraEffectCount(); ++i)
205 if (HasEffect(i) && (removeEffMask & (1 << i)))
206 _HandleEffect(i, false);
207
208 _effectsToApply = newEffMask;
209
210 if (canHandleNewEffects)
211 for (std::size_t i = 0; i < GetBase()->GetAuraEffectCount(); ++i)
212 if (addEffMask & (1 << i))
213 _HandleEffect(i, true);
214}
215
217{
218 if (_effectsToApply & (1 << spellEffectIndex))
219 return;
220
221 _effectsToApply |= 1 << spellEffectIndex;
222 if (Aura::EffectTypeNeedsSendingAmount(GetBase()->GetEffect(spellEffectIndex)->GetAuraType()))
224}
225
234
236{
237 ASSERT(_target->HasVisibleAura(this) != remove);
238
239 auraInfo.Slot = GetSlot();
240 if (remove)
241 return;
242
243 Aura const* aura = GetBase();
244
245 WorldPackets::Spells::AuraDataInfo& auraData = auraInfo.AuraData.emplace();
246 auraData.CastID = aura->GetCastId();
247 auraData.SpellID = aura->GetId();
248 auraData.Visual = aura->GetSpellVisual();
249 auraData.Flags = GetFlags();
251 auraData.Flags |= AFLAG_DURATION;
252
253 auraData.ActiveFlags = GetEffectMask();
255 auraData.CastLevel = aura->GetCasterLevel();
256 else
257 auraData.CastLevel = uint16(aura->GetCastItemLevel());
258
259 // send stack amount for aura which could be stacked (never 0 - causes incorrect display) or charges
260 // stack amount has priority over charges (checked on retail with spell 50262)
261 auraData.Applications = aura->IsUsingStacks() ? aura->GetStackAmount() : aura->GetCharges();
262 if (!aura->GetCasterGUID().IsUnit())
263 auraData.CastUnit = ObjectGuid::Empty; // optional data is filled in, but cast unit contains empty guid in packet
264 else if (!(auraData.Flags & AFLAG_NOCASTER))
265 auraData.CastUnit = aura->GetCasterGUID();
266
267 if (!aura->GetCastItemGUID().IsEmpty())
268 auraData.CastItem = aura->GetCastItemGUID();
269
270 if (auraData.Flags & AFLAG_DURATION)
271 {
272 auraData.Duration = aura->GetMaxDuration();
273 auraData.Remaining = aura->GetDuration();
274 }
275
276 if (auraData.Flags & AFLAG_SCALABLE)
277 {
278 auraData.Points.reserve(aura->GetAuraEffectCount());
279 bool hasEstimatedAmounts = false;
280 for (AuraEffect const* effect : GetBase()->GetAuraEffects())
281 {
282 if (HasEffect(effect->GetEffIndex())) // Not all of aura's effects have to be applied on every target
283 {
284 Trinity::Containers::EnsureWritableVectorIndex(auraData.Points, effect->GetEffIndex()) = float(effect->GetAmount());
285 if (effect->GetEstimatedAmount())
286 hasEstimatedAmounts = true;
287 }
288 }
289 if (hasEstimatedAmounts)
290 {
291 // When sending EstimatedPoints all effects (at least up to the last one that uses GetEstimatedAmount) must have proper value in packet
292 auraData.EstimatedPoints.resize(auraData.Points.size());
293 for (AuraEffect const* effect : GetBase()->GetAuraEffects())
294 if (HasEffect(effect->GetEffIndex())) // Not all of aura's effects have to be applied on every target
295 auraData.EstimatedPoints[effect->GetEffIndex()] = effect->GetEstimatedAmount().value_or(effect->GetAmount());
296 }
297 }
298}
299
301{
302 _needClientUpdate = false;
303
305 update.UpdateAll = false;
306 update.UnitGUID = GetTarget()->GetGUID();
307
309 BuildUpdatePacket(auraInfo, remove);
310 update.Auras.push_back(auraInfo);
311
312 _target->SendMessageToSet(update.Write(), true);
313}
314
316{
317 std::stringstream sstr;
318 sstr << "Base: " << (GetBase() ? GetBase()->GetDebugInfo() : "NULL")
319 << "\nTarget: " << (GetTarget() ? GetTarget()->GetDebugInfo() : "NULL");
320 return sstr.str();
321}
322
323uint32 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 availableEffectMask, WorldObject* owner)
324{
325 ASSERT_NODEBUGINFO(spellProto);
326 ASSERT_NODEBUGINFO(owner);
327 uint32 effMask = 0;
328 switch (owner->GetTypeId())
329 {
330 case TYPEID_UNIT:
331 case TYPEID_PLAYER:
332 for (SpellEffectInfo const& spellEffectInfo : spellProto->GetEffects())
333 {
334 if (spellEffectInfo.IsUnitOwnedAuraEffect())
335 effMask |= 1 << spellEffectInfo.EffectIndex;
336 }
337 break;
339 for (SpellEffectInfo const& spellEffectInfo : spellProto->GetEffects())
340 {
341 if (spellEffectInfo.IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA))
342 effMask |= 1 << spellEffectInfo.EffectIndex;
343 }
344 break;
345 default:
346 ABORT();
347 break;
348 }
349
350 return effMask & availableEffectMask;
351}
352
353Aura* Aura::TryRefreshStackOrCreate(AuraCreateInfo& createInfo, bool updateEffectMask)
354{
355 ASSERT_NODEBUGINFO(createInfo.Caster || !createInfo.CasterGUID.IsEmpty());
356
357 if (createInfo.IsRefresh)
358 *createInfo.IsRefresh = false;
359
360 createInfo._auraEffectMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, createInfo._auraEffectMask, createInfo._owner);
361 createInfo._targetEffectMask &= createInfo._auraEffectMask;
362
363 uint32 effMask = createInfo._auraEffectMask;
364 if (createInfo._targetEffectMask)
365 effMask = createInfo._targetEffectMask;
366
367 if (!effMask)
368 return nullptr;
369
370 if (Aura* foundAura = createInfo._owner->ToUnit()->_TryStackingOrRefreshingExistingAura(createInfo))
371 {
372 // we've here aura, which script triggered removal after modding stack amount
373 // check the state here, so we won't create new Aura object
374 if (foundAura->IsRemoved())
375 return nullptr;
376
377 if (createInfo.IsRefresh)
378 *createInfo.IsRefresh = true;
379
380 // add owner
381 Unit* unit = createInfo._owner->ToUnit();
382
383 // check effmask on owner application (if existing)
384 if (updateEffectMask)
385 if (AuraApplication* aurApp = foundAura->GetApplicationOfTarget(unit->GetGUID()))
386 aurApp->UpdateApplyEffectMask(effMask, false);
387 return foundAura;
388 }
389 else
390 return Create(createInfo);
391}
392
394{
395 uint32 effMask = createInfo._auraEffectMask;
396 if (createInfo._targetEffectMask)
397 effMask = createInfo._targetEffectMask;
398
399 effMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, effMask, createInfo._owner);
400 if (!effMask)
401 return nullptr;
402
403 return Create(createInfo);
404}
405
407{
408 // try to get caster of aura
409 if (!createInfo.CasterGUID.IsEmpty())
410 {
411 if (createInfo.CasterGUID.IsUnit())
412 {
413 if (createInfo._owner->GetGUID() == createInfo.CasterGUID)
414 createInfo.Caster = createInfo._owner->ToUnit();
415 else
416 createInfo.Caster = ObjectAccessor::GetUnit(*createInfo._owner, createInfo.CasterGUID);
417 }
418 }
419 else if (createInfo.Caster)
420 createInfo.CasterGUID = createInfo.Caster->GetGUID();
421
422 // check if aura can be owned by owner
423 if (Unit* ownerUnit = createInfo._owner->ToUnit())
424 if (!ownerUnit->IsInWorld() || ownerUnit->IsDuringRemoveFromWorld())
425 // owner not in world so don't allow to own not self cast single target auras
426 if (createInfo.CasterGUID != ownerUnit->GetGUID() && createInfo._spellInfo->IsSingleTarget())
427 return nullptr;
428
429 Aura* aura = nullptr;
430 switch (createInfo._owner->GetTypeId())
431 {
432 case TYPEID_UNIT:
433 case TYPEID_PLAYER:
434 {
435 aura = new UnitAura(createInfo);
436
437 // aura can be removed in Unit::_AddAura call
438 if (aura->IsRemoved())
439 return nullptr;
440
441 // add owner
442 uint32 effMask = createInfo._auraEffectMask;
443 if (createInfo._targetEffectMask)
444 effMask = createInfo._targetEffectMask;
445
446 effMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, effMask, createInfo._owner);
447 ASSERT_NODEBUGINFO(effMask);
448
449 Unit* unit = createInfo._owner->ToUnit();
450 aura->ToUnitAura()->AddStaticApplication(unit, effMask);
451 break;
452 }
454 createInfo._auraEffectMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, createInfo._auraEffectMask, createInfo._owner);
456
457 aura = new DynObjAura(createInfo);
458 break;
459 default:
460 ABORT();
461 return nullptr;
462 }
463
464 // scripts, etc.
465 if (aura->IsRemoved())
466 return nullptr;
467
468 return aura;
469}
470
472{
473 return _spellVisual.value_or<SpellCastVisual>({
475 .ScriptVisualID = 0
476 });
477}
478
479Aura::Aura(AuraCreateInfo const& createInfo) :
480m_spellInfo(createInfo._spellInfo), m_castDifficulty(createInfo._castDifficulty), m_castId(createInfo._castId), m_casterGuid(createInfo.CasterGUID),
481m_castItemGuid(createInfo.CastItemGUID), m_castItemId(createInfo.CastItemId),
482m_castItemLevel(createInfo.CastItemLevel), m_spellVisual(createInfo.CalcSpellVisual()),
483m_applyTime(GameTime::GetGameTime()), m_owner(createInfo._owner), m_timeCla(0), m_updateTargetMapInterval(0),
484m_casterLevel(createInfo.Caster ? createInfo.Caster->GetLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(createInfo.StackAmount),
485m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr),
486m_procCooldown(TimePoint::min()),
487m_lastProcAttemptTime(GameTime::Now() - Seconds(10)), m_lastProcSuccessTime(GameTime::Now() - Seconds(120)), m_scriptRef(this, NoopAuraDeleter())
488{
490 {
491 for (SpellPowerEntry const* power : m_spellInfo->PowerCosts)
492 if (power && (power->ManaPerSecond != 0 || power->PowerPctPerSecond > 0.0f))
493 m_periodicCosts.push_back(power);
494
495 if (!m_periodicCosts.empty())
497 }
498
501 m_procCharges = CalcMaxCharges(createInfo.Caster);
503 // m_casterLevel = cast item level/caster level, caster level should be saved to db, confirmed with sniffs
504}
505
506AuraScript* Aura::GetScriptByType(std::type_info const& type) const
507{
508 for (AuraScript* script : m_loadedScripts)
509 if (typeid(*script) == type)
510 return script;
511 return nullptr;
512}
513
514void Aura::_InitEffects(uint32 effMask, Unit* caster, SpellEffectValue const* baseAmount)
515{
516 // shouldn't be in constructor - functions in AuraEffect::AuraEffect use polymorphism
517 _effects.resize(GetSpellInfo()->GetEffects().size());
518
519 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
520 if (effMask & (1 << spellEffectInfo.EffectIndex))
521 _effects[spellEffectInfo.EffectIndex] = new AuraEffect(this, spellEffectInfo, baseAmount ? baseAmount + spellEffectInfo.EffectIndex : nullptr, caster);
522
523 while (!_effects.back())
524 _effects.pop_back();
525}
526
528{
529 if (GetSpellInfo()->HasAttribute(SPELL_ATTR2_CANT_CRIT))
530 return false;
531
532 if (GetSpellInfo()->HasAttribute(SPELL_ATTR8_PERIODIC_CAN_CRIT))
533 return true;
534
535 return false;
536}
537
539{
540 // unload scripts
541 for (AuraScript* script : m_loadedScripts)
542 {
543 script->_Unload();
544 delete script;
545 }
546
547 for (AuraEffect* effect : _effects)
548 delete effect;
549
550 ASSERT(m_applications.empty());
552}
553
554void Aura::SetSpellVisual(SpellCastVisual const& spellVisual)
555{
556 m_spellVisual = spellVisual;
558}
559
561{
562 if (GetOwner()->GetGUID() == GetCasterGUID())
563 return GetUnitOwner();
564
566}
567
569{
570 if (GetCasterGUID().IsUnit())
571 return GetCaster();
572
574}
575
577{
578 if (index >= _effects.size())
579 return nullptr;
580
581 return _effects[index];
582}
583
588
589void Aura::_ApplyForTarget(Unit* target, Unit* caster, AuraApplication* auraApp)
590{
591 ASSERT(target);
592 ASSERT(auraApp);
593 // aura mustn't be already applied on target
594 ASSERT (!IsAppliedOnTarget(target->GetGUID()) && "Aura::_ApplyForTarget: aura musn't be already applied on target");
595
596 m_applications[target->GetGUID()] = auraApp;
597
598 // set infinity cooldown state for spells
599 if (caster && caster->GetTypeId() == TYPEID_PLAYER)
600 {
602 {
603 Item* castItem = !m_castItemGuid.IsEmpty() ? caster->ToPlayer()->GetItemByGuid(m_castItemGuid) : nullptr;
604 caster->GetSpellHistory()->StartCooldown(m_spellInfo, castItem ? castItem->GetEntry() : 0, nullptr, true);
605 }
606 }
607}
608
609void Aura::_UnapplyForTarget(Unit* target, Unit* caster, AuraApplication* auraApp)
610{
611 ASSERT(target);
612 ASSERT(auraApp->GetRemoveMode());
613 ASSERT(auraApp);
614
615 ApplicationMap::iterator itr = m_applications.find(target->GetGUID());
616
618 if (itr == m_applications.end())
619 {
620 TC_LOG_ERROR("spells", "Aura::_UnapplyForTarget, target: {}, caster: {}, spell:{} was not found in owners application map!",
621 target->GetGUID().ToString(), caster ? caster->GetGUID().ToString().c_str() : "Empty", auraApp->GetBase()->GetSpellInfo()->Id);
622 ABORT();
623 }
624
625 // aura has to be already applied
626 ASSERT(itr->second == auraApp);
627 m_applications.erase(itr);
628
629 _removedApplications.push_back(auraApp);
630
631 // reset cooldown state for spells
632 if (caster && GetSpellInfo()->IsCooldownStartedOnEvent())
633 // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
635}
636
637// removes aura from all targets
638// and marks aura as removed
640{
642 m_isRemoved = true;
643 ApplicationMap::iterator appItr = m_applications.begin();
644 for (appItr = m_applications.begin(); appItr != m_applications.end();)
645 {
646 AuraApplication * aurApp = appItr->second;
647 Unit* target = aurApp->GetTarget();
648 target->_UnapplyAura(aurApp, removeMode);
649 appItr = m_applications.begin();
650 }
651
652 if (m_dropEvent)
653 {
655 m_dropEvent = nullptr;
656 }
657
658 m_scriptRef = nullptr;
659}
660
661void Aura::UpdateTargetMap(Unit* caster, bool apply)
662{
663 if (IsRemoved())
664 return;
665
667
668 // fill up to date target list
669 // target, effMask
670 std::unordered_map<Unit*, uint32> targets;
671
672 FillTargetMap(targets, caster);
673
674 std::vector<Unit*> targetsToRemove;
675
676 // mark all auras as ready to remove
677 for (auto const& applicationPair : m_applications)
678 {
679 auto itr = targets.find(applicationPair.second->GetTarget());
680 // not found in current area - remove the aura
681 if (itr == targets.end())
682 targetsToRemove.push_back(applicationPair.second->GetTarget());
683 else
684 {
685 // needs readding - remove now, will be applied in next update cycle
686 // (dbcs do not have auras which apply on same type of targets but have different radius, so this is not really needed)
687 if (itr->first->IsImmunedToSpell(GetSpellInfo(), itr->second, caster, true) || !CanBeAppliedOn(itr->first))
688 {
689 targetsToRemove.push_back(applicationPair.second->GetTarget());
690 continue;
691 }
692
693 // check target immunities (for existing targets)
694 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
695 if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster, true))
696 itr->second &= ~(1 << spellEffectInfo.EffectIndex);
697
698 // needs to add/remove effects from application, don't remove from map so it gets updated
699 if (applicationPair.second->GetEffectMask() != itr->second)
700 continue;
701
702 // nothing to do - aura already applied
703 // remove from auras to register list
704 targets.erase(itr);
705 }
706 }
707
708 // register auras for units
709 for (auto itr = targets.begin(); itr != targets.end();)
710 {
711 bool addUnit = true;
712 AuraApplication* aurApp = GetApplicationOfTarget(itr->first->GetGUID());
713 if (!aurApp)
714 {
715 // check target immunities (for new targets)
716 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
717 if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster))
718 itr->second &= ~(1 << spellEffectInfo.EffectIndex);
719
720 if (!itr->second || itr->first->IsImmunedToSpell(GetSpellInfo(), itr->second, caster) || !CanBeAppliedOn(itr->first))
721 addUnit = false;
722 }
723
724 if (addUnit && !itr->first->IsHighestExclusiveAura(this, true))
725 addUnit = false;
726
727 // Dynobj auras don't hit flying targets
728 if (GetType() == DYNOBJ_AURA_TYPE && itr->first->IsInFlight())
729 addUnit = false;
730
731 // Do not apply aura if it cannot stack with existing auras
732 if (addUnit)
733 {
734 // Allow to remove by stack when aura is going to be applied on owner
735 if (itr->first != GetOwner())
736 {
737 // check if not stacking aura already on target
738 // this one prevents unwanted usefull buff loss because of stacking and prevents overriding auras periodicaly by 2 near area aura owners
739 for (Unit::AuraApplicationMap::iterator iter = itr->first->GetAppliedAuras().begin(); iter != itr->first->GetAppliedAuras().end(); ++iter)
740 {
741 Aura const* aura = iter->second->GetBase();
742 if (!CanStackWith(aura))
743 {
744 addUnit = false;
745 break;
746 }
747 }
748 }
749 }
750
751 if (!addUnit)
752 itr = targets.erase(itr);
753 else
754 {
755 // owner has to be in world, or effect has to be applied to self
756 if (!GetOwner()->IsSelfOrInSameMap(itr->first))
757 {
759 TC_LOG_FATAL("spells", "Aura {}: Owner {} (map {}) is not in the same map as target {} (map {}).", GetSpellInfo()->Id,
760 GetOwner()->GetName(), GetOwner()->IsInWorld() ? GetOwner()->GetMap()->GetId() : uint32(-1),
761 itr->first->GetName(), itr->first->IsInWorld() ? itr->first->GetMap()->GetId() : uint32(-1));
762 ABORT();
763 }
764
765 if (aurApp)
766 {
767 aurApp->UpdateApplyEffectMask(itr->second, true); // aura is already applied, this means we need to update effects of current application
768 itr = targets.erase(itr);
769 }
770 else
771 {
772 itr->first->_CreateAuraApplication(this, itr->second);
773 ++itr;
774 }
775 }
776 }
777
778 // remove auras from units no longer needing them
779 for (Unit* unit : targetsToRemove)
780 if (AuraApplication* aurApp = GetApplicationOfTarget(unit->GetGUID()))
781 unit->_UnapplyAura(aurApp, AURA_REMOVE_BY_DEFAULT);
782
783 if (!apply)
784 return;
785
786 // apply aura effects for units
787 for (auto itr = targets.begin(); itr!= targets.end(); ++itr)
788 {
789 if (AuraApplication* aurApp = GetApplicationOfTarget(itr->first->GetGUID()))
790 {
791 // owner has to be in world, or effect has to be applied to self
792 ASSERT((!GetOwner()->IsInWorld() && GetOwner() == itr->first) || GetOwner()->IsInMap(itr->first));
793 itr->first->_ApplyAura(aurApp, itr->second);
794 }
795 }
796}
797
798// targets have to be registered and not have effect applied yet to use this function
800{
801 // prepare list of aura targets
802 UnitList targetList;
803 for (ApplicationMap::iterator appIter = m_applications.begin(); appIter != m_applications.end(); ++appIter)
804 {
805 if ((appIter->second->GetEffectsToApply() & (1 << effIndex)) && !appIter->second->HasEffect(effIndex))
806 targetList.push_back(appIter->second->GetTarget());
807 }
808
809 // apply effect to targets
810 for (UnitList::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
811 {
812 if (GetApplicationOfTarget((*itr)->GetGUID()))
813 {
814 // owner has to be in world, or effect has to be applied to self
815 ASSERT((!GetOwner()->IsInWorld() && GetOwner() == *itr) || GetOwner()->IsInMap(*itr));
816 (*itr)->_ApplyAuraEffect(this, effIndex);
817 }
818 }
819}
821{
822 ASSERT(owner == m_owner);
823
824 Unit* caster = GetCaster();
825 // Apply spellmods for channeled auras
826 // used for example when triggered spell of spell:10 is modded
827 Spell* modSpell = nullptr;
828 Player* modOwner = nullptr;
829 if (caster)
830 {
831 modOwner = caster->GetSpellModOwner();
832 if (modOwner)
833 {
834 modSpell = modOwner->FindCurrentSpellBySpellId(GetId());
835 if (modSpell)
836 modOwner->SetSpellModTakingSpell(modSpell, true);
837 }
838 }
839
840 Update(diff, caster);
841
842 if (m_updateTargetMapInterval <= int32(diff))
843 UpdateTargetMap(caster);
844 else
846
847 // update aura effects
848 for (AuraEffect* effect : GetAuraEffects())
849 effect->Update(diff, caster);
850
851 // remove spellmods after effects update
852 if (modSpell)
853 modOwner->SetSpellModTakingSpell(modSpell, false);
854
856}
857
858void Aura::Update(uint32 diff, Unit* caster)
859{
860 if (m_duration > 0)
861 {
862 m_duration -= diff;
863 if (m_duration < 0)
864 m_duration = 0;
865
866 // handle manaPerSecond/manaPerSecondPerLevel
867 if (m_timeCla)
868 {
869 if (m_timeCla > int32(diff))
870 m_timeCla -= diff;
871 else if (caster && (caster == GetOwner() || !GetSpellInfo()->HasAttribute(SPELL_ATTR2_NO_TARGET_PER_SECOND_COSTS)))
872 {
873 if (!m_periodicCosts.empty())
874 {
875 m_timeCla += 1000 - diff;
876
877 for (SpellPowerEntry const* power : m_periodicCosts)
878 {
879 if (power->RequiredAuraSpellID && !caster->HasAura(power->RequiredAuraSpellID))
880 continue;
881
882 int32 manaPerSecond = power->ManaPerSecond;
883 Powers powertype = Powers(power->PowerType);
884 if (powertype != POWER_HEALTH)
885 manaPerSecond += int32(CalculatePct(caster->GetMaxPower(powertype), power->PowerPctPerSecond));
886 else
887 manaPerSecond += int32(CalculatePct(caster->GetMaxHealth(), power->PowerPctPerSecond));
888
889 if (manaPerSecond)
890 {
891 if (powertype == POWER_HEALTH)
892 {
893 if (int32(caster->GetHealth()) > manaPerSecond)
894 caster->ModifyHealth(-manaPerSecond);
895 else
896 Remove();
897 }
898 else if (int32(caster->GetPower(powertype)) >= manaPerSecond)
899 caster->ModifyPower(powertype, -manaPerSecond);
900 else
901 Remove();
902 }
903 }
904 }
905 }
906 }
907 }
908}
909
911{
912 return Aura::CalcMaxDuration(GetSpellInfo(), caster, nullptr);
913}
914
915/*static*/ int32 Aura::CalcMaxDuration(SpellInfo const* spellInfo, WorldObject const* caster, std::vector<SpellPowerCost> const* powerCosts)
916{
917 Player* modOwner = nullptr;
918 int32 maxDuration;
919
920 if (caster)
921 {
922 modOwner = caster->GetSpellModOwner();
923 maxDuration = caster->CalcSpellDuration(spellInfo, powerCosts);
924 }
925 else
926 maxDuration = spellInfo->GetDuration();
927
928 if (spellInfo->IsPassive() && !spellInfo->DurationEntry)
929 maxDuration = -1;
930
931 // IsPermanent() checks max duration (which we are supposed to calculate here)
932 if (maxDuration != -1)
933 {
934 if (modOwner)
935 modOwner->ApplySpellMod(spellInfo, SpellModOp::Duration, maxDuration);
936
937 if (spellInfo->IsEmpowerSpell())
938 maxDuration += SPELL_EMPOWER_HOLD_TIME_AT_MAX;
939 }
940
941 return maxDuration;
942}
943
944void Aura::SetDuration(int32 duration, bool withMods)
945{
946 if (withMods)
947 if (Unit* caster = GetCaster())
948 if (Player* modOwner = caster->GetSpellModOwner())
949 modOwner->ApplySpellMod(GetSpellInfo(), SpellModOp::Duration, duration);
950
951 m_duration = duration;
953}
954
955void Aura::RefreshDuration(bool withMods)
956{
957 Unit* caster = GetCaster();
958 if (withMods && caster)
959 {
960 int32 duration = m_spellInfo->GetMaxDuration();
961 // Calculate duration of periodics affected by haste.
963 duration = int32(duration * caster->m_unitData->ModCastingSpeed);
964
965 SetMaxDuration(duration);
966 SetDuration(duration);
967 }
968 else
970
971 if (!m_periodicCosts.empty())
973
974 // also reset periodic counters
975 for (AuraEffect* aurEff : GetAuraEffects())
976 aurEff->ResetTicks();
977}
978
979void Aura::RefreshTimers(bool resetPeriodicTimer)
980{
982
983 // Pandemic Mechanic
985 {
986 // Pandemic doesn't reset periodic timer
987 resetPeriodicTimer = false;
988 }
989
991
992 Unit* caster = GetCaster();
993 for (AuraEffect* aurEff : GetAuraEffects())
994 aurEff->CalculatePeriodic(caster, resetPeriodicTimer, false);
995}
996
998{
999 if (m_procCharges == charges)
1000 return;
1001
1002 m_procCharges = charges;
1005}
1006
1008{
1009 uint32 maxProcCharges = m_spellInfo->ProcCharges;
1010 if (SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetSpellInfo()))
1011 maxProcCharges = procEntry->Charges;
1012
1013 if (caster)
1014 if (Player* modOwner = caster->GetSpellModOwner())
1015 modOwner->ApplySpellMod(GetSpellInfo(), SpellModOp::ProcCharges, maxProcCharges);
1016
1017 return uint8(maxProcCharges);
1018}
1019
1021{
1022 if (IsUsingCharges())
1023 {
1024 int32 charges = m_procCharges + num;
1025 int32 maxCharges = CalcMaxCharges();
1026
1027 // limit charges (only on charges increase, charges may be changed manually)
1028 if ((num > 0) && (charges > int32(maxCharges)))
1029 charges = maxCharges;
1030 // we're out of charges, remove
1031 else if (charges <= 0)
1032 {
1033 Remove(removeMode);
1034 return true;
1035 }
1036
1037 SetCharges(charges);
1038 }
1039
1040 return false;
1041}
1042
1044{
1045 m_dropEvent = nullptr;
1046 ModCharges(num, removeMode);
1047}
1048
1050{
1051 // aura is already during delayed charge drop
1052 if (m_dropEvent)
1053 return;
1054
1055 m_dropEvent = new ChargeDropEvent(this, removeMode);
1057}
1058
1060{
1061 m_stackAmount = stackAmount;
1062 Unit* caster = GetCaster();
1063
1064 std::vector<AuraApplication*> applications;
1065 GetApplicationVector(applications);
1066
1067 for (AuraApplication* aurApp : applications)
1068 if (!aurApp->GetRemoveMode())
1069 HandleAuraSpecificMods(aurApp, caster, false, true);
1070
1071 for (AuraEffect* aurEff : GetAuraEffects())
1072 aurEff->ChangeAmount(aurEff->CalculateAmount(caster), false, true);
1073
1074 for (AuraApplication* aurApp : applications)
1075 if (!aurApp->GetRemoveMode())
1076 HandleAuraSpecificMods(aurApp, caster, true, true);
1077
1079}
1080
1082{
1083 return m_spellInfo->StackAmount > 0 || m_stackAmount > 1;
1084}
1085
1087{
1088 int32 maxStackAmount = m_spellInfo->StackAmount;
1089 if (Unit* caster = GetCaster())
1090 if (Player* modOwner = caster->GetSpellModOwner())
1091 modOwner->ApplySpellMod(m_spellInfo, SpellModOp::MaxAuraStacks, maxStackAmount);
1092
1093 return maxStackAmount;
1094}
1095
1096bool Aura::ModStackAmount(int32 num, AuraRemoveMode removeMode /*= AURA_REMOVE_BY_DEFAULT*/, bool resetPeriodicTimer /*= true*/)
1097{
1098 int32 stackAmount = m_stackAmount + num;
1099 int32 maxStackAmount = int32(CalcMaxStackAmount());
1100
1101 // limit the stack amount (only on stack increase, stack amount may be changed manually)
1102 if ((num > 0) && (stackAmount > maxStackAmount))
1103 {
1104 // not stackable aura - set stack amount to 1
1106 stackAmount = 1;
1107 else
1108 stackAmount = maxStackAmount;
1109 }
1110 // we're out of stacks, remove
1111 else if (stackAmount <= 0)
1112 {
1113 Remove(removeMode);
1114 return true;
1115 }
1116
1118
1119 // Update stack amount
1120 SetStackAmount(stackAmount);
1121
1122 if (refresh)
1123 {
1124 RefreshTimers(resetPeriodicTimer);
1125
1126 // reset charges
1128 }
1129
1131 return false;
1132}
1133
1135{
1136 uint32 count = 0;
1137 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1138 if (HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.ApplyAuraName == auraType)
1139 ++count;
1140
1141 return count > 1;
1142}
1143
1144bool Aura::IsArea() const
1145{
1146 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1147 if (HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.IsAreaAuraEffect())
1148 return true;
1149
1150 return false;
1151}
1152
1154{
1155 return GetSpellInfo()->IsPassive();
1156}
1157
1159{
1160 return GetSpellInfo()->IsDeathPersistent();
1161}
1162
1170
1172{
1173 if (IsPassive())
1174 return false;
1175
1176 if (GetSpellInfo()->IsChanneled())
1177 return false;
1178
1179 // Check if aura is single target, not only spell info
1180 if (GetCasterGUID() != GetOwner()->GetGUID())
1181 {
1182 // owner == caster for area auras, check for possible bad data in DB
1183 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1184 {
1185 if (!spellEffectInfo.IsEffect())
1186 continue;
1187
1188 if (spellEffectInfo.IsTargetingArea() || spellEffectInfo.IsAreaAuraEffect())
1189 return false;
1190 }
1191
1193 return false;
1194 }
1195
1197 return false;
1198
1199 // don't save auras removed by proc system
1200 if (IsUsingCharges() && !GetCharges())
1201 return false;
1202
1203 // don't save permanent auras triggered by items, they'll be recasted on login if necessary
1204 if (!GetCastItemGUID().IsEmpty() && IsPermanent())
1205 return false;
1206
1207 return true;
1208}
1209
1210bool Aura::IsSingleTargetWith(Aura const* aura) const
1211{
1212 // Same spell?
1213 if (GetSpellInfo()->IsRankOf(aura->GetSpellInfo()))
1214 return true;
1215
1217 // spell with single target specific types
1218 switch (spec)
1219 {
1221 if (aura->GetSpellInfo()->GetSpellSpecific() == spec)
1222 return true;
1223 break;
1224 default:
1225 break;
1226 }
1227
1228 return false;
1229}
1230
1232{
1234 Unit* caster = GetCaster();
1235 ASSERT(caster);
1237 SetIsSingleTarget(false);
1238}
1239
1240int32 Aura::CalcDispelChance(Unit const* /*auraTarget*/, bool /*offensive*/) const
1241{
1242 // we assume that aura dispel chance is 100% on start
1243 // need formula for level difference based chance
1244 int32 resistChance = 0;
1245
1246 // Apply dispel mod from aura caster
1247 if (Unit* caster = GetCaster())
1248 if (Player* modOwner = caster->GetSpellModOwner())
1249 modOwner->ApplySpellMod(GetSpellInfo(), SpellModOp::DispelResistance, resistChance);
1250
1251 RoundToInterval(resistChance, 0, 100);
1252 return 100 - resistChance;
1253}
1254
1255AuraKey Aura::GenerateKey(uint32& recalculateMask) const
1256{
1257 AuraKey key;
1258 key.Caster = GetCasterGUID();
1259 key.Item = GetCastItemGUID();
1260 key.SpellId = GetId();
1261 key.EffectMask = 0;
1262 recalculateMask = 0;
1263 for (uint32 i = 0; i < _effects.size(); ++i)
1264 {
1265 if (AuraEffect const* effect = _effects[i])
1266 {
1267 key.EffectMask |= 1 << i;
1268 if (effect->CanBeRecalculated())
1269 recalculateMask |= 1 << i;
1270 }
1271 }
1272
1273 return key;
1274}
1275
1276void Aura::SetLoadedState(int32 maxDuration, int32 duration, int32 charges, uint32 recalculateMask, SpellEffectValue const* amount)
1277{
1278 m_maxDuration = maxDuration;
1279 m_duration = duration;
1280 m_procCharges = charges;
1282 Unit* caster = GetCaster();
1283 for (AuraEffect* effect : GetAuraEffects())
1284 {
1285 effect->SetAmount(amount[effect->GetEffIndex()]);
1286 effect->SetCanBeRecalculated((recalculateMask & (1 << effect->GetEffIndex())) != 0);
1287 effect->CalculatePeriodic(caster, false, true);
1288 effect->CalculateSpellMod();
1289 effect->RecalculateAmount(caster);
1290 }
1291}
1292
1294{
1295 for (AuraEffect const* effect : GetAuraEffects())
1296 if (effect->GetAuraType() == type)
1297 return true;
1298
1299 return false;
1300}
1301
1303{
1304 switch (type)
1305 {
1312 return true;
1313 default:
1314 break;
1315 }
1316
1317 return false;
1318}
1319
1321{
1322 ASSERT (!IsRemoved());
1323 Unit* caster = GetCaster();
1324 for (AuraEffect* effect : GetAuraEffects())
1325 if (!IsRemoved())
1326 effect->RecalculateAmount(caster);
1327}
1328
1329void Aura::HandleAllEffects(AuraApplication * aurApp, uint8 mode, bool apply)
1330{
1331 ASSERT (!IsRemoved());
1332 for (AuraEffect* effect : GetAuraEffects())
1333 if (!IsRemoved())
1334 effect->HandleEffect(aurApp, mode, apply);
1335}
1336
1338{
1339 uint32 effMask = 0;
1340 for (AuraEffect const* aurEff : GetAuraEffects())
1341 effMask |= 1 << aurEff->GetEffIndex();
1342 return effMask;
1343}
1344
1345void Aura::GetApplicationVector(std::vector<AuraApplication*>& applications) const
1346{
1347 for (auto const& applicationPair : m_applications)
1348 {
1349 if (!applicationPair.second->GetEffectMask())
1350 continue;
1351
1352 applications.push_back(applicationPair.second);
1353 }
1354}
1355
1360
1365
1367{
1368 return m_applications.contains(guid);
1369}
1370
1372{
1373 for (ApplicationMap::const_iterator appIter = m_applications.begin(); appIter != m_applications.end(); ++appIter)
1374 appIter->second->SetNeedClientUpdate();
1375}
1376
1377// trigger effects on real aura apply/remove
1378void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, bool apply, bool onReapply)
1379{
1380 Unit* target = aurApp->GetTarget();
1381 AuraRemoveMode removeMode = aurApp->GetRemoveMode();
1382 // handle spell_area table
1383 SpellAreaForAreaMapBounds saBounds = sSpellMgr->GetSpellAreaForAuraMapBounds(GetId());
1384 if (saBounds.first != saBounds.second)
1385 {
1386 uint32 zone, area;
1387 target->GetZoneAndAreaId(zone, area);
1388
1389 for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
1390 {
1391 // some auras remove at aura remove
1392 if (itr->second->flags & SPELL_AREA_FLAG_AUTOREMOVE && !itr->second->IsFitToRequirements(target->ToPlayer(), zone, area))
1393 target->RemoveAurasDueToSpell(itr->second->spellId);
1394 // some auras applied at aura apply
1395 else if (itr->second->flags & SPELL_AREA_FLAG_AUTOCAST)
1396 {
1397 if (!target->HasAura(itr->second->spellId))
1398 target->CastSpell(target, itr->second->spellId, CastSpellExtraArgs(TRIGGERED_FULL_MASK)
1400 }
1401 }
1402 }
1403
1404 // handle spell_linked_spell table
1405 if (!onReapply)
1406 {
1407 // apply linked auras
1408 if (apply)
1409 {
1410 if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(SPELL_LINK_AURA, GetId()))
1411 {
1412 for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
1413 {
1414 if (*itr < 0)
1415 target->ApplySpellImmune(GetId(), IMMUNITY_ID, -(*itr), true);
1416 else if (caster)
1417 caster->AddAura(*itr, target);
1418 }
1419 }
1420 }
1421 else
1422 {
1423 // remove linked auras
1424 if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(SPELL_LINK_REMOVE, GetId()))
1425 {
1426 for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
1427 {
1428 if (*itr < 0)
1429 target->RemoveAurasDueToSpell(-(*itr));
1430 else if (removeMode != AURA_REMOVE_BY_DEATH)
1431 target->CastSpell(target, *itr, CastSpellExtraArgs(TRIGGERED_FULL_MASK)
1434 }
1435 }
1436 if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(SPELL_LINK_AURA, GetId()))
1437 {
1438 for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
1439 {
1440 if (*itr < 0)
1441 target->ApplySpellImmune(GetId(), IMMUNITY_ID, -(*itr), false);
1442 else
1443 target->RemoveAura(*itr, GetCasterGUID(), 0, removeMode);
1444 }
1445 }
1446 }
1447 }
1448 else if (apply)
1449 {
1450 // modify stack amount of linked auras
1451 if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(SPELL_LINK_AURA, GetId()))
1452 {
1453 for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
1454 if (*itr > 0)
1455 if (Aura* triggeredAura = target->GetAura(*itr, GetCasterGUID()))
1456 triggeredAura->ModStackAmount(GetStackAmount() - triggeredAura->GetStackAmount());
1457 }
1458 }
1459
1460 // mods at aura apply
1461 if (apply)
1462 {
1463 switch (GetSpellInfo()->SpellFamilyName)
1464 {
1466 switch (GetId())
1467 {
1468 case 33572: // Gronn Lord's Grasp, becomes stoned
1469 if (GetStackAmount() >= 5 && !target->HasAura(33652))
1470 target->CastSpell(target, 33652, CastSpellExtraArgs(TRIGGERED_FULL_MASK)
1472 break;
1473 case 50836: //Petrifying Grip, becomes stoned
1474 if (GetStackAmount() >= 5 && !target->HasAura(50812))
1475 target->CastSpell(target, 50812, CastSpellExtraArgs(TRIGGERED_FULL_MASK)
1477 break;
1478 case 60970: // Heroic Fury (remove Intercept cooldown)
1479 if (target->GetTypeId() == TYPEID_PLAYER)
1480 target->GetSpellHistory()->ResetCooldown(20252, true);
1481 break;
1482 }
1483 break;
1484 case SPELLFAMILY_DRUID:
1485 if (!caster)
1486 break;
1487 // Rejuvenation
1488 if (GetSpellInfo()->SpellFamilyFlags[0] & 0x10 && GetEffect(EFFECT_0))
1489 {
1490 // Druid T8 Restoration 4P Bonus
1491 if (caster->HasAura(64760))
1492 {
1495 caster->CastSpell(target, 64801, args);
1496 }
1497 }
1498 break;
1499 }
1500 }
1501 // mods at aura remove
1502 else
1503 {
1504 switch (GetSpellInfo()->SpellFamilyName)
1505 {
1506 case SPELLFAMILY_MAGE:
1507 switch (GetId())
1508 {
1509 case 66: // Invisibility
1510 if (removeMode != AURA_REMOVE_BY_EXPIRE)
1511 break;
1512 target->CastSpell(target, 32612, GetEffect(1));
1513 break;
1514 default:
1515 break;
1516 }
1517 break;
1518 case SPELLFAMILY_PRIEST:
1519 if (!caster)
1520 break;
1521 // Power word: shield
1522 if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && GetSpellInfo()->SpellFamilyFlags[0] & 0x00000001)
1523 {
1524 // Rapture
1525 if (Aura const* aura = caster->GetAuraOfRankedSpell(47535))
1526 {
1527 // check cooldown
1528 if (caster->GetTypeId() == TYPEID_PLAYER)
1529 {
1530 if (caster->GetSpellHistory()->HasCooldown(aura->GetSpellInfo()))
1531 {
1532 // This additional check is needed to add a minimal delay before cooldown in in effect
1533 // to allow all bubbles broken by a single damage source proc mana return
1534 if (caster->GetSpellHistory()->GetRemainingCooldown(aura->GetSpellInfo()) <= 11s)
1535 break;
1536 }
1537 else // and add if needed
1538 caster->GetSpellHistory()->AddCooldown(aura->GetId(), 0, 12s);
1539 }
1540
1541 // effect on caster
1542 if (AuraEffect const* aurEff = aura->GetEffect(0))
1543 {
1544 SpellEffectValue multiplier = aurEff->GetAmount();
1548 caster->CastSpell(caster, 47755, args);
1549 }
1550 }
1551 }
1552 break;
1553 case SPELLFAMILY_ROGUE:
1554 // Remove Vanish on stealth remove
1555 if (GetId() == 1784)
1556 target->RemoveAurasWithFamily(SPELLFAMILY_ROGUE, flag128(0x0000800, 0, 0, 0), target->GetGUID());
1557 break;
1558 }
1559 }
1560
1561 // mods at aura apply or remove
1562 switch (GetSpellInfo()->SpellFamilyName)
1563 {
1564 case SPELLFAMILY_HUNTER:
1565 switch (GetId())
1566 {
1567 case 19574: // Bestial Wrath
1568 // The Beast Within cast on owner if talent present
1569 if (Unit* owner = target->GetOwner())
1570 {
1571 // Search talent
1572 if (owner->HasAura(34692))
1573 {
1574 if (apply)
1575 owner->CastSpell(owner, 34471, GetEffect(0));
1576 else
1577 owner->RemoveAurasDueToSpell(34471);
1578 }
1579 }
1580 break;
1581 }
1582 break;
1584 switch (GetId())
1585 {
1586 case 31842: // Divine Favor
1587 // Item - Paladin T10 Holy 2P Bonus
1588 if (target->HasAura(70755))
1589 {
1590 if (apply)
1591 target->CastSpell(target, 71166, CastSpellExtraArgs(TRIGGERED_FULL_MASK)
1592 .SetOriginalCastId(GetCastId()));
1593 else
1594 target->RemoveAurasDueToSpell(71166);
1595 }
1596 break;
1597 }
1598 break;
1599 }
1600
1601 if (apply)
1602 {
1603 if (Creature* creature = target->ToCreature())
1604 if (CreatureAI* ai = creature->AI())
1605 ai->OnAuraApplied(aurApp);
1606 }
1607 else
1608 {
1609 if (Creature* creature = target->ToCreature())
1610 if (CreatureAI* ai = creature->AI())
1611 ai->OnAuraRemoved(aurApp);
1612 }
1613}
1614
1616{
1617 for (uint32 label : GetSpellInfo()->Labels)
1619 return false;
1620
1621 // unit not in world or during remove from world
1622 if (!target->IsInWorld() || target->IsDuringRemoveFromWorld())
1623 {
1624 // area auras mustn't be applied
1625 if (GetOwner() != target)
1626 return false;
1627 // do not apply non-selfcast single target auras
1629 return false;
1630 return true;
1631 }
1632 else
1633 return CheckAreaTarget(target);
1634}
1635
1637{
1638 return CallScriptCheckAreaTargetHandlers(target);
1639}
1640
1641bool Aura::CanStackWith(Aura const* existingAura) const
1642{
1643 // Can stack with self
1644 if (this == existingAura)
1645 return true;
1646
1647 bool sameCaster = GetCasterGUID() == existingAura->GetCasterGUID();
1648 SpellInfo const* existingSpellInfo = existingAura->GetSpellInfo();
1649
1650 // Dynobj auras do not stack when they come from the same spell cast by the same caster
1651 if (GetType() == DYNOBJ_AURA_TYPE || existingAura->GetType() == DYNOBJ_AURA_TYPE)
1652 {
1653 if (sameCaster && m_spellInfo->Id == existingSpellInfo->Id)
1654 return false;
1655 return true;
1656 }
1657
1658 // passive auras don't stack with another rank of the spell cast by same caster
1659 if (IsPassive() && sameCaster && (m_spellInfo->IsDifferentRankOf(existingSpellInfo) || (m_spellInfo->Id == existingSpellInfo->Id && m_castItemGuid.IsEmpty())))
1660 return false;
1661
1662 for (SpellEffectInfo const& spellEffectInfo : existingSpellInfo->GetEffects())
1663 {
1664 // prevent remove triggering aura by triggered aura
1665 if (spellEffectInfo.TriggerSpell == GetId())
1666 return true;
1667 }
1668
1669 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1670 {
1671 // prevent remove triggered aura by triggering aura refresh
1672 if (spellEffectInfo.TriggerSpell == existingAura->GetId())
1673 return true;
1674 }
1675
1676 // check spell specific stack rules
1677 if (m_spellInfo->IsAuraExclusiveBySpecificWith(existingSpellInfo)
1678 || (sameCaster && m_spellInfo->IsAuraExclusiveBySpecificPerCasterWith(existingSpellInfo)))
1679 return false;
1680
1681 // check spell group stack rules
1682 switch (sSpellMgr->CheckSpellGroupStackRules(m_spellInfo, existingSpellInfo))
1683 {
1685 case SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST: // if it reaches this point, existing aura is lower/equal
1686 return false;
1688 if (sameCaster)
1689 return false;
1690 break;
1693 default:
1694 break;
1695 }
1696
1697 if (m_spellInfo->SpellFamilyName != existingSpellInfo->SpellFamilyName)
1698 return true;
1699
1700 if (!sameCaster)
1701 {
1702 // Channeled auras can stack if not forbidden by db or aura type
1703 if (existingAura->GetSpellInfo()->IsChanneled())
1704 return true;
1705
1707 return true;
1708
1709 // check same periodic auras
1710 auto hasPeriodicNonAreaEffect = [](SpellInfo const* spellInfo)
1711 {
1712 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
1713 {
1714 switch (spellEffectInfo.ApplyAuraName)
1715 {
1716 // DOT or HOT from different casters will stack
1730 // periodic auras which target areas are not allowed to stack this way (replenishment for example)
1731 if (spellEffectInfo.IsTargetingArea())
1732 return false;
1733 return true;
1734 default:
1735 break;
1736 }
1737 }
1738 return false;
1739 };
1740
1741 if (hasPeriodicNonAreaEffect(m_spellInfo) && hasPeriodicNonAreaEffect(existingSpellInfo))
1742 return true;
1743 }
1744
1746 {
1747 Vehicle* veh = nullptr;
1748 if (GetOwner()->ToUnit())
1749 veh = GetOwner()->ToUnit()->GetVehicleKit();
1750
1751 if (!veh) // We should probably just let it stack. Vehicle system will prevent undefined behaviour later
1752 return true;
1753
1754 if (!veh->GetAvailableSeatCount())
1755 return false; // No empty seat available
1756
1757 return true; // Empty seat available (skip rest)
1758 }
1759
1762 return false;
1763
1764 // spell of same spell rank chain
1765 if (m_spellInfo->IsRankOf(existingSpellInfo))
1766 {
1767 // don't allow passive area auras to stack
1768 if (m_spellInfo->IsMultiSlotAura() && !IsArea())
1769 return true;
1770 if (!GetCastItemGUID().IsEmpty() && !existingAura->GetCastItemGUID().IsEmpty())
1772 return true;
1773 // same spell with same caster should not stack
1774 return false;
1775 }
1776
1777 return true;
1778}
1779
1781{
1782 return m_procCooldown > now;
1783}
1784
1786{
1787 // cooldowns should be added to the whole aura (see 51698 area aura)
1788 int32 procCooldown = procEntry->Cooldown.count();
1789 if (Unit* caster = GetCaster())
1790 if (Player* modOwner = caster->GetSpellModOwner())
1791 modOwner->ApplySpellMod(GetSpellInfo(), SpellModOp::ProcCooldown, procCooldown);
1792
1793 m_procCooldown = now + Milliseconds(procCooldown);
1794}
1795
1800
1802{
1803 bool prepare = CallScriptPrepareProcHandlers(aurApp, eventInfo);
1804 if (!prepare)
1805 return;
1806
1807 SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetSpellInfo());
1808 ASSERT(procEntry);
1809
1810 PrepareProcChargeDrop(procEntry, eventInfo);
1811
1812 // cooldowns should be added to the whole aura (see 51698 area aura)
1813 AddProcCooldown(procEntry, now);
1814
1816}
1817
1818void Aura::PrepareProcChargeDrop(SpellProcEntry const* procEntry, ProcEventInfo const& eventInfo)
1819{
1820 // take one charge, aura expiration will be handled in Aura::TriggerProcOnEvent (if needed)
1822 {
1823 --m_procCharges;
1825 }
1826}
1827
1829{
1830 // Remove aura if we've used last charge to proc
1832 {
1833 ModStackAmount(-1);
1834 }
1835 else if (IsUsingCharges())
1836 {
1837 if (!GetCharges())
1838 Remove();
1839 }
1840}
1841
1843{
1844 SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetSpellInfo());
1845 // only auras with spell proc entry can trigger proc
1846 if (!procEntry)
1847 return 0;
1848
1849 // check spell triggering us
1850 if (Spell const* spell = eventInfo.GetProcSpell())
1851 {
1852 // Do not allow auras to proc from effect triggered from itself
1853 if (spell->IsTriggeredByAura(m_spellInfo))
1854 return 0;
1855
1856 // check if aura can proc when spell is triggered (exception for hunter auto shot & wands)
1858 if (spell->IsTriggered() && !spell->GetSpellInfo()->HasAttribute(SPELL_ATTR3_NOT_A_PROC))
1859 return 0;
1860
1861 if (spell->m_CastItem && (procEntry->AttributesMask & PROC_ATTR_CANT_PROC_FROM_ITEM_CAST))
1862 return 0;
1863
1864 if (spell->GetSpellInfo()->HasAttribute(SPELL_ATTR4_SUPPRESS_WEAPON_PROCS) && GetSpellInfo()->HasAttribute(SPELL_ATTR6_AURA_IS_WEAPON_PROC))
1865 return 0;
1866
1868 return 0;
1869
1870 if (eventInfo.GetTypeMask() & TAKEN_HIT_PROC_FLAG_MASK)
1871 {
1872 if (spell->GetSpellInfo()->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS)
1874 return 0;
1875 }
1876 else
1877 {
1878 if (spell->GetSpellInfo()->HasAttribute(SPELL_ATTR3_SUPPRESS_CASTER_PROCS)
1879 && !spell->GetSpellInfo()->HasAttribute(SPELL_ATTR12_ENABLE_PROCS_FROM_SUPPRESSED_CASTER_PROCS)
1881 return 0;
1882 }
1883 }
1884
1885 // check don't break stealth attr present
1887 {
1888 if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo())
1889 if (spellInfo->HasAttribute(SPELL_ATTR0_CU_DONT_BREAK_STEALTH))
1890 return 0;
1891 }
1892
1893 // check if we have charges to proc with
1894 if (IsUsingCharges() && !GetCharges())
1895 return 0;
1896
1898 if (Spell const* spell = eventInfo.GetProcSpell())
1899 if (!spell->m_appliedMods.contains(const_cast<Aura*>(this)))
1900 return 0;
1901
1902 // check proc cooldown
1903 if (IsProcOnCooldown(now))
1904 return 0;
1905
1906 // do checks against db data
1907 if (!SpellMgr::CanSpellTriggerProcOnEvent(*procEntry, eventInfo))
1908 return 0;
1909
1910 // do checks using conditions table
1911 if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_SPELL_PROC, GetId(), eventInfo.GetActor(), eventInfo.GetActionTarget()))
1912 return 0;
1913
1914 // AuraScript Hook
1915 bool check = const_cast<Aura*>(this)->CallScriptCheckProcHandlers(aurApp, eventInfo);
1916 if (!check)
1917 return 0;
1918
1919 // At least one effect has to pass checks to proc aura
1920 uint32 procEffectMask = aurApp->GetEffectMask();
1921 for (AuraEffect const* aurEff : GetAuraEffects())
1922 if (procEffectMask & (1u << aurEff->GetEffIndex()))
1923 if ((procEntry->DisableEffectsMask & (1u << aurEff->GetEffIndex())) || !aurEff->CheckEffectProc(aurApp, eventInfo))
1924 procEffectMask &= ~(1u << aurEff->GetEffIndex());
1925
1926 if (!procEffectMask)
1927 return 0;
1928
1930 // do allow additional requirements for procs
1931 // this is needed because this is the last moment in which you can prevent aura charge drop on proc
1932 // and possibly a way to prevent default checks (if there're going to be any)
1933
1934 // Check if current equipment meets aura requirements
1935 // do that only for passive spells
1937 Unit* target = aurApp->GetTarget();
1938 if (IsPassive() && target->GetTypeId() == TYPEID_PLAYER && GetSpellInfo()->EquippedItemClass != -1)
1939 {
1941 {
1942 Item* item = nullptr;
1944 {
1945 if (target->ToPlayer()->IsInFeralForm())
1946 return 0;
1947
1948 if (DamageInfo const* damageInfo = eventInfo.GetDamageInfo())
1949 {
1950 if (damageInfo->GetAttackType() != OFF_ATTACK)
1952 else
1954 }
1955 }
1957 {
1958 // Check if player is wearing shield
1960 }
1961
1962 if (!item || item->IsBroken() || !item->IsFitToSpellRequirements(GetSpellInfo()))
1963 return 0;
1964 }
1965 }
1966
1968 if (!target->IsOutdoors())
1969 return 0;
1970
1972 if (target->GetGUID() != GetCasterGUID())
1973 return 0;
1974
1976 if (!target->IsStandState())
1977 return 0;
1978
1979 bool success = roll_chance(CalcProcChance(*procEntry, eventInfo));
1980
1981 const_cast<Aura*>(this)->SetLastProcAttemptTime(now);
1982
1983 if (success)
1984 return procEffectMask;
1985
1986 return 0;
1987}
1988
1989float Aura::CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const
1990{
1991 float chance = procEntry.Chance;
1992 // calculate chances depending on unit with caster's data
1993 // so talents modifying chances and judgements will have properly calculated proc chance
1994 if (Unit* caster = GetCaster())
1995 {
1996 // calculate ppm chance if present and we're using weapon
1997 if (eventInfo.GetDamageInfo() && procEntry.ProcsPerMinute != 0)
1998 {
1999 uint32 WeaponSpeed = caster->GetBaseAttackTime(eventInfo.GetDamageInfo()->GetAttackType());
2000 chance = caster->GetPPMProcChance(WeaponSpeed, procEntry.ProcsPerMinute, GetSpellInfo());
2001 }
2002
2003 if (GetSpellInfo()->ProcBasePPM > 0.0f)
2004 chance = CalcPPMProcChance(caster);
2005
2006 // apply chance modifer aura, applies also to ppm chance (see improved judgement of light spell)
2007 if (Player* modOwner = caster->GetSpellModOwner())
2008 modOwner->ApplySpellMod(GetSpellInfo(), SpellModOp::ProcChance, chance);
2009 }
2010
2011 // proc chance is reduced by an additional 3.333% per level past 60
2012 if ((procEntry.AttributesMask & PROC_ATTR_REDUCE_PROC_60) && eventInfo.GetActor()->GetLevel() > 60)
2013 chance = std::max(0.f, (1.f - ((eventInfo.GetActor()->GetLevel() - 60) * 1.f / 30.f)) * chance);
2014
2015 return chance;
2016}
2017
2018void Aura::TriggerProcOnEvent(uint32 procEffectMask, AuraApplication* aurApp, ProcEventInfo& eventInfo)
2019{
2020 if (procEffectMask)
2021 {
2022 bool prevented = CallScriptProcHandlers(aurApp, eventInfo);
2023 if (!prevented)
2024 {
2025 for (std::size_t i = 0; i < GetAuraEffectCount(); ++i)
2026 {
2027 if (!(procEffectMask & (1 << i)))
2028 continue;
2029
2030 // OnEffectProc / AfterEffectProc hooks handled in AuraEffect::HandleProc()
2031 if (aurApp->HasEffect(i))
2032 GetEffect(i)->HandleProc(aurApp, eventInfo);
2033 }
2034
2035 CallScriptAfterProcHandlers(aurApp, eventInfo);
2036 }
2037 }
2038
2040}
2041
2043{
2044 // Formula see http://us.battle.net/wow/en/forum/topic/8197741003#1
2045 float ppm = m_spellInfo->CalcProcPPM(actor, GetCastItemLevel());
2046 float averageProcInterval = 60.0f / ppm;
2047
2048 TimePoint currentTime = GameTime::Now();
2049 float secondsSinceLastAttempt = std::min(duration_cast<FloatSeconds>(currentTime - m_lastProcAttemptTime).count(), 10.0);
2050 float secondsSinceLastProc = std::min(duration_cast<FloatSeconds>(currentTime - m_lastProcSuccessTime).count(), 1000.0);
2051
2052 float chance = std::max(1.0f, 1.0f + ((secondsSinceLastProc / averageProcInterval - 1.5f) * 3.0f)) * ppm * secondsSinceLastAttempt / 60.0f;
2053 RoundToInterval(chance, 0.0f, 1.0f);
2054 return chance * 100.0f;
2055}
2056
2058{
2060 delete aurApp;
2061
2062 _removedApplications.clear();
2063}
2064
2066{
2067 sScriptMgr->CreateAuraScripts(m_spellInfo->Id, m_loadedScripts, this);
2068 for (AuraScript* script : m_loadedScripts)
2069 {
2070 TC_LOG_DEBUG("spells", "Aura::LoadScripts: Script `{}` for aura `{}` is loaded now", script->GetScriptName(), m_spellInfo->Id);
2071 script->Register();
2072 }
2073}
2074
2076{
2077 bool result = true;
2078 for (AuraScript* script : m_loadedScripts)
2079 {
2080 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_AREA_TARGET);
2081 for (AuraScript::CheckAreaTargetHandler const& checkAreaTarget : script->DoCheckAreaTarget)
2082 result &= checkAreaTarget.Call(script, target);
2083
2084 script->_FinishScriptCall();
2085 }
2086 return result;
2087}
2088
2090{
2091 for (AuraScript* script : m_loadedScripts)
2092 {
2093 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_DISPEL);
2094 for (AuraScript::AuraDispelHandler const& onDispel : script->OnDispel)
2095 onDispel.Call(script, dispelInfo);
2096
2097 script->_FinishScriptCall();
2098 }
2099}
2100
2102{
2103 for (AuraScript* script : m_loadedScripts)
2104 {
2105 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_DISPEL);
2106 for (AuraScript::AuraDispelHandler const& afterDispel : script->AfterDispel)
2107 afterDispel.Call(script, dispelInfo);
2108
2109 script->_FinishScriptCall();
2110 }
2111}
2112
2114{
2115 for (AuraScript* script : m_loadedScripts)
2116 {
2117 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_ON_HEARTBEAT);
2118 for (AuraScript::AuraHeartbeatHandler const& onHeartbeat : script->OnHeartbeat)
2119 onHeartbeat.Call(script);
2120
2121 script->_FinishScriptCall();
2122 }
2123}
2124
2126{
2127 bool preventDefault = false;
2128 for (AuraScript* script : m_loadedScripts)
2129 {
2130 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_APPLY, aurApp);
2131 for (AuraScript::EffectApplyHandler const& onEffectApply : script->OnEffectApply)
2132 if (onEffectApply.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2133 onEffectApply.Call(script, aurEff, mode);
2134
2135 if (!preventDefault)
2136 preventDefault = script->_IsDefaultActionPrevented();
2137
2138 script->_FinishScriptCall();
2139 }
2140
2141 return preventDefault;
2142}
2143
2145{
2146 bool preventDefault = false;
2147 for (AuraScript* script : m_loadedScripts)
2148 {
2149 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_REMOVE, aurApp);
2150 for (AuraScript::EffectApplyHandler const& onEffectRemove : script->OnEffectRemove)
2151 if (onEffectRemove.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2152 onEffectRemove.Call(script, aurEff, mode);
2153
2154 if (!preventDefault)
2155 preventDefault = script->_IsDefaultActionPrevented();
2156
2157 script->_FinishScriptCall();
2158 }
2159 return preventDefault;
2160}
2161
2163{
2164 for (AuraScript* script : m_loadedScripts)
2165 {
2166 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_APPLY, aurApp);
2167 for (AuraScript::EffectApplyHandler const& afterEffectApply : script->AfterEffectApply)
2168 if (afterEffectApply.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2169 afterEffectApply.Call(script, aurEff, mode);
2170
2171 script->_FinishScriptCall();
2172 }
2173}
2174
2176{
2177 for (AuraScript* script : m_loadedScripts)
2178 {
2179 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_REMOVE, aurApp);
2180 for (AuraScript::EffectApplyHandler const& afterEffectRemove : script->AfterEffectRemove)
2181 if (afterEffectRemove.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2182 afterEffectRemove.Call(script, aurEff, mode);
2183
2184 script->_FinishScriptCall();
2185 }
2186}
2187
2189{
2190 bool preventDefault = false;
2191 for (AuraScript* script : m_loadedScripts)
2192 {
2193 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PERIODIC, aurApp);
2194 for (AuraScript::EffectPeriodicHandler const& onEffectPeriodic : script->OnEffectPeriodic)
2195 if (onEffectPeriodic.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2196 onEffectPeriodic.Call(script, aurEff);
2197
2198 if (!preventDefault)
2199 preventDefault = script->_IsDefaultActionPrevented();
2200
2201 script->_FinishScriptCall();
2202 }
2203
2204 return preventDefault;
2205}
2206
2208{
2209 for (AuraScript* script : m_loadedScripts)
2210 {
2211 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_UPDATE_PERIODIC);
2212 for (AuraScript::EffectUpdatePeriodicHandler const& onEffectUpdatePeriodic : script->OnEffectUpdatePeriodic)
2213 if (onEffectUpdatePeriodic.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2214 onEffectUpdatePeriodic.Call(script, aurEff);
2215
2216 script->_FinishScriptCall();
2217 }
2218}
2219
2220void Aura::CallScriptEffectCalcAmountHandlers(AuraEffect const* aurEff, SpellEffectValue& amount, bool& canBeRecalculated)
2221{
2222 for (AuraScript* script : m_loadedScripts)
2223 {
2224 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT);
2225 for (AuraScript::EffectCalcAmountHandler const& effectCalcAmount : script->DoEffectCalcAmount)
2226 if (effectCalcAmount.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2227 effectCalcAmount.Call(script, aurEff, amount, canBeRecalculated);
2228
2229 script->_FinishScriptCall();
2230 }
2231}
2232
2233void Aura::CallScriptEffectCalcPeriodicHandlers(AuraEffect const* aurEff, bool& isPeriodic, int32& amplitude)
2234{
2235 for (AuraScript* script : m_loadedScripts)
2236 {
2237 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC);
2238 for (AuraScript::EffectCalcPeriodicHandler const& effectCalcPeriodic : script->DoEffectCalcPeriodic)
2239 if (effectCalcPeriodic.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2240 effectCalcPeriodic.Call(script, aurEff, isPeriodic, amplitude);
2241
2242 script->_FinishScriptCall();
2243 }
2244}
2245
2247{
2248 for (AuraScript* script : m_loadedScripts)
2249 {
2250 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD);
2251 for (AuraScript::EffectCalcSpellModHandler const& effectCalcSpellMod : script->DoEffectCalcSpellMod)
2252 if (effectCalcSpellMod.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2253 effectCalcSpellMod.Call(script, aurEff, spellMod);
2254
2255 script->_FinishScriptCall();
2256 }
2257}
2258
2259void Aura::CallScriptEffectCalcCritChanceHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, Unit const* victim, float& critChance)
2260{
2261 for (AuraScript* script : m_loadedScripts)
2262 {
2263 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_CRIT_CHANCE, aurApp);
2264 for (AuraScript::EffectCalcCritChanceHandler const& effectCalcCritChance : script->DoEffectCalcCritChance)
2265 if (effectCalcCritChance.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2266 effectCalcCritChance.Call(script, aurEff, victim, critChance);
2267
2268 script->_FinishScriptCall();
2269 }
2270}
2271
2272void Aura::CallScriptCalcDamageAndHealingHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, Unit* victim, int32& damageOrHealing, int32& flatMod, float& pctMod)
2273{
2274 for (AuraScript* script : m_loadedScripts)
2275 {
2276 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_DAMAGE_AND_HEALING, aurApp);
2277 for (AuraScript::EffectCalcDamageAndHealingHandler const& effectCalcDamageAndHealing : script->DoEffectCalcDamageAndHealing)
2278 if (effectCalcDamageAndHealing.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2279 effectCalcDamageAndHealing.Call(script, aurEff, victim, damageOrHealing, flatMod, pctMod);
2280
2281 script->_FinishScriptCall();
2282 }
2283}
2284
2285void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& defaultPrevented)
2286{
2287 for (AuraScript* script : m_loadedScripts)
2288 {
2289 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp);
2290 for (AuraScript::EffectAbsorbHandler const& onEffectAbsorb : script->OnEffectAbsorb)
2291 if (onEffectAbsorb.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2292 onEffectAbsorb.Call(script, aurEff, dmgInfo, absorbAmount);
2293
2294 if (!defaultPrevented)
2295 defaultPrevented = script->_IsDefaultActionPrevented();
2296
2297 script->_FinishScriptCall();
2298 }
2299}
2300
2301void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount)
2302{
2303 for (AuraScript* script : m_loadedScripts)
2304 {
2305 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp);
2306 for (AuraScript::EffectAbsorbHandler const& afterEffectAbsorb : script->AfterEffectAbsorb)
2307 if (afterEffectAbsorb.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2308 afterEffectAbsorb.Call(script, aurEff, dmgInfo, absorbAmount);
2309
2310 script->_FinishScriptCall();
2311 }
2312}
2313
2314void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, HealInfo& healInfo, uint32& absorbAmount, bool& defaultPrevented)
2315{
2316 for (AuraScript* script : m_loadedScripts)
2317 {
2318 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp);
2319 for (AuraScript::EffectAbsorbHealHandler const& onEffectAbsorbHeal : script->OnEffectAbsorbHeal)
2320 if (onEffectAbsorbHeal.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2321 onEffectAbsorbHeal.Call(script, aurEff, healInfo, absorbAmount);
2322
2323 if (!defaultPrevented)
2324 defaultPrevented = script->_IsDefaultActionPrevented();
2325
2326 script->_FinishScriptCall();
2327 }
2328}
2329
2330void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, HealInfo& healInfo, uint32& absorbAmount)
2331{
2332 for (AuraScript* script : m_loadedScripts)
2333 {
2334 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp);
2335 for (AuraScript::EffectAbsorbHealHandler const& afterEffectAbsorbHeal : script->AfterEffectAbsorbHeal)
2336 if (afterEffectAbsorbHeal.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2337 afterEffectAbsorbHeal.Call(script, aurEff, healInfo, absorbAmount);
2338
2339 script->_FinishScriptCall();
2340 }
2341}
2342
2343void Aura::CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& defaultPrevented)
2344{
2345 for (AuraScript* script : m_loadedScripts)
2346 {
2347 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_MANASHIELD, aurApp);
2348 for (AuraScript::EffectAbsorbHandler const& onEffectManaShield : script->OnEffectManaShield)
2349 if (onEffectManaShield.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2350 onEffectManaShield.Call(script, aurEff, dmgInfo, absorbAmount);
2351
2352 if (!defaultPrevented)
2353 defaultPrevented = script->_IsDefaultActionPrevented();
2354
2355 script->_FinishScriptCall();
2356 }
2357}
2358
2360{
2361 for (AuraScript* script : m_loadedScripts)
2362 {
2363 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD, aurApp);
2364 for (AuraScript::EffectAbsorbHandler const& afterEffectManaShield : script->AfterEffectManaShield)
2365 if (afterEffectManaShield.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2366 afterEffectManaShield.Call(script, aurEff, dmgInfo, absorbAmount);
2367
2368 script->_FinishScriptCall();
2369 }
2370}
2371
2372void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& splitAmount)
2373{
2374 for (AuraScript* script : m_loadedScripts)
2375 {
2376 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_SPLIT, aurApp);
2377 for (AuraScript::EffectAbsorbHandler const& effectSplit : script->OnEffectSplit)
2378 if (effectSplit.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2379 effectSplit.Call(script, aurEff, dmgInfo, splitAmount);
2380
2381 script->_FinishScriptCall();
2382 }
2383}
2384
2385void Aura::CallScriptEnterLeaveCombatHandlers(AuraApplication const* aurApp, bool isNowInCombat)
2386{
2387 for (AuraScript* script : m_loadedScripts)
2388 {
2389 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_ENTER_LEAVE_COMBAT, aurApp);
2390 for (AuraScript::EnterLeaveCombatHandler const& onEnterLeaveCombat : script->OnEnterLeaveCombat)
2391 onEnterLeaveCombat.Call(script, isNowInCombat);
2392
2393 script->_FinishScriptCall();
2394 }
2395}
2396
2398{
2399 bool result = true;
2400 for (AuraScript* script : m_loadedScripts)
2401 {
2402 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_PROC, aurApp);
2403 for (AuraScript::CheckProcHandler const& checkProc : script->DoCheckProc)
2404 result &= checkProc.Call(script, eventInfo);
2405
2406 script->_FinishScriptCall();
2407 }
2408
2409 return result;
2410}
2411
2413{
2414 bool prepare = true;
2415 for (AuraScript* script : m_loadedScripts)
2416 {
2417 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_PREPARE_PROC, aurApp);
2418 for (AuraScript::AuraProcHandler const& prepareProc : script->DoPrepareProc)
2419 prepareProc.Call(script, eventInfo);
2420
2421 if (prepare)
2422 prepare = !script->_IsDefaultActionPrevented();
2423
2424 script->_FinishScriptCall();
2425 }
2426
2427 return prepare;
2428}
2429
2431{
2432 bool handled = false;
2433 for (AuraScript* script : m_loadedScripts)
2434 {
2435 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_PROC, aurApp);
2436 for (AuraScript::AuraProcHandler const& onProc : script->OnProc)
2437 onProc.Call(script, eventInfo);
2438
2439 handled |= script->_IsDefaultActionPrevented();
2440 script->_FinishScriptCall();
2441 }
2442
2443 return handled;
2444}
2445
2447{
2448 for (AuraScript* script : m_loadedScripts)
2449 {
2450 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_PROC, aurApp);
2451 for (AuraScript::AuraProcHandler const& afterProc : script->AfterProc)
2452 afterProc.Call(script, eventInfo);
2453
2454 script->_FinishScriptCall();
2455 }
2456}
2457
2459{
2460 bool result = true;
2461 for (AuraScript* script : m_loadedScripts)
2462 {
2463 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_EFFECT_PROC, aurApp);
2464 for (AuraScript::CheckEffectProcHandler const& checkEffectProc : script->DoCheckEffectProc)
2465 if (checkEffectProc.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2466 result &= checkEffectProc.Call(script, aurEff, eventInfo);
2467
2468 script->_FinishScriptCall();
2469 }
2470
2471 return result;
2472}
2473
2475{
2476 bool preventDefault = false;
2477 for (AuraScript* script : m_loadedScripts)
2478 {
2479 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PROC, aurApp);
2480 for (AuraScript::EffectProcHandler const& onEffectProc : script->OnEffectProc)
2481 if (onEffectProc.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2482 onEffectProc.Call(script, aurEff, eventInfo);
2483
2484 if (!preventDefault)
2485 preventDefault = script->_IsDefaultActionPrevented();
2486
2487 script->_FinishScriptCall();
2488 }
2489 return preventDefault;
2490}
2491
2493{
2494 for (AuraScript* script : m_loadedScripts)
2495 {
2496 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC, aurApp);
2497 for (AuraScript::EffectProcHandler const& afterEffectProc : script->AfterEffectProc)
2498 if (afterEffectProc.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2499 afterEffectProc.Call(script, aurEff, eventInfo);
2500
2501 script->_FinishScriptCall();
2502 }
2503}
2504
2505std::string Aura::GetDebugInfo() const
2506{
2507 std::stringstream sstr;
2508 sstr << std::boolalpha
2509 << "Id: " << GetId() << " Name: '" << (*GetSpellInfo()->SpellName)[sWorld->GetDefaultDbcLocale()] << "' Caster: " << GetCasterGUID().ToString()
2510 << "\nOwner: " << (GetOwner() ? GetOwner()->GetDebugInfo() : "NULL");
2511 return sstr.str();
2512}
2513
2515 : Aura(createInfo)
2516{
2518 LoadScripts();
2519 _InitEffects(createInfo._auraEffectMask, createInfo.Caster, createInfo.BaseAmount);
2520 GetUnitOwner()->_AddAura(this, createInfo.Caster);
2521}
2522
2524{
2525 Aura::_ApplyForTarget(target, caster, aurApp);
2526
2527 // register aura diminishing on apply
2528 if (DiminishingGroup group = GetDiminishGroup())
2529 target->ApplyDiminishingAura(group, true);
2530}
2531
2533{
2534 Aura::_UnapplyForTarget(target, caster, aurApp);
2535
2536 // unregister aura diminishing (and store last time)
2537 if (DiminishingGroup group = GetDiminishGroup())
2538 target->ApplyDiminishingAura(group, false);
2539}
2540
2542{
2543 if (IsRemoved())
2544 return;
2545 GetUnitOwner()->RemoveOwnedAura(this, removeMode);
2546}
2547
2548void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* caster)
2549{
2550 Unit* unitOwner = GetUnitOwner();
2551 if (GetSpellInfo()->HasAttribute(SPELL_ATTR7_DISABLE_AURA_WHILE_DEAD) && !unitOwner->IsAlive())
2552 return;
2553
2554 Unit* ref = caster;
2555 if (!ref)
2556 ref = unitOwner;
2557
2558 // add non area aura targets
2559 // static applications go through spell system first, so we assume they meet conditions
2560 for (auto const& [targetGuid, effectMask] : _staticApplications)
2561 {
2562 Unit* target = ObjectAccessor::GetUnit(*unitOwner, targetGuid);
2563 if (!target && targetGuid == unitOwner->GetGUID())
2564 target = unitOwner;
2565
2566 if (target)
2567 targets.emplace(target, effectMask);
2568 }
2569
2570 // skip area update if owner is not in world!
2571 if (!unitOwner->IsInWorld())
2572 return;
2573
2574 if (unitOwner->HasAuraState(AURA_STATE_BANISHED, GetSpellInfo(), caster))
2575 return;
2576
2577 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
2578 {
2579 if (!HasEffect(spellEffectInfo.EffectIndex))
2580 continue;
2581
2582 // area auras only
2583 if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA))
2584 continue;
2585
2586 std::vector<Unit*> units;
2587 ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions.get();
2588
2589 SpellRange radius = spellEffectInfo.CalcRadius(ref);
2590 float extraSearchRadius = 0.0f;
2591
2593 switch (spellEffectInfo.Effect)
2594 {
2597 selectionType = TARGET_CHECK_PARTY;
2598 break;
2600 selectionType = TARGET_CHECK_RAID;
2601 break;
2603 selectionType = TARGET_CHECK_ALLY;
2604 break;
2606 selectionType = TARGET_CHECK_ENEMY;
2607 extraSearchRadius = radius.Max > 0.0f ? EXTRA_CELL_SEARCH_RADIUS : 0.0f;
2608 break;
2610 if (!condList || sConditionMgr->IsObjectMeetToConditions(unitOwner, ref, *condList))
2611 units.push_back(unitOwner);
2612 [[fallthrough]];
2614 {
2615 if (Unit* owner = unitOwner->GetCharmerOrOwner())
2616 if (owner->IsInWorld() && unitOwner->InSamePhase(owner) && unitOwner->IsInRange3d(owner, radius.Min, radius.Max))
2617 if (!condList || sConditionMgr->IsObjectMeetToConditions(owner, ref, *condList))
2618 units.push_back(owner);
2619 break;
2620 }
2622 {
2623 if (Unit* pet = ObjectAccessor::GetUnit(*unitOwner, unitOwner->GetPetGUID()))
2624 if (!condList || sConditionMgr->IsObjectMeetToConditions(pet, ref, *condList))
2625 units.push_back(pet);
2626 break;
2627 }
2629 {
2630 if (!condList || sConditionMgr->IsObjectMeetToConditions(unitOwner, ref, *condList))
2631 units.push_back(unitOwner);
2632
2633 selectionType = TARGET_CHECK_SUMMONED;
2634 break;
2635 }
2636 default:
2637 break;
2638 }
2639
2640 if (selectionType != TARGET_CHECK_DEFAULT)
2641 {
2642 if (uint32 containerTypeMask = Spell::GetSearcherTypeMask(m_spellInfo, spellEffectInfo, TARGET_OBJECT_TYPE_UNIT, condList))
2643 {
2644 Trinity::WorldObjectSpellAreaTargetCheck check(radius, unitOwner, ref, unitOwner, m_spellInfo, selectionType, condList, TARGET_OBJECT_TYPE_UNIT);
2646 Spell::SearchTargets(searcher, containerTypeMask, unitOwner, unitOwner, radius.Max + extraSearchRadius);
2647
2648 // by design WorldObjectSpellAreaTargetCheck allows not-in-world units (for spells) but for auras it is not acceptable
2649 Trinity::Containers::EraseIf(units, [unitOwner](Unit const* unit) { return !unit->IsSelfOrInSameMap(unitOwner); });
2650 }
2651 }
2652
2653 for (Unit* unit : units)
2654 targets[unit] |= 1 << spellEffectInfo.EffectIndex;
2655 }
2656}
2657
2659{
2660 // only valid for non-area auras
2661 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
2662 {
2663 if ((effMask & (1 << spellEffectInfo.EffectIndex)) && !spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA))
2664 effMask &= ~(1 << spellEffectInfo.EffectIndex);
2665 }
2666
2667 if (!effMask)
2668 return;
2669
2670 _staticApplications[target->GetGUID()] |= effMask;
2671}
2672
2674{
2676
2677 // Periodic food and drink emote animation
2679
2680 // Invoke the OnHeartbeat AuraScript hook
2682}
2683
2685{
2687
2688 bool food = specificType == SPELL_SPECIFIC_FOOD || specificType == SPELL_SPECIFIC_FOOD_AND_DRINK;
2689 bool drink = specificType == SPELL_SPECIFIC_DRINK || specificType == SPELL_SPECIFIC_FOOD_AND_DRINK;
2690
2691 if (food)
2693
2694 if (drink)
2696}
2697
2699 : Aura(createInfo)
2700{
2701 LoadScripts();
2702 DynamicObject* dynObjOwner = GetDynobjOwner();
2703 ASSERT(dynObjOwner);
2704 ASSERT(createInfo.Caster);
2705 ASSERT(dynObjOwner->IsInMap(createInfo.Caster));
2706 _InitEffects(createInfo._auraEffectMask, createInfo.Caster, createInfo.BaseAmount);
2707 dynObjOwner->SetAura(this);
2708}
2709
2711{
2712 if (IsRemoved())
2713 return;
2714 _Remove(removeMode);
2715}
2716
2717void DynObjAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* /*caster*/)
2718{
2719 DynamicObject* dynObjOwner = GetDynobjOwner();
2720 Unit* dynObjOwnerCaster = dynObjOwner->GetCaster();
2721 float radius = dynObjOwner->GetRadius();
2722
2723 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
2724 {
2725 if (!HasEffect(spellEffectInfo.EffectIndex))
2726 continue;
2727
2728 // we can't use effect type like area auras to determine check type, check targets
2729 SpellTargetCheckTypes selectionType = spellEffectInfo.TargetA.GetCheckType();
2730 if (spellEffectInfo.TargetB.GetReferenceType() == TARGET_REFERENCE_TYPE_DEST)
2731 selectionType = spellEffectInfo.TargetB.GetCheckType();
2732
2733 std::vector<Unit*> units;
2734 ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions.get();
2735
2736 Trinity::WorldObjectSpellAreaTargetCheck check({ .Max = radius }, dynObjOwner, dynObjOwnerCaster, dynObjOwnerCaster, m_spellInfo, selectionType, condList, TARGET_OBJECT_TYPE_UNIT);
2737 Trinity::UnitListSearcher searcher(dynObjOwner, units, check);
2738 Cell::VisitAllObjects(dynObjOwner, searcher, radius);
2739
2740 // by design WorldObjectSpellAreaTargetCheck allows not-in-world units (for spells) but for auras it is not acceptable
2741 Trinity::Containers::EraseIf(units, [dynObjOwner](Unit const* unit) { return !unit->IsSelfOrInSameMap(dynObjOwner); });
2742
2743 for (Unit* unit : units)
2744 targets[unit] |= 1 << spellEffectInfo.EffectIndex;
2745 }
2746}
@ IN_MILLISECONDS
Definition Common.h:38
std::vector< Condition > ConditionContainer
#define sConditionMgr
@ CONDITION_SOURCE_TYPE_SPELL_PROC
#define MAX_EFFECT_MASK
Definition DBCEnums.h:2431
Difficulty
Definition DBCEnums.h:932
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint64_t uint64
Definition Define.h:153
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:28
std::chrono::steady_clock::time_point TimePoint
time_point shorthand typedefs
Definition Duration.h:40
#define ABORT
Definition Errors.h:87
#define ASSERT_NODEBUGINFO
Definition Errors.h:81
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:82
#define ASSERT
Definition Errors.h:80
@ ITEM_CLASS_ARMOR
@ ITEM_CLASS_WEAPON
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:181
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define TC_LOG_FATAL(filterType__, message__,...)
Definition Log.h:193
#define EXTRA_CELL_SEARCH_RADIUS
@ TYPEID_DYNAMICOBJECT
Definition ObjectGuid.h:47
@ TYPEID_UNIT
Definition ObjectGuid.h:43
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
@ EQUIPMENT_SLOT_MAINHAND
Definition Player.h:744
@ EQUIPMENT_SLOT_OFFHAND
Definition Player.h:745
#define INVENTORY_SLOT_BAG_0
Definition Player.h:723
bool roll_chance(T chance)
Definition Random.h:55
#define sScriptMgr
Definition ScriptMgr.h:1449
@ SPELL_ATTR11_SCALES_WITH_ITEM_LEVEL
SpellEffIndex
@ EFFECT_0
@ SPELL_ATTR7_CAN_PROC_FROM_SUPPRESSED_TARGET_PROCS
@ SPELL_ATTR7_DISABLE_AURA_WHILE_DEAD
@ SPELL_ATTR5_DO_NOT_DISPLAY_DURATION
@ SPELL_ATTR5_AURA_UNIQUE_PER_CASTER
@ SPELL_ATTR2_ALLOW_WHILE_NOT_SHAPESHIFTED_CASTER_FORM
@ SPELL_ATTR2_CANT_CRIT
@ SPELL_ATTR2_NO_TARGET_PER_SECOND_COSTS
@ SPELL_ATTR1_AURA_UNIQUE
@ SPELL_ATTR3_NOT_A_PROC
@ SPELL_ATTR3_SUPPRESS_TARGET_PROCS
@ SPELL_ATTR3_ONLY_PROC_ON_CASTER
@ SPELL_ATTR3_DOT_STACKING_RULE
@ SPELL_ATTR3_NO_PROC_EQUIP_REQUIREMENT
@ SPELL_ATTR3_CAN_PROC_FROM_PROCS
@ SPELL_ATTR3_ONLY_PROC_OUTDOORS
@ SPELL_ATTR3_SUPPRESS_CASTER_PROCS
@ SPELL_EFFECT_APPLY_AREA_AURA_PARTY
@ SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
@ SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM
@ SPELL_EFFECT_APPLY_AURA_ON_PET
@ 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_AREA_AURA_SUMMONS
@ SPELL_EFFECT_APPLY_AURA
@ SPELL_EFFECT_APPLY_AREA_AURA_OWNER
@ OFF_ATTACK
@ IMMUNITY_ID
Powers
@ POWER_HEALTH
@ POWER_MANA
@ SPELL_ATTR0_NOT_SHAPESHIFTED
@ SPELL_VISUAL_KIT_DRINK
@ SPELL_VISUAL_KIT_FOOD
@ SPELL_ATTR12_ONLY_PROC_FROM_CLASS_ABILITIES
@ SPELL_ATTR12_CAN_PROC_FROM_SUPPRESSED_CASTER_PROCS
@ SPELL_ATTR12_ENABLE_PROCS_FROM_SUPPRESSED_CASTER_PROCS
DiminishingGroup
@ DIMINISHING_NONE
@ AURA_STATE_BANISHED
@ SPELLFAMILY_PRIEST
@ SPELLFAMILY_MAGE
@ SPELLFAMILY_GENERIC
@ SPELLFAMILY_PALADIN
@ SPELLFAMILY_HUNTER
@ SPELLFAMILY_ROGUE
@ SPELLFAMILY_DRUID
@ SPELL_ATTR13_ALLOW_CLASS_ABILITY_PROCS
@ SPELL_ATTR13_PERIODIC_REFRESH_EXTENDS_DURATION
@ SPELL_ATTR4_SUPPRESS_WEAPON_PROCS
@ SPELL_ATTR4_ALLOW_PROC_WHILE_SITTING
@ SPELL_ATTR8_PERIODIC_CAN_CRIT
@ SPELL_ATTR8_HASTE_AFFECTS_DURATION
@ SPELL_ATTR8_AURA_POINTS_ON_CLIENT
@ SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES
@ SPELL_ATTR6_AURA_IS_WEAPON_PROC
#define MAX_AURAS
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
AuraRemoveMode
@ AURA_REMOVE_NONE
@ AURA_REMOVE_BY_DEFAULT
@ AURA_REMOVE_BY_DEATH
@ AURA_REMOVE_BY_EXPIRE
@ AURA_REMOVE_BY_ENEMY_SPELL
@ SPELL_AURA_PERIODIC_WEAPON_PERCENT_DAMAGE
@ SPELL_AURA_PERIODIC_DAMAGE
@ SPELL_AURA_OBS_MOD_HEALTH
@ SPELL_AURA_SHOW_CONFIRMATION_PROMPT_WITH_DIFFICULTY
@ SPELL_AURA_PERIODIC_MANA_LEECH
@ SPELL_AURA_CHARGE_RECOVERY_MOD
@ SPELL_AURA_OBS_MOD_POWER
@ SPELL_AURA_CONTROL_VEHICLE
@ SPELL_AURA_PERIODIC_HEAL
@ SPELL_AURA_PERIODIC_DAMAGE_PERCENT
@ SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_TRIGGERED
@ SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN
@ SPELL_AURA_CHARGE_RECOVERY_MULTIPLIER
@ 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_MAX_CHARGES
@ SPELL_AURA_SHOW_CONFIRMATION_PROMPT
@ SPELL_AURA_MOD_STEALTH
@ SPELL_AURA_SUPPRESS_ITEM_PASSIVE_EFFECT_BY_SPELL_LABEL
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL
@ SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS
@ AFLAG_POSITIVE
@ AFLAG_NONE
@ AFLAG_NEGATIVE
@ AFLAG_SCALABLE
@ AFLAG_NOCASTER
@ AFLAG_DURATION
AuraObjectType
@ DYNOBJ_AURA_TYPE
@ UNIT_AURA_TYPE
#define UPDATE_TARGET_MAP_INTERVAL
Definition SpellAuras.h:58
double SpellEffectValue
This is a double instead of float to be able to store full range of int32.
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
@ SPELLVALUE_BASE_POINT0
SpellTargetCheckTypes
Definition SpellInfo.h:80
@ TARGET_CHECK_PARTY
Definition SpellInfo.h:85
@ TARGET_CHECK_ENEMY
Definition SpellInfo.h:83
@ TARGET_CHECK_DEFAULT
Definition SpellInfo.h:81
@ TARGET_CHECK_SUMMONED
Definition SpellInfo.h:89
@ TARGET_CHECK_ALLY
Definition SpellInfo.h:84
@ TARGET_CHECK_RAID
Definition SpellInfo.h:86
@ TARGET_OBJECT_TYPE_UNIT
Definition SpellInfo.h:68
@ SPELL_ATTR0_CU_ENCHANT_PROC
Definition SpellInfo.h:144
@ SPELL_ATTR0_CU_DONT_BREAK_STEALTH
Definition SpellInfo.h:150
@ SPELL_ATTR0_CU_AURA_CANNOT_BE_SAVED
Definition SpellInfo.h:168
SpellSpecificType
Definition SpellInfo.h:116
@ SPELL_SPECIFIC_FOOD
Definition SpellInfo.h:128
@ SPELL_SPECIFIC_DRINK
Definition SpellInfo.h:129
@ SPELL_SPECIFIC_MAGE_POLYMORPH
Definition SpellInfo.h:127
@ SPELL_SPECIFIC_FOOD_AND_DRINK
Definition SpellInfo.h:130
@ TARGET_REFERENCE_TYPE_DEST
Definition SpellInfo.h:60
@ PROC_ATTR_CANT_PROC_FROM_ITEM_CAST
Definition SpellMgr.h:265
@ PROC_ATTR_USE_STACKS_FOR_CHARGES
Definition SpellMgr.h:262
@ PROC_ATTR_REDUCE_PROC_60
Definition SpellMgr.h:264
@ PROC_ATTR_TRIGGERED_CAN_PROC
Definition SpellMgr.h:259
@ PROC_ATTR_REQ_SPELLMOD
Definition SpellMgr.h:261
std::pair< SpellAreaForAreaMap::const_iterator, SpellAreaForAreaMap::const_iterator > SpellAreaForAreaMapBounds
Definition SpellMgr.h:512
@ SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER
Definition SpellMgr.h:347
@ SPELL_GROUP_STACK_RULE_EXCLUSIVE
Definition SpellMgr.h:346
@ SPELL_GROUP_STACK_RULE_DEFAULT
Definition SpellMgr.h:345
@ SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT
Definition SpellMgr.h:348
@ SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST
Definition SpellMgr.h:349
#define sSpellMgr
Definition SpellMgr.h:812
@ SPELL_LINK_AURA
Definition SpellMgr.h:85
@ SPELL_LINK_REMOVE
Definition SpellMgr.h:86
@ SPELL_AREA_FLAG_AUTOREMOVE
Definition SpellMgr.h:484
@ SPELL_AREA_FLAG_AUTOCAST
Definition SpellMgr.h:483
@ AUTO_ATTACK_PROC_FLAG_MASK
Definition SpellMgr.h:148
@ TAKEN_HIT_PROC_FLAG_MASK
Definition SpellMgr.h:175
@ AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC
@ AURA_SCRIPT_HOOK_CHECK_EFFECT_PROC
@ AURA_SCRIPT_HOOK_EFFECT_CALC_DAMAGE_AND_HEALING
@ AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT
@ AURA_SCRIPT_HOOK_EFFECT_REMOVE
@ AURA_SCRIPT_HOOK_EFFECT_CALC_CRIT_CHANCE
@ AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD
@ AURA_SCRIPT_HOOK_PREPARE_PROC
@ AURA_SCRIPT_HOOK_ON_HEARTBEAT
@ 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_ENTER_LEAVE_COMBAT
@ AURA_SCRIPT_HOOK_EFFECT_UPDATE_PERIODIC
#define SPELL_EMPOWER_HOLD_TIME_AT_MAX
Definition Spell.h:88
std::list< Unit * > UnitList
Definition Unit.h:123
T RoundToInterval(T &num, T floor, T ceil)
Definition Util.h:97
T CalculatePct(T base, U pct)
Definition Util.h:72
Unit * GetTarget() const
Definition SpellAuras.h:81
void BuildUpdatePacket(WorldPackets::Spells::AuraInfo &auraInfo, bool remove)
uint16 GetSlot() const
Definition SpellAuras.h:84
std::string GetDebugInfo() const
uint32 _effectsToApply
Definition SpellAuras.h:70
void ClientUpdate(bool remove=false)
bool _needClientUpdate
Definition SpellAuras.h:71
void _HandleEffect(uint8 effIndex, bool apply)
uint32 _effectMask
Definition SpellAuras.h:72
void _InitFlags(Unit *caster, uint32 effMask)
AuraApplication(Unit *target, Unit *caster, Aura *base, uint32 effMask)
void AddEffectToApplyEffectMask(SpellEffIndex spellEffectIndex)
uint16 GetFlags() const
Definition SpellAuras.h:85
Aura * GetBase() const
Definition SpellAuras.h:82
uint32 GetEffectsToApply() const
Definition SpellAuras.h:91
void UpdateApplyEffectMask(uint32 newEffMask, bool canHandleNewEffects)
void SetNeedClientUpdate()
uint32 GetEffectMask() const
Definition SpellAuras.h:86
bool IsSelfcast() const
Definition SpellAuras.h:89
AuraRemoveMode GetRemoveMode() const
Definition SpellAuras.h:96
bool HasEffect(uint8 effect) const
Definition SpellAuras.h:87
Unit *const _target
Definition SpellAuras.h:65
AuraType GetAuraType() const
SpellEffIndex GetEffIndex() const
void HandleEffect(AuraApplication *aurApp, uint8 mode, bool apply, AuraEffect const *triggeredBy=nullptr)
SpellEffectValue GetAmount() const
void HandleProc(AuraApplication *aurApp, ProcEventInfo &eventInfo)
void HandleAllEffects(AuraApplication *aurApp, uint8 mode, bool apply)
bool HasMoreThanOneEffectForType(AuraType auraType) const
UnitAura * ToUnitAura()
Definition SpellAuras.h:348
void ResetProcCooldown()
virtual void _UnapplyForTarget(Unit *target, Unit *caster, AuraApplication *auraApp)
void CallScriptEffectCalcCritChanceHandlers(AuraEffect const *aurEff, AuraApplication const *aurApp, Unit const *victim, float &critChance)
bool CanBeSaved() const
ObjectGuid GetCastId() const
Definition SpellAuras.h:186
static Aura * Create(AuraCreateInfo &createInfo)
bool CheckAreaTarget(Unit *target)
bool IsArea() const
int32 GetMaxDuration() const
Definition SpellAuras.h:217
SpellCastVisual m_spellVisual
Definition SpellAuras.h:399
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:431
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 SetStackAmount(uint8 num)
int32 GetCastItemLevel() const
Definition SpellAuras.h:190
void CallScriptEffectCalcSpellModHandlers(AuraEffect const *aurEff, SpellModifier *&spellMod)
void CallScriptCalcDamageAndHealingHandlers(AuraEffect const *aurEff, AuraApplication const *aurApp, Unit *victim, int32 &damageOrHealing, int32 &flatMod, float &pctMod)
AuraEffectVector _effects
Definition SpellAuras.h:428
int32 m_maxDuration
Definition SpellAuras.h:403
Unit * GetUnitOwner() const
Definition SpellAuras.h:196
void SetLastProcAttemptTime(TimePoint lastProcAttemptTime)
Definition SpellAuras.h:310
Trinity::IteratorPair< DBStorageIterator< AuraEffect * > > GetAuraEffects()
Definition SpellAuras.h:362
AuraApplication const * GetApplicationOfTarget(ObjectGuid guid) const
bool IsUsingStacks() const
void RefreshDuration(bool withMods=false)
float CalcPPMProcChance(Unit *actor) const
DynamicObject * GetDynobjOwner() const
Definition SpellAuras.h:197
bool CallScriptCheckAreaTargetHandlers(Unit *target)
bool CallScriptEffectRemoveHandlers(AuraEffect const *aurEff, AuraApplication const *aurApp, AuraEffectHandleModes mode)
bool CallScriptEffectPeriodicHandlers(AuraEffect const *aurEff, AuraApplication const *aurApp)
void CallScriptAfterProcHandlers(AuraApplication const *aurApp, ProcEventInfo &eventInfo)
uint8 m_stackAmount
Definition SpellAuras.h:411
ObjectGuid GetCasterGUID() const
Definition SpellAuras.h:187
bool HasEffect(uint8 effIndex) const
Definition SpellAuras.h:277
int32 m_duration
Definition SpellAuras.h:404
void RefreshTimers(bool resetPeriodicTimer)
bool CanPeriodicTickCrit() const
void CallScriptOnHeartbeat()
bool IsRemoved() const
Definition SpellAuras.h:254
void PrepareProcToTrigger(AuraApplication *aurApp, ProcEventInfo &eventInfo, TimePoint now)
std::vector< AuraApplication * > _removedApplications
Definition SpellAuras.h:426
void Update(uint32 diff, Unit *caster)
uint32 GetProcEffectMask(AuraApplication *aurApp, ProcEventInfo &eventInfo, TimePoint now) const
uint8 GetCasterLevel() const
Definition SpellAuras.h:244
WorldObject * GetOwner() const
Definition SpellAuras.h:195
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:183
int32 CalcDispelChance(Unit const *auraTarget, bool offensive) const
void GetApplicationVector(std::vector< AuraApplication * > &applications) const
TimePoint m_procCooldown
Definition SpellAuras.h:421
bool IsAppliedOnTarget(ObjectGuid guid) const
void CallScriptAfterEffectProcHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, ProcEventInfo &eventInfo)
ApplicationMap m_applications
Definition SpellAuras.h:413
void SetSpellVisual(SpellCastVisual const &spellVisual)
void AddProcCooldown(SpellProcEntry const *procEntry, TimePoint now)
int32 GetDuration() const
Definition SpellAuras.h:222
bool IsUsingCharges() const
Definition SpellAuras.h:301
void UpdateOwner(uint32 diff, WorldObject *owner)
void CallScriptEffectCalcAmountHandlers(AuraEffect const *aurEff, SpellEffectValue &amount, bool &canBeRecalculated)
void UnregisterSingleTarget()
bool IsDeathPersistent() const
bool CallScriptPrepareProcHandlers(AuraApplication const *aurApp, ProcEventInfo &eventInfo)
void PrepareProcChargeDrop(SpellProcEntry const *procEntry, ProcEventInfo const &eventInfo)
void ConsumeProcCharges(SpellProcEntry const *procEntry)
bool HasEffectType(AuraType type) const
AuraEffect * GetEffect(uint32 index) const
TimePoint m_lastProcSuccessTime
Definition SpellAuras.h:423
Unit * GetCaster() const
uint32 CalcMaxStackAmount() const
ObjectGuid const m_castItemGuid
Definition SpellAuras.h:396
void CallScriptAfterEffectApplyHandlers(AuraEffect const *aurEff, AuraApplication const *aurApp, AuraEffectHandleModes mode)
int32 m_timeCla
Definition SpellAuras.h:405
void SetCharges(uint8 charges)
virtual void FillTargetMap(std::unordered_map< Unit *, uint32 > &targets, Unit *caster)=0
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:360
void UpdateTargetMap(Unit *caster, bool apply=true)
void SetNeedClientUpdateForTargets() const
void CallScriptEnterLeaveCombatHandlers(AuraApplication const *aurApp, bool isNowInCombat)
bool ModStackAmount(int32 num, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT, bool resetPeriodicTimer=true)
int32 CalcMaxDuration() const
Definition SpellAuras.h:219
void SetDuration(int32 duration, bool withMods=false)
bool CallScriptProcHandlers(AuraApplication const *aurApp, ProcEventInfo &eventInfo)
std::size_t GetAuraEffectCount() const
Definition SpellAuras.h:374
void TriggerProcOnEvent(uint32 procEffectMask, AuraApplication *aurApp, ProcEventInfo &eventInfo)
void LoadScripts()
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:392
TimePoint m_lastProcAttemptTime
Definition SpellAuras.h:422
void CallScriptEffectSplitHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, DamageInfo &dmgInfo, uint32 &splitAmount)
AuraObjectType GetType() const
uint8 GetStackAmount() const
Definition SpellAuras.h:238
void _ApplyEffectForTargets(uint8 effIndex)
uint8 GetCharges() const
Definition SpellAuras.h:229
WorldObject *const m_owner
Definition SpellAuras.h:401
SpellInfo const * GetSpellInfo() const
Definition SpellAuras.h:182
bool CallScriptEffectProcHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, ProcEventInfo &eventInfo)
ObjectGuid GetCastItemGUID() const
Definition SpellAuras.h:188
uint32 GetEffectMask() const
bool IsRemovedOnShapeLost(Unit *target) const
void CallScriptEffectCalcPeriodicHandlers(AuraEffect const *aurEff, bool &isPeriodic, int32 &amplitude)
void _InitEffects(uint32 effMask, Unit *caster, SpellEffectValue const *baseAmount)
static bool EffectTypeNeedsSendingAmount(AuraType type)
void SetMaxDuration(int32 duration)
Definition SpellAuras.h:218
bool CanBeAppliedOn(Unit *target)
WorldObject * GetWorldObjectCaster() const
void HandleAuraSpecificMods(AuraApplication const *aurApp, Unit *caster, bool apply, bool onReapply)
virtual ~Aura()
virtual void Heartbeat()
Definition SpellAuras.h:312
void SetLastProcSuccessTime(TimePoint lastProcSuccessTime)
Definition SpellAuras.h:311
bool IsProcOnCooldown(TimePoint now) const
void SetIsSingleTarget(bool val)
Definition SpellAuras.h:258
void _DeleteRemovedApplications()
virtual void _ApplyForTarget(Unit *target, Unit *caster, AuraApplication *auraApp)
void SetLoadedState(int32 maxDuration, int32 duration, int32 charges, uint32 recalculateMask, SpellEffectValue const *amount)
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:232
bool m_isUsingCharges
Definition SpellAuras.h:417
static uint32 BuildEffectMaskForOwner(SpellInfo const *spellProto, uint32 availableEffectMask, WorldObject *owner)
void CallScriptEffectUpdatePeriodicHandlers(AuraEffect *aurEff)
void RecalculateAmountOfEffects()
AuraScript * GetScriptByType(std::type_info const &type) const
bool IsPassive() const
bool m_isRemoved
Definition SpellAuras.h:415
Aura(AuraCreateInfo const &createInfo)
std::vector< SpellPowerEntry const * > m_periodicCosts
Definition SpellAuras.h:406
int32 m_updateTargetMapInterval
Definition SpellAuras.h:407
void CallScriptEffectAfterManaShieldHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, DamageInfo &dmgInfo, uint32 &absorbAmount)
bool m_isSingleTarget
Definition SpellAuras.h:416
AuraKey GenerateKey(uint32 &recalculateMask) const
Fills a helper structure containing aura primary key for character_aura, character_aura_effect,...
uint8 m_procCharges
Definition SpellAuras.h:410
bool IsPermanent() const
Definition SpellAuras.h:227
ChargeDropEvent * m_dropEvent
Definition SpellAuras.h:419
SpellCastVisual GetSpellVisual() const
Definition SpellAuras.h:191
void CallScriptAfterDispel(DispelInfo *dispelInfo)
void _Remove(AuraRemoveMode removeMode)
bool IsSingleTarget() const
Definition SpellAuras.h:256
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
bool IsInWorld() const
Definition BaseEntity.h:158
TypeID GetTypeId() const
Definition BaseEntity.h:166
void ScheduleAbort()
AuraRemoveMode _mode
ChargeDropEvent(Aura *base, AuraRemoveMode mode)
bool Execute(uint64, uint32) override
WeaponAttackType GetAttackType() const
Definition Unit.h:451
void FillTargetMap(std::unordered_map< Unit *, uint32 > &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 AddEventAtOffset(BasicEvent *event, Milliseconds offset)
Definition Item.h:179
bool IsBroken() const
Definition Item.h:267
bool IsFitToSpellRequirements(SpellInfo const *spellInfo) const
Definition Item.cpp:1477
static ObjectGuid const Empty
Definition ObjectGuid.h:314
bool IsEmpty() const
Definition ObjectGuid.h:362
bool IsUnit() const
Definition ObjectGuid.h:370
std::string ToString() const
Player * ToPlayer()
Definition Object.h:126
uint32 GetEntry() const
Definition Object.h:89
Creature * ToCreature()
Definition Object.h:121
Unit * ToUnit()
Definition Object.h:116
static PhaseShift const & GetAlwaysVisiblePhaseShift()
void SetSpellModTakingSpell(Spell *spell, bool apply)
Definition Player.cpp:23021
void ApplySpellMod(SpellInfo const *spellInfo, SpellModOp op, T &basevalue, Spell *spell=nullptr) const
Definition Player.cpp:22893
Item * GetUseableItemByPos(uint8 bag, uint8 slot) const
Definition Player.cpp:9647
Item * GetItemByGuid(ObjectGuid guid) const
Definition Player.cpp:9614
Unit * GetActionTarget() const
Definition Unit.h:500
Spell const * GetProcSpell() const
Definition Unit.h:514
SpellInfo const * GetSpellInfo() const
Definition Unit.cpp:281
ProcFlagsInit GetTypeMask() const
Definition Unit.h:503
DamageInfo * GetDamageInfo() const
Definition Unit.h:511
Unit * GetActor() const
Definition Unit.h:499
void AddCooldown(uint32 spellId, uint32 itemId, Duration cooldownDuration)
void SendCooldownEvent(SpellInfo const *spellInfo, uint32 itemId=0, Spell *spell=nullptr, bool startCooldown=true)
void ResetCooldown(uint32 spellId, bool update=false)
Duration GetRemainingCooldown(SpellInfo const *spellInfo) const
void StartCooldown(SpellInfo const *spellInfo, uint32 itemId, Spell *spell=nullptr, bool onHold=false, Optional< Duration > forcedCooldown={})
bool HasCooldown(SpellInfo const *spellInfo, uint32 itemId=0) const
std::array< SpellPowerEntry const *, MAX_POWERS_PER_SPELL > PowerCosts
Definition SpellInfo.h:391
uint32 GetSpellXSpellVisualId(WorldObject const *caster=nullptr, WorldObject const *viewer=nullptr) const
bool IsRankOf(SpellInfo const *spellInfo) const
std::unordered_set< uint32 > Labels
Definition SpellInfo.h:421
float CalcProcPPM(Unit *caster, int32 itemLevel) const
uint32 const Id
Definition SpellInfo.h:328
bool IsAuraExclusiveBySpecificPerCasterWith(SpellInfo const *spellInfo) const
bool IsDeathPersistent() const
bool IsCooldownStartedOnEvent() const
uint64 Stances
Definition SpellInfo.h:352
bool IsPassive() const
uint32 StackAmount
Definition SpellInfo.h:396
bool IsAuraExclusiveBySpecificWith(SpellInfo const *spellInfo) const
uint32 ProcCharges
Definition SpellInfo.h:383
SpellSpecificType GetSpellSpecific() const
bool IsMultiSlotAura() const
int32 GetMaxDuration() const
int32 EquippedItemClass
Definition SpellInfo.h:402
flag128 SpellFamilyFlags
Definition SpellInfo.h:415
bool IsChanneled() const
bool HasAttribute(SpellAttr0 attribute) const
Definition SpellInfo.h:456
SpellDurationEntry const * DurationEntry
Definition SpellInfo.h:390
int32 GetDuration() const
std::vector< SpellEffectInfo > const & GetEffects() const
Definition SpellInfo.h:587
bool IsEmpowerSpell() const
bool IsDifferentRankOf(SpellInfo const *spellInfo) const
LocalizedString const * SpellName
Definition SpellInfo.h:409
bool HasAura(AuraType aura) const
uint32 SpellFamilyName
Definition SpellInfo.h:414
bool IsPositiveEffect(uint8 effIndex) const
bool IsSingleTarget() const
static bool CanSpellTriggerProcOnEvent(SpellProcEntry const &procEntry, ProcEventInfo &eventInfo)
Definition SpellMgr.cpp:524
Definition Spell.h:277
static uint32 GetSearcherTypeMask(SpellInfo const *spellInfo, SpellEffectInfo const &spellEffectInfo, SpellTargetObjectTypes objType, ConditionContainer const *condList)
Definition Spell.cpp:2113
static void SearchTargets(SEARCHER &searcher, uint32 containerMask, WorldObject *referer, Position const *pos, float radius)
Definition Spell.cpp:2151
void HandlePeriodicFoodSpellVisualKit()
void Remove(AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT) override
DiminishingGroup m_AuraDRGroup
Definition SpellAuras.h:457
void FillTargetMap(std::unordered_map< Unit *, uint32 > &targets, Unit *caster) override
void AddStaticApplication(Unit *target, uint32 effMask)
void Heartbeat() override
DiminishingGroup GetDiminishGroup() const
Definition SpellAuras.h:449
void _ApplyForTarget(Unit *target, Unit *caster, AuraApplication *aurApp) override
UnitAura(AuraCreateInfo const &createInfo)
std::unordered_map< ObjectGuid, uint32 > _staticApplications
Definition SpellAuras.h:458
void _UnapplyForTarget(Unit *target, Unit *caster, AuraApplication *aurApp) override
Definition Unit.h:635
void ApplySpellImmune(uint32 spellId, SpellImmunity op, uint32 type, bool apply)
Definition Unit.cpp:8242
int32 ModifyPower(Powers power, int32 val, bool withPowerUpdate=true)
Definition Unit.cpp:8697
void RemoveOwnedAura(AuraMap::iterator &i, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3751
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3828
int64 ModifyHealth(int64 val)
Definition Unit.cpp:8599
uint32 GetCastSpellXSpellVisualId(SpellInfo const *spellInfo) const override
Definition Unit.cpp:14509
void _UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode)
Definition Unit.cpp:3602
bool HasAuraTypeWithMiscvalue(AuraType auraType, int32 miscValue) const
Definition Unit.cpp:4827
Spell * FindCurrentSpellBySpellId(uint32 spell_id) const
Definition Unit.cpp:3246
void RemoveVisibleAura(AuraApplication *aurApp)
Definition Unit.cpp:724
Aura * AddAura(uint32 spellId, Unit *target)
Definition Unit.cpp:12249
std::string GetDebugInfo() const override
Definition Unit.cpp:14591
bool HasVisibleAura(AuraApplication *aurApp) const
Definition Unit.h:1593
bool IsAlive() const
Definition Unit.h:1185
int32 GetMaxPower(Powers power) const
Definition Unit.cpp:10037
bool IsStandState() const
Definition Unit.cpp:10725
bool IsDuringRemoveFromWorld() const
Definition Unit.h:1820
Unit * GetCharmerOrOwner() const
Definition Unit.h:1221
uint64 GetMaxHealth() const
Definition Unit.h:789
Aura * GetAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4700
uint64 GetHealth() const
Definition Unit.h:788
void _AddAura(UnitAura *aura, Unit *caster)
Definition Unit.cpp:3450
bool HasAuraState(AuraStateType flag, SpellInfo const *spellProto=nullptr, Unit const *Caster=nullptr) const
Definition Unit.cpp:6146
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition Unit.h:1881
int32 GetPower(Powers power) const
Definition Unit.cpp:10028
bool IsInFeralForm() const
Definition Unit.cpp:9532
void SendPlaySpellVisualKit(uint32 id, uint32 type, uint32 duration) const
Definition Unit.cpp:12342
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4804
SpellHistory * GetSpellHistory()
Definition Unit.h:1498
void SetVisibleAura(AuraApplication *aurApp)
Definition Unit.cpp:717
void SetVisibleAuraUpdate(AuraApplication *aurApp)
Definition Unit.cpp:731
void ApplyDiminishingAura(DiminishingGroup group, bool apply)
Definition Unit.cpp:9428
AuraList & GetSingleCastAuras()
Definition Unit.h:1344
Vehicle * GetVehicleKit() const
Definition Unit.h:1782
Aura * GetAuraOfRankedSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4730
void RemoveAurasWithFamily(SpellFamilyNames family, flag128 const &familyFlag, ObjectGuid casterGUID)
Definition Unit.cpp:4276
VisibleAuraContainer const & GetVisibleAuras() const
Definition Unit.h:1592
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3974
uint8 GetLevel() const
Definition Unit.h:757
Aura * _TryStackingOrRefreshingExistingAura(AuraCreateInfo &createInfo)
Definition Unit.cpp:3387
ObjectGuid GetPetGUID() const
Definition Unit.h:1197
uint8 GetAvailableSeatCount() const
Gets the available seat count.
Definition Vehicle.cpp:712
bool InSamePhase(PhaseShift const &phaseShift) const
Definition Object.h:314
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
Definition Object.cpp:1094
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2217
std::string GetDebugInfo() const override
Definition Object.cpp:3136
Unit * GetOwner() const
Definition Object.cpp:1598
int32 CalcSpellDuration(SpellInfo const *spellInfo, std::vector< SpellPowerCost > const *powerCosts) const
Definition Object.cpp:1700
bool IsSelfOrInSameMap(WorldObject const *obj) const
Definition Object.cpp:462
bool IsOutdoors() const
Definition Object.h:336
Player * GetSpellModOwner() const
Definition Object.cpp:1641
EventProcessor m_Events
Definition Object.h:561
bool IsInRange3d(Position const *pos, float minRange, float maxRange) const
Definition Object.cpp:635
void GetZoneAndAreaId(uint32 &zoneid, uint32 &areaid) const
Definition Object.h:334
bool IsFriendlyTo(WorldObject const *target) const
Definition Object.cpp:2186
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:469
WorldPacket const * Write() override
std::vector< AuraInfo > Auras
#define sWorld
Definition World.h:916
TimePoint Now()
Current chrono steady_clock time point.
Definition GameTime.cpp:67
TC_GAME_API WorldObject * GetWorldObject(WorldObject const &, ObjectGuid const &)
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
std::list< T, Alloc >::iterator RemoveUnique(std::list< T, Alloc > &list, std::type_identity_t< T > const &value)
Definition ListUtils.h:27
constexpr void EraseIf(Container &c, Predicate p)
Definition Containers.h:283
constexpr decltype(auto) EnsureWritableVectorIndex(std::vector< T > &vec, typename std::vector< T >::size_type i)
Definition Containers.h:299
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition MapUtils.h:37
uint32 _targetEffectMask
Definition SpellAuras.h:145
SpellInfo const * _spellInfo
Definition SpellAuras.h:139
ObjectGuid CasterGUID
Definition SpellAuras.h:127
AuraCreateInfo(ObjectGuid castId, SpellInfo const *spellInfo, Difficulty castDifficulty, uint32 auraEffMask, WorldObject *owner)
WorldObject * _owner
Definition SpellAuras.h:142
Optional< SpellCastVisual > _spellVisual
Definition SpellAuras.h:143
SpellEffectValue const * BaseAmount
Definition SpellAuras.h:129
SpellCastVisual CalcSpellVisual() const
uint32 _auraEffectMask
Definition SpellAuras.h:141
uint32 SpellId
Definition SpellAuras.h:155
ObjectGuid Caster
Definition SpellAuras.h:153
ObjectGuid Item
Definition SpellAuras.h:154
uint32 EffectMask
Definition SpellAuras.h:156
CastSpellExtraArgs & SetOriginalCastId(ObjectGuid const &castId)
CastSpellExtraArgs & SetOriginalCaster(ObjectGuid const &guid)
CastSpellExtraArgs & AddSpellMod(SpellValueMod mod, int32 val)
static void VisitAllObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:203
float ProcsPerMinute
Definition SpellMgr.h:289
Milliseconds Cooldown
Definition SpellMgr.h:291
uint32 DisableEffectsMask
Definition SpellMgr.h:288
ProcAttributes AttributesMask
Definition SpellMgr.h:287
std::vector< float > EstimatedPoints
Optional< ObjectGuid > CastItem
Optional< ObjectGuid > CastUnit
Optional< AuraDataInfo > AuraData