Core/Auras: Allow SPELL_AURA_MECHANIC_IMMUNITY_MASK to apply aoe/chain targeting immunity

This commit is contained in:
Shauren
2024-02-13 00:46:42 +01:00
parent 96191b9ce2
commit ed0b621d15
7 changed files with 52 additions and 25 deletions

View File

@@ -7522,6 +7522,16 @@ uint64 Unit::GetMechanicImmunityMask() const
return mask;
}
EnumFlag<SpellOtherImmunity> Unit::GetSpellOtherImmunityMask() const
{
SpellOtherImmunity mask = { };
SpellImmuneContainer const& damageList = m_spellImmune[IMMUNITY_OTHER];
for (auto itr = damageList.begin(); itr != damageList.end(); ++itr)
mask |= SpellOtherImmunity(itr->first);
return mask;
}
bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster,
bool requireImmunityPurgesEffectAttribute /*= false*/) const
{

View File

@@ -102,6 +102,7 @@ enum MovementGeneratorType : uint8;
enum ProcFlagsHit : uint32;
enum ProcFlagsSpellPhase : uint32;
enum ProcFlagsSpellType : uint32;
enum class SpellOtherImmunity : uint8;
enum ZLiquidStatus : uint32;
namespace Movement
@@ -1611,6 +1612,7 @@ class TC_GAME_API Unit : public WorldObject
uint32 GetSchoolImmunityMask() const;
uint32 GetDamageImmunityMask() const;
uint64 GetMechanicImmunityMask() const;
EnumFlag<SpellOtherImmunity> GetSpellOtherImmunityMask() const;
bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const;
bool IsImmunedToDamage(SpellInfo const* spellInfo, SpellEffectInfo const* spellEffectInfo = nullptr) const;

View File

@@ -2618,6 +2618,7 @@ enum SpellImmunity
IMMUNITY_DISPEL = 4, // enum DispelType
IMMUNITY_MECHANIC = 5, // enum Mechanics
IMMUNITY_ID = 6,
IMMUNITY_OTHER = 7, // enum SpellOtherImmunity
MAX_SPELL_IMMUNITY
};

View File

@@ -9217,24 +9217,20 @@ bool WorldObjectSpellAreaTargetCheck::operator()(WorldObject* target) const
if (!isInsideCylinder)
return false;
if (Creature* creatureTarget = target->ToCreature())
if (Unit* unitTarget = target->ToUnit())
{
if (CreatureImmunities const* immunities = SpellMgr::GetCreatureImmunities(creatureTarget->GetCreatureTemplate()->CreatureImmunitiesId))
switch (_searchReason)
{
switch (_searchReason)
{
case WorldObjectSpellAreaTargetSearchReason::Area:
if (immunities->ImmuneAoE)
return false;
break;
case WorldObjectSpellAreaTargetSearchReason::Chain:
if (immunities->ImmuneChain)
return false;
break;
default:
break;
}
case WorldObjectSpellAreaTargetSearchReason::Area:
if (unitTarget->GetSpellOtherImmunityMask().HasFlag(SpellOtherImmunity::AoETarget))
return false;
break;
case WorldObjectSpellAreaTargetSearchReason::Chain:
if (unitTarget->GetSpellOtherImmunityMask().HasFlag(SpellOtherImmunity::ChainTarget))
return false;
break;
default:
break;
}
}
}

View File

