aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/SpellInfo.cpp
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2016-11-12 21:58:00 +0100
committerjoschiwald <joschiwald.trinity@gmail.com>2017-12-26 17:11:18 +0100
commit5a91e1e31b547b5030a95a342dd46d5da1a1c84f (patch)
tree9ad0ae2ac085c6646d0173c080cf1f5a07b124d6 /src/server/game/Spells/SpellInfo.cpp
parent03082db8101f73c90f677f6ffcd6ce21f59b6ce0 (diff)
Core/Spell: revamp of immunities system
- Spell attributes research - Container optimization - Do not skip damage immunity checks on SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY present - Added additonal arguments support to SendCastResult / CheckCast, spells can now send proper error messages - Loads spell immune masks/states/effects at startup. - This cached info is used whenever a spell cast requires immunities to be known beforehand (to see if an aura could be applied for example) Closes #16658 Closes #16901 Closes #18114 (cherry picked from commit 50a3ce5703bdaa4fe16e2e773eabafa9a4818083) Core/Spell: fix warning (cherry picked from commit 3588ff894bef2fc1f1600c73ad67fbdceecf8e2a) Core/Unit: misc codestyle use typedef for constant reference (cherry picked from commit 7943150dcb20597f30259354563d79fb1606b21f) Core/Spell: Fixed immunities for some spells (they were broken before rewrite too) - Warlord's Presence, Uncontrollable Frenzy, Free Friend - Overload, Lightning Tendrils - Fervor, Berserk - Determination (cherry picked from commit fc6844173f70f436b92fb0dbc4398290ce935038) Core/Spell: fix typos (cherry picked from commit f060efbdb4c51a7fe22cb6a9012cc76477a1f92b) Core/Unit: improved handling of some spell attributes - SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE - SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE - SPELL_ATTR3_IGNORE_HIT_RESULT (cherry picked from commit 352c84943c4495631a5dd1e9285cde35fdc23c37) Core/Spell: fix typo Closes #18248 (cherry picked from commit 1ad9c7d3fd4e7cfb2a6b12fc37bd748cf5fd772b) Core/Spell: perform charmer check against player controlling unit. Fixes spellcasts while charmed (cherry picked from commit 425f6c3c34b72190e481ba89fd4757df238475d8) Core/Unit: don't use damage immunity to calculate hit result for the whole spell. Should be used only for damage (cherry picked from commit 9f5df023b746d324588f175e264c62205b69e165) Core/Spell: fix a potential null dereference crash (cherry picked from commit 64304d8b2b33ac04d3013d47b2f50c5023300c2e)
Diffstat (limited to 'src/server/game/Spells/SpellInfo.cpp')
-rw-r--r--src/server/game/Spells/SpellInfo.cpp492
1 files changed, 481 insertions, 11 deletions
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 94dac870c6e..0008a65939a 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -1584,31 +1584,35 @@ bool SpellInfo::IsAffectedBySpellMod(SpellModifier const* mod) const
return IsAffected(affectSpell->SpellFamilyName, mod->mask);
}
-bool SpellInfo::CanPierceImmuneAura(SpellInfo const* aura) const
+bool SpellInfo::CanPierceImmuneAura(SpellInfo const* auraSpellInfo) const
{
- // these spells pierce all avalible spells (Resurrection Sickness for example)
+ // aura can't be pierced
+ if (!auraSpellInfo || auraSpellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
+ return false;
+
+ // these spells pierce all available spells (Resurrection Sickness for example)
if (HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
return true;
- // these spells (Cyclone for example) can pierce all... // ...but not these (Divine shield, Ice block, Cyclone and Banish for example)
- if (HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) && !(aura && (aura->Mechanic == MECHANIC_IMMUNE_SHIELD || aura->Mechanic == MECHANIC_INVULNERABILITY || aura->Mechanic == MECHANIC_BANISH)))
+ // Dispels other auras on immunity, check if this spell makes the unit immune to aura
+ if (HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY) && CanSpellProvideImmunityAgainstAura(auraSpellInfo))
return true;
return false;
}
-bool SpellInfo::CanDispelAura(SpellInfo const* aura) const
+bool SpellInfo::CanDispelAura(SpellInfo const* auraSpellInfo) const
{
- // These spells (like Mass Dispel) can dispell all auras, except death persistent ones (like Dungeon and Battleground Deserter)
- if (HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY) && !aura->IsDeathPersistent())
- return true;
-
// These auras (like Divine Shield) can't be dispelled
- if (aura->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
+ if (auraSpellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
return false;
+ // These spells (like Mass Dispel) can dispel all auras
+ if (HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
+ return true;
+
// These auras (Cyclone for example) are not dispelable
- if (aura->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE))
+ if (auraSpellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) || auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
return false;
return true;
@@ -2968,6 +2972,472 @@ int32 SpellInfo::GetDiminishingReturnsLimitDuration() const
return _diminishInfo.DiminishDurationLimit;
}
+void SpellInfo::_LoadImmunityInfo()
+{
+ auto loadImmunityInfoFn = [this](SpellEffectInfo* effectInfo)
+ {
+ uint32 schoolImmunityMask = 0;
+ uint32 applyHarmfulAuraImmunityMask = 0;
+ uint32 mechanicImmunityMask = 0;
+ uint32 dispelImmunity = 0;
+ uint32 damageImmunityMask = 0;
+
+ int32 miscVal = effectInfo->MiscValue;
+ int32 amount = effectInfo->CalcValue();
+
+ ImmunityInfo& immuneInfo = *const_cast<ImmunityInfo*>(effectInfo->GetImmunityInfo());
+
+ switch (effectInfo->ApplyAuraName)
+ {
+ case SPELL_AURA_MECHANIC_IMMUNITY_MASK:
+ {
+ switch (miscVal)
+ {
+ case 96: // Free Friend, Uncontrollable Frenzy, Warlord's Presence
+ {
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT_2);
+ break;
+ }
+ case 1615: // Incite Rage, Wolf Spirit, Overload, Lightning Tendrils
+ {
+ switch (Id)
+ {
+ case 43292: // Incite Rage
+ case 49172: // Wolf Spirit
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT_2);
+ // no break intended
+ case 61869: // Overload
+ case 63481:
+ case 61887: // Lightning Tendrils
+ case 63486:
+ mechanicImmunityMask |= (1 << MECHANIC_INTERRUPT) | (1 << MECHANIC_SILENCE);
+
+ immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_KNOCK_BACK);
+ immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_KNOCK_BACK_DEST);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case 679: // Mind Control, Avenging Fury
+ {
+ if (Id == 57742) // Avenging Fury
+ {
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT_2);
+ }
+ break;
+ }
+ case 1557: // Startling Roar, Warlord Roar, Break Bonds, Stormshield
+ {
+ if (Id == 64187) // Stormshield
+ {
+ mechanicImmunityMask |= (1 << MECHANIC_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ }
+ else
+ {
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT_2);
+ }
+ break;
+ }
+ case 1614: // Fixate
+ case 1694: // Fixated, Lightning Tendrils
+ {
+ immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_ATTACK_ME);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_TAUNT);
+ break;
+ }
+ case 1630: // Fervor, Berserk
+ {
+ if (Id == 64112) // Berserk
+ {
+ immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_ATTACK_ME);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_TAUNT);
+ }
+ else
+ {
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT_2);
+ }
+ break;
+ }
+ case 477: // Bladestorm
+ case 1733: // Bladestorm, Killing Spree
+ {
+ if (!amount)
+ {
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+
+ immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_KNOCK_BACK);
+ immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_KNOCK_BACK_DEST);
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT_2);
+ }
+ break;
+ }
+ case 878: // Whirlwind, Fog of Corruption, Determination
+ {
+ if (Id == 66092) // Determination
+ {
+ mechanicImmunityMask |= (1 << MECHANIC_SNARE) | (1 << MECHANIC_STUN)
+ | (1 << MECHANIC_DISORIENTED) | (1 << MECHANIC_FREEZE);
+
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (immuneInfo.AuraTypeImmune.empty())
+ {
+ if (miscVal & (1 << 10))
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN);
+ if (miscVal & (1 << 1))
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_TRANSFORM);
+
+ // These flag can be recognized wrong:
+ if (miscVal & (1 << 6))
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DECREASE_SPEED);
+ if (miscVal & (1 << 0))
+ {
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT);
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_ROOT_2);
+ }
+ if (miscVal & (1 << 2))
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_CONFUSE);
+ if (miscVal & (1 << 9))
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_FEAR);
+ if (miscVal & (1 << 7))
+ immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_DISARM);
+ }
+ break;
+ }
+ case SPELL_AURA_MECHANIC_IMMUNITY:
+ {
+ switch (Id)
+ {
+ case 34471: // The Beast Within
+ case 19574: // Bestial Wrath
+ case 42292: // PvP trinket
+ case 46227: // Medallion of Immunity
+ case 59752: // Every Man for Himself
+ case 53490: // Bullheaded
+ case 65547: // PvP Trinket
+ case 134946: // Supremacy of the Alliance
+ case 134956: // Supremacy of the Horde
+ case 195710: // Honorable Medallion
+ case 208683: // Gladiator's Medallion
+ mechanicImmunityMask |= IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+ break;
+ case 54508: // Demonic Empowerment
+ mechanicImmunityMask |= (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) | (1 << MECHANIC_STUN);
+ break;
+ default:
+ if (miscVal < 1)
+ return;
+
+ mechanicImmunityMask |= 1 << miscVal;
+ break;
+ }
+ break;
+ }
+ case SPELL_AURA_EFFECT_IMMUNITY:
+ {
+ immuneInfo.SpellEffectImmune.insert(static_cast<SpellEffectName>(miscVal));
+ break;
+ }
+ case SPELL_AURA_STATE_IMMUNITY:
+ {
+ immuneInfo.AuraTypeImmune.insert(static_cast<AuraType>(miscVal));
+ break;
+ }
+ case SPELL_AURA_SCHOOL_IMMUNITY:
+ {
+ schoolImmunityMask |= uint32(miscVal);
+ break;
+ }
+ case SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL:
+ {
+ applyHarmfulAuraImmunityMask |= uint32(miscVal);
+ break;
+ }
+ case SPELL_AURA_DAMAGE_IMMUNITY:
+ {
+ damageImmunityMask |= uint32(miscVal);
+ break;
+ }
+ case SPELL_AURA_DISPEL_IMMUNITY:
+ {
+ dispelImmunity = uint32(miscVal);
+ break;
+ }
+ default:
+ break;
+ }
+
+ immuneInfo.SchoolImmuneMask = schoolImmunityMask;
+ immuneInfo.ApplyHarmfulAuraImmuneMask = applyHarmfulAuraImmunityMask;
+ immuneInfo.MechanicImmuneMask = mechanicImmunityMask;
+ immuneInfo.DispelImmune = dispelImmunity;
+ immuneInfo.DamageSchoolMask = damageImmunityMask;
+
+ immuneInfo.AuraTypeImmune.shrink_to_fit();
+ immuneInfo.SpellEffectImmune.shrink_to_fit();
+ };
+
+ for (auto const& effects : _effects)
+ {
+ for (SpellEffectInfo const* effect : effects.second)
+ {
+ if (!effect)
+ continue;
+
+ loadImmunityInfoFn(const_cast<SpellEffectInfo*>(effect));
+ }
+ }
+}
+
+void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const* effect, bool apply) const
+{
+ ImmunityInfo const* immuneInfo = effect->GetImmunityInfo();
+
+ if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask)
+ {
+ target->ApplySpellImmune(Id, IMMUNITY_SCHOOL, schoolImmunity, apply);
+
+ if (apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
+ {
+ target->RemoveAppliedAuras([this, schoolImmunity](AuraApplication const* aurApp) -> bool
+ {
+ SpellInfo const* auraSpellInfo = aurApp->GetBase()->GetSpellInfo();
+ return ((auraSpellInfo->GetSchoolMask() & schoolImmunity) != 0 && // Check for school mask
+ CanDispelAura(auraSpellInfo) &&
+ (IsPositive() != aurApp->IsPositive()) && // Check spell vs aura possitivity
+ !auraSpellInfo->IsPassive() && // Don't remove passive auras
+ auraSpellInfo->Id != Id); // Don't remove self
+ });
+ }
+ }
+
+ if (uint32 mechanicImmunity = immuneInfo->MechanicImmuneMask)
+ {
+ for (uint32 i = 0; i < MAX_MECHANIC; ++i)
+ if (mechanicImmunity & (1 << i))
+ target->ApplySpellImmune(Id, IMMUNITY_MECHANIC, i, apply);
+
+ if (apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
+ target->RemoveAurasWithMechanic(mechanicImmunity, AURA_REMOVE_BY_DEFAULT, Id);
+ }
+
+ if (uint32 dispelImmunity = immuneInfo->DispelImmune)
+ {
+ target->ApplySpellImmune(Id, IMMUNITY_DISPEL, dispelImmunity, apply);
+
+ if (apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
+ {
+ target->RemoveAppliedAuras([dispelImmunity](AuraApplication const* aurApp) -> bool
+ {
+ SpellInfo const* spellInfo = aurApp->GetBase()->GetSpellInfo();
+ if (spellInfo->Dispel == dispelImmunity)
+ return true;
+
+ return false;
+ });
+ }
+ }
+
+ if (uint32 damageImmunity = immuneInfo->DamageSchoolMask)
+ target->ApplySpellImmune(Id, IMMUNITY_DAMAGE, damageImmunity, apply);
+
+ for (AuraType auraType : immuneInfo->AuraTypeImmune)
+ {
+ target->ApplySpellImmune(Id, IMMUNITY_STATE, auraType, apply);
+ if (apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
+ target->RemoveAurasByType(auraType);
+ }
+
+ for (SpellEffectName effectType : immuneInfo->SpellEffectImmune)
+ target->ApplySpellImmune(Id, IMMUNITY_EFFECT, effectType, apply);
+}
+
+bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInfo) const
+{
+ if (!auraSpellInfo)
+ return false;
+
+ for (SpellEffectInfo const* effectInfo : GetEffectsForDifficulty(DIFFICULTY_NONE))
+ {
+ if (!effectInfo)
+ continue;
+
+ ImmunityInfo const* immuneInfo = effectInfo->GetImmunityInfo();
+
+ if (!auraSpellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
+ {
+ if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask)
+ if ((auraSpellInfo->SchoolMask & schoolImmunity) != 0)
+ return true;
+ }
+
+ if (uint32 mechanicImmunity = immuneInfo->MechanicImmuneMask)
+ if ((mechanicImmunity & (1 << auraSpellInfo->Mechanic)) != 0)
+ return true;
+
+ if (uint32 dispelImmunity = immuneInfo->DispelImmune)
+ if (auraSpellInfo->Dispel == dispelImmunity)
+ return true;
+
+ bool immuneToAllEffects = true;
+ for (SpellEffectInfo const* auraSpellEffectInfo : auraSpellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
+ {
+ if (!auraSpellEffectInfo)
+ continue;
+
+ uint32 effectName = auraSpellEffectInfo->Effect;
+ if (!effectName)
+ continue;
+
+ auto spellImmuneItr = immuneInfo->SpellEffectImmune.find(static_cast<SpellEffectName>(effectName));
+ if (spellImmuneItr == immuneInfo->SpellEffectImmune.cend())
+ {
+ immuneToAllEffects = false;
+ break;
+ }
+
+ if (uint32 mechanic = auraSpellEffectInfo->Mechanic)
+ {
+ if (!(immuneInfo->MechanicImmuneMask & (1 << mechanic)))
+ {
+ immuneToAllEffects = false;
+ break;
+ }
+ }
+
+ if (!auraSpellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
+ {
+ if (uint32 auraName = auraSpellEffectInfo->ApplyAuraName)
+ {
+ bool isImmuneToAuraEffectApply = false;
+ auto auraImmuneItr = immuneInfo->AuraTypeImmune.find(static_cast<AuraType>(auraName));
+ if (auraImmuneItr != immuneInfo->AuraTypeImmune.cend())
+ isImmuneToAuraEffectApply = true;
+
+ if (!isImmuneToAuraEffectApply && !auraSpellInfo->IsPositiveEffect(auraSpellEffectInfo->EffectIndex) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
+ {
+ if (uint32 applyHarmfulAuraImmunityMask = immuneInfo->ApplyHarmfulAuraImmuneMask)
+ if ((auraSpellInfo->GetSchoolMask() & applyHarmfulAuraImmunityMask) != 0)
+ isImmuneToAuraEffectApply = true;
+ }
+
+ if (!isImmuneToAuraEffectApply)
+ {
+ immuneToAllEffects = false;
+ break;
+ }
+ }
+ }
+ }
+
+ if (immuneToAllEffects)
+ return true;
+ }
+
+ return false;
+}
+
+// based on client sub_007FDFA0
+bool SpellInfo::CanSpellCastOverrideAuraEffect(AuraEffect const* aurEff) const
+{
+ if (!HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
+ return false;
+
+ if (aurEff->GetSpellInfo()->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
+ return false;
+
+ for (SpellEffectInfo const* effectInfo : GetEffectsForDifficulty(DIFFICULTY_NONE))
+ {
+ if (!effectInfo)
+ continue;
+
+ if (effectInfo->Effect != SPELL_EFFECT_APPLY_AURA)
+ continue;
+
+ uint32 const miscValue = static_cast<uint32>(effectInfo->MiscValue);
+ switch (effectInfo->ApplyAuraName)
+ {
+ case SPELL_AURA_STATE_IMMUNITY:
+ if (miscValue != aurEff->GetSpellEffectInfo()->ApplyAuraName)
+ continue;
+ break;
+ case SPELL_AURA_SCHOOL_IMMUNITY:
+ case SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL:
+ if (aurEff->GetSpellInfo()->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE) || !(aurEff->GetSpellInfo()->SchoolMask & miscValue))
+ continue;
+ break;
+ case SPELL_AURA_DISPEL_IMMUNITY:
+ if (miscValue != aurEff->GetSpellInfo()->Dispel)
+ continue;
+ break;
+ case SPELL_AURA_MECHANIC_IMMUNITY:
+ if (miscValue != aurEff->GetSpellInfo()->Mechanic)
+ {
+ if (miscValue != aurEff->GetSpellEffectInfo()->Mechanic)
+ continue;
+ }
+ break;
+ default:
+ continue;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
float SpellInfo::GetMinRange(bool positive) const
{
if (!RangeEntry)