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_SELF_CAST))
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 BuildUpdatePacket(update.Auras.emplace_back(), remove);
308
309 _target->SendMessageToSet(update.Write(), true);
310}
311
313{
314 std::stringstream sstr;
315 sstr << "Base: " << (GetBase() ? GetBase()->GetDebugInfo() : "NULL")
316 << "\nTarget: " << (GetTarget() ? GetTarget()->GetDebugInfo() : "NULL");
317 return sstr.str();
318}
319
320uint32 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 availableEffectMask, WorldObject* owner)
321{
322 ASSERT_NODEBUGINFO(spellProto);
323 ASSERT_NODEBUGINFO(owner);
324 uint32 effMask = 0;
325 switch (owner->GetTypeId())
326 {
327 case TYPEID_UNIT:
328 case TYPEID_PLAYER:
329 for (SpellEffectInfo const& spellEffectInfo : spellProto->GetEffects())
330 {
331 if (spellEffectInfo.IsUnitOwnedAuraEffect())
332 effMask |= 1 << spellEffectInfo.EffectIndex;
333 }
334 break;
336 for (SpellEffectInfo const& spellEffectInfo : spellProto->GetEffects())
337 {
338 if (spellEffectInfo.IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA))
339 effMask |= 1 << spellEffectInfo.EffectIndex;
340 }
341 break;
342 default:
343 ABORT();
344 break;
345 }
346
347 return effMask & availableEffectMask;
348}
349
350Aura* Aura::TryRefreshStackOrCreate(AuraCreateInfo& createInfo, bool updateEffectMask)
351{
352 ASSERT_NODEBUGINFO(createInfo.Caster || !createInfo.CasterGUID.IsEmpty());
353
354 if (createInfo.IsRefresh)
355 *createInfo.IsRefresh = false;
356
357 createInfo._auraEffectMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, createInfo._auraEffectMask, createInfo._owner);
358 createInfo._targetEffectMask &= createInfo._auraEffectMask;
359
360 uint32 effMask = createInfo._auraEffectMask;
361 if (createInfo._targetEffectMask)
362 effMask = createInfo._targetEffectMask;
363
364 if (!effMask)
365 return nullptr;
366
367 if (Aura* foundAura = createInfo._owner->ToUnit()->_TryStackingOrRefreshingExistingAura(createInfo))
368 {
369 // we've here aura, which script triggered removal after modding stack amount
370 // check the state here, so we won't create new Aura object
371 if (foundAura->IsRemoved())
372 return nullptr;
373
374 if (createInfo.IsRefresh)
375 *createInfo.IsRefresh = true;
376
377 // add owner
378 Unit* unit = createInfo._owner->ToUnit();
379
380 // check effmask on owner application (if existing)
381 if (updateEffectMask)
382 if (AuraApplication* aurApp = foundAura->GetApplicationOfTarget(unit->GetGUID()))
383 aurApp->UpdateApplyEffectMask(effMask, false);
384 return foundAura;
385 }
386 else
387 return Create(createInfo);
388}
389
391{
392 uint32 effMask = createInfo._auraEffectMask;
393 if (createInfo._targetEffectMask)
394 effMask = createInfo._targetEffectMask;
395
396 effMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, effMask, createInfo._owner);
397 if (!effMask)
398 return nullptr;
399
400 return Create(createInfo);
401}
402
404{
405 // try to get caster of aura
406 if (!createInfo.CasterGUID.IsEmpty())
407 {
408 if (createInfo.CasterGUID.IsUnit())
409 {
410 if (createInfo._owner->GetGUID() == createInfo.CasterGUID)
411 createInfo.Caster = createInfo._owner->ToUnit();
412 else
413 createInfo.Caster = ObjectAccessor::GetUnit(*createInfo._owner, createInfo.CasterGUID);
414 }
415 }
416 else if (createInfo.Caster)
417 createInfo.CasterGUID = createInfo.Caster->GetGUID();
418
419 // check if aura can be owned by owner
420 if (Unit* ownerUnit = createInfo._owner->ToUnit())
421 if (!ownerUnit->IsInWorld() || ownerUnit->IsDuringRemoveFromWorld())
422 // owner not in world so don't allow to own not self cast single target auras
423 if (createInfo.CasterGUID != ownerUnit->GetGUID() && createInfo._spellInfo->IsSingleTarget())
424 return nullptr;
425
426 Aura* aura = nullptr;
427 switch (createInfo._owner->GetTypeId())
428 {
429 case TYPEID_UNIT:
430 case TYPEID_PLAYER:
431 {
432 aura = new UnitAura(createInfo);
433
434 // aura can be removed in Unit::_AddAura call
435 if (aura->IsRemoved())
436 return nullptr;
437
438 // add owner
439 uint32 effMask = createInfo._auraEffectMask;
440 if (createInfo._targetEffectMask)
441 effMask = createInfo._targetEffectMask;
442
443 effMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, effMask, createInfo._owner);
444 ASSERT_NODEBUGINFO(effMask);
445
446 Unit* unit = createInfo._owner->ToUnit();
447 aura->ToUnitAura()->AddStaticApplication(unit, effMask);
448 break;
449 }
451 createInfo._auraEffectMask = Aura::BuildEffectMaskForOwner(createInfo._spellInfo, createInfo._auraEffectMask, createInfo._owner);
453
454 aura = new DynObjAura(createInfo);
455 break;
456 default:
457 ABORT();
458 return nullptr;
459 }
460
461 // scripts, etc.
462 if (aura->IsRemoved())
463 return nullptr;
464
465 return aura;
466}
467
469{
470 return _spellVisual.value_or<SpellCastVisual>({
472 .ScriptVisualID = 0
473 });
474}
475
476Aura::Aura(AuraCreateInfo const& createInfo) :
477m_spellInfo(createInfo._spellInfo), m_castDifficulty(createInfo._castDifficulty), m_castId(createInfo._castId), m_casterGuid(createInfo.CasterGUID),
478m_castItemGuid(createInfo.CastItemGUID), m_castItemId(createInfo.CastItemId),
479m_castItemLevel(createInfo.CastItemLevel), m_spellVisual(createInfo.CalcSpellVisual()),
480m_applyTime(GameTime::GetGameTime()), m_owner(createInfo._owner), m_timeCla(0), m_updateTargetMapInterval(0),
481m_casterLevel(createInfo.Caster ? createInfo.Caster->GetLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(createInfo.StackAmount),
482m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr),
483m_procCooldown(TimePoint::min()),
484m_lastProcAttemptTime(GameTime::Now() - Seconds(10)), m_lastProcSuccessTime(GameTime::Now() - Seconds(120)), m_scriptRef(this, NoopAuraDeleter())
485{
487 {
488 for (SpellPowerEntry const* power : m_spellInfo->PowerCosts)
489 if (power && (power->ManaPerSecond != 0 || power->PowerPctPerSecond > 0.0f))
490 m_periodicCosts.push_back(power);
491
492 if (!m_periodicCosts.empty())
494 }
495
498 m_procCharges = CalcMaxCharges(createInfo.Caster);
500 // m_casterLevel = cast item level/caster level, caster level should be saved to db, confirmed with sniffs
501}
502
503AuraScript* Aura::GetScriptByType(std::type_info const& type) const
504{
505 for (AuraScript* script : m_loadedScripts)
506 if (typeid(*script) == type)
507 return script;
508 return nullptr;
509}
510
511void Aura::_InitEffects(uint32 effMask, Unit* caster, SpellEffectValue const* baseAmount)
512{
513 // shouldn't be in constructor - functions in AuraEffect::AuraEffect use polymorphism
514 m_effects.resize(GetSpellInfo()->GetEffects().size());
515
516 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
517 if (effMask & (1 << spellEffectInfo.EffectIndex))
518 m_effects[spellEffectInfo.EffectIndex] = new AuraEffect(this, spellEffectInfo, baseAmount ? baseAmount + spellEffectInfo.EffectIndex : nullptr, caster);
519
520 while (!m_effects.back())
521 m_effects.pop_back();
522}
523
525{
526 if (GetSpellInfo()->HasAttribute(SPELL_ATTR2_CANT_CRIT))
527 return false;
528
529 if (GetSpellInfo()->HasAttribute(SPELL_ATTR8_PERIODIC_CAN_CRIT))
530 return true;
531
532 return false;
533}
534
536{
537 // unload scripts
538 for (AuraScript* script : m_loadedScripts)
539 {
540 script->_Unload();
541 delete script;
542 }
543
544 for (AuraEffect* effect : m_effects)
545 delete effect;
546
547 ASSERT(m_applications.empty());
549}
550
551void Aura::SetSpellVisual(SpellCastVisual const& spellVisual)
552{
553 m_spellVisual = spellVisual;
555}
556
558{
559 if (GetOwner()->GetGUID() == GetCasterGUID())
560 return GetUnitOwner();
561
563}
564
566{
567 if (GetCasterGUID().IsUnit())
568 return GetCaster();
569
571}
572
574{
575 if (index >= m_effects.size())
576 return nullptr;
577
578 return m_effects[index];
579}
580
585
586void Aura::_ApplyForTarget(Unit* target, Unit* caster, AuraApplication* auraApp)
587{
588 ASSERT(target);
589 ASSERT(auraApp);
590 // aura mustn't be already applied on target
591 ASSERT (!IsAppliedOnTarget(target->GetGUID()) && "Aura::_ApplyForTarget: aura musn't be already applied on target");
592
593 m_applications[target->GetGUID()] = auraApp;
594
595 // set infinity cooldown state for spells
596 if (caster && caster->GetTypeId() == TYPEID_PLAYER)
597 {
599 {
600 Item* castItem = !m_castItemGuid.IsEmpty() ? caster->ToPlayer()->GetItemByGuid(m_castItemGuid) : nullptr;
601 caster->GetSpellHistory()->StartCooldown(m_spellInfo, castItem ? castItem->GetEntry() : 0, nullptr, true);
602 }
603 }
604}
605
606void Aura::_UnapplyForTarget(Unit* target, Unit* caster, AuraApplication* auraApp)
607{
608 ASSERT(target);
609 ASSERT(auraApp->GetRemoveMode());
610 ASSERT(auraApp);
611
612 ApplicationMap::iterator itr = m_applications.find(target->GetGUID());
613
615 if (itr == m_applications.end())
616 {
617 TC_LOG_ERROR("spells", "Aura::_UnapplyForTarget, target: {}, caster: {}, spell:{} was not found in owners application map!",
618 target->GetGUID().ToString(), caster ? caster->GetGUID().ToString().c_str() : "Empty", auraApp->GetBase()->GetSpellInfo()->Id);
619 ABORT();
620 }
621
622 // aura has to be already applied
623 ASSERT(itr->second == auraApp);
624 m_applications.erase(itr);
625
626 _removedApplications.push_back(auraApp);
627
628 // reset cooldown state for spells
629 if (caster && GetSpellInfo()->IsCooldownStartedOnEvent())
630 // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
632}
633
634// removes aura from all targets
635// and marks aura as removed
637{
639 m_isRemoved = true;
640 ApplicationMap::iterator appItr = m_applications.begin();
641 for (appItr = m_applications.begin(); appItr != m_applications.end();)
642 {
643 AuraApplication * aurApp = appItr->second;
644 Unit* target = aurApp->GetTarget();
645 target->_UnapplyAura(aurApp, removeMode);
646 appItr = m_applications.begin();
647 }
648
649 if (m_dropEvent)
650 {
652 m_dropEvent = nullptr;
653 }
654
655 m_scriptRef = nullptr;
656}
657
658void Aura::UpdateTargetMap(Unit* caster, bool apply)
659{
660 if (IsRemoved())
661 return;
662
664
665 // fill up to date target list
666 // target, effMask
667 std::unordered_map<Unit*, uint32> targets;
668
669 FillTargetMap(targets, caster);
670
671 std::vector<Unit*> targetsToRemove;
672
673 // mark all auras as ready to remove
674 for (auto const& applicationPair : m_applications)
675 {
676 auto itr = targets.find(applicationPair.second->GetTarget());
677 // not found in current area - remove the aura
678 if (itr == targets.end())
679 targetsToRemove.push_back(applicationPair.second->GetTarget());
680 else
681 {
682 // needs readding - remove now, will be applied in next update cycle
683 // (dbcs do not have auras which apply on same type of targets but have different radius, so this is not really needed)
684 if (itr->first->IsImmunedToSpell(GetSpellInfo(), itr->second, caster, true) || !CanBeAppliedOn(itr->first))
685 {
686 targetsToRemove.push_back(applicationPair.second->GetTarget());
687 continue;
688 }
689
690 // check target immunities (for existing targets)
691 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
692 if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster, true))
693 itr->second &= ~(1 << spellEffectInfo.EffectIndex);
694
695 // needs to add/remove effects from application, don't remove from map so it gets updated
696 if (applicationPair.second->GetEffectMask() != itr->second)
697 continue;
698
699 // nothing to do - aura already applied
700 // remove from auras to register list
701 targets.erase(itr);
702 }
703 }
704
705 // register auras for units
706 for (auto itr = targets.begin(); itr != targets.end();)
707 {
708 bool addUnit = true;
709 AuraApplication* aurApp = GetApplicationOfTarget(itr->first->GetGUID());
710 if (!aurApp)
711 {
712 // check target immunities (for new targets)
713 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
714 if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster))
715 itr->second &= ~(1 << spellEffectInfo.EffectIndex);
716
717 if (!itr->second || itr->first->IsImmunedToSpell(GetSpellInfo(), itr->second, caster) || !CanBeAppliedOn(itr->first))
718 addUnit = false;
719 }
720
721 if (addUnit && !itr->first->IsHighestExclusiveAura(this, true))
722 addUnit = false;
723
724 // Dynobj auras don't hit flying targets
725 if (GetType() == DYNOBJ_AURA_TYPE && itr->first->IsInFlight())
726 addUnit = false;
727
728 // Do not apply aura if it cannot stack with existing auras
729 if (addUnit)
730 {
731 // Allow to remove by stack when aura is going to be applied on owner
732 if (itr->first != GetOwner())
733 {
734 // check if not stacking aura already on target
735 // this one prevents unwanted usefull buff loss because of stacking and prevents overriding auras periodicaly by 2 near area aura owners
736 for (Unit::AuraApplicationMap::iterator iter = itr->first->GetAppliedAuras().begin(); iter != itr->first->GetAppliedAuras().end(); ++iter)
737 {
738 Aura const* aura = iter->second->GetBase();
739 if (!CanStackWith(aura))
740 {
741 addUnit = false;
742 break;
743 }
744 }
745 }
746 }
747
748 if (!addUnit)
749 itr = targets.erase(itr);
750 else
751 {
752 // owner has to be in world, or effect has to be applied to self
753 if (!GetOwner()->IsSelfOrInSameMap(itr->first))
754 {
756 TC_LOG_FATAL("spells", "Aura {}: Owner {} (map {}) is not in the same map as target {} (map {}).", GetSpellInfo()->Id,
757 GetOwner()->GetName(), GetOwner()->IsInWorld() ? GetOwner()->GetMap()->GetId() : uint32(-1),
758 itr->first->GetName(), itr->first->IsInWorld() ? itr->first->GetMap()->GetId() : uint32(-1));
759 ABORT();
760 }
761
762 if (aurApp)
763 {
764 aurApp->UpdateApplyEffectMask(itr->second, true); // aura is already applied, this means we need to update effects of current application
765 itr = targets.erase(itr);
766 }
767 else
768 {
769 itr->first->_CreateAuraApplication(this, itr->second);
770 ++itr;
771 }
772 }
773 }
774
775 // remove auras from units no longer needing them
776 for (Unit* unit : targetsToRemove)
777 if (AuraApplication* aurApp = GetApplicationOfTarget(unit->GetGUID()))
778 unit->_UnapplyAura(aurApp, AURA_REMOVE_BY_DEFAULT);
779
780 if (!apply)
781 return;
782
783 // apply aura effects for units
784 for (auto itr = targets.begin(); itr!= targets.end(); ++itr)
785 {
786 if (AuraApplication* aurApp = GetApplicationOfTarget(itr->first->GetGUID()))
787 {
788 // owner has to be in world, or effect has to be applied to self
789 ASSERT((!GetOwner()->IsInWorld() && GetOwner() == itr->first) || GetOwner()->IsInMap(itr->first));
790 itr->first->_ApplyAura(aurApp, itr->second);
791 }
792 }
793}
794
795// targets have to be registered and not have effect applied yet to use this function
797{
798 // prepare list of aura targets
799 UnitList targetList;
800 for (ApplicationMap::iterator appIter = m_applications.begin(); appIter != m_applications.end(); ++appIter)
801 {
802 if ((appIter->second->GetEffectsToApply() & (1 << effIndex)) && !appIter->second->HasEffect(effIndex))
803 targetList.push_back(appIter->second->GetTarget());
804 }
805
806 // apply effect to targets
807 for (UnitList::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
808 {
809 if (GetApplicationOfTarget((*itr)->GetGUID()))
810 {
811 // owner has to be in world, or effect has to be applied to self
812 ASSERT((!GetOwner()->IsInWorld() && GetOwner() == *itr) || GetOwner()->IsInMap(*itr));
813 (*itr)->_ApplyAuraEffect(this, effIndex);
814 }
815 }
816}
818{
819 ASSERT(owner == m_owner);
820
821 Unit* caster = GetCaster();
822 // Apply spellmods for channeled auras
823 // used for example when triggered spell of spell:10 is modded
824 Spell* modSpell = nullptr;
825 Player* modOwner = nullptr;
826 if (caster)
827 {
828 modOwner = caster->GetSpellModOwner();
829 if (modOwner)
830 {
831 modSpell = modOwner->FindCurrentSpellBySpellId(GetId());
832 if (modSpell)
833 modOwner->SetSpellModTakingSpell(modSpell, true);
834 }
835 }
836
837 Update(diff, caster);
838
839 if (m_updateTargetMapInterval <= int32(diff))
840 UpdateTargetMap(caster);
841 else
843
844 // update aura effects
845 for (AuraEffect* effect : GetAuraEffects())
846 effect->Update(diff, caster);
847
848 // remove spellmods after effects update
849 if (modSpell)
850 modOwner->SetSpellModTakingSpell(modSpell, false);
851
853}
854
855void Aura::Update(uint32 diff, Unit* caster)
856{
857 if (m_duration > 0)
858 {
859 m_duration -= diff;
860 if (m_duration < 0)
861 m_duration = 0;
862
863 // handle manaPerSecond/manaPerSecondPerLevel
864 if (m_timeCla)
865 {
866 if (m_timeCla > int32(diff))
867 m_timeCla -= diff;
868 else if (caster && (caster == GetOwner() || !GetSpellInfo()->HasAttribute(SPELL_ATTR2_NO_TARGET_PER_SECOND_COSTS)))
869 {
870 if (!m_periodicCosts.empty())
871 {
872 m_timeCla += 1000 - diff;
873
874 for (SpellPowerEntry const* power : m_periodicCosts)
875 {
876 if (power->RequiredAuraSpellID && !caster->HasAura(power->RequiredAuraSpellID))
877 continue;
878
879 int32 manaPerSecond = power->ManaPerSecond;
880 Powers powertype = Powers(power->PowerType);
881 if (powertype != POWER_HEALTH)
882 manaPerSecond += int32(CalculatePct(caster->GetMaxPower(powertype), power->PowerPctPerSecond));
883 else
884 manaPerSecond += int32(CalculatePct(caster->GetMaxHealth(), power->PowerPctPerSecond));
885
886 if (manaPerSecond)
887 {
888 if (powertype == POWER_HEALTH)
889 {
890 if (int32(caster->GetHealth()) > manaPerSecond)
891 caster->ModifyHealth(-manaPerSecond);
892 else
893 Remove();
894 }
895 else if (int32(caster->GetPower(powertype)) >= manaPerSecond)
896 caster->ModifyPower(powertype, -manaPerSecond);
897 else
898 Remove();
899 }
900 }
901 }
902 }
903 }
904 }
905}
906
908{
909 return Aura::CalcMaxDuration(GetSpellInfo(), caster, nullptr);
910}
911
912/*static*/ int32 Aura::CalcMaxDuration(SpellInfo const* spellInfo, WorldObject const* caster, std::vector<SpellPowerCost> const* powerCosts)
913{
914 Player* modOwner = nullptr;
915 int32 maxDuration;
916
917 if (caster)
918 {
919 modOwner = caster->GetSpellModOwner();
920 maxDuration = caster->CalcSpellDuration(spellInfo, powerCosts);
921 }
922 else
923 maxDuration = spellInfo->GetDuration();
924
925 if (spellInfo->IsPassive() && !spellInfo->DurationEntry)
926 maxDuration = -1;
927
928 // IsPermanent() checks max duration (which we are supposed to calculate here)
929 if (maxDuration != -1)
930 {
931 if (modOwner)
932 modOwner->ApplySpellMod(spellInfo, SpellModOp::Duration, maxDuration);
933
934 if (spellInfo->IsEmpowerSpell())
935 maxDuration += SPELL_EMPOWER_HOLD_TIME_AT_MAX;
936 }
937
938 return maxDuration;
939}
940
941void Aura::SetDuration(int32 duration, bool withMods)
942{
943 if (withMods)
944 if (Unit* caster = GetCaster())
945 if (Player* modOwner = caster->GetSpellModOwner())
946 modOwner->ApplySpellMod(GetSpellInfo(), SpellModOp::Duration, duration);
947
948 m_duration = duration;
950}
951
952void Aura::RefreshDuration(bool withMods)
953{
954 Unit* caster = GetCaster();
955 if (withMods && caster)
956 {
957 int32 duration = m_spellInfo->GetMaxDuration();
958 // Calculate duration of periodics affected by haste.
960 duration = int32(duration * caster->m_unitData->ModCastingSpeed);
961
962 SetMaxDuration(duration);
963 SetDuration(duration);
964 }
965 else
967
968 if (!m_periodicCosts.empty())
970
971 // also reset periodic counters
972 for (AuraEffect* aurEff : GetAuraEffects())
973 aurEff->ResetTicks();
974}
975
976void Aura::RefreshTimers(bool resetPeriodicTimer)
977{
979
980 // Pandemic Mechanic
982 {
983 // Pandemic doesn't reset periodic timer
984 resetPeriodicTimer = false;
985 }
986
988
989 Unit* caster = GetCaster();
990 for (AuraEffect* aurEff : GetAuraEffects())
991 aurEff->CalculatePeriodic(caster, resetPeriodicTimer, false);
992}
993
995{
996 if (m_procCharges == charges)
997 return;
998
999 m_procCharges = charges;
1002}
1003
1005{
1006 uint32 maxProcCharges = m_spellInfo->ProcCharges;
1007 if (SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetSpellInfo()))
1008 maxProcCharges = procEntry->Charges;
1009
1010 if (caster)
1011 if (Player* modOwner = caster->GetSpellModOwner())
1012 modOwner->ApplySpellMod(GetSpellInfo(), SpellModOp::ProcCharges, maxProcCharges);
1013
1014 return uint8(maxProcCharges);
1015}
1016
1018{
1019 if (IsUsingCharges())
1020 {
1021 int32 charges = m_procCharges + num;
1022 int32 maxCharges = CalcMaxCharges();
1023
1024 // limit charges (only on charges increase, charges may be changed manually)
1025 if ((num > 0) && (charges > int32(maxCharges)))
1026 charges = maxCharges;
1027 // we're out of charges, remove
1028 else if (charges <= 0)
1029 {
1030 Remove(removeMode);
1031 return true;
1032 }
1033
1034 SetCharges(charges);
1035 }
1036
1037 return false;
1038}
1039
1041{
1042 m_dropEvent = nullptr;
1043 ModCharges(num, removeMode);
1044}
1045
1047{
1048 // aura is already during delayed charge drop
1049 if (m_dropEvent)
1050 return;
1051
1052 m_dropEvent = new ChargeDropEvent(this, removeMode);
1054}
1055
1057{
1058 m_stackAmount = stackAmount;
1059 Unit* caster = GetCaster();
1060
1061 std::vector<AuraApplication*> applications;
1062 GetApplicationVector(applications);
1063
1064 for (AuraApplication* aurApp : applications)
1065 if (!aurApp->GetRemoveMode())
1066 HandleAuraSpecificMods(aurApp, caster, false, true);
1067
1068 for (AuraEffect* aurEff : GetAuraEffects())
1069 aurEff->ChangeAmount(aurEff->CalculateAmount(caster), false, true);
1070
1071 for (AuraApplication* aurApp : applications)
1072 if (!aurApp->GetRemoveMode())
1073 HandleAuraSpecificMods(aurApp, caster, true, true);
1074
1076}
1077
1079{
1080 return m_spellInfo->StackAmount > 0 || m_stackAmount > 1;
1081}
1082
1084{
1085 int32 maxStackAmount = m_spellInfo->StackAmount;
1086 if (Unit* caster = GetCaster())
1087 if (Player* modOwner = caster->GetSpellModOwner())
1088 modOwner->ApplySpellMod(m_spellInfo, SpellModOp::MaxAuraStacks, maxStackAmount);
1089
1090 return maxStackAmount;
1091}
1092
1093bool Aura::ModStackAmount(int32 num, AuraRemoveMode removeMode /*= AURA_REMOVE_BY_DEFAULT*/, bool resetPeriodicTimer /*= true*/)
1094{
1095 int32 stackAmount = m_stackAmount + num;
1096 int32 maxStackAmount = int32(CalcMaxStackAmount());
1097
1098 // limit the stack amount (only on stack increase, stack amount may be changed manually)
1099 if ((num > 0) && (stackAmount > maxStackAmount))
1100 {
1101 // not stackable aura - set stack amount to 1
1103 stackAmount = 1;
1104 else
1105 stackAmount = maxStackAmount;
1106 }
1107 // we're out of stacks, remove
1108 else if (stackAmount <= 0)
1109 {
1110 Remove(removeMode);
1111 return true;
1112 }
1113
1115
1116 // Update stack amount
1117 SetStackAmount(stackAmount);
1118
1119 if (refresh)
1120 {
1121 RefreshTimers(resetPeriodicTimer);
1122
1123 // reset charges
1125 }
1126
1128 return false;
1129}
1130
1132{
1133 uint32 count = 0;
1134 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1135 if (HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.ApplyAuraName == auraType)
1136 ++count;
1137
1138 return count > 1;
1139}
1140
1141bool Aura::IsArea() const
1142{
1143 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1144 if (HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.IsAreaAuraEffect())
1145 return true;
1146
1147 return false;
1148}
1149
1151{
1152 return GetSpellInfo()->IsPassive();
1153}
1154
1156{
1157 return GetSpellInfo()->IsDeathPersistent();
1158}
1159
1167
1169{
1170 if (IsPassive())
1171 return false;
1172
1173 if (GetSpellInfo()->IsChanneled())
1174 return false;
1175
1176 // Check if aura is single target, not only spell info
1177 if (GetCasterGUID() != GetOwner()->GetGUID())
1178 {
1179 // owner == caster for area auras, check for possible bad data in DB
1180 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1181 {
1182 if (!spellEffectInfo.IsEffect())
1183 continue;
1184
1185 if (spellEffectInfo.IsTargetingArea() || spellEffectInfo.IsAreaAuraEffect())
1186 return false;
1187 }
1188
1190 return false;
1191 }
1192
1194 return false;
1195
1196 // don't save auras removed by proc system
1197 if (IsUsingCharges() && !GetCharges())
1198 return false;
1199
1200 // don't save permanent auras triggered by items, they'll be recasted on login if necessary
1201 if (!GetCastItemGUID().IsEmpty() && IsPermanent())
1202 return false;
1203
1204 return true;
1205}
1206
1207bool Aura::IsSingleTargetWith(Aura const* aura) const
1208{
1209 // Same spell?
1210 if (GetSpellInfo()->IsRankOf(aura->GetSpellInfo()))
1211 return true;
1212
1214 // spell with single target specific types
1215 switch (spec)
1216 {
1218 if (aura->GetSpellInfo()->GetSpellSpecific() == spec)
1219 return true;
1220 break;
1221 default:
1222 break;
1223 }
1224
1225 return false;
1226}
1227
1229{
1231 Unit* caster = GetCaster();
1232 ASSERT(caster);
1234 SetIsSingleTarget(false);
1235}
1236
1237int32 Aura::CalcDispelChance(Unit const* /*auraTarget*/, bool /*offensive*/) const
1238{
1239 // we assume that aura dispel chance is 100% on start
1240 // need formula for level difference based chance
1241 int32 resistChance = 0;
1242
1243 // Apply dispel mod from aura caster
1244 if (Unit* caster = GetCaster())
1245 if (Player* modOwner = caster->GetSpellModOwner())
1246 modOwner->ApplySpellMod(GetSpellInfo(), SpellModOp::DispelResistance, resistChance);
1247
1248 RoundToInterval(resistChance, 0, 100);
1249 return 100 - resistChance;
1250}
1251
1252AuraKey Aura::GenerateKey(uint32& recalculateMask) const
1253{
1254 AuraKey key;
1255 key.Caster = GetCasterGUID();
1256 key.Item = GetCastItemGUID();
1257 key.SpellId = GetId();
1258 key.EffectMask = 0;
1259 recalculateMask = 0;
1260 for (uint32 i = 0; i < m_effects.size(); ++i)
1261 {
1262 if (AuraEffect const* effect = m_effects[i])
1263 {
1264 key.EffectMask |= 1 << i;
1265 if (effect->CanBeRecalculated())
1266 recalculateMask |= 1 << i;
1267 }
1268 }
1269
1270 return key;
1271}
1272
1273void Aura::SetLoadedState(int32 maxDuration, int32 duration, int32 charges, uint32 recalculateMask, SpellEffectValue const* amount)
1274{
1275 m_maxDuration = maxDuration;
1276 m_duration = duration;
1277 m_procCharges = charges;
1279 Unit* caster = GetCaster();
1280 for (AuraEffect* effect : GetAuraEffects())
1281 {
1282 effect->SetAmount(amount[effect->GetEffIndex()]);
1283 effect->SetCanBeRecalculated((recalculateMask & (1 << effect->GetEffIndex())) != 0);
1284 effect->CalculatePeriodic(caster, false, true);
1285 effect->CalculateSpellMod();
1286 effect->RecalculateAmount(caster);
1287 }
1288}
1289
1291{
1292 for (AuraEffect const* effect : GetAuraEffects())
1293 if (effect->GetAuraType() == type)
1294 return true;
1295
1296 return false;
1297}
1298
1300{
1301 switch (type)
1302 {
1309 return true;
1310 default:
1311 break;
1312 }
1313
1314 return false;
1315}
1316
1318{
1319 ASSERT (!IsRemoved());
1320 Unit* caster = GetCaster();
1321 for (AuraEffect* effect : GetAuraEffects())
1322 if (!IsRemoved())
1323 effect->RecalculateAmount(caster);
1324}
1325
1326void Aura::HandleAllEffects(AuraApplication * aurApp, uint8 mode, bool apply)
1327{
1328 ASSERT (!IsRemoved());
1329 for (AuraEffect* effect : GetAuraEffects())
1330 if (!IsRemoved())
1331 effect->HandleEffect(aurApp, mode, apply);
1332}
1333
1335{
1336 uint32 effMask = 0;
1337 for (AuraEffect const* aurEff : GetAuraEffects())
1338 effMask |= 1 << aurEff->GetEffIndex();
1339 return effMask;
1340}
1341
1342void Aura::GetApplicationVector(std::vector<AuraApplication*>& applications) const
1343{
1344 for (auto const& applicationPair : m_applications)
1345 {
1346 if (!applicationPair.second->GetEffectMask())
1347 continue;
1348
1349 applications.push_back(applicationPair.second);
1350 }
1351}
1352
1357
1362
1364{
1365 return m_applications.contains(guid);
1366}
1367
1369{
1370 for (ApplicationMap::const_iterator appIter = m_applications.begin(); appIter != m_applications.end(); ++appIter)
1371 appIter->second->SetNeedClientUpdate();
1372}
1373
1374// trigger effects on real aura apply/remove
1375void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, bool apply, bool onReapply)
1376{
1377 Unit* target = aurApp->GetTarget();
1378 AuraRemoveMode removeMode = aurApp->GetRemoveMode();
1379 // handle spell_area table
1380 SpellAreaForAreaMapBounds saBounds = sSpellMgr->GetSpellAreaForAuraMapBounds(GetId());
1381 if (saBounds.first != saBounds.second)
1382 {
1383 uint32 zone, area;
1384 target->GetZoneAndAreaId(zone, area);
1385
1386 for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
1387 {
1388 // some auras remove at aura remove
1389 if (itr->second->flags & SPELL_AREA_FLAG_AUTOREMOVE && !itr->second->IsFitToRequirements(target->ToPlayer(), zone, area))
1390 target->RemoveAurasDueToSpell(itr->second->spellId);
1391 // some auras applied at aura apply
1392 else if (itr->second->flags & SPELL_AREA_FLAG_AUTOCAST)
1393 {
1394 if (!target->HasAura(itr->second->spellId))
1395 target->CastSpell(target, itr->second->spellId, CastSpellExtraArgs(TRIGGERED_FULL_MASK)
1397 }
1398 }
1399 }
1400
1401 // handle spell_linked_spell table
1402 if (!onReapply)
1403 {
1404 // apply linked auras
1405 if (apply)
1406 {
1407 if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(SPELL_LINK_AURA, GetId()))
1408 {
1409 for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
1410 {
1411 if (*itr < 0)
1412 target->ApplySpellImmune(GetId(), IMMUNITY_ID, -(*itr), true);
1413 else if (caster)
1414 caster->AddAura(*itr, target);
1415 }
1416 }
1417 }
1418 else
1419 {
1420 // remove linked auras
1421 if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(SPELL_LINK_REMOVE, GetId()))
1422 {
1423 for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
1424 {
1425 if (*itr < 0)
1426 target->RemoveAurasDueToSpell(-(*itr));
1427 else if (removeMode != AURA_REMOVE_BY_DEATH)
1428 target->CastSpell(target, *itr, CastSpellExtraArgs(TRIGGERED_FULL_MASK)
1431 }
1432 }
1433 if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(SPELL_LINK_AURA, GetId()))
1434 {
1435 for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
1436 {
1437 if (*itr < 0)
1438 target->ApplySpellImmune(GetId(), IMMUNITY_ID, -(*itr), false);
1439 else
1440 target->RemoveAura(*itr, GetCasterGUID(), 0, removeMode);
1441 }
1442 }
1443 }
1444 }
1445 else if (apply)
1446 {
1447 // modify stack amount of linked auras
1448 if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(SPELL_LINK_AURA, GetId()))
1449 {
1450 for (std::vector<int32>::const_iterator itr = spellTriggered->begin(); itr != spellTriggered->end(); ++itr)
1451 if (*itr > 0)
1452 if (Aura* triggeredAura = target->GetAura(*itr, GetCasterGUID()))
1453 triggeredAura->ModStackAmount(GetStackAmount() - triggeredAura->GetStackAmount());
1454 }
1455 }
1456
1457 // mods at aura apply
1458 if (apply)
1459 {
1460 switch (GetSpellInfo()->SpellFamilyName)
1461 {
1463 switch (GetId())
1464 {
1465 case 50836: //Petrifying Grip, becomes stoned
1466 if (GetStackAmount() >= 5 && !target->HasAura(50812))
1467 target->CastSpell(target, 50812, CastSpellExtraArgs(TRIGGERED_FULL_MASK)
1469 break;
1470 case 60970: // Heroic Fury (remove Intercept cooldown)
1471 if (target->GetTypeId() == TYPEID_PLAYER)
1472 target->GetSpellHistory()->ResetCooldown(20252, true);
1473 break;
1474 }
1475 break;
1476 case SPELLFAMILY_DRUID:
1477 if (!caster)
1478 break;
1479 // Rejuvenation
1480 if (GetSpellInfo()->SpellFamilyFlags[0] & 0x10 && GetEffect(EFFECT_0))
1481 {
1482 // Druid T8 Restoration 4P Bonus
1483 if (caster->HasAura(64760))
1484 {
1487 caster->CastSpell(target, 64801, args);
1488 }
1489 }
1490 break;
1491 }
1492 }
1493 // mods at aura remove
1494 else
1495 {
1496 switch (GetSpellInfo()->SpellFamilyName)
1497 {
1498 case SPELLFAMILY_MAGE:
1499 switch (GetId())
1500 {
1501 case 66: // Invisibility
1502 if (removeMode != AURA_REMOVE_BY_EXPIRE)
1503 break;
1504 target->CastSpell(target, 32612, GetEffect(1));
1505 break;
1506 default:
1507 break;
1508 }
1509 break;
1510 case SPELLFAMILY_PRIEST:
1511 if (!caster)
1512 break;
1513 // Power word: shield
1514 if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && GetSpellInfo()->SpellFamilyFlags[0] & 0x00000001)
1515 {
1516 // Rapture
1517 if (Aura const* aura = caster->GetAuraOfRankedSpell(47535))
1518 {
1519 // check cooldown
1520 if (caster->GetTypeId() == TYPEID_PLAYER)
1521 {
1522 if (caster->GetSpellHistory()->HasCooldown(aura->GetSpellInfo()))
1523 {
1524 // This additional check is needed to add a minimal delay before cooldown in in effect
1525 // to allow all bubbles broken by a single damage source proc mana return
1526 if (caster->GetSpellHistory()->GetRemainingCooldown(aura->GetSpellInfo()) <= 11s)
1527 break;
1528 }
1529 else // and add if needed
1530 caster->GetSpellHistory()->AddCooldown(aura->GetId(), 0, 12s);
1531 }
1532
1533 // effect on caster
1534 if (AuraEffect const* aurEff = aura->GetEffect(0))
1535 {
1536 SpellEffectValue multiplier = aurEff->GetAmount();
1540 caster->CastSpell(caster, 47755, args);
1541 }
1542 }
1543 }
1544 break;
1545 case SPELLFAMILY_ROGUE:
1546 // Remove Vanish on stealth remove
1547 if (GetId() == 1784)
1548 target->RemoveAurasWithFamily(SPELLFAMILY_ROGUE, flag128(0x0000800, 0, 0, 0), target->GetGUID());
1549 break;
1550 }
1551 }
1552
1553 // mods at aura apply or remove
1554 switch (GetSpellInfo()->SpellFamilyName)
1555 {
1556 case SPELLFAMILY_HUNTER:
1557 switch (GetId())
1558 {
1559 case 19574: // Bestial Wrath
1560 // The Beast Within cast on owner if talent present
1561 if (Unit* owner = target->GetOwner())
1562 {
1563 // Search talent
1564 if (owner->HasAura(34692))
1565 {
1566 if (apply)
1567 owner->CastSpell(owner, 34471, GetEffect(0));
1568 else
1569 owner->RemoveAurasDueToSpell(34471);
1570 }
1571 }
1572 break;
1573 }
1574 break;
1576 switch (GetId())
1577 {
1578 case 31842: // Divine Favor
1579 // Item - Paladin T10 Holy 2P Bonus
1580 if (target->HasAura(70755))
1581 {
1582 if (apply)
1583 target->CastSpell(target, 71166, CastSpellExtraArgs(TRIGGERED_FULL_MASK)
1584 .SetOriginalCastId(GetCastId()));
1585 else
1586 target->RemoveAurasDueToSpell(71166);
1587 }
1588 break;
1589 }
1590 break;
1591 }
1592
1593 if (apply)
1594 {
1595 if (Creature* creature = target->ToCreature())
1596 if (CreatureAI* ai = creature->AI())
1597 ai->OnAuraApplied(aurApp);
1598 }
1599 else
1600 {
1601 if (Creature* creature = target->ToCreature())
1602 if (CreatureAI* ai = creature->AI())
1603 ai->OnAuraRemoved(aurApp);
1604 }
1605}
1606
1608{
1609 for (uint32 label : GetSpellInfo()->Labels)
1611 return false;
1612
1613 // unit not in world or during remove from world
1614 if (!target->IsInWorld() || target->IsDuringRemoveFromWorld())
1615 {
1616 // area auras mustn't be applied
1617 if (GetOwner() != target)
1618 return false;
1619 // do not apply non-selfcast single target auras
1621 return false;
1622 return true;
1623 }
1624 else
1625 return CheckAreaTarget(target);
1626}
1627
1629{
1630 return CallScriptCheckAreaTargetHandlers(target);
1631}
1632
1633bool Aura::CanStackWith(Aura const* existingAura) const
1634{
1635 // Can stack with self
1636 if (this == existingAura)
1637 return true;
1638
1639 bool sameCaster = GetCasterGUID() == existingAura->GetCasterGUID();
1640 SpellInfo const* existingSpellInfo = existingAura->GetSpellInfo();
1641
1642 // Dynobj auras do not stack when they come from the same spell cast by the same caster
1643 if (GetType() == DYNOBJ_AURA_TYPE || existingAura->GetType() == DYNOBJ_AURA_TYPE)
1644 {
1645 if (sameCaster && m_spellInfo->Id == existingSpellInfo->Id)
1646 return false;
1647 return true;
1648 }
1649
1650 // passive auras don't stack with another rank of the spell cast by same caster
1651 if (IsPassive() && sameCaster && (m_spellInfo->IsDifferentRankOf(existingSpellInfo) || (m_spellInfo->Id == existingSpellInfo->Id && m_castItemGuid.IsEmpty())))
1652 return false;
1653
1654 for (SpellEffectInfo const& spellEffectInfo : existingSpellInfo->GetEffects())
1655 {
1656 // prevent remove triggering aura by triggered aura
1657 if (spellEffectInfo.TriggerSpell == GetId())
1658 return true;
1659 }
1660
1661 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
1662 {
1663 // prevent remove triggered aura by triggering aura refresh
1664 if (spellEffectInfo.TriggerSpell == existingAura->GetId())
1665 return true;
1666 }
1667
1668 // check spell specific stack rules
1669 if (m_spellInfo->IsAuraExclusiveBySpecificWith(existingSpellInfo)
1670 || (sameCaster && m_spellInfo->IsAuraExclusiveBySpecificPerCasterWith(existingSpellInfo)))
1671 return false;
1672
1673 // check spell group stack rules
1674 switch (sSpellMgr->CheckSpellGroupStackRules(m_spellInfo, existingSpellInfo))
1675 {
1677 case SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST: // if it reaches this point, existing aura is lower/equal
1678 return false;
1680 if (sameCaster)
1681 return false;
1682 break;
1685 default:
1686 break;
1687 }
1688
1689 if (m_spellInfo->SpellFamilyName != existingSpellInfo->SpellFamilyName)
1690 return true;
1691
1692 if (!sameCaster)
1693 {
1694 // Channeled auras can stack if not forbidden by db or aura type
1695 if (existingAura->GetSpellInfo()->IsChanneled())
1696 return true;
1697
1699 return true;
1700
1701 // check same periodic auras
1702 auto hasPeriodicNonAreaEffect = [](SpellInfo const* spellInfo)
1703 {
1704 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
1705 {
1706 switch (spellEffectInfo.ApplyAuraName)
1707 {
1708 // DOT or HOT from different casters will stack
1722 // periodic auras which target areas are not allowed to stack this way (replenishment for example)
1723 if (spellEffectInfo.IsTargetingArea())
1724 return false;
1725 return true;
1726 default:
1727 break;
1728 }
1729 }
1730 return false;
1731 };
1732
1733 if (hasPeriodicNonAreaEffect(m_spellInfo) && hasPeriodicNonAreaEffect(existingSpellInfo))
1734 return true;
1735 }
1736
1738 {
1739 Vehicle* veh = nullptr;
1740 if (GetOwner()->ToUnit())
1741 veh = GetOwner()->ToUnit()->GetVehicleKit();
1742
1743 if (!veh) // We should probably just let it stack. Vehicle system will prevent undefined behaviour later
1744 return true;
1745
1746 if (!veh->GetAvailableSeatCount())
1747 return false; // No empty seat available
1748
1749 return true; // Empty seat available (skip rest)
1750 }
1751
1754 return false;
1755
1756 // spell of same spell rank chain
1757 if (m_spellInfo->IsRankOf(existingSpellInfo))
1758 {
1759 // don't allow passive area auras to stack
1760 if (m_spellInfo->IsMultiSlotAura() && !IsArea())
1761 return true;
1762 if (!GetCastItemGUID().IsEmpty() && !existingAura->GetCastItemGUID().IsEmpty())
1764 return true;
1765 // same spell with same caster should not stack
1766 return false;
1767 }
1768
1769 return true;
1770}
1771
1773{
1774 return m_procCooldown > now;
1775}
1776
1778{
1779 // cooldowns should be added to the whole aura (see 51698 area aura)
1780 int32 procCooldown = procEntry->Cooldown.count();
1781 if (Unit* caster = GetCaster())
1782 if (Player* modOwner = caster->GetSpellModOwner())
1783 modOwner->ApplySpellMod(GetSpellInfo(), SpellModOp::ProcCooldown, procCooldown);
1784
1785 m_procCooldown = now + Milliseconds(procCooldown);
1786}
1787
1792
1794{
1795 bool prepare = CallScriptPrepareProcHandlers(aurApp, eventInfo);
1796 if (!prepare)
1797 return;
1798
1799 SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetSpellInfo());
1800 ASSERT(procEntry);
1801
1802 PrepareProcChargeDrop(procEntry, eventInfo);
1803
1804 // cooldowns should be added to the whole aura (see 51698 area aura)
1805 AddProcCooldown(procEntry, now);
1806
1808}
1809
1810void Aura::PrepareProcChargeDrop(SpellProcEntry const* procEntry, ProcEventInfo const& eventInfo)
1811{
1812 // take one charge, aura expiration will be handled in Aura::TriggerProcOnEvent (if needed)
1814 {
1815 --m_procCharges;
1817 }
1818}
1819
1821{
1822 // Remove aura if we've used last charge to proc
1824 {
1825 ModStackAmount(-1);
1826 }
1827 else if (IsUsingCharges())
1828 {
1829 if (!GetCharges())
1830 Remove();
1831 }
1832}
1833
1835{
1836 SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetSpellInfo());
1837 // only auras with spell proc entry can trigger proc
1838 if (!procEntry)
1839 return 0;
1840
1841 // check spell triggering us
1842 if (Spell const* spell = eventInfo.GetProcSpell())
1843 {
1844 // Do not allow auras to proc from effect triggered from itself
1845 if (spell->IsTriggeredByAura(m_spellInfo))
1846 return 0;
1847
1848 // check if aura can proc when spell is triggered (exception for hunter auto shot & wands)
1850 if (spell->IsTriggered() && !spell->GetSpellInfo()->HasAttribute(SPELL_ATTR3_NOT_A_PROC))
1851 return 0;
1852
1853 if (spell->m_CastItem && (procEntry->AttributesMask & PROC_ATTR_CANT_PROC_FROM_ITEM_CAST))
1854 return 0;
1855
1856 if (spell->GetSpellInfo()->HasAttribute(SPELL_ATTR4_SUPPRESS_WEAPON_PROCS) && GetSpellInfo()->HasAttribute(SPELL_ATTR6_AURA_IS_WEAPON_PROC))
1857 return 0;
1858
1860 return 0;
1861
1862 if (eventInfo.GetTypeMask() & TAKEN_HIT_PROC_FLAG_MASK)
1863 {
1864 if (spell->GetSpellInfo()->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS)
1866 return 0;
1867 }
1868 else
1869 {
1870 if (spell->GetSpellInfo()->HasAttribute(SPELL_ATTR3_SUPPRESS_CASTER_PROCS)
1871 && !spell->GetSpellInfo()->HasAttribute(SPELL_ATTR12_ENABLE_PROCS_FROM_SUPPRESSED_CASTER_PROCS)
1873 return 0;
1874 }
1875 }
1876
1877 // check don't break stealth attr present
1879 {
1880 if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo())
1881 if (spellInfo->HasAttribute(SPELL_ATTR0_CU_DONT_BREAK_STEALTH))
1882 return 0;
1883 }
1884
1885 // check if we have charges to proc with
1886 if (IsUsingCharges() && !GetCharges())
1887 return 0;
1888
1890 if (Spell const* spell = eventInfo.GetProcSpell())
1891 if (!spell->m_appliedMods.contains(const_cast<Aura*>(this)))
1892 return 0;
1893
1894 // check proc cooldown
1895 if (IsProcOnCooldown(now))
1896 return 0;
1897
1898 // do checks against db data
1899 if (!SpellMgr::CanSpellTriggerProcOnEvent(*procEntry, eventInfo))
1900 return 0;
1901
1902 // do checks using conditions table
1903 if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_SPELL_PROC, GetId(), eventInfo.GetActor(), eventInfo.GetActionTarget()))
1904 return 0;
1905
1906 // AuraScript Hook
1907 bool check = const_cast<Aura*>(this)->CallScriptCheckProcHandlers(aurApp, eventInfo);
1908 if (!check)
1909 return 0;
1910
1911 // At least one effect has to pass checks to proc aura
1912 uint32 procEffectMask = aurApp->GetEffectMask();
1913 for (AuraEffect const* aurEff : GetAuraEffects())
1914 if (procEffectMask & (1u << aurEff->GetEffIndex()))
1915 if ((procEntry->DisableEffectsMask & (1u << aurEff->GetEffIndex())) || !aurEff->CheckEffectProc(aurApp, eventInfo))
1916 procEffectMask &= ~(1u << aurEff->GetEffIndex());
1917
1918 if (!procEffectMask)
1919 return 0;
1920
1922 // do allow additional requirements for procs
1923 // this is needed because this is the last moment in which you can prevent aura charge drop on proc
1924 // and possibly a way to prevent default checks (if there're going to be any)
1925
1926 // Check if current equipment meets aura requirements
1927 // do that only for passive spells
1929 Unit* target = aurApp->GetTarget();
1930 if (IsPassive() && target->GetTypeId() == TYPEID_PLAYER && GetSpellInfo()->EquippedItemClass != -1)
1931 {
1933 {
1934 Item* item = nullptr;
1936 {
1937 if (target->ToPlayer()->IsInFeralForm())
1938 return 0;
1939
1940 if (DamageInfo const* damageInfo = eventInfo.GetDamageInfo())
1941 {
1942 if (damageInfo->GetAttackType() != OFF_ATTACK)
1944 else
1946 }
1947 }
1949 {
1950 // Check if player is wearing shield
1952 }
1953
1954 if (!item || item->IsBroken() || !item->IsFitToSpellRequirements(GetSpellInfo()))
1955 return 0;
1956 }
1957 }
1958
1960 if (!target->IsOutdoors())
1961 return 0;
1962
1964 if (target->GetGUID() != GetCasterGUID())
1965 return 0;
1966
1968 if (!target->IsStandState())
1969 return 0;
1970
1971 bool success = roll_chance(CalcProcChance(*procEntry, eventInfo));
1972
1973 const_cast<Aura*>(this)->SetLastProcAttemptTime(now);
1974
1975 if (success)
1976 return procEffectMask;
1977
1978 return 0;
1979}
1980
1981float Aura::CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const
1982{
1983 float chance = procEntry.Chance;
1984 // calculate chances depending on unit with caster's data
1985 // so talents modifying chances and judgements will have properly calculated proc chance
1986 if (Unit* caster = GetCaster())
1987 {
1988 // calculate ppm chance if present and we're using weapon
1989 if (eventInfo.GetDamageInfo() && procEntry.ProcsPerMinute != 0)
1990 {
1991 uint32 WeaponSpeed = caster->GetBaseAttackTime(eventInfo.GetDamageInfo()->GetAttackType());
1992 chance = caster->GetPPMProcChance(WeaponSpeed, procEntry.ProcsPerMinute, GetSpellInfo());
1993 }
1994
1995 if (GetSpellInfo()->ProcBasePPM > 0.0f)
1996 chance = CalcPPMProcChance(caster);
1997
1998 // apply chance modifer aura, applies also to ppm chance (see improved judgement of light spell)
1999 if (Player* modOwner = caster->GetSpellModOwner())
2000 modOwner->ApplySpellMod(GetSpellInfo(), SpellModOp::ProcChance, chance);
2001 }
2002
2003 // proc chance is reduced by an additional 3.333% per level past 60
2004 if ((procEntry.AttributesMask & PROC_ATTR_REDUCE_PROC_60) && eventInfo.GetActor()->GetLevel() > 60)
2005 chance = std::max(0.f, (1.f - ((eventInfo.GetActor()->GetLevel() - 60) * 1.f / 30.f)) * chance);
2006
2007 return chance;
2008}
2009
2010void Aura::TriggerProcOnEvent(uint32 procEffectMask, AuraApplication* aurApp, ProcEventInfo& eventInfo)
2011{
2012 if (procEffectMask)
2013 {
2014 bool prevented = CallScriptProcHandlers(aurApp, eventInfo);
2015 if (!prevented)
2016 {
2017 for (std::size_t i = 0; i < GetAuraEffectCount(); ++i)
2018 {
2019 if (!(procEffectMask & (1 << i)))
2020 continue;
2021
2022 // OnEffectProc / AfterEffectProc hooks handled in AuraEffect::HandleProc()
2023 if (aurApp->HasEffect(i))
2024 GetEffect(i)->HandleProc(aurApp, eventInfo);
2025 }
2026
2027 CallScriptAfterProcHandlers(aurApp, eventInfo);
2028 }
2029 }
2030
2032}
2033
2035{
2036 // Formula see http://us.battle.net/wow/en/forum/topic/8197741003#1
2037 float ppm = m_spellInfo->CalcProcPPM(actor, GetCastItemLevel());
2038 float averageProcInterval = 60.0f / ppm;
2039
2040 TimePoint currentTime = GameTime::Now();
2041 float secondsSinceLastAttempt = std::min(duration_cast<FloatSeconds>(currentTime - m_lastProcAttemptTime).count(), 10.0);
2042 float secondsSinceLastProc = std::min(duration_cast<FloatSeconds>(currentTime - m_lastProcSuccessTime).count(), 1000.0);
2043
2044 float chance = std::max(1.0f, 1.0f + ((secondsSinceLastProc / averageProcInterval - 1.5f) * 3.0f)) * ppm * secondsSinceLastAttempt / 60.0f;
2045 RoundToInterval(chance, 0.0f, 1.0f);
2046 return chance * 100.0f;
2047}
2048
2050{
2052 delete aurApp;
2053
2054 _removedApplications.clear();
2055}
2056
2058{
2059 sScriptMgr->CreateAuraScripts(m_spellInfo->Id, m_loadedScripts, this);
2060 for (AuraScript* script : m_loadedScripts)
2061 {
2062 TC_LOG_DEBUG("spells", "Aura::LoadScripts: Script `{}` for aura `{}` is loaded now", script->GetScriptName(), m_spellInfo->Id);
2063 script->Register();
2064 }
2065}
2066
2068{
2069 bool result = true;
2070 for (AuraScript* script : m_loadedScripts)
2071 {
2072 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_AREA_TARGET);
2073 for (AuraScript::CheckAreaTargetHandler const& checkAreaTarget : script->DoCheckAreaTarget)
2074 result &= checkAreaTarget.Call(script, target);
2075
2076 script->_FinishScriptCall();
2077 }
2078 return result;
2079}
2080
2082{
2083 for (AuraScript* script : m_loadedScripts)
2084 {
2085 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_DISPEL);
2086 for (AuraScript::AuraDispelHandler const& onDispel : script->OnDispel)
2087 onDispel.Call(script, dispelInfo);
2088
2089 script->_FinishScriptCall();
2090 }
2091}
2092
2094{
2095 for (AuraScript* script : m_loadedScripts)
2096 {
2097 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_DISPEL);
2098 for (AuraScript::AuraDispelHandler const& afterDispel : script->AfterDispel)
2099 afterDispel.Call(script, dispelInfo);
2100
2101 script->_FinishScriptCall();
2102 }
2103}
2104
2106{
2107 for (AuraScript* script : m_loadedScripts)
2108 {
2109 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_ON_HEARTBEAT);
2110 for (AuraScript::AuraHeartbeatHandler const& onHeartbeat : script->OnHeartbeat)
2111 onHeartbeat.Call(script);
2112
2113 script->_FinishScriptCall();
2114 }
2115}
2116
2118{
2119 bool preventDefault = false;
2120 for (AuraScript* script : m_loadedScripts)
2121 {
2122 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_APPLY, aurApp);
2123 for (AuraScript::EffectApplyHandler const& onEffectApply : script->OnEffectApply)
2124 if (onEffectApply.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2125 onEffectApply.Call(script, aurEff, mode);
2126
2127 if (!preventDefault)
2128 preventDefault = script->_IsDefaultActionPrevented();
2129
2130 script->_FinishScriptCall();
2131 }
2132
2133 return preventDefault;
2134}
2135
2137{
2138 bool preventDefault = false;
2139 for (AuraScript* script : m_loadedScripts)
2140 {
2141 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_REMOVE, aurApp);
2142 for (AuraScript::EffectApplyHandler const& onEffectRemove : script->OnEffectRemove)
2143 if (onEffectRemove.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2144 onEffectRemove.Call(script, aurEff, mode);
2145
2146 if (!preventDefault)
2147 preventDefault = script->_IsDefaultActionPrevented();
2148
2149 script->_FinishScriptCall();
2150 }
2151 return preventDefault;
2152}
2153
2155{
2156 for (AuraScript* script : m_loadedScripts)
2157 {
2158 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_APPLY, aurApp);
2159 for (AuraScript::EffectApplyHandler const& afterEffectApply : script->AfterEffectApply)
2160 if (afterEffectApply.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2161 afterEffectApply.Call(script, aurEff, mode);
2162
2163 script->_FinishScriptCall();
2164 }
2165}
2166
2168{
2169 for (AuraScript* script : m_loadedScripts)
2170 {
2171 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_REMOVE, aurApp);
2172 for (AuraScript::EffectApplyHandler const& afterEffectRemove : script->AfterEffectRemove)
2173 if (afterEffectRemove.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2174 afterEffectRemove.Call(script, aurEff, mode);
2175
2176 script->_FinishScriptCall();
2177 }
2178}
2179
2181{
2182 bool preventDefault = false;
2183 for (AuraScript* script : m_loadedScripts)
2184 {
2185 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PERIODIC, aurApp);
2186 for (AuraScript::EffectPeriodicHandler const& onEffectPeriodic : script->OnEffectPeriodic)
2187 if (onEffectPeriodic.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2188 onEffectPeriodic.Call(script, aurEff);
2189
2190 if (!preventDefault)
2191 preventDefault = script->_IsDefaultActionPrevented();
2192
2193 script->_FinishScriptCall();
2194 }
2195
2196 return preventDefault;
2197}
2198
2200{
2201 for (AuraScript* script : m_loadedScripts)
2202 {
2203 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_UPDATE_PERIODIC);
2204 for (AuraScript::EffectUpdatePeriodicHandler const& onEffectUpdatePeriodic : script->OnEffectUpdatePeriodic)
2205 if (onEffectUpdatePeriodic.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2206 onEffectUpdatePeriodic.Call(script, aurEff);
2207
2208 script->_FinishScriptCall();
2209 }
2210}
2211
2212void Aura::CallScriptEffectCalcAmountHandlers(AuraEffect const* aurEff, SpellEffectValue& amount, bool& canBeRecalculated)
2213{
2214 for (AuraScript* script : m_loadedScripts)
2215 {
2216 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT);
2217 for (AuraScript::EffectCalcAmountHandler const& effectCalcAmount : script->DoEffectCalcAmount)
2218 if (effectCalcAmount.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2219 effectCalcAmount.Call(script, aurEff, amount, canBeRecalculated);
2220
2221 script->_FinishScriptCall();
2222 }
2223}
2224
2225void Aura::CallScriptEffectCalcPeriodicHandlers(AuraEffect const* aurEff, bool& isPeriodic, int32& amplitude)
2226{
2227 for (AuraScript* script : m_loadedScripts)
2228 {
2229 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC);
2230 for (AuraScript::EffectCalcPeriodicHandler const& effectCalcPeriodic : script->DoEffectCalcPeriodic)
2231 if (effectCalcPeriodic.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2232 effectCalcPeriodic.Call(script, aurEff, isPeriodic, amplitude);
2233
2234 script->_FinishScriptCall();
2235 }
2236}
2237
2239{
2240 for (AuraScript* script : m_loadedScripts)
2241 {
2242 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD);
2243 for (AuraScript::EffectCalcSpellModHandler const& effectCalcSpellMod : script->DoEffectCalcSpellMod)
2244 if (effectCalcSpellMod.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2245 effectCalcSpellMod.Call(script, aurEff, spellMod);
2246
2247 script->_FinishScriptCall();
2248 }
2249}
2250
2251void Aura::CallScriptEffectCalcCritChanceHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, Unit const* victim, float& critChance)
2252{
2253 for (AuraScript* script : m_loadedScripts)
2254 {
2255 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_CRIT_CHANCE, aurApp);
2256 for (AuraScript::EffectCalcCritChanceHandler const& effectCalcCritChance : script->DoEffectCalcCritChance)
2257 if (effectCalcCritChance.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2258 effectCalcCritChance.Call(script, aurEff, victim, critChance);
2259
2260 script->_FinishScriptCall();
2261 }
2262}
2263
2264void Aura::CallScriptCalcDamageAndHealingHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, Unit* victim, int32& damageOrHealing, int32& flatMod, float& pctMod)
2265{
2266 for (AuraScript* script : m_loadedScripts)
2267 {
2268 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_DAMAGE_AND_HEALING, aurApp);
2269 for (AuraScript::EffectCalcDamageAndHealingHandler const& effectCalcDamageAndHealing : script->DoEffectCalcDamageAndHealing)
2270 if (effectCalcDamageAndHealing.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2271 effectCalcDamageAndHealing.Call(script, aurEff, victim, damageOrHealing, flatMod, pctMod);
2272
2273 script->_FinishScriptCall();
2274 }
2275}
2276
2277void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& defaultPrevented)
2278{
2279 for (AuraScript* script : m_loadedScripts)
2280 {
2281 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp);
2282 for (AuraScript::EffectAbsorbHandler const& onEffectAbsorb : script->OnEffectAbsorb)
2283 if (onEffectAbsorb.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2284 onEffectAbsorb.Call(script, aurEff, dmgInfo, absorbAmount);
2285
2286 if (!defaultPrevented)
2287 defaultPrevented = script->_IsDefaultActionPrevented();
2288
2289 script->_FinishScriptCall();
2290 }
2291}
2292
2293void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount)
2294{
2295 for (AuraScript* script : m_loadedScripts)
2296 {
2297 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp);
2298 for (AuraScript::EffectAbsorbHandler const& afterEffectAbsorb : script->AfterEffectAbsorb)
2299 if (afterEffectAbsorb.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2300 afterEffectAbsorb.Call(script, aurEff, dmgInfo, absorbAmount);
2301
2302 script->_FinishScriptCall();
2303 }
2304}
2305
2306void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, HealInfo& healInfo, uint32& absorbAmount, bool& defaultPrevented)
2307{
2308 for (AuraScript* script : m_loadedScripts)
2309 {
2310 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp);
2311 for (AuraScript::EffectAbsorbHealHandler const& onEffectAbsorbHeal : script->OnEffectAbsorbHeal)
2312 if (onEffectAbsorbHeal.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2313 onEffectAbsorbHeal.Call(script, aurEff, healInfo, absorbAmount);
2314
2315 if (!defaultPrevented)
2316 defaultPrevented = script->_IsDefaultActionPrevented();
2317
2318 script->_FinishScriptCall();
2319 }
2320}
2321
2322void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, HealInfo& healInfo, uint32& absorbAmount)
2323{
2324 for (AuraScript* script : m_loadedScripts)
2325 {
2326 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp);
2327 for (AuraScript::EffectAbsorbHealHandler const& afterEffectAbsorbHeal : script->AfterEffectAbsorbHeal)
2328 if (afterEffectAbsorbHeal.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2329 afterEffectAbsorbHeal.Call(script, aurEff, healInfo, absorbAmount);
2330
2331 script->_FinishScriptCall();
2332 }
2333}
2334
2335void Aura::CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& defaultPrevented)
2336{
2337 for (AuraScript* script : m_loadedScripts)
2338 {
2339 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_MANASHIELD, aurApp);
2340 for (AuraScript::EffectAbsorbHandler const& onEffectManaShield : script->OnEffectManaShield)
2341 if (onEffectManaShield.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2342 onEffectManaShield.Call(script, aurEff, dmgInfo, absorbAmount);
2343
2344 if (!defaultPrevented)
2345 defaultPrevented = script->_IsDefaultActionPrevented();
2346
2347 script->_FinishScriptCall();
2348 }
2349}
2350
2352{
2353 for (AuraScript* script : m_loadedScripts)
2354 {
2355 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD, aurApp);
2356 for (AuraScript::EffectAbsorbHandler const& afterEffectManaShield : script->AfterEffectManaShield)
2357 if (afterEffectManaShield.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2358 afterEffectManaShield.Call(script, aurEff, dmgInfo, absorbAmount);
2359
2360 script->_FinishScriptCall();
2361 }
2362}
2363
2364void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& splitAmount)
2365{
2366 for (AuraScript* script : m_loadedScripts)
2367 {
2368 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_SPLIT, aurApp);
2369 for (AuraScript::EffectAbsorbHandler const& effectSplit : script->OnEffectSplit)
2370 if (effectSplit.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2371 effectSplit.Call(script, aurEff, dmgInfo, splitAmount);
2372
2373 script->_FinishScriptCall();
2374 }
2375}
2376
2377void Aura::CallScriptEnterLeaveCombatHandlers(AuraApplication const* aurApp, bool isNowInCombat)
2378{
2379 for (AuraScript* script : m_loadedScripts)
2380 {
2381 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_ENTER_LEAVE_COMBAT, aurApp);
2382 for (AuraScript::EnterLeaveCombatHandler const& onEnterLeaveCombat : script->OnEnterLeaveCombat)
2383 onEnterLeaveCombat.Call(script, isNowInCombat);
2384
2385 script->_FinishScriptCall();
2386 }
2387}
2388
2390{
2391 bool result = true;
2392 for (AuraScript* script : m_loadedScripts)
2393 {
2394 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_PROC, aurApp);
2395 for (AuraScript::CheckProcHandler const& checkProc : script->DoCheckProc)
2396 result &= checkProc.Call(script, eventInfo);
2397
2398 script->_FinishScriptCall();
2399 }
2400
2401 return result;
2402}
2403
2405{
2406 bool prepare = true;
2407 for (AuraScript* script : m_loadedScripts)
2408 {
2409 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_PREPARE_PROC, aurApp);
2410 for (AuraScript::AuraProcHandler const& prepareProc : script->DoPrepareProc)
2411 prepareProc.Call(script, eventInfo);
2412
2413 if (prepare)
2414 prepare = !script->_IsDefaultActionPrevented();
2415
2416 script->_FinishScriptCall();
2417 }
2418
2419 return prepare;
2420}
2421
2423{
2424 bool handled = false;
2425 for (AuraScript* script : m_loadedScripts)
2426 {
2427 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_PROC, aurApp);
2428 for (AuraScript::AuraProcHandler const& onProc : script->OnProc)
2429 onProc.Call(script, eventInfo);
2430
2431 handled |= script->_IsDefaultActionPrevented();
2432 script->_FinishScriptCall();
2433 }
2434
2435 return handled;
2436}
2437
2439{
2440 for (AuraScript* script : m_loadedScripts)
2441 {
2442 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_PROC, aurApp);
2443 for (AuraScript::AuraProcHandler const& afterProc : script->AfterProc)
2444 afterProc.Call(script, eventInfo);
2445
2446 script->_FinishScriptCall();
2447 }
2448}
2449
2451{
2452 bool result = true;
2453 for (AuraScript* script : m_loadedScripts)
2454 {
2455 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_EFFECT_PROC, aurApp);
2456 for (AuraScript::CheckEffectProcHandler const& checkEffectProc : script->DoCheckEffectProc)
2457 if (checkEffectProc.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2458 result &= checkEffectProc.Call(script, aurEff, eventInfo);
2459
2460 script->_FinishScriptCall();
2461 }
2462
2463 return result;
2464}
2465
2467{
2468 bool preventDefault = false;
2469 for (AuraScript* script : m_loadedScripts)
2470 {
2471 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PROC, aurApp);
2472 for (AuraScript::EffectProcHandler const& onEffectProc : script->OnEffectProc)
2473 if (onEffectProc.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2474 onEffectProc.Call(script, aurEff, eventInfo);
2475
2476 if (!preventDefault)
2477 preventDefault = script->_IsDefaultActionPrevented();
2478
2479 script->_FinishScriptCall();
2480 }
2481 return preventDefault;
2482}
2483
2485{
2486 for (AuraScript* script : m_loadedScripts)
2487 {
2488 script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC, aurApp);
2489 for (AuraScript::EffectProcHandler const& afterEffectProc : script->AfterEffectProc)
2490 if (afterEffectProc.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
2491 afterEffectProc.Call(script, aurEff, eventInfo);
2492
2493 script->_FinishScriptCall();
2494 }
2495}
2496
2497std::string Aura::GetDebugInfo() const
2498{
2499 std::stringstream sstr;
2500 sstr << std::boolalpha
2501 << "Id: " << GetId() << " Name: '" << (*GetSpellInfo()->SpellName)[sWorld->GetDefaultDbcLocale()] << "' Caster: " << GetCasterGUID().ToString()
2502 << "\nOwner: " << (GetOwner() ? GetOwner()->GetDebugInfo() : "NULL");
2503 return sstr.str();
2504}
2505
2507 : Aura(createInfo)
2508{
2510 LoadScripts();
2511 _InitEffects(createInfo._auraEffectMask, createInfo.Caster, createInfo.BaseAmount);
2512 GetUnitOwner()->_AddAura(this, createInfo.Caster);
2513}
2514
2516{
2517 Aura::_ApplyForTarget(target, caster, aurApp);
2518
2519 // register aura diminishing on apply
2520 if (DiminishingGroup group = GetDiminishGroup())
2521 target->ApplyDiminishingAura(group, true);
2522}
2523
2525{
2526 Aura::_UnapplyForTarget(target, caster, aurApp);
2527
2528 // unregister aura diminishing (and store last time)
2529 if (DiminishingGroup group = GetDiminishGroup())
2530 target->ApplyDiminishingAura(group, false);
2531}
2532
2534{
2535 if (IsRemoved())
2536 return;
2537 GetUnitOwner()->RemoveOwnedAura(this, removeMode);
2538}
2539
2540void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* caster)
2541{
2542 Unit* unitOwner = GetUnitOwner();
2543 if (GetSpellInfo()->HasAttribute(SPELL_ATTR7_DISABLE_AURA_WHILE_DEAD) && !unitOwner->IsAlive())
2544 return;
2545
2546 Unit* ref = caster;
2547 if (!ref)
2548 ref = unitOwner;
2549
2550 // add non area aura targets
2551 // static applications go through spell system first, so we assume they meet conditions
2552 for (auto const& [targetGuid, effectMask] : _staticApplications)
2553 {
2554 Unit* target = ObjectAccessor::GetUnit(*unitOwner, targetGuid);
2555 if (!target && targetGuid == unitOwner->GetGUID())
2556 target = unitOwner;
2557
2558 if (target)
2559 targets.emplace(target, effectMask);
2560 }
2561
2562 // skip area update if owner is not in world!
2563 if (!unitOwner->IsInWorld())
2564 return;
2565
2566 if (unitOwner->HasAuraState(AURA_STATE_BANISHED, GetSpellInfo(), caster))
2567 return;
2568
2569 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
2570 {
2571 if (!HasEffect(spellEffectInfo.EffectIndex))
2572 continue;
2573
2574 // area auras only
2575 if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA))
2576 continue;
2577
2578 std::vector<Unit*> units;
2579 ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions.get();
2580
2581 SpellRange radius = spellEffectInfo.CalcRadius(ref);
2582 float extraSearchRadius = 0.0f;
2583
2585 switch (spellEffectInfo.Effect)
2586 {
2589 selectionType = TARGET_CHECK_PARTY;
2590 break;
2592 selectionType = TARGET_CHECK_RAID;
2593 break;
2595 selectionType = TARGET_CHECK_ALLY;
2596 break;
2598 selectionType = TARGET_CHECK_ENEMY;
2599 extraSearchRadius = radius.Max > 0.0f ? EXTRA_CELL_SEARCH_RADIUS : 0.0f;
2600 break;
2602 if (!condList || sConditionMgr->IsObjectMeetToConditions(unitOwner, ref, *condList))
2603 units.push_back(unitOwner);
2604 [[fallthrough]];
2606 {
2607 if (Unit* owner = unitOwner->GetCharmerOrOwner())
2608 if (owner->IsInWorld() && unitOwner->InSamePhase(owner) && unitOwner->IsInRange3d(owner, radius.Min, radius.Max))
2609 if (!condList || sConditionMgr->IsObjectMeetToConditions(owner, ref, *condList))
2610 units.push_back(owner);
2611 break;
2612 }
2614 {
2615 if (Unit* pet = ObjectAccessor::GetUnit(*unitOwner, unitOwner->GetPetGUID()))
2616 if (!condList || sConditionMgr->IsObjectMeetToConditions(pet, ref, *condList))
2617 units.push_back(pet);
2618 break;
2619 }
2621 {
2622 if (!condList || sConditionMgr->IsObjectMeetToConditions(unitOwner, ref, *condList))
2623 units.push_back(unitOwner);
2624
2625 selectionType = TARGET_CHECK_SUMMONED;
2626 break;
2627 }
2628 default:
2629 break;
2630 }
2631
2632 if (selectionType != TARGET_CHECK_DEFAULT)
2633 {
2634 if (uint32 containerTypeMask = Spell::GetSearcherTypeMask(m_spellInfo, spellEffectInfo, TARGET_OBJECT_TYPE_UNIT, condList))
2635 {
2636 Trinity::WorldObjectSpellAreaTargetCheck check(radius, unitOwner, ref, unitOwner, m_spellInfo, selectionType, condList, TARGET_OBJECT_TYPE_UNIT);
2638 Spell::SearchTargets(searcher, containerTypeMask, unitOwner, unitOwner, radius.Max + extraSearchRadius);
2639
2640 // by design WorldObjectSpellAreaTargetCheck allows not-in-world units (for spells) but for auras it is not acceptable
2641 Trinity::Containers::EraseIf(units, [unitOwner](Unit const* unit) { return !unit->IsSelfOrInSameMap(unitOwner); });
2642 }
2643 }
2644
2645 for (Unit* unit : units)
2646 targets[unit] |= 1 << spellEffectInfo.EffectIndex;
2647 }
2648}
2649
2651{
2652 // only valid for non-area auras
2653 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
2654 {
2655 if ((effMask & (1 << spellEffectInfo.EffectIndex)) && !spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA))
2656 effMask &= ~(1 << spellEffectInfo.EffectIndex);
2657 }
2658
2659 if (!effMask)
2660 return;
2661
2662 _staticApplications[target->GetGUID()] |= effMask;
2663}
2664
2666{
2668
2669 // Periodic food and drink emote animation
2671
2672 // Invoke the OnHeartbeat AuraScript hook
2674}
2675
2677{
2679
2680 bool food = specificType == SPELL_SPECIFIC_FOOD || specificType == SPELL_SPECIFIC_FOOD_AND_DRINK;
2681 bool drink = specificType == SPELL_SPECIFIC_DRINK || specificType == SPELL_SPECIFIC_FOOD_AND_DRINK;
2682
2683 if (food)
2685
2686 if (drink)
2688}
2689
2691 : Aura(createInfo)
2692{
2693 LoadScripts();
2694 DynamicObject* dynObjOwner = GetDynobjOwner();
2695 ASSERT(dynObjOwner);
2696 ASSERT(createInfo.Caster);
2697 ASSERT(dynObjOwner->IsInMap(createInfo.Caster));
2698 _InitEffects(createInfo._auraEffectMask, createInfo.Caster, createInfo.BaseAmount);
2699 dynObjOwner->SetAura(this);
2700}
2701
2703{
2704 if (IsRemoved())
2705 return;
2706 _Remove(removeMode);
2707}
2708
2709void DynObjAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* /*caster*/)
2710{
2711 DynamicObject* dynObjOwner = GetDynobjOwner();
2712 Unit* dynObjOwnerCaster = dynObjOwner->GetCaster();
2713 float radius = dynObjOwner->GetRadius();
2714
2715 for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
2716 {
2717 if (!HasEffect(spellEffectInfo.EffectIndex))
2718 continue;
2719
2720 // we can't use effect type like area auras to determine check type, check targets
2721 SpellTargetCheckTypes selectionType = spellEffectInfo.TargetA.GetCheckType();
2722 if (spellEffectInfo.TargetB.GetReferenceType() == TARGET_REFERENCE_TYPE_DEST)
2723 selectionType = spellEffectInfo.TargetB.GetCheckType();
2724
2725 std::vector<Unit*> units;
2726 ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions.get();
2727
2728 Trinity::WorldObjectSpellAreaTargetCheck check({ .Max = radius }, dynObjOwner, dynObjOwnerCaster, dynObjOwnerCaster, m_spellInfo, selectionType, condList, TARGET_OBJECT_TYPE_UNIT);
2729 Trinity::UnitListSearcher searcher(dynObjOwner, units, check);
2730 Cell::VisitAllObjects(dynObjOwner, searcher, radius);
2731
2732 // by design WorldObjectSpellAreaTargetCheck allows not-in-world units (for spells) but for auras it is not acceptable
2733 Trinity::Containers::EraseIf(units, [dynObjOwner](Unit const* unit) { return !unit->IsSelfOrInSameMap(dynObjOwner); });
2734
2735 for (Unit* unit : units)
2736 targets[unit] |= 1 << spellEffectInfo.EffectIndex;
2737 }
2738}
@ IN_MILLISECONDS
Definition Common.h:38
std::vector< Condition > ConditionContainer
#define sConditionMgr
@ CONDITION_SOURCE_TYPE_SPELL_PROC
#define MAX_EFFECT_MASK
Definition DBCEnums.h:2451
Difficulty
Definition DBCEnums.h:935
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:79
#define ASSERT_NODEBUGINFO
Definition Errors.h:73
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:74
#define ASSERT
Definition Errors.h:72
@ ITEM_CLASS_ARMOR
@ ITEM_CLASS_WEAPON
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:173
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:182
#define TC_LOG_FATAL(filterType__, message__,...)
Definition Log.h:185
#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:730
@ EQUIPMENT_SLOT_OFFHAND
Definition Player.h:731
constexpr uint8 INVENTORY_SLOT_BAG_0
Definition Player.h:706
bool roll_chance(float chance, PseudoRandomDistributionState &state)
Definition Random.cpp:131
#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_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
@ 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
@ 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_SELF_CAST
@ 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:125
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:430
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)
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:427
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:422
bool IsAppliedOnTarget(ObjectGuid guid) const
void CallScriptAfterEffectProcHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, ProcEventInfo &eventInfo)
ApplicationMap m_applications
Definition SpellAuras.h:414
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:424
Unit * GetCaster() const
uint32 CalcMaxStackAmount() const
ObjectGuid const m_castItemGuid
Definition SpellAuras.h:396
AuraEffectVector m_effects
Definition SpellAuras.h:413
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:423
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:418
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:416
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:417
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:420
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:465
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:185
bool IsBroken() const
Definition Item.h:273
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:22967
void ApplySpellMod(SpellInfo const *spellInfo, SpellModOp op, T &basevalue, Spell *spell=nullptr) const
Definition Player.cpp:22840
Item * GetUseableItemByPos(uint8 bag, uint8 slot) const
Definition Player.cpp:9555
Item * GetItemByGuid(ObjectGuid guid) const
Definition Player.cpp:9522
Unit * GetActionTarget() const
Definition Unit.h:514
Spell const * GetProcSpell() const
Definition Unit.h:527
SpellInfo const * GetSpellInfo() const
Definition Unit.cpp:281
ProcFlagsInit GetTypeMask() const
Definition Unit.h:516
DamageInfo * GetDamageInfo() const
Definition Unit.h:524
Unit * GetActor() const
Definition Unit.h:513
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:589
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:2125
static void SearchTargets(SEARCHER &searcher, uint32 containerMask, WorldObject *referer, Position const *pos, float radius)
Definition Spell.cpp:2163
void HandlePeriodicFoodSpellVisualKit()
void Remove(AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT) override
DiminishingGroup m_AuraDRGroup
Definition SpellAuras.h:456
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:448
void _ApplyForTarget(Unit *target, Unit *caster, AuraApplication *aurApp) override
UnitAura(AuraCreateInfo const &createInfo)
std::unordered_map< ObjectGuid, uint32 > _staticApplications
Definition SpellAuras.h:457
void _UnapplyForTarget(Unit *target, Unit *caster, AuraApplication *aurApp) override
Definition Unit.h:647
void ApplySpellImmune(uint32 spellId, SpellImmunity op, uint32 type, bool apply)
Definition Unit.cpp:8261
int32 ModifyPower(Powers power, int32 val, bool withPowerUpdate=true)
Definition Unit.cpp:8716
void RemoveOwnedAura(AuraMap::iterator &i, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3769
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3846
int64 ModifyHealth(int64 val)
Definition Unit.cpp:8618
uint32 GetCastSpellXSpellVisualId(SpellInfo const *spellInfo) const override
Definition Unit.cpp:14656
void _UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode)
Definition Unit.cpp:3620
bool HasAuraTypeWithMiscvalue(AuraType auraType, int32 miscValue) const
Definition Unit.cpp:4845
Spell * FindCurrentSpellBySpellId(uint32 spell_id) const
Definition Unit.cpp:3268
void RemoveVisibleAura(AuraApplication *aurApp)
Definition Unit.cpp:729
Aura * AddAura(uint32 spellId, Unit *target)
Definition Unit.cpp:12344
std::string GetDebugInfo() const override
Definition Unit.cpp:14738
bool HasVisibleAura(AuraApplication *aurApp) const
Definition Unit.h:1620
bool IsAlive() const
Definition Unit.h:1205
int32 GetMaxPower(Powers power) const
Definition Unit.cpp:10105
bool IsStandState() const
Definition Unit.cpp:10798
bool IsDuringRemoveFromWorld() const
Definition Unit.h:1836
Unit * GetCharmerOrOwner() const
Definition Unit.h:1241
uint64 GetMaxHealth() const
Definition Unit.h:801
Aura * GetAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4718
uint64 GetHealth() const
Definition Unit.h:800
void _AddAura(UnitAura *aura, Unit *caster)
Definition Unit.cpp:3468
bool HasAuraState(AuraStateType flag, SpellInfo const *spellProto=nullptr, Unit const *Caster=nullptr) const
Definition Unit.cpp:6165
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition Unit.h:1897
int32 GetPower(Powers power) const
Definition Unit.cpp:10096
bool IsInFeralForm() const
Definition Unit.cpp:9559
void SendPlaySpellVisualKit(uint32 id, uint32 type, uint32 duration) const
Definition Unit.cpp:12437
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4822
SpellHistory * GetSpellHistory()
Definition Unit.h:1521
void SetVisibleAura(AuraApplication *aurApp)
Definition Unit.cpp:722
void SetVisibleAuraUpdate(AuraApplication *aurApp)
Definition Unit.cpp:736
void ApplyDiminishingAura(DiminishingGroup group, bool apply)
Definition Unit.cpp:9455
AuraList & GetSingleCastAuras()
Definition Unit.h:1364
Vehicle * GetVehicleKit() const
Definition Unit.h:1798
Aura * GetAuraOfRankedSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4748
void RemoveAurasWithFamily(SpellFamilyNames family, flag128 const &familyFlag, ObjectGuid casterGUID)
Definition Unit.cpp:4294
VisibleAuraContainer const & GetVisibleAuras() const
Definition Unit.h:1619
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3992
uint8 GetLevel() const
Definition Unit.h:769
Aura * _TryStackingOrRefreshingExistingAura(AuraCreateInfo &createInfo)
Definition Unit.cpp:3405
ObjectGuid GetPetGUID() const
Definition Unit.h:1217
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:1099
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
std::string GetDebugInfo() const override
Definition Object.cpp:3139
Unit * GetOwner() const
Definition Object.cpp:1603
int32 CalcSpellDuration(SpellInfo const *spellInfo, std::vector< SpellPowerCost > const *powerCosts) const
Definition Object.cpp:1705
bool IsSelfOrInSameMap(WorldObject const *obj) const
Definition Object.cpp:460
bool IsOutdoors() const
Definition Object.h:336
Player * GetSpellModOwner() const
Definition Object.cpp:1646
EventProcessor m_Events
Definition Object.h:561
bool IsInRange3d(Position const *pos, float minRange, float maxRange) const
Definition Object.cpp:633
void GetZoneAndAreaId(uint32 &zoneid, uint32 &areaid) const
Definition Object.h:334
bool IsFriendlyTo(WorldObject const *target) const
Definition Object.cpp:2191
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:467
WorldPacket const * Write() override
std::vector< AuraInfo > Auras
#define sWorld
Definition World.h:919
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)
Definition CellImpl.h:160
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