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