Core/Spell: revamp of immunities system
- Spell attributes research - Container optimization - Do not skip damage immunity checks on SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY present - Added additonal arguments support to SendCastResult / CheckCast, spells can now send proper error messages - Loads spell immune masks/states/effects at startup. - This cached info is used whenever a spell cast requires immunities to be known beforehand (to see if an aura could be applied for example)
This commit is contained in:
1 parent
ab289e8494
commit
e4dd97765e
11 files changed
+874
-692
No files matched your search
@@ -224,9 +224,6 @@ Unit::Unit(bool isWorldObject) :
|
||||
m_transform = 0;
|
||||
m_canModifyStats = false;
|
||||
|
||||
for (uint8 i = 0; i < MAX_SPELL_IMMUNITY; ++i)
|
||||
m_spellImmune[i].clear();
|
||||
|
||||
for (uint8 i = 0; i < UNIT_MOD_END; ++i)
|
||||
{
|
||||
m_auraModifiersGroup[i][BASE_VALUE] = 0.0f;
|
||||
@@ -3006,10 +3003,14 @@ int32 Unit::GetCurrentSpellCastTime(uint32 spell_id) const
|
||||
bool Unit::CanMoveDuringChannel() const
|
||||
{
|
||||
if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL])
|
||||
if (spell->getState() != SPELL_STATE_FINISHED)
|
||||
return spell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING) && spell->IsChannelActive();
|
||||
{
|
||||
if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive())
|
||||
if (!spell->GetSpellInfo()->IsMoveAllowedChannel())
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const
|
||||
@@ -9703,18 +9704,18 @@ int32 Unit::SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask) const
|
||||
return advertisedBenefit;
|
||||
}
|
||||
|
||||
bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask) const
|
||||
bool Unit::IsImmunedToDamage(SpellSchoolMask schoolMask) const
|
||||
{
|
||||
// If m_immuneToSchool type contain this school type, IMMUNE damage.
|
||||
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
||||
if (itr->type & shoolMask)
|
||||
auto const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||
for (auto itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
||||
if ((itr->first & schoolMask) != 0)
|
||||
return true;
|
||||
|
||||
// If m_immuneToDamage type contain magic, IMMUNE damage.
|
||||
SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
|
||||
for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
|
||||
if (itr->type & shoolMask)
|
||||
auto const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
|
||||
for (auto itr = damageList.begin(); itr != damageList.end(); ++itr)
|
||||
if ((itr->first & schoolMask) != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -9722,23 +9723,17 @@ bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask) const
|
||||
|
||||
bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo) const
|
||||
{
|
||||
if (spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
|
||||
return false;
|
||||
|
||||
uint32 shoolMask = spellInfo->GetSchoolMask();
|
||||
if (spellInfo->Id != 42292 && spellInfo->Id != 59752)
|
||||
{
|
||||
// If m_immuneToSchool type contain this school type, IMMUNE damage.
|
||||
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
||||
if (itr->type & shoolMask && !spellInfo->CanPierceImmuneAura(sSpellMgr->GetSpellInfo(itr->spellId)))
|
||||
return true;
|
||||
}
|
||||
uint32 schoolMask = spellInfo->GetSchoolMask();
|
||||
// If m_immuneToSchool type contain this school type, IMMUNE damage.
|
||||
auto 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)))
|
||||
return true;
|
||||
|
||||
// If m_immuneToDamage type contain magic, IMMUNE damage.
|
||||
SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
|
||||
for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
|
||||
if (itr->type & shoolMask)
|
||||
auto const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
|
||||
for (auto itr = damageList.begin(); itr != damageList.end(); ++itr)
|
||||
if ((itr->first & schoolMask) != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -9750,29 +9745,26 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) const
|
||||
return false;
|
||||
|
||||
// Single spell immunity.
|
||||
SpellImmuneList const& idList = m_spellImmune[IMMUNITY_ID];
|
||||
for (SpellImmuneList::const_iterator itr = idList.begin(); itr != idList.end(); ++itr)
|
||||
if (itr->type == spellInfo->Id)
|
||||
return true;
|
||||
auto const& idList = m_spellImmune[IMMUNITY_ID];
|
||||
if (idList.count(spellInfo->Id) > 0)
|
||||
return true;
|
||||
|
||||
if (spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
|
||||
return false;
|
||||
|
||||
if (spellInfo->Dispel)
|
||||
if (uint32 dispel = spellInfo->Dispel)
|
||||
{
|
||||
SpellImmuneList const& dispelList = m_spellImmune[IMMUNITY_DISPEL];
|
||||
for (SpellImmuneList::const_iterator itr = dispelList.begin(); itr != dispelList.end(); ++itr)
|
||||
if (itr->type == spellInfo->Dispel)
|
||||
return true;
|
||||
auto const& dispelList = m_spellImmune[IMMUNITY_DISPEL];
|
||||
if (dispelList.count(dispel) > 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Spells that don't have effectMechanics.
|
||||
if (spellInfo->Mechanic)
|
||||
if (uint32 mechanic = spellInfo->Mechanic)
|
||||
{
|
||||
SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
|
||||
for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
|
||||
if (itr->type == spellInfo->Mechanic)
|
||||
return true;
|
||||
auto const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
|
||||
if (mechanicList.count(mechanic) > 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool immuneToAllEffects = true;
|
||||
@@ -9780,8 +9772,6 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) const
|
||||
{
|
||||
// State/effect immunities applied by aura expect full spell immunity
|
||||
// Ignore effects with mechanic, they are supposed to be checked separately
|
||||
if (!spellInfo->Effects[i].IsEffect())
|
||||
continue;
|
||||
if (!IsImmunedToSpellEffect(spellInfo, i))
|
||||
{
|
||||
immuneToAllEffects = false;
|
||||
@@ -9792,17 +9782,14 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) const
|
||||
if (immuneToAllEffects) //Return immune only if the target is immune to all spell effects.
|
||||
return true;
|
||||
|
||||
if (spellInfo->Id != 42292 && spellInfo->Id != 59752)
|
||||
auto const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||
for (auto itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
||||
{
|
||||
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
|
||||
{
|
||||
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->spellId);
|
||||
if ((itr->type & spellInfo->GetSchoolMask())
|
||||
&& !(immuneSpellInfo && immuneSpellInfo->IsPositive() && spellInfo->IsPositive())
|
||||
&& !spellInfo->CanPierceImmuneAura(immuneSpellInfo))
|
||||
return true;
|
||||
}
|
||||
SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->second);
|
||||
if ((itr->first & spellInfo->GetSchoolMask())
|
||||
&& !(immuneSpellInfo && immuneSpellInfo->IsPositive() && spellInfo->IsPositive())
|
||||
&& !spellInfo->CanPierceImmuneAura(immuneSpellInfo))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -9811,9 +9798,9 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) const
|
||||
uint32 Unit::GetSchoolImmunityMask() const
|
||||
{
|
||||
uint32 mask = 0;
|
||||
SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||
for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
|
||||
mask |= itr->type;
|
||||
auto const& mechanicList = m_spellImmune[IMMUNITY_SCHOOL];
|
||||
for (auto itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
|
||||
mask |= itr->first;
|
||||
|
||||
return mask;
|
||||
}
|
||||
@@ -9821,9 +9808,9 @@ uint32 Unit::GetSchoolImmunityMask() const
|
||||
uint32 Unit::GetMechanicImmunityMask() const
|
||||
{
|
||||
uint32 mask = 0;
|
||||
SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
|
||||
for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
|
||||
mask |= (1 << itr->type);
|
||||
auto const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
|
||||
for (auto itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
|
||||
mask |= (1 << itr->first);
|
||||
|
||||
return mask;
|
||||
}
|
||||
@@ -9838,26 +9825,25 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons
|
||||
|
||||
// If m_immuneToEffect type contain this effect type, IMMUNE effect.
|
||||
uint32 effect = spellInfo->Effects[index].Effect;
|
||||
SpellImmuneList const& effectList = m_spellImmune[IMMUNITY_EFFECT];
|
||||
for (SpellImmuneList::const_iterator itr = effectList.begin(); itr != effectList.end(); ++itr)
|
||||
if (itr->type == effect)
|
||||
return true;
|
||||
auto const& effectList = m_spellImmune[IMMUNITY_EFFECT];
|
||||
if (effectList.count(effect) > 0)
|
||||
return true;
|
||||
|
||||
if (uint32 mechanic = spellInfo->Effects[index].Mechanic)
|
||||
{
|
||||
SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
|
||||
for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
|
||||
if (itr->type == mechanic)
|
||||
return true;
|
||||
auto const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
|
||||
if (mechanicList.count(mechanic) > 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (uint32 aura = spellInfo->Effects[index].ApplyAuraName)
|
||||
{
|
||||
SpellImmuneList const& list = m_spellImmune[IMMUNITY_STATE];
|
||||
for (SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
|
||||
if (itr->type == aura)
|
||||
if (!spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
|
||||
return true;
|
||||
if (!spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
|
||||
{
|
||||
auto const& list = m_spellImmune[IMMUNITY_STATE];
|
||||
if (list.count(aura) > 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for immune to application of harmful magical effects
|
||||
AuraEffectList const& immuneAuraApply = GetAuraEffectsByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL);
|
||||
@@ -10103,52 +10089,14 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
|
||||
void Unit::ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply)
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
for (SpellImmuneList::iterator itr = m_spellImmune[op].begin(), next; itr != m_spellImmune[op].end(); itr = next)
|
||||
{
|
||||
next = itr; ++next;
|
||||
if (itr->type == type)
|
||||
{
|
||||
m_spellImmune[op].erase(itr);
|
||||
next = m_spellImmune[op].begin();
|
||||
}
|
||||
}
|
||||
SpellImmune Immune;
|
||||
Immune.spellId = spellId;
|
||||
Immune.type = type;
|
||||
m_spellImmune[op].push_back(Immune);
|
||||
}
|
||||
m_spellImmune[op].emplace(type, spellId);
|
||||
else
|
||||
{
|
||||
for (SpellImmuneList::iterator itr = m_spellImmune[op].begin(); itr != m_spellImmune[op].end(); ++itr)
|
||||
auto bounds = m_spellImmune[op].equal_range(type);
|
||||
for (auto itr = bounds.first; itr != bounds.second;)
|
||||
{
|
||||
if (itr->spellId == spellId && itr->type == type)
|
||||
{
|
||||
m_spellImmune[op].erase(itr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::ApplySpellDispelImmunity(const SpellInfo* spellProto, DispelType type, bool apply)
|
||||
{
|
||||
ApplySpellImmune(spellProto->Id, IMMUNITY_DISPEL, type, apply);
|
||||
|
||||
if (apply && spellProto->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
|
||||
{
|
||||
// Create dispel mask by dispel type
|
||||
uint32 dispelMask = SpellInfo::GetDispelMask(type);
|
||||
// Dispel all existing auras vs current dispel type
|
||||
AuraApplicationMap& auras = GetAppliedAuras();
|
||||
for (AuraApplicationMap::iterator itr = auras.begin(); itr != auras.end();)
|
||||
{
|
||||
SpellInfo const* spell = itr->second->GetBase()->GetSpellInfo();
|
||||
if (spell->GetDispelMask() & dispelMask)
|
||||
{
|
||||
// Dispel aura
|
||||
RemoveAura(itr);
|
||||
}
|
||||
if (itr->second == spellId)
|
||||
itr = m_spellImmune[op].erase(itr);
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user