diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 809a873ad2..64b99c128d 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2026,7 +2026,7 @@ void Creature::LoadTemplateImmunities() } } -bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster) const +bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster, Optional effectMask /*= nullptr*/) const { if (!spellInfo) return false; @@ -2036,6 +2036,10 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster) const { if (!spellInfo->Effects[i].IsEffect()) continue; + + if (effectMask && !(effectMask.get() & (1 << i))) + continue; + if (!IsImmunedToSpellEffect(spellInfo, i, caster)) { immunedToAllEffects = false; diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index e3ebe52a4f..4369939d34 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -111,7 +111,7 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma bool IsClassTrainerOf(Player const* player) const; bool CanCreatureAttack(Unit const* victim, bool force = true) const; void LoadTemplateImmunities(); - bool IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster) const override; + bool IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster, Optional effectMask = nullptr) const override; bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Unit* caster) const override; bool isElite() const; bool isWorldBoss() const; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 294ca80ff8..184071387f 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -2795,7 +2795,7 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo // Parry // For spells // Resist -SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool canReflect /*= false*/) +SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool canReflect /*= false*/, Optional effectMask /*= nullptr*/) { // All positive spells can`t miss /// @todo client not show miss log for this spells - so need find info for this in dbc and use it! @@ -2826,7 +2826,7 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, boo return SPELL_MISS_NONE; // Check for immune - if (victim->IsImmunedToSpell(spellInfo, this)) + if (victim->IsImmunedToSpell(spellInfo, this, effectMask)) return SPELL_MISS_IMMUNE; // Damage immunity is only checked if the spell has damage effects, this immunity must not prevent aura apply @@ -7831,7 +7831,7 @@ bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo) const return false; } -bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster) const +bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster, Optional effectMask /*= nullptr*/) const { if (!spellInfo) return false; @@ -7867,6 +7867,9 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster) const if (!spellInfo->Effects[i].IsEffect()) continue; + if (effectMask && !(effectMask.get() & (1 << i))) + continue; + if (!IsImmunedToSpellEffect(spellInfo, i, caster)) { immuneToAllEffects = false; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index b912ec91e4..0c9f1e9d18 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1207,7 +1207,7 @@ class TC_GAME_API Unit : public WorldObject float MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, uint32 spellId) const; SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo); SpellMissInfo MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo); - SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool canReflect = false); + SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool canReflect = false, Optional effectMask = nullptr); float GetUnitDodgeChance(Unit const* attacker) const; float GetUnitParryChance(Unit const* attacker) const; @@ -1758,7 +1758,7 @@ class TC_GAME_API Unit : public WorldObject uint32 GetRemainingPeriodicAmount(ObjectGuid caster, uint32 spellId, AuraType auraType, uint8 effectIndex = 0) const; void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply); - virtual bool IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster) const; // redefined in Creature + virtual bool IsImmunedToSpell(SpellInfo const* spellInfo, Unit* caster, Optional effectMask = nullptr) const; // redefined in Creature uint32 GetSchoolImmunityMask() const; uint32 GetMechanicImmunityMask() const; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 1d5c2e2a5b..28b9e7a675 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2236,7 +2236,7 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= if (Unit* owner = m_originalCaster->GetOwner()) caster = owner; - targetInfo.missCondition = caster->SpellHitResult(target, m_spellInfo, m_canReflect && !(m_spellInfo->IsPositive() && m_caster->IsFriendlyTo(target))); + targetInfo.missCondition = caster->SpellHitResult(target, m_spellInfo, m_canReflect && !(m_spellInfo->IsPositive() && m_caster->IsFriendlyTo(target)), effectMask); if (m_skipCheck && targetInfo.missCondition != SPELL_MISS_IMMUNE) targetInfo.missCondition = SPELL_MISS_NONE; } @@ -2742,7 +2742,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA return SPELL_MISS_EVADE; // For delayed spells immunity may be applied between missile launch and hit - check immunity for that case - if (m_spellInfo->Speed && unit->IsImmunedToSpell(m_spellInfo, m_caster)) + if (m_spellInfo->Speed && unit->IsImmunedToSpell(m_spellInfo, m_caster, effectMask)) return SPELL_MISS_IMMUNE; // disable effects to which unit is immune