@@ -233,6 +233,7 @@ struct SpellEffectInfo::ImmunityInfo
uint64 MechanicImmuneMask = 0;
uint32 DispelImmuneMask = 0;
uint32 DamageSchoolMask = 0;
uint8 OtherImmuneMask = 0;
Trinity::Containers::FlatSet<AuraType> AuraTypeImmune;
Trinity::Containers::FlatSet<SpellEffectName> SpellEffectImmune;
@@ -2250,6 +2251,10 @@ SpellCastResult SpellInfo::CheckTarget(WorldObject const* caster, WorldObject co
if (HasAttribute(SPELL_ATTR8_ONLY_TARGET_OWN_SUMMONS))
if (!unitTarget->IsSummon() || unitTarget->ToTempSummon()->GetSummonerGUID() != caster->GetGUID())
return SPELL_FAILED_BAD_TARGETS;
if (HasAttribute(SPELL_ATTR3_NOT_ON_AOE_IMMUNE))
if (unitTarget->GetSpellOtherImmunityMask().HasFlag(SpellOtherImmunity::AoETarget))
return SPELL_FAILED_BAD_TARGETS;
}
// corpse specific target checks
else if (Corpse const* corpseTarget = target->ToCorpse())
@@ -2275,11 +2280,6 @@ SpellCastResult SpellInfo::CheckTarget(WorldObject const* caster, WorldObject co
if (HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER_CONTROLLED_NPC) && unitTarget->IsControlledByPlayer())
return SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED;
if (HasAttribute(SPELL_ATTR3_NOT_ON_AOE_IMMUNE))
if (CreatureImmunities const* immunities = SpellMgr::GetCreatureImmunities(unitTarget->ToCreature()->GetCreatureTemplate()->CreatureImmunitiesId))
if (immunities->ImmuneAoE)
return SPELL_FAILED_BAD_TARGETS;
}
else if (HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER))
return SPELL_FAILED_TARGET_IS_PLAYER;
@@ -3316,6 +3316,7 @@ void SpellInfo::_LoadImmunityInfo()
uint64 mechanicImmunityMask = 0;
uint32 dispelImmunityMask = 0;
uint32 damageImmunityMask = 0;
uint8 otherImmunityMask = 0;
int32 miscVal = effect.MiscValue;
@@ -3330,6 +3331,7 @@ void SpellInfo::_LoadImmunityInfo()
schoolImmunityMask |= creatureImmunities->School.to_ulong();
dispelImmunityMask |= creatureImmunities->DispelType.to_ulong();
mechanicImmunityMask |= creatureImmunities->Mechanic.to_ullong();
otherImmunityMask |= creatureImmunities->Other.AsUnderlyingType();
for (SpellEffectName effectType : creatureImmunities->Effect)
immuneInfo.SpellEffectImmune.insert(effectType);
for (AuraType aura : creatureImmunities->Aura)
@@ -3408,6 +3410,7 @@ void SpellInfo::_LoadImmunityInfo()
immuneInfo.MechanicImmuneMask = mechanicImmunityMask;
immuneInfo.DispelImmuneMask = dispelImmunityMask;
immuneInfo.DamageSchoolMask = damageImmunityMask;
immuneInfo.OtherImmuneMask = otherImmunityMask;
immuneInfo.AuraTypeImmune.shrink_to_fit();
immuneInfo.SpellEffectImmune.shrink_to_fit();
@@ -3417,6 +3420,7 @@ void SpellInfo::_LoadImmunityInfo()
|| immuneInfo.MechanicImmuneMask
|| immuneInfo.DispelImmuneMask
|| immuneInfo.DamageSchoolMask
|| immuneInfo.OtherImmuneMask
|| !immuneInfo.AuraTypeImmune.empty()
|| !immuneInfo.SpellEffectImmune.empty())
{
@@ -3597,6 +3601,9 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const& s
for (SpellEffectName effectType : immuneInfo->SpellEffectImmune)
target->ApplySpellImmune(Id, IMMUNITY_EFFECT, effectType, apply);
if (uint8 otherImmuneMask = immuneInfo->OtherImmuneMask)
target->ApplySpellImmune(Id, IMMUNITY_OTHER, otherImmuneMask, apply);
}
bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInfo) const

View File

@@ -4957,8 +4957,10 @@ void SpellMgr::LoadSpellInfoImmunities()
immunities.School = school;
immunities.DispelType = dispelType;
immunities.Mechanic = mechanics;
immunities.ImmuneAoE = fields[6].GetBool();
immunities.ImmuneChain = fields[7].GetBool();
if (fields[6].GetBool())
immunities.Other |= SpellOtherImmunity::AoETarget;
if (fields[7].GetBool())
immunities.Other |= SpellOtherImmunity::ChainTarget;
if (immunities.School.to_ullong() != school)
TC_LOG_ERROR("sql.sql", "Invalid value in `SchoolMask` {} for creature immunities {}, truncated", school, id);

View File

@@ -23,6 +23,7 @@
#include "Define.h"
#include "DBCEnums.h"
#include "Duration.h"
#include "EnumFlag.h"
#include "Errors.h"
#include "FlagsArray.h"
#include "Hash.h"
@@ -594,6 +595,15 @@ struct SpellLearnSpellNode
bool AutoLearned; // This marks the spell as automatically learned from another source that - will only be used for unlearning
};
enum class SpellOtherImmunity : uint8
{
None = 0x0,
AoETarget = 0x1,
ChainTarget = 0x2
};
DEFINE_ENUM_FLAG(SpellOtherImmunity)
struct CreatureImmunities
{
std::bitset<MAX_SPELL_SCHOOL> School;
@@ -601,8 +611,7 @@ struct CreatureImmunities
std::bitset<MAX_MECHANIC> Mechanic;
std::vector<SpellEffectName> Effect;
std::vector<AuraType> Aura;
bool ImmuneAoE = false; // NYI
bool ImmuneChain = false; // NYI
EnumFlag<SpellOtherImmunity> Other = SpellOtherImmunity::None;
};
typedef std::multimap<uint32, SpellLearnSpellNode> SpellLearnSpellMap;