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