diff options
Diffstat (limited to 'src/server/game/Spells/SpellInfo.cpp')
| -rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 463 |
1 files changed, 452 insertions, 11 deletions
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 07da0d8ab9f..b7fc753ffe0 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -16,6 +16,7 @@ */ #include "SpellAuraDefines.h" +#include "SpellAuras.h" #include "SpellInfo.h" #include "SpellMgr.h" #include "Spell.h" @@ -1251,31 +1252,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->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; @@ -2462,6 +2467,442 @@ int32 SpellInfo::GetDiminishingReturnsLimitDuration(bool triggered) const return triggered ? _diminishInfoTriggered.DiminishDurationLimit : _diminishInfoNonTriggered.DiminishDurationLimit; } +void SpellInfo::_LoadImmunityInfo() +{ + uint32 schoolImmunityMask = 0; + uint32 applyHarmfulAuraImmunityMask = 0; + uint32 mechanicImmunityMask = 0; + uint32 dispelImmunity = 0; + uint32 damageImmunityMask = 0; + + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + int32 miscVal = Effects[i].MiscValue; + int32 amount = Effects[i].CalcValue(); + + ImmunityInfo& immuneInfo = _immunityInfo[i]; + + switch (Effects[i].ApplyAuraName) + { + case SPELL_AURA_MECHANIC_IMMUNITY_MASK: + { + switch (miscVal) + { + case 27: + mechanicImmunityMask |= (1 << MECHANIC_SILENCE); + immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_SILENCE); + break; + case 96: + case 1615: + { + if (amount) + { + mechanicImmunityMask |= (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN) | (1 << MECHANIC_BANISH); + + 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); + } + break; + } + case 679: + { + if (Id == 57742) + { + mechanicImmunityMask |= (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN) | (1 << MECHANIC_BANISH); + + 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); + } + break; + } + case 1557: + { + if (Id == 64187) + { + mechanicImmunityMask |= (1 << MECHANIC_STUN); + immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_STUN); + } + else + { + mechanicImmunityMask |= (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN) | (1 << MECHANIC_BANISH); + + 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); + } + break; + } + case 1614: + case 1694: + { + immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_ATTACK_ME); + immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_TAUNT); + break; + } + case 1630: + { + if (!amount) + { + immuneInfo.SpellEffectImmune.insert(SPELL_EFFECT_ATTACK_ME); + immuneInfo.AuraTypeImmune.insert(SPELL_AURA_MOD_TAUNT); + } + else + { + mechanicImmunityMask |= (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN) | (1 << MECHANIC_BANISH); + + 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); + } + break; + } + case 477: + case 1733: + { + if (!amount) + { + mechanicImmunityMask |= (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN) | (1 << MECHANIC_BANISH); + + 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); + } + break; + } + case 878: + { + if (amount == 1) + { + 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); + 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 59752: // Every Man for Himself + case 53490: // Bullheaded + 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) + continue; + + mechanicImmunityMask |= 1 << miscVal; + break; + } + break; + } + case SPELL_AURA_EFFECT_IMMUNITY: + { + immuneInfo.SpellEffectImmune.insert(static_cast<SpellEffects>(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(); + } +} + +void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool apply) const +{ + ImmunityInfo const* immuneInfo = _immunityInfo + effIndex; + + 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->SchoolImmuneMask) + 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 (SpellEffects effectType : immuneInfo->SpellEffectImmune) + target->ApplySpellImmune(Id, IMMUNITY_EFFECT, effectType, apply); +} + +bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInfo) const +{ + if (!auraSpellInfo) + return false; + + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + ImmunityInfo const* immuneInfo = _immunityInfo + i; + + 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 (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + { + uint32 effectName = auraSpellInfo->Effects[effIndex].Effect; + if (!effectName) + continue; + + auto spellImmuneItr = immuneInfo->SpellEffectImmune.find(static_cast<SpellEffects>(effectName)); + if (spellImmuneItr == immuneInfo->SpellEffectImmune.cend()) + { + immuneToAllEffects = false; + break; + } + + if (uint32 mechanic = auraSpellInfo->Effects[effIndex].Mechanic) + { + if (!(immuneInfo->MechanicImmuneMask & (1 << mechanic))) + { + immuneToAllEffects = false; + break; + } + } + + if (!auraSpellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT)) + { + if (uint32 auraName = auraSpellInfo->Effects[effIndex].ApplyAuraName) + { + bool isImmuneToAuraEffectApply = false; + auto auraImmuneItr = immuneInfo->AuraTypeImmune.find(static_cast<AuraType>(auraName)); + if (auraImmuneItr != immuneInfo->AuraTypeImmune.cend()) + isImmuneToAuraEffectApply = true; + + if (!isImmuneToAuraEffectApply && !auraSpellInfo->IsPositiveEffect(effIndex) && !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(SpellInfo const* auraSpellInfo, uint8 auraEffIndex) const +{ + if (!HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)) + return false; + + if (auraSpellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)) + return false; + + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if (Effects[i].Effect != SPELL_EFFECT_APPLY_AURA) + continue; + + int32 const miscValue = Effects[i].MiscValue; + switch (Effects[i].ApplyAuraName) + { + case SPELL_AURA_STATE_IMMUNITY: + if (miscValue != auraSpellInfo->Effects[auraEffIndex].ApplyAuraName) + continue; + break; + case SPELL_AURA_SCHOOL_IMMUNITY: + case SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL: + if (auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE) || !(auraSpellInfo->SchoolMask & miscValue)) + continue; + break; + case SPELL_AURA_DISPEL_IMMUNITY: + if (miscValue != auraSpellInfo->Dispel) + continue; + break; + case SPELL_AURA_MECHANIC_IMMUNITY: + if (miscValue != auraSpellInfo->Mechanic) + { + if (miscValue != auraSpellInfo->Effects[auraEffIndex].Mechanic) + continue; + } + break; + default: + continue; + } + + return true; + } + + return false; +} + float SpellInfo::GetMinRange(bool positive) const { if (!RangeEntry) |
