mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-07 15:28:02 +00:00
fix(Core/Unit): correct partial school immunity for dual-school spells (#26254)
This commit is contained in:
@@ -939,34 +939,8 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, uint32 effectMask, Unit
|
||||
if (hasCheckedEffect && immuneToAllEffects)
|
||||
return true;
|
||||
|
||||
if (!spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
|
||||
{
|
||||
if (spellInfo->Id == 42292 || spellInfo->Id == 59752 || spellInfo->Id == 19574 || spellInfo->Id == 34471)
|
||||
return false;
|
||||
|
||||
SpellSchoolMask schoolMask = spellInfo->GetSchoolMask();
|
||||
if (schoolMask != SPELL_SCHOOL_MASK_NONE)
|
||||
{
|
||||
SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||
for (auto const& [immunitySchoolMask, immunityAuraId] : schoolList)
|
||||
{
|
||||
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(immunityAuraId);
|
||||
if (immunityAuraId == spellInfo->Id)
|
||||
continue;
|
||||
|
||||
if ((immunitySchoolMask & schoolMask) != schoolMask)
|
||||
continue;
|
||||
|
||||
if (IgnoresSchoolImmunityFromFriendlyCaster(caster, immunityAuraId, immuneSpellInfo))
|
||||
continue;
|
||||
|
||||
if (spellInfo->CanPierceImmuneAura(immuneSpellInfo))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES) && HasSchoolImmunityForMask(spellInfo->GetSchoolMask(), caster, spellInfo))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -9860,6 +9834,32 @@ bool Unit::IgnoresSchoolImmunityFromFriendlyCaster(Unit const* caster, uint32 im
|
||||
return immunityAuraId == std::numeric_limits<uint32>::max();
|
||||
}
|
||||
|
||||
bool Unit::HasSchoolImmunityForMask(SpellSchoolMask schoolMask, Unit const* caster, SpellInfo const* spellInfo) const
|
||||
{
|
||||
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||
return false;
|
||||
|
||||
uint32 accumulatedMask = 0;
|
||||
for (auto const& [immunitySchoolMask, immunityAuraId] : m_spellImmune[IMMUNITY_SCHOOL])
|
||||
{
|
||||
// Skip the spell's own immunity entry
|
||||
if (spellInfo && immunityAuraId == spellInfo->Id)
|
||||
continue;
|
||||
|
||||
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(immunityAuraId);
|
||||
|
||||
if (IgnoresSchoolImmunityFromFriendlyCaster(caster, immunityAuraId, immuneSpellInfo))
|
||||
continue;
|
||||
|
||||
if (spellInfo && immuneSpellInfo && spellInfo->CanPierceImmuneAura(immuneSpellInfo))
|
||||
continue;
|
||||
|
||||
accumulatedMask |= immunitySchoolMask;
|
||||
}
|
||||
|
||||
return (SpellSchoolMask(accumulatedMask) & schoolMask) == schoolMask;
|
||||
}
|
||||
|
||||
bool Unit::IsImmunedToDamage(SpellSchoolMask schoolMask) const
|
||||
{
|
||||
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||
@@ -9935,68 +9935,10 @@ bool Unit::IsImmunedToSchool(SpellSchoolMask schoolMask) const
|
||||
});
|
||||
}
|
||||
|
||||
bool Unit::IsImmunedToSchool(SpellInfo const* spellInfo) const
|
||||
{
|
||||
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) && !HasSpiritOfRedemptionAura())
|
||||
return false;
|
||||
|
||||
uint32 schoolMask = spellInfo->GetSchoolMask();
|
||||
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (spellInfo->Id != 42292 && spellInfo->Id != 59752 && spellInfo->Id != 19574 && spellInfo->Id != 34471)
|
||||
{
|
||||
// Check IMMUNITY_SCHOOL: returns true if ALL schools in the mask are covered and spell can't pierce
|
||||
SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||
for (auto itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
||||
if ((itr->first & schoolMask) == schoolMask && !spellInfo->CanPierceImmuneAura(sSpellMgr->GetSpellInfo(itr->second)))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Unit::IsImmunedToSchool(Spell const* spell) const
|
||||
{
|
||||
SpellInfo const* spellInfo = spell->GetSpellInfo();
|
||||
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) && !HasSpiritOfRedemptionAura())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 schoolMask = spell->GetSpellSchoolMask();
|
||||
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (spellInfo->Id != 42292 && spellInfo->Id != 59752 && spellInfo->Id != 19574 && spellInfo->Id != 34471)
|
||||
{
|
||||
// Check IMMUNITY_SCHOOL: returns true if ALL schools in the mask are covered and spell can't pierce
|
||||
SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||
for (auto itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
||||
{
|
||||
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->second);
|
||||
if ((itr->first & schoolMask) == schoolMask
|
||||
&& !IgnoresSchoolImmunityFromFriendlyCaster(spell->GetCaster(), itr->second, immuneSpellInfo)
|
||||
&& !spellInfo->CanPierceImmuneAura(immuneSpellInfo))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Unit::IsImmunedToDamageOrSchool(SpellSchoolMask schoolMask) const
|
||||
{
|
||||
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsImmunedToDamage(schoolMask) || IsImmunedToSchool(schoolMask);
|
||||
}
|
||||
@@ -10102,27 +10044,8 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Unit const* caster, Spel
|
||||
|
||||
if (!spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
|
||||
{
|
||||
if (spellSchoolMask != SPELL_SCHOOL_MASK_NONE)
|
||||
{
|
||||
SpellImmuneContainer const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||
for (auto itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
||||
{
|
||||
if (itr->second == spellInfo->Id)
|
||||
continue;
|
||||
|
||||
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->second);
|
||||
if (!(itr->first & spellSchoolMask))
|
||||
continue;
|
||||
|
||||
if (IgnoresSchoolImmunityFromFriendlyCaster(caster, itr->second, immuneSpellInfo))
|
||||
continue;
|
||||
|
||||
if (spellInfo->CanPierceImmuneAura(immuneSpellInfo))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (HasSchoolImmunityForMask(spellSchoolMask, caster, spellInfo))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -1645,14 +1645,13 @@ public:
|
||||
[[nodiscard]] bool IsImmunedToDamage(SpellSchoolMask schoolMask) const;
|
||||
[[nodiscard]] bool IsImmunedToDamage(Unit const* caster, SpellInfo const* spellInfo) const;
|
||||
[[nodiscard]] bool IsImmunedToSchool(SpellSchoolMask schoolMask) const;
|
||||
[[nodiscard]] bool HasSchoolImmunityForMask(SpellSchoolMask schoolMask, Unit const* caster, SpellInfo const* spellInfo) const;
|
||||
|
||||
static bool IsImmuneMaskFully(SpellSchoolMask immuneMask, SpellSchoolMask schoolMask) { return (immuneMask & schoolMask) == schoolMask; }
|
||||
|
||||
[[nodiscard]] uint32 GetSchoolImmunityMask() const;
|
||||
[[nodiscard]] uint32 GetDamageImmunityMask() const;
|
||||
|
||||
[[nodiscard]] bool IsImmunedToSchool(SpellInfo const* spellInfo) const;
|
||||
[[nodiscard]] bool IsImmunedToSchool(Spell const* spell) const;
|
||||
[[nodiscard]] bool IsImmunedToDamageOrSchool(SpellSchoolMask schoolMask) const;
|
||||
[[nodiscard]] bool IsImmunedToAuraPeriodicTick(Unit const* caster, SpellInfo const* spellInfo) const;
|
||||
virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit const* caster = nullptr) const;
|
||||
|
||||
@@ -2982,7 +2982,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
|
||||
return SPELL_MISS_EVADE;
|
||||
|
||||
// For delayed spells immunity may be applied between missile launch and hit - check immunity for that case
|
||||
if (m_spellInfo->Speed && ((m_damage > 0 && unit->IsImmunedToDamage(m_caster, m_spellInfo)) || unit->IsImmunedToSchool(this) || unit->IsImmunedToSpell(m_spellInfo, this)))
|
||||
if (m_spellInfo->Speed && ((m_damage > 0 && unit->IsImmunedToDamage(m_caster, m_spellInfo)) || unit->IsImmunedToSpell(m_spellInfo, this)))
|
||||
{
|
||||
return SPELL_MISS_IMMUNE;
|
||||
}
|
||||
|
||||
@@ -5202,6 +5202,16 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
spellInfo->Effects[EFFECT_0].BasePoints = 1;
|
||||
});
|
||||
|
||||
ApplySpellFix({
|
||||
42292, // PvP Trinket
|
||||
59752, // Every Man for Himself
|
||||
19574, // Bestial Wrath
|
||||
34471 // The Beast Within
|
||||
}, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->AttributesEx2 |= SPELL_ATTR2_NO_SCHOOL_IMMUNITIES;
|
||||
});
|
||||
|
||||
// 51036 Summon Venture Co. Air Patrol
|
||||
ApplySpellFix({ 51036 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user