Core/Auras: Improve aura interactions with immunities on spell effect level

* Effects that target is immune to will be suppressed instead of completely removed
This commit is contained in:
Shauren authored and Ovahlord committed 2022-09-30 12:49:31 +02:00
1 parent 0f4442c630
commit c3b52fd29f
12 files changed
+147 -97

No files matched your search

@@ -2150,7 +2150,8 @@ void Creature::LoadTemplateImmunities()
}
}
bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const
bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster,
bool requireImmunityPurgesEffectAttribute /*= false*/) const
{
if (!spellInfo->Effects[index].IsEffect())
return true;
@@ -2158,7 +2159,7 @@ bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index,
if (GetCreatureTemplate()->type == CREATURE_TYPE_MECHANICAL && spellInfo->Effects[index].Effect == SPELL_EFFECT_HEAL)
return true;
return Unit::IsImmunedToSpellEffect(spellInfo, index, caster);
return Unit::IsImmunedToSpellEffect(spellInfo, index, caster, requireImmunityPurgesEffectAttribute);
}
bool Creature::isElite() const
+1 -1
View File
@@ -129,7 +129,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool IsClassTrainerOf(Player const* player) const;
bool CanCreatureAttack(Unit const* victim, bool force = true) const;
void LoadTemplateImmunities();
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const override;
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute = false) const override;
bool isElite() const;
bool isWorldBoss() const;
+3 -2
View File
@@ -1798,7 +1798,8 @@ void Player::SetObjectScale(float scale)
SendMovementSetCollisionHeight(GetCollisionHeight(), UPDATE_COLLISION_HEIGHT_SCALE);
}
bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const
bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster,
bool requireImmunityPurgesEffectAttribute /*= false*/) const
{
// players are immune to taunt (the aura and the spell effect)
if (spellInfo->Effects[index].IsAura(SPELL_AURA_MOD_TAUNT))
@@ -1806,7 +1807,7 @@ bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Wo
if (spellInfo->Effects[index].IsEffect(SPELL_EFFECT_ATTACK_ME))
return true;
return Unit::IsImmunedToSpellEffect(spellInfo, index, caster);
return Unit::IsImmunedToSpellEffect(spellInfo, index, caster, requireImmunityPurgesEffectAttribute);
}
void Player::RegenerateAll(uint32 diff)
+1 -1
View File
@@ -1031,7 +1031,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void Update(uint32 time) override;
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const override;
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute = false) const override;
bool IsInAreaTriggerRadius(AreaTriggerEntry const* trigger) const;
+3 -2
View File
@@ -145,7 +145,8 @@ void Totem::UnSummon(uint32 msTime)
AddObjectToRemoveList();
}
bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const
bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, 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
@@ -166,5 +167,5 @@ bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Wor
break;
}
return Creature::IsImmunedToSpellEffect(spellInfo, index, caster);
return Creature::IsImmunedToSpellEffect(spellInfo, index, caster, requireImmunityPurgesEffectAttribute);
}
+1 -1
View File
@@ -61,7 +61,7 @@ class TC_GAME_API Totem : public Minion
void UpdateAttackPowerAndDamage(bool /*ranged*/) override { }
void UpdateDamagePhysical(WeaponAttackType /*attType*/) override { }
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const override;
bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute = false) const override;
protected:
TotemType m_type;
+75 -51
View File
@@ -3465,59 +3465,59 @@ void Unit::RemoveAura(Aura* aura, AuraRemoveFlags mode)
RemoveAura(aurApp, mode);
}
void Unit::RemoveAppliedAuras(std::function<bool(AuraApplication const*)> const& check)
void Unit::RemoveAppliedAuras(std::function<bool(AuraApplication const*)> const& check, AuraRemoveFlags removeMode /* = AuraRemoveFlags::ByDefault*/)
{
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, AuraRemoveFlags removeMode /* = AuraRemoveFlags::ByDefault*/)
{
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, AuraRemoveFlags removeMode /* = AuraRemoveFlags::ByDefault*/)
{
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, AuraRemoveFlags removeMode /* = AuraRemoveFlags::ByDefault*/)
{
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, AuraRemoveFlags removeMode /* = AuraRemoveFlags::ByDefault*/)
{
for (AuraEffectList::iterator iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end();)
{
@@ -3529,7 +3529,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();
}
@@ -3856,42 +3856,31 @@ void Unit::RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, ui
void Unit::RemoveMovementImpairingAuras(bool withRoot)
{
if (withRoot)
RemoveAurasWithMechanic(1 << MECHANIC_ROOT);
RemoveAurasWithMechanic(1 << MECHANIC_ROOT, AuraRemoveFlags::ByDefault, 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 (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (((1 << i) & iter->second->GetEffectMask()) && aura->GetSpellInfo()->Effects[i].Mechanic == MECHANIC_SNARE)
aura->GetEffect(i)->ChangeAmount(0);
++iter;
}
RemoveAurasWithMechanic(1 << MECHANIC_ROOT, AuraRemoveFlags::ByDefault, 0, false);
}
void Unit::RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveFlags removemode, uint32 except)
void Unit::RemoveAurasWithMechanic(uint32 mechanicMaskToRemove, AuraRemoveFlags 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()
@@ -7313,14 +7302,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_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))
@@ -7329,7 +7334,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;
}
@@ -7337,7 +7342,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;
}
@@ -7349,7 +7354,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste
if (!spellInfo->Effects[i].IsEffect())
continue;
if (!IsImmunedToSpellEffect(spellInfo, i, caster))
if (!IsImmunedToSpellEffect(spellInfo, i, caster, requireImmunityPurgesEffectAttribute))
{
immuneToAllEffects = false;
break;
@@ -7374,7 +7379,8 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste
// 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;
}
@@ -7416,7 +7422,8 @@ uint32 Unit::GetMechanicImmunityMask() const
return mask;
}
bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster) const
bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster,
bool requireImmunityPurgesEffectAttribute /*= false*/) const
{
if (!spellInfo || !spellInfo->Effects[index].IsEffect())
return false;
@@ -7424,16 +7431,33 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Worl
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))
if (immunitySourceSpell->HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT))
return true;
return false;
});
};
// If m_immuneToEffect type contain this effect type, IMMUNE effect.
uint32 effect = spellInfo->Effects[index].Effect;
SpellImmuneContainer const& effectList = m_spellImmune[IMMUNITY_EFFECT];
if (effectList.count(effect) > 0)
if (hasImmunity(effectList, effect))
return true;
if (uint32 mechanic = spellInfo->Effects[index].Mechanic)
{
SpellImmuneContainer const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
if (mechanicList.count(mechanic) > 0)
if (hasImmunity(mechanicList, mechanic))
return true;
}
@@ -7442,7 +7466,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Worl
if (uint32 aura = spellInfo->Effects[index].ApplyAuraName)
{
SpellImmuneContainer const& list = m_spellImmune[IMMUNITY_STATE];
if (list.count(aura) > 0)
if (hasImmunity(list, aura))
return true;
if (!spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
+8 -8
View File
@@ -1332,14 +1332,14 @@ class TC_GAME_API Unit : public WorldObject
void RemoveAura(Aura* aur, AuraRemoveFlags mode = AuraRemoveFlags::ByDefault);
// 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, AuraRemoveFlags removeMode = AuraRemoveFlags::ByDefault);
void RemoveOwnedAuras(std::function<bool(Aura const*)> const& check, AuraRemoveFlags removeMode = AuraRemoveFlags::ByDefault);
// 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, AuraRemoveFlags removeMode = AuraRemoveFlags::ByDefault);
void RemoveOwnedAuras(uint32 spellId, std::function<bool(Aura const*)> const& check, AuraRemoveFlags removeMode = AuraRemoveFlags::ByDefault);
void RemoveAurasByType(AuraType auraType, std::function<bool(AuraApplication const*)> const& check);
void RemoveAurasByType(AuraType auraType, std::function<bool(AuraApplication const*)> const& check, AuraRemoveFlags removeMode = AuraRemoveFlags::ByDefault);
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, uint8 reqEffMask = 0, AuraRemoveFlags removeMode = AuraRemoveFlags::ByDefault);
void RemoveAuraFromStack(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, AuraRemoveFlags removeMode = AuraRemoveFlags::ByDefault);
@@ -1352,7 +1352,7 @@ class TC_GAME_API Unit : public WorldObject
void RemoveAurasWithInterruptFlags(InterruptFlags flag, SpellInfo const* source = nullptr);
void RemoveAurasWithAttribute(uint32 flags);
void RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, ObjectGuid casterGUID);
void RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveFlags removemode = AuraRemoveFlags::ByDefault, uint32 except = 0);
void RemoveAurasWithMechanic(uint32 mechanicMaskToRemove, AuraRemoveFlags removeMode = AuraRemoveFlags::ByDefault, uint32 exceptSpellId = 0, bool withEffectMechanics = false);
void RemoveMovementImpairingAuras(bool withRoot);
void RemoveAurasByShapeShift();
@@ -1616,14 +1616,14 @@ class TC_GAME_API Unit : public WorldObject
float CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffectType damagetype) const;
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, uint32 index, WorldObject const* caster) const; // redefined in Creature
virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute = false) const; // redefined in Creature
static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = nullptr);
static uint32 CalcArmorReducedDamage(Unit const* attacker, Unit* victim, const uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = MAX_ATTACK, uint8 attackerLevel = 0);
+33 -25
View File
@@ -201,7 +201,7 @@ void AuraApplication::_HandleEffect(uint8 effIndex, bool apply)
SetNeedClientUpdate();
}
void AuraApplication::UpdateApplyEffectMask(uint8 newEffMask)
void AuraApplication::UpdateApplyEffectMask(uint8 newEffMask, bool canHandleNewEffects)
{
if (_effectsToApply == newEffMask)
return;
@@ -216,20 +216,17 @@ void AuraApplication::UpdateApplyEffectMask(uint8 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 (!(_flags & (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::BuildUpdatePacket(WorldPackets::Spells::AuraInfo& auraInfo, bool remove) const
@@ -351,7 +348,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
@@ -672,12 +669,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 (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), i, caster, true))
itr->second &= ~(1 << i);
// needs to add/remove effects from application, don't remove from map so it gets updated
if (applicationPair.second->GetEffectMask() != itr->second)
continue;
@@ -692,13 +694,17 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
for (auto itr = targets.begin(); itr != targets.end();)
{
bool addUnit = true;
// check target immunities
for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), effIndex, caster))
itr->second &= ~(1 << effIndex);
AuraApplication* aurApp = GetApplicationOfTarget(itr->first->GetGUID());
if (!aurApp)
{
// check target immunities (for new targets)
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), i, caster))
itr->second &= ~(1 << i);
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;
@@ -741,14 +747,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, AuraRemoveFlags::ByDefault);
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;
}
}
+1 -1
View File
@@ -82,7 +82,7 @@ class TC_GAME_API AuraApplication
bool IsPositive() const { return (_flags & AFLAG_POSITIVE) != 0; }
bool IsSelfcast() const { return (_flags & AFLAG_CASTER) != 0; }
uint8 GetEffectsToApply() const { return _effectsToApply; }
void UpdateApplyEffectMask(uint8 newEffMask);
void UpdateApplyEffectMask(uint8 newEffMask, bool canHandleNewEffects);
void SetRemoveMode(AuraRemoveFlags mode) { _removeMode = mode; }
EnumFlag<AuraRemoveFlags> GetRemoveMode() const { return _removeMode; }
+1 -1
View File
@@ -960,7 +960,7 @@ void Spell::EffectApplyAura(SpellEffIndex effIndex)
if (!aurApp)
aurApp = unitTarget->_CreateAuraApplication(_spellAura, 1 << effIndex);
else
aurApp->UpdateApplyEffectMask(aurApp->GetEffectsToApply() | 1 << effIndex);
aurApp->UpdateApplyEffectMask(aurApp->GetEffectsToApply() | 1 << effIndex, false);
}
void Spell::EffectUnlearnSpecialization(SpellEffIndex effIndex)
+17 -2
View File
@@ -3117,8 +3117,23 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool app
if (mechanicImmunity & (1 << i))
target->ApplySpellImmune(Id, IMMUNITY_MECHANIC, i, apply);
if(apply && HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT))
target->RemoveAurasWithMechanic(mechanicImmunity, AuraRemoveFlags::ByDefault, Id);
if (HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT))
{
if (apply)
target->RemoveAurasWithMechanic(mechanicImmunity, AuraRemoveFlags::ByDefault, 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;
});
}
}
}
if (uint32 dispelImmunity = immuneInfo->DispelImmune)