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* 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 }
710
711 return radius;
712}
713
715{
717}
718
719uint32 SpellEffectInfo::GetMissingTargetMask(bool srcSet /*= false*/, bool dstSet /*= false*/, uint32 mask /*=0*/) const
720{
721 uint32 effImplicitTargetMask = GetTargetFlagMask(GetUsedTargetObjectType());
722 uint32 providedTargetMask = GetProvidedTargetMask() | mask;
723
724 // remove all flags covered by effect target mask
725 if (providedTargetMask & TARGET_FLAG_UNIT_MASK)
726 effImplicitTargetMask &= ~(TARGET_FLAG_UNIT_MASK);
727 if (providedTargetMask & TARGET_FLAG_CORPSE_MASK)
728 effImplicitTargetMask &= ~(TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK);
729 if (providedTargetMask & TARGET_FLAG_GAMEOBJECT_ITEM)
731 if (providedTargetMask & TARGET_FLAG_GAMEOBJECT)
732 effImplicitTargetMask &= ~(TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_GAMEOBJECT_ITEM);
733 if (providedTargetMask & TARGET_FLAG_ITEM)
734 effImplicitTargetMask &= ~(TARGET_FLAG_ITEM | TARGET_FLAG_GAMEOBJECT_ITEM);
735 if (dstSet || providedTargetMask & TARGET_FLAG_DEST_LOCATION)
736 effImplicitTargetMask &= ~(TARGET_FLAG_DEST_LOCATION);
737 if (srcSet || providedTargetMask & TARGET_FLAG_SOURCE_LOCATION)
738 effImplicitTargetMask &= ~(TARGET_FLAG_SOURCE_LOCATION);
739
740 return effImplicitTargetMask;
741}
742
744{
745 return _data[Effect].ImplicitTargetType;
746}
747
749{
750 return _data[Effect].UsedTargetObjectType;
751}
752
754{
755 switch (Effect)
756 {
768 if (MiscValue == POWER_MANA)
784 switch (ApplyAuraName)
785 {
829 if (MiscValue == POWER_MANA)
832 default:
833 break;
834 }
835 break;
836 default:
837 break;
838 }
839
841}
842
843std::array<SpellEffectInfo::StaticData, TOTAL_SPELL_EFFECTS> SpellEffectInfo::_data =
844{ {
845 // implicit target type used target object type
847 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 1 SPELL_EFFECT_INSTAKILL
848 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 2 SPELL_EFFECT_SCHOOL_DAMAGE
849 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 3 SPELL_EFFECT_DUMMY
850 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 4 SPELL_EFFECT_PORTAL_TELEPORT
852 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 6 SPELL_EFFECT_APPLY_AURA
853 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
854 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 8 SPELL_EFFECT_POWER_DRAIN
855 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 9 SPELL_EFFECT_HEALTH_LEECH
858 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 12 SPELL_EFFECT_PORTAL
859 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT_AND_DEST}, // 13 SPELL_EFFECT_TELEPORT_TO_RETURN_POINT
860 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 14 SPELL_EFFECT_INCREASE_CURRENCY_CAP
861 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT_AND_DEST}, // 15 SPELL_EFFECT_TELEPORT_WITH_SPELL_VISUAL_KIT_LOADING_SCREEN
862 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 16 SPELL_EFFECT_QUEST_COMPLETE
863 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
865 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
866 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 20 SPELL_EFFECT_DODGE
867 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 21 SPELL_EFFECT_EVADE
868 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 22 SPELL_EFFECT_PARRY
869 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 23 SPELL_EFFECT_BLOCK
870 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 24 SPELL_EFFECT_CREATE_ITEM
871 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 25 SPELL_EFFECT_WEAPON
872 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 26 SPELL_EFFECT_DEFENSE
873 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
874 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 28 SPELL_EFFECT_SUMMON
876 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 30 SPELL_EFFECT_ENERGIZE
877 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
878 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 32 SPELL_EFFECT_TRIGGER_MISSILE
880 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
881 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
882 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 36 SPELL_EFFECT_LEARN_SPELL
883 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 37 SPELL_EFFECT_SPELL_DEFENSE
884 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 38 SPELL_EFFECT_DISPEL
885 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 39 SPELL_EFFECT_LANGUAGE
886 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 40 SPELL_EFFECT_DUAL_WIELD
888 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 42 SPELL_EFFECT_JUMP_DEST
889 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT_AND_DEST}, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
890 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 44 SPELL_EFFECT_SKILL_STEP
891 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 45 SPELL_EFFECT_ADD_HONOR
892 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 46 SPELL_EFFECT_SPAWN
893 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 47 SPELL_EFFECT_TRADE_SKILL
894 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 48 SPELL_EFFECT_STEALTH
895 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 49 SPELL_EFFECT_DETECT
896 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 50 SPELL_EFFECT_TRANS_DOOR
897 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT
898 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 52 SPELL_EFFECT_SET_MAX_BATTLE_PET_COUNT
899 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 53 SPELL_EFFECT_ENCHANT_ITEM
900 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
901 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 55 SPELL_EFFECT_TAMECREATURE
902 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 56 SPELL_EFFECT_SUMMON_PET
903 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 57 SPELL_EFFECT_LEARN_PET_SPELL
904 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 58 SPELL_EFFECT_WEAPON_DAMAGE
905 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM
906 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 60 SPELL_EFFECT_PROFICIENCY
907 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 61 SPELL_EFFECT_SEND_EVENT
908 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 62 SPELL_EFFECT_POWER_BURN
909 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 63 SPELL_EFFECT_THREAT
910 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 64 SPELL_EFFECT_TRIGGER_SPELL
911 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
912 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 66 SPELL_EFFECT_RECHARGE_ITEM
913 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
914 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 68 SPELL_EFFECT_INTERRUPT_CAST
916 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 70 SPELL_EFFECT_COMPLETE_AND_REWARD_WORLD_QUEST
917 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 71 SPELL_EFFECT_PICKPOCKET
918 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 72 SPELL_EFFECT_ADD_FARSIGHT
919 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
920 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 74 SPELL_EFFECT_APPLY_GLYPH
921 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 75 SPELL_EFFECT_HEAL_MECHANICAL
922 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
923 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 77 SPELL_EFFECT_SCRIPT_EFFECT
924 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 78 SPELL_EFFECT_ATTACK
925 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 79 SPELL_EFFECT_SANCTUARY
926 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 80 SPELL_EFFECT_MODIFY_FOLLOWER_ITEM_LEVEL
927 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 81 SPELL_EFFECT_PUSH_ABILITY_TO_ACTION_BAR
928 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 82 SPELL_EFFECT_BIND_SIGHT
930 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 84 SPELL_EFFECT_STUCK
931 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 85 SPELL_EFFECT_SUMMON_PLAYER
932 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_GOBJ}, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
933 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_GOBJ}, // 87 SPELL_EFFECT_GAMEOBJECT_DAMAGE
934 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_GOBJ}, // 88 SPELL_EFFECT_GAMEOBJECT_REPAIR
935 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_GOBJ}, // 89 SPELL_EFFECT_GAMEOBJECT_SET_DESTRUCTION_STATE
936 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 90 SPELL_EFFECT_KILL_CREDIT
937 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 91 SPELL_EFFECT_THREAT_ALL
938 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
939 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 93 SPELL_EFFECT_FORCE_DESELECT
940 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 94 SPELL_EFFECT_SELF_RESURRECT
941 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 95 SPELL_EFFECT_SKINNING
942 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 96 SPELL_EFFECT_CHARGE
943 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 97 SPELL_EFFECT_CAST_BUTTON
944 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 98 SPELL_EFFECT_KNOCK_BACK
945 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 99 SPELL_EFFECT_DISENCHANT
946 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 100 SPELL_EFFECT_INEBRIATE
947 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 101 SPELL_EFFECT_FEED_PET
948 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 102 SPELL_EFFECT_DISMISS_PET
949 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 103 SPELL_EFFECT_REPUTATION
950 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
951 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 105 SPELL_EFFECT_SURVEY
952 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 106 SPELL_EFFECT_CHANGE_RAID_MARKER
953 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 107 SPELL_EFFECT_SHOW_CORPSE_LOOT
954 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 108 SPELL_EFFECT_DISPEL_MECHANIC
955 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 109 SPELL_EFFECT_RESURRECT_PET
956 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
957 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 111 SPELL_EFFECT_DURABILITY_DAMAGE
959 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 113 SPELL_EFFECT_CANCEL_CONVERSATION
960 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 114 SPELL_EFFECT_ATTACK_ME
961 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
962 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_CORPSE_ENEMY}, // 116 SPELL_EFFECT_SKIN_PLAYER_CORPSE
963 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 117 SPELL_EFFECT_SPIRIT_HEAL
964 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 118 SPELL_EFFECT_SKILL
965 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 119 SPELL_EFFECT_APPLY_AREA_AURA_PET
966 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 120 SPELL_EFFECT_TELEPORT_GRAVEYARD
967 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
968 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 122 SPELL_EFFECT_122
969 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 123 SPELL_EFFECT_SEND_TAXI
970 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 124 SPELL_EFFECT_PULL_TOWARDS
971 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
972 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF
973 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 127 SPELL_EFFECT_PROSPECTING
974 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
975 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
976 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 130 SPELL_EFFECT_REDIRECT_THREAT
977 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 131 SPELL_EFFECT_PLAY_SOUND
978 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 132 SPELL_EFFECT_PLAY_MUSIC
979 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 133 SPELL_EFFECT_UNLEARN_SPECIALIZATION
980 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 134 SPELL_EFFECT_KILL_CREDIT2
981 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 135 SPELL_EFFECT_CALL_PET
982 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 136 SPELL_EFFECT_HEAL_PCT
983 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 137 SPELL_EFFECT_ENERGIZE_PCT
984 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 138 SPELL_EFFECT_LEAP_BACK
985 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 139 SPELL_EFFECT_CLEAR_QUEST
986 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 140 SPELL_EFFECT_FORCE_CAST
987 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 141 SPELL_EFFECT_FORCE_CAST_WITH_VALUE
988 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
989 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
990 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT_AND_DEST}, // 144 SPELL_EFFECT_KNOCK_BACK_DEST
991 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT_AND_DEST}, // 145 SPELL_EFFECT_PULL_TOWARDS_DEST
992 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 146 SPELL_EFFECT_RESTORE_GARRISON_TROOP_VITALITY
993 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 147 SPELL_EFFECT_QUEST_FAIL
994 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 148 SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE
995 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 149 SPELL_EFFECT_CHARGE_DEST
996 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 150 SPELL_EFFECT_QUEST_START
997 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 151 SPELL_EFFECT_TRIGGER_SPELL_2
998 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 152 SPELL_EFFECT_SUMMON_RAF_FRIEND
999 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 153 SPELL_EFFECT_CREATE_TAMED_PET
1000 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 154 SPELL_EFFECT_DISCOVER_TAXI
1001 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 155 SPELL_EFFECT_TITAN_GRIP
1002 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
1003 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 157 SPELL_EFFECT_CREATE_LOOT
1004 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 158 SPELL_EFFECT_MILLING
1005 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 159 SPELL_EFFECT_ALLOW_RENAME_PET
1006 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 160 SPELL_EFFECT_FORCE_CAST_2
1007 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 161 SPELL_EFFECT_TALENT_SPEC_COUNT
1008 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 162 SPELL_EFFECT_TALENT_SPEC_SELECT
1009 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 163 SPELL_EFFECT_OBLITERATE_ITEM
1010 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 164 SPELL_EFFECT_REMOVE_AURA
1011 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 165 SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT
1012 {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 166 SPELL_EFFECT_GIVE_CURRENCY
1013 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 167 SPELL_EFFECT_UPDATE_PLAYER_PHASE
1014 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 168 SPELL_EFFECT_ALLOW_CONTROL_PET
1015 {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 169 SPELL_EFFECT_DESTROY_ITEM
1016 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 170 SPELL_EFFECT_UPDATE_ZONE_AURAS_AND_PHASES
1017 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 171 SPELL_EFFECT_SUMMON_PERSONAL_GAMEOBJECT
1018 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_CORPSE_ALLY}, // 172 SPELL_EFFECT_RESURRECT_WITH_AURA
1019 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 173 SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB
1020 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 174 SPELL_EFFECT_APPLY_AURA_ON_PET
1021 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 175 SPELL_EFFECT_175
1022 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 176 SPELL_EFFECT_SANCTUARY_2
1023 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 177 SPELL_EFFECT_DESPAWN_PERSISTENT_AREA_AURA
1024 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 178 SPELL_EFFECT_178
1025 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 179 SPELL_EFFECT_CREATE_AREATRIGGER
1026 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 180 SPELL_EFFECT_UPDATE_AREATRIGGER
1027 {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 181 SPELL_EFFECT_REMOVE_TALENT
1028 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 182 SPELL_EFFECT_DESPAWN_AREATRIGGER
1029 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 183 SPELL_EFFECT_183
1030 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 184 SPELL_EFFECT_REPUTATION_2
1031 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 185 SPELL_EFFECT_185
1032 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 186 SPELL_EFFECT_186
1033 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 187 SPELL_EFFECT_RANDOMIZE_ARCHAEOLOGY_DIGSITES
1034 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 188 SPELL_EFFECT_SUMMON_STABLED_PET_AS_GUARDIAN
1035 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 189 SPELL_EFFECT_LOOT
1036 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 190 SPELL_EFFECT_CHANGE_PARTY_MEMBERS
1037 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 191 SPELL_EFFECT_TELEPORT_TO_DIGSITE
1038 {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 192 SPELL_EFFECT_UNCAGE_BATTLEPET
1039 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 193 SPELL_EFFECT_START_PET_BATTLE
1040 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 194 SPELL_EFFECT_194
1041 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 195 SPELL_EFFECT_PLAY_SCENE_SCRIPT_PACKAGE
1042 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 196 SPELL_EFFECT_CREATE_SCENE_OBJECT
1043 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 197 SPELL_EFFECT_CREATE_PERSONAL_SCENE_OBJECT
1044 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 198 SPELL_EFFECT_PLAY_SCENE
1045 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 199 SPELL_EFFECT_DESPAWN_SUMMON
1046 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 200 SPELL_EFFECT_HEAL_BATTLEPET_PCT
1047 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 201 SPELL_EFFECT_ENABLE_BATTLE_PETS
1048 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 202 SPELL_EFFECT_APPLY_AREA_AURA_SUMMONS
1049 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 203 SPELL_EFFECT_REMOVE_AURA_2
1050 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 204 SPELL_EFFECT_CHANGE_BATTLEPET_QUALITY
1051 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 205 SPELL_EFFECT_LAUNCH_QUEST_CHOICE
1052 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 206 SPELL_EFFECT_ALTER_IETM
1053 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 207 SPELL_EFFECT_LAUNCH_QUEST_TASK
1054 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 208 SPELL_EFFECT_SET_REPUTATION
1055 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 209 SPELL_EFFECT_209
1056 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 210 SPELL_EFFECT_LEARN_GARRISON_BUILDING
1057 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 211 SPELL_EFFECT_LEARN_GARRISON_SPECIALIZATION
1058 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 212 SPELL_EFFECT_REMOVE_AURA_BY_SPELL_LABEL
1059 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 213 SPELL_EFFECT_JUMP_DEST_2
1060 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 214 SPELL_EFFECT_CREATE_GARRISON
1061 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 215 SPELL_EFFECT_UPGRADE_CHARACTER_SPELLS
1062 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 216 SPELL_EFFECT_CREATE_SHIPMENT
1063 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 217 SPELL_EFFECT_UPGRADE_GARRISON
1064 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 218 SPELL_EFFECT_218
1065 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 219 SPELL_EFFECT_CREATE_CONVERSATION
1066 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 220 SPELL_EFFECT_ADD_GARRISON_FOLLOWER
1067 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 221 SPELL_EFFECT_ADD_GARRISON_MISSION
1068 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 222 SPELL_EFFECT_CREATE_HEIRLOOM_ITEM
1069 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 223 SPELL_EFFECT_CHANGE_ITEM_BONUSES
1070 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 224 SPELL_EFFECT_ACTIVATE_GARRISON_BUILDING
1071 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 225 SPELL_EFFECT_GRANT_BATTLEPET_LEVEL
1072 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 226 SPELL_EFFECT_TRIGGER_ACTION_SET
1073 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 227 SPELL_EFFECT_TELEPORT_TO_LFG_DUNGEON
1074 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 228 SPELL_EFFECT_228
1075 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 229 SPELL_EFFECT_SET_FOLLOWER_QUALITY
1077 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 231 SPELL_EFFECT_INCREASE_FOLLOWER_EXPERIENCE
1078 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 232 SPELL_EFFECT_REMOVE_PHASE
1079 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 233 SPELL_EFFECT_RANDOMIZE_FOLLOWER_ABILITIES
1080 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 234 SPELL_EFFECT_234
1081 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 235 SPELL_EFFECT_235
1082 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 236 SPELL_EFFECT_GIVE_EXPERIENCE
1083 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 237 SPELL_EFFECT_GIVE_RESTED_EXPERIENCE_BONUS
1084 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 238 SPELL_EFFECT_INCREASE_SKILL
1085 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 239 SPELL_EFFECT_END_GARRISON_BUILDING_CONSTRUCTION
1086 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 240 SPELL_EFFECT_GIVE_ARTIFACT_POWER
1087 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 241 SPELL_EFFECT_241
1088 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 242 SPELL_EFFECT_GIVE_ARTIFACT_POWER_NO_BONUS
1089 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 243 SPELL_EFFECT_APPLY_ENCHANT_ILLUSION
1090 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 244 SPELL_EFFECT_LEARN_FOLLOWER_ABILITY
1091 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 245 SPELL_EFFECT_UPGRADE_HEIRLOOM
1092 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 246 SPELL_EFFECT_FINISH_GARRISON_MISSION
1093 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 247 SPELL_EFFECT_ADD_GARRISON_MISSION_SET
1094 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 248 SPELL_EFFECT_FINISH_SHIPMENT
1095 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 249 SPELL_EFFECT_FORCE_EQUIP_ITEM
1096 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 250 SPELL_EFFECT_TAKE_SCREENSHOT
1097 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 251 SPELL_EFFECT_SET_GARRISON_CACHE_SIZE
1098 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT_AND_DEST}, // 252 SPELL_EFFECT_TELEPORT_UNITS
1099 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 253 SPELL_EFFECT_GIVE_HONOR
1100 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_DEST}, // 254 SPELL_EFFECT_JUMP_CHARGE
1101 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 255 SPELL_EFFECT_LEARN_TRANSMOG_SET
1102 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 256 SPELL_EFFECT_256
1103 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 257 SPELL_EFFECT_257
1104 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 258 SPELL_EFFECT_MODIFY_KEYSTONE
1105 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 259 SPELL_EFFECT_RESPEC_AZERITE_EMPOWERED_ITEM
1106 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 260 SPELL_EFFECT_SUMMON_STABLED_PET
1107 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 261 SPELL_EFFECT_SCRAP_ITEM
1108 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 262 SPELL_EFFECT_262
1109 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 263 SPELL_EFFECT_REPAIR_ITEM
1110 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 264 SPELL_EFFECT_REMOVE_GEM
1111 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 265 SPELL_EFFECT_LEARN_AZERITE_ESSENCE_POWER
1112 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 266 SPELL_EFFECT_SET_ITEM_BONUS_LIST_GROUP_ENTRY
1113 {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 267 SPELL_EFFECT_CREATE_PRIVATE_CONVERSATION
1114 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 268 SPELL_EFFECT_APPLY_MOUNT_EQUIPMENT
1115 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 269 SPELL_EFFECT_INCREASE_ITEM_BONUS_LIST_GROUP_STEP
1117 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 271 SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM
1118 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 272 SPELL_EFFECT_SET_COVENANT
1119 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 273 SPELL_EFFECT_CRAFT_RUNEFORGE_LEGENDARY
1120 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 274 SPELL_EFFECT_274
1121 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 275 SPELL_EFFECT_275
1122 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 276 SPELL_EFFECT_LEARN_TRANSMOG_ILLUSION
1123 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 277 SPELL_EFFECT_SET_CHROMIE_TIME
1124 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 278 SPELL_EFFECT_278
1125 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 279 SPELL_EFFECT_LEARN_GARR_TALENT
1126 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 280 SPELL_EFFECT_280
1127 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 281 SPELL_EFFECT_LEARN_SOULBIND_CONDUIT
1128 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 282 SPELL_EFFECT_CONVERT_ITEMS_TO_CURRENCY
1129 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 283 SPELL_EFFECT_COMPLETE_CAMPAIGN
1130 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 284 SPELL_EFFECT_SEND_CHAT_MESSAGE
1131 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 285 SPELL_EFFECT_MODIFY_KEYSTONE_2
1132 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 286 SPELL_EFFECT_GRANT_BATTLEPET_EXPERIENCE
1133 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 287 SPELL_EFFECT_SET_GARRISON_FOLLOWER_LEVEL
1134 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 288 SPELL_EFFECT_CRAFT_ITEM
1135 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 289 SPELL_EFFECT_MODIFY_AURA_STACKS
1136 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 290 SPELL_EFFECT_MODIFY_COOLDOWN
1137 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 291 SPELL_EFFECT_MODIFY_COOLDOWNS
1138 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 292 SPELL_EFFECT_MODIFY_COOLDOWNS_BY_CATEGORY
1139 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 293 SPELL_EFFECT_MODIFY_CHARGES
1140 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 294 SPELL_EFFECT_CRAFT_LOOT
1141 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 295 SPELL_EFFECT_SALVAGE_ITEM
1142 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 296 SPELL_EFFECT_CRAFT_SALVAGE_ITEM
1143 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 297 SPELL_EFFECT_RECRAFT_ITEM
1144 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 298 SPELL_EFFECT_CANCEL_ALL_PRIVATE_CONVERSATIONS
1145 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 299 SPELL_EFFECT_299
1146 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 300 SPELL_EFFECT_300
1147 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 301 SPELL_EFFECT_CRAFT_ENCHANT
1148 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_NONE}, // 302 SPELL_EFFECT_GATHERING
1149 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 303 SPELL_EFFECT_CREATE_TRAIT_TREE_CONFIG
1150 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 304 SPELL_EFFECT_CHANGE_ACTIVE_COMBAT_TRAIT_CONFIG
1151 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 305 SPELL_EFFECT_305
1152 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 306 SPELL_EFFECT_UPDATE_INTERACTIONS
1153 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 307 SPELL_EFFECT_307
1154 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 308 SPELL_EFFECT_CANCEL_PRELOAD_WORLD
1155 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 309 SPELL_EFFECT_PRELOAD_WORLD
1156 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 310 SPELL_EFFECT_310
1157 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 311 SPELL_EFFECT_ENSURE_WORLD_LOADED
1158 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 312 SPELL_EFFECT_312
1159 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 313 SPELL_EFFECT_CHANGE_ITEM_BONUSES_2
1160 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 314 SPELL_EFFECT_ADD_SOCKET_BONUS
1161 {EFFECT_IMPLICIT_TARGET_CASTER, TARGET_OBJECT_TYPE_UNIT}, // 315 SPELL_EFFECT_LEARN_TRANSMOG_APPEARANCE_FROM_ITEM_MOD_APPEARANCE_GROUP
1162} };
1163
1165 : Id(spellName->ID), Difficulty(difficulty)
1166{
1167 _effects.reserve(32);
1168 for (SpellEffectEntry const* spellEffect : data.Effects)
1169 {
1170 if (!spellEffect)
1171 continue;
1172
1174 }
1175
1176 // Correct EffectIndex for blank effects
1177 for (size_t i = 0; i < _effects.size(); ++i)
1178 {
1179 _effects[i]._spellInfo = this;
1180 _effects[i].EffectIndex = SpellEffIndex(i);
1181 }
1182
1183 _effects.shrink_to_fit();
1184
1185 SpellName = &spellName->Name;
1186
1187 // SpellMiscEntry
1188 if (SpellMiscEntry const* _misc = data.Misc)
1189 {
1190 Attributes = _misc->Attributes[0];
1191 AttributesEx = _misc->Attributes[1];
1192 AttributesEx2 = _misc->Attributes[2];
1193 AttributesEx3 = _misc->Attributes[3];
1194 AttributesEx4 = _misc->Attributes[4];
1195 AttributesEx5 = _misc->Attributes[5];
1196 AttributesEx6 = _misc->Attributes[6];
1197 AttributesEx7 = _misc->Attributes[7];
1198 AttributesEx8 = _misc->Attributes[8];
1199 AttributesEx9 = _misc->Attributes[9];
1200 AttributesEx10 = _misc->Attributes[10];
1201 AttributesEx11 = _misc->Attributes[11];
1202 AttributesEx12 = _misc->Attributes[12];
1203 AttributesEx13 = _misc->Attributes[13];
1204 AttributesEx14 = _misc->Attributes[14];
1205 CastTimeEntry = sSpellCastTimesStore.LookupEntry(_misc->CastingTimeIndex);
1206 DurationEntry = sSpellDurationStore.LookupEntry(_misc->DurationIndex);
1207 RangeEntry = sSpellRangeStore.LookupEntry(_misc->RangeIndex);
1208 Speed = _misc->Speed;
1209 LaunchDelay = _misc->LaunchDelay;
1210 SchoolMask = _misc->SchoolMask;
1211 IconFileDataId = _misc->SpellIconFileDataID;
1212 ActiveIconFileDataId = _misc->ActiveIconFileDataID;
1213 ContentTuningId = _misc->ContentTuningID;
1214 ShowFutureSpellPlayerConditionID = _misc->ShowFutureSpellPlayerConditionID;
1215 }
1216
1217 // SpellScalingEntry
1218 if (SpellScalingEntry const* _scaling = data.Scaling)
1219 {
1220 Scaling.MinScalingLevel = _scaling->MinScalingLevel;
1221 Scaling.MaxScalingLevel = _scaling->MaxScalingLevel;
1222 Scaling.ScalesFromItemLevel = _scaling->ScalesFromItemLevel;
1223 }
1224
1225 // SpellAuraOptionsEntry
1226 if (SpellAuraOptionsEntry const* _options = data.AuraOptions)
1227 {
1228 ProcFlags = _options->ProcTypeMask;
1229 ProcChance = _options->ProcChance;
1230 ProcCharges = _options->ProcCharges;
1231 ProcCooldown = _options->ProcCategoryRecovery;
1232 StackAmount = _options->CumulativeAura;
1233 if (SpellProcsPerMinuteEntry const* _ppm = sSpellProcsPerMinuteStore.LookupEntry(_options->SpellProcsPerMinuteID))
1234 {
1235 ProcBasePPM = _ppm->BaseProcRate;
1236 ProcPPMMods = sDB2Manager.GetSpellProcsPerMinuteMods(_ppm->ID);
1237 }
1238 }
1239
1240 // SpellAuraRestrictionsEntry
1241 if (SpellAuraRestrictionsEntry const* _aura = data.AuraRestrictions)
1242 {
1243 CasterAuraState = _aura->CasterAuraState;
1244 TargetAuraState = _aura->TargetAuraState;
1245 ExcludeCasterAuraState = _aura->ExcludeCasterAuraState;
1246 ExcludeTargetAuraState = _aura->ExcludeTargetAuraState;
1247 CasterAuraSpell = _aura->CasterAuraSpell;
1248 TargetAuraSpell = _aura->TargetAuraSpell;
1249 ExcludeCasterAuraSpell = _aura->ExcludeCasterAuraSpell;
1250 ExcludeTargetAuraSpell = _aura->ExcludeTargetAuraSpell;
1251 CasterAuraType = AuraType(_aura->CasterAuraType);
1252 TargetAuraType = AuraType(_aura->TargetAuraType);
1253 ExcludeCasterAuraType = AuraType(_aura->ExcludeCasterAuraType);
1254 ExcludeTargetAuraType = AuraType(_aura->ExcludeTargetAuraType);
1255 }
1256
1257 // SpellCastingRequirementsEntry
1258 if (SpellCastingRequirementsEntry const* _castreq = data.CastingRequirements)
1259 {
1260 RequiresSpellFocus = _castreq->RequiresSpellFocus;
1261 FacingCasterFlags = _castreq->FacingCasterFlags;
1262 RequiredAreasID = _castreq->RequiredAreasID;
1263 }
1264
1265 // SpellCategoriesEntry
1266 if (SpellCategoriesEntry const* _categories = data.Categories)
1267 {
1268 CategoryId = _categories->Category;
1269 Dispel = _categories->DispelType;
1270 Mechanic = _categories->Mechanic;
1271 StartRecoveryCategory = _categories->StartRecoveryCategory;
1272 DmgClass = _categories->DefenseType;
1273 PreventionType = _categories->PreventionType;
1274 ChargeCategoryId = _categories->ChargeCategory;
1275 }
1276
1277 // SpellClassOptionsEntry
1278 if (SpellClassOptionsEntry const* _class = data.ClassOptions)
1279 {
1280 SpellFamilyName = _class->SpellClassSet;
1281 SpellFamilyFlags = _class->SpellClassMask;
1282 }
1283
1284 // SpellCooldownsEntry
1285 if (SpellCooldownsEntry const* _cooldowns = data.Cooldowns)
1286 {
1287 RecoveryTime = _cooldowns->RecoveryTime;
1288 CategoryRecoveryTime = _cooldowns->CategoryRecoveryTime;
1289 StartRecoveryTime = _cooldowns->StartRecoveryTime;
1290 CooldownAuraSpellId = _cooldowns->AuraSpellID;
1291 }
1292
1293 // SpellEquippedItemsEntry
1294 if (SpellEquippedItemsEntry const* _equipped = data.EquippedItems)
1295 {
1296 EquippedItemClass = _equipped->EquippedItemClass;
1297 EquippedItemSubClassMask = _equipped->EquippedItemSubclass;
1298 EquippedItemInventoryTypeMask = _equipped->EquippedItemInvTypes;
1299 }
1300
1301 // SpellInterruptsEntry
1302 if (SpellInterruptsEntry const* _interrupt = data.Interrupts)
1303 {
1304 InterruptFlags = SpellInterruptFlags(_interrupt->InterruptFlags);
1305 AuraInterruptFlags = SpellAuraInterruptFlags(_interrupt->AuraInterruptFlags[0]);
1306 AuraInterruptFlags2 = SpellAuraInterruptFlags2(_interrupt->AuraInterruptFlags[1]);
1307 ChannelInterruptFlags = SpellAuraInterruptFlags(_interrupt->ChannelInterruptFlags[0]);
1308 ChannelInterruptFlags2 = SpellAuraInterruptFlags2(_interrupt->ChannelInterruptFlags[1]);
1309 }
1310
1311 for (SpellLabelEntry const* label : data.Labels)
1312 Labels.insert(label->LabelID);
1313
1314 // SpellLevelsEntry
1315 if (SpellLevelsEntry const* _levels = data.Levels)
1316 {
1317 MaxLevel = _levels->MaxLevel;
1318 BaseLevel = _levels->BaseLevel;
1319 SpellLevel = _levels->SpellLevel;
1320 }
1321
1322 // SpellPowerEntry
1323 PowerCosts = data.Powers;
1324
1325 // SpellReagentsEntry
1326 if (SpellReagentsEntry const* _reagents = data.Reagents)
1327 {
1328 Reagent = _reagents->Reagent;
1329 ReagentCount = _reagents->ReagentCount;
1330 }
1331
1333
1334 // SpellShapeshiftEntry
1335 if (SpellShapeshiftEntry const* _shapeshift = data.Shapeshift)
1336 {
1337 Stances = MAKE_PAIR64(_shapeshift->ShapeshiftMask[0], _shapeshift->ShapeshiftMask[1]);
1338 StancesNot = MAKE_PAIR64(_shapeshift->ShapeshiftExclude[0], _shapeshift->ShapeshiftExclude[1]);
1339 }
1340
1341 // SpellTargetRestrictionsEntry
1342 if (SpellTargetRestrictionsEntry const* _target = data.TargetRestrictions)
1343 {
1344 ConeAngle = _target->ConeDegrees;
1345 Width = _target->Width;
1346 Targets = _target->Targets;
1347 TargetCreatureType = _target->TargetCreatureType;
1348 MaxAffectedTargets = _target->MaxTargets;
1349 MaxTargetLevel = _target->MaxTargetLevel;
1350 }
1351
1352 // SpellTotemsEntry
1353 if (SpellTotemsEntry const* _totem = data.Totems)
1354 {
1355 TotemCategory = _totem->RequiredTotemCategoryID;
1356 Totem = _totem->Totem;
1357 }
1358
1359 _visuals = data.Visuals;
1360}
1361
1362SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, std::vector<SpellEffectEntry> const& effects)
1363 : Id(spellName->ID), Difficulty(difficulty)
1364{
1365 SpellName = &spellName->Name;
1366
1367 _effects.reserve(32);
1368 for (SpellEffectEntry const& spellEffect : effects)
1369 Trinity::Containers::EnsureWritableVectorIndex(_effects, spellEffect.EffectIndex) = SpellEffectInfo(this, spellEffect);
1370
1371 // Correct EffectIndex for blank effects
1372 for (size_t i = 0; i < _effects.size(); ++i)
1373 {
1374 _effects[i]._spellInfo = this;
1375 _effects[i].EffectIndex = SpellEffIndex(i);
1376 }
1377
1378 _effects.shrink_to_fit();
1379}
1380
1382{
1384}
1385
1387{
1388 return CategoryId;
1389}
1390
1392{
1393 for (SpellEffectInfo const& eff : GetEffects())
1394 if (eff.IsEffect(effect))
1395 return true;
1396
1397 return false;
1398}
1399
1401{
1402 for (SpellEffectInfo const& effect : GetEffects())
1403 if (effect.IsAura(aura))
1404 return true;
1405
1406 return false;
1407}
1408
1410{
1411 for (SpellEffectInfo const& effect : GetEffects())
1412 if (effect.IsAreaAuraEffect())
1413 return true;
1414
1415 return false;
1416}
1417
1419{
1420 for (SpellEffectInfo const& effect : GetEffects())
1421 {
1422 if (effect.IsEffect())
1423 {
1424 switch (effect.Effect)
1425 {
1434 continue;
1435 default:
1436 return false;
1437 }
1438 }
1439 }
1440
1441 return true;
1442}
1443
1445{
1446 for (SpellEffectInfo const& effect : GetEffects())
1447 if (effect.TargetA.GetTarget() == target || effect.TargetB.GetTarget() == target)
1448 return true;
1449
1450 return false;
1451}
1452
1453bool SpellInfo::CanBeInterrupted(WorldObject const* interruptCaster, Unit const* interruptTarget, bool ignoreImmunity /*= false*/) const
1454{
1459 || (interruptCaster && interruptCaster->IsUnit() && interruptCaster->ToUnit()->HasAuraTypeWithMiscvalue(SPELL_AURA_ALLOW_INTERRUPT_SPELL, Id))
1460 || ((!(interruptTarget->GetMechanicImmunityMask() & (1 << MECHANIC_INTERRUPT)) || ignoreImmunity)
1463}
1464
1466{
1468}
1469
1471{
1472 if (GetEffects().size() < 2)
1473 return false;
1474
1478 || Id == 64323;
1479}
1480
1482{
1484}
1485
1487{
1488 for (SpellEffectInfo const& effect : GetEffects())
1489 {
1490 if (effect.Effect == SPELL_EFFECT_SKILL)
1491 {
1492 uint32 skill = effect.MiscValue;
1493
1494 if (IsProfessionSkill(skill))
1495 return true;
1496 }
1497 }
1498 return false;
1499}
1500
1502{
1503 for (SpellEffectInfo const& effect : GetEffects())
1504 {
1505 if (effect.Effect == SPELL_EFFECT_SKILL)
1506 {
1507 uint32 skill = effect.MiscValue;
1508
1509 if (IsPrimaryProfessionSkill(skill))
1510 return true;
1511 }
1512 }
1513 return false;
1514}
1515
1517{
1518 return IsPrimaryProfession() && GetRank() == 1;
1519}
1520
1522{
1523 SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(Id);
1524
1525 for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
1526 if (_spell_idx->second->SkillLine == int32(skillType))
1527 return true;
1528
1529 return false;
1530}
1531
1533{
1534 for (SpellEffectInfo const& effect : GetEffects())
1535 if (effect.IsEffect() && (effect.IsTargetingArea() || effect.IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) || effect.IsAreaAuraEffect()))
1536 return true;
1537
1538 return false;
1539}
1540
1541// checks if spell targets are selected from area, doesn't include spell effects in check (like area wide auras for example)
1543{
1544 for (SpellEffectInfo const& effect : GetEffects())
1545 if (effect.IsEffect() && effect.IsTargetingArea())
1546 return true;
1547
1548 return false;
1549}
1550
1552{
1554}
1555
1556bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const
1557{
1559 return true;
1560
1561 /*
1562 for (SpellEffectInfo const& effect : GetEffects())
1563 {
1564 if (effect.IsEffect())
1565 {
1566 if (effect.TargetA.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CHANNEL
1567 || effect.TargetB.GetSelectionCategory() == TARGET_SELECT_CATEGORY_CHANNEL)
1568 return true;
1569 }
1570 }
1571 */
1572
1573 if (triggeringSpell->IsChanneled())
1574 {
1575 uint32 mask = 0;
1576 for (SpellEffectInfo const& effect : GetEffects())
1577 {
1578 if (effect.TargetA.GetTarget() != TARGET_UNIT_CASTER && effect.TargetA.GetTarget() != TARGET_DEST_CASTER
1579 && effect.TargetB.GetTarget() != TARGET_UNIT_CASTER && effect.TargetB.GetTarget() != TARGET_DEST_CASTER)
1580 {
1581 mask |= effect.GetProvidedTargetMask();
1582 }
1583 }
1584
1585 if (mask & TARGET_FLAG_UNIT_MASK)
1586 return true;
1587 }
1588
1589 return false;
1590}
1591
1593{
1595}
1596
1598{
1599 if (IsPassive())
1600 return false;
1602 return false;
1603 return true;
1604}
1605
1607{
1608 if (IsPassive())
1609 return false;
1610
1611 // All stance spells. if any better way, change it.
1612 for (SpellEffectInfo const& effect : GetEffects())
1613 {
1614 switch (SpellFamilyName)
1615 {
1617 // Paladin aura Spell
1618 if (effect.Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID)
1619 return false;
1620 break;
1621 case SPELLFAMILY_DRUID:
1622 // Druid form Spell
1623 if (effect.Effect == SPELL_EFFECT_APPLY_AURA &&
1624 effect.ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT)
1625 return false;
1626 break;
1627 }
1628 }
1629
1630 return true;
1631}
1632
1634{
1636}
1637
1639{
1640 return IsPassive() || Id == 55849 || Id == 40075 || Id == 44413; // Power Spark, Fel Flak Fire, Incanter's Absorption
1641}
1642
1644{
1647}
1648
1650{
1652 return true;
1653
1654 SpellCategoryEntry const* category = sSpellCategoryStore.LookupEntry(CategoryId);
1655 return category && category->Flags & SPELL_CATEGORY_FLAG_COOLDOWN_STARTS_ON_EVENT;
1656}
1657
1659{
1661}
1662
1664{
1666}
1667
1669{
1671 return true;
1672
1673 for (SpellEffectInfo const& effect : GetEffects())
1674 {
1675 if (!effect.IsEffect())
1676 continue;
1677
1678 if (effect.TargetA.GetObjectType() == TARGET_OBJECT_TYPE_CORPSE || effect.TargetB.GetObjectType() == TARGET_OBJECT_TYPE_CORPSE)
1679 return true;
1680 }
1681
1682 return false;
1683}
1684
1686{
1687 for (SpellEffectInfo const& effect : GetEffects())
1688 {
1689 switch (effect.TargetA.GetCheckType())
1690 {
1691 case TARGET_CHECK_PARTY:
1692 case TARGET_CHECK_RAID:
1694 return true;
1695 default:
1696 break;
1697 }
1698 }
1699
1700 return false;
1701}
1702
1703bool SpellInfo::CanBeUsedInCombat(Unit const* caster) const
1704{
1707}
1708
1710{
1711 return NegativeEffects.none();
1712}
1713
1715{
1716 return !NegativeEffects.test(effIndex);
1717}
1718
1720{
1722}
1723
1725{
1727}
1728
1730{
1732}
1733
1735{
1736 return (SpellFamilyName == SPELLFAMILY_HUNTER && !(SpellFamilyFlags[1] & 0x10000000)) // for 53352, cannot find better way
1739}
1740
1742{
1744}
1745
1747{
1749}
1750
1752{
1753 return Speed > 0.0f || LaunchDelay > 0.0f;
1754}
1755
1757{
1758 WeaponAttackType result;
1759 switch (DmgClass)
1760 {
1763 result = OFF_ATTACK;
1764 else
1765 result = BASE_ATTACK;
1766 break;
1769 break;
1770 default:
1771 // Wands
1773 result = RANGED_ATTACK;
1774 else
1775 result = BASE_ATTACK;
1776 break;
1777 }
1778
1779 return result;
1780}
1781
1783{
1784 // item neutral spell
1785 if (EquippedItemClass == -1)
1786 return true;
1787
1788 // item dependent spell
1789 if (item && item->IsFitToSpellRequirements(this))
1790 return true;
1791
1792 return false;
1793}
1794
1795bool SpellInfo::IsAffected(uint32 familyName, flag128 const& familyFlags) const
1796{
1797 if (!familyName)
1798 return true;
1799
1800 if (familyName != SpellFamilyName)
1801 return false;
1802
1803 if (familyFlags && !(familyFlags & SpellFamilyFlags))
1804 return false;
1805
1806 return true;
1807}
1808
1810{
1812}
1813
1815{
1816 if (!IsAffectedBySpellMods())
1817 return false;
1818
1819 SpellInfo const* affectSpell = sSpellMgr->GetSpellInfo(mod->spellId, Difficulty);
1820 if (!affectSpell)
1821 return false;
1822
1823 switch (mod->type)
1824 {
1825 case SPELLMOD_FLAT:
1826 case SPELLMOD_PCT:
1827 // TEMP: dont use IsAffected - !familyName and !familyFlags are not valid options for spell mods
1828 // TODO: investigate if the !familyName and !familyFlags conditions are even valid for all other (nonmod) uses of SpellInfo::IsAffected
1829 return affectSpell->SpellFamilyName == SpellFamilyName && static_cast<SpellModifierByClassMask const*>(mod)->mask & SpellFamilyFlags;
1831 return HasLabel(static_cast<SpellFlatModifierByLabel const*>(mod)->value.LabelID);
1832 case SPELLMOD_LABEL_PCT:
1833 return HasLabel(static_cast<SpellPctModifierByLabel const*>(mod)->value.LabelID);
1834 default:
1835 break;
1836 }
1837
1838 return false;
1839}
1840
1841bool SpellInfo::CanPierceImmuneAura(SpellInfo const* auraSpellInfo) const
1842{
1843 // aura can't be pierced
1844 if (!auraSpellInfo || auraSpellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES))
1845 return false;
1846
1847 // these spells pierce all available spells (Resurrection Sickness for example)
1849 return true;
1850
1851 // these spells (Cyclone for example) can pierce all...
1853 {
1854 // ...but not these (Divine shield, Ice block, Cyclone and Banish for example)
1855 if (auraSpellInfo->Mechanic != MECHANIC_IMMUNE_SHIELD &&
1856 auraSpellInfo->Mechanic != MECHANIC_INVULNERABILITY &&
1857 (auraSpellInfo->Mechanic != MECHANIC_BANISH || (IsRankOf(auraSpellInfo) && auraSpellInfo->Dispel != DISPEL_NONE))) // Banish shouldn't be immune to itself, but Cyclone should
1858 return true;
1859 }
1860
1861 // Dispels other auras on immunity, check if this spell makes the unit immune to aura
1863 return true;
1864
1865 return false;
1866}
1867
1868bool SpellInfo::CanDispelAura(SpellInfo const* auraSpellInfo) const
1869{
1870 // These auras (like Divine Shield) can't be dispelled
1871 if (auraSpellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES))
1872 return false;
1873
1874 // These spells (like Mass Dispel) can dispel all auras
1876 return true;
1877
1878 // These auras (Cyclone for example) are not dispelable
1881 return false;
1882
1883 return true;
1884}
1885
1887{
1888 // all other single target spells have if it has AttributesEx5
1890 return true;
1891
1892 return false;
1893}
1894
1896{
1897 SpellSpecificType spellSpec1 = GetSpellSpecific();
1898 SpellSpecificType spellSpec2 = spellInfo->GetSpellSpecific();
1899 switch (spellSpec1)
1900 {
1911 return spellSpec1 == spellSpec2;
1913 return spellSpec2 == SPELL_SPECIFIC_FOOD
1914 || spellSpec2 == SPELL_SPECIFIC_FOOD_AND_DRINK;
1916 return spellSpec2 == SPELL_SPECIFIC_DRINK
1917 || spellSpec2 == SPELL_SPECIFIC_FOOD_AND_DRINK;
1919 return spellSpec2 == SPELL_SPECIFIC_FOOD
1920 || spellSpec2 == SPELL_SPECIFIC_DRINK
1921 || spellSpec2 == SPELL_SPECIFIC_FOOD_AND_DRINK;
1922 default:
1923 return false;
1924 }
1925}
1926
1928{
1929 SpellSpecificType spellSpec = GetSpellSpecific();
1930 switch (spellSpec)
1931 {
1940 return spellSpec == spellInfo->GetSpellSpecific();
1941 default:
1942 return false;
1943 }
1944}
1945
1947{
1948 // talents that learn spells can have stance requirements that need ignore
1949 // (this requirement only for client-side stance show in talent description)
1950 /* TODO: 6.x fix this in proper way (probably spell flags/attributes?)
1951 if (GetTalentSpellCost(Id) > 0 && HasEffect(SPELL_EFFECT_LEARN_SPELL))
1952 return SPELL_CAST_OK;*/
1953
1954 //if (HasAttribute(SPELL_ATTR13_ACTIVATES_REQUIRED_SHAPESHIFT))
1955 // return SPELL_CAST_OK;
1956
1957 uint64 stanceMask = (form ? UI64LIT(1) << (form - 1) : 0);
1958
1959 if (stanceMask & StancesNot) // can explicitly not be cast in this stance
1961
1962 if (stanceMask & Stances) // can explicitly be cast in this stance
1963 return SPELL_CAST_OK;
1964
1965 bool actAsShifted = false;
1966 SpellShapeshiftFormEntry const* shapeInfo = nullptr;
1967 if (form > 0)
1968 {
1969 shapeInfo = sSpellShapeshiftFormStore.LookupEntry(form);
1970 if (!shapeInfo)
1971 {
1972 TC_LOG_ERROR("spells", "GetErrorAtShapeshiftedCast: unknown shapeshift {}", form);
1973 return SPELL_CAST_OK;
1974 }
1975 actAsShifted = !shapeInfo->GetFlags().HasFlag(SpellShapeshiftFormFlags::Stance);
1976 }
1977
1978 if (actAsShifted)
1979 {
1980 if (HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFTED) || (shapeInfo && shapeInfo->GetFlags().HasFlag(SpellShapeshiftFormFlags::CanOnlyCastShapeshiftSpells))) // not while shapeshifted
1982 else if (Stances != 0) // needs other shapeshift
1984 }
1985 else
1986 {
1987 // needs shapeshift
1990 }
1991
1992 return SPELL_CAST_OK;
1993}
1994
1995SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player) const
1996{
1997 // normal case
1998 if (RequiredAreasID > 0)
1999 {
2000 bool found = false;
2001 std::vector<uint32> areaGroupMembers = sDB2Manager.GetAreasForGroup(RequiredAreasID);
2002 for (uint32 areaId : areaGroupMembers)
2003 {
2004 if (DB2Manager::IsInArea(area_id, areaId))
2005 {
2006 found = true;
2007 break;
2008 }
2009 }
2010
2011 if (!found)
2013 }
2014
2015 // continent limitation (virtual continent)
2017 {
2019 if (player && player->HasAuraType(SPELL_AURA_MOUNT_RESTRICTIONS))
2020 {
2021 for (AuraEffect const* auraEffect : player->GetAuraEffectsByType(SPELL_AURA_MOUNT_RESTRICTIONS))
2022 mountFlags |= AreaMountFlags(auraEffect->GetMiscValue());
2023 }
2024 else if (AreaTableEntry const* areaTable = sAreaTableStore.LookupEntry(area_id))
2025 mountFlags = areaTable->GetMountFlags();
2026
2027 if (!(mountFlags.HasFlag(AreaMountFlags::AllowFlyingMounts)))
2029
2030 if (player)
2031 {
2032 uint32 mapToCheck = map_id;
2033 if (MapEntry const* mapEntry = sMapStore.LookupEntry(map_id))
2034 mapToCheck = mapEntry->CosmeticParentMapID;
2035
2036 if ((mapToCheck == 1116 || mapToCheck == 1464) && !player->HasSpell(191645)) // Draenor Pathfinder
2038 else if (mapToCheck == 1220 && !player->HasSpell(233368)) // Broken Isles Pathfinder
2040 else if ((mapToCheck == 1642 || mapToCheck == 1643) && !player->HasSpell(278833)) // Battle for Azeroth Pathfinder
2042 }
2043 }
2044
2045 // raid instance limitation
2047 {
2048 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2049 if (!mapEntry || mapEntry->IsRaid())
2051 }
2052
2054 {
2055 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2056 if (!mapEntry || !mapEntry->IsDungeon())
2058 }
2059
2061 {
2062 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2063 if (!mapEntry || mapEntry->IsBattleground())
2065 }
2066
2067 // DB base check (if non empty then must fit at least single for allow)
2068 SpellAreaMapBounds saBounds = sSpellMgr->GetSpellAreaMapBounds(Id);
2069 if (saBounds.first != saBounds.second)
2070 {
2071 for (SpellAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
2072 {
2073 if (itr->second.IsFitToRequirements(player, zone_id, area_id))
2074 return SPELL_CAST_OK;
2075 }
2077 }
2078
2079 // bg spell checks
2080 switch (Id)
2081 {
2082 case 23333: // Warsong Flag
2083 case 23335: // Silverwing Flag
2084 return map_id == 489 && player && player->InBattleground() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
2085 case 2584: // Waiting to Resurrect
2086 case 42792: // Recently Dropped Flag
2087 case 43681: // Inactive
2088 case 44535: // Spirit Heal (mana)
2089 {
2090 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2091 if (!mapEntry)
2093
2094 return zone_id == AREA_WINTERGRASP || (mapEntry->IsBattleground() && player && player->InBattleground()) ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
2095 }
2096 case 44521: // Preparation
2097 {
2098 if (!player)
2100
2101 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2102 if (!mapEntry)
2104
2105 if (!mapEntry->IsBattleground())
2107
2108 Battleground* bg = player->GetBattleground();
2110 }
2111 case 32724: // Gold Team (Alliance)
2112 case 32725: // Green Team (Alliance)
2113 case 35774: // Gold Team (Horde)
2114 case 35775: // Green Team (Horde)
2115 {
2116 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2117 if (!mapEntry)
2119
2120 return mapEntry->IsBattleArena() && player && player->InBattleground() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
2121 }
2122 case 32727: // Arena Preparation
2123 {
2124 if (!player)
2126
2127 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2128 if (!mapEntry)
2130
2131 if (!mapEntry->IsBattleArena())
2133
2134 Battleground* bg = player->GetBattleground();
2136 }
2137 }
2138
2139 // aura limitations
2140 if (player)
2141 {
2142 for (SpellEffectInfo const& effect : GetEffects())
2143 {
2144 if (!effect.IsAura())
2145 continue;
2146
2147 switch (effect.ApplyAuraName)
2148 {
2150 {
2151 if (SpellShapeshiftFormEntry const* spellShapeshiftForm = sSpellShapeshiftFormStore.LookupEntry(effect.MiscValue))
2152 if (uint32 mountType = spellShapeshiftForm->MountTypeID)
2153 if (!player->GetMountCapability(mountType))
2154 return SPELL_FAILED_NOT_HERE;
2155 break;
2156 }
2157 case SPELL_AURA_MOUNTED:
2158 {
2159 uint32 mountType = effect.MiscValueB;
2160 if (MountEntry const* mountEntry = sDB2Manager.GetMount(Id))
2161 mountType = mountEntry->MountTypeID;
2162 if (mountType && !player->GetMountCapability(mountType))
2163 return SPELL_FAILED_NOT_HERE;
2164 break;
2165 }
2166 default:
2167 break;
2168 }
2169 }
2170 }
2171
2172 return SPELL_CAST_OK;
2173}
2174
2175SpellCastResult SpellInfo::CheckTarget(WorldObject const* caster, WorldObject const* target, bool implicit /*= true*/) const
2176{
2177 if (HasAttribute(SPELL_ATTR1_EXCLUDE_CASTER) && caster == target)
2179
2180 // check visibility - ignore invisibility/stealth for implicit (area) targets
2181 if (!HasAttribute(SPELL_ATTR6_IGNORE_PHASE_SHIFT) && !caster->CanSeeOrDetect(target, implicit))
2183
2184 Unit const* unitTarget = target->ToUnit();
2185
2187 {
2188 auto getCreatorOrSelf = [](WorldObject const* obj)
2189 {
2190 ObjectGuid creator = obj->GetCreatorGUID();
2191 if (creator.IsEmpty())
2192 creator = obj->GetGUID();
2193
2194 return creator;
2195 };
2196 if (getCreatorOrSelf(caster) != getCreatorOrSelf(target))
2198 }
2199
2200 // creature/player specific target checks
2201 if (unitTarget)
2202 {
2203 // spells cannot be cast if target has a pet in combat either
2206
2207 // only spells with SPELL_ATTR3_ONLY_TARGET_GHOSTS can target ghosts
2209 {
2212 else
2214 }
2215
2216 if (caster != unitTarget)
2217 {
2218 if (caster->GetTypeId() == TYPEID_PLAYER)
2219 {
2220 // Do not allow these spells to target creatures not tapped by us (Banish, Polymorph, many quest spells)
2222 if (Creature const* targetCreature = unitTarget->ToCreature())
2223 if (targetCreature->hasLootRecipient() && !targetCreature->isTappedBy(caster->ToPlayer()))
2225
2227 {
2228 Creature const* targetCreature = unitTarget->ToCreature();
2229 if (!targetCreature)
2231
2232 if (!targetCreature->CanHaveLoot() || !LootTemplates_Pickpocketing.HaveLootFor(targetCreature->GetCreatureDifficulty()->PickPocketLootID))
2234 }
2235
2236 // Not allow disarm unarmed player
2238 {
2239 if (unitTarget->GetTypeId() == TYPEID_PLAYER)
2240 {
2241 Player const* player = unitTarget->ToPlayer();
2242 if (!player->GetWeaponForAttack(BASE_ATTACK) || !player->IsUseEquipedWeapon(true))
2244 }
2245 else if (!unitTarget->GetVirtualItemId(0))
2247 }
2248 }
2249 }
2250
2252 if (!unitTarget->IsSummon() || unitTarget->ToTempSummon()->GetSummonerGUID() != caster->GetGUID())
2254
2258 }
2259 // corpse specific target checks
2260 else if (Corpse const* corpseTarget = target->ToCorpse())
2261 {
2262 // cannot target bare bones
2263 if (corpseTarget->GetType() == CORPSE_BONES)
2265 // we have to use owner for some checks (aura preventing resurrection for example)
2266 if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()))
2267 unitTarget = owner;
2268 // we're not interested in corpses without owner
2269 else
2271 }
2272 // other types of objects - always valid
2273 else return SPELL_CAST_OK;
2274
2275 // corpseOwner and unit specific target checks
2276 if (!unitTarget->IsPlayer())
2277 {
2280
2283 }
2286
2287 if (!IsAllowingDeadTarget() && !unitTarget->IsAlive())
2289
2290 // check this flag only for implicit targets (chain and area), allow to explicitly target units for spells like Shield of Righteousness
2293
2294 // checked in Unit::IsValidAttack/AssistTarget, shouldn't be checked for ENTRY targets
2295 //if (!HasAttribute(SPELL_ATTR6_CAN_TARGET_UNTARGETABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNINTERACTIBLE))
2296 // return SPELL_FAILED_BAD_TARGETS;
2297
2298 if (!CheckTargetCreatureType(unitTarget))
2299 {
2300 if (target->GetTypeId() == TYPEID_PLAYER)
2302 else
2304 }
2305
2306 // check GM mode and GM invisibility - only for player casts (npc casts are controlled by AI) and negative spells
2307 if (unitTarget != caster && (caster->GetAffectingPlayer() || !IsPositive()) && unitTarget->GetTypeId() == TYPEID_PLAYER)
2308 {
2309 if (!unitTarget->ToPlayer()->IsVisible())
2311
2312 if (unitTarget->ToPlayer()->IsGameMaster())
2314 }
2315
2316 // not allow casting on flying player
2319
2320 /* TARGET_UNIT_MASTER gets blocked here for passengers, because the whole idea of this check is to
2321 not allow passengers to be implicitly hit by spells, however this target type should be an exception,
2322 if this is left it kills spells that award kill credit from vehicle to master (few spells),
2323 the use of these 2 covers passenger target check, logically, if vehicle cast this to master it should always hit
2324 him, because it would be it's passenger, there's no such case where this gets to fail legitimacy, this problem
2325 cannot be solved from within the check in other way since target type cannot be called for the spell currently
2326 Spell examples: [ID - 52864 Devour Water, ID - 52862 Devour Wind, ID - 49370 Wyrmrest Defender: Destabilize Azure Dragonshrine Effect] */
2327 if (Unit const* unitCaster = caster->ToUnit())
2328 {
2329 if (!unitCaster->IsVehicle() && !(unitCaster->GetCharmerOrOwner() == target))
2330 {
2331 if (TargetAuraState && !unitTarget->HasAuraState(AuraStateType(TargetAuraState), this, unitCaster))
2333
2334 if (ExcludeTargetAuraState && unitTarget->HasAuraState(AuraStateType(ExcludeTargetAuraState), this, unitCaster))
2336 }
2337 }
2338
2339 if (TargetAuraSpell && !unitTarget->HasAura(TargetAuraSpell))
2341
2344
2348
2350 if (Map* map = caster->GetMap())
2351 if (InstanceMap* iMap = map->ToInstanceMap())
2352 if (InstanceScript* instance = iMap->GetInstanceScript())
2353 if (instance->GetCombatResurrectionCharges() == 0 && instance->IsEncounterInProgress())
2355
2356 return SPELL_CAST_OK;
2357}
2358
2359SpellCastResult SpellInfo::CheckExplicitTarget(WorldObject const* caster, WorldObject const* target, Item const* itemTarget /*= nullptr*/) const
2360{
2361 uint32 neededTargets = GetExplicitTargetMask();
2362 if (!target)
2363 {
2365 if (!(neededTargets & TARGET_FLAG_GAMEOBJECT_ITEM) || !itemTarget)
2367 return SPELL_CAST_OK;
2368 }
2369
2370 if (Unit const* unitTarget = target->ToUnit())
2371 {
2373 {
2374 Unit const* unitCaster = caster->ToUnit();
2375 if (neededTargets & TARGET_FLAG_UNIT_ENEMY)
2376 if (caster->IsValidAttackTarget(unitTarget, this))
2377 return SPELL_CAST_OK;
2378 if ((neededTargets & TARGET_FLAG_UNIT_ALLY)
2379 || ((neededTargets & TARGET_FLAG_UNIT_PARTY) && unitCaster && unitCaster->IsInPartyWith(unitTarget))
2380 || ((neededTargets & TARGET_FLAG_UNIT_RAID) && unitCaster && unitCaster->IsInRaidWith(unitTarget)))
2381 if (caster->IsValidAssistTarget(unitTarget, this))
2382 return SPELL_CAST_OK;
2383 if ((neededTargets & TARGET_FLAG_UNIT_MINIPET) && unitCaster)
2384 if (unitTarget->GetGUID() == unitCaster->GetCritterGUID())
2385 return SPELL_CAST_OK;
2386 if ((neededTargets & TARGET_FLAG_UNIT_PASSENGER) && unitCaster)
2387 if (unitTarget->IsOnVehicle(unitCaster))
2388 return SPELL_CAST_OK;
2390 }
2391 }
2392 return SPELL_CAST_OK;
2393}
2394
2396{
2397 // All creatures should be able to cast as passengers freely, restriction and attribute are only for players
2398 if (caster->GetTypeId() != TYPEID_PLAYER)
2399 return SPELL_CAST_OK;
2400
2401 Vehicle* vehicle = caster->GetVehicle();
2402 if (vehicle)
2403 {
2404 uint16 checkMask = 0;
2405 for (SpellEffectInfo const& effect : GetEffects())
2406 {
2407 if (effect.IsAura(SPELL_AURA_MOD_SHAPESHIFT))
2408 {
2409 SpellShapeshiftFormEntry const* shapeShiftFromEntry = sSpellShapeshiftFormStore.LookupEntry(effect.MiscValue);
2410 if (shapeShiftFromEntry && (shapeShiftFromEntry->Flags & 1) == 0) // unk flag
2411 checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED;
2412 break;
2413 }
2414 }
2415
2418
2419 if (!checkMask)
2420 checkMask = VEHICLE_SEAT_FLAG_CAN_ATTACK;
2421
2422 VehicleSeatEntry const* vehicleSeat = vehicle->GetSeatForPassenger(caster);
2424 && (vehicleSeat->Flags & checkMask) != checkMask)
2426
2427 // Can only summon uncontrolled minions/guardians when on controlled vehicle
2429 {
2430 for (SpellEffectInfo const& effect : GetEffects())
2431 {
2432 if (!effect.IsEffect(SPELL_EFFECT_SUMMON))
2433 continue;
2434
2435 SummonPropertiesEntry const* props = sSummonPropertiesStore.LookupEntry(effect.MiscValueB);
2436 if (props && props->Control != SUMMON_CATEGORY_WILD)
2438 }
2439 }
2440 }
2441
2442 return SPELL_CAST_OK;
2443}
2444
2446{
2447 // Curse of Doom & Exorcism: not find another way to fix spell target check :/
2449 {
2450 // not allow cast at player
2451 if (target->GetTypeId() == TYPEID_PLAYER)
2452 return false;
2453 else
2454 return true;
2455 }
2456
2457 // if target is magnet (i.e Grounding Totem) the check is skipped
2458 if (target->IsMagnet())
2459 return true;
2460
2461 uint32 creatureType = target->GetCreatureTypeMask();
2462 return !TargetCreatureType || !creatureType || (creatureType & TargetCreatureType) || target->HasAuraType(SPELL_AURA_IGNORE_SPELL_CREATURE_TYPE_REQUIREMENTS);
2463}
2464
2466{
2468}
2469
2471{
2472 uint64 mask = 0;
2473 if (Mechanic)
2474 mask |= UI64LIT(1) << Mechanic;
2475
2476 for (SpellEffectInfo const& effect : GetEffects())
2477 if (effect.IsEffect() && effect.Mechanic)
2478 mask |= UI64LIT(1) << effect.Mechanic;
2479
2480 return mask;
2481}
2482
2484{
2485 uint64 mask = 0;
2486 if (Mechanic)
2487 mask |= UI64LIT(1) << Mechanic;
2488
2489 if (GetEffect(effIndex).IsEffect() && GetEffect(effIndex).Mechanic)
2490 mask |= UI64LIT(1) << GetEffect(effIndex).Mechanic;
2491
2492 return mask;
2493}
2494
2496{
2497 uint64 mask = 0;
2498 if (Mechanic)
2499 mask |= UI64LIT(1) << Mechanic;
2500
2501 for (SpellEffectInfo const& effect : GetEffects())
2502 if ((effectMask & (1 << effect.EffectIndex)) && effect.Mechanic)
2503 mask |= UI64LIT(1) << effect.Mechanic;
2504
2505 return mask;
2506}
2507
2509{
2510 if (GetEffect(effIndex).IsEffect() && GetEffect(effIndex).Mechanic)
2511 return GetEffect(effIndex).Mechanic;
2512
2513 if (Mechanic)
2514 return Mechanics(Mechanic);
2515
2516 return MECHANIC_NONE;
2517}
2518
2520{
2522}
2523
2525{
2526 // If dispel all
2527 if (type == DISPEL_ALL)
2528 return DISPEL_ALL_MASK;
2529 else
2530 return uint32(1 << type);
2531}
2532
2534{
2535 return ExplicitTargetMask;
2536}
2537
2539{
2540 return _auraState;
2541}
2542
2544{
2545 _auraState = [this]()->AuraStateType
2546 {
2547 // Faerie Fire (Feral)
2548 if (GetCategory() == 1133)
2550
2551 // Swiftmend state on Regrowth, Rejuvenation, Wild Growth
2552 if (SpellFamilyName == SPELLFAMILY_DRUID && (SpellFamilyFlags[0] & 0x50 || SpellFamilyFlags[1] & 0x4000000))
2554
2555 // Deadly poison aura state
2556 if (SpellFamilyName == SPELLFAMILY_ROGUE && SpellFamilyFlags[0] & 0x10000)
2558
2559 // Enrage aura state
2560 if (Dispel == DISPEL_ENRAGE)
2561 return AURA_STATE_ENRAGED;
2562
2563 // Bleeding aura state
2565 return AURA_STATE_BLEED;
2566
2568 for (SpellEffectInfo const& effect : GetEffects())
2569 if (effect.IsAura(SPELL_AURA_MOD_STUN) || effect.IsAura(SPELL_AURA_MOD_ROOT) || effect.IsAura(SPELL_AURA_MOD_ROOT_2))
2570 return AURA_STATE_FROZEN;
2571
2572 switch (Id)
2573 {
2574 case 1064: // Dazed
2575 return AURA_STATE_DAZED;
2576 case 32216: // Victorious
2577 return AURA_STATE_VICTORIOUS;
2578 case 71465: // Divine Surge
2579 case 50241: // Evasive Charges
2580 case 81262: // Efflorescence
2582 case 6950: // Faerie Fire
2583 case 9806: // Phantom Strike
2584 case 9991: // Touch of Zanzil
2585 case 13424: // Faerie Fire
2586 case 13752: // Faerie Fire
2587 case 16432: // Plague Mist
2588 case 20656: // Faerie Fire
2589 case 25602: // Faerie Fire
2590 case 32129: // Faerie Fire
2591 case 35325: // Glowing Blood
2592 case 35328: // Lambent Blood
2593 case 35329: // Vibrant Blood
2594 case 35331: // Black Blood
2595 case 49163: // Perpetual Instability
2596 case 65863: // Faerie Fire
2597 case 79559: // Luxscale Light
2598 case 82855: // Dazzling
2599 case 102953: // In the Rumpus
2600 case 127907: // Phosphorescence
2601 case 127913: // Phosphorescence
2602 case 129007: // Zijin Sting
2603 case 130159: // Fae Touch
2604 case 142537: // Spotter Smoke
2605 case 168455: // Spotted!
2606 case 176905: // Super Sticky Glitter Bomb
2607 case 189502: // Marked
2608 case 201785: // Intruder Alert!
2609 case 201786: // Intruder Alert!
2610 case 201935: // Spotted!
2611 case 239233: // Smoke Bomb
2612 case 319400: // Glitter Burst
2613 case 321470: // Dimensional Shifter Mishap
2614 case 331134: // Spotted
2616 default:
2617 break;
2618 }
2619
2620 return AURA_STATE_NONE;
2621 }();
2622}
2623
2625{
2626 return _spellSpecific;
2627};
2628
2630{
2632 {
2633 switch (SpellFamilyName)
2634 {
2636 {
2637 // Food / Drinks (mostly)
2639 {
2640 bool food = false;
2641 bool drink = false;
2642 for (SpellEffectInfo const& effect : GetEffects())
2643 {
2644 if (!effect.IsAura())
2645 continue;
2646 switch (effect.ApplyAuraName)
2647 {
2648 // Food
2651 food = true;
2652 break;
2653 // Drink
2656 drink = true;
2657 break;
2658 default:
2659 break;
2660 }
2661 }
2662
2663 if (food && drink)
2665 else if (food)
2666 return SPELL_SPECIFIC_FOOD;
2667 else if (drink)
2668 return SPELL_SPECIFIC_DRINK;
2669 }
2670 // scrolls effects
2671 else
2672 {
2673 SpellInfo const* firstRankSpellInfo = GetFirstRankSpell();
2674 switch (firstRankSpellInfo->Id)
2675 {
2676 case 8118: // Strength
2677 case 8099: // Stamina
2678 case 8112: // Spirit
2679 case 8096: // Intellect
2680 case 8115: // Agility
2681 case 8091: // Armor
2682 return SPELL_SPECIFIC_SCROLL;
2683 default:
2684 break;
2685 }
2686 }
2687 break;
2688 }
2689 case SPELLFAMILY_MAGE:
2690 {
2691 // family flags 18(Molten), 25(Frost/Ice), 28(Mage)
2692 if (SpellFamilyFlags[0] & 0x12040000)
2694
2695 // Arcane brillance and Arcane intelect (normal check fails because of flags difference)
2696 if (SpellFamilyFlags[0] & 0x400)
2698
2699 if ((SpellFamilyFlags[0] & 0x1000000) && GetEffect(EFFECT_0).IsAura(SPELL_AURA_MOD_CONFUSE))
2701
2702 break;
2703 }
2705 {
2706 if (Id == 12292) // Death Wish
2708
2709 break;
2710 }
2712 {
2713 // Warlock (Bane of Doom | Bane of Agony | Bane of Havoc)
2714 if (Id == 603 || Id == 980 || Id == 80240)
2715 return SPELL_SPECIFIC_BANE;
2716
2717 // only warlock curses have this
2718 if (Dispel == DISPEL_CURSE)
2719 return SPELL_SPECIFIC_CURSE;
2720
2721 // Warlock (Demon Armor | Demon Skin | Fel Armor)
2722 if (SpellFamilyFlags[1] & 0x20000020 || SpellFamilyFlags[2] & 0x00000010)
2724
2725 //seed of corruption and corruption
2726 if (SpellFamilyFlags[1] & 0x10 || SpellFamilyFlags[0] & 0x2)
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, schoolImmunity](AuraApplication const* aurApp) -> bool
3520 {
3521 SpellInfo const* auraSpellInfo = aurApp->GetBase()->GetSpellInfo();
3522 return ((auraSpellInfo->GetSchoolMask() & schoolImmunity) != 0 && // Check for school mask
3523 CanDispelAura(auraSpellInfo) &&
3524 (IsPositive() != aurApp->IsPositive()) && // Check spell vs aura possitivity
3525 !auraSpellInfo->IsPassive() && // Don't remove passive auras
3526 auraSpellInfo->Id != Id); // Don't remove self
3527 });
3528 }
3529
3530 if (apply && schoolImmunity & SPELL_SCHOOL_MASK_NORMAL)
3532 }
3533
3534 if (uint64 mechanicImmunity = immuneInfo->MechanicImmuneMask)
3535 {
3536 for (uint32 i = 0; i < MAX_MECHANIC; ++i)
3537 if (mechanicImmunity & (UI64LIT(1) << i))
3539
3541 {
3542 if (apply)
3543 target->RemoveAurasWithMechanic(mechanicImmunity, AURA_REMOVE_BY_DEFAULT, Id);
3544 else
3545 {
3546 std::vector<Aura*> aurasToUpdateTargets;
3547 target->RemoveAppliedAuras([mechanicImmunity, &aurasToUpdateTargets](AuraApplication const* aurApp)
3548 {
3549 Aura* aura = aurApp->GetBase();
3550 if (aura->GetSpellInfo()->GetAllEffectsMechanicMask() & mechanicImmunity)
3551 aurasToUpdateTargets.push_back(aura);
3552
3553 // only update targets, don't remove anything
3554 return false;
3555 });
3556
3557 for (Aura* aura : aurasToUpdateTargets)
3558 aura->UpdateTargetMap(aura->GetCaster());
3559 }
3560 }
3561 }
3562
3563 if (uint32 dispelImmunity = immuneInfo->DispelImmuneMask)
3564 {
3565 for (uint32 i = 0; i < DISPEL_MAX; ++i)
3566 if (dispelImmunity & (1 << i))
3568
3570 {
3571 target->RemoveAppliedAuras([dispelImmunity](AuraApplication const* aurApp) -> bool
3572 {
3573 SpellInfo const* spellInfo = aurApp->GetBase()->GetSpellInfo();
3574 uint32 dispelMask = spellInfo->GetDispelMask();
3575 if ((dispelMask & dispelImmunity) == dispelMask)
3576 return true;
3577
3578 return false;
3579 });
3580 }
3581 }
3582
3583 if (uint32 damageImmunity = immuneInfo->DamageSchoolMask)
3584 {
3585 target->ApplySpellImmune(Id, IMMUNITY_DAMAGE, damageImmunity, apply);
3586
3587 if (apply && damageImmunity & SPELL_SCHOOL_MASK_NORMAL)
3589 }
3590
3591 for (AuraType auraType : immuneInfo->AuraTypeImmune)
3592 {
3593 target->ApplySpellImmune(Id, IMMUNITY_STATE, auraType, apply);
3595 target->RemoveAurasByType(auraType, [](AuraApplication const* aurApp) -> bool
3596 {
3597 // if the aura has SPELL_ATTR0_NO_IMMUNITIES, then it cannot be removed by immunity
3598 return !aurApp->GetBase()->GetSpellInfo()->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES);
3599 });
3600 }
3601
3602 for (SpellEffectName effectType : immuneInfo->SpellEffectImmune)
3603 target->ApplySpellImmune(Id, IMMUNITY_EFFECT, effectType, apply);
3604
3605 if (uint8 otherImmuneMask = immuneInfo->OtherImmuneMask)
3606 target->ApplySpellImmune(Id, IMMUNITY_OTHER, otherImmuneMask, apply);
3607}
3608
3610{
3611 if (!auraSpellInfo)
3612 return false;
3613
3614 for (SpellEffectInfo const& effectInfo : _effects)
3615 {
3616 if (!effectInfo.IsEffect())
3617 continue;
3618
3619 SpellEffectInfo::ImmunityInfo const* immuneInfo = effectInfo.GetImmunityInfo();
3620 if (!immuneInfo)
3621 continue;
3622
3624 {
3625 if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask)
3626 if ((auraSpellInfo->SchoolMask & schoolImmunity) != 0)
3627 return true;
3628 }
3629
3630 if (uint64 mechanicImmunity = immuneInfo->MechanicImmuneMask)
3631 if ((mechanicImmunity & (UI64LIT(1) << auraSpellInfo->Mechanic)) != 0)
3632 return true;
3633
3634 if (uint32 dispelImmunity = immuneInfo->DispelImmuneMask)
3635 if (auraSpellInfo->Dispel == dispelImmunity)
3636 return true;
3637
3638 bool immuneToAllEffects = true;
3639 for (SpellEffectInfo const& auraSpellEffectInfo : auraSpellInfo->GetEffects())
3640 {
3641 if (!auraSpellEffectInfo.IsEffect())
3642 continue;
3643
3644 auto spellImmuneItr = immuneInfo->SpellEffectImmune.find(auraSpellEffectInfo.Effect);
3645 if (spellImmuneItr == immuneInfo->SpellEffectImmune.end())
3646 {
3647 immuneToAllEffects = false;
3648 break;
3649 }
3650
3651 if (uint32 mechanic = auraSpellEffectInfo.Mechanic)
3652 {
3653 if (!(immuneInfo->MechanicImmuneMask & (UI64LIT(1) << mechanic)))
3654 {
3655 immuneToAllEffects = false;
3656 break;
3657 }
3658 }
3659
3660 if (!auraSpellInfo->HasAttribute(SPELL_ATTR3_ALWAYS_HIT))
3661 {
3662 if (AuraType auraName = auraSpellEffectInfo.ApplyAuraName)
3663 {
3664 bool isImmuneToAuraEffectApply = false;
3665 auto auraImmuneItr = immuneInfo->AuraTypeImmune.find(auraName);
3666 if (auraImmuneItr != immuneInfo->AuraTypeImmune.end())
3667 isImmuneToAuraEffectApply = true;
3668
3669 if (!isImmuneToAuraEffectApply && !auraSpellInfo->IsPositiveEffect(auraSpellEffectInfo.EffectIndex) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
3670 {
3671 if (uint32 applyHarmfulAuraImmunityMask = immuneInfo->ApplyHarmfulAuraImmuneMask)
3672 if ((auraSpellInfo->GetSchoolMask() & applyHarmfulAuraImmunityMask) != 0)
3673 isImmuneToAuraEffectApply = true;
3674 }
3675
3676 if (!isImmuneToAuraEffectApply)
3677 {
3678 immuneToAllEffects = false;
3679 break;
3680 }
3681 }
3682 }
3683 }
3684
3685 if (immuneToAllEffects)
3686 return true;
3687 }
3688
3689 return false;
3690}
3691
3692// based on client Spell_C::CancelsAuraEffect
3694{
3696 return false;
3697
3699 return false;
3700
3701 for (SpellEffectInfo const& effect : GetEffects())
3702 {
3703 if (!effect.IsEffect(SPELL_EFFECT_APPLY_AURA))
3704 continue;
3705
3706 uint32 const miscValue = static_cast<uint32>(effect.MiscValue);
3707 switch (effect.ApplyAuraName)
3708 {
3710 if (miscValue != aurEff->GetAuraType())
3711 continue;
3712 break;
3715 if (aurEff->GetSpellInfo()->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES) || !(aurEff->GetSpellInfo()->SchoolMask & miscValue))
3716 continue;
3717 break;
3719 if (miscValue != aurEff->GetSpellInfo()->Dispel)
3720 continue;
3721 break;
3723 if (miscValue != aurEff->GetSpellInfo()->Mechanic)
3724 {
3725 if (miscValue != aurEff->GetSpellEffectInfo().Mechanic)
3726 continue;
3727 }
3728 break;
3729 default:
3730 continue;
3731 }
3732
3733 return true;
3734 }
3735
3736 return false;
3737}
3738
3740{
3741 return _allowedMechanicMask;
3742}
3743
3745{
3746 uint64 casterMechanicImmunityMask = caster->GetMechanicImmunityMask();
3747 uint64 mechanicImmunityMask = 0;
3748
3749 if (CanBeInterrupted(nullptr, caster, true))
3750 {
3751 if (casterMechanicImmunityMask & (1 << MECHANIC_SILENCE))
3752 mechanicImmunityMask |= (1 << MECHANIC_SILENCE);
3753
3754 if (casterMechanicImmunityMask & (1 << MECHANIC_INTERRUPT))
3755 mechanicImmunityMask |= (1 << MECHANIC_INTERRUPT);
3756 }
3757
3758 return mechanicImmunityMask;
3759}
3760
3761float SpellInfo::GetMinRange(bool positive /*= false*/) const
3762{
3763 if (!RangeEntry)
3764 return 0.0f;
3765 return RangeEntry->RangeMin[positive ? 1 : 0];
3766}
3767
3768float SpellInfo::GetMaxRange(bool positive /*= false*/, WorldObject* caster /*= nullptr*/, Spell* spell /*= nullptr*/) const
3769{
3770 if (!RangeEntry)
3771 return 0.0f;
3772 float range = RangeEntry->RangeMax[positive ? 1 : 0];
3773 if (caster)
3774 if (Player* modOwner = caster->GetSpellModOwner())
3775 modOwner->ApplySpellMod(this, SpellModOp::Range, range, spell);
3776
3777 return range;
3778}
3779
3780int32 SpellInfo::CalcDuration(WorldObject const* caster /*= nullptr*/) const
3781{
3782 int32 duration = GetDuration();
3783
3784 if (caster)
3785 if (Player* modOwner = caster->GetSpellModOwner())
3786 modOwner->ApplySpellMod(this, SpellModOp::Duration, duration);
3787
3788 return duration;
3789}
3790
3792{
3793 if (!DurationEntry)
3794 return IsPassive() ? -1 : 0;
3795 return (DurationEntry->Duration == -1) ? -1 : abs(DurationEntry->Duration);
3796}
3797
3799{
3800 if (!DurationEntry)
3801 return IsPassive() ? -1 : 0;
3802 return (DurationEntry->MaxDuration == -1) ? -1 : abs(DurationEntry->MaxDuration);
3803}
3804
3805uint32 SpellInfo::CalcCastTime(Spell* spell /*= nullptr*/) const
3806{
3807 int32 castTime = 0;
3808 if (CastTimeEntry)
3809 castTime = std::max(CastTimeEntry->Base, CastTimeEntry->Minimum);
3810
3811 if (castTime <= 0)
3812 return 0;
3813
3814 if (spell)
3815 spell->GetCaster()->ModSpellCastTime(this, castTime, spell);
3816
3818 castTime += 500;
3819
3820 return (castTime > 0) ? uint32(castTime) : 0;
3821}
3822
3824{
3825 uint32 totalTicks = 0;
3826 int32 DotDuration = GetDuration();
3827
3828 for (SpellEffectInfo const& effect : GetEffects())
3829 {
3830 if (effect.IsEffect(SPELL_EFFECT_APPLY_AURA))
3831 {
3832 switch (effect.ApplyAuraName)
3833 {
3848 // skip infinite periodics
3849 if (effect.ApplyAuraPeriod > 0 && DotDuration > 0)
3850 {
3851 totalTicks = static_cast<uint32>(DotDuration) / effect.ApplyAuraPeriod;
3853 ++totalTicks;
3854 }
3855 break;
3856 default:
3857 break;
3858 }
3859 }
3860 }
3861
3862 return totalTicks;
3863}
3864
3866{
3867 return RecoveryTime >