aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp4
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp4
-rw-r--r--src/server/game/Combat/ThreatManager.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp13
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp102
-rw-r--r--src/server/game/Entities/Unit/Unit.h15
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp2
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp3
-rw-r--r--src/server/game/Handlers/LootHandler.cpp2
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp8
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp5
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp2
-rw-r--r--src/server/game/Server/Packets/SpellPackets.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp43
-rw-r--r--src/server/game/Spells/Spell.cpp21
-rw-r--r--src/server/game/Spells/SpellDefines.h81
-rw-r--r--src/server/game/Spells/SpellEffects.cpp2
-rw-r--r--src/server/game/Spells/SpellInfo.cpp20
-rw-r--r--src/server/game/Spells/SpellInfo.h83
-rw-r--r--src/server/game/Spells/SpellMgr.cpp19
22 files changed, 248 insertions, 189 deletions
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp
index 318c7c29583..ccdb4097323 100644
--- a/src/server/game/AI/CoreAI/UnitAI.cpp
+++ b/src/server/game/AI/CoreAI/UnitAI.cpp
@@ -154,7 +154,7 @@ void UnitAI::DoCast(uint32 spellId)
float range = spellInfo->GetMaxRange(false);
DefaultTargetSelector targetSelector(me, range, playerOnly, true, -(int32)spellId);
- if (!spellInfo->HasAuraInterruptFlag(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 508fd47ed8d..4e3600b069b 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
@@ -431,7 +431,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/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
index c42350756d5..e440e7ef912 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
@@ -684,7 +684,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);
@@ -811,7 +811,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/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
index fbdaa647090..68a064a7395 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
@@ -287,7 +287,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())
@@ -563,7 +563,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/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp
index 0e9b871c8e5..5aaa063a0d8 100644
--- a/src/server/game/Combat/ThreatManager.cpp
+++ b/src/server/game/Combat/ThreatManager.cpp
@@ -334,7 +334,7 @@ HostileReference* ThreatContainer::selectNextVictim(Creature* attacker, HostileR
ASSERT(target); // if the ref has status online the target must be there !
// some units are prefered in comparison to others
- if (!noPriorityTargetFound && (target->IsImmunedToDamage(attacker->GetMeleeDamageSchoolMask()) || target->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE)))
+ if (!noPriorityTargetFound && (target->IsImmunedToDamage(attacker->GetMeleeDamageSchoolMask()) || target->HasNegativeAuraWithInterruptFlag(SpellAuraInterruptFlags::Damage)))
{
if (iter != lastRef)
{
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 6dd5de7275f..e2f970031da 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -1070,7 +1070,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);
}*/
}
}
@@ -1494,7 +1494,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
InterruptNonMeleeSpells(true);
//remove auras before removing from map...
- RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING));
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Moving | SpellAuraInterruptFlags::Turning);
if (!GetSession()->PlayerLogout() && !(options & TELE_TO_SEAMLESS))
{
@@ -4215,6 +4215,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_SET_WATER_WALK
// there must be SMSG.STOP_MIRROR_TIMER
@@ -6046,9 +6048,9 @@ bool Player::UpdatePosition(float x, float y, float z, float orientation, bool t
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);
+ // mover->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Turning);
// group update
if (GetGroup())
@@ -22864,7 +22866,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
UpdateCriteria(CRITERIA_TYPE_FLIGHT_PATHS_TAKEN, 1);
// prevent stealth flight
- //RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK);
+ //RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Interacting);
if (sWorld->getBoolConfig(CONFIG_INSTANT_TAXI))
{
@@ -25359,6 +25361,7 @@ void Player::SummonIfPossible(bool agree)
m_summon_expire = 0;
UpdateCriteria(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 d28da5afd8d..759a111136a 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -298,7 +298,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_regenTimer(0), m_ThreatManager(this),
+ m_removedAurasCount(0), m_interruptMask(SpellAuraInterruptFlags::None), m_interruptMask2(SpellAuraInterruptFlags2::None),
+ i_motionMaster(new MotionMaster(this)), m_regenTimer(0), m_ThreatManager(this),
m_vehicle(nullptr), m_vehicleKit(nullptr), m_unitTypeMask(UNIT_MASK_NONE), m_Diminishing(),
m_HostileRefManager(this), _aiAnimKitId(0), _movementAnimKitId(0), _meleeAnimKitId(0),
_spellHistory(new SpellHistory(this))
@@ -334,7 +335,6 @@ Unit::Unit(bool isWorldObject) :
m_auraUpdateIterator = m_ownedAuras.end();
- m_interruptMask.fill(0);
m_transform = 0;
m_canModifyStats = false;
@@ -664,15 +664,22 @@ void Unit::RemoveVisibleAura(AuraApplication* aurApp)
void Unit::UpdateInterruptMask()
{
- m_interruptMask.fill(0);
+ m_interruptMask = SpellAuraInterruptFlags::None;
+ m_interruptMask2 = SpellAuraInterruptFlags2::None;
for (AuraApplication const* aurApp : m_interruptableAuras)
- for (std::size_t i = 0; i < m_interruptMask.size(); ++i)
- m_interruptMask[i] |= aurApp->GetBase()->GetSpellInfo()->AuraInterruptFlags[i];
+ {
+ 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)
- for (std::size_t i = 0; i < m_interruptMask.size(); ++i)
- m_interruptMask[i] |= spell->m_spellInfo->ChannelInterruptFlags[i];
+ {
+ m_interruptMask |= spell->m_spellInfo->ChannelInterruptFlags;
+ m_interruptMask2 |= spell->m_spellInfo->ChannelInterruptFlags2;
+ }
+ }
}
bool Unit::HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, flag128 familyFlags) const
@@ -688,7 +695,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()->HasAuraInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE))
+ (*itr)->GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::Damage))
return true;
return false;
}
@@ -748,14 +755,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)
@@ -883,7 +890,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
victim->ModifyHealth(-(int32)damage);
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);
if (victim->GetTypeId() != TYPEID_PLAYER)
{
@@ -930,7 +937,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 && spell->m_spellInfo->HasChannelInterruptFlag(CHANNEL_FLAG_DELAY) && damagetype != DOT)
+ if (spell->getState() == SPELL_STATE_CASTING && spell->m_spellInfo->HasChannelInterruptFlag(SpellAuraInterruptFlags::DamageChannelDuration) && damagetype != DOT)
spell->DelayedChannel();
}
}
@@ -2014,7 +2021,7 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr
return;
CombatStart(victim);
- RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MELEE_ATTACK);
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Attacking);
if (attType != BASE_ATTACK && attType != OFF_ATTACK)
return; // ignore ranged case
@@ -2095,7 +2102,7 @@ void Unit::FakeAttackerStateUpdate(Unit* victim, WeaponAttackType attType /*= BA
return;
CombatStart(victim);
- RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MELEE_ATTACK);
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Attacking);
if (attType != BASE_ATTACK && attType != OFF_ATTACK)
return; // ignore ranged case
@@ -3180,9 +3187,9 @@ void Unit::SetInWater(bool inWater)
{
// remove appropriate auras if we are swimming/not swimming respectively
if (inWater)
- RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_ABOVEWATER);
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::UnderWater);
else
- RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_UNDERWATER);
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::AboveWater);
}
void Unit::ProcessTerrainStatusUpdate(ZLiquidStatus status, Optional<LiquidData> const& liquidData)
@@ -3354,7 +3361,7 @@ AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint32 effMask)
if (aurSpellInfo->HasAnyAuraInterruptFlag())
{
m_interruptableAuras.push_back(aurApp);
- AddInterruptMask(aurSpellInfo->AuraInterruptFlags);
+ AddInterruptMask(aurSpellInfo->AuraInterruptFlags, aurSpellInfo->AuraInterruptFlags2);
}
if (AuraStateType aState = aura->GetSpellInfo()->GetAuraState())
@@ -3402,7 +3409,7 @@ void Unit::_ApplyAura(AuraApplication * aurApp, uint32 effMask)
return;
// Sitdown on apply aura req seated
- if (aura->GetSpellInfo()->HasAuraInterruptFlag(AURA_INTERRUPT_FLAG_NOT_SEATED) && !IsSitState())
+ if (aura->GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::Standing) && !IsSitState())
SetStandState(UNIT_STAND_STATE_SIT);
Unit* caster = aura->GetCaster();
@@ -4031,10 +4038,22 @@ void Unit::RemoveNotOwnSingleTargetAuras(bool onPhaseChange /*= false*/)
}
}
+template<typename InterruptFlag>
+bool IsInterruptFlagIgnoredForSpell(InterruptFlag /*flag*/, Unit const* /*unit*/, SpellInfo const* /*spellInfo*/)
+{
+ 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 <typename InterruptFlags>
void Unit::RemoveAurasWithInterruptFlags(InterruptFlags flag, uint32 except)
{
- if (!(m_interruptMask[AuraInterruptFlagIndex<InterruptFlags>::value] & flag))
+ if (!HasInterruptFlag(flag))
return;
// interrupt auras
@@ -4042,8 +4061,9 @@ void Unit::RemoveAurasWithInterruptFlags(InterruptFlags flag, uint32 except)
{
Aura* aura = (*iter)->GetBase();
++iter;
- if (aura->GetSpellInfo()->AuraInterruptFlags[AuraInterruptFlagIndex<InterruptFlags>::value] & 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, AURA_REMOVE_BY_INTERRUPT);
@@ -4055,9 +4075,9 @@ void Unit::RemoveAurasWithInterruptFlags(InterruptFlags flag, uint32 except)
// interrupt channeled spell
if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL])
if (spell->getState() == SPELL_STATE_CASTING
- && (spell->GetSpellInfo()->ChannelInterruptFlags[AuraInterruptFlagIndex<InterruptFlags>::value] & flag)
+ && spell->GetSpellInfo()->HasChannelInterruptFlag(flag)
&& spell->GetSpellInfo()->Id != except
- && !(flag & AURA_INTERRUPT_FLAG_MOVE && HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, spell->GetSpellInfo())))
+ && !IsInterruptFlagIgnoredForSpell(flag, this, spell->GetSpellInfo()))
InterruptNonMeleeSpells(false);
UpdateInterruptMask();
@@ -4553,11 +4573,11 @@ bool Unit::HasAuraTypeWithValue(AuraType auratype, int32 value) const
template <typename InterruptFlags>
bool Unit::HasNegativeAuraWithInterruptFlag(InterruptFlags flag, ObjectGuid guid) const
{
- if (!(m_interruptMask[AuraInterruptFlagIndex<InterruptFlags>::value] & 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[AuraInterruptFlagIndex<InterruptFlags>::value] & flag &&
+ if (!(*iter)->IsPositive() && (*iter)->GetBase()->GetSpellInfo()->HasAuraInterruptFlag(flag) &&
(!guid || (*iter)->GetBase()->GetCasterGUID() == guid))
return true;
@@ -5441,6 +5461,13 @@ void Unit::UpdateDisplayPower()
SetPowerType(displayPower);
}
+void Unit::SetSheath(SheathState sheathed)
+{
+ SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::SheatheState), sheathed);
+ if (sheathed == SHEATH_STATE_UNARMED)
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Sheathing);
+}
+
FactionTemplateEntry const* Unit::GetFactionTemplateEntry() const
{
FactionTemplateEntry const* entry = sFactionTemplateStore.LookupEntry(GetFaction());
@@ -7907,7 +7934,7 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
player->SendMovementSetCollisionHeight(player->GetCollisionHeight(), WorldPackets::Movement::UpdateCollisionHeightReason::Mount);
}
- RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNT);
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Mount);
}
void Unit::Dismount()
@@ -7928,7 +7955,7 @@ void Unit::Dismount()
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
@@ -8120,7 +8147,7 @@ void Unit::CombatStart(Unit* target, bool initialAggro)
|| !me->duel || me->duel->opponent != who))
{
me->UpdatePvP(true);
- me->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
+ me->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::PvPActive);
}
}
@@ -8178,6 +8205,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy)
controlled->SetInCombatState(PvP, enemy);
}
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::EnteringCombat);
ProcSkillsAndAuras(enemy, PROC_FLAG_ENTER_COMBAT, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, nullptr, nullptr, nullptr);
}
@@ -8206,7 +8234,7 @@ void Unit::ClearInCombat()
else
ToPlayer()->OnCombatExit();
- RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LEAVE_COMBAT);
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::LeavingCombat);
}
void Unit::ClearInPetCombat()
@@ -10078,6 +10106,13 @@ int32 Unit::GetCreatePowers(Powers power) const
return 0;
}
+void Unit::AddToWorld()
+{
+ WorldObject::AddToWorld();
+
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::EnterWorld);
+}
+
void Unit::RemoveFromWorld()
{
// cleanup
@@ -10092,6 +10127,7 @@ void Unit::RemoveFromWorld()
RemoveCharmAuras();
RemoveBindSightAuras();
RemoveNotOwnSingleTargetAuras();
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::LeaveWorld);
RemoveAllGameObjects();
RemoveAllDynObjects();
@@ -10875,7 +10911,7 @@ void Unit::SetStandState(UnitStandStateType state, uint32 animKitID /* = 0*/)
SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::StandState), state);
if (IsStandState())
- RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_SEATED);
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Standing);
if (GetTypeId() == TYPEID_PLAYER)
{
@@ -13162,12 +13198,12 @@ bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool tel
// TODO: Check if orientation transport offset changed instead of only global orientation
if (turn)
- RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING);
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Turning);
if (relocated)
{
if (!GetVehicle())
- RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOVE);
+ RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Moving);
// move and update visible state if need
if (GetTypeId() == TYPEID_PLAYER)
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index ec46f67fcb4..2b8122c6125 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -25,6 +25,7 @@
#include "HostileRefManager.h"
#include "OptionalFwd.h"
#include "SpellAuraDefines.h"
+#include "SpellDefines.h"
#include "ThreatManager.h"
#include "Timer.h"
#include "UnitDefines.h"
@@ -943,6 +944,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);
@@ -1122,7 +1124,7 @@ class TC_GAME_API Unit : public WorldObject
void SetEmoteState(Emote emote) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::EmoteState), emote); }
SheathState GetSheath() const { return SheathState(*m_unitData->SheatheState); }
- void SetSheath(SheathState sheathed) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::SheatheState), sheathed); }
+ void SetSheath(SheathState sheathed);
// faction template id
uint32 GetFaction() const { return m_unitData->FactionTemplate; }
@@ -1797,10 +1799,12 @@ class TC_GAME_API Unit : public WorldObject
void SetVisibleAuraUpdate(AuraApplication* aurApp) { m_visibleAurasToUpdate.insert(aurApp); }
void RemoveVisibleAura(AuraApplication* aurApp);
- void AddInterruptMask(std::array<uint32, 2> const& 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)
{
- for (std::size_t i = 0; i < m_interruptMask.size(); ++i)
- m_interruptMask[i] |= mask[i];
+ m_interruptMask |= flags;
+ m_interruptMask2 |= flags2;
}
void UpdateInterruptMask();
@@ -2102,7 +2106,8 @@ class TC_GAME_API Unit : public WorldObject
AuraList m_scAuras; // cast singlecast 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
- std::array<uint32, 2> m_interruptMask;
+ EnumFlag<SpellAuraInterruptFlags> m_interruptMask;
+ EnumFlag<SpellAuraInterruptFlags2> m_interruptMask2;
float m_auraFlatModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_FLAT_END];
float m_auraPctModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_PCT_END];
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 4e589db6d47..c49fcbac361 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -1153,6 +1153,8 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
}
}
+ pCurrChar->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Login);
+
pCurrChar->SendInitialPacketsAfterAddToMap();
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ONLINE);
diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
index cbbb0942341..f685cfb2c1e 100644
--- a/src/server/game/Handlers/ChatHandler.cpp
+++ b/src/server/game/Handlers/ChatHandler.cpp
@@ -636,6 +636,9 @@ void WorldSession::HandleTextEmoteOpcode(WorldPackets::Chat::CTextEmote& packet)
if (unit)
if (Creature* creature = unit->ToCreature())
creature->AI()->ReceiveEmote(_player, packet.EmoteID);
+
+ if (emoteAnim != EMOTE_ONESHOT_NONE)
+ _player->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Anim);
}
void WorldSession::HandleChatIgnoredOpcode(WorldPackets::Chat::ChatReportIgnored& chatReportIgnored)
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index 80158c10fad..111cfd892a8 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -295,6 +295,8 @@ void WorldSession::HandleLootOpcode(WorldPackets::Loot::LootUnit& packet)
// interrupt cast
if (GetPlayer()->IsNonMeleeSpellCast(false))
GetPlayer()->InterruptNonMeleeSpells(false);
+
+ GetPlayer()->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Looting);
}
void WorldSession::HandleLootReleaseOpcode(WorldPackets::Loot::LootRelease& packet)
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 15d65c9a6d8..1e77f518357 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -385,8 +385,8 @@ void WorldSession::HandleMovementOpcode(OpcodeClient opcode, MovementInfo& movem
plrMover->HandleFall(movementInfo);
// interrupt parachutes upon falling or landing in water
- if (opcode == CMSG_MOVE_FALL_LAND || opcode == CMSG_MOVE_START_SWIM)
- mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LANDING); // Parachutes
+ if (opcode == CMSG_MOVE_FALL_LAND || opcode == CMSG_MOVE_START_SWIM || opcode == CMSG_MOVE_SET_FLY)
+ mover->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::LandingOrFlight); // Parachutes
uint32 mstime = GameTime::GetGameTimeMS();
/*----------------------*/
@@ -409,7 +409,7 @@ void WorldSession::HandleMovementOpcode(OpcodeClient opcode, MovementInfo& movem
if (movementInfo.pos.GetOrientation() != mover->GetOrientation())
{
mover->SetOrientation(movementInfo.pos.GetOrientation());
- mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING);
+ mover->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Turning);
}
}
}
@@ -453,7 +453,7 @@ void WorldSession::HandleMovementOpcode(OpcodeClient opcode, MovementInfo& movem
if (opcode == CMSG_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 4ef08588c07..b3522d1a18d 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -163,10 +163,7 @@ void WorldSession::HandleGossipHelloOpcode(WorldPackets::NPC::Hello& packet)
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
unit->PauseMovement(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER));
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index 94c3c73147e..11db09e1013 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -120,6 +120,8 @@ void WorldSession::HandleUseItemOpcode(WorldPackets::Spells::UseItem& packet)
}
}
+ user->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::ItemUse);
+
SpellCastTargets targets(user, packet.Cast);
// Note: If script stop casting it must send appropriate data to client to prevent stuck item in gray state.
diff --git a/src/server/game/Server/Packets/SpellPackets.h b/src/server/game/Server/Packets/SpellPackets.h
index fa043ec305f..97775684a08 100644
--- a/src/server/game/Server/Packets/SpellPackets.h
+++ b/src/server/game/Server/Packets/SpellPackets.h
@@ -59,7 +59,7 @@ namespace WorldPackets
void Read() override;
int32 ChannelSpell = 0;
- int32 Reason = 0; // 40 = /run SpellStopCasting(), 16 = movement/AURA_INTERRUPT_FLAG_MOVE, 41 = turning/AURA_INTERRUPT_FLAG_TURNING
+ int32 Reason = 0; // 40 = /run SpellStopCasting(), 16 = movement/SpellAuraInterruptFlags::Moving, 41 = turning/SpellAuraInterruptFlags::Turning
// does not match SpellCastResult enum
};
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index e8b49494813..7f42e771a00 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1389,7 +1389,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();
}
@@ -1454,7 +1454,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();
}
@@ -1574,14 +1574,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);
}
@@ -1594,14 +1587,7 @@ void AuraEffect::HandlePhaseGroup(AuraApplication const* aurApp, uint8 mode, boo
Unit* target = aurApp->GetTarget();
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);
}
@@ -1686,6 +1672,9 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
if (!transformSpellInfo || !GetSpellInfo()->IsPositive())
target->SetDisplayId(modelid);
}
+
+ if (!shapeInfo->GetFlags().HasFlag(SpellShapeshiftFormFlags::Stance))
+ target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Shapeshifting, GetId());
}
else
{
@@ -2053,7 +2042,6 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
}
}
target->CombatStop();
- target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
// prevent interrupt message
if (GetCasterGUID() == target->GetGUID() && target->GetCurrentSpell(CURRENT_GENERIC_SPELL))
@@ -2103,10 +2091,7 @@ void AuraEffect::HandleModUnattackable(AuraApplication const* aurApp, uint8 mode
// call functions which may have additional effects after chainging state of unit
if (apply && (mode & AURA_EFFECT_HANDLE_REAL))
- {
target->CombatStop();
- target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
- }
}
void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3084,8 +3069,9 @@ void AuraEffect::HandleAuraModEffectImmunity(AuraApplication const* aurApp, uint
m_spellInfo->ApplyAllSpellImmunitiesTo(target, GetSpellEffectInfo(), 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()->HasAuraInterruptFlag(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION))
+ if (!apply && player && GetSpellInfo()->HasAuraInterruptFlag(SpellAuraInterruptFlags::StealthOrInvis))
{
if (player->InBattleground())
{
@@ -3136,13 +3122,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);
+ }
}
void AuraEffect::HandleAuraModDmgImmunity(AuraApplication const* aurApp, uint8 mode, bool apply) const
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 2458f505fde..281b603d931 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -2524,7 +2524,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);
+ m_caster->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Interacting);
unitTarget->ToCreature()->EngageWithTarget(m_caster);
}
}
@@ -2609,7 +2609,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask)
return SPELL_MISS_EVADE;
if (m_caster->_IsValidAttackTarget(unit, m_spellInfo))
- unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_HITBYSPELL);
+ unit->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::HostileActionReceived);
else if (m_caster->IsFriendlyTo(unit))
{
// for delayed spells ignore negative spells (after duel end) for friendly targets
@@ -3057,15 +3057,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);
- for (SpellEffectInfo const* effect : m_spellInfo->GetEffects())
- if (effect && effect->GetUsedTargetObjectType() == TARGET_OBJECT_TYPE_UNIT)
- {
- m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_SPELL_ATTACK);
- break;
- }
- }
+ m_caster->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Action);
m_caster->SetCurrentCastSpell(this);
SendSpellStart();
@@ -3387,6 +3379,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
@@ -3412,14 +3405,14 @@ void Spell::handle_immediate()
m_caster->ModSpellDurationTime(m_spellInfo, duration, this);
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);
}
}
@@ -5031,7 +5024,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
SpellEffectInfo const* effect = m_spellInfo->GetEffect(EFFECT_0);
if ((!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || (effect && effect->Effect != SPELL_EFFECT_STUCK)) &&
- (IsAutoRepeat() || m_spellInfo->HasAuraInterruptFlag(AURA_INTERRUPT_FLAG_NOT_SEATED)))
+ (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 30eb419f53f..cf26e4a7c05 100644
--- a/src/server/game/Spells/SpellDefines.h
+++ b/src/server/game/Spells/SpellDefines.h
@@ -19,6 +19,7 @@
#define TRINITY_SPELLDEFINES_H
#include "Define.h"
+#include "EnumFlag.h"
namespace UF
{
@@ -33,6 +34,86 @@ namespace WorldPackets
}
}
+enum SpellInterruptFlags : uint32
+{
+ SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, // why need this for instant?
+ SPELL_INTERRUPT_FLAG_PUSH_BACK = 0x02, // push back
+ SPELL_INTERRUPT_FLAG_UNK3 = 0x04, // any info?
+ SPELL_INTERRUPT_FLAG_INTERRUPT = 0x08, // interrupt
+ SPELL_INTERRUPT_FLAG_ABORT_ON_DMG = 0x10 // _complete_ interrupt on direct damage
+ //SPELL_INTERRUPT_UNK = 0x20 // unk, 564 of 727 spells having this spell start with "Glyph"
+};
+
+enum class SpellAuraInterruptFlags : uint32
+{
+ 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,
+
+ 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);
+
struct SpellCastVisual
{
uint32 SpellXSpellVisualID = 0;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index a27ff470485..bc784f91830 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -2969,7 +2969,7 @@ void Spell::EffectInterruptCast(SpellEffIndex effIndex)
|| (spell->getState() == SPELL_STATE_PREPARING && spell->GetCastTime() > 0.0f))
&& (curSpellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE)
&& ((i == CURRENT_GENERIC_SPELL && curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT)
- || (i == CURRENT_CHANNELED_SPELL && curSpellInfo->HasChannelInterruptFlag(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 aa8d5f513ea..f8cabac4d00 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -1213,8 +1213,10 @@ SpellInfo::SpellInfo(SpellNameEntry const* spellName, ::Difficulty difficulty, S
if (SpellInterruptsEntry const* _interrupt = data.Interrupts)
{
InterruptFlags = _interrupt->InterruptFlags;
- std::copy(std::begin(_interrupt->AuraInterruptFlags), std::end(_interrupt->AuraInterruptFlags), AuraInterruptFlags.begin());
- std::copy(std::begin(_interrupt->ChannelInterruptFlags), std::end(_interrupt->ChannelInterruptFlags), ChannelInterruptFlags.begin());
+ AuraInterruptFlags = SpellAuraInterruptFlags(_interrupt->AuraInterruptFlags[0]);
+ AuraInterruptFlags2 = SpellAuraInterruptFlags2(_interrupt->AuraInterruptFlags[1]);
+ ChannelInterruptFlags = SpellAuraInterruptFlags(_interrupt->ChannelInterruptFlags[0]);
+ ChannelInterruptFlags2 = SpellAuraInterruptFlags2(_interrupt->ChannelInterruptFlags[1]);
}
// SpellLevelsEntry
@@ -1360,7 +1362,7 @@ bool SpellInfo::HasTargetType(::Targets target) const
bool SpellInfo::HasAnyAuraInterruptFlag() const
{
- return std::find_if(AuraInterruptFlags.begin(), AuraInterruptFlags.end(), [](uint32 flag) { return flag != 0; }) != AuraInterruptFlags.end();
+ return AuraInterruptFlags != SpellAuraInterruptFlags::None || AuraInterruptFlags2 != SpellAuraInterruptFlags2::None;
}
bool SpellInfo::IsExplicitDiscovery() const
@@ -1633,7 +1635,7 @@ bool SpellInfo::IsChanneled() const
bool SpellInfo::IsMoveAllowedChannel() const
{
- return IsChanneled() && (HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING) || (!(ChannelInterruptFlags[0] & (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
@@ -2513,7 +2515,7 @@ void SpellInfo::_LoadSpellSpecific()
case SPELLFAMILY_GENERIC:
{
// Food / Drinks (mostly)
- if (HasAuraInterruptFlag(AURA_INTERRUPT_FLAG_NOT_SEATED))
+ if (HasAuraInterruptFlag(SpellAuraInterruptFlags::Standing))
{
bool food = false;
bool drink = false;
@@ -3486,6 +3488,9 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const* e
auraSpellInfo->Id != Id); // Don't remove self
});
}
+
+ if (apply && schoolImmunity & SPELL_SCHOOL_MASK_NORMAL)
+ target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::InvulnerabilityBuff);
}
if (uint32 mechanicImmunity = immuneInfo->MechanicImmuneMask)
@@ -3516,8 +3521,13 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const* e
}
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);
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index 5b129755826..f453b11cb76 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -23,6 +23,7 @@
#include "Util.h"
#include "Object.h"
#include "SpellAuraDefines.h"
+#include "SpellDefines.h"
#include <boost/container/flat_set.hpp>
#include <bitset>
@@ -208,75 +209,6 @@ enum SpellCustomAttributes
SPELL_ATTR0_CU_AURA_CANNOT_BE_SAVED = 0x01000000,
};
-enum SpellInterruptFlags : uint32
-{
- SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, // why need this for instant?
- SPELL_INTERRUPT_FLAG_PUSH_BACK = 0x02, // push back
- SPELL_INTERRUPT_FLAG_UNK3 = 0x04, // any info?
- SPELL_INTERRUPT_FLAG_INTERRUPT = 0x08, // interrupt
- SPELL_INTERRUPT_FLAG_ABORT_ON_DMG = 0x10 // _complete_ interrupt on direct damage
- //SPELL_INTERRUPT_UNK = 0x20 // unk, 564 of 727 spells having this spell start with "Glyph"
-};
-
-// See SpellAuraInterruptFlags for other values definitions
-enum SpellChannelInterruptFlags : uint32
-{
- CHANNEL_INTERRUPT_FLAG_INTERRUPT = 0x08, // interrupt
- CHANNEL_FLAG_DELAY = 0x4000
-};
-
-enum 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 jumping
- 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
-
- AURA_INTERRUPT_FLAG_NOT_VICTIM = (AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE | AURA_INTERRUPT_FLAG_DIRECT_DAMAGE)
-};
-
-enum SpellAuraInterruptFlags2 : uint32
-{
-};
-
-template <typename InterruptFlag>
-struct AuraInterruptFlagIndex {};
-
-template <>
-struct AuraInterruptFlagIndex<SpellAuraInterruptFlags>
-{
- static std::size_t constexpr value = 0;
-};
-
-template <>
-struct AuraInterruptFlagIndex<SpellAuraInterruptFlags2>
-{
- static std::size_t constexpr value = 1;
-};
-
uint32 GetTargetFlagMask(SpellTargetObjectTypes objType);
class TC_GAME_API SpellImplicitTargetInfo
@@ -483,8 +415,10 @@ class TC_GAME_API SpellInfo
uint32 StartRecoveryCategory = 0;
uint32 StartRecoveryTime = 0;
uint32 InterruptFlags = 0;
- std::array<uint32, MAX_SPELL_AURA_INTERRUPT_FLAGS> AuraInterruptFlags = {};
- std::array<uint32, MAX_SPELL_AURA_INTERRUPT_FLAGS> ChannelInterruptFlags = {};
+ EnumFlag<SpellAuraInterruptFlags> AuraInterruptFlags = SpellAuraInterruptFlags::None;
+ EnumFlag<SpellAuraInterruptFlags2> AuraInterruptFlags2 = SpellAuraInterruptFlags2::None;
+ EnumFlag<SpellAuraInterruptFlags> ChannelInterruptFlags = SpellAuraInterruptFlags::None;
+ EnumFlag<SpellAuraInterruptFlags2> ChannelInterruptFlags2 = SpellAuraInterruptFlags2::None;
uint32 ProcFlags = 0;
uint32 ProcChance = 0;
uint32 ProcCharges = 0;
@@ -565,10 +499,11 @@ class TC_GAME_API SpellInfo
bool HasAttribute(SpellCustomAttributes customAttribute) const { return !!(AttributesCu & customAttribute); }
bool HasAnyAuraInterruptFlag() const;
- bool HasAuraInterruptFlag(SpellAuraInterruptFlags flag) const { return (AuraInterruptFlags[AuraInterruptFlagIndex<SpellAuraInterruptFlags>::value] & flag) != 0; }
- bool HasAuraInterruptFlag(SpellAuraInterruptFlags2 flag) const { return (AuraInterruptFlags[AuraInterruptFlagIndex<SpellAuraInterruptFlags2>::value] & flag) != 0; }
+ bool HasAuraInterruptFlag(SpellAuraInterruptFlags flag) const { return AuraInterruptFlags.HasFlag(flag); }
+ bool HasAuraInterruptFlag(SpellAuraInterruptFlags2 flag) const { return AuraInterruptFlags2.HasFlag(flag); }
- bool HasChannelInterruptFlag(SpellChannelInterruptFlags flag) const { return (ChannelInterruptFlags[AuraInterruptFlagIndex<SpellAuraInterruptFlags>::value] & flag) != 0; }
+ bool HasChannelInterruptFlag(SpellAuraInterruptFlags flag) const { return ChannelInterruptFlags.HasFlag(flag); }
+ bool HasChannelInterruptFlag(SpellAuraInterruptFlags2 flag) const { return ChannelInterruptFlags2.HasFlag(flag); }
bool IsExplicitDiscovery() const;
bool IsLootCrafting() const;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 3b1d3a1f91b..78459cbf0d3 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -2828,10 +2828,10 @@ void SpellMgr::LoadSpellInfoServerside()
spellInfo.StartRecoveryCategory = fields[37].GetUInt32();
spellInfo.StartRecoveryTime = fields[38].GetUInt32();
spellInfo.InterruptFlags = fields[39].GetUInt32();
- spellInfo.AuraInterruptFlags[0] = fields[40].GetUInt32();
- spellInfo.AuraInterruptFlags[1] = fields[41].GetUInt32();
- spellInfo.ChannelInterruptFlags[0] = fields[42].GetUInt32();
- spellInfo.ChannelInterruptFlags[1] = fields[43].GetUInt32();
+ spellInfo.AuraInterruptFlags = SpellAuraInterruptFlags(fields[40].GetUInt32());
+ spellInfo.AuraInterruptFlags2 = SpellAuraInterruptFlags2(fields[41].GetUInt32());
+ spellInfo.ChannelInterruptFlags = SpellAuraInterruptFlags(fields[42].GetUInt32());
+ spellInfo.ChannelInterruptFlags2 = SpellAuraInterruptFlags2(fields[43].GetUInt32());
spellInfo.ProcFlags = fields[44].GetUInt32();
spellInfo.ProcChance = fields[45].GetUInt32();
spellInfo.ProcCharges = fields[46].GetUInt32();
@@ -3652,7 +3652,7 @@ void SpellMgr::LoadSpellInfoCorrections()
// Easter Lay Noblegarden Egg Aura - Interrupt flags copied from aura which this aura is linked with
ApplySpellFix({ 61719 }, [](SpellInfo* spellInfo)
{
- spellInfo->AuraInterruptFlags[0] = AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE;
+ spellInfo->AuraInterruptFlags = SpellAuraInterruptFlags::HostileActionReceived | SpellAuraInterruptFlags::Damage;
});
ApplySpellFix({
@@ -3727,7 +3727,7 @@ void SpellMgr::LoadSpellInfoCorrections()
// Test Ribbon Pole Channel
ApplySpellFix({ 29726 }, [](SpellInfo* spellInfo)
{
- spellInfo->InterruptFlags &= ~AURA_INTERRUPT_FLAG_CAST;
+ spellInfo->ChannelInterruptFlags &= ~SpellAuraInterruptFlags::Action;
});
// Sic'em
@@ -3870,7 +3870,8 @@ void SpellMgr::LoadSpellInfoCorrections()
// Spinning Up (Mimiron)
ApplySpellFix({ 63414 }, [](SpellInfo* spellInfo)
{
- spellInfo->ChannelInterruptFlags.fill(0);
+ spellInfo->ChannelInterruptFlags = SpellAuraInterruptFlags::None;
+ spellInfo->ChannelInterruptFlags2 = SpellAuraInterruptFlags2::None;
ApplySpellEffectFix(spellInfo, EFFECT_0, [](SpellEffectInfo* spellEffectInfo)
{
spellEffectInfo->TargetB = SpellImplicitTargetInfo(TARGET_UNIT_CASTER);
@@ -4318,7 +4319,7 @@ void SpellMgr::LoadSpellInfoCorrections()
// Threatening Gaze
ApplySpellFix({ 24314 }, [](SpellInfo* spellInfo)
{
- spellInfo->AuraInterruptFlags[0] |= AURA_INTERRUPT_FLAG_CAST | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_JUMP;
+ spellInfo->AuraInterruptFlags |= SpellAuraInterruptFlags::Action | SpellAuraInterruptFlags::Moving | SpellAuraInterruptFlags::Anim;
});
// Travel Form (dummy) - cannot be cast indoors.
@@ -4391,7 +4392,7 @@ void SpellMgr::LoadSpellInfoCorrections()
// Blaze of Glory
ApplySpellFix({ 99252 }, [](SpellInfo* spellInfo)
{
- spellInfo->AuraInterruptFlags[0] |= AURA_INTERRUPT_FLAG_CHANGE_MAP;
+ spellInfo->AuraInterruptFlags |= SpellAuraInterruptFlags::LeaveWorld;
});
// ENDOF FIRELANDS SPELLS