Core/Spells: Fixed spells with SPELL_ATTR6_DO_NOT_CHAIN_TO_CROWD_CONTROLLED_TARGETS ignoring permanently rooted creatures (with static flags)

Signed-off-by: luis <[email protected]>
This commit is contained in:
Shauren
2026-03-07 00:11:08 -03:00
committed by luis
parent 8bb504b6c4
commit 9ee3a615f7
4 changed files with 24 additions and 17 deletions
+20 -14
View File
@@ -769,26 +769,32 @@ bool Unit::HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, flag
bool Unit::HasBreakableByDamageAuraType(AuraType type, uint32 excludeAura) const bool Unit::HasBreakableByDamageAuraType(AuraType type, uint32 excludeAura) const
{ {
AuraEffectList const& auras = GetAuraEffectsByType(type); for (AuraEffect const* aura : GetAuraEffectsByType(type))
for (AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) if ((!excludeAura || excludeAura != aura->GetSpellInfo()->Id) && //Avoid self interrupt of channeled Crowd Control spells like Seduction
if ((!excludeAura || excludeAura != (*itr)->GetSpellInfo()->Id) && //Avoid self interrupt of channeled Crowd Control spells like Seduction aura->GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::AnyDamageMask))
(*itr)->GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::Damage))
return true; return true;
return false; return false;
} }
bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) const bool Unit::HasBreakableByDamageCrowdControlAura(Unit const* excludeCasterChannel) const
{ {
uint32 excludeAura = 0; if (!HasInterruptFlag(SpellAuraInterruptFlags::AnyDamageMask))
if (Spell* currentChanneledSpell = excludeCasterChannel ? excludeCasterChannel->GetCurrentSpell(CURRENT_CHANNELED_SPELL) : nullptr) return false;
excludeAura = currentChanneledSpell->GetSpellInfo()->Id; //Avoid self interrupt of channeled Crowd Control spells like Seduction
return ( HasBreakableByDamageAuraType(SPELL_AURA_MOD_CONFUSE, excludeAura) uint32 excludeAura = 0;
|| HasBreakableByDamageAuraType(SPELL_AURA_MOD_FEAR, excludeAura) if (excludeCasterChannel)
|| HasBreakableByDamageAuraType(SPELL_AURA_MOD_STUN, excludeAura) if (Spell const* currentChanneledSpell = excludeCasterChannel->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|| HasBreakableByDamageAuraType(SPELL_AURA_MOD_ROOT, excludeAura) excludeAura = currentChanneledSpell->GetSpellInfo()->Id; //Avoid self interrupt of channeled Crowd Control spells like Seduction
|| HasBreakableByDamageAuraType(SPELL_AURA_MOD_ROOT_2, excludeAura)
|| HasBreakableByDamageAuraType(SPELL_AURA_TRANSFORM, excludeAura)); // This function is named after spell attribute it is meant for - SPELL_ATTR6_DO_NOT_CHAIN_TO_CROWD_CONTROLLED_TARGETS
// Not checking aura type is not a mistake here
for (AuraApplication const* aurApp : m_interruptableAuras)
if (!aurApp->IsPositive()
&& (!excludeAura || excludeAura != aurApp->GetBase()->GetId())
&& aurApp->GetBase()->GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::AnyDamageMask))
return true;
return false;
} }
/*static*/ void Unit::DealDamageMods(Unit const* attacker, Unit const* victim, uint32& damage, uint32* absorb) /*static*/ void Unit::DealDamageMods(Unit const* attacker, Unit const* victim, uint32& damage, uint32* absorb)
+1 -1
View File
@@ -1084,7 +1084,7 @@ class TC_GAME_API Unit : public WorldObject
bool HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, flag128 familyFlags) const; bool HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, flag128 familyFlags) const;
bool virtual HasSpell(uint32 /*spellID*/) const { return false; } bool virtual HasSpell(uint32 /*spellID*/) const { return false; }
bool HasBreakableByDamageAuraType(AuraType type, uint32 excludeAura = 0) const; bool HasBreakableByDamageAuraType(AuraType type, uint32 excludeAura = 0) const;
bool HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel = nullptr) const; bool HasBreakableByDamageCrowdControlAura(Unit const* excludeCasterChannel = nullptr) const;
bool HasStealthAura() const { return HasAuraType(SPELL_AURA_MOD_STEALTH); } bool HasStealthAura() const { return HasAuraType(SPELL_AURA_MOD_STEALTH); }
bool HasInvisibilityAura() const { return HasAuraType(SPELL_AURA_MOD_INVISIBILITY); } bool HasInvisibilityAura() const { return HasAuraType(SPELL_AURA_MOD_INVISIBILITY); }
+2 -1
View File
@@ -110,7 +110,8 @@ enum class SpellAuraInterruptFlags : uint32
Summon = 0x40000000, Summon = 0x40000000,
LeavingCombat = 0x80000000, LeavingCombat = 0x80000000,
NOT_VICTIM = (HostileActionReceived | Damage | NonPeriodicDamage) NOT_VICTIM = HostileActionReceived | Damage | NonPeriodicDamage,
AnyDamageMask = Damage | NonPeriodicDamage | DamageCancelsScript
}; };
DEFINE_ENUM_FLAG(SpellAuraInterruptFlags); DEFINE_ENUM_FLAG(SpellAuraInterruptFlags);
+1 -1
View File
@@ -2418,7 +2418,7 @@ SpellCastResult SpellInfo::CheckTarget(WorldObject const* caster, WorldObject co
return SPELL_FAILED_TARGETS_DEAD; return SPELL_FAILED_TARGETS_DEAD;
// check this flag only for implicit targets (chain and area), allow to explicitly target units for spells like Shield of Righteousness // check this flag only for implicit targets (chain and area), allow to explicitly target units for spells like Shield of Righteousness
if (implicit && HasAttribute(SPELL_ATTR6_DO_NOT_CHAIN_TO_CROWD_CONTROLLED_TARGETS) && !unitTarget->CanFreeMove()) if (implicit && HasAttribute(SPELL_ATTR6_DO_NOT_CHAIN_TO_CROWD_CONTROLLED_TARGETS) && unitTarget->HasBreakableByDamageCrowdControlAura())
return SPELL_FAILED_BAD_TARGETS; return SPELL_FAILED_BAD_TARGETS;
// checked in Unit::IsValidAttack/AssistTarget, shouldn't be checked for ENTRY targets // checked in Unit::IsValidAttack/AssistTarget, shouldn't be checked for ENTRY targets