From fed82c10025c450090d0b0f4bcda413cb98261b7 Mon Sep 17 00:00:00 2001 From: Shauren Date: Wed, 24 Mar 2021 14:52:48 +0100 Subject: [PATCH] Core/Auras: Defined and implemented many new interrupt flags --- src/server/game/AI/CoreAI/UnitAI.cpp | 3 +- .../Battlegrounds/Zones/BattlegroundAB.cpp | 2 +- .../Battlegrounds/Zones/BattlegroundBFG.cpp | 2 +- .../Battlegrounds/Zones/BattlegroundEY.cpp | 4 +- .../Battlegrounds/Zones/BattlegroundTP.cpp | 4 +- .../Battlegrounds/Zones/BattlegroundWS.cpp | 4 +- src/server/game/DataStores/DBCEnums.h | 1 + src/server/game/Entities/Player/Player.cpp | 21 ++-- src/server/game/Entities/Unit/Unit.cpp | 118 ++++++++++++------ src/server/game/Entities/Unit/Unit.h | 23 ++-- src/server/game/Handlers/CharacterHandler.cpp | 1 + src/server/game/Handlers/ChatHandler.cpp | 3 + src/server/game/Handlers/LootHandler.cpp | 2 + src/server/game/Handlers/MovementHandler.cpp | 8 +- src/server/game/Handlers/NPCHandler.cpp | 5 +- src/server/game/Handlers/SpellHandler.cpp | 2 + .../game/Spells/Auras/SpellAuraEffects.cpp | 46 +++---- src/server/game/Spells/Spell.cpp | 21 ++-- src/server/game/Spells/SpellDefines.h | 98 ++++++++++----- src/server/game/Spells/SpellEffects.cpp | 2 +- src/server/game/Spells/SpellInfo.cpp | 26 +++- src/server/game/Spells/SpellInfo.h | 14 ++- src/server/game/Spells/SpellMgr.cpp | 23 ++-- 23 files changed, 264 insertions(+), 169 deletions(-) diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp index a60c39f95de..218ec76cc25 100644 --- a/src/server/game/AI/CoreAI/UnitAI.cpp +++ b/src/server/game/AI/CoreAI/UnitAI.cpp @@ -154,8 +154,7 @@ void UnitAI::DoCast(uint32 spellId) float range = spellInfo->GetMaxRange(false); DefaultTargetSelector targetSelector(me, range, playerOnly, true, -(int32)spellId); - if (!(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM) - && targetSelector(me->GetVictim())) + if (!spellInfo->HasAuraInterruptFlag(SpellAuraInterruptFlags::NOT_VICTIM) && targetSelector(me->GetVictim())) target = me->GetVictim(); else target = SelectTarget(SELECT_TARGET_RANDOM, 0, targetSelector); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp index 3898ededf03..0fcd573cd6e 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp @@ -435,7 +435,7 @@ void BattlegroundAB::EventPlayerClickedOnFlag(Player* source, GameObject* /*targ if (!(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2)) return; - source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + source->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive); uint32 sound = 0; // If node is neutral, change to contested if (m_Nodes[node] == BG_AB_NODE_TYPE_NEUTRAL) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp index 25f74ee72c8..1c998e52a08 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.cpp @@ -413,7 +413,7 @@ void BattlegroundBFG::EventPlayerClickedOnFlag(Player* source, GameObject* /*tar if (!(m_Nodes[node] == 0 || teamIndex == m_Nodes[node] % 2)) return; - source->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + source->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive); uint32 sound = 0; // If node is neutral, change to contested if (m_Nodes[node] == BG_BFG_NODE_TYPE_NEUTRAL) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp index 0bfdb0a4b23..baefe146838 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp @@ -663,7 +663,7 @@ void BattlegroundEY::EventPlayerClickedOnFlag(Player* player, GameObject* target SetFlagPicker(player->GetGUID()); //get flag aura on player player->CastSpell(player, BG_EY_NETHERSTORM_FLAG_SPELL, true); - player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive); if (player->GetTeam() == ALLIANCE) SendBroadcastText(BG_EY_TEXT_TAKEN_FLAG, CHAT_MSG_BG_SYSTEM_ALLIANCE, player); @@ -789,7 +789,7 @@ void BattlegroundEY::EventPlayerCapturedFlag(Player* player, uint32 BgObjectType m_FlagState = BG_EY_FLAG_STATE_WAIT_RESPAWN; player->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); - player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive); if (player->GetTeam() == ALLIANCE) { diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp index 1b7ada36300..f77ef315a51 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundTP.cpp @@ -702,7 +702,7 @@ void BattlegroundTP::EventPlayerClickedOnFlag(Player* player, GameObject* target } } - player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive); } void BattlegroundTP::EventPlayerCapturedFlag(Player* player) @@ -712,7 +712,7 @@ void BattlegroundTP::EventPlayerCapturedFlag(Player* player) uint32 winner = 0; - player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive); if (player->GetTeam() == ALLIANCE) { if (!IsHordeFlagPickedup()) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp index 8a6bf762901..b2e63e7495a 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp @@ -293,7 +293,7 @@ void BattlegroundWS::EventPlayerCapturedFlag(Player* player) uint32 winner = 0; - player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive); if (player->GetTeam() == ALLIANCE) { if (!IsHordeFlagPickedup()) @@ -569,7 +569,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* target //target_obj->Delete(); } - player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive); } void BattlegroundWS::RemovePlayer(Player* player, ObjectGuid guid, uint32 /*team*/) diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 1afe96f149f..56499921243 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -19,6 +19,7 @@ #define DBCENUMS_H #include "Define.h" +#include "EnumFlag.h" #include enum LevelLimit diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 55666c39156..1879747a7df 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1139,7 +1139,7 @@ void Player::Update(uint32 p_time) if (u->IsPvP() && (!duel || duel->opponent != u)) { UpdatePvP(true); - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive); }*/ } } @@ -1609,7 +1609,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati InterruptNonMeleeSpells(true); //remove auras before removing from map... - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Moving | SpellAuraInterruptFlags::Turning); if (!GetSession()->PlayerLogout()) { @@ -1867,12 +1867,12 @@ void Player::RegenerateAll(uint32 diff) for (auto itr = auraList.begin(); itr != auraList.end(); ++itr) { // Food emote comes above drinking emote if we have to decide (mage regen food for example) - if ((*itr)->GetBase()->HasEffectType(SPELL_AURA_MOD_REGEN) && (*itr)->GetSpellInfo()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) + if ((*itr)->GetBase()->HasEffectType(SPELL_AURA_MOD_REGEN) && (*itr)->GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::Standing)) { SendPlaySpellVisualKit(SPELL_VISUAL_KIT_FOOD, 0, 0); break; } - else if ((*itr)->GetBase()->HasEffectType(SPELL_AURA_MOD_POWER_REGEN) && (*itr)->GetSpellInfo()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) + else if ((*itr)->GetBase()->HasEffectType(SPELL_AURA_MOD_POWER_REGEN) && (*itr)->GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::Standing)) { SendPlaySpellVisualKit(SPELL_VISUAL_KIT_DRINK, 0, 0); break; @@ -2069,7 +2069,7 @@ void Player::SetInWater(bool apply) m_isInWater = apply; // remove auras that need water/land - RemoveAurasWithInterruptFlags(apply ? AURA_INTERRUPT_FLAG_NOT_ABOVEWATER : AURA_INTERRUPT_FLAG_NOT_UNDERWATER); + RemoveAurasWithInterruptFlags(apply ? SpellAuraInterruptFlags::UnderWater : SpellAuraInterruptFlags::AboveWater); } bool Player::IsInAreaTriggerRadius(AreaTriggerEntry const* trigger) const @@ -4082,6 +4082,8 @@ void Player::BuildPlayerRepop() CastSpell(this, 20584, true); CastSpell(this, 8326, true); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Release); + // there must be SMSG.FORCE_RUN_SPEED_CHANGE, SMSG.FORCE_SWIM_SPEED_CHANGE, SMSG.MOVE_WATER_WALK // there must be SMSG.STOP_MIRROR_TIMER @@ -5874,12 +5876,10 @@ bool Player::UpdatePosition(float x, float y, float z, float orientation, bool t if (!Unit::UpdatePosition(x, y, z, orientation, teleport)) return false; - //if (movementInfo.flags & MOVEMENTFLAG_MOVING) - // mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOVE); + // mover->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Moving); //if (movementInfo.flags & MOVEMENTFLAG_TURNING) - // mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING); - //AURA_INTERRUPT_FLAG_JUMP not sure + // mover->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Turning); // Update player zone if needed if (m_needsZoneUpdate) @@ -21814,7 +21814,7 @@ bool Player::ActivateTaxiPathTo(std::vector const& nodes, Creature* npc UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN, 1); // prevent stealth flight - //RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); + //RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Interacting); if (sWorld->getBoolConfig(CONFIG_INSTANT_TAXI)) { @@ -24377,6 +24377,7 @@ void Player::SummonIfPossible(bool agree) m_summon_expire = 0; UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS, 1); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Summon); TeleportTo(m_summon_location); } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 8efe6fd72cb..a581def5282 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -327,7 +327,8 @@ Unit::Unit(bool isWorldObject) : IsAIEnabled(false), NeedChangeAI(false), LastCharmerGUID(), m_ControlledByPlayer(false), movespline(new Movement::MoveSpline()), i_AI(nullptr), i_disabledAI(nullptr), m_AutoRepeatFirstCast(false), m_procDeep(0), - m_removedAurasCount(0), i_motionMaster(new MotionMaster(this)), m_vehicle(nullptr), + m_removedAurasCount(0), m_interruptMask(SpellAuraInterruptFlags::None), m_interruptMask2(SpellAuraInterruptFlags2::None), + i_motionMaster(new MotionMaster(this)), m_vehicle(nullptr), m_vehicleKit(nullptr), m_unitTypeMask(UNIT_MASK_NONE), m_Diminishing(), m_isEngaged(false), m_combatManager(this), m_threatManager(this), _lastDamagedTime(0), m_spellHistory(new SpellHistory(this)), _isIgnoringCombat(false) @@ -363,7 +364,6 @@ Unit::Unit(bool isWorldObject) : m_auraUpdateIterator = m_ownedAuras.end(); - m_interruptMask = 0; m_transform = 0; m_canModifyStats = false; @@ -612,10 +612,10 @@ void Unit::InterruptMovementBasedAuras() { // TODO: Check if orientation transport offset changed instead of only global orientation if (_positionUpdateInfo.Turned) - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Turning); if (_positionUpdateInfo.Relocated && !GetVehicle()) - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOVE); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Moving); } void Unit::DisableSpline() @@ -699,13 +699,22 @@ void Unit::RemoveVisibleAura(uint8 slot) void Unit::UpdateInterruptMask() { - m_interruptMask = 0; - for (AuraApplicationList::const_iterator i = m_interruptableAuras.begin(); i != m_interruptableAuras.end(); ++i) - m_interruptMask |= (*i)->GetBase()->GetSpellInfo()->AuraInterruptFlags; + m_interruptMask = SpellAuraInterruptFlags::None; + m_interruptMask2 = SpellAuraInterruptFlags2::None; + for (AuraApplication const* aurApp : m_interruptableAuras) + { + m_interruptMask |= aurApp->GetBase()->GetSpellInfo()->AuraInterruptFlags; + m_interruptMask2 |= aurApp->GetBase()->GetSpellInfo()->AuraInterruptFlags2; + } if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) + { if (spell->getState() == SPELL_STATE_CASTING) + { m_interruptMask |= spell->m_spellInfo->ChannelInterruptFlags; + m_interruptMask2 |= spell->m_spellInfo->ChannelInterruptFlags2; + } + } } bool Unit::HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint32 familyFlags) const @@ -725,7 +734,7 @@ bool Unit::HasBreakableByDamageAuraType(AuraType type, uint32 excludeAura) const AuraEffectList const& auras = GetAuraEffectsByType(type); for (AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) if ((!excludeAura || excludeAura != (*itr)->GetSpellInfo()->Id) && //Avoid self interrupt of channeled Crowd Control spells like Seduction - ((*itr)->GetSpellInfo()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_TAKE_DAMAGE)) + (*itr)->GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::Damage)) return true; return false; } @@ -812,14 +821,14 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam if (damagetype != NODAMAGE) { - // interrupting auras with AURA_INTERRUPT_FLAG_DAMAGE before checking !damage (absorbed damage breaks that type of auras) + // interrupting auras with SpellAuraInterruptFlags::Damage before checking !damage (absorbed damage breaks that type of auras) if (spellProto) { if (!spellProto->HasAttribute(SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS)) - victim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TAKE_DAMAGE, spellProto->Id); + victim->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Damage, spellProto->Id); } else - victim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TAKE_DAMAGE, 0); + victim->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Damage, 0); // interrupt spells with SPELL_INTERRUPT_FLAG_ABORT_ON_DMG on absorbed damage (no dots) if (!damage && damagetype != DOT && cleanDamage && cleanDamage->absorbed_damage) @@ -965,7 +974,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam if (damagetype == DIRECT_DAMAGE || damagetype == SPELL_DIRECT_DAMAGE) { - victim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE, spellProto ? spellProto->Id : 0); + victim->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::NonPeriodicDamage, spellProto ? spellProto->Id : 0); victim->UpdateLastDamagedTime(spellProto); } @@ -1017,8 +1026,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam if (Spell* spell = victim->m_currentSpells[CURRENT_CHANNELED_SPELL]) if (spell->getState() == SPELL_STATE_CASTING) { - uint32 channelInterruptFlags = spell->m_spellInfo->ChannelInterruptFlags; - if (((channelInterruptFlags & CHANNEL_FLAG_DELAY) != 0) && (damagetype != DOT)) + if (spell->getState() == SPELL_STATE_CASTING && spell->m_spellInfo->HasChannelInterruptFlag(SpellAuraInterruptFlags::DamageChannelDuration) && damagetype != DOT) spell->DelayedChannel(); } } @@ -1987,7 +1995,7 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr return; AtTargetAttacked(victim, true); - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MELEE_ATTACK); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Attacking); if (attType != BASE_ATTACK && attType != OFF_ATTACK) return; // ignore ranged case @@ -2087,7 +2095,7 @@ void Unit::FakeAttackerStateUpdate(Unit* victim, WeaponAttackType attType /*= BA return; AtTargetAttacked(victim, true); - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MELEE_ATTACK); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Attacking); if (attType != BASE_ATTACK && attType != OFF_ATTACK) return; // ignore ranged case @@ -3165,9 +3173,9 @@ void Unit::ProcessTerrainStatusUpdate(ZLiquidStatus status, Optional // remove appropriate auras if we are swimming/not swimming respectively if (status & MAP_LIQUID_STATUS_SWIMMING) - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_ABOVEWATER); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::AboveWater); else - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_UNDERWATER); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::UnderWater); // liquid aura handling LiquidTypeEntry const* curLiquid = nullptr; @@ -3325,10 +3333,10 @@ AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint8 effMask) AuraApplication * aurApp = new AuraApplication(this, caster, aura, effMask); m_appliedAuras.insert(AuraApplicationMap::value_type(aurId, aurApp)); - if (aurSpellInfo->AuraInterruptFlags) + if (aurSpellInfo->HasAnyAuraInterruptFlag()) { m_interruptableAuras.push_back(aurApp); - AddInterruptMask(aurSpellInfo->AuraInterruptFlags); + AddInterruptMask(aurSpellInfo->AuraInterruptFlags, aurSpellInfo->AuraInterruptFlags2); } if (AuraStateType aState = aura->GetSpellInfo()->GetAuraState()) @@ -3369,7 +3377,7 @@ void Unit::_ApplyAura(AuraApplication * aurApp, uint8 effMask) return; // Sitdown on apply aura req seated - if (aura->GetSpellInfo()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED && !IsSitState()) + if (aura->GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::Standing) && !IsSitState()) SetStandState(UNIT_STAND_STATE_SIT); Unit* caster = aura->GetCaster(); @@ -3413,7 +3421,7 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveFlags removeM // Remove all pointers from lists here to prevent possible pointer invalidation on spellcast/auraapply/auraremove m_appliedAuras.erase(i); - if (aura->GetSpellInfo()->AuraInterruptFlags) + if (aura->GetSpellInfo()->HasAnyAuraInterruptFlag()) { m_interruptableAuras.remove(aurApp); UpdateInterruptMask(); @@ -3991,9 +3999,22 @@ void Unit::RemoveNotOwnLimitedTargetAuras(bool onPhaseChange /*= false*/) } } -void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except, Spell* interruptingSpell /* = nullptr */) +template +bool IsInterruptFlagIgnoredForSpell(InterruptFlag /*flag*/, Unit const* /*unit*/, SpellInfo const* /*spellInfo*/) { - if (!(m_interruptMask & flag)) + return false; +} + +template<> +bool IsInterruptFlagIgnoredForSpell(SpellAuraInterruptFlags flag, Unit const* unit, SpellInfo const* spellInfo) +{ + return flag == SpellAuraInterruptFlags::Moving && unit->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, spellInfo); +} + +template +void Unit::RemoveAurasWithInterruptFlags(InterruptFlags flag, uint32 except, Spell* interruptingSpell /* = nullptr */) +{ + if (!HasInterruptFlag(flag)) return; // interrupt auras @@ -4001,8 +4022,9 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except, Spell* inte { Aura* aura = (*iter)->GetBase(); ++iter; - if ((aura->GetSpellInfo()->AuraInterruptFlags & flag) && (!except || aura->GetId() != except) - && !(flag & AURA_INTERRUPT_FLAG_MOVE && HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, aura->GetSpellInfo()))) + if (aura->GetSpellInfo()->HasAuraInterruptFlag(flag) + && (!except || aura->GetId() != except) + && !IsInterruptFlagIgnoredForSpell(flag, this, aura->GetSpellInfo())) { uint32 removedAuras = m_removedAurasCount; RemoveAura(aura); @@ -4014,9 +4036,9 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except, Spell* inte // interrupt channeled spell if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) if (spell->getState() == SPELL_STATE_CASTING - && (spell->m_spellInfo->ChannelInterruptFlags & flag) - && spell->m_spellInfo->Id != except - && !(flag & AURA_INTERRUPT_FLAG_MOVE && HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, spell->GetSpellInfo()))) + && spell->GetSpellInfo()->HasChannelInterruptFlag(flag) + && spell->GetSpellInfo()->Id != except + && !IsInterruptFlagIgnoredForSpell(flag, this, spell->GetSpellInfo())) InterruptNonMeleeSpells(false, 0, true, interruptingSpell); UpdateInterruptMask(); @@ -4490,13 +4512,15 @@ bool Unit::HasAuraTypeWithValue(AuraType auraType, int32 value) const return false; } -bool Unit::HasNegativeAuraWithInterruptFlag(uint32 flag, ObjectGuid guid) const +template +bool Unit::HasNegativeAuraWithInterruptFlag(InterruptFlags flag, ObjectGuid guid) const { - if (!(m_interruptMask & flag)) + if (!HasInterruptFlag(flag)) return false; + for (AuraApplicationList::const_iterator iter = m_interruptableAuras.begin(); iter != m_interruptableAuras.end(); ++iter) { - if (!(*iter)->IsPositive() && (*iter)->GetBase()->GetSpellInfo()->AuraInterruptFlags & flag && (!guid || (*iter)->GetBase()->GetCasterGUID() == guid)) + if (!(*iter)->IsPositive() && (*iter)->GetBase()->GetSpellInfo()->HasAuraInterruptFlag(flag) && (!guid || (*iter)->GetBase()->GetCasterGUID() == guid)) return true; } return false; @@ -5298,6 +5322,13 @@ void Unit::UpdateDisplayPower() SetPowerType(displayPower); } +void Unit::SetSheath(SheathState sheathed) +{ + SetByteValue(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_SHEATH_STATE, sheathed); + if (sheathed == SHEATH_STATE_UNARMED) + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Sheathing); +} + FactionTemplateEntry const* Unit::GetFactionTemplateEntry() const { FactionTemplateEntry const* entry = sFactionTemplateStore.LookupEntry(GetFaction()); @@ -8031,7 +8062,7 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry) player->SendMovementSetCollisionHeight(player->GetCollisionHeight(), UPDATE_COLLISION_HEIGHT_MOUNT); } - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNT); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Mount); } void Unit::Dismount() @@ -8053,7 +8084,7 @@ void Unit::Dismount() if (GetTypeId() == TYPEID_PLAYER && GetVehicleKit()) RemoveVehicleKit(); - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_MOUNTED); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Dismount); // only resummon old pet if the player is already added to a map // this prevents adding a pet to a not created map which would otherwise cause a crash @@ -9019,9 +9050,14 @@ void Unit::setDeathState(DeathState s) //====================================================================== +void Unit::AtEnterCombat() +{ + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::EnteringCombat); +} + void Unit::AtExitCombat() { - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LEAVE_COMBAT); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::LeavingCombat); } void Unit::AtTargetAttacked(Unit* target, bool canInitialAggro) @@ -9043,7 +9079,7 @@ void Unit::AtTargetAttacked(Unit* target, bool canInitialAggro) { myPlayerOwner->UpdatePvP(true); myPlayerOwner->SetContestedPvP(targetPlayerOwner); - myPlayerOwner->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); + myPlayerOwner->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive); } } @@ -9930,6 +9966,13 @@ void Unit::Regenerate(Powers powerType, uint32 diff) UpdateUInt32Value(UNIT_FIELD_POWER1 + powerIndex, curValue); } +void Unit::AddToWorld() +{ + WorldObject::AddToWorld(); + + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::EnterWorld); +} + void Unit::RemoveFromWorld() { // cleanup @@ -9947,6 +9990,7 @@ void Unit::RemoveFromWorld() RemoveCharmAuras(); RemoveBindSightAuras(); RemoveNotOwnLimitedTargetAuras(); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::LeaveWorld); RemoveAllGameObjects(); RemoveAllDynObjects(); @@ -10754,7 +10798,7 @@ void Unit::SetStandState(uint8 state) SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, state); if (IsStandState()) - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_SEATED); + RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Standing); if (IsPlayer()) { diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 49d4ae82b3d..64f5bb1b72b 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -768,6 +768,7 @@ class TC_GAME_API Unit : public WorldObject UnitAI* GetAI() { return i_AI; } void SetAI(UnitAI* newAI) { i_AI = newAI; } + void AddToWorld() override; void RemoveFromWorld() override; void CleanupBeforeRemoveFromMap(bool finalCleanup); @@ -911,7 +912,7 @@ class TC_GAME_API Unit : public WorldObject void ApplyCastTimePercentMod(float val, bool apply); SheathState GetSheath() const { return SheathState(GetByteValue(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_SHEATH_STATE)); } - virtual void SetSheath(SheathState sheathed) { SetByteValue(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_SHEATH_STATE, sheathed); } + virtual void SetSheath(SheathState sheathed); // faction template id uint32 GetFaction() const { return GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); } @@ -1293,7 +1294,8 @@ class TC_GAME_API Unit : public WorldObject void RemoveAurasDueToItemSpell(uint32 spellId, ObjectGuid castItemGuid); void RemoveAurasByType(AuraType auraType, ObjectGuid casterGUID = ObjectGuid::Empty, Aura* except = nullptr, bool negative = true, bool positive = true); void RemoveNotOwnLimitedTargetAuras(bool onPhaseChange = false); - void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except = 0, Spell* interruptingSpell = nullptr); + template + void RemoveAurasWithInterruptFlags(InterruptFlags flag, uint32 except = 0, Spell* interruptingSpell = nullptr); void RemoveAurasWithAttribute(uint32 flags); void RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, ObjectGuid casterGUID); void RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveFlags removemode = AuraRemoveFlags::ByDefault, uint32 except = 0); @@ -1339,7 +1341,8 @@ class TC_GAME_API Unit : public WorldObject bool HasAuraTypeWithMiscvalue(AuraType auraType, int32 miscValue) const; bool HasAuraTypeWithAffectMask(AuraType auraType, SpellInfo const* affectedSpell) const; bool HasAuraTypeWithValue(AuraType auraType, int32 value) const; - bool HasNegativeAuraWithInterruptFlag(uint32 flag, ObjectGuid guid = ObjectGuid::Empty) const; + template + bool HasNegativeAuraWithInterruptFlag(InterruptFlags flag, ObjectGuid guid = ObjectGuid::Empty) const; bool HasAuraWithMechanic(uint32 mechanicMask) const; bool HasStrongerAuraWithDR(SpellInfo const* auraSpellInfo, Unit* caster, bool triggered) const; @@ -1484,8 +1487,13 @@ class TC_GAME_API Unit : public WorldObject void SetVisibleAura(uint8 slot, AuraApplication * aur); void RemoveVisibleAura(uint8 slot); - uint32 GetInterruptMask() const { return m_interruptMask; } - void AddInterruptMask(uint32 mask) { m_interruptMask |= mask; } + bool HasInterruptFlag(SpellAuraInterruptFlags flags) const { return m_interruptMask.HasFlag(flags); } + bool HasInterruptFlag(SpellAuraInterruptFlags2 flags) const { return m_interruptMask2.HasFlag(flags); } + void AddInterruptMask(SpellAuraInterruptFlags flags, SpellAuraInterruptFlags2 flags2) + { + m_interruptMask |= flags; + m_interruptMask2 |= flags2; + } void UpdateInterruptMask(); virtual float GetNativeObjectScale() const { return 1.0f; } @@ -1774,7 +1782,8 @@ class TC_GAME_API Unit : public WorldObject AurasBySpellIdMap m_ltAuras; // cast limited target auras AuraApplicationList m_interruptableAuras; // auras which have interrupt mask applied on unit AuraStateAurasMap m_auraStateAuras; // Used for improve performance of aura state checks on aura apply/remove - uint32 m_interruptMask; + EnumFlag m_interruptMask; + EnumFlag m_interruptMask2; float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; float m_weaponDamage[MAX_ATTACK][2]; @@ -1809,7 +1818,7 @@ class TC_GAME_API Unit : public WorldObject virtual void ProcessTerrainStatusUpdate(ZLiquidStatus status, Optional const& liquidData); // notifiers - virtual void AtEnterCombat() { } + virtual void AtEnterCombat(); virtual void AtExitCombat(); virtual void AtEngage(Unit* /*target*/) {} diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 75322336d03..7d365d178bf 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -958,6 +958,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder const& holder) } pCurrChar->UpdatePositionData(); + pCurrChar->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Login); pCurrChar->UpdateMountCapabilities(); pCurrChar->SendInitialPacketsAfterAddToMap(); diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp index 54558845dcc..c0bff569507 100644 --- a/src/server/game/Handlers/ChatHandler.cpp +++ b/src/server/game/Handlers/ChatHandler.cpp @@ -817,6 +817,9 @@ void WorldSession::HandleTextEmoteOpcode(WorldPacket& recvData) //Send scripted event call if (unit && unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->AI()) ((Creature*)unit)->AI()->ReceiveEmote(GetPlayer(), text_emote); + + if (emote_anim != EMOTE_ONESHOT_NONE) + _player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Anim); } void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recvData) diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp index c91cff088fd..b4bd7f5dfad 100644 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -287,6 +287,8 @@ void WorldSession::HandleLootOpcode(WorldPacket& recvData) // interrupt cast if (GetPlayer()->IsNonMeleeSpellCast(false)) GetPlayer()->InterruptNonMeleeSpells(false); + + GetPlayer()->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Looting); } void WorldSession::HandleLootReleaseOpcode(WorldPacket& recvData) diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index f899bcbdcfb..36df8dc465f 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -368,8 +368,8 @@ void WorldSession::HandleMovementOpcode(uint16 opcode, MovementInfo& movementInf plrMover->HandleFall(movementInfo); // interrupt parachutes upon falling or landing in water - if (opcode == MSG_MOVE_FALL_LAND || opcode == MSG_MOVE_START_SWIM) - mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LANDING); // Parachutes + if (opcode == MSG_MOVE_FALL_LAND || opcode == MSG_MOVE_START_SWIM || opcode == CMSG_MOVE_SET_CAN_FLY) + mover->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::LandingOrFlight); // Parachutes if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) { @@ -402,7 +402,7 @@ void WorldSession::HandleMovementOpcode(uint16 opcode, MovementInfo& movementInf if (movementInfo.pos.GetOrientation() != mover->GetOrientation()) { mover->SetOrientation(movementInfo.pos.GetOrientation()); - mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING); + mover->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Turning); } } } @@ -444,7 +444,7 @@ void WorldSession::HandleMovementOpcode(uint16 opcode, MovementInfo& movementInf if (opcode == MSG_MOVE_JUMP) { - plrMover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_JUMP, 605); // Mind Control + plrMover->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags2::Jump); plrMover->ProcSkillsAndAuras(nullptr, PROC_FLAG_JUMP, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr); } } diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index faf5bebb386..03b16ec0fdd 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -194,10 +194,7 @@ void WorldSession::HandleGossipHelloOpcode(WorldPacket& recvData) if (FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(unit->GetFaction())) _player->GetReputationMgr().SetVisible(factionTemplateEntry); - GetPlayer()->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); - // remove fake death - //if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) - // GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Interacting); // Stop the npc if moving if (uint32 pause = unit->GetMovementTemplate().GetInteractionPauseTimer()) diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index cef639dbad1..c579d2c8f3a 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -185,6 +185,8 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) } } + pUser->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::ItemUse); + SpellCastTargets targets; targets.Read(recvPacket, pUser); HandleClientCastFlags(recvPacket, castFlags, targets); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index eb8b3637854..2cbf59f1420 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1548,7 +1548,7 @@ void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode if (apply && (mode & AURA_EFFECT_HANDLE_REAL)) { // drop flag at invisibiliy in bg - target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::StealthOrInvis); } target->UpdateObjectVisibility(); } @@ -1613,7 +1613,7 @@ void AuraEffect::HandleModStealth(AuraApplication const* aurApp, uint8 mode, boo if (apply && (mode & AURA_EFFECT_HANDLE_REAL)) { // drop flag at stealth in bg - target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::StealthOrInvis); } target->UpdateObjectVisibility(); } @@ -1720,14 +1720,7 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app Unit* target = aurApp->GetTarget(); if (apply) - { PhasingHandler::AddPhase(target, uint32(GetMiscValueB()), true); - - // call functions which may have additional effects after chainging state of unit - // phase auras normally not expected at BG but anyway better check - // drop flag at invisibiliy in bg - target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); - } else PhasingHandler::RemovePhase(target, uint32(GetMiscValueB()), true); } @@ -1742,14 +1735,7 @@ void AuraEffect::HandlePhaseGroup(AuraApplication const* aurApp, uint8 mode, boo PhasingHandler::AddPhaseGroup(target, uint32(GetMiscValueB()), true); if (apply) - { PhasingHandler::AddPhaseGroup(target, uint32(GetMiscValueB()), true); - - // call functions which may have additional effects after chainging state of unit - // phase auras normally not expected at BG but anyway better check - // drop flag at invisibiliy in bg - target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); - } else PhasingHandler::RemovePhaseGroup(target, uint32(GetMiscValueB()), true); } @@ -1890,6 +1876,10 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo if (!transformSpellInfo || !GetSpellInfo()->IsPositive()) target->SetDisplayId(modelid); } + + if (SpellShapeshiftFormEntry const* shapeshift = sSpellShapeshiftFormStore.LookupEntry(form)) + if (!shapeshift->GetFlags().HasFlag(SpellShapeshiftFormFlags::Stance)) + target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Shapeshifting, GetId()); } else { @@ -2313,8 +2303,6 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo else target->CombatStop(false, false); - target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); - // prevent interrupt message if (GetCasterGUID() == target->GetGUID() && target->GetCurrentSpell(CURRENT_GENERIC_SPELL)) target->FinishSpell(CURRENT_GENERIC_SPELL, false); @@ -2362,10 +2350,6 @@ void AuraEffect::HandleModUnattackable(AuraApplication const* aurApp, uint8 mode target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2, apply); target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE, apply); - - // call functions which may have additional effects after chainging state of unit - if (apply && (mode & AURA_EFFECT_HANDLE_REAL)) - target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); } void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -3220,8 +3204,9 @@ void AuraEffect::HandleAuraModEffectImmunity(AuraApplication const* aurApp, uint m_spellInfo->ApplyAllSpellImmunitiesTo(target, GetEffIndex(), apply); // when removing flag aura, handle flag drop + // TODO: this should be handled in aura script for flag spells using AfterEffectRemove hook Player* player = target->ToPlayer(); - if (!apply && player && (GetSpellInfo()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION)) + if (!apply && player && GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::StealthOrInvis)) { if (player->InBattleground()) { @@ -3272,13 +3257,16 @@ void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const* aurApp, uint } } - if (apply && GetMiscValue() == SPELL_SCHOOL_MASK_NORMAL) - target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + // TODO: should be changed to a proc script on flag spell (they have "Taken positive" proc flags in db2) + { + if (apply && GetMiscValue() == SPELL_SCHOOL_MASK_NORMAL) + target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::StealthOrInvis); - // remove all flag auras (they are positive, but they must be removed when you are immune) - if (GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY) - && GetSpellInfo()->HasAttribute(SPELL_ATTR2_DAMAGE_REDUCED_SHIELD)) - target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + // remove all flag auras (they are positive, but they must be removed when you are immune) + if (GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY) + && GetSpellInfo()->HasAttribute(SPELL_ATTR2_DAMAGE_REDUCED_SHIELD)) + target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::StealthOrInvis); + } if (apply) { diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index ea579e60f7b..3ee615b4bbd 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2709,7 +2709,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) // Failed Pickpocket, reveal rogue if (missInfo == SPELL_MISS_RESIST && m_spellInfo->HasAttribute(SPELL_ATTR0_CU_PICKPOCKET) && unitTarget->GetTypeId() == TYPEID_UNIT) { - m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK, 0, this); + m_caster->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Interacting, 0, this); unitTarget->ToCreature()->EngageWithTarget(m_caster); } } @@ -2798,7 +2798,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA return SPELL_MISS_EVADE; if (m_caster->_IsValidAttackTarget(unit, m_spellInfo)) - unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_HITBYSPELL, 0, this); + unit->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::HostileActionReceived); else if (m_caster->IsFriendlyTo(unit)) { // for delayed spells ignore negative spells (after duel end) for friendly targets @@ -3304,15 +3304,7 @@ void Spell::prepare(SpellCastTargets const& targets, AuraEffect const* triggered // stealth must be removed at cast starting (at show channel bar) // skip triggered spell (item equip spell casting and other not explicit character casts/item uses) if (!(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS) && m_spellInfo->IsBreakingStealth()) - { - m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CAST, 0, this); - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_spellInfo->Effects[i].GetUsedTargetObjectType() == TARGET_OBJECT_TYPE_UNIT) - { - m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_SPELL_ATTACK, 0, this); - break; - } - } + m_caster->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Action); m_caster->SetCurrentCastSpell(this); SendSpellStart(); @@ -3664,6 +3656,7 @@ void Spell::_cast(bool skipCheck) if (!(hitMask & PROC_HIT_CRITICAL)) hitMask |= PROC_HIT_NORMAL; + m_originalCaster->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::ActionDelayed); m_originalCaster->ProcSkillsAndAuras(nullptr, procAttacker, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_CAST, hitMask, this, nullptr, nullptr); // Call CreatureAI hook OnSuccessfulSpellCast @@ -3681,14 +3674,14 @@ void Spell::handle_immediate() if (duration > 0) { m_spellState = SPELL_STATE_CASTING; - m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags); + m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags, m_spellInfo->ChannelInterruptFlags2); m_channeledDuration = duration; SendChannelStart(duration); } else if (duration == -1) { m_spellState = SPELL_STATE_CASTING; - m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags); + m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags, m_spellInfo->ChannelInterruptFlags2); SendChannelStart(duration); } } @@ -5535,7 +5528,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint { // skip stuck spell to allow use it in falling case and apply spell limitations at movement if ((!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK) && - (IsAutoRepeat() || (m_spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) != 0)) + (IsAutoRepeat() || m_spellInfo->HasAuraInterruptFlag(SpellAuraInterruptFlags::Standing))) return SPELL_FAILED_MOVING; } diff --git a/src/server/game/Spells/SpellDefines.h b/src/server/game/Spells/SpellDefines.h index 1e66a88ad6d..98d734babbf 100644 --- a/src/server/game/Spells/SpellDefines.h +++ b/src/server/game/Spells/SpellDefines.h @@ -19,13 +19,14 @@ #define TRINITY_SPELLDEFINES_H #include "Define.h" +#include "EnumFlag.h" #include "ObjectGuid.h" #include class Item; class AuraEffect; -enum SpellInterruptFlags +enum SpellInterruptFlags : uint32 { SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, // why need this for instant? SPELL_INTERRUPT_FLAG_PUSH_BACK = 0x02, // push back @@ -42,39 +43,76 @@ enum SpellChannelInterruptFlags CHANNEL_FLAG_DELAY = 0x4000 }; -enum SpellAuraInterruptFlags +enum class SpellAuraInterruptFlags : uint32 { - AURA_INTERRUPT_FLAG_HITBYSPELL = 0x00000001, // 0 removed when getting hit by a negative spell? - AURA_INTERRUPT_FLAG_TAKE_DAMAGE = 0x00000002, // 1 removed by any damage - AURA_INTERRUPT_FLAG_CAST = 0x00000004, // 2 cast any spells - AURA_INTERRUPT_FLAG_MOVE = 0x00000008, // 3 removed by any movement - AURA_INTERRUPT_FLAG_TURNING = 0x00000010, // 4 removed by any turning - AURA_INTERRUPT_FLAG_JUMP = 0x00000020, // 5 removed by entering combat - AURA_INTERRUPT_FLAG_NOT_MOUNTED = 0x00000040, // 6 removed by dismounting - AURA_INTERRUPT_FLAG_NOT_ABOVEWATER = 0x00000080, // 7 removed by entering water - AURA_INTERRUPT_FLAG_NOT_UNDERWATER = 0x00000100, // 8 removed by leaving water - AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9 removed by unsheathing - AURA_INTERRUPT_FLAG_TALK = 0x00000400, // 10 talk to npc / loot? action on creature - AURA_INTERRUPT_FLAG_USE = 0x00000800, // 11 mine/use/open action on gameobject - AURA_INTERRUPT_FLAG_MELEE_ATTACK = 0x00001000, // 12 removed by attacking - AURA_INTERRUPT_FLAG_SPELL_ATTACK = 0x00002000, // 13 ??? - AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14 - AURA_INTERRUPT_FLAG_TRANSFORM = 0x00008000, // 15 removed by transform? - AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16 - AURA_INTERRUPT_FLAG_MOUNT = 0x00020000, // 17 misdirect, aspect, swim speed - AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up (used by food and drink mostly and sleep/Fake Death like) - AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported - AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION = 0x00100000, // 20 removed by auras that make you invulnerable, or make other to lose selection on you - AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21 - AURA_INTERRUPT_FLAG_TELEPORTED = 0x00400000, // 22 - AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat - AURA_INTERRUPT_FLAG_DIRECT_DAMAGE = 0x01000000, // 24 removed by any direct damage - AURA_INTERRUPT_FLAG_LANDING = 0x02000000, // 25 removed by hitting the ground - AURA_INTERRUPT_FLAG_LEAVE_COMBAT = 0x80000000, // 31 removed by leaving combat + None = 0, + HostileActionReceived = 0x00000001, + Damage = 0x00000002, + Action = 0x00000004, + Moving = 0x00000008, + Turning = 0x00000010, + Anim = 0x00000020, + Dismount = 0x00000040, + UnderWater = 0x00000080, // TODO: disallow casting when swimming (SPELL_FAILED_ONLY_ABOVEWATER) + AboveWater = 0x00000100, // TODO: disallow casting when not swimming (SPELL_FAILED_ONLY_UNDERWATER) + Sheathing = 0x00000200, + Interacting = 0x00000400, // TODO: more than gossip, replace all the feign death removals by aura type + Looting = 0x00000800, + Attacking = 0x00001000, + ItemUse = 0x00002000, + DamageChannelDuration = 0x00004000, + Shapeshifting = 0x00008000, + ActionDelayed = 0x00010000, + Mount = 0x00020000, + Standing = 0x00040000, + LeaveWorld = 0x00080000, + StealthOrInvis = 0x00100000, + InvulnerabilityBuff = 0x00200000, + EnterWorld = 0x00400000, + PvPActive = 0x00800000, + NonPeriodicDamage = 0x01000000, + LandingOrFlight = 0x02000000, + Release = 0x04000000, + DamageCancelsScript = 0x08000000, // NYI dedicated aura script hook + EnteringCombat = 0x10000000, + Login = 0x20000000, + Summon = 0x40000000, + LeavingCombat = 0x80000000, - AURA_INTERRUPT_FLAG_NOT_VICTIM = (AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE | AURA_INTERRUPT_FLAG_DIRECT_DAMAGE) + NOT_VICTIM = (HostileActionReceived | Damage | NonPeriodicDamage) }; +DEFINE_ENUM_FLAG(SpellAuraInterruptFlags); + +enum class SpellAuraInterruptFlags2 : uint32 +{ + None = 0, + Falling = 0x00000001, // NYI + Swimming = 0x00000002, // NYI + NotMoving = 0x00000004, // NYI + Ground = 0x00000008, // NYI + Transform = 0x00000010, // NYI + Jump = 0x00000020, + ChangeSpec = 0x00000040, // NYI + AbandonVehicle = 0x00000080, // NYI + StartOfEncounter = 0x00000100, // NYI + EndOfEncounter = 0x00000200, // NYI + Disconnect = 0x00000400, // NYI + EnteringInstance = 0x00000800, // NYI + DuelEnd = 0x00001000, // NYI + LeaveArenaOrBattleground = 0x00002000, // NYI + ChangeTalent = 0x00004000, // NYI + ChangeGlyph = 0x00008000, // NYI + SeamlessTransfer = 0x00010000, // NYI + WarModeLeave = 0x00020000, // NYI + TouchingGround = 0x00040000, // NYI + ChromieTime = 0x00080000, // NYI + SplineFlightOrFreeFlight = 0x00100000, // NYI + ProcOrPeriodicAttacking = 0x00200000 // NYI +}; + +DEFINE_ENUM_FLAG(SpellAuraInterruptFlags2); + enum SpellModOp : uint8 { SPELLMOD_DAMAGE = 0, diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index f12db340344..755c45a6eb3 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2890,7 +2890,7 @@ void Spell::EffectInterruptCast(SpellEffIndex effIndex) || (spell->getState() == SPELL_STATE_PREPARING && spell->GetCastTime() > 0.0f)) && (curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE || curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_UNK) && ((i == CURRENT_GENERIC_SPELL && curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT) - || (i == CURRENT_CHANNELED_SPELL && curSpellInfo->ChannelInterruptFlags & CHANNEL_INTERRUPT_FLAG_INTERRUPT))) + || i == CURRENT_CHANNELED_SPELL)) { if (m_originalCaster) { diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 5b7855dd032..b8e827d4131 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -988,9 +988,11 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry, SpellEffectEntry const** effe // SpellInterruptsEntry SpellInterruptsEntry const* _interrupt = GetSpellInterrupts(); - InterruptFlags = _interrupt ? _interrupt->InterruptFlags : 0; - AuraInterruptFlags = _interrupt ? _interrupt->AuraInterruptFlags[0] : 0; - ChannelInterruptFlags = _interrupt ? _interrupt->ChannelInterruptFlags[0] : 0; + + AuraInterruptFlags = _interrupt ? SpellAuraInterruptFlags(_interrupt->AuraInterruptFlags[0]) : SpellAuraInterruptFlags::None; + AuraInterruptFlags2 = _interrupt? SpellAuraInterruptFlags2(_interrupt->AuraInterruptFlags[1]) : SpellAuraInterruptFlags2::None; + ChannelInterruptFlags = _interrupt ? SpellAuraInterruptFlags(_interrupt->ChannelInterruptFlags[0] ) : SpellAuraInterruptFlags::None; + ChannelInterruptFlags2 = _interrupt? SpellAuraInterruptFlags2(_interrupt->ChannelInterruptFlags[1]) : SpellAuraInterruptFlags2::None; // SpellLevelsEntry SpellLevelsEntry const* _levels = GetSpellLevels(); @@ -1109,6 +1111,11 @@ bool SpellInfo::HasOnlyDamageEffects() const return true; } +bool SpellInfo::HasAnyAuraInterruptFlag() const +{ + return AuraInterruptFlags != SpellAuraInterruptFlags::None || AuraInterruptFlags2 != SpellAuraInterruptFlags2::None; +} + bool SpellInfo::IsExplicitDiscovery() const { return ((Effects[0].Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM @@ -1434,7 +1441,7 @@ bool SpellInfo::IsChanneled() const bool SpellInfo::IsMoveAllowedChannel() const { - return IsChanneled() && ((HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING) && !(ChannelInterruptFlags & AURA_INTERRUPT_FLAG_MOVE)) || (!(ChannelInterruptFlags & (AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING)))); + return IsChanneled() && ((HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING) && !ChannelInterruptFlags.HasFlag(SpellAuraInterruptFlags::Moving | SpellAuraInterruptFlags::Turning))); } bool SpellInfo::NeedsComboPoints() const @@ -2265,7 +2272,7 @@ void SpellInfo::_LoadSpellSpecific() case SPELLFAMILY_GENERIC: { // Food / Drinks (mostly) - if (AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) + if (HasAuraInterruptFlag(SpellAuraInterruptFlags::Standing)) { bool food = false; bool drink = false; @@ -3079,6 +3086,8 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool app auraSpellInfo->Id != Id); // Don't remove self }); } + if (apply && schoolImmunity & SPELL_SCHOOL_MASK_NORMAL) + target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::InvulnerabilityBuff); } if (uint32 mechanicImmunity = immuneInfo->MechanicImmuneMask) @@ -3109,8 +3118,13 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool app } if (uint32 damageImmunity = immuneInfo->DamageSchoolMask) + { target->ApplySpellImmune(Id, IMMUNITY_DAMAGE, damageImmunity, apply); + if (apply && damageImmunity & SPELL_SCHOOL_MASK_NORMAL) + target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::InvulnerabilityBuff); + } + for (AuraType auraType : immuneInfo->AuraTypeImmune) { target->ApplySpellImmune(Id, IMMUNITY_STATE, auraType, apply); @@ -3257,7 +3271,7 @@ uint32 SpellInfo::GetMechanicImmunityMask(Unit* caster, bool channeled) const { uint32 casterMechanicImmunityMask = caster->GetMechanicImmunityMask(); uint32 mechanicImmunityMask = 0; - uint32 flags = channeled ? ChannelInterruptFlags : InterruptFlags; + uint32 flags = channeled ? ChannelInterruptFlags.AsUnderlyingType() : InterruptFlags; // @todo: research other interrupt flags if (flags & SPELL_INTERRUPT_FLAG_INTERRUPT) diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 5c768e7a0b1..90973b34ee8 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -23,6 +23,7 @@ #include "DBCStructure.h" #include "Object.h" #include "SpellAuraDefines.h" +#include "SpellDefines.h" #include @@ -370,8 +371,10 @@ class TC_GAME_API SpellInfo uint32 StartRecoveryCategory; uint32 StartRecoveryTime; uint32 InterruptFlags; - uint32 AuraInterruptFlags; - uint32 ChannelInterruptFlags; + EnumFlag AuraInterruptFlags = SpellAuraInterruptFlags::None; + EnumFlag AuraInterruptFlags2 = SpellAuraInterruptFlags2::None; + EnumFlag ChannelInterruptFlags = SpellAuraInterruptFlags::None; + EnumFlag ChannelInterruptFlags2 = SpellAuraInterruptFlags2::None; uint32 ProcFlags; uint32 ProcChance; uint32 ProcCharges; @@ -478,6 +481,13 @@ class TC_GAME_API SpellInfo inline bool HasAttribute(SpellAttr10 attribute) const { return !!(AttributesEx10 & attribute); } inline bool HasAttribute(SpellCustomAttributes customAttribute) const { return !!(AttributesCu & customAttribute); } + bool HasAnyAuraInterruptFlag() const; + bool HasAuraInterruptFlag(SpellAuraInterruptFlags flag) const { return AuraInterruptFlags.HasFlag(flag); } + bool HasAuraInterruptFlag(SpellAuraInterruptFlags2 flag) const { return AuraInterruptFlags2.HasFlag(flag); } + + bool HasChannelInterruptFlag(SpellAuraInterruptFlags flag) const { return ChannelInterruptFlags.HasFlag(flag); } + bool HasChannelInterruptFlag(SpellAuraInterruptFlags2 flag) const { return ChannelInterruptFlags2.HasFlag(flag); } + bool IsExplicitDiscovery() const; bool IsLootCrafting() const; bool IsQuestTame() const; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index dfe87892175..66113d98ccb 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3346,11 +3346,10 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_0].BasePoints = 0; }); - // Easter Lay Noblegarden Egg Aura + // Easter Lay Noblegarden Egg Aura - Interrupt flags copied from aura which this aura is linked with ApplySpellFix({ 61719 }, [](SpellInfo* spellInfo) { - // Interrupt flags copied from aura which this aura is linked with - spellInfo->AuraInterruptFlags = AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE; + spellInfo->AuraInterruptFlags = SpellAuraInterruptFlags::HostileActionReceived | SpellAuraInterruptFlags::Damage; }); ApplySpellFix({ @@ -3429,7 +3428,7 @@ void SpellMgr::LoadSpellInfoCorrections() // Test Ribbon Pole Channel ApplySpellFix({ 29726 }, [](SpellInfo* spellInfo) { - spellInfo->InterruptFlags &= ~AURA_INTERRUPT_FLAG_CAST; + spellInfo->ChannelInterruptFlags &= ~SpellAuraInterruptFlags::Action; }); ApplySpellFix({ @@ -3626,7 +3625,8 @@ void SpellMgr::LoadSpellInfoCorrections() ApplySpellFix({ 63414 }, [](SpellInfo* spellInfo) { spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); - spellInfo->ChannelInterruptFlags = 0; + spellInfo->ChannelInterruptFlags = SpellAuraInterruptFlags::None; + spellInfo->ChannelInterruptFlags2 = SpellAuraInterruptFlags2::None; }); // Rocket Strike (Mimiron) @@ -4199,7 +4199,7 @@ void SpellMgr::LoadSpellInfoCorrections() ApplySpellFix({ 92426 }, [](SpellInfo* spellInfo) { spellInfo->CasterAuraSpell = 0; - spellInfo->AuraInterruptFlags = AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE; + spellInfo->AuraInterruptFlags = SpellAuraInterruptFlags::Damage | SpellAuraInterruptFlags::HostileActionReceived; }); // Rupture @@ -4760,7 +4760,7 @@ void SpellMgr::LoadSpellInfoCorrections() // Toxic Coagulant ApplySpellFix({ 93617 }, [](SpellInfo* spellInfo) { - spellInfo->AuraInterruptFlags = AURA_INTERRUPT_FLAG_MOVE; + spellInfo->AuraInterruptFlags = SpellAuraInterruptFlags::Moving; }); // END OF SHADOWFANG KEEP SPELLS @@ -4768,7 +4768,7 @@ void SpellMgr::LoadSpellInfoCorrections() // Threatening Gaze ApplySpellFix({ 24314 }, [](SpellInfo* spellInfo) { - spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CAST | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_JUMP; + spellInfo->AuraInterruptFlags |= SpellAuraInterruptFlags::Action | SpellAuraInterruptFlags::Moving | SpellAuraInterruptFlags::Anim; }); // Feral Charge (Cat Form @@ -4821,13 +4821,6 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->MaxAffectedTargets = 1; }); - // Bore - ApplySpellFix({ 75205 }, [](SpellInfo* spellInfo) - { - spellInfo->ChannelInterruptFlags = 0; - spellInfo->AuraInterruptFlags &= ~AURA_INTERRUPT_FLAG_TURNING; - }); - // Twilight Portal ApplySpellFix({ 95210,