TrinityCore
SpellInfo.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 "SpellInfo.h"
19#include "Battleground.h"
20#include "Containers.h"
21#include "Corpse.h"
22#include "DB2Stores.h"
23#include "FlatSet.h"
24#include "GameTables.h"
25#include "InstanceScript.h"
26#include "Item.h"
27#include "ItemTemplate.h"
28#include "Log.h"
29#include "LootMgr.h"
30#include "Map.h"
31#include "ObjectAccessor.h"
32#include "Pet.h"
33#include "Player.h"
34#include "Random.h"
35#include "Spell.h"
36#include "SpellAuraEffects.h"
37#include "SpellMgr.h"
38#include "Vehicle.h"
39#include <G3D/g3dmath.h>
40
42{
43 switch (objType)
44 {
56 return TARGET_FLAG_UNIT;
62 return TARGET_FLAG_ITEM;
65 default:
66 return TARGET_FLAG_NONE;
67 }
68}
69
71{
72 _target = Targets(target);
73}
74
76{
78}
79
81{
82 return _data[_target].SelectionCategory;
83}
84
86{
87 return _data[_target].ReferenceType;
88}
89
91{
92 return _data[_target].ObjectType;
93}
94
96{
97 return _data[_target].SelectionCheckType;
98}
99
101{
102 return _data[_target].DirectionType;
103}
104
106{
107 switch (GetDirectionType())
108 {
109 case TARGET_DIR_FRONT:
110 return 0.0f;
111 case TARGET_DIR_BACK:
112 return static_cast<float>(M_PI);
113 case TARGET_DIR_RIGHT:
114 return static_cast<float>(-M_PI/2);
115 case TARGET_DIR_LEFT:
116 return static_cast<float>(M_PI/2);
118 return static_cast<float>(-M_PI/4);
120 return static_cast<float>(-3*M_PI/4);
122 return static_cast<float>(3*M_PI/4);
124 return static_cast<float>(M_PI/4);
126 return rand_norm() * static_cast<float>(2 * M_PI);
127 default:
128 return 0.0f;
129 }
130}
131
133{
134 return _target;
135}
136
138{
139 uint32 targetMask = 0;
141 {
142 if (!srcSet)
143 targetMask = TARGET_FLAG_SOURCE_LOCATION;
144 if (!dstSet)
145 targetMask |= TARGET_FLAG_DEST_LOCATION;
146 }
147 else
148 {
149 switch (GetReferenceType())
150 {
152 if (srcSet)
153 break;
154 targetMask = TARGET_FLAG_SOURCE_LOCATION;
155 break;
157 if (dstSet)
158 break;
159 targetMask = TARGET_FLAG_DEST_LOCATION;
160 break;
162 switch (GetObjectType())
163 {
165 targetMask = TARGET_FLAG_GAMEOBJECT;
166 break;
168 targetMask = TARGET_FLAG_GAMEOBJECT_ITEM;
169 break;
173 switch (GetCheckType())
174 {
176 targetMask = TARGET_FLAG_UNIT_ENEMY;
177 break;
179 targetMask = TARGET_FLAG_UNIT_ALLY;
180 break;
182 targetMask = TARGET_FLAG_UNIT_PARTY;
183 break;
185 targetMask = TARGET_FLAG_UNIT_RAID;
186 break;
188 targetMask = TARGET_FLAG_UNIT_PASSENGER;
189 break;
191 [[fallthrough]];
192 default:
193 targetMask = TARGET_FLAG_UNIT;
194 break;
195 }
196 break;
197 default:
198 break;
199 }
200 break;
201 default:
202 break;
203 }
204 }
205
206 switch (GetObjectType())
207 {
209 srcSet = true;
210 break;
213 dstSet = true;
214 break;
215 default:
216 break;
217 }
218 return targetMask;
219}
220
222{
223 ImmunityInfo() = default;
224 ~ImmunityInfo() = default;
225
226 ImmunityInfo(ImmunityInfo const&) = delete;
227 ImmunityInfo(ImmunityInfo&&) noexcept = delete;
228 ImmunityInfo& operator=(ImmunityInfo const&) = delete;
229 ImmunityInfo& operator=(ImmunityInfo&&) noexcept = delete;
230
237
238 Trinity::Containers::FlatSet<AuraType> AuraTypeImmune;
240};
241
243{ {
397} };
398
405{
406}
407
409 : EffectAttributes(SpellEffectAttributes::None)
410{
411 ASSERT(spellInfo);
412
413 _spellInfo = spellInfo;
415 Effect = SpellEffectName(_effect.Effect);
421 Amplitude = _effect.EffectAmplitude;
424 MiscValue = _effect.EffectMiscValue[0];
425 MiscValueB = _effect.EffectMiscValue[1];
433 ItemType = _effect.EffectItemType;
437 Scaling.Class = _effect.ScalingClass;
439 Scaling.Variance = _effect.Variance;
441 ImplicitTargetConditions = nullptr;
443 _immunityInfo = nullptr;
444}
445
447SpellEffectInfo& SpellEffectInfo::operator=(SpellEffectInfo&&) noexcept = default;
448
449SpellEffectInfo::~SpellEffectInfo() = default;
450
451bool SpellEffectInfo::IsEffect() const
452{
453 return Effect != 0;
454}
455
457{
458 return Effect == effectName;
459}
460
462{
464}
465
467{
468 return IsAura() && ApplyAuraName == uint32(aura);
469}
470
472{
473 return TargetA.IsArea() || TargetB.IsArea();
474}
475
477{
486 return true;
487 return false;
488}
489
491{
493}
494
495int32 SpellEffectInfo::CalcValue(WorldObject const* caster /*= nullptr*/, int32 const* bp /*= nullptr*/, Unit const* target /*= nullptr*/, float* variance /*= nullptr*/, uint32 castItemId /*= 0*/, int32 itemLevel /*= -1*/) const
496{
497 double basePointsPerLevel = RealPointsPerLevel;
498 // TODO: this needs to be a float, not rounded
499 int32 basePoints = CalcBaseValue(caster, target, castItemId, itemLevel);
500 double value = bp ? *bp : basePoints;
501 double comboDamage = PointsPerResource;
502
503 Unit const* casterUnit = nullptr;
504 if (caster)
505 casterUnit = caster->ToUnit();
506
507 if (Scaling.Variance)
508 {
509 float delta = fabs(Scaling.Variance * 0.5f);
510 double valueVariance = frand(-delta, delta);
511 value += double(basePoints) * valueVariance;
512
513 if (variance)
514 *variance = valueVariance;
515 }
516
517 // base amount modification based on spell lvl vs caster lvl
518 if (Scaling.Coefficient != 0.0f)
519 {
521 comboDamage = Scaling.ResourceCoefficient * value;
522 }
524 {
525 if (casterUnit && basePointsPerLevel != 0.0)
526 {
527 int32 level = int32(casterUnit->GetLevel());
528 if (level > int32(_spellInfo->MaxLevel) && _spellInfo->MaxLevel > 0)
529 level = int32(_spellInfo->MaxLevel);
530
531 // if base level is greater than spell level, reduce by base level (eg. pilgrims foods)
532 level -= int32(std::max(_spellInfo->BaseLevel, _spellInfo->SpellLevel));
533 if (level < 0)
534 level = 0;
535 value += level * basePointsPerLevel;
536 }
537 }
538
539 // random damage
540 if (casterUnit)
541 {
542 // bonus amount from combo points
543 if (comboDamage)
544 if (int32 comboPoints = casterUnit->GetPower(POWER_COMBO_POINTS))
545 value += comboDamage * comboPoints;
546 }
547
548 if (caster)
549 value = caster->ApplyEffectModifiers(_spellInfo, EffectIndex, value);
550
551 return int32(round(value));
552}
553
554int32 SpellEffectInfo::CalcBaseValue(WorldObject const* caster, Unit const* target, uint32 itemId, int32 itemLevel) const
555{
556 if (Scaling.Coefficient != 0.0f)
557 {
560 level = target->GetLevel();
561 else if (caster && caster->IsUnit())
562 level = caster->ToUnit()->GetLevel();
563
565 level = _spellInfo->BaseLevel;
566
569
572
573 float value = 0.0f;
574 if (level > 0)
575 {
576 if (!Scaling.Class)
577 return 0;
578
579 uint32 effectiveItemLevel = itemLevel != -1 ? uint32(itemLevel) : 1u;
581 {
583 effectiveItemLevel = _spellInfo->Scaling.ScalesFromItemLevel;
584
585 if (Scaling.Class == -8 || Scaling.Class == -9)
586 {
587 RandPropPointsEntry const* randPropPoints = sRandPropPointsStore.LookupEntry(effectiveItemLevel);
588 if (!randPropPoints)
589 randPropPoints = sRandPropPointsStore.AssertEntry(sRandPropPointsStore.GetNumRows() - 1);
590
591 value = Scaling.Class == -8 ? randPropPoints->DamageReplaceStatF : randPropPoints->DamageSecondaryF;
592 }
593 else
594 value = GetRandomPropertyPoints(effectiveItemLevel, ITEM_QUALITY_RARE, INVTYPE_CHEST, 0);
595 }
596 else
598
599 if (Scaling.Class == -7)
600 if (GtCombatRatingsMultByILvl const* ratingMult = sCombatRatingsMultByILvlGameTable.GetRow(effectiveItemLevel))
601 if (ItemSparseEntry const* itemSparse = sItemSparseStore.LookupEntry(itemId))
602 value *= GetIlvlStatMultiplier(ratingMult, InventoryType(itemSparse->InventoryType));
603
604 if (Scaling.Class == -6)
605 if (GtStaminaMultByILvl const* staminaMult = sStaminaMultByILvlGameTable.GetRow(effectiveItemLevel))
606 if (ItemSparseEntry const* itemSparse = sItemSparseStore.LookupEntry(itemId))
607 value *= GetIlvlStatMultiplier(staminaMult, InventoryType(itemSparse->InventoryType));
608 }
609
610 value *= Scaling.Coefficient;
611 if (value > 0.0f && value < 1.0f)
612 value = 1.0f;
613
614 return int32(round(value));
615 }
616 else
617 {
618 float value = BasePoints;
620 if (stat != ExpectedStatType::None)
621 {
624
625 // TODO - add expansion and content tuning id args?
626 uint32 contentTuningId = _spellInfo->ContentTuningId; // content tuning should be passed as arg, the one stored in SpellInfo is fallback
627 int32 expansion = -2;
628 if (ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(contentTuningId))
629 expansion = contentTuning->ExpansionID;
630
631 int32 level = 1;
633 level = target->GetLevel();
634 else if (caster && caster->IsUnit())
635 level = caster->ToUnit()->GetLevel();
636
637 value = sDB2Manager.EvaluateExpectedStat(stat, level, expansion, 0, CLASS_NONE, 0) * BasePoints / 100.0f;
638 }
639
640 return int32(round(value));
641 }
642}
643
644float SpellEffectInfo::CalcValueMultiplier(WorldObject* caster, Spell* spell /*= nullptr*/) const
645{
646 float multiplier = Amplitude;
647 if (Player* modOwner = (caster ? caster->GetSpellModOwner() : nullptr))
648 modOwner->ApplySpellMod(_spellInfo, SpellModOp::Amplitude, multiplier, spell);
649 return multiplier;
650}
651
652float SpellEffectInfo::CalcDamageMultiplier(WorldObject* caster, Spell* spell /*= nullptr*/) const
653{
654 float multiplierPercent = ChainAmplitude * 100.0f;
655 if (Player* modOwner = (caster ? caster->GetSpellModOwner() : nullptr))
656 modOwner->ApplySpellMod(_spellInfo, SpellModOp::ChainAmplitude, multiplierPercent, spell);
657 return multiplierPercent / 100.0f;
658}
659
661{
662 switch (targetIndex)
663 {
665 return TargetARadiusEntry != nullptr;
667 return TargetBRadiusEntry != nullptr;
668 default:
669 return false;
670 }
671}
672
673float SpellEffectInfo::CalcRadius(WorldObject* caster /*= nullptr*/, SpellTargetIndex targetIndex /*=SpellTargetIndex::TargetA*/, Spell* spell /*= nullptr*/) const
674{
675 // TargetA -> TargetARadiusEntry
676 // TargetB -> TargetBRadiusEntry
677 // Aura effects have TargetARadiusEntry == TargetBRadiusEntry (mostly)
680 if (targetIndex == SpellTargetIndex::TargetB && HasRadius(targetIndex))
681 {
682 target = TargetB;
683 entry = TargetBRadiusEntry;
684 }
685
686 if (!entry)
687 return 0.0f;
688
689 float radius = entry->RadiusMin;
690
691 // Random targets use random value between RadiusMin and RadiusMax
692 // For other cases, client uses RadiusMax if RadiusMin is 0
693 if (target.GetTarget() == TARGET_DEST_CASTER_RANDOM ||
696 radius += (entry->RadiusMax - radius) * rand_norm();
697 else if (radius == 0.0f)
698 radius = entry->RadiusMax;
699
700 if (caster)
701 {
702 if (Unit const* casterUnit = caster->ToUnit())
703 radius += entry->RadiusPerLevel * casterUnit->GetLevel();
704
705 radius = std::min(radius, entry->RadiusMax);
706
707 if (Player* modOwner = caster->GetSpellModOwner())
708 modOwner->ApplySpellMod(_spellInfo, SpellModOp::Radius, radius, spell);
709
711 if (Unit const* casterUnit = caster->ToUnit(); casterUnit && Spell::CanIncreaseRangeByMovement(casterUnit))
712 radius += 2.0f;
713 }
714
715 return radius;
716}
717
719{
721}
722
723uint32 SpellEffectInfo::GetMissingTargetMask(bool srcSet /*= false*/, bool dstSet /*= false*/, uint32 mask /*=0*/) const
724{
725 uint32 effImplicitTargetMask = GetTargetFlagMask(GetUsedTargetObjectType());
726 uint32 providedTargetMask = GetProvidedTargetMask() | mask;
727
728 // remove all flags covered by effect target mask
729 if (providedTargetMask & TARGET_FLAG_UNIT_MASK)
730 effImplicitTargetMask &= ~(TARGET_FLAG_UNIT_MASK);
731 if (providedTargetMask & TARGET_FLAG_CORPSE_MASK)
732 effImplicitTargetMask &= ~(TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK);
733 if (providedTargetMask & TARGET_FLAG_GAMEOBJECT_ITEM)
735 if (providedTargetMask & TARGET_FLAG_GAMEOBJECT)
736 effImplicitTargetMask &= ~(TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_GAMEOBJECT_ITEM);
737 if (providedTargetMask & TARGET_FLAG_ITEM)
738 effImplicitTargetMask &= ~(TARGET_FLAG_ITEM | TARGET_FLAG_GAMEOBJECT_ITEM);
739 if (dstSet || providedTargetMask & TARGET_FLAG_DEST_LOCATION)
740 effImplicitTargetMask &= ~(TARGET_FLAG_DEST_LOCATION);
741 if (srcSet || providedTargetMask & TARGET_FLAG_SOURCE_LOCATION)
742 effImplicitTargetMask &= ~(TARGET_FLAG_SOURCE_LOCATION);
743
744 return effImplicitTargetMask;
745}
746
748{
749 return _data[Effect].ImplicitTargetType;
750}
751
753{
754 return _data[Effect].UsedTargetObjectType;
755}
756
758{
759 switch (Effect)
760 {
772 if (MiscValue == POWER_MANA)
788 switch (ApplyAuraName)
789 {
833 if (MiscValue == POWER_MANA)
836 default:
837 break;
838 }
839 break;
840 default:
841 break;
842 }
843
845}
846
847std::array<SpellEffectInfo::StaticData, TOTAL_SPELL_EFFECTS> SpellEffectInfo::_data =
848{ {
849 // implicit target type used target object type
851 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 1 SPELL_EFFECT_INSTAKILL
852 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
853 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 3 SPELL_EFFECT_DUMMY
854 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 4 SPELL_EFFECT_PORTAL_TELEPORT
856 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 6 SPELL_EFFECT_APPLY_AURA
857 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
858 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 8 SPELL_EFFECT_POWER_DRAIN
859 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 9 SPELL_EFFECT_HEALTH_LEECH
862 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 12 SPELL_EFFECT_PORTAL
863 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT_AND_DEST}, // 13 SPELL_EFFECT_TELEPORT_TO_RETURN_POINT
864 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 14 SPELL_EFFECT_INCREASE_CURRENCY_CAP
865 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT_AND_DEST}, // 15 SPELL_EFFECT_TELEPORT_WITH_SPELL_VISUAL_KIT_LOADING_SCREEN
866 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 16 SPELL_EFFECT_QUEST_COMPLETE
867 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
869 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
870 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 20 SPELL_EFFECT_DODGE
871 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 21 SPELL_EFFECT_EVADE
872 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 22 SPELL_EFFECT_PARRY
873 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 23 SPELL_EFFECT_BLOCK
874 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 24 SPELL_EFFECT_CREATE_ITEM
875 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 25 SPELL_EFFECT_WEAPON
876 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 26 SPELL_EFFECT_DEFENSE
877 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
878 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 28 SPELL_EFFECT_SUMMON
880 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 30 SPELL_EFFECT_ENERGIZE
881 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
882 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 32 SPELL_EFFECT_TRIGGER_MISSILE
884 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
885 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
886 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 36 SPELL_EFFECT_LEARN_SPELL
887 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 37 SPELL_EFFECT_SPELL_DEFENSE
888 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 38 SPELL_EFFECT_DISPEL
889 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 39 SPELL_EFFECT_LANGUAGE
890 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 40 SPELL_EFFECT_DUAL_WIELD
892 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 42 SPELL_EFFECT_JUMP_DEST
893 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT_AND_DEST}, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
894 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 44 SPELL_EFFECT_SKILL_STEP
895 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 45 SPELL_EFFECT_ADD_HONOR
896 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 46 SPELL_EFFECT_SPAWN
897 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 47 SPELL_EFFECT_TRADE_SKILL
898 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 48 SPELL_EFFECT_STEALTH
899 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 49 SPELL_EFFECT_DETECT
900 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 50 SPELL_EFFECT_TRANS_DOOR
901 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT
902 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 52 SPELL_EFFECT_SET_MAX_BATTLE_PET_COUNT
903 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 53 SPELL_EFFECT_ENCHANT_ITEM
904 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
905 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 55 SPELL_EFFECT_TAMECREATURE
906 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 56 SPELL_EFFECT_SUMMON_PET
907 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 57 SPELL_EFFECT_LEARN_PET_SPELL
908 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 58 SPELL_EFFECT_WEAPON_DAMAGE
909 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM
910 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 60 SPELL_EFFECT_PROFICIENCY
911 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 61 SPELL_EFFECT_SEND_EVENT
912 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 62 SPELL_EFFECT_POWER_BURN
913 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 63 SPELL_EFFECT_THREAT
914 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 64 SPELL_EFFECT_TRIGGER_SPELL
915 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
916 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 66 SPELL_EFFECT_RECHARGE_ITEM
917 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
918 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 68 SPELL_EFFECT_INTERRUPT_CAST
920 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 70 SPELL_EFFECT_COMPLETE_AND_REWARD_WORLD_QUEST
921 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 71 SPELL_EFFECT_PICKPOCKET
922 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 72 SPELL_EFFECT_ADD_FARSIGHT
923 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
924 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 74 SPELL_EFFECT_APPLY_GLYPH
925 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 75 SPELL_EFFECT_HEAL_MECHANICAL
926 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
927 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 77 SPELL_EFFECT_SCRIPT_EFFECT
928 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 78 SPELL_EFFECT_ATTACK
929 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 79 SPELL_EFFECT_SANCTUARY
930 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 80 SPELL_EFFECT_MODIFY_FOLLOWER_ITEM_LEVEL
931 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 81 SPELL_EFFECT_PUSH_ABILITY_TO_ACTION_BAR
932 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 82 SPELL_EFFECT_BIND_SIGHT
934 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 84 SPELL_EFFECT_STUCK
935 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 85 SPELL_EFFECT_SUMMON_PLAYER
936 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_GOBJ}, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
937 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_GOBJ}, // 87 SPELL_EFFECT_GAMEOBJECT_DAMAGE
938 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_GOBJ}, // 88 SPELL_EFFECT_GAMEOBJECT_REPAIR
939 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_GOBJ}, // 89 SPELL_EFFECT_GAMEOBJECT_SET_DESTRUCTION_STATE
940 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 90 SPELL_EFFECT_KILL_CREDIT
941 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 91 SPELL_EFFECT_THREAT_ALL
942 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
943 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 93 SPELL_EFFECT_FORCE_DESELECT
944 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 94 SPELL_EFFECT_SELF_RESURRECT
945 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 95 SPELL_EFFECT_SKINNING
946 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 96 SPELL_EFFECT_CHARGE
947 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 97 SPELL_EFFECT_CAST_BUTTON
948 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 98 SPELL_EFFECT_KNOCK_BACK
949 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 99 SPELL_EFFECT_DISENCHANT
950 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 100 SPELL_EFFECT_INEBRIATE
951 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 101 SPELL_EFFECT_FEED_PET
952 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 102 SPELL_EFFECT_DISMISS_PET
953 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 103 SPELL_EFFECT_REPUTATION
954 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
955 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 105 SPELL_EFFECT_SURVEY
956 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 106 SPELL_EFFECT_CHANGE_RAID_MARKER
957 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 107 SPELL_EFFECT_SHOW_CORPSE_LOOT
958 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 108 SPELL_EFFECT_DISPEL_MECHANIC
959 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 109 SPELL_EFFECT_RESURRECT_PET
960 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
961 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 111 SPELL_EFFECT_DURABILITY_DAMAGE
963 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 113 SPELL_EFFECT_CANCEL_CONVERSATION
964 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 114 SPELL_EFFECT_ATTACK_ME
965 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
966 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_CORPSE_ENEMY}, // 116 SPELL_EFFECT_SKIN_PLAYER_CORPSE
967 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 117 SPELL_EFFECT_SPIRIT_HEAL
968 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 118 SPELL_EFFECT_SKILL
969 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 119 SPELL_EFFECT_APPLY_AREA_AURA_PET
970 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 120 SPELL_EFFECT_TELEPORT_GRAVEYARD
971 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
972 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 122 SPELL_EFFECT_122
973 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 123 SPELL_EFFECT_SEND_TAXI
974 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 124 SPELL_EFFECT_PULL_TOWARDS
975 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
976 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF
977 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 127 SPELL_EFFECT_PROSPECTING
978 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
979 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
980 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 130 SPELL_EFFECT_REDIRECT_THREAT
981 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 131 SPELL_EFFECT_PLAY_SOUND
982 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 132 SPELL_EFFECT_PLAY_MUSIC
983 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 133 SPELL_EFFECT_UNLEARN_SPECIALIZATION
984 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 134 SPELL_EFFECT_KILL_CREDIT2
985 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 135 SPELL_EFFECT_CALL_PET
986 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 136 SPELL_EFFECT_HEAL_PCT
987 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 137 SPELL_EFFECT_ENERGIZE_PCT
988 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 138 SPELL_EFFECT_LEAP_BACK
989 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 139 SPELL_EFFECT_CLEAR_QUEST
990 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 140 SPELL_EFFECT_FORCE_CAST
991 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 141 SPELL_EFFECT_FORCE_CAST_WITH_VALUE
992 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
993 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
994 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT_AND_DEST}, // 144 SPELL_EFFECT_KNOCK_BACK_DEST
995 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT_AND_DEST}, // 145 SPELL_EFFECT_PULL_TOWARDS_DEST
996 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 146 SPELL_EFFECT_RESTORE_GARRISON_TROOP_VITALITY
997 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 147 SPELL_EFFECT_QUEST_FAIL
998 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 148 SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE
999 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 149 SPELL_EFFECT_CHARGE_DEST
1000 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 150 SPELL_EFFECT_QUEST_START
1001 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 151 SPELL_EFFECT_TRIGGER_SPELL_2
1002 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 152 SPELL_EFFECT_SUMMON_RAF_FRIEND
1003 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 153 SPELL_EFFECT_CREATE_TAMED_PET
1004 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 154 SPELL_EFFECT_DISCOVER_TAXI
1005 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 155 SPELL_EFFECT_TITAN_GRIP
1006 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
1007 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 157 SPELL_EFFECT_CREATE_LOOT
1008 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 158 SPELL_EFFECT_MILLING
1009 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 159 SPELL_EFFECT_ALLOW_RENAME_PET
1010 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 160 SPELL_EFFECT_FORCE_CAST_2
1011 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 161 SPELL_EFFECT_TALENT_SPEC_COUNT
1012 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 162 SPELL_EFFECT_TALENT_SPEC_SELECT
1013 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 163 SPELL_EFFECT_OBLITERATE_ITEM
1014 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 164 SPELL_EFFECT_REMOVE_AURA
1015 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 165 SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT
1016 {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 166 SPELL_EFFECT_GIVE_CURRENCY
1017 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 167 SPELL_EFFECT_UPDATE_PLAYER_PHASE
1018 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 168 SPELL_EFFECT_ALLOW_CONTROL_PET
1019 {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 169 SPELL_EFFECT_DESTROY_ITEM
1020 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 170 SPELL_EFFECT_UPDATE_ZONE_AURAS_AND_PHASES
1021 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 171 SPELL_EFFECT_SUMMON_PERSONAL_GAMEOBJECT
1022 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_CORPSE_ALLY}, // 172 SPELL_EFFECT_RESURRECT_WITH_AURA
1023 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 173 SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB
1024 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 174 SPELL_EFFECT_APPLY_AURA_ON_PET
1025 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 175 SPELL_EFFECT_175
1026 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 176 SPELL_EFFECT_SANCTUARY_2
1027 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 177 SPELL_EFFECT_DESPAWN_PERSISTENT_AREA_AURA
1028 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 178 SPELL_EFFECT_178
1029 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 179 SPELL_EFFECT_CREATE_AREATRIGGER
1030 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 180 SPELL_EFFECT_UPDATE_AREATRIGGER
1031 {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 181 SPELL_EFFECT_REMOVE_TALENT
1032 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 182 SPELL_EFFECT_DESPAWN_AREATRIGGER
1033 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 183 SPELL_EFFECT_183
1034 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 184 SPELL_EFFECT_REPUTATION_2
1035 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 185 SPELL_EFFECT_185
1036 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 186 SPELL_EFFECT_186
1037 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 187 SPELL_EFFECT_RANDOMIZE_ARCHAEOLOGY_DIGSITES
1038 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 188 SPELL_EFFECT_SUMMON_STABLED_PET_AS_GUARDIAN
1039 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 189 SPELL_EFFECT_LOOT
1040 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 190 SPELL_EFFECT_CHANGE_PARTY_MEMBERS
1041 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 191 SPELL_EFFECT_TELEPORT_TO_DIGSITE
1042 {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 192 SPELL_EFFECT_UNCAGE_BATTLEPET
1043 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 193 SPELL_EFFECT_START_PET_BATTLE
1044 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 194 SPELL_EFFECT_194
1045 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 195 SPELL_EFFECT_PLAY_SCENE_SCRIPT_PACKAGE
1046 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 196 SPELL_EFFECT_CREATE_SCENE_OBJECT
1047 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 197 SPELL_EFFECT_CREATE_PERSONAL_SCENE_OBJECT
1048 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 198 SPELL_EFFECT_PLAY_SCENE
1049 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 199 SPELL_EFFECT_DESPAWN_SUMMON
1050 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 200 SPELL_EFFECT_HEAL_BATTLEPET_PCT
1051 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 201 SPELL_EFFECT_ENABLE_BATTLE_PETS
1052 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 202 SPELL_EFFECT_APPLY_AREA_AURA_SUMMONS
1053 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 203 SPELL_EFFECT_REMOVE_AURA_2
1054 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 204 SPELL_EFFECT_CHANGE_BATTLEPET_QUALITY
1055 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 205 SPELL_EFFECT_LAUNCH_QUEST_CHOICE
1056 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 206 SPELL_EFFECT_ALTER_IETM
1057 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 207 SPELL_EFFECT_LAUNCH_QUEST_TASK
1058 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 208 SPELL_EFFECT_SET_REPUTATION
1059 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 209 SPELL_EFFECT_209
1060 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 210 SPELL_EFFECT_LEARN_GARRISON_BUILDING
1061 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 211 SPELL_EFFECT_LEARN_GARRISON_SPECIALIZATION
1062 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 212 SPELL_EFFECT_REMOVE_AURA_BY_SPELL_LABEL
1063 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 213 SPELL_EFFECT_JUMP_DEST_2
1064 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 214 SPELL_EFFECT_CREATE_GARRISON
1065 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 215 SPELL_EFFECT_UPGRADE_CHARACTER_SPELLS
1066 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 216 SPELL_EFFECT_CREATE_SHIPMENT
1067 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 217 SPELL_EFFECT_UPGRADE_GARRISON
1068 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 218 SPELL_EFFECT_218
1069 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 219 SPELL_EFFECT_CREATE_CONVERSATION
1070 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 220 SPELL_EFFECT_ADD_GARRISON_FOLLOWER
1071 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 221 SPELL_EFFECT_ADD_GARRISON_MISSION
1072 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 222 SPELL_EFFECT_CREATE_HEIRLOOM_ITEM
1073 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 223 SPELL_EFFECT_CHANGE_ITEM_BONUSES
1074 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 224 SPELL_EFFECT_ACTIVATE_GARRISON_BUILDING
1075 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 225 SPELL_EFFECT_GRANT_BATTLEPET_LEVEL
1076 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 226 SPELL_EFFECT_TRIGGER_ACTION_SET
1077 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 227 SPELL_EFFECT_TELEPORT_TO_LFG_DUNGEON
1078 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 228 SPELL_EFFECT_228
1079 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 229 SPELL_EFFECT_SET_FOLLOWER_QUALITY
1081 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 231 SPELL_EFFECT_INCREASE_FOLLOWER_EXPERIENCE
1082 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 232 SPELL_EFFECT_REMOVE_PHASE
1083 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 233 SPELL_EFFECT_RANDOMIZE_FOLLOWER_ABILITIES
1084 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 234 SPELL_EFFECT_234
1085 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 235 SPELL_EFFECT_235
1086 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 236 SPELL_EFFECT_GIVE_EXPERIENCE
1087 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 237 SPELL_EFFECT_GIVE_RESTED_EXPERIENCE_BONUS
1088 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 238 SPELL_EFFECT_INCREASE_SKILL
1089 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 239 SPELL_EFFECT_END_GARRISON_BUILDING_CONSTRUCTION
1090 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 240 SPELL_EFFECT_GIVE_ARTIFACT_POWER
1091 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 241 SPELL_EFFECT_241
1092 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 242 SPELL_EFFECT_GIVE_ARTIFACT_POWER_NO_BONUS
1093 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 243 SPELL_EFFECT_APPLY_ENCHANT_ILLUSION
1094 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 244 SPELL_EFFECT_LEARN_FOLLOWER_ABILITY
1095 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 245 SPELL_EFFECT_UPGRADE_HEIRLOOM
1096 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 246 SPELL_EFFECT_FINISH_GARRISON_MISSION
1097 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 247 SPELL_EFFECT_ADD_GARRISON_MISSION_SET
1098 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 248 SPELL_EFFECT_FINISH_SHIPMENT
1099 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 249 SPELL_EFFECT_FORCE_EQUIP_ITEM
1100 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 250 SPELL_EFFECT_TAKE_SCREENSHOT
1101 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 251 SPELL_EFFECT_SET_GARRISON_CACHE_SIZE
1102 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT_AND_DEST}, // 252 SPELL_EFFECT_TELEPORT_UNITS
1103 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 253 SPELL_EFFECT_GIVE_HONOR
1104 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 254 SPELL_EFFECT_JUMP_CHARGE
1105 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 255 SPELL_EFFECT_LEARN_TRANSMOG_SET
1106 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 256 SPELL_EFFECT_256
1107 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 257 SPELL_EFFECT_257
1108 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 258 SPELL_EFFECT_MODIFY_KEYSTONE
1109 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 259 SPELL_EFFECT_RESPEC_AZERITE_EMPOWERED_ITEM
1110 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 260 SPELL_EFFECT_SUMMON_STABLED_PET
1111 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 261 SPELL_EFFECT_SCRAP_ITEM
1112 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 262 SPELL_EFFECT_262
1113 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 263 SPELL_EFFECT_REPAIR_ITEM
1114 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 264 SPELL_EFFECT_REMOVE_GEM
1115 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 265 SPELL_EFFECT_LEARN_AZERITE_ESSENCE_POWER
1116 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 266 SPELL_EFFECT_SET_ITEM_BONUS_LIST_GROUP_ENTRY
1117 {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 267 SPELL_EFFECT_CREATE_PRIVATE_CONVERSATION
1118 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 268 SPELL_EFFECT_APPLY_MOUNT_EQUIPMENT
1119 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 269 SPELL_EFFECT_INCREASE_ITEM_BONUS_LIST_GROUP_STEP
1121 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 271 SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM
1122 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 272 SPELL_EFFECT_SET_COVENANT
1123 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 273 SPELL_EFFECT_CRAFT_RUNEFORGE_LEGENDARY
1124 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 274 SPELL_EFFECT_274
1125 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 275 SPELL_EFFECT_275
1126 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 276 SPELL_EFFECT_LEARN_TRANSMOG_ILLUSION
1127 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 277 SPELL_EFFECT_SET_CHROMIE_TIME
1128 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 278 SPELL_EFFECT_278
1129 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 279 SPELL_EFFECT_LEARN_GARR_TALENT
1130 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 280 SPELL_EFFECT_280
1131 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 281 SPELL_EFFECT_LEARN_SOULBIND_CONDUIT
1132 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 282 SPELL_EFFECT_CONVERT_ITEMS_TO_CURRENCY
1133 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 283 SPELL_EFFECT_COMPLETE_CAMPAIGN
1134 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 284 SPELL_EFFECT_SEND_CHAT_MESSAGE
1135 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 285 SPELL_EFFECT_MODIFY_KEYSTONE_2
1136 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 286 SPELL_EFFECT_GRANT_BATTLEPET_EXPERIENCE
1137 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 287 SPELL_EFFECT_SET_GARRISON_FOLLOWER_LEVEL
1138 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 288 SPELL_EFFECT_CRAFT_ITEM
1139 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 289 SPELL_EFFECT_MODIFY_AURA_STACKS
1140 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 290 SPELL_EFFECT_MODIFY_COOLDOWN
1141 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 291 SPELL_EFFECT_MODIFY_COOLDOWNS
1142 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 292 SPELL_EFFECT_MODIFY_COOLDOWNS_BY_CATEGORY
1143 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 293 SPELL_EFFECT_MODIFY_CHARGES
1144 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 294 SPELL_EFFECT_CRAFT_LOOT
1145 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 295 SPELL_EFFECT_SALVAGE_ITEM
1146 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 296 SPELL_EFFECT_CRAFT_SALVAGE_ITEM
1147 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 297 SPELL_EFFECT_RECRAFT_ITEM
1148 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 298 SPELL_EFFECT_CANCEL_ALL_PRIVATE_CONVERSATIONS
1149 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 299 SPELL_EFFECT_299
1150 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 300 SPELL_EFFECT_300
1151 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 301 SPELL_EFFECT_CRAFT_ENCHANT
1152 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_NONE}, // 302 SPELL_EFFECT_GATHERING
1153 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 303 SPELL_EFFECT_CREATE_TRAIT_TREE_CONFIG
1154 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 304 SPELL_EFFECT_CHANGE_ACTIVE_COMBAT_TRAIT_CONFIG
1155 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 305 SPELL_EFFECT_305
1156 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 306 SPELL_EFFECT_UPDATE_INTERACTIONS
1157 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 307 SPELL_EFFECT_307
1158 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 308 SPELL_EFFECT_CANCEL_PRELOAD_WORLD
1159 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 309 SPELL_EFFECT_PRELOAD_WORLD
1160 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 310 SPELL_EFFECT_310
1161 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 311 SPELL_EFFECT_ENSURE_WORLD_LOADED
1162 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 312 SPELL_EFFECT_312
1163 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 313 SPELL_EFFECT_CHANGE_ITEM_BONUSES_2
1164 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 314 SPELL_EFFECT_ADD_SOCKET_BONUS
1165 {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 315 SPELL_EFFECT_LEARN_TRANSMOG_APPEARANCE_FROM_ITEM_MOD_APPEARANCE_GROUP
1166 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 316 SPELL_EFFECT_KILL_CREDIT_LABEL_1
1167 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 317 SPELL_EFFECT_KILL_CREDIT_LABEL_2
1168 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 318 SPELL_EFFECT_318
1169 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 319 SPELL_EFFECT_319
1170 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 320 SPELL_EFFECT_320
1171 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 321 SPELL_EFFECT_321
1172 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 322 SPELL_EFFECT_322
1173 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 323 SPELL_EFFECT_323
1174 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 324 SPELL_EFFECT_324
1175 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 325 SPELL_EFFECT_325
1176 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 326 SPELL_EFFECT_326
1177 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 327 SPELL_EFFECT_327
1178 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 328 SPELL_EFFECT_328
1179 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 329 SPELL_EFFECT_329
1180 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 330 SPELL_EFFECT_330
1181 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 331 SPELL_EFFECT_331
1182 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 332 SPELL_EFFECT_332
1183 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 333 SPELL_EFFECT_333
1184} };
1185
1187 : Id(spellName->ID), Difficulty(difficulty)
1188{
1189 _effects.reserve(32);
1190 for (SpellEffectEntry const* spellEffect : data.Effects)
1191 {
1192 if (!spellEffect)
1193 continue;
1194
1196 }
1197
1198 // Correct EffectIndex for blank effects
1199 for (size_t i = 0; i < _effects.size(); ++i)
1200 {
1201 _effects[i]._spellInfo = this;
1202 _effects[i].EffectIndex = SpellEffIndex(i);
1203 }
1204
1205 _effects.shrink_to_fit();
1206
1207 SpellName = &spellName->Name;
1208
1209 // SpellMiscEntry
1210 if (SpellMiscEntry const* _misc = data.Misc)
1211 {
1212 Attributes = _misc->Attributes[0];
1213 AttributesEx = _misc->Attributes[1];
1214 AttributesEx2 = _misc->Attributes[2];
1215 AttributesEx3 = _misc->Attributes[3];
1216 AttributesEx4 = _misc->Attributes[4];
1217 AttributesEx5 = _misc->Attributes[5];
1218 AttributesEx6 = _misc->Attributes[6];
1219 AttributesEx7 = _misc->Attributes[7];
1220 AttributesEx8 = _misc->Attributes[8];
1221 AttributesEx9 = _misc->Attributes[9];
1222 AttributesEx10 = _misc->Attributes[10];
1223 AttributesEx11 = _misc->Attributes[11];
1224 AttributesEx12 = _misc->Attributes[12];
1225 AttributesEx13 = _misc->Attributes[13];
1226 AttributesEx14 = _misc->Attributes[14];
1227 CastTimeEntry = sSpellCastTimesStore.LookupEntry(_misc->CastingTimeIndex);
1228 DurationEntry = sSpellDurationStore.LookupEntry(_misc->DurationIndex);
1229 RangeEntry = sSpellRangeStore.LookupEntry(_misc->RangeIndex);
1230 Speed = _misc->Speed;
1231 LaunchDelay = _misc->LaunchDelay;
1232 SchoolMask = _misc->SchoolMask;
1233 IconFileDataId = _misc->SpellIconFileDataID;
1234 ActiveIconFileDataId = _misc->ActiveIconFileDataID;
1235 ContentTuningId = _misc->ContentTuningID;
1236 ShowFutureSpellPlayerConditionID = _misc->ShowFutureSpellPlayerConditionID;
1237 }
1238
1239 // SpellScalingEntry
1240 if (SpellScalingEntry const* _scaling = data.Scaling)
1241 {
1242 Scaling.MinScalingLevel = _scaling->MinScalingLevel;
1243 Scaling.MaxScalingLevel = _scaling->MaxScalingLevel;
1244 Scaling.ScalesFromItemLevel = _scaling->ScalesFromItemLevel;
1245 }
1246
1247 // SpellAuraOptionsEntry
1248 if (SpellAuraOptionsEntry const* _options = data.AuraOptions)
1249 {
1250 ProcFlags = _options->ProcTypeMask;
1251 ProcChance = _options->ProcChance;
1252 ProcCharges = _options->ProcCharges;
1253 ProcCooldown = _options->ProcCategoryRecovery;
1254 StackAmount = _options->CumulativeAura;
1255 if (SpellProcsPerMinuteEntry const* _ppm = sSpellProcsPerMinuteStore.LookupEntry(_options->SpellProcsPerMinuteID))
1256 {
1257 ProcBasePPM = _ppm->BaseProcRate;
1258 ProcPPMMods = sDB2Manager.GetSpellProcsPerMinuteMods(_ppm->ID);
1259 }
1260 }
1261
1262 // SpellAuraRestrictionsEntry
1263 if (SpellAuraRestrictionsEntry const* _aura = data.AuraRestrictions)
1264 {
1265 CasterAuraState = _aura->CasterAuraState;
1266 TargetAuraState = _aura->TargetAuraState;
1267 ExcludeCasterAuraState = _aura->ExcludeCasterAuraState;
1268 ExcludeTargetAuraState = _aura->ExcludeTargetAuraState;
1269 CasterAuraSpell = _aura->CasterAuraSpell;
1270 TargetAuraSpell = _aura->TargetAuraSpell;
1271 ExcludeCasterAuraSpell = _aura->ExcludeCasterAuraSpell;
1272 ExcludeTargetAuraSpell = _aura->ExcludeTargetAuraSpell;
1273 CasterAuraType = AuraType(_aura->CasterAuraType);
1274 TargetAuraType = AuraType(_aura->TargetAuraType);
1275 ExcludeCasterAuraType = AuraType(_aura->ExcludeCasterAuraType);
1276 ExcludeTargetAuraType = AuraType(_aura->ExcludeTargetAuraType);
1277 }
1278
1279 // SpellCastingRequirementsEntry
1280 if (SpellCastingRequirementsEntry const* _castreq = data.CastingRequirements)
1281 {
1282 RequiresSpellFocus = _castreq->RequiresSpellFocus;
1283 FacingCasterFlags = _castreq->FacingCasterFlags;
1284 RequiredAreasID = _castreq->RequiredAreasID;
1285 }
1286
1287 // SpellCategoriesEntry
1288 if (SpellCategoriesEntry const* _categories = data.Categories)
1289 {
1290 CategoryId = _categories->Category;
1291 Dispel = _categories->DispelType;
1292 Mechanic = _categories->Mechanic;
1293 StartRecoveryCategory = _categories->StartRecoveryCategory;
1294 DmgClass = _categories->DefenseType;
1295 PreventionType = _categories->PreventionType;
1296 ChargeCategoryId = _categories->ChargeCategory;
1297 }
1298
1299 // SpellClassOptionsEntry
1300 if (SpellClassOptionsEntry const* _class = data.ClassOptions)
1301 {
1302 SpellFamilyName = _class->SpellClassSet;
1303 SpellFamilyFlags = _class->SpellClassMask;
1304 }
1305
1306 // SpellCooldownsEntry
1307 if (SpellCooldownsEntry const* _cooldowns = data.Cooldowns)
1308 {
1309 RecoveryTime = _cooldowns->RecoveryTime;
1310 CategoryRecoveryTime = _cooldowns->CategoryRecoveryTime;
1311 StartRecoveryTime = _cooldowns->StartRecoveryTime;
1312 CooldownAuraSpellId = _cooldowns->AuraSpellID;
1313 }
1314
1315 // SpellEmpowerStageEntry
1316 std::ranges::transform(data.EmpowerStages, std::back_inserter(EmpowerStageThresholds), [](SpellEmpowerStageEntry const* stage) { return Milliseconds(stage->DurationMs); });
1317
1318 // SpellEquippedItemsEntry
1319 if (SpellEquippedItemsEntry const* _equipped = data.EquippedItems)
1320 {
1321 EquippedItemClass = _equipped->EquippedItemClass;
1322 EquippedItemSubClassMask = _equipped->EquippedItemSubclass;
1323 EquippedItemInventoryTypeMask = _equipped->EquippedItemInvTypes;
1324 }
1325
1326 // SpellInterruptsEntry
1327 if (SpellInterruptsEntry const* _interrupt = data.Interrupts)
1328 {
1329 InterruptFlags = SpellInterruptFlags(_interrupt->InterruptFlags);
1330 AuraInterruptFlags = SpellAuraInterruptFlags(_interrupt->AuraInterruptFlags[0]);
1331 AuraInterruptFlags2 = SpellAuraInterruptFlags2(_interrupt->AuraInterruptFlags[1]);
1332 ChannelInterruptFlags = SpellAuraInterruptFlags(_interrupt->ChannelInterruptFlags[0]);
1333 ChannelInterruptFlags2 = SpellAuraInterruptFlags2(_interrupt->ChannelInterruptFlags[1]);
1334 }
1335
1336 for (SpellLabelEntry const* label : data.Labels)
1337 Labels.insert(label->LabelID);
1338
1339 // SpellLevelsEntry
1340 if (SpellLevelsEntry const* _levels = data.Levels)
1341 {
1342 MaxLevel = _levels->MaxLevel;
1343 BaseLevel = _levels->BaseLevel;
1344 SpellLevel = _levels->SpellLevel;
1345 }
1346
1347 // SpellPowerEntry
1348 PowerCosts = data.Powers;
1349
1350 // SpellReagentsEntry
1351 if (SpellReagentsEntry const* _reagents = data.Reagents)
1352 {
1353 Reagent = _reagents->Reagent;
1354 ReagentCount = _reagents->ReagentCount;
1355 }
1356
1358
1359 // SpellShapeshiftEntry
1360 if (SpellShapeshiftEntry const* _shapeshift = data.Shapeshift)
1361 {
1362 Stances = MAKE_PAIR64(_shapeshift->ShapeshiftMask[0], _shapeshift->ShapeshiftMask[1]);
1363 StancesNot = MAKE_PAIR64(_shapeshift->ShapeshiftExclude[0], _shapeshift->ShapeshiftExclude[1]);
1364 }
1365
1366 // SpellTargetRestrictionsEntry
1367 if (SpellTargetRestrictionsEntry const* _target = data.TargetRestrictions)
1368 {
1369 ConeAngle = _target->ConeDegrees;
1370 Width = _target->Width;
1371 Targets = _target->Targets;
1372 TargetCreatureType = _target->TargetCreatureType;
1373 MaxAffectedTargets = _target->MaxTargets;
1374 MaxTargetLevel = _target->MaxTargetLevel;
1375 }
1376
1377 // SpellTotemsEntry
1378 if (SpellTotemsEntry const* _totem = data.Totems)
1379 {
1380 TotemCategory = _totem->RequiredTotemCategoryID;
1381 Totem = _totem->Totem;
1382 }
1383
1384 _visuals = data.Visuals;
1385}
1386
1387SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, std::vector<SpellEffectEntry> const& effects)
1388 : Id(spellName->ID), Difficulty(difficulty)
1389{
1390 SpellName = &spellName->Name;
1391
1392 _effects.reserve(32);
1393 for (SpellEffectEntry const& spellEffect : effects)
1394 Trinity::Containers::EnsureWritableVectorIndex(_effects, spellEffect.EffectIndex) = SpellEffectInfo(this, spellEffect);
1395
1396 // Correct EffectIndex for blank effects
1397 for (size_t i = 0; i < _effects.size(); ++i)
1398 {
1399 _effects[i]._spellInfo = this;
1400 _effects[i].EffectIndex = SpellEffIndex(i);
1401 }
1402
1403 _effects.shrink_to_fit();
1404}
1405
1407{
1409}
1410
1412{
1413 return CategoryId;
1414}
1415
1417{
1418 for (SpellEffectInfo const& eff : GetEffects())
1419 if (eff.IsEffect(effect))
1420 return true;
1421
1422 return false;
1423}
1424
1426{
1427 for (SpellEffectInfo const& effect : GetEffects())
1428 if (effect.IsAura(aura))
1429 return true;
1430
1431 return false;
1432}
1433
1435{
1436 for (SpellEffectInfo const& effect : GetEffects())
1437 if (effect.IsAreaAuraEffect())
1438 return true;
1439
1440 return false;
1441}
1442
1444{
1445 for (SpellEffectInfo const& effect : GetEffects())
1446 {
1447 if (effect.IsEffect())
1448 {
1449 switch (effect.Effect)
1450 {
1459 continue;
1460 default:
1461 return false;
1462 }
1463 }
1464 }
1465
1466 return true;
1467}
1468
1470{
1471 for (SpellEffectInfo const& effect : GetEffects())
1472 if (effect.TargetA.GetTarget() == target || effect.TargetB.GetTarget() == target)
1473 return true;
1474
1475 return false;
1476}
1477
1478bool SpellInfo::CanBeInterrupted(WorldObject const* interruptCaster, Unit const* interruptTarget, bool ignoreImmunity /*= false*/) const
1479{
1484 || (interruptCaster && interruptCaster->IsUnit() && interruptCaster->ToUnit()->HasAuraTypeWithMiscvalue(SPELL_AURA_ALLOW_INTERRUPT_SPELL, Id))
1485 || ((!(interruptTarget->GetMechanicImmunityMask() & (1 << MECHANIC_INTERRUPT)) || ignoreImmunity)
1488}
1489
1491{
1493}
1494
1496{
1497 if (GetEffects().size() < 2)
1498 return false;
1499
1503 || Id == 64323;
1504}
1505
1507{
1509}
1510
1512{
1513 for (SpellEffectInfo const& effect : GetEffects())
1514 {
1515 if (effect.Effect == SPELL_EFFECT_SKILL)
1516 {
1517 uint32 skill = effect.MiscValue;
1518
1519 if (IsProfessionSkill(skill))
1520 return true;
1521 }
1522 }
1523 return false;
1524}
1525
1527{
1528 for (SpellEffectInfo const& effect : GetEffects())
1529 {
1530 if (effect.Effect == SPELL_EFFECT_SKILL)
1531 {
1532 uint32 skill = effect.MiscValue;
1533
1534 if (IsPrimaryProfessionSkill(skill))
1535 return true;
1536 }
1537 }
1538 return false;
1539}
1540
1542{
1543 return IsPrimaryProfession() && GetRank() == 1;
1544}
1545
1547{
1548 SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(Id);
1549
1550 for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
1551 if (_spell_idx->second->SkillLine == skillType)
1552 return true;
1553
1554 return false;
1555}
1556
1558{
1559 for (SpellEffectInfo const& effect : GetEffects())
1560 if (effect.IsEffect() && (effect.IsTargetingArea() || effect.IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) || effect.IsAreaAuraEffect()))
1561 return true;
1562
1563 return false;
1564}
1565
1566// checks if spell targets are selected from area, doesn't include spell effects in check (like area wide auras for example)
1568{
1569 for (SpellEffectInfo const& effect : GetEffects())
1570 if (effect.IsEffect() && effect.IsTargetingArea())
1571 return true;
1572
1573 return false;
1574}
1575
1577{
1579}
1580
1581bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const
1582{
1584 return true;
1585
1586 /*
1587 for (SpellEffectInfo const& effect : GetEffects())
1588 {
1589 if (effect.IsEffect())
1590 {
1591 if (effect.TargetA.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CHANNEL
1592 || effect.TargetB.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CHANNEL)
1593 return true;
1594 }
1595 }
1596 */
1597
1598 if (triggeringSpell->IsChanneled())
1599 {
1600 uint32 mask = 0;
1601 for (SpellEffectInfo const& effect : GetEffects())
1602 {
1603 if (effect.TargetA.GetTarget() != TARGET_UNIT_CASTER && effect.TargetA.GetTarget() != TARGET_DEST_CASTER
1604 && effect.TargetB.GetTarget() != TARGET_UNIT_CASTER && effect.TargetB.GetTarget() != TARGET_DEST_CASTER)
1605 {
1606 mask |= effect.GetProvidedTargetMask();
1607 }
1608 }
1609
1610 if (mask & TARGET_FLAG_UNIT_MASK)
1611 return true;
1612 }
1613
1614 return false;
1615}
1616
1618{
1620}
1621
1623{
1624 if (IsPassive())
1625 return false;
1627 return false;
1628 return true;
1629}
1630
1632{
1634}
1635
1637{
1638 if (IsPassive())
1639 return false;
1640
1641 // All stance spells. if any better way, change it.
1642 for (SpellEffectInfo const& effect : GetEffects())
1643 {
1644 switch (SpellFamilyName)
1645 {
1647 // Paladin aura Spell
1648 if (effect.Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID)
1649 return false;
1650 break;
1651 case SPELLFAMILY_DRUID:
1652 // Druid form Spell
1653 if (effect.Effect == SPELL_EFFECT_APPLY_AURA &&
1654 effect.ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT)
1655 return false;
1656 break;
1657 }
1658 }
1659
1660 return true;
1661}
1662
1664{
1666}
1667
1669{
1670 return IsPassive() || Id == 55849 || Id == 40075 || Id == 44413; // Power Spark, Fel Flak Fire, Incanter's Absorption
1671}
1672
1674{
1677}
1678
1680{
1682 return true;
1683
1684 SpellCategoryEntry const* category = sSpellCategoryStore.LookupEntry(CategoryId);
1685 return category && category->Flags & SPELL_CATEGORY_FLAG_COOLDOWN_STARTS_ON_EVENT;
1686}
1687
1689{
1691}
1692
1694{
1696}
1697
1699{
1701 return true;
1702
1703 for (SpellEffectInfo const& effect : GetEffects())
1704 {
1705 if (!effect.IsEffect())
1706 continue;
1707
1708 if (effect.TargetA.GetObjectType() == TARGET_OBJECT_TYPE_CORPSE || effect.TargetB.GetObjectType() == TARGET_OBJECT_TYPE_CORPSE)
1709 return true;
1710 }
1711
1712 return false;
1713}
1714
1716{
1717 for (SpellEffectInfo const& effect : GetEffects())
1718 {
1719 switch (effect.TargetA.GetCheckType())
1720 {
1721 case TARGET_CHECK_PARTY:
1722 case TARGET_CHECK_RAID:
1724 return true;
1725 default:
1726 break;
1727 }
1728 }
1729
1730 return false;
1731}
1732
1733bool SpellInfo::CanBeUsedInCombat(Unit const* caster) const
1734{
1737}
1738
1740{
1741 return NegativeEffects.none();
1742}
1743
1745{
1746 return !NegativeEffects.test(effIndex);
1747}
1748
1750{
1752}
1753
1755{
1757}
1758
1760{
1762}
1763
1765{
1766 return (SpellFamilyName == SPELLFAMILY_HUNTER && !(SpellFamilyFlags[1] & 0x10000000)) // for 53352, cannot find better way
1769}
1770
1772{
1774}
1775
1777{
1778 return !EmpowerStageThresholds.empty();
1779}
1780
1782{
1784}
1785
1787{
1788 return Speed > 0.0f || LaunchDelay > 0.0f;
1789}
1790
1792{
1793 WeaponAttackType result;
1794 switch (DmgClass)
1795 {
1798 result = OFF_ATTACK;
1799 else
1800 result = BASE_ATTACK;
1801 break;
1804 break;
1805 default:
1806 // Wands
1808 result = RANGED_ATTACK;
1809 else
1810 result = BASE_ATTACK;
1811 break;
1812 }
1813
1814 return result;
1815}
1816
1818{
1819 // item neutral spell
1820 if (EquippedItemClass == -1)
1821 return true;
1822
1823 // item dependent spell
1824 if (item && item->IsFitToSpellRequirements(this))
1825 return true;
1826
1827 return false;
1828}
1829
1830bool SpellInfo::IsAffected(uint32 familyName, flag128 const& familyFlags) const
1831{
1832 if (!familyName)
1833 return true;
1834
1835 if (familyName != SpellFamilyName)
1836 return false;
1837
1838 if (familyFlags && !(familyFlags & SpellFamilyFlags))
1839 return false;
1840
1841 return true;
1842}
1843
1845{
1847}
1848
1850{
1851 if (!IsAffectedBySpellMods())
1852 return false;
1853
1854 SpellInfo const* affectSpell = sSpellMgr->GetSpellInfo(mod->spellId, Difficulty);
1855 if (!affectSpell)
1856 return false;
1857
1858 switch (mod->type)
1859 {
1860 case SPELLMOD_FLAT:
1861 case SPELLMOD_PCT:
1862 // TEMP: dont use IsAffected - !familyName and !familyFlags are not valid options for spell mods
1863 // TODO: investigate if the !familyName and !familyFlags conditions are even valid for all other (nonmod) uses of SpellInfo::IsAffected
1864 return affectSpell->SpellFamilyName == SpellFamilyName && static_cast<SpellModifierByClassMask const*>(mod)->mask & SpellFamilyFlags;
1866 return HasLabel(static_cast<SpellFlatModifierByLabel const*>(mod)->value.LabelID);
1867 case SPELLMOD_LABEL_PCT:
1868 return HasLabel(static_cast<SpellPctModifierByLabel const*>(mod)->value.LabelID);
1869 default:
1870 break;
1871 }
1872
1873 return false;
1874}
1875
1876bool SpellInfo::CanPierceImmuneAura(SpellInfo const* auraSpellInfo) const
1877{
1878 // Dispels other auras on immunity, check if this spell makes the unit immune to aura
1880 return true;
1881
1882 return false;
1883}
1884
1885bool SpellInfo::CanDispelAura(SpellInfo const* auraSpellInfo) const
1886{
1887 // These auras (like Divine Shield) can't be dispelled
1888 if (auraSpellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES))
1889 return false;
1890
1891 return true;
1892}
1893
1895{
1896 // all other single target spells have if it has AttributesEx5
1898 return true;
1899
1900 return false;
1901}
1902
1904{
1905 SpellSpecificType spellSpec1 = GetSpellSpecific();
1906 SpellSpecificType spellSpec2 = spellInfo->GetSpellSpecific();
1907 switch (spellSpec1)
1908 {
1919 return spellSpec1 == spellSpec2;
1921 return spellSpec2 == SPELL_SPECIFIC_FOOD
1922 || spellSpec2 == SPELL_SPECIFIC_FOOD_AND_DRINK;
1924 return spellSpec2 == SPELL_SPECIFIC_DRINK
1925 || spellSpec2 == SPELL_SPECIFIC_FOOD_AND_DRINK;
1927 return spellSpec2 == SPELL_SPECIFIC_FOOD
1928 || spellSpec2 == SPELL_SPECIFIC_DRINK
1929 || spellSpec2 == SPELL_SPECIFIC_FOOD_AND_DRINK;
1930 default:
1931 return false;
1932 }
1933}
1934
1936{
1937 SpellSpecificType spellSpec = GetSpellSpecific();
1938 switch (spellSpec)
1939 {
1947 return spellSpec == spellInfo->GetSpellSpecific();
1948 default:
1949 return false;
1950 }
1951}
1952
1954{
1955 // talents that learn spells can have stance requirements that need ignore
1956 // (this requirement only for client-side stance show in talent description)
1957 /* TODO: 6.x fix this in proper way (probably spell flags/attributes?)
1958 if (GetTalentSpellCost(Id) > 0 && HasEffect(SPELL_EFFECT_LEARN_SPELL))
1959 return SPELL_CAST_OK;*/
1960
1961 //if (HasAttribute(SPELL_ATTR13_ACTIVATES_REQUIRED_SHAPESHIFT))
1962 // return SPELL_CAST_OK;
1963
1964 uint64 stanceMask = (form ? UI64LIT(1) << (form - 1) : 0);
1965
1966 if (stanceMask & StancesNot) // can explicitly not be cast in this stance
1968
1969 if (stanceMask & Stances) // can explicitly be cast in this stance
1970 return SPELL_CAST_OK;
1971
1972 bool actAsShifted = false;
1973 SpellShapeshiftFormEntry const* shapeInfo = nullptr;
1974 if (form > 0)
1975 {
1976 shapeInfo = sSpellShapeshiftFormStore.LookupEntry(form);
1977 if (!shapeInfo)
1978 {
1979 TC_LOG_ERROR("spells", "GetErrorAtShapeshiftedCast: unknown shapeshift {}", form);
1980 return SPELL_CAST_OK;
1981 }
1982 actAsShifted = !shapeInfo->GetFlags().HasFlag(SpellShapeshiftFormFlags::Stance);
1983 }
1984
1985 if (actAsShifted)
1986 {
1987 if (HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFTED) || (shapeInfo && shapeInfo->GetFlags().HasFlag(SpellShapeshiftFormFlags::CanOnlyCastShapeshiftSpells))) // not while shapeshifted
1989 else if (Stances != 0) // needs other shapeshift
1991 }
1992 else
1993 {
1994 // needs shapeshift
1997 }
1998
1999 return SPELL_CAST_OK;
2000}
2001
2002SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player) const
2003{
2004 // normal case
2005 if (RequiredAreasID > 0)
2006 {
2007 bool found = false;
2008 std::vector<uint32> areaGroupMembers = sDB2Manager.GetAreasForGroup(RequiredAreasID);
2009 for (uint32 areaId : areaGroupMembers)
2010 {
2011 if (DB2Manager::IsInArea(area_id, areaId))
2012 {
2013 found = true;
2014 break;
2015 }
2016 }
2017
2018 if (!found)
2020 }
2021
2022 // continent limitation (virtual continent)
2024 {
2026 if (player && player->HasAuraType(SPELL_AURA_MOUNT_RESTRICTIONS))
2027 {
2028 for (AuraEffect const* auraEffect : player->GetAuraEffectsByType(SPELL_AURA_MOUNT_RESTRICTIONS))
2029 mountFlags |= AreaMountFlags(auraEffect->GetMiscValue());
2030 }
2031 else if (AreaTableEntry const* areaTable = sAreaTableStore.LookupEntry(area_id))
2032 mountFlags = areaTable->GetMountFlags();
2033
2034 if (!(mountFlags.HasFlag(AreaMountFlags::AllowFlyingMounts)))
2036
2037 if (player && !ConditionMgr::IsPlayerMeetingCondition(player, 72968)) // Hardcoded PlayerCondition id for attribute check in client
2039 }
2040
2041 // raid instance limitation
2043 {
2044 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2045 if (!mapEntry || mapEntry->IsRaid())
2047 }
2048
2050 {
2051 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2052 if (!mapEntry || !mapEntry->IsDungeon())
2054 }
2055
2057 {
2058 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2059 if (!mapEntry || mapEntry->IsBattleground())
2061 }
2062
2063 // DB base check (if non empty then must fit at least single for allow)
2064 SpellAreaMapBounds saBounds = sSpellMgr->GetSpellAreaMapBounds(Id);
2065 if (saBounds.first != saBounds.second)
2066 {
2067 for (SpellAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
2068 {
2069 if (itr->second.IsFitToRequirements(player, zone_id, area_id))
2070 return SPELL_CAST_OK;
2071 }
2073 }
2074
2075 // bg spell checks
2076 switch (Id)
2077 {
2078 case 23333: // Warsong Flag
2079 case 23335: // Silverwing Flag
2080 return map_id == 489 && player && player->InBattleground() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
2081 case 2584: // Waiting to Resurrect
2082 case 42792: // Recently Dropped Flag
2083 case 43681: // Inactive
2084 case 44535: // Spirit Heal (mana)
2085 {
2086 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2087 if (!mapEntry)
2089
2090 return zone_id == AREA_WINTERGRASP || (mapEntry->IsBattleground() && player && player->InBattleground()) ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
2091 }
2092 case 44521: // Preparation
2093 {
2094 if (!player)
2096
2097 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2098 if (!mapEntry)
2100
2101 if (!mapEntry->IsBattleground())
2103
2104 Battleground* bg = player->GetBattleground();
2106 }
2107 case 32724: // Gold Team (Alliance)
2108 case 32725: // Green Team (Alliance)
2109 case 35774: // Gold Team (Horde)
2110 case 35775: // Green Team (Horde)
2111 {
2112 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2113 if (!mapEntry)
2115
2116 return mapEntry->IsBattleArena() && player && player->InBattleground() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
2117 }
2118 case 32727: // Arena Preparation
2119 {
2120 if (!player)
2122
2123 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2124 if (!mapEntry)
2126
2127 if (!mapEntry->IsBattleArena())
2129
2130 Battleground* bg = player->GetBattleground();
2132 }
2133 }
2134
2135 // aura limitations
2136 if (player)
2137 {
2138 for (SpellEffectInfo const& effect : GetEffects())
2139 {
2140 if (!effect.IsAura())
2141 continue;
2142
2143 switch (effect.ApplyAuraName)
2144 {
2146 {
2147 if (SpellShapeshiftFormEntry const* spellShapeshiftForm = sSpellShapeshiftFormStore.LookupEntry(effect.MiscValue))
2148 if (uint32 mountType = spellShapeshiftForm->MountTypeID)
2149 if (!player->GetMountCapability(mountType))
2150 return SPELL_FAILED_NOT_HERE;
2151 break;
2152 }
2153 case SPELL_AURA_MOUNTED:
2154 {
2155 uint32 mountType = effect.MiscValueB;
2156 if (MountEntry const* mountEntry = sDB2Manager.GetMount(Id))
2157 mountType = mountEntry->MountTypeID;
2158 if (mountType && !player->GetMountCapability(mountType))
2159 return SPELL_FAILED_NOT_HERE;
2160 break;
2161 }
2162 default:
2163 break;
2164 }
2165 }
2166 }
2167
2168 return SPELL_CAST_OK;
2169}
2170
2171SpellCastResult SpellInfo::CheckTarget(WorldObject const* caster, WorldObject const* target, bool implicit /*= true*/) const
2172{
2173 if (HasAttribute(SPELL_ATTR1_EXCLUDE_CASTER) && caster == target)
2175
2176 // check visibility - ignore invisibility/stealth for implicit (area) targets
2177 if (!HasAttribute(SPELL_ATTR6_IGNORE_PHASE_SHIFT) && !caster->CanSeeOrDetect(target, implicit))
2179
2180 Unit const* unitTarget = target->ToUnit();
2181
2183 {
2184 auto getCreatorOrSelf = [](WorldObject const* obj)
2185 {
2186 ObjectGuid creator = obj->GetCreatorGUID();
2187 if (creator.IsEmpty())
2188 creator = obj->GetGUID();
2189
2190 return creator;
2191 };
2192 if (getCreatorOrSelf(caster) != getCreatorOrSelf(target))
2194 }
2195
2196 // creature/player specific target checks
2197 if (unitTarget)
2198 {
2199 // spells cannot be cast if target has a pet in combat either
2202
2203 // only spells with SPELL_ATTR3_ONLY_TARGET_GHOSTS can target ghosts
2205 {
2208 else
2210 }
2211
2212 if (caster != unitTarget)
2213 {
2214 if (caster->GetTypeId() == TYPEID_PLAYER)
2215 {
2216 // Do not allow these spells to target creatures not tapped by us (Banish, Polymorph, many quest spells)
2218 if (Creature const* targetCreature = unitTarget->ToCreature())
2219 if (targetCreature->hasLootRecipient() && !targetCreature->isTappedBy(caster->ToPlayer()))
2221
2223 {
2224 Creature const* targetCreature = unitTarget->ToCreature();
2225 if (!targetCreature)
2227
2228 if (!targetCreature->CanHaveLoot() || !LootTemplates_Pickpocketing.HaveLootFor(targetCreature->GetCreatureDifficulty()->PickPocketLootID))
2230 }
2231
2232 // Not allow disarm unarmed player
2234 {
2235 if (unitTarget->GetTypeId() == TYPEID_PLAYER)
2236 {
2237 Player const* player = unitTarget->ToPlayer();
2238 if (!player->GetWeaponForAttack(BASE_ATTACK) || !player->IsUseEquipedWeapon(true))
2240 }
2241 else if (!unitTarget->GetVirtualItemId(0))
2243 }
2244 }
2245 }
2246
2248 if (!unitTarget->IsSummon() || unitTarget->ToTempSummon()->GetSummonerGUID() != caster->GetGUID())
2250
2254
2259 }
2260 // corpse specific target checks
2261 else if (Corpse const* corpseTarget = target->ToCorpse())
2262 {
2263 // cannot target bare bones
2264 if (corpseTarget->GetType() == CORPSE_BONES)
2266 // we have to use owner for some checks (aura preventing resurrection for example)
2267 if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()))
2268 unitTarget = owner;
2269 // we're not interested in corpses without owner
2270 else
2272 }
2273 // other types of objects - always valid
2274 else return SPELL_CAST_OK;
2275
2276 // corpseOwner and unit specific target checks
2277 if (!unitTarget->IsPlayer())
2278 {
2281
2284 }
2287
2288 if (!IsAllowingDeadTarget() && !unitTarget->IsAlive())
2290
2291 // check this flag only for implicit targets (chain and area), allow to explicitly target units for spells like Shield of Righteousness
2294
2295 // checked in Unit::IsValidAttack/AssistTarget, shouldn't be checked for ENTRY targets
2296 //if (!HasAttribute(SPELL_ATTR6_CAN_TARGET_UNTARGETABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNINTERACTIBLE))
2297 // return SPELL_FAILED_BAD_TARGETS;
2298
2299 if (!CheckTargetCreatureType(unitTarget))
2300 {
2301 if (target->GetTypeId() == TYPEID_PLAYER)
2303 else
2305 }
2306
2307 // check GM mode and GM invisibility - only for player casts (npc casts are controlled by AI) and negative spells
2308 if (unitTarget != caster && (caster->GetAffectingPlayer() || !IsPositive()) && unitTarget->GetTypeId() == TYPEID_PLAYER)
2309 {
2310 if (!unitTarget->ToPlayer()->IsVisible())
2312
2313 if (unitTarget->ToPlayer()->IsGameMaster())
2315 }
2316
2317 // not allow casting on flying player
2320
2321 /* TARGET_UNIT_MASTER gets blocked here for passengers, because the whole idea of this check is to
2322 not allow passengers to be implicitly hit by spells, however this target type should be an exception,
2323 if this is left it kills spells that award kill credit from vehicle to master (few spells),
2324 the use of these 2 covers passenger target check, logically, if vehicle cast this to master it should always hit
2325 him, because it would be it's passenger, there's no such case where this gets to fail legitimacy, this problem
2326 cannot be solved from within the check in other way since target type cannot be called for the spell currently
2327 Spell examples: [ID - 52864 Devour Water, ID - 52862 Devour Wind, ID - 49370 Wyrmrest Defender: Destabilize Azure Dragonshrine Effect] */
2328 if (Unit const* unitCaster = caster->ToUnit())
2329 {
2330 if (!unitCaster->IsVehicle() && !(unitCaster->GetCharmerOrOwner() == target))
2331 {
2332 if (TargetAuraState && !unitTarget->HasAuraState(AuraStateType(TargetAuraState), this, unitCaster))
2334
2335 if (ExcludeTargetAuraState && unitTarget->HasAuraState(AuraStateType(ExcludeTargetAuraState), this, unitCaster))
2337 }
2338 }
2339
2340 if (TargetAuraSpell && !unitTarget->HasAura(TargetAuraSpell))
2342
2345
2349
2351 if (Map* map = caster->GetMap())
2352 if (InstanceMap* iMap = map->ToInstanceMap())
2353 if (InstanceScript* instance = iMap->GetInstanceScript())
2354 if (instance->GetCombatResurrectionCharges() == 0 && instance->IsEncounterInProgress())
2356
2357 return SPELL_CAST_OK;
2358}
2359
2360SpellCastResult SpellInfo::CheckExplicitTarget(WorldObject const* caster, WorldObject const* target, Item const* itemTarget /*= nullptr*/) const
2361{
2362 uint32 neededTargets = GetExplicitTargetMask();
2363 if (!target)
2364 {
2366 if (!(neededTargets & TARGET_FLAG_GAMEOBJECT_ITEM) || !itemTarget)
2368 return SPELL_CAST_OK;
2369 }
2370
2371 if (Unit const* unitTarget = target->ToUnit())
2372 {
2374 {
2375 Unit const* unitCaster = caster->ToUnit();
2376 if (neededTargets & TARGET_FLAG_UNIT_ENEMY)
2377 if (caster->IsValidAttackTarget(unitTarget, this))
2378 return SPELL_CAST_OK;
2379 if ((neededTargets & TARGET_FLAG_UNIT_ALLY)
2380 || ((neededTargets & TARGET_FLAG_UNIT_PARTY) && unitCaster && unitCaster->IsInPartyWith(unitTarget))
2381 || ((neededTargets & TARGET_FLAG_UNIT_RAID) && unitCaster && unitCaster->IsInRaidWith(unitTarget)))
2382 if (caster->IsValidAssistTarget(unitTarget, this))
2383 return SPELL_CAST_OK;
2384 if ((neededTargets & TARGET_FLAG_UNIT_MINIPET) && unitCaster)
2385 if (unitTarget->GetGUID() == unitCaster->GetCritterGUID())
2386 return SPELL_CAST_OK;
2387 if ((neededTargets & TARGET_FLAG_UNIT_PASSENGER) && unitCaster)
2388 if (unitTarget->IsOnVehicle(unitCaster))
2389 return SPELL_CAST_OK;
2391 }
2392 }
2393 return SPELL_CAST_OK;
2394}
2395
2397{
2398 // All creatures should be able to cast as passengers freely, restriction and attribute are only for players
2399 if (caster->GetTypeId() != TYPEID_PLAYER)
2400 return SPELL_CAST_OK;
2401
2402 Vehicle* vehicle = caster->GetVehicle();
2403 if (vehicle)
2404 {
2405 uint16 checkMask = 0;
2406 for (SpellEffectInfo const& effect : GetEffects())
2407 {
2408 if (effect.IsAura(SPELL_AURA_MOD_SHAPESHIFT))
2409 {
2410 SpellShapeshiftFormEntry const* shapeShiftFromEntry = sSpellShapeshiftFormStore.LookupEntry(effect.MiscValue);
2411 if (shapeShiftFromEntry && (shapeShiftFromEntry->Flags & 1) == 0) // unk flag
2412 checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED;
2413 break;
2414 }
2415 }
2416
2419
2420 if (!checkMask)
2421 checkMask = VEHICLE_SEAT_FLAG_CAN_ATTACK;
2422
2423 VehicleSeatEntry const* vehicleSeat = vehicle->GetSeatForPassenger(caster);
2425 && (vehicleSeat->Flags & checkMask) != checkMask)
2427
2428 // Can only summon uncontrolled minions/guardians when on controlled vehicle
2430 {
2431 for (SpellEffectInfo const& effect : GetEffects())
2432 {
2433 if (!effect.IsEffect(SPELL_EFFECT_SUMMON))
2434 continue;
2435
2436 SummonPropertiesEntry const* props = sSummonPropertiesStore.LookupEntry(effect.MiscValueB);
2437 if (props && props->Control != SUMMON_CATEGORY_WILD)
2439 }
2440 }
2441 }
2442
2443 return SPELL_CAST_OK;
2444}
2445
2447{
2448 // Curse of Doom & Exorcism: not find another way to fix spell target check :/
2450 {
2451 // not allow cast at player
2452 if (target->GetTypeId() == TYPEID_PLAYER)
2453 return false;
2454 else
2455 return true;
2456 }
2457
2458 // if target is magnet (i.e Grounding Totem) the check is skipped
2459 if (target->IsMagnet())
2460 return true;
2461
2462 uint32 creatureType = target->GetCreatureTypeMask();
2463 return !TargetCreatureType || !creatureType || (creatureType & TargetCreatureType) || target->HasAuraType(SPELL_AURA_IGNORE_SPELL_CREATURE_TYPE_REQUIREMENTS);
2464}
2465
2467{
2469}
2470
2472{
2473 uint64 mask = 0;
2474 if (Mechanic)
2475 mask |= UI64LIT(1) << Mechanic;
2476
2477 for (SpellEffectInfo const& effect : GetEffects())
2478 if (effect.IsEffect() && effect.Mechanic)
2479 mask |= UI64LIT(1) << effect.Mechanic;
2480
2481 return mask;
2482}
2483
2485{
2486 uint64 mask = 0;
2487 if (Mechanic)
2488 mask |= UI64LIT(1) << Mechanic;
2489
2490 if (GetEffect(effIndex).IsEffect() && GetEffect(effIndex).Mechanic)
2491 mask |= UI64LIT(1) << GetEffect(effIndex).Mechanic;
2492
2493 return mask;
2494}
2495
2497{
2498 uint64 mask = 0;
2499 if (Mechanic)
2500 mask |= UI64LIT(1) << Mechanic;
2501
2502 for (SpellEffectInfo const& effect : GetEffects())
2503 if ((effectMask & (1 << effect.EffectIndex)) && effect.Mechanic)
2504 mask |= UI64LIT(1) << effect.Mechanic;
2505
2506 return mask;
2507}
2508
2510{
2511 if (GetEffect(effIndex).IsEffect() && GetEffect(effIndex).Mechanic)
2512 return GetEffect(effIndex).Mechanic;
2513
2514 if (Mechanic)
2515 return Mechanics(Mechanic);
2516
2517 return MECHANIC_NONE;
2518}
2519
2521{
2523}
2524
2526{
2527 // If dispel all
2528 if (type == DISPEL_ALL)
2529 return DISPEL_ALL_MASK;
2530 else
2531 return uint32(1 << type);
2532}
2533
2535{
2536 return ExplicitTargetMask;
2537}
2538
2540{
2541 return _auraState;
2542}
2543
2545{
2546 _auraState = [this]()->AuraStateType
2547 {
2548 // Faerie Fire (Feral)
2549 if (GetCategory() == 1133)
2551
2552 // Swiftmend state on Regrowth, Rejuvenation, Wild Growth
2553 if (SpellFamilyName == SPELLFAMILY_DRUID && (SpellFamilyFlags[0] & 0x50 || SpellFamilyFlags[1] & 0x4000000))
2555
2556 // Deadly poison aura state
2557 if (SpellFamilyName == SPELLFAMILY_ROGUE && SpellFamilyFlags[0] & 0x10000)
2559
2560 // Enrage aura state
2561 if (Dispel == DISPEL_ENRAGE)
2562 return AURA_STATE_ENRAGED;
2563
2564 // Bleeding aura state
2566 return AURA_STATE_BLEED;
2567
2569 for (SpellEffectInfo const& effect : GetEffects())
2570 if (effect.IsAura(SPELL_AURA_MOD_STUN) || effect.IsAura(SPELL_AURA_MOD_ROOT) || effect.IsAura(SPELL_AURA_MOD_ROOT_2))
2571 return AURA_STATE_FROZEN;
2572
2573 switch (Id)
2574 {
2575 case 1064: // Dazed
2576 return AURA_STATE_DAZED;
2577 case 32216: // Victorious
2578 return AURA_STATE_VICTORIOUS;
2579 case 71465: // Divine Surge
2580 case 50241: // Evasive Charges
2581 case 81262: // Efflorescence
2583 case 6950: // Faerie Fire
2584 case 9806: // Phantom Strike
2585 case 9991: // Touch of Zanzil
2586 case 13424: // Faerie Fire
2587 case 13752: // Faerie Fire
2588 case 16432: // Plague Mist
2589 case 20656: // Faerie Fire
2590 case 25602: // Faerie Fire
2591 case 32129: // Faerie Fire
2592 case 35325: // Glowing Blood
2593 case 35328: // Lambent Blood
2594 case 35329: // Vibrant Blood
2595 case 35331: // Black Blood
2596 case 49163: // Perpetual Instability
2597 case 65863: // Faerie Fire
2598 case 79559: // Luxscale Light
2599 case 82855: // Dazzling
2600 case 102953: // In the Rumpus
2601 case 127907: // Phosphorescence
2602 case 127913: // Phosphorescence
2603 case 129007: // Zijin Sting
2604 case 130159: // Fae Touch
2605 case 142537: // Spotter Smoke
2606 case 168455: // Spotted!
2607 case 176905: // Super Sticky Glitter Bomb
2608 case 189502: // Marked
2609 case 201785: // Intruder Alert!
2610 case 201786: // Intruder Alert!
2611 case 201935: // Spotted!
2612 case 239233: // Smoke Bomb
2613 case 319400: // Glitter Burst
2614 case 321470: // Dimensional Shifter Mishap
2615 case 331134: // Spotted
2617 default:
2618 break;
2619 }
2620
2622 return AURA_STATE_BANISHED;
2623
2624 return AURA_STATE_NONE;
2625 }();
2626}
2627
2629{
2630 return _spellSpecific;
2631};
2632
2634{
2636 {
2637 switch (SpellFamilyName)
2638 {
2640 {
2641 // Food / Drinks (mostly)
2643 {
2644 bool food = false;
2645 bool drink = false;
2646 for (SpellEffectInfo const& effect : GetEffects())
2647 {
2648 if (!effect.IsAura())
2649 continue;
2650 switch (effect.ApplyAuraName)
2651 {
2652 // Food
2655 food = true;
2656 break;
2657 // Drink
2660 drink = true;
2661 break;
2662 default:
2663 break;
2664 }
2665 }
2666
2667 if (food && drink)
2669 else if (food)
2670 return SPELL_SPECIFIC_FOOD;
2671 else if (drink)
2672 return SPELL_SPECIFIC_DRINK;
2673 }
2674 // scrolls effects
2675 else
2676 {
2677 SpellInfo const* firstRankSpellInfo = GetFirstRankSpell();
2678 switch (firstRankSpellInfo->Id)
2679 {
2680 case 8118: // Strength
2681 case 8099: // Stamina
2682 case 8112: // Spirit
2683 case 8096: // Intellect
2684 case 8115: // Agility
2685 case 8091: // Armor
2686 return SPELL_SPECIFIC_SCROLL;
2687 default:
2688 break;
2689 }
2690 }
2691 break;
2692 }
2693 case SPELLFAMILY_MAGE:
2694 {
2695 // family flags 18(Molten), 25(Frost/Ice), 28(Mage)
2696 if (SpellFamilyFlags[0] & 0x12040000)
2698
2699 // Arcane brillance and Arcane intelect (normal check fails because of flags difference)
2700 if (SpellFamilyFlags[0] & 0x400)
2702
2703 if ((SpellFamilyFlags[0] & 0x1000000) && GetEffect(EFFECT_0).IsAura(SPELL_AURA_MOD_CONFUSE))
2705
2706 break;
2707 }
2709 {
2710 if (Id == 12292) // Death Wish
2712
2713 break;
2714 }
2716 {
2717 // Warlock (Bane of Doom | Bane of Agony | Bane of Havoc)
2718 if (Id == 603 || Id == 980 || Id == 80240)
2719 return SPELL_SPECIFIC_BANE;
2720
2721 // only warlock curses have this
2722 if (Dispel == DISPEL_CURSE)
2723 return SPELL_SPECIFIC_CURSE;
2724
2725 // Warlock (Demon Armor | Demon Skin | Fel Armor)
2726 if (SpellFamilyFlags[1] & 0x20000020 || SpellFamilyFlags[2] & 0x00000010)
2728 break;
2729 }
2730 case SPELLFAMILY_PRIEST:
2731 {
2732 // Divine Spirit and Prayer of Spirit
2733 if (SpellFamilyFlags[0] & 0x20)
2735
2736 break;
2737 }
2738 case SPELLFAMILY_HUNTER:
2739 {
2740 // only hunter stings have this
2741 if (Dispel == DISPEL_POISON)
2742 return SPELL_SPECIFIC_STING;
2743
2744 // only hunter aspects have this (but not all aspects in hunter family)
2745 if (SpellFamilyFlags & flag128(0x00200000, 0x00000000, 0x00001010, 0x00000000))
2746 return SPELL_SPECIFIC_ASPECT;
2747
2748 break;
2749 }
2751 {
2752 // Collection of all the seal family flags. No other paladin spell has any of those.
2753 if (SpellFamilyFlags[1] & 0xA2000800)
2754 return SPELL_SPECIFIC_SEAL;
2755
2756 if (SpellFamilyFlags[0] & 0x00002190)
2757 return SPELL_SPECIFIC_HAND;
2758
2759 // only paladin auras have this (for palaldin class family)
2760 switch (Id)
2761 {
2762 case 465: // Devotion Aura
2763 case 32223: // Crusader Aura
2764 case 183435: // Retribution Aura
2765 case 317920: // Concentration Aura
2766 return SPELL_SPECIFIC_AURA;
2767 default:
2768 break;
2769 }
2770
2771 break;
2772 }
2773 case SPELLFAMILY_SHAMAN:
2774 {
2775 // family flags 10 (Lightning), 42 (Earth), 37 (Water), proc shield from T2 8 pieces bonus
2776 if (SpellFamilyFlags[1] & 0x420
2777 || SpellFamilyFlags[0] & 0x00000400
2778 || Id == 23552)
2780
2781 break;
2782 }
2784 if (Id == 48266 || Id == 48263 || Id == 48265)
2786 break;
2787 }
2788
2789 for (SpellEffectInfo const& effect : GetEffects())
2790 {
2791 if (effect.IsEffect(SPELL_EFFECT_APPLY_AURA))
2792 {
2793 switch (effect.ApplyAuraName)
2794 {
2799 return SPELL_SPECIFIC_CHARM;
2802 if (Id == 30645) // Gas Cloud Tracking
2803 return SPELL_SPECIFIC_NORMAL;
2804 [[fallthrough]];
2808 default:
2809 break;
2810 }
2811 }
2812 }
2813 return SPELL_SPECIFIC_NORMAL;
2814 }();
2815}
2816
2818{
2819 auto diminishingGroupCompute = [this]() -> DiminishingGroup
2820 {
2821 if (IsPositive())
2822 return DIMINISHING_NONE;
2823
2825 return DIMINISHING_TAUNT;
2826
2827 switch (Id)
2828 {
2829 case 20549: // War Stomp (Racial - Tauren)
2830 case 24394: // Intimidation
2831 case 118345: // Pulverize (Primal Earth Elemental)
2832 case 118905: // Static Charge (Capacitor Totem)
2833 return DIMINISHING_STUN;
2834 case 107079: // Quaking Palm
2836 case 155145: // Arcane Torrent (Racial - Blood Elf)
2837 return DIMINISHING_SILENCE;
2838 case 108199: // Gorefiend's Grasp
2839 case 191244: // Sticky Bomb
2841 default:
2842 break;
2843 }
2844
2845 // Explicit Diminishing Groups
2846 switch (SpellFamilyName)
2847 {
2849 // Frost Tomb
2850 if (Id == 48400)
2851 return DIMINISHING_NONE;
2852 // Gnaw
2853 else if (Id == 47481)
2854 return DIMINISHING_STUN;
2855 // ToC Icehowl Arctic Breath
2856 else if (Id == 66689)
2857 return DIMINISHING_NONE;
2858 // Black Plague
2859 else if (Id == 64155)
2860 return DIMINISHING_NONE;
2861 // Screams of the Dead (King Ymiron)
2862 else if (Id == 51750)
2863 return DIMINISHING_NONE;
2864 // Crystallize (Keristrasza heroic)
2865 else if (Id == 48179)
2866 return DIMINISHING_NONE;
2867 break;
2868 case SPELLFAMILY_MAGE:
2869 {
2870 // Frost Nova -- 122
2871 if (SpellFamilyFlags[0] & 0x40)
2872 return DIMINISHING_ROOT;
2873 // Freeze (Water Elemental) -- 33395
2874 if (SpellFamilyFlags[2] & 0x200)
2875 return DIMINISHING_ROOT;
2876
2877 // Dragon's Breath -- 31661
2878 if (SpellFamilyFlags[0] & 0x800000)
2880 // Polymorph -- 118
2881 if (SpellFamilyFlags[0] & 0x1000000)
2883 // Ring of Frost -- 82691
2884 if (SpellFamilyFlags[2] & 0x40)
2886 // Ice Nova -- 157997
2887 if (SpellFamilyFlags[2] & 0x800000)
2889 break;
2890 }
2892 {
2893 // Shockwave -- 132168
2894 if (SpellFamilyFlags[1] & 0x8000)
2895 return DIMINISHING_STUN;
2896 // Storm Bolt -- 132169
2897 if (SpellFamilyFlags[2] & 0x1000)
2898 return DIMINISHING_STUN;
2899
2900 // Intimidating Shout -- 5246
2901 if (SpellFamilyFlags[0] & 0x40000)
2902 return DIMINISHING_DISORIENT;
2903 break;
2904 }
2906 {
2907 // Mortal Coil -- 6789
2908 if (SpellFamilyFlags[0] & 0x80000)
2910 // Banish -- 710
2911 if (SpellFamilyFlags[1] & 0x8000000)
2913
2914 // Fear -- 118699
2915 if (SpellFamilyFlags[1] & 0x400)
2916 return DIMINISHING_DISORIENT;
2917 // Howl of Terror -- 5484
2918 if (SpellFamilyFlags[1] & 0x8)
2919 return DIMINISHING_DISORIENT;
2920
2921 // Shadowfury -- 30283
2922 if (SpellFamilyFlags[1] & 0x1000)
2923 return DIMINISHING_STUN;
2924 // Summon Infernal -- 22703
2925 if (SpellFamilyFlags[0] & 0x1000)
2926 return DIMINISHING_STUN;
2927
2928 // 170995 -- Cripple
2929 if (Id == 170995)
2930 return DIMINISHING_LIMITONLY;
2931 break;
2932 }
2934 {
2935 // Fellash -- 115770
2936 // Whiplash -- 6360
2937 if (SpellFamilyFlags[0] & 0x8000000)
2939
2940 // Mesmerize (Shivarra pet) -- 115268
2941 // Seduction (Succubus pet) -- 6358
2942 if (SpellFamilyFlags[0] & 0x2000000)
2943 return DIMINISHING_DISORIENT;
2944
2945 // Axe Toss (Felguard pet) -- 89766
2946 if (SpellFamilyFlags[1] & 0x4)
2947 return DIMINISHING_STUN;
2948 break;
2949 }
2950 case SPELLFAMILY_DRUID:
2951 {
2952 // Maim -- 22570
2953 if (SpellFamilyFlags[1] & 0x80)
2954 return DIMINISHING_STUN;
2955 // Mighty Bash -- 5211
2956 if (SpellFamilyFlags[0] & 0x2000)
2957 return DIMINISHING_STUN;
2958 // Rake -- 163505 -- no flags on the stun
2959 if (Id == 163505)
2960 return DIMINISHING_STUN;
2961
2962 // Incapacitating Roar -- 99, no flags on the stun, 14
2963 if (SpellFamilyFlags[1] & 0x1)
2965
2966 // Cyclone -- 33786
2967 if (SpellFamilyFlags[1] & 0x20)
2968 return DIMINISHING_DISORIENT;
2969
2970 // Solar Beam -- 81261
2971 if (Id == 81261)
2972 return DIMINISHING_SILENCE;
2973
2974 // Typhoon -- 61391
2975 if (SpellFamilyFlags[1] & 0x1000000)
2977 // Ursol's Vortex -- 118283, no family flags
2978 if (Id == 118283)
2980
2981 // Entangling Roots -- 339
2982 if (SpellFamilyFlags[0] & 0x200)
2983 return DIMINISHING_ROOT;
2984 // Mass Entanglement -- 102359
2985 if (SpellFamilyFlags[2] & 0x4)
2986 return DIMINISHING_ROOT;
2987 break;
2988 }
2989 case SPELLFAMILY_ROGUE:
2990 {
2991 // Between the Eyes -- 199804
2992 if (SpellFamilyFlags[0] & 0x800000)
2993 return DIMINISHING_STUN;
2994 // Cheap Shot -- 1833
2995 if (SpellFamilyFlags[0] & 0x400)
2996 return DIMINISHING_STUN;
2997 // Kidney Shot -- 408
2998 if (SpellFamilyFlags[0] & 0x200000)
2999 return DIMINISHING_STUN;
3000
3001 // Gouge -- 1776
3002 if (SpellFamilyFlags[0] & 0x8)
3004 // Sap -- 6770
3005 if (SpellFamilyFlags[0] & 0x80)
3007
3008 // Blind -- 2094
3009 if (SpellFamilyFlags[0] & 0x1000000)
3010 return DIMINISHING_DISORIENT;
3011
3012 // Garrote -- 1330
3013 if (SpellFamilyFlags[1] & 0x20000000)
3014 return DIMINISHING_SILENCE;
3015 break;
3016 }
3017 case SPELLFAMILY_HUNTER:
3018 {
3019 // Charge (Tenacity pet) -- 53148, no flags
3020 if (Id == 53148)
3021 return DIMINISHING_ROOT;
3022 // Ranger's Net -- 200108
3023 // Tracker's Net -- 212638
3024 if (Id == 200108 || Id == 212638)
3025 return DIMINISHING_ROOT;
3026
3027 // Binding Shot -- 117526, no flags
3028 if (Id == 117526)
3029 return DIMINISHING_STUN;
3030
3031 // Freezing Trap -- 3355
3032 if (SpellFamilyFlags[0] & 0x8)
3034 // Wyvern Sting -- 19386
3035 if (SpellFamilyFlags[1] & 0x1000)
3037
3038 // Bursting Shot -- 224729
3039 if (SpellFamilyFlags[2] & 0x40)
3040 return DIMINISHING_DISORIENT;
3041 // Scatter Shot -- 213691
3042 if (SpellFamilyFlags[2] & 0x8000)
3043 return DIMINISHING_DISORIENT;
3044
3045 // Spider Sting -- 202933
3046 if (Id == 202933)
3047 return DIMINISHING_SILENCE;
3048 break;
3049 }
3051 {
3052 // Repentance -- 20066
3053 if (SpellFamilyFlags[0] & 0x4)
3055
3056 // Blinding Light -- 105421
3057 if (Id == 105421)
3058 return DIMINISHING_DISORIENT;
3059
3060 // Avenger's Shield -- 31935
3061 if (SpellFamilyFlags[0] & 0x4000)
3062 return DIMINISHING_SILENCE;
3063
3064 // Hammer of Justice -- 853
3065 if (SpellFamilyFlags[0] & 0x800)
3066 return DIMINISHING_STUN;
3067 break;
3068 }
3069 case SPELLFAMILY_SHAMAN:
3070 {
3071 // Hex -- 51514
3072 // Hex -- 196942 (Voodoo Totem)
3073 if (SpellFamilyFlags[1] & 0x8000)
3075
3076 // Thunderstorm -- 51490
3077 if (SpellFamilyFlags[1] & 0x2000)
3079
3080 // Earthgrab Totem -- 64695
3081 if (SpellFamilyFlags[2] & 0x4000)
3082 return DIMINISHING_ROOT;
3083
3084 // Lightning Lasso -- 204437
3085 if (SpellFamilyFlags[3] & 0x2000000)
3086 return DIMINISHING_STUN;
3087 break;
3088 }
3090 {
3091 // Chains of Ice -- 96294
3092 if (Id == 96294)
3093 return DIMINISHING_ROOT;
3094
3095 // Blinding Sleet -- 207167
3096 if (Id == 207167)
3097 return DIMINISHING_DISORIENT;
3098
3099 // Strangulate -- 47476
3100 if (SpellFamilyFlags[0] & 0x200)
3101 return DIMINISHING_SILENCE;
3102
3103 // Asphyxiate -- 108194
3104 if (SpellFamilyFlags[2] & 0x100000)
3105 return DIMINISHING_STUN;
3106 // Gnaw (Ghoul) -- 91800, no flags
3107 if (Id == 91800)
3108 return DIMINISHING_STUN;
3109 // Monstrous Blow (Ghoul w/ Dark Transformation active) -- 91797
3110 if (Id == 91797)
3111 return DIMINISHING_STUN;
3112 // Winter is Coming -- 207171
3113 if (Id == 207171)
3114 return DIMINISHING_STUN;
3115 break;
3116 }
3117 case SPELLFAMILY_PRIEST:
3118 {
3119 // Holy Word: Chastise -- 200200
3120 if (SpellFamilyFlags[2] & 0x20 && GetSpellVisual() == 52021)
3121 return DIMINISHING_STUN;
3122 // Mind Bomb -- 226943
3123 if (Id == 226943)
3124 return DIMINISHING_STUN;
3125
3126 // Mind Control -- 605
3127 if (SpellFamilyFlags[0] & 0x20000 && GetSpellVisual() == 39068)
3129 // Holy Word: Chastise -- 200196
3130 if (SpellFamilyFlags[2] & 0x20 && GetSpellVisual() == 52019)
3132
3133 // Psychic Scream -- 8122
3134 if (SpellFamilyFlags[0] & 0x10000)
3135 return DIMINISHING_DISORIENT;
3136
3137 // Silence -- 15487
3138 if (SpellFamilyFlags[1] & 0x200000 && GetSpellVisual() == 39025)
3139 return DIMINISHING_SILENCE;
3140
3141 // Shining Force -- 204263
3142 if (Id == 204263)
3144 break;
3145 }
3146 case SPELLFAMILY_MONK:
3147 {
3148 // Disable -- 116706, no flags
3149 if (Id == 116706)
3150 return DIMINISHING_ROOT;
3151
3152 // Fists of Fury -- 120086
3153 if (SpellFamilyFlags[1] & 0x800000 && !(SpellFamilyFlags[2] & 0x8))
3154 return DIMINISHING_STUN;
3155 // Leg Sweep -- 119381
3156 if (SpellFamilyFlags[1] & 0x200)
3157 return DIMINISHING_STUN;
3158
3159 // Incendiary Breath (honor talent) -- 202274, no flags
3160 if (Id == 202274)
3162 // Paralysis -- 115078
3163 if (SpellFamilyFlags[2] & 0x800000)
3165
3166 // Song of Chi-Ji -- 198909
3167 if (Id == 198909)
3168 return DIMINISHING_DISORIENT;
3169 break;
3170 }
3172 {
3173 switch (Id)
3174 {
3175 case 179057: // Chaos Nova
3176 case 211881: // Fel Eruption
3177 case 200166: // Metamorphosis
3178 case 205630: // Illidan's Grasp
3179 return DIMINISHING_STUN;
3180 case 217832: // Imprison
3181 case 221527: // Imprison
3183 default:
3184 break;
3185 }
3186 break;
3187 }
3188 default:
3189 break;
3190 }
3191
3192 return DIMINISHING_NONE;
3193 };
3194
3195 auto diminishingTypeCompute = [](DiminishingGroup group) -> DiminishingReturnsType
3196 {
3197 switch (group)
3198 {
3199 case DIMINISHING_TAUNT:
3200 case DIMINISHING_STUN:
3201 return DRTYPE_ALL;
3203 case DIMINISHING_NONE:
3204 return DRTYPE_NONE;
3205 default:
3206 return DRTYPE_PLAYER;
3207 }
3208 };
3209
3210 auto diminishingMaxLevelCompute = [](DiminishingGroup group) -> DiminishingLevels
3211 {
3212 switch (group)
3213 {
3214 case DIMINISHING_TAUNT:
3217 return DIMINISHING_LEVEL_2;
3218 default:
3220 }
3221 };
3222
3223 auto diminishingLimitDurationCompute = [this]() -> int32
3224 {
3225 // Explicit diminishing duration
3226 switch (SpellFamilyName)
3227 {
3228 case SPELLFAMILY_MAGE:
3229 {
3230 // Dragon's Breath - 3 seconds in PvP
3231 if (SpellFamilyFlags[0] & 0x800000)
3232 return 3 * IN_MILLISECONDS;
3233 break;
3234 }
3236 {
3237 // Cripple - 4 seconds in PvP
3238 if (Id == 170995)
3239 return 4 * IN_MILLISECONDS;
3240 break;
3241 }
3242 case SPELLFAMILY_HUNTER:
3243 {
3244 // Binding Shot - 3 seconds in PvP
3245 if (Id == 117526)
3246 return 3 * IN_MILLISECONDS;
3247
3248 // Wyvern Sting - 6 seconds in PvP
3249 if (SpellFamilyFlags[1] & 0x1000)
3250 return 6 * IN_MILLISECONDS;
3251 break;
3252 }
3253 case SPELLFAMILY_MONK:
3254 {
3255 // Paralysis - 4 seconds in PvP regardless of if they are facing you
3256 if (SpellFamilyFlags[2] & 0x800000)
3257 return 4 * IN_MILLISECONDS;
3258 break;
3259 }
3261 {
3262 switch (Id)
3263 {
3264 case 217832: // Imprison
3265 case 221527: // Imprison
3266 return 4 * IN_MILLISECONDS;
3267 default:
3268 break;
3269 }
3270 break;
3271 }
3272 default:
3273 break;
3274 }
3275
3276 return 8 * IN_MILLISECONDS;
3277 };
3278
3279 SpellDiminishInfo diminishInfo;
3280 diminishInfo.DiminishGroup = diminishingGroupCompute();
3281 diminishInfo.DiminishReturnType = diminishingTypeCompute(diminishInfo.DiminishGroup);
3282 diminishInfo.DiminishMaxLevel = diminishingMaxLevelCompute(diminishInfo.DiminishGroup);
3283 diminishInfo.DiminishDurationLimit = diminishingLimitDurationCompute();
3284
3285 _diminishInfo = diminishInfo;
3286}
3287
3289{
3291}
3292
3294{
3296}
3297
3299{
3301}
3302
3304{
3306}
3307
3309{
3310 std::unique_ptr<SpellEffectInfo::ImmunityInfo> workBuffer = std::make_unique<SpellEffectInfo::ImmunityInfo>();
3311
3312 for (SpellEffectInfo& effect : _effects)
3313 {
3314 uint32 schoolImmunityMask = 0;
3315 uint32 applyHarmfulAuraImmunityMask = 0;
3316 uint64 mechanicImmunityMask = 0;
3317 uint32 dispelImmunityMask = 0;
3318 uint32 damageImmunityMask = 0;
3319 uint8 otherImmunityMask = 0;
3320
3321 int32 miscVal = effect.MiscValue;
3322
3323 SpellEffectInfo::ImmunityInfo& immuneInfo = *workBuffer;
3324
3325 switch (effect.ApplyAuraName)
3326 {
3328 {
3329 if (CreatureImmunities const* creatureImmunities = SpellMgr::GetCreatureImmunities(miscVal))
3330 {
3331 schoolImmunityMask |= creatureImmunities->School.to_ulong();
3332 dispelImmunityMask |= creatureImmunities->DispelType.to_ulong();
3333 mechanicImmunityMask |= creatureImmunities->Mechanic.to_ullong();
3334 otherImmunityMask |= creatureImmunities->Other.AsUnderlyingType();
3335 for (SpellEffectName effectType : creatureImmunities->Effect)
3336 immuneInfo.SpellEffectImmune.insert(effectType);
3337 for (AuraType aura : creatureImmunities->Aura)
3338 immuneInfo.AuraTypeImmune.insert(aura);
3339 }
3340 break;
3341 }
3343 {
3344 switch (Id)
3345 {
3346 case 42292: // PvP trinket
3347 case 59752: // Every Man for Himself
3350 break;
3351 case 34471: // The Beast Within
3352 case 19574: // Bestial Wrath
3353 case 46227: // Medallion of Immunity
3354 case 53490: // Bullheaded
3355 case 65547: // PvP Trinket
3356 case 134946: // Supremacy of the Alliance
3357 case 134956: // Supremacy of the Horde
3358 case 195710: // Honorable Medallion
3359 case 208683: // Gladiator's Medallion
3361 break;
3362 case 54508: // Demonic Empowerment
3363 mechanicImmunityMask |= (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) | (1 << MECHANIC_STUN);
3364 break;
3365 default:
3366 if (miscVal < 1)
3367 break;
3368
3369 mechanicImmunityMask |= UI64LIT(1) << miscVal;
3370 break;
3371 }
3372 break;
3373 }
3375 {
3376 immuneInfo.SpellEffectImmune.insert(static_cast<SpellEffectName>(miscVal));
3377 break;
3378 }
3380 {
3381 immuneInfo.AuraTypeImmune.insert(static_cast<AuraType>(miscVal));
3382 break;
3383 }
3385 {
3386 schoolImmunityMask |= uint32(miscVal);
3387 break;
3388 }
3390 {
3391 applyHarmfulAuraImmunityMask |= uint32(miscVal);
3392 break;
3393 }
3395 {
3396 damageImmunityMask |= uint32(miscVal);
3397 break;
3398 }
3400 {
3401 dispelImmunityMask = 1u << miscVal;
3402 break;
3403 }
3404 default:
3405 break;
3406 }
3407
3408 immuneInfo.SchoolImmuneMask = schoolImmunityMask;
3409 immuneInfo.ApplyHarmfulAuraImmuneMask = applyHarmfulAuraImmunityMask;
3410 immuneInfo.MechanicImmuneMask = mechanicImmunityMask;
3411 immuneInfo.DispelImmuneMask = dispelImmunityMask;
3412 immuneInfo.DamageSchoolMask = damageImmunityMask;
3413 immuneInfo.OtherImmuneMask = otherImmunityMask;
3414
3415 immuneInfo.AuraTypeImmune.shrink_to_fit();
3416 immuneInfo.SpellEffectImmune.shrink_to_fit();
3417
3418 if (immuneInfo.SchoolImmuneMask
3419 || immuneInfo.ApplyHarmfulAuraImmuneMask
3420 || immuneInfo.MechanicImmuneMask
3421 || immuneInfo.DispelImmuneMask
3422 || immuneInfo.DamageSchoolMask
3423 || immuneInfo.OtherImmuneMask
3424 || !immuneInfo.AuraTypeImmune.empty()
3425 || !immuneInfo.SpellEffectImmune.empty())
3426 {
3427 effect._immunityInfo = std::move(workBuffer);
3428 workBuffer = std::make_unique<SpellEffectInfo::ImmunityInfo>();
3429 }
3430
3432 }
3433
3435 {
3436 switch (Id)
3437 {
3438 case 22812: // Barkskin
3439 case 47585: // Dispersion
3441 (1 << MECHANIC_STUN) |
3442 (1 << MECHANIC_FREEZE) |
3443 (1 << MECHANIC_KNOCKOUT) |
3444 (1 << MECHANIC_SLEEP);
3445 break;
3446 case 49039: // Lichborne, don't allow normal stuns
3447 break;
3448 default:
3450 break;
3451 }
3452 }
3453
3456
3458 {
3459 switch (Id)
3460 {
3461 case 22812: // Barkskin
3462 case 47585: // Dispersion
3464 break;
3465 default:
3467 break;
3468 }
3469 }
3470}
3471
3472void SpellInfo::_LoadSqrtTargetLimit(int32 maxTargets, int32 numNonDiminishedTargets, Optional<SpellEffIndex> maxTargetsEffectValueHolder,
3473 Optional<SpellEffIndex> numNonDiminishedTargetsEffectValueHolder)
3474{
3475 SqrtDamageAndHealingDiminishing.MaxTargets = maxTargets;
3476 SqrtDamageAndHealingDiminishing.NumNonDiminishedTargets = numNonDiminishedTargets;
3477
3478 if (maxTargetsEffectValueHolder)
3479 {
3480 if (maxTargetsEffectValueHolder < GetEffects().size())
3481 {
3482 SpellEffectInfo const& valueHolder = GetEffect(*maxTargetsEffectValueHolder);
3483 int32 expectedValue = valueHolder.CalcBaseValue(nullptr, nullptr, 0, -1);
3484 if (maxTargets != expectedValue)
3485 TC_LOG_ERROR("spells", "SpellInfo::_LoadSqrtTargetLimit(maxTargets): Spell {} has different value in effect {} than expected, recheck target caps (expected {}, got {})",
3486 Id, AsUnderlyingType(*maxTargetsEffectValueHolder), maxTargets, expectedValue);
3487 }
3488 else
3489 TC_LOG_ERROR("spells", "SpellInfo::_LoadSqrtTargetLimit(maxTargets): Spell {} does not have effect {}", Id, AsUnderlyingType(*maxTargetsEffectValueHolder));
3490 }
3491
3492 if (numNonDiminishedTargetsEffectValueHolder)
3493 {
3494 if (numNonDiminishedTargetsEffectValueHolder < GetEffects().size())
3495 {
3496 SpellEffectInfo const& valueHolder = GetEffect(*numNonDiminishedTargetsEffectValueHolder);
3497 int32 expectedValue = valueHolder.CalcBaseValue(nullptr, nullptr, 0, -1);
3498 if (numNonDiminishedTargets != expectedValue)
3499 TC_LOG_ERROR("spells", "SpellInfo::_LoadSqrtTargetLimit(numNonDiminishedTargets): Spell {} has different value in effect {} than expected, recheck target caps (expected {}, got {})",
3500 Id, AsUnderlyingType(*numNonDiminishedTargetsEffectValueHolder), numNonDiminishedTargets, expectedValue);
3501 }
3502 else
3503 TC_LOG_ERROR("spells", "SpellInfo::_LoadSqrtTargetLimit(numNonDiminishedTargets): Spell {} does not have effect {}", Id, AsUnderlyingType(*numNonDiminishedTargetsEffectValueHolder));
3504 }
3505}
3506
3507void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const& spellEffectInfo, bool apply) const
3508{
3509 SpellEffectInfo::ImmunityInfo const* immuneInfo = spellEffectInfo.GetImmunityInfo();
3510 if (!immuneInfo)
3511 return;
3512
3513 if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask)
3514 {
3515 target->ApplySpellImmune(Id, IMMUNITY_SCHOOL, schoolImmunity, apply);
3516
3518 {
3519 target->RemoveAppliedAuras([this, target, schoolImmunity](AuraApplication const* aurApp) -> bool
3520 {
3521 SpellInfo const* auraSpellInfo = aurApp->GetBase()->GetSpellInfo();
3522 if (auraSpellInfo->Id == Id) // Don't remove self
3523 return false;
3524 if (auraSpellInfo->IsPassive()) // Don't remove passive auras
3525 return false;
3526 if (!(auraSpellInfo->GetSchoolMask() & schoolImmunity)) // Check for school mask
3527 return false;
3528 if (!CanDispelAura(auraSpellInfo))
3529 return false;
3531 {
3532 WorldObject const* existingAuraCaster = aurApp->GetBase()->GetWorldObjectCaster();
3533 if (existingAuraCaster && existingAuraCaster->IsFriendlyTo(target)) // Check spell vs aura possitivity
3534 return false;
3535 }
3536 return true;
3537 });
3538 }
3539
3540 if (apply && schoolImmunity & SPELL_SCHOOL_MASK_NORMAL)
3542 }
3543
3544 if (uint64 mechanicImmunity = immuneInfo->MechanicImmuneMask)
3545 {
3546 for (uint32 i = 0; i < MAX_MECHANIC; ++i)
3547 if (mechanicImmunity & (UI64LIT(1) << i))
3549
3551 {
3552 if (apply)
3553 target->RemoveAurasWithMechanic(mechanicImmunity, AURA_REMOVE_BY_DEFAULT, Id);
3554 else
3555 {
3556 std::vector<Aura*> aurasToUpdateTargets;
3557 target->RemoveAppliedAuras([mechanicImmunity, &aurasToUpdateTargets](AuraApplication const* aurApp)
3558 {
3559 Aura* aura = aurApp->GetBase();
3560 if (aura->GetSpellInfo()->GetAllEffectsMechanicMask() & mechanicImmunity)
3561 aurasToUpdateTargets.push_back(aura);
3562
3563 // only update targets, don't remove anything
3564 return false;
3565 });
3566
3567 for (Aura* aura : aurasToUpdateTargets)
3568 aura->UpdateTargetMap(aura->GetCaster());
3569 }
3570 }
3571 }
3572
3573 if (uint32 dispelImmunity = immuneInfo->DispelImmuneMask)
3574 {
3575 for (uint32 i = 0; i < DISPEL_MAX; ++i)
3576 if (dispelImmunity & (1 << i))
3578
3580 {
3581 target->RemoveAppliedAuras([dispelImmunity](AuraApplication const* aurApp) -> bool
3582 {
3583 SpellInfo const* spellInfo = aurApp->GetBase()->GetSpellInfo();
3584 uint32 dispelMask = spellInfo->GetDispelMask();
3585 if ((dispelMask & dispelImmunity) == dispelMask)
3586 return true;
3587
3588 return false;
3589 });
3590 }
3591 }
3592
3593 if (uint32 damageImmunity = immuneInfo->DamageSchoolMask)
3594 {
3595 target->ApplySpellImmune(Id, IMMUNITY_DAMAGE, damageImmunity, apply);
3596
3597 if (apply && damageImmunity & SPELL_SCHOOL_MASK_NORMAL)
3599 }
3600
3601 for (AuraType auraType : immuneInfo->AuraTypeImmune)
3602 {
3603 target->ApplySpellImmune(Id, IMMUNITY_STATE, auraType, apply);
3605 target->RemoveAurasByType(auraType, [this](AuraApplication const* aurApp) -> bool
3606 {
3607 return CanDispelAura(aurApp->GetBase()->GetSpellInfo());
3608 });
3609 }
3610
3611 for (SpellEffectName effectType : immuneInfo->SpellEffectImmune)
3612 target->ApplySpellImmune(Id, IMMUNITY_EFFECT, effectType, apply);
3613
3614 if (uint8 otherImmuneMask = immuneInfo->OtherImmuneMask)
3615 target->ApplySpellImmune(Id, IMMUNITY_OTHER, otherImmuneMask, apply);
3616}
3617
3619{
3620 if (!auraSpellInfo)
3621 return false;
3622
3623 for (SpellEffectInfo const& effectInfo : _effects)
3624 {
3625 if (!effectInfo.IsEffect())
3626 continue;
3627
3628 SpellEffectInfo::ImmunityInfo const* immuneInfo = effectInfo.GetImmunityInfo();
3629 if (!immuneInfo)
3630 continue;
3631
3633 if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask)
3634 if ((auraSpellInfo->SchoolMask & schoolImmunity) != 0)
3635 return true;
3636
3637 if (uint64 mechanicImmunity = immuneInfo->MechanicImmuneMask)
3638 if ((mechanicImmunity & (UI64LIT(1) << auraSpellInfo->Mechanic)) != 0)
3639 return true;
3640
3641 if (uint32 dispelImmunity = immuneInfo->DispelImmuneMask)
3642 if (auraSpellInfo->Dispel == dispelImmunity)
3643 return true;
3644
3645 bool immuneToAllEffects = true;
3646 for (SpellEffectInfo const& auraSpellEffectInfo : auraSpellInfo->GetEffects())
3647 {
3648 if (!auraSpellEffectInfo.IsAura())
3649 continue;
3650
3651 if (uint64 mechanicImmunity = immuneInfo->MechanicImmuneMask)
3652 if ((mechanicImmunity & (UI64LIT(1) << auraSpellEffectInfo.Mechanic)) != 0)
3653 continue;
3654
3655 if (AuraType auraName = auraSpellEffectInfo.ApplyAuraName)
3656 {
3657 if (immuneInfo->AuraTypeImmune.find(auraName) != immuneInfo->AuraTypeImmune.end())
3658 continue;
3659
3660 if (!auraSpellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES) && !auraSpellInfo->IsPositiveEffect(auraSpellEffectInfo.EffectIndex))
3661 if (uint32 applyHarmfulAuraImmunityMask = immuneInfo->ApplyHarmfulAuraImmuneMask)
3662 if ((auraSpellInfo->GetSchoolMask() & applyHarmfulAuraImmunityMask) != 0)
3663 continue;
3664 }
3665
3666 immuneToAllEffects = false;
3667 }
3668
3669 if (immuneToAllEffects)
3670 return true;
3671 }
3672
3673 return false;
3674}
3675
3676bool SpellInfo::CanSpellEffectProvideImmunityAgainstAuraEffect(SpellEffectInfo const& immunityEffectInfo, SpellInfo const* auraSpellInfo, SpellEffectInfo const& auraEffectInfo) const
3677{
3678 SpellEffectInfo::ImmunityInfo const* immuneInfo = immunityEffectInfo.GetImmunityInfo();
3679 if (!immuneInfo)
3680 return false;
3681
3683 {
3684 if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask)
3685 if ((auraSpellInfo->SchoolMask & schoolImmunity) != 0)
3686 return true;
3687
3688 if (uint32 applyHarmfulAuraImmunityMask = immuneInfo->ApplyHarmfulAuraImmuneMask)
3689 if ((auraSpellInfo->GetSchoolMask() & applyHarmfulAuraImmunityMask) != 0)
3690 return true;
3691 }
3692
3693 if (uint64 mechanicImmunity = immuneInfo->MechanicImmuneMask)
3694 {
3695 if ((mechanicImmunity & (UI64LIT(1) << auraSpellInfo->Mechanic)) != 0)
3696 return true;
3697 if ((mechanicImmunity & (UI64LIT(1) << auraEffectInfo.Mechanic)) != 0)
3698 return true;
3699 }
3700
3701 if (uint32 dispelImmunity = immuneInfo->DispelImmune