-
Notifications
You must be signed in to change notification settings - Fork 6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Core/Auras: Improve aura interactions with immunities on spell effect…
… level * Effects that target is immune to will be suppressed instead of completely removed Closes #28096
- Loading branch information
Showing
12 changed files
with
147 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3739,59 +3739,59 @@ void Unit::RemoveAura(Aura* aura, AuraRemoveMode mode) | |
RemoveAura(aurApp, mode); | ||
} | ||
|
||
void Unit::RemoveAppliedAuras(std::function<bool(AuraApplication const*)> const& check) | ||
void Unit::RemoveAppliedAuras(std::function<bool(AuraApplication const*)> const& check, AuraRemoveMode removeMode /*= AURA_REMOVE_BY_DEFAULT*/) | ||
{ | ||
for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();) | ||
{ | ||
if (check(iter->second)) | ||
{ | ||
RemoveAura(iter); | ||
RemoveAura(iter, removeMode); | ||
continue; | ||
} | ||
++iter; | ||
} | ||
} | ||
|
||
void Unit::RemoveOwnedAuras(std::function<bool(Aura const*)> const& check) | ||
void Unit::RemoveOwnedAuras(std::function<bool(Aura const*)> const& check, AuraRemoveMode removeMode /*= AURA_REMOVE_BY_DEFAULT*/) | ||
{ | ||
for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();) | ||
{ | ||
if (check(iter->second)) | ||
{ | ||
RemoveOwnedAura(iter); | ||
RemoveOwnedAura(iter, removeMode); | ||
continue; | ||
} | ||
++iter; | ||
} | ||
} | ||
|
||
void Unit::RemoveAppliedAuras(uint32 spellId, std::function<bool(AuraApplication const*)> const& check) | ||
void Unit::RemoveAppliedAuras(uint32 spellId, std::function<bool(AuraApplication const*)> const& check, AuraRemoveMode removeMode /*= AURA_REMOVE_BY_DEFAULT*/) | ||
{ | ||
for (AuraApplicationMap::iterator iter = m_appliedAuras.lower_bound(spellId); iter != m_appliedAuras.upper_bound(spellId);) | ||
{ | ||
if (check(iter->second)) | ||
{ | ||
RemoveAura(iter); | ||
RemoveAura(iter, removeMode); | ||
continue; | ||
} | ||
++iter; | ||
} | ||
} | ||
|
||
void Unit::RemoveOwnedAuras(uint32 spellId, std::function<bool(Aura const*)> const& check) | ||
void Unit::RemoveOwnedAuras(uint32 spellId, std::function<bool(Aura const*)> const& check, AuraRemoveMode removeMode /*= AURA_REMOVE_BY_DEFAULT*/) | ||
{ | ||
for (AuraMap::iterator iter = m_ownedAuras.lower_bound(spellId); iter != m_ownedAuras.upper_bound(spellId);) | ||
{ | ||
if (check(iter->second)) | ||
{ | ||
RemoveOwnedAura(iter); | ||
RemoveOwnedAura(iter, removeMode); | ||
continue; | ||
} | ||
++iter; | ||
} | ||
} | ||
|
||
void Unit::RemoveAurasByType(AuraType auraType, std::function<bool(AuraApplication const*)> const& check) | ||
void Unit::RemoveAurasByType(AuraType auraType, std::function<bool(AuraApplication const*)> const& check, AuraRemoveMode removeMode /*= AURA_REMOVE_BY_DEFAULT*/) | ||
{ | ||
for (AuraEffectList::iterator iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end();) | ||
{ | ||
|
@@ -3803,7 +3803,7 @@ void Unit::RemoveAurasByType(AuraType auraType, std::function<bool(AuraApplicati | |
if (check(aurApp)) | ||
{ | ||
uint32 removedAuras = m_removedAurasCount; | ||
RemoveAura(aurApp); | ||
RemoveAura(aurApp, removeMode); | ||
if (m_removedAurasCount > removedAuras + 1) | ||
iter = m_modAuras[auraType].begin(); | ||
} | ||
|
@@ -4098,42 +4098,31 @@ void Unit::RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, ui | |
void Unit::RemoveMovementImpairingAuras(bool withRoot) | ||
{ | ||
if (withRoot) | ||
RemoveAurasWithMechanic(1 << MECHANIC_ROOT); | ||
|
||
// Snares | ||
for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();) | ||
{ | ||
Aura const* aura = iter->second->GetBase(); | ||
if (aura->GetSpellInfo()->Mechanic == MECHANIC_SNARE) | ||
{ | ||
RemoveAura(iter); | ||
continue; | ||
} | ||
RemoveAurasWithMechanic(1 << MECHANIC_ROOT, AURA_REMOVE_BY_DEFAULT, 0, true); | ||
|
||
// turn off snare auras by setting amount to 0 | ||
for (SpellEffectInfo const& spellEffectInfo : aura->GetSpellInfo()->GetEffects()) | ||
if (iter->second->HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.Mechanic == MECHANIC_SNARE) | ||
aura->GetEffect(spellEffectInfo.EffectIndex)->ChangeAmount(0); | ||
|
||
++iter; | ||
} | ||
RemoveAurasWithMechanic(1 << MECHANIC_SNARE, AURA_REMOVE_BY_DEFAULT, 0, false); | ||
} | ||
|
||
void Unit::RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveMode removemode, uint32 except) | ||
void Unit::RemoveAurasWithMechanic(uint32 mechanicMaskToRemove, AuraRemoveMode removeMode, uint32 exceptSpellId, bool withEffectMechanics) | ||
{ | ||
for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();) | ||
RemoveAppliedAuras([=](AuraApplication const* aurApp) | ||
{ | ||
Aura const* aura = iter->second->GetBase(); | ||
if (!except || aura->GetId() != except) | ||
{ | ||
if (aura->GetSpellInfo()->GetAllEffectsMechanicMask() & mechanic_mask) | ||
{ | ||
RemoveAura(iter, removemode); | ||
continue; | ||
} | ||
} | ||
++iter; | ||
} | ||
Aura* aura = aurApp->GetBase(); | ||
if (exceptSpellId && aura->GetId() == exceptSpellId) | ||
return false; | ||
|
||
uint32 appliedMechanicMask = aura->GetSpellInfo()->GetSpellMechanicMaskByEffectMask(aurApp->GetEffectMask()); | ||
if (!(appliedMechanicMask & mechanicMaskToRemove)) | ||
return false; | ||
|
||
// spell mechanic matches required mask for removal | ||
if ((1 << aura->GetSpellInfo()->Mechanic) & mechanicMaskToRemove || withEffectMechanics) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
return true; | ||
|
||
// effect mechanic matches required mask for removal - don't remove, only update targets | ||
aura->UpdateTargetMap(aura->GetCaster()); | ||
return false; | ||
}, removeMode); | ||
} | ||
|
||
void Unit::RemoveAurasByShapeShift() | ||
|
@@ -7702,14 +7691,30 @@ bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo) const | |
return false; | ||
} | ||
|
||
bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caster) const | ||
bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute /*= false*/) const | ||
{ | ||
if (!spellInfo) | ||
return false; | ||
|
||
auto hasImmunity = [requireImmunityPurgesEffectAttribute](SpellImmuneContainer const& container, uint32 key) | ||
{ | ||
Trinity::IteratorPair<SpellImmuneContainer::const_iterator> range = Trinity::Containers::MapEqualRange(container, key); | ||
if (!requireImmunityPurgesEffectAttribute) | ||
return range.begin() != range.end(); | ||
|
||
return std::any_of(range.begin(), range.end(), [](SpellImmuneContainer::value_type const& entry) | ||
{ | ||
if (SpellInfo const* immunitySourceSpell = sSpellMgr->GetSpellInfo(entry.second)) | ||
if (immunitySourceSpell->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)) | ||
return true; | ||
|
||
return false; | ||
}); | ||
}; | ||
|
||
// Single spell immunity. | ||
SpellImmuneContainer const& idList = m_spellImmune[IMMUNITY_ID]; | ||
if (idList.count(spellInfo->Id) > 0) | ||
if (hasImmunity(idList, spellInfo->Id)) | ||
return true; | ||
|
||
if (spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)) | ||
|
@@ -7718,15 +7723,15 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste | |
if (uint32 dispel = spellInfo->Dispel) | ||
{ | ||
SpellImmuneContainer const& dispelList = m_spellImmune[IMMUNITY_DISPEL]; | ||
if (dispelList.count(dispel) > 0) | ||
if (hasImmunity(dispelList, dispel)) | ||
return true; | ||
} | ||
|
||
// Spells that don't have effectMechanics. | ||
if (uint32 mechanic = spellInfo->Mechanic) | ||
{ | ||
SpellImmuneContainer const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; | ||
if (mechanicList.count(mechanic) > 0) | ||
if (hasImmunity(mechanicList, mechanic)) | ||
return true; | ||
} | ||
|
||
|
@@ -7738,7 +7743,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste | |
if (!spellEffectInfo.IsEffect()) | ||
continue; | ||
|
||
if (!IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster)) | ||
if (!IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster, requireImmunityPurgesEffectAttribute)) | ||
{ | ||
immuneToAllEffects = false; | ||
break; | ||
|
@@ -7760,7 +7765,8 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste | |
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->second); | ||
// 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 ((immuneSpellInfo && !immuneSpellInfo->IsPositive() && (!requireImmunityPurgesEffectAttribute || immuneSpellInfo->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))) | ||
|| !spellInfo->IsPositive() || !caster || !IsFriendlyTo(caster)) | ||
if (!spellInfo->CanPierceImmuneAura(immuneSpellInfo)) | ||
schoolImmunityMask |= itr->first; | ||
} | ||
|
@@ -7802,23 +7808,40 @@ uint32 Unit::GetMechanicImmunityMask() const | |
return mask; | ||
} | ||
|
||
bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const | ||
bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster, | ||
bool requireImmunityPurgesEffectAttribute /*= false*/) const | ||
{ | ||
if (!spellInfo || !spellEffectInfo.IsEffect()) | ||
return false; | ||
|
||
if (spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)) | ||
return false; | ||
|
||
auto hasImmunity = [requireImmunityPurgesEffectAttribute](SpellImmuneContainer const& container, uint32 key) | ||
This comment has been minimized.
Sorry, something went wrong.
lineagedr
Contributor
|
||
{ | ||
Trinity::IteratorPair<SpellImmuneContainer::const_iterator> range = Trinity::Containers::MapEqualRange(container, key); | ||
if (!requireImmunityPurgesEffectAttribute) | ||
return range.begin() != range.end(); | ||
|
||
return std::any_of(range.begin(), range.end(), [](SpellImmuneContainer::value_type const& entry) | ||
{ | ||
if (SpellInfo const* immunitySourceSpell = sSpellMgr->GetSpellInfo(entry.second)) | ||
if (immunitySourceSpell->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)) | ||
return true; | ||
|
||
return false; | ||
}); | ||
}; | ||
|
||
// If m_immuneToEffect type contain this effect type, IMMUNE effect. | ||
SpellImmuneContainer const& effectList = m_spellImmune[IMMUNITY_EFFECT]; | ||
if (effectList.count(spellEffectInfo.Effect) > 0) | ||
if (hasImmunity(effectList, spellEffectInfo.Effect)) | ||
return true; | ||
|
||
if (uint32 mechanic = spellEffectInfo.Mechanic) | ||
{ | ||
SpellImmuneContainer const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; | ||
if (mechanicList.count(mechanic) > 0) | ||
if (hasImmunity(mechanicList, mechanic)) | ||
return true; | ||
} | ||
|
||
|
@@ -7827,7 +7850,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo co | |
if (!spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT)) | ||
{ | ||
SpellImmuneContainer const& list = m_spellImmune[IMMUNITY_STATE]; | ||
if (list.count(aura) > 0) | ||
if (hasImmunity(list, aura)) | ||
return true; | ||
} | ||
|
||
|
Oops, something went wrong.
Possibly missing parenthesis