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 (cherry picked from commit 3306a4d06cc557967c23adcc60c2e3257811b324)
This commit is contained in:
@@ -2344,12 +2344,13 @@ void Creature::LoadTemplateImmunities()
|
||||
}
|
||||
}
|
||||
|
||||
bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const
|
||||
bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster,
|
||||
bool requireImmunityPurgesEffectAttribute /*= false*/) const
|
||||
{
|
||||
if (GetCreatureTemplate()->type == CREATURE_TYPE_MECHANICAL && spellEffectInfo.IsEffect(SPELL_EFFECT_HEAL))
|
||||
return true;
|
||||
|
||||
return Unit::IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster);
|
||||
return Unit::IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster, requireImmunityPurgesEffectAttribute);
|
||||
}
|
||||
|
||||
bool Creature::isElite() const
|
||||
|
||||
@@ -151,7 +151,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
|
||||
bool CanResetTalents(Player* player) const;
|
||||
bool CanCreatureAttack(Unit const* victim, bool force = true) const;
|
||||
void LoadTemplateImmunities();
|
||||
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const override;
|
||||
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute = false) const override;
|
||||
bool isElite() const;
|
||||
bool isWorldBoss() const;
|
||||
|
||||
|
||||
@@ -1673,7 +1673,8 @@ void Player::SetObjectScale(float scale)
|
||||
SendMovementSetCollisionHeight(scale * GetCollisionHeight(), WorldPackets::Movement::UpdateCollisionHeightReason::Scale);
|
||||
}
|
||||
|
||||
bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const
|
||||
bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster,
|
||||
bool requireImmunityPurgesEffectAttribute /*= false*/) const
|
||||
{
|
||||
// players are immune to taunt (the aura and the spell effect).
|
||||
if (spellEffectInfo.IsAura(SPELL_AURA_MOD_TAUNT))
|
||||
@@ -1681,7 +1682,7 @@ bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo
|
||||
if (spellEffectInfo.IsEffect(SPELL_EFFECT_ATTACK_ME))
|
||||
return true;
|
||||
|
||||
return Unit::IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster);
|
||||
return Unit::IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster, requireImmunityPurgesEffectAttribute);
|
||||
}
|
||||
|
||||
void Player::RegenerateAll()
|
||||
|
||||
@@ -1150,7 +1150,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
|
||||
void Update(uint32 time) override;
|
||||
|
||||
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const override;
|
||||
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute = false) const override;
|
||||
|
||||
bool IsInAreaTriggerRadius(AreaTriggerEntry const* trigger) const;
|
||||
|
||||
|
||||
@@ -140,7 +140,8 @@ void Totem::UnSummon(uint32 msTime)
|
||||
AddObjectToRemoveList();
|
||||
}
|
||||
|
||||
bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const
|
||||
bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster,
|
||||
bool requireImmunityPurgesEffectAttribute /*= false*/) const
|
||||
{
|
||||
// immune to all positive spells, except of stoneclaw totem absorb and sentry totem bind sight
|
||||
// totems positive spells have unit_caster target
|
||||
@@ -161,5 +162,5 @@ bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo c
|
||||
break;
|
||||
}
|
||||
|
||||
return Creature::IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster);
|
||||
return Creature::IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster, requireImmunityPurgesEffectAttribute);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class TC_GAME_API Totem : public Minion
|
||||
void UpdateAttackPowerAndDamage(bool /*ranged*/) override { }
|
||||
void UpdateDamagePhysical(WeaponAttackType /*attType*/) override { }
|
||||
|
||||
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const override;
|
||||
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute = false) const override;
|
||||
|
||||
protected:
|
||||
TotemType m_type;
|
||||
|
||||
@@ -3642,59 +3642,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();)
|
||||
{
|
||||
@@ -3706,7 +3706,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();
|
||||
}
|
||||
@@ -4039,42 +4039,31 @@ void Unit::RemoveAurasWithFamily(SpellFamilyNames family, flag128 const& familyF
|
||||
void Unit::RemoveMovementImpairingAuras(bool withRoot)
|
||||
{
|
||||
if (withRoot)
|
||||
RemoveAurasWithMechanic(1 << MECHANIC_ROOT);
|
||||
RemoveAurasWithMechanic(1 << MECHANIC_ROOT, AURA_REMOVE_BY_DEFAULT, 0, true);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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)
|
||||
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()
|
||||
@@ -7244,14 +7233,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, DIFFICULTY_NONE))
|
||||
if (immunitySourceSpell->HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT))
|
||||
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_NO_IMMUNITIES))
|
||||
@@ -7260,7 +7265,7 @@ 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;
|
||||
}
|
||||
|
||||
@@ -7268,7 +7273,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste
|
||||
if (uint32 mechanic = spellInfo->Mechanic)
|
||||
{
|
||||
SpellImmuneContainer const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
|
||||
if (mechanicList.count(mechanic) > 0)
|
||||
if (hasImmunity(mechanicList, mechanic))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7279,7 +7284,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste
|
||||
// Ignore effects with mechanic, they are supposed to be checked separately
|
||||
if (!spellEffectInfo.IsEffect())
|
||||
continue;
|
||||
if (!IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster))
|
||||
if (!IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster, requireImmunityPurgesEffectAttribute))
|
||||
{
|
||||
immuneToAllEffects = false;
|
||||
break;
|
||||
@@ -7303,7 +7308,8 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste
|
||||
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->second, GetMap()->GetDifficultyID());
|
||||
// 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_IMMUNITY_PURGES_EFFECT)))
|
||||
|| !spellInfo->IsPositive() || !caster || !IsFriendlyTo(caster))
|
||||
if (!spellInfo->CanPierceImmuneAura(immuneSpellInfo))
|
||||
schoolImmunityMask |= itr->first;
|
||||
}
|
||||
@@ -7344,7 +7350,8 @@ 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)
|
||||
return false;
|
||||
@@ -7352,15 +7359,31 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo co
|
||||
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES))
|
||||
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, DIFFICULTY_NONE))
|
||||
if (immunitySourceSpell->HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
// If m_immuneToEffect type contain this effect type, IMMUNE effect.
|
||||
auto 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;
|
||||
}
|
||||
|
||||
@@ -7369,7 +7392,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo co
|
||||
if (!spellInfo->HasAttribute(SPELL_ATTR3_ALWAYS_HIT))
|
||||
{
|
||||
SpellImmuneContainer const& list = m_spellImmune[IMMUNITY_STATE];
|
||||
if (list.count(aura) > 0)
|
||||
if (hasImmunity(list, aura))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1367,14 +1367,14 @@ class TC_GAME_API Unit : public WorldObject
|
||||
void RemoveAura(Aura* aur, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
|
||||
|
||||
// Convenience methods removing auras by predicate
|
||||
void RemoveAppliedAuras(std::function<bool(AuraApplication const*)> const& check);
|
||||
void RemoveOwnedAuras(std::function<bool(Aura const*)> const& check);
|
||||
void RemoveAppliedAuras(std::function<bool(AuraApplication const*)> const& check, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
|
||||
void RemoveOwnedAuras(std::function<bool(Aura const*)> const& check, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
|
||||
|
||||
// Optimized overloads taking advantage of map key
|
||||
void RemoveAppliedAuras(uint32 spellId, std::function<bool(AuraApplication const*)> const& check);
|
||||
void RemoveOwnedAuras(uint32 spellId, std::function<bool(Aura const*)> const& check);
|
||||
void RemoveAppliedAuras(uint32 spellId, std::function<bool(AuraApplication const*)> const& check, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
|
||||
void RemoveOwnedAuras(uint32 spellId, std::function<bool(Aura const*)> const& check, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
|
||||
|
||||
void RemoveAurasByType(AuraType auraType, std::function<bool(AuraApplication const*)> const& check);
|
||||
void RemoveAurasByType(AuraType auraType, std::function<bool(AuraApplication const*)> const& check, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
|
||||
|
||||
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, uint32 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
|
||||
void RemoveAuraFromStack(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT, uint16 num = 1);
|
||||
@@ -1387,7 +1387,7 @@ class TC_GAME_API Unit : public WorldObject
|
||||
void RemoveAurasWithInterruptFlags(InterruptFlags flag, SpellInfo const* source = nullptr);
|
||||
void RemoveAurasWithAttribute(uint32 flags);
|
||||
void RemoveAurasWithFamily(SpellFamilyNames family, flag128 const& familyFlag, ObjectGuid casterGUID);
|
||||
void RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveMode removemode = AURA_REMOVE_BY_DEFAULT, uint32 except = 0);
|
||||
void RemoveAurasWithMechanic(uint32 mechanicMaskToRemove, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT, uint32 exceptSpellId = 0, bool withEffectMechanics = false);
|
||||
void RemoveMovementImpairingAuras(bool withRoot);
|
||||
void RemoveAurasByShapeShift();
|
||||
|
||||
@@ -1710,14 +1710,14 @@ class TC_GAME_API Unit : public WorldObject
|
||||
static uint32 SpellCriticalHealingBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage, Unit* victim);
|
||||
|
||||
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply);
|
||||
bool IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caster) const;
|
||||
bool IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute = false) const;
|
||||
uint32 GetSchoolImmunityMask() const;
|
||||
uint32 GetDamageImmunityMask() const;
|
||||
uint32 GetMechanicImmunityMask() const;
|
||||
|
||||
bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const;
|
||||
bool IsImmunedToDamage(SpellInfo const* spellInfo) const;
|
||||
virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const;
|
||||
virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute = false) 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);
|
||||
|
||||
@@ -179,7 +179,7 @@ void AuraApplication::_HandleEffect(uint8 effIndex, bool apply)
|
||||
SetNeedClientUpdate();
|
||||
}
|
||||
|
||||
void AuraApplication::UpdateApplyEffectMask(uint32 newEffMask)
|
||||
void AuraApplication::UpdateApplyEffectMask(uint32 newEffMask, bool canHandleNewEffects)
|
||||
{
|
||||
if (_effectsToApply == newEffMask)
|
||||
return;
|
||||
@@ -194,20 +194,17 @@ void AuraApplication::UpdateApplyEffectMask(uint32 newEffMask)
|
||||
return;
|
||||
}
|
||||
|
||||
// update real effects only if they were applied already
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
{
|
||||
// update real effects only if they were applied already
|
||||
if (!(_effectMask & (1 << i)))
|
||||
continue;
|
||||
|
||||
if (removeEffMask & (1 << i))
|
||||
if (HasEffect(i) && (removeEffMask & (1 << i)))
|
||||
_HandleEffect(i, false);
|
||||
|
||||
if (addEffMask & (1 << i))
|
||||
_HandleEffect(i, true);
|
||||
}
|
||||
|
||||
_effectsToApply = newEffMask;
|
||||
|
||||
if (canHandleNewEffects)
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
if (addEffMask & (1 << i))
|
||||
_HandleEffect(i, true);
|
||||
}
|
||||
|
||||
void AuraApplication::SetNeedClientUpdate()
|
||||
@@ -367,7 +364,7 @@ Aura* Aura::TryRefreshStackOrCreate(AuraCreateInfo& createInfo, bool updateEffec
|
||||
// check effmask on owner application (if existing)
|
||||
if (updateEffectMask)
|
||||
if (AuraApplication* aurApp = foundAura->GetApplicationOfTarget(unit->GetGUID()))
|
||||
aurApp->UpdateApplyEffectMask(effMask);
|
||||
aurApp->UpdateApplyEffectMask(effMask, false);
|
||||
return foundAura;
|
||||
}
|
||||
else
|
||||
@@ -635,12 +632,17 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
|
||||
{
|
||||
// needs readding - remove now, will be applied in next update cycle
|
||||
// (dbcs do not have auras which apply on same type of targets but have different radius, so this is not really needed)
|
||||
if (!CanBeAppliedOn(itr->first))
|
||||
if (itr->first->IsImmunedToSpell(GetSpellInfo(), caster, true) || !CanBeAppliedOn(itr->first))
|
||||
{
|
||||
targetsToRemove.push_back(applicationPair.second->GetTarget());
|
||||
continue;
|
||||
}
|
||||
|
||||
// check target immunities (for existing targets)
|
||||
for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
|
||||
if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster, true))
|
||||
itr->second &= ~(1 << spellEffectInfo.EffectIndex);
|
||||
|
||||
// needs to add/remove effects from application, don't remove from map so it gets updated
|
||||
if (applicationPair.second->GetEffectMask() != itr->second)
|
||||
continue;
|
||||
@@ -655,13 +657,17 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
|
||||
for (auto itr = targets.begin(); itr != targets.end();)
|
||||
{
|
||||
bool addUnit = true;
|
||||
// check target immunities
|
||||
for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
|
||||
if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster))
|
||||
itr->second &= ~(1 << spellEffectInfo.EffectIndex);
|
||||
AuraApplication* aurApp = GetApplicationOfTarget(itr->first->GetGUID());
|
||||
if (!aurApp)
|
||||
{
|
||||
// check target immunities (for new targets)
|
||||
for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
|
||||
if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster))
|
||||
itr->second &= ~(1 << spellEffectInfo.EffectIndex);
|
||||
|
||||
if (!itr->second || itr->first->IsImmunedToSpell(GetSpellInfo(), caster) || !CanBeAppliedOn(itr->first))
|
||||
addUnit = false;
|
||||
if (!itr->second || itr->first->IsImmunedToSpell(GetSpellInfo(), caster) || !CanBeAppliedOn(itr->first))
|
||||
addUnit = false;
|
||||
}
|
||||
|
||||
if (addUnit && !itr->first->IsHighestExclusiveAura(this, true))
|
||||
addUnit = false;
|
||||
@@ -704,14 +710,16 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
|
||||
ABORT();
|
||||
}
|
||||
|
||||
if (AuraApplication* aurApp = GetApplicationOfTarget(itr->first->GetGUID()))
|
||||
if (aurApp)
|
||||
{
|
||||
// aura is already applied, this means we need to update effects of current application
|
||||
itr->first->_UnapplyAura(aurApp, AURA_REMOVE_BY_DEFAULT);
|
||||
aurApp->UpdateApplyEffectMask(itr->second, true); // aura is already applied, this means we need to update effects of current application
|
||||
itr = targets.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
itr->first->_CreateAuraApplication(this, itr->second);
|
||||
++itr;
|
||||
}
|
||||
|
||||
itr->first->_CreateAuraApplication(this, itr->second);
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ class TC_GAME_API AuraApplication
|
||||
bool IsSelfcast() const { return (_flags & AFLAG_NOCASTER) != 0; }
|
||||
|
||||
uint32 GetEffectsToApply() const { return _effectsToApply; }
|
||||
void UpdateApplyEffectMask(uint32 newEffMask);
|
||||
void UpdateApplyEffectMask(uint32 newEffMask, bool canHandleNewEffects);
|
||||
|
||||
void SetRemoveMode(AuraRemoveMode mode) { _removeMode = mode; }
|
||||
AuraRemoveMode GetRemoveMode() const { return _removeMode; }
|
||||
|
||||
@@ -989,7 +989,7 @@ void Spell::EffectApplyAura()
|
||||
if (!aurApp)
|
||||
aurApp = unitTarget->_CreateAuraApplication(_spellAura, 1 << effectInfo->EffectIndex);
|
||||
else
|
||||
aurApp->UpdateApplyEffectMask(aurApp->GetEffectsToApply() | 1 << effectInfo->EffectIndex);
|
||||
aurApp->UpdateApplyEffectMask(aurApp->GetEffectsToApply() | 1 << effectInfo->EffectIndex, false);
|
||||
}
|
||||
|
||||
void Spell::EffectUnlearnSpecialization()
|
||||
|
||||
@@ -3531,13 +3531,22 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const& s
|
||||
if (mechanicImmunity & (1 << i))
|
||||
target->ApplySpellImmune(Id, IMMUNITY_MECHANIC, i, apply);
|
||||
|
||||
if (apply && HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT))
|
||||
if (HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT))
|
||||
{
|
||||
// exception for purely snare mechanic (eg. hands of freedom)!
|
||||
if (mechanicImmunity == (1 << MECHANIC_SNARE))
|
||||
target->RemoveMovementImpairingAuras(false);
|
||||
else
|
||||
if (apply)
|
||||
target->RemoveAurasWithMechanic(mechanicImmunity, AURA_REMOVE_BY_DEFAULT, Id);
|
||||
else
|
||||
{
|
||||
target->RemoveAppliedAuras([mechanicImmunity](AuraApplication const* aurApp)
|
||||
{
|
||||
Aura* aura = aurApp->GetBase();
|
||||
if (aura->GetSpellInfo()->GetAllEffectsMechanicMask() & mechanicImmunity)
|
||||
aura->UpdateTargetMap(aura->GetCaster());
|
||||
|
||||
// only update targets, don't remove anything
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user