Core/Spells: implement SpellInfo helper to filter for relevant mechanic immunities in spell_start packet (#26183)

* Core/Spells: implement SpellInfo helper to filter for relevant mechanic immunities when sending SMSG_SPELL_START packets.

According to sniff analysis Blizzard does not send all mechanic immunities of creatures but instead only the ones that are responsible for actual interrupts which are MECHANIC_INTERRUPT  and MECHANIC_SILENCE. Additionally we no longer send immunities for instant cast spells as sniffs confirm that they are not sent for spells without a cast time.

(cherry picked from commit 6215cb4e0014fbe9df35a8c6b013e7801bd8ffec)
This commit is contained in:
Ovah
2022-03-08 00:31:02 +01:00
committed by Shauren
parent b4f27875f3
commit 60119ba850
3 changed files with 25 additions and 6 deletions
+2 -2
View File
@@ -4469,8 +4469,8 @@ void Spell::SendSpellStart()
uint32 mechanicImmunityMask = 0;
if (Unit* unitCaster = m_caster->ToUnit())
{
schoolImmunityMask = unitCaster->GetSchoolImmunityMask();
mechanicImmunityMask = unitCaster->GetMechanicImmunityMask();
schoolImmunityMask = m_timer!= 0 ? unitCaster->GetSchoolImmunityMask() : 0;
mechanicImmunityMask = m_timer != 0 ? m_spellInfo->GetMechanicImmunityMask(unitCaster) : 0;
}
if (schoolImmunityMask || mechanicImmunityMask)
+20 -3
View File
@@ -1376,14 +1376,14 @@ bool SpellInfo::HasTargetType(::Targets target) const
return false;
}
bool SpellInfo::CanBeInterrupted(WorldObject const* interruptCaster, Unit const* interruptTarget) const
bool SpellInfo::CanBeInterrupted(WorldObject const* interruptCaster, Unit const* interruptTarget, bool ignoreImmunity /*= false*/) const
{
return HasAttribute(SPELL_ATTR7_CAN_ALWAYS_BE_INTERRUPTED)
|| HasChannelInterruptFlag(SpellAuraInterruptFlags::Damage | SpellAuraInterruptFlags::EnteringCombat)
|| (interruptTarget->IsPlayer() && InterruptFlags.HasFlag(SpellInterruptFlags::DamageCancelsPlayerOnly))
|| InterruptFlags.HasFlag(SpellInterruptFlags::DamageCancels)
|| (interruptCaster->IsUnit() && interruptCaster->ToUnit()->HasAuraTypeWithMiscvalue(SPELL_AURA_ALLOW_INTERRUPT_SPELL, Id))
|| (!(interruptTarget->GetMechanicImmunityMask() & (1 << MECHANIC_INTERRUPT))
|| (interruptCaster && interruptCaster->IsUnit() && interruptCaster->ToUnit()->HasAuraTypeWithMiscvalue(SPELL_AURA_ALLOW_INTERRUPT_SPELL, Id))
|| ((!(interruptTarget->GetMechanicImmunityMask() & (1 << MECHANIC_INTERRUPT)) || ignoreImmunity)
&& !interruptTarget->HasAuraTypeWithAffectMask(SPELL_AURA_PREVENT_INTERRUPT, this)
&& PreventionType & SPELL_PREVENTION_TYPE_SILENCE);
}
@@ -3729,6 +3729,23 @@ uint32 SpellInfo::GetAllowedMechanicMask() const
return _allowedMechanicMask;
}
uint32 SpellInfo::GetMechanicImmunityMask(Unit const* caster) const
{
uint32 casterMechanicImmunityMask = caster->GetMechanicImmunityMask();
uint32 mechanicImmunityMask = 0;
if (CanBeInterrupted(nullptr, caster, true))
{
if (casterMechanicImmunityMask & (1 << MECHANIC_SILENCE))
mechanicImmunityMask |= (1 << MECHANIC_SILENCE);
if (casterMechanicImmunityMask & (1 << MECHANIC_INTERRUPT))
mechanicImmunityMask |= (1 << MECHANIC_INTERRUPT);
}
return mechanicImmunityMask;
}
float SpellInfo::GetMinRange(bool positive /*= false*/) const
{
if (!RangeEntry)
+3 -1
View File
@@ -476,7 +476,7 @@ class TC_GAME_API SpellInfo
bool HasAttribute(SpellAttr14 attribute) const { return !!(AttributesEx14 & attribute); }
bool HasAttribute(SpellCustomAttributes customAttribute) const { return !!(AttributesCu & customAttribute); }
bool CanBeInterrupted(WorldObject const* interruptCaster, Unit const* interruptTarget) const;
bool CanBeInterrupted(WorldObject const* interruptCaster, Unit const* interruptTarget, bool ignoreImmunity = false) const;
bool HasAnyAuraInterruptFlag() const;
bool HasAuraInterruptFlag(SpellAuraInterruptFlags flag) const { return AuraInterruptFlags.HasFlag(flag); }
@@ -605,6 +605,8 @@ class TC_GAME_API SpellInfo
uint32 GetAllowedMechanicMask() const;
uint32 GetMechanicImmunityMask(Unit const* caster) const;
// Player Condition
bool MeetsFutureSpellPlayerCondition(Player const* player) const;