diff options
author | Shauren <shauren.trinity@gmail.com> | 2024-06-19 20:14:53 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2024-06-19 20:14:53 +0200 |
commit | c968dedfee59db53fc912ac166309f3d87470821 (patch) | |
tree | 040b523a5bed5e38c7447dadbad8b314ea6c6463 | |
parent | e54e3ed2040d0c21c3b05433269044568572cb7a (diff) |
Core/Spells: Fixed implementation of SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS and removed banish special cases that were neccessary because that attribute wasn't correctly supported
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 179 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 8 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 4 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 40 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 56 | ||||
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp | 2 |
10 files changed, 155 insertions, 144 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 8400dec52ae..6f4795a8b4b 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2642,7 +2642,7 @@ SpellMissInfo WorldObject::SpellHitResult(Unit* victim, SpellInfo const* spellIn // Damage immunity is only checked if the spell has damage effects, this immunity must not prevent aura apply // returns SPELL_MISS_IMMUNE in that case, for other spells, the SMSG_SPELL_GO must show hit - if (spellInfo->HasOnlyDamageEffects() && victim->IsImmunedToDamage(spellInfo)) + if (spellInfo->HasOnlyDamageEffects() && victim->IsImmunedToDamage(this, spellInfo)) return SPELL_MISS_IMMUNE; // All positive spells can`t miss diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 7ffa74abba4..b02c7a5f130 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1584,7 +1584,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss) } // ...or immuned - if (IsImmunedToDamage(spellInfo)) + if (IsImmunedToDamage(this, spellInfo)) { victim->SendSpellDamageImmune(this, spellInfo->Id, false); continue; @@ -7420,61 +7420,6 @@ int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const return advertisedBenefit; } -bool Unit::IsImmunedToDamage(SpellSchoolMask schoolMask) const -{ - if (schoolMask == SPELL_SCHOOL_MASK_NONE) - return false; - - // If m_immuneToSchool type contain this school type, IMMUNE damage. - uint32 schoolImmunityMask = GetSchoolImmunityMask(); - if ((schoolImmunityMask & schoolMask) == schoolMask) // We need to be immune to all types - return true; - - // If m_immuneToDamage type contain magic, IMMUNE damage. - uint32 damageImmunityMask = GetDamageImmunityMask(); - if ((damageImmunityMask & schoolMask) == schoolMask) // We need to be immune to all types - return true; - - return false; -} - -bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo, SpellEffectInfo const* spellEffectInfo /*= nullptr*/) const -{ - if (!spellInfo) - return false; - - // for example 40175 - if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) && spellInfo->HasAttribute(SPELL_ATTR3_ALWAYS_HIT)) - return false; - - if (spellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) || spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES)) - return false; - - if (spellEffectInfo && spellEffectInfo->EffectAttributes.HasFlag(SpellEffectAttributes::NoImmunity)) - return false; - - if (uint32 schoolMask = spellInfo->GetSchoolMask()) - { - // If m_immuneToSchool type contain this school type, IMMUNE damage. - uint32 schoolImmunityMask = 0; - SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL]; - for (auto itr = schoolList.begin(); itr != schoolList.end(); ++itr) - if ((itr->first & schoolMask) && !spellInfo->CanPierceImmuneAura(sSpellMgr->GetSpellInfo(itr->second, GetMap()->GetDifficultyID()))) - schoolImmunityMask |= itr->first; - - // // We need to be immune to all types - if ((schoolImmunityMask & schoolMask) == schoolMask) - return true; - - // If m_immuneToDamage type contain magic, IMMUNE damage. - uint32 damageImmunityMask = GetDamageImmunityMask(); - if ((damageImmunityMask & schoolMask) == schoolMask) // We need to be immune to all types - return true; - } - - return false; -} - bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute /*= false*/) const { if (!spellInfo) @@ -7552,11 +7497,13 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste if (!immuneSpellInfo || !immuneSpellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT)) continue; - // Consider the school immune if any of these conditions are not satisfied. - // In case of no immuneSpellInfo, ignore that condition and check only the other conditions - if ((immuneSpellInfo && !immuneSpellInfo->IsPositive()) || !spellInfo->IsPositive() || !caster || !IsFriendlyTo(caster)) - if (!spellInfo->CanPierceImmuneAura(immuneSpellInfo)) - schoolImmunityMask |= itr->first; + if (immuneSpellInfo && !immuneSpellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) && caster && !caster->IsFriendlyTo(this)) + continue; + + if (spellInfo->CanPierceImmuneAura(immuneSpellInfo)) + continue; + + schoolImmunityMask |= itr->first; } if ((schoolImmunityMask & schoolMask) == schoolMask) return true; @@ -7605,6 +7552,68 @@ EnumFlag<SpellOtherImmunity> Unit::GetSpellOtherImmunityMask() const return mask; } +bool Unit::IsImmunedToDamage(SpellSchoolMask schoolMask) const +{ + if (schoolMask == SPELL_SCHOOL_MASK_NONE) + return false; + + // If m_immuneToSchool type contain this school type, IMMUNE damage. + uint32 schoolImmunityMask = GetSchoolImmunityMask(); + if ((schoolImmunityMask & schoolMask) == schoolMask) // We need to be immune to all types + return true; + + // If m_immuneToDamage type contain magic, IMMUNE damage. + uint32 damageImmunityMask = GetDamageImmunityMask(); + if ((damageImmunityMask & schoolMask) == schoolMask) // We need to be immune to all types + return true; + + return false; +} + +bool Unit::IsImmunedToDamage(WorldObject const* caster, SpellInfo const* spellInfo, SpellEffectInfo const* spellEffectInfo /*= nullptr*/) const +{ + if (!spellInfo) + return false; + + if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) || spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES)) + return false; + + if (spellEffectInfo && spellEffectInfo->EffectAttributes.HasFlag(SpellEffectAttributes::NoImmunity)) + return false; + + if (uint32 schoolMask = spellInfo->GetSchoolMask()) + { + auto hasImmunity = [&](SpellImmuneContainer const& container) + { + uint32 schoolImmunityMask = 0; + for (auto&& [immunitySchoolMask, immunityAuraId] : container) + { + SpellInfo const* immuneAuraInfo = sSpellMgr->GetSpellInfo(immunityAuraId, GetMap()->GetDifficultyID()); + if (immuneAuraInfo && !immuneAuraInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) && caster && caster->IsFriendlyTo(this)) + continue; + + if (immuneAuraInfo && spellInfo->CanPierceImmuneAura(immuneAuraInfo)) + continue; + + schoolImmunityMask |= immunitySchoolMask; + } + + // // We need to be immune to all types + return (schoolImmunityMask & schoolMask) == schoolMask; + }; + + // If m_immuneToSchool type contain this school type, IMMUNE damage. + if (hasImmunity(m_spellImmune[IMMUNITY_SCHOOL])) + return true; + + // If m_immuneToDamage type contain magic, IMMUNE damage. + if (hasImmunity(m_spellImmune[IMMUNITY_DAMAGE])) + return true; + } + + return false; +} + bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute /*= false*/) const { @@ -7657,17 +7666,57 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo co if (!spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES)) { // Check for immune to application of harmful magical effects - AuraEffectList const& immuneAuraApply = GetAuraEffectsByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL); - for (AuraEffectList::const_iterator iter = immuneAuraApply.begin(); iter != immuneAuraApply.end(); ++iter) - if (((*iter)->GetMiscValue() & spellInfo->GetSchoolMask()) && // Check school - ((caster && !IsFriendlyTo(caster)) || !spellInfo->IsPositiveEffect(spellEffectInfo.EffectIndex))) // Harmful + for (AuraEffect const* immuneAuraApply : GetAuraEffectsByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL)) + { + if (!(immuneAuraApply->GetMiscValue() & spellInfo->GetSchoolMask())) // Check school + continue; + + if (spellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) || (caster && !IsFriendlyTo(caster))) // Harmful return true; + } } } return false; } +bool Unit::IsImmunedToAuraPeriodicTick(WorldObject const* caster, SpellInfo const* spellInfo, SpellEffectInfo const* spellEffectInfo) const +{ + if (!spellInfo) + return false; + + if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) || spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES) /*only school immunities are checked in this function*/) + return false; + + if (spellEffectInfo && spellEffectInfo->EffectAttributes.HasFlag(SpellEffectAttributes::NoImmunity)) + return false; + + if (uint32 schoolMask = spellInfo->GetSchoolMask()) + { + auto hasImmunity = [&](SpellImmuneContainer const& container) + { + uint32 schoolImmunityMask = 0; + for (auto&& [immunitySchoolMask, immunityAuraId] : container) + { + SpellInfo const* immuneAuraInfo = sSpellMgr->GetSpellInfo(immunityAuraId, GetMap()->GetDifficultyID()); + if (immuneAuraInfo && !immuneAuraInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) && caster && caster->IsFriendlyTo(this)) + continue; + + schoolImmunityMask |= immunitySchoolMask; + } + + // // We need to be immune to all types + return (schoolImmunityMask & schoolMask) == schoolMask; + }; + + // If m_immuneToSchool type contain this school type, IMMUNE damage. + if (hasImmunity(m_spellImmune[IMMUNITY_SCHOOL])) + return true; + } + + return false; +} + int32 Unit::MeleeDamageBonusDone(Unit* pVictim, int32 damage, WeaponAttackType attType, DamageEffectType damagetype, SpellInfo const* spellProto /*= nullptr*/, Mechanics mechanic /*= nullptr*/, SpellSchoolMask damageSchoolMask /*= SPELL_SCHOOL_MASK_NORMAL*/, Spell* spell /*= nullptr*/, AuraEffect const* aurEff /*= nullptr*/) { if (!pVictim || damage == 0) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index a8c9c110a5e..c2ecd8d7c7d 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -266,7 +266,7 @@ enum UnitState : uint32 UNIT_STATE_ROOT = 0x00000400, UNIT_STATE_CONFUSED = 0x00000800, UNIT_STATE_DISTRACTED = 0x00001000, - UNIT_STATE_ISOLATED = 0x00002000, // area auras do not affect other players + UNIT_STATE_ISOLATED_DEPRECATED = 0x00002000, // REUSE UNIT_STATE_ATTACK_PLAYER = 0x00004000, UNIT_STATE_CASTING = 0x00008000, UNIT_STATE_POSSESSED = 0x00010000, // being possessed by another unit @@ -286,7 +286,7 @@ enum UnitState : uint32 UNIT_STATE_ALL_STATE_SUPPORTED = UNIT_STATE_DIED | UNIT_STATE_MELEE_ATTACKING | UNIT_STATE_CHARMED | UNIT_STATE_STUNNED | UNIT_STATE_ROAMING | UNIT_STATE_CHASE | UNIT_STATE_FOCUSING | UNIT_STATE_FLEEING | UNIT_STATE_IN_FLIGHT | UNIT_STATE_FOLLOW | UNIT_STATE_ROOT | UNIT_STATE_CONFUSED - | UNIT_STATE_DISTRACTED | UNIT_STATE_ISOLATED | UNIT_STATE_ATTACK_PLAYER | UNIT_STATE_CASTING + | UNIT_STATE_DISTRACTED | UNIT_STATE_ATTACK_PLAYER | UNIT_STATE_CASTING | UNIT_STATE_POSSESSED | UNIT_STATE_CHARGING | UNIT_STATE_JUMPING | UNIT_STATE_MOVE | UNIT_STATE_ROTATING | UNIT_STATE_EVADE | UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE | UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE | UNIT_STATE_IGNORE_PATHFINDING | UNIT_STATE_FOLLOW_FORMATION_MOVE, @@ -1638,9 +1638,11 @@ class TC_GAME_API Unit : public WorldObject EnumFlag<SpellOtherImmunity> GetSpellOtherImmunityMask() const; bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const; - bool IsImmunedToDamage(SpellInfo const* spellInfo, SpellEffectInfo const* spellEffectInfo = nullptr) const; + bool IsImmunedToDamage(WorldObject const* caster, SpellInfo const* spellInfo, SpellEffectInfo const* spellEffectInfo = nullptr) const; virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute = false) const; + bool IsImmunedToAuraPeriodicTick(WorldObject const* caster, SpellInfo const* spellInfo, SpellEffectInfo const* spellEffectInfo = nullptr) const; + static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = nullptr); static uint32 CalcArmorReducedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = MAX_ATTACK, uint8 attackerLevel = 0); static uint32 CalcSpellResistedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellSchoolMask schoolMask, SpellInfo const* spellInfo); diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 93363a57b9d..3196074a2fa 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -479,7 +479,7 @@ enum SpellAttr1 : uint32 SPELL_ATTR1_TOGGLE_FAR_SIGHT = 0x00002000, // TITLE Toggle Far Sight (client only) SPELL_ATTR1_TRACK_TARGET_IN_CHANNEL = 0x00004000, // TITLE Track Target in Channel DESCRIPTION While channeling, adjust facing to face target SPELL_ATTR1_IMMUNITY_PURGES_EFFECT = 0x00008000, // TITLE Immunity Purges Effect DESCRIPTION For immunity spells, cancel all auras that this spell would make you immune to when the spell is applied - SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS = 0x00010000, /*WRONG IMPL*/ // TITLE Immunity to Hostile & Friendly Effects DESCRIPTION Will not pierce Divine Shield, Ice Block and other full invulnerabilities + SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS = 0x00010000, // TITLE Immunity to Hostile & Friendly Effects DESCRIPTION Immunity applied by this aura will also be checked for friendly spells (school immunity only) - used by Cyclone for example to cause friendly spells and healing over time to be immuned SPELL_ATTR1_NO_AUTOCAST_AI = 0x00020000, // TITLE No AutoCast (AI) SPELL_ATTR1_PREVENTS_ANIM = 0x00040000, /*NYI*/ // TITLE Prevents Anim DESCRIPTION Auras apply UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT SPELL_ATTR1_EXCLUDE_CASTER = 0x00080000, // TITLE Exclude Caster @@ -2549,7 +2549,7 @@ enum AuraStateType AURA_STATE_MARKED = 5, // C t| NYI AURA_STATE_WOUNDED_25_PERCENT = 6, // T | AURA_STATE_DEFENSIVE_2 = 7, // Cc | NYI - AURA_STATE_BANISHED = 8, // c | NYI + AURA_STATE_BANISHED = 8, // c | AURA_STATE_DAZED = 9, // t| AURA_STATE_VICTORIOUS = 10, // C | AURA_STATE_RAMPAGE = 11, // | NYI diff --git a/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp b/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp index f1bf1611ac2..fc45be673c4 100644 --- a/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp +++ b/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp @@ -419,7 +419,7 @@ TC_API_EXPORT EnumText EnumUtils<SpellAttr1>::ToString(SpellAttr1 value) case SPELL_ATTR1_TOGGLE_FAR_SIGHT: return { "SPELL_ATTR1_TOGGLE_FAR_SIGHT", "Toggle Far Sight (client only)", "" }; case SPELL_ATTR1_TRACK_TARGET_IN_CHANNEL: return { "SPELL_ATTR1_TRACK_TARGET_IN_CHANNEL", "Track Target in Channel", "While channeling, adjust facing to face target" }; case SPELL_ATTR1_IMMUNITY_PURGES_EFFECT: return { "SPELL_ATTR1_IMMUNITY_PURGES_EFFECT", "Immunity Purges Effect", "For immunity spells, cancel all auras that this spell would make you immune to when the spell is applied" }; - case SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS: return { "SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS", "Immunity to Hostile & Friendly Effects", "Will not pierce Divine Shield, Ice Block and other full invulnerabilities" }; + case SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS: return { "SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS", "Immunity to Hostile & Friendly Effects", "Immunity applied by this aura will also be checked for friendly spells (school immunity only) - used by Cyclone for example to cause friendly spells and healing over time to be immuned" }; case SPELL_ATTR1_NO_AUTOCAST_AI: return { "SPELL_ATTR1_NO_AUTOCAST_AI", "No AutoCast (AI)", "" }; case SPELL_ATTR1_PREVENTS_ANIM: return { "SPELL_ATTR1_PREVENTS_ANIM", "Prevents Anim", "Auras apply UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT" }; case SPELL_ATTR1_EXCLUDE_CASTER: return { "SPELL_ATTR1_EXCLUDE_CASTER", "Exclude Caster", "" }; @@ -3216,7 +3216,7 @@ TC_API_EXPORT EnumText EnumUtils<AuraStateType>::ToString(AuraStateType value) case AURA_STATE_MARKED: return { "AURA_STATE_MARKED", "AURA_STATE_MARKED", "C t| NYI" }; case AURA_STATE_WOUNDED_25_PERCENT: return { "AURA_STATE_WOUNDED_25_PERCENT", "AURA_STATE_WOUNDED_25_PERCENT", "T |" }; case AURA_STATE_DEFENSIVE_2: return { "AURA_STATE_DEFENSIVE_2", "AURA_STATE_DEFENSIVE_2", "Cc | NYI" }; - case AURA_STATE_BANISHED: return { "AURA_STATE_BANISHED", "AURA_STATE_BANISHED", "c | NYI" }; + case AURA_STATE_BANISHED: return { "AURA_STATE_BANISHED", "AURA_STATE_BANISHED", "c |" }; case AURA_STATE_DAZED: return { "AURA_STATE_DAZED", "AURA_STATE_DAZED", "t|" }; case AURA_STATE_VICTORIOUS: return { "AURA_STATE_VICTORIOUS", "AURA_STATE_VICTORIOUS", "C |" }; case AURA_STATE_RAMPAGE: return { "AURA_STATE_RAMPAGE", "AURA_STATE_RAMPAGE", "| NYI" }; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 1ee6f4545c0..37d938dd7e7 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -3369,28 +3369,6 @@ void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const* aurApp, uint Unit* target = aurApp->GetTarget(); m_spellInfo->ApplyAllSpellImmunitiesTo(target, GetSpellEffectInfo(), apply); - if (GetSpellInfo()->Mechanic == MECHANIC_BANISH) - { - if (apply) - target->AddUnitState(UNIT_STATE_ISOLATED); - else - { - bool banishFound = false; - Unit::AuraEffectList const& banishAuras = target->GetAuraEffectsByType(GetAuraType()); - for (AuraEffect const* aurEff : banishAuras) - { - if (aurEff->GetSpellInfo()->Mechanic == MECHANIC_BANISH) - { - banishFound = true; - break; - } - } - - if (!banishFound) - target->ClearUnitState(UNIT_STATE_ISOLATED); - } - } - // TODO: should be changed to a proc script on flag spell (they have "Taken positive" proc flags in db2) { if (apply && GetMiscValue() == SPELL_SCHOOL_MASK_NORMAL) @@ -5431,7 +5409,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const if (!target->IsAlive()) return; - if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo(), &GetSpellEffectInfo())) + if (target->IsImmunedToDamage(caster, GetSpellInfo(), &GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5566,7 +5544,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c if (!target->IsAlive()) return; - if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo(), &GetSpellEffectInfo())) + if (target->IsImmunedToDamage(caster, GetSpellInfo(), &GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5665,7 +5643,7 @@ void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster) if (!caster || !caster->IsAlive() || !target->IsAlive()) return; - if (target->HasUnitState(UNIT_STATE_ISOLATED)) + if (target->IsImmunedToAuraPeriodicTick(caster, GetSpellInfo(), &GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5695,7 +5673,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const if (!target->IsAlive()) return; - if (target->HasUnitState(UNIT_STATE_ISOLATED)) + if (target->IsImmunedToAuraPeriodicTick(caster, GetSpellInfo(), &GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5755,7 +5733,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con if (!caster || !caster->IsAlive() || !target->IsAlive() || target->GetPowerType() != powerType) return; - if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo(), &GetSpellEffectInfo())) + if (target->IsImmunedToAuraPeriodicTick(caster, GetSpellInfo(), &GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5818,7 +5796,7 @@ void AuraEffect::HandleObsModPowerAuraTick(Unit* target, Unit* caster) const if (!target->IsAlive() || !target->GetMaxPower(powerType)) return; - if (target->HasUnitState(UNIT_STATE_ISOLATED)) + if (target->IsImmunedToAuraPeriodicTick(caster, GetSpellInfo(), &GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5848,7 +5826,7 @@ void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) cons if (!target->IsAlive() || !target->GetMaxPower(powerType)) return; - if (target->HasUnitState(UNIT_STATE_ISOLATED)) + if (target->IsImmunedToAuraPeriodicTick(caster, GetSpellInfo(), &GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5880,7 +5858,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con if (!caster || !target->IsAlive() || target->GetPowerType() != powerType) return; - if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo(), &GetSpellEffectInfo())) + if (target->IsImmunedToDamage(caster, GetSpellInfo(), &GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -6008,7 +5986,7 @@ void AuraEffect::HandleProcTriggerDamageAuraProc(AuraApplication* aurApp, ProcEv { Unit* target = aurApp->GetTarget(); Unit* triggerTarget = eventInfo.GetProcTarget(); - if (triggerTarget->HasUnitState(UNIT_STATE_ISOLATED) || triggerTarget->IsImmunedToDamage(GetSpellInfo(), &GetSpellEffectInfo())) + if (triggerTarget->IsImmunedToDamage(target, GetSpellInfo(), &GetSpellEffectInfo())) { SendTickImmune(triggerTarget, target); return; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index c28730263bb..00287b1f4b7 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -2541,7 +2541,7 @@ void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint32>& targets, Unit* c if (!GetUnitOwner()->IsInWorld()) continue; - if (GetUnitOwner()->HasUnitState(UNIT_STATE_ISOLATED)) + if (GetUnitOwner()->HasAuraState(AURA_STATE_BANISHED, GetSpellInfo(), caster)) continue; std::vector<WorldObject*> units; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index f84066f77c4..785f468612d 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2920,7 +2920,7 @@ void Spell::TargetInfo::DoDamageAndTriggers(Spell* spell) // Fill base damage struct (unitTarget - is real spell target) SpellNonMeleeDamage damageInfo(caster, spell->unitTarget, spell->m_spellInfo, spell->m_SpellVisual, spell->m_spellSchoolMask, spell->m_castId); // Check damage immunity - if (spell->unitTarget->IsImmunedToDamage(spell->m_spellInfo)) + if (spell->unitTarget->IsImmunedToDamage(caster, spell->m_spellInfo)) { hitMask = PROC_HIT_IMMUNE; spell->m_damage = 0; diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index c732f497e0c..0d172cef5e6 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1848,24 +1848,6 @@ bool SpellInfo::IsAffectedBySpellMod(SpellModifier const* mod) const bool SpellInfo::CanPierceImmuneAura(SpellInfo const* auraSpellInfo) const { - // aura can't be pierced - if (!auraSpellInfo || auraSpellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES)) - return false; - - // these spells pierce all available spells (Resurrection Sickness for example) - if (HasAttribute(SPELL_ATTR0_NO_IMMUNITIES)) - return true; - - // these spells (Cyclone for example) can pierce all... - if (HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) || HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES)) - { - // ...but not these (Divine shield, Ice block, Cyclone and Banish for example) - if (auraSpellInfo->Mechanic != MECHANIC_IMMUNE_SHIELD && - auraSpellInfo->Mechanic != MECHANIC_INVULNERABILITY && - (auraSpellInfo->Mechanic != MECHANIC_BANISH || (IsRankOf(auraSpellInfo) && auraSpellInfo->Dispel != DISPEL_NONE))) // Banish shouldn't be immune to itself, but Cyclone should - return true; - } - // Dispels other auras on immunity, check if this spell makes the unit immune to aura if (HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT) && CanSpellProvideImmunityAgainstAura(auraSpellInfo)) return true; @@ -1879,15 +1861,6 @@ bool SpellInfo::CanDispelAura(SpellInfo const* auraSpellInfo) const if (auraSpellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES)) return false; - // These spells (like Mass Dispel) can dispel all auras - if (HasAttribute(SPELL_ATTR0_NO_IMMUNITIES)) - return true; - - // These auras (Cyclone for example) are not dispelable - if ((auraSpellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) && auraSpellInfo->Mechanic != MECHANIC_NONE) - || auraSpellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES)) - return false; - return true; } @@ -3521,14 +3494,24 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const& s if (apply && HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT)) { - target->RemoveAppliedAuras([this, schoolImmunity](AuraApplication const* aurApp) -> bool + target->RemoveAppliedAuras([this, target, 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 (auraSpellInfo->Id == Id) // Don't remove self + return false; + if (auraSpellInfo->IsPassive()) // Don't remove passive auras + return false; + if (!(auraSpellInfo->GetSchoolMask() & schoolImmunity)) // Check for school mask + return false; + if (!CanDispelAura(auraSpellInfo)) + return false; + if (!HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS)) + { + WorldObject const* existingAuraCaster = aurApp->GetBase()->GetWorldObjectCaster(); + if (existingAuraCaster && existingAuraCaster->IsFriendlyTo(target)) // Check spell vs aura possitivity + return false; + } + return true; }); } @@ -3597,10 +3580,9 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const& s { target->ApplySpellImmune(Id, IMMUNITY_STATE, auraType, apply); if (apply && HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT)) - target->RemoveAurasByType(auraType, [](AuraApplication const* aurApp) -> bool + target->RemoveAurasByType(auraType, [this](AuraApplication const* aurApp) -> bool { - // if the aura has SPELL_ATTR0_NO_IMMUNITIES, then it cannot be removed by immunity - return !aurApp->GetBase()->GetSpellInfo()->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES); + return CanDispelAura(aurApp->GetBase()->GetSpellInfo()); }); } @@ -3625,7 +3607,7 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf if (!immuneInfo) continue; - if (!auraSpellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES)) + if (!auraSpellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES)) { if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask) if ((auraSpellInfo->SchoolMask & schoolImmunity) != 0) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index df500406a23..807109e1493 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -1048,7 +1048,7 @@ class spell_sindragosa_s_fury : public SpellScript if (!GetHitUnit()->IsAlive() || !_targetCount) return; - if (GetHitUnit()->IsImmunedToDamage(GetSpellInfo(), &GetEffectInfo())) + if (GetHitUnit()->IsImmunedToDamage(GetCaster(), GetSpellInfo(), &GetEffectInfo())) { GetCaster()->SendSpellDamageImmune(GetHitUnit(), GetSpellInfo()->Id, false); return; |