diff options
-rw-r--r-- | src/server/game/AI/CoreAI/UnitAI.cpp | 3 | ||||
-rw-r--r-- | src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp | 1 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Structure.h | 4 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 57 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 65 | ||||
-rw-r--r-- | src/server/game/Handlers/MovementHandler.cpp | 22 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 19 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.h | 109 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 8 |
16 files changed, 174 insertions, 126 deletions
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp index fc0a0c117f7..a4ee3025130 100644 --- a/src/server/game/AI/CoreAI/UnitAI.cpp +++ b/src/server/game/AI/CoreAI/UnitAI.cpp @@ -150,8 +150,7 @@ void UnitAI::DoCast(uint32 spellId) float range = spellInfo->GetMaxRange(false); DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId); - if (!(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM) - && targetSelector(me->GetVictim())) + if (!spellInfo->HasAuraInterruptFlag(AURA_INTERRUPT_FLAG_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 6049e877156..9675186a2f4 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp @@ -26,6 +26,7 @@ #include "Map.h" #include "Player.h" #include "Random.h" +#include "SpellInfo.h" #include "Util.h" #include "WorldSession.h" #include "WorldStatePackets.h" diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp index d36c9d8b575..4ccd3eaee95 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp @@ -28,6 +28,7 @@ #include "ObjectAccessor.h" #include "Player.h" #include "Random.h" +#include "SpellInfo.h" #include "Util.h" #include "WorldStatePackets.h" diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp index 1f160b19653..b627b1b22a6 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp @@ -27,6 +27,7 @@ #include "Object.h" #include "ObjectAccessor.h" #include "Player.h" +#include "SpellInfo.h" #include "WorldPacket.h" #include "WorldStatePackets.h" diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index ba6bf40090a..72d92e975fa 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -2459,8 +2459,8 @@ struct SpellInterruptsEntry { uint32 ID; uint32 SpellID; - uint32 AuraInterruptFlags[2]; - uint32 ChannelInterruptFlags[2]; + uint32 AuraInterruptFlags[MAX_SPELL_AURA_INTERRUPT_FLAGS]; + uint32 ChannelInterruptFlags[MAX_SPELL_AURA_INTERRUPT_FLAGS]; uint16 InterruptFlags; uint8 DifficultyID; }; diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index ecade307f26..db91142e146 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -847,6 +847,8 @@ enum SpellCategoryFlags #define MAX_SPELL_EFFECTS 32 #define MAX_EFFECT_MASK 0xFFFFFFFF +#define MAX_SPELL_AURA_INTERRUPT_FLAGS 2 + enum SpellItemEnchantmentFlags { ENCHANTMENT_CAN_SOULBOUND = 0x01, diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 6915b68061b..35f768c8338 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1613,7 +1613,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(AURA_INTERRUPT_FLAG_CHANGE_MAP | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING)); if (!GetSession()->PlayerLogout() && !(options & TELE_TO_SEAMLESS)) { diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index a2a7d5b1697..7430ea90499 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -319,7 +319,7 @@ Unit::Unit(bool isWorldObject) : m_auraUpdateIterator = m_ownedAuras.end(); - m_interruptMask = 0; + m_interruptMask.fill(0); m_transform = 0; m_canModifyStats = false; @@ -644,13 +644,15 @@ void Unit::RemoveVisibleAura(AuraApplication* aurApp) 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.fill(0); + 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]; if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) if (spell->getState() == SPELL_STATE_CASTING) - m_interruptMask |= spell->m_spellInfo->ChannelInterruptFlags; + for (std::size_t i = 0; i < m_interruptMask.size(); ++i) + m_interruptMask[i] |= spell->m_spellInfo->ChannelInterruptFlags[i]; } bool Unit::HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint32 familyFlags) const @@ -670,7 +672,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(AURA_INTERRUPT_FLAG_TAKE_DAMAGE)) return true; return false; } @@ -912,12 +914,8 @@ 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)) - spell->DelayedChannel(); - } + if (spell->getState() == SPELL_STATE_CASTING && spell->m_spellInfo->HasChannelInterruptFlag(CHANNEL_FLAG_DELAY) && damagetype != DOT) + spell->DelayedChannel(); } } @@ -3241,7 +3239,7 @@ AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint32 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); @@ -3285,7 +3283,7 @@ void Unit::_ApplyAura(AuraApplication * aurApp, uint32 effMask) return; // Sitdown on apply aura req seated - if (aura->GetSpellInfo()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED && !IsSitState()) + if (aura->GetSpellInfo()->HasAuraInterruptFlag(AURA_INTERRUPT_FLAG_NOT_SEATED) && !IsSitState()) SetStandState(UNIT_STAND_STATE_SIT); Unit* caster = aura->GetCaster(); @@ -3326,7 +3324,7 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMo // 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(); @@ -3904,9 +3902,10 @@ void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase, bool phaseid) } } -void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except) +template <typename InterruptFlags> +void Unit::RemoveAurasWithInterruptFlags(InterruptFlags flag, uint32 except) { - if (!(m_interruptMask & flag)) + if (!(m_interruptMask[AuraInterruptFlagIndex<InterruptFlags>::value] & flag)) return; // interrupt auras @@ -3914,7 +3913,7 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except) { Aura* aura = (*iter)->GetBase(); ++iter; - if ((aura->GetSpellInfo()->AuraInterruptFlags & flag) && (!except || aura->GetId() != except) + 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()))) { uint32 removedAuras = m_removedAurasCount; @@ -3927,14 +3926,17 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except) // 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 + && (spell->GetSpellInfo()->ChannelInterruptFlags[AuraInterruptFlagIndex<InterruptFlags>::value] & flag) + && spell->GetSpellInfo()->Id != except && !(flag & AURA_INTERRUPT_FLAG_MOVE && HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, spell->GetSpellInfo()))) InterruptNonMeleeSpells(false); UpdateInterruptMask(); } +template TC_GAME_API void Unit::RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags flag, uint32 except); +template TC_GAME_API void Unit::RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags2 flag, uint32 except); + void Unit::RemoveAurasWithFamily(SpellFamilyNames family, flag128 const& familyFlag, ObjectGuid casterGUID) { for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();) @@ -4374,18 +4376,23 @@ bool Unit::HasAuraTypeWithValue(AuraType auratype, int32 value) const return false; } -bool Unit::HasNegativeAuraWithInterruptFlag(uint32 flag, ObjectGuid guid) const +template <typename InterruptFlags> +bool Unit::HasNegativeAuraWithInterruptFlag(InterruptFlags flag, ObjectGuid guid) const { - if (!(m_interruptMask & flag)) + if (!(m_interruptMask[AuraInterruptFlagIndex<InterruptFlags>::value] & 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()->AuraInterruptFlags[AuraInterruptFlagIndex<InterruptFlags>::value] & flag && + (!guid || (*iter)->GetBase()->GetCasterGUID() == guid)) return true; - } + return false; } +template TC_GAME_API bool Unit::HasNegativeAuraWithInterruptFlag(SpellAuraInterruptFlags flag, ObjectGuid guid) const; +template TC_GAME_API bool Unit::HasNegativeAuraWithInterruptFlag(SpellAuraInterruptFlags2 flag, ObjectGuid guid) const; + bool Unit::HasNegativeAuraWithAttribute(uint32 flag, ObjectGuid guid) const { for (AuraApplicationMap::const_iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end(); ++iter) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 59bac640af3..a37081a8153 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -38,56 +38,6 @@ #define ARTIFACTS_ALL_WEAPONS_GENERAL_WEAPON_EQUIPPED_PASSIVE 197886 #define SPELL_DH_DOUBLE_JUMP 196055 -enum SpellInterruptFlags -{ - 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 -{ - 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 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 - - AURA_INTERRUPT_FLAG_NOT_VICTIM = (AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE | AURA_INTERRUPT_FLAG_DIRECT_DAMAGE) -}; - enum SpellModOp : uint8 { SPELLMOD_DAMAGE = 0, @@ -1489,7 +1439,8 @@ class TC_GAME_API Unit : public WorldObject void RemoveAurasDueToItemSpell(uint32 spellId, ObjectGuid castItemGuid); void RemoveAurasByType(AuraType auraType, ObjectGuid casterGUID = ObjectGuid::Empty, Aura* except = NULL, bool negative = true, bool positive = true); void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0, bool phaseid = false); - void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except = 0); + template <typename InterruptFlags> + void RemoveAurasWithInterruptFlags(InterruptFlags flag, uint32 except = 0); void RemoveAurasWithAttribute(uint32 flags); void RemoveAurasWithFamily(SpellFamilyNames family, flag128 const& familyFlag, ObjectGuid casterGUID); void RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveMode removemode = AURA_REMOVE_BY_DEFAULT, uint32 except = 0); @@ -1533,7 +1484,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 <typename InterruptFlags> + bool HasNegativeAuraWithInterruptFlag(InterruptFlags flag, ObjectGuid guid = ObjectGuid::Empty) const; bool HasNegativeAuraWithAttribute(uint32 flag, ObjectGuid guid = ObjectGuid::Empty) const; bool HasAuraWithMechanic(uint32 mechanicMask) const; @@ -1690,8 +1642,11 @@ class TC_GAME_API Unit : public WorldObject void SetVisibleAuraUpdate(AuraApplication* aurApp) { m_visibleAurasToUpdate.insert(aurApp); } void RemoveVisibleAura(AuraApplication* aurApp); - uint32 GetInterruptMask() const { return m_interruptMask; } - void AddInterruptMask(uint32 mask) { m_interruptMask |= mask; } + void AddInterruptMask(std::array<uint32, 2> const& mask) + { + for (std::size_t i = 0; i < m_interruptMask.size(); ++i) + m_interruptMask[i] |= mask[i]; + } void UpdateInterruptMask(); uint32 GetDisplayId() const { return GetUInt32Value(UNIT_FIELD_DISPLAYID); } @@ -1980,7 +1935,7 @@ 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 - uint32 m_interruptMask; + std::array<uint32, 2> m_interruptMask; float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; float m_weaponDamage[MAX_ATTACK][2]; diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 03cca539025..11df92f78b0 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -16,23 +16,23 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Common.h" -#include "WorldPacket.h" #include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" +#include "Battleground.h" +#include "Common.h" #include "Corpse.h" -#include "Player.h" #include "Garrison.h" -#include "MapManager.h" -#include "Transport.h" -#include "Battleground.h" -#include "WaypointMovementGenerator.h" +#include "InstancePackets.h" #include "InstanceSaveMgr.h" +#include "Log.h" +#include "MapManager.h" +#include "MovementPackets.h" #include "ObjectMgr.h" +#include "Opcodes.h" +#include "Player.h" +#include "SpellInfo.h" +#include "Transport.h" #include "Vehicle.h" -#include "InstancePackets.h" -#include "MovementPackets.h" +#include "WaypointMovementGenerator.h" #define MOVEMENT_PACKET_TIME_DELAY 0 diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 08a712c326a..076452542ff 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -3412,7 +3412,7 @@ void AuraEffect::HandleAuraModEffectImmunity(AuraApplication const* aurApp, uint // when removing flag aura, handle flag drop Player* player = target->ToPlayer(); - if (!apply && player && (GetSpellInfo()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION)) + if (!apply && player && GetSpellInfo()->HasAuraInterruptFlag(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION)) { if (player->InBattleground()) { diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 2bbe805b5ec..65899f518d8 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4938,7 +4938,7 @@ SpellCastResult Spell::CheckCast(bool strict) // skip stuck spell to allow use it in falling case and apply spell limitations at movement SpellEffectInfo const* effect = GetEffect(EFFECT_0); if ((!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || (effect && effect->Effect != SPELL_EFFECT_STUCK)) && - (IsAutoRepeat() || (m_spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) != 0)) + (IsAutoRepeat() || m_spellInfo->HasAuraInterruptFlag(AURA_INTERRUPT_FLAG_NOT_SEATED))) return SPELL_FAILED_MOVING; } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index b37e632f452..2c0a91c4277 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3078,7 +3078,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->ChannelInterruptFlags & CHANNEL_INTERRUPT_FLAG_INTERRUPT))) + || (i == CURRENT_CHANNELED_SPELL && curSpellInfo->HasChannelInterruptFlag(CHANNEL_INTERRUPT_FLAG_INTERRUPT)))) { if (m_originalCaster) { diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 1de54909348..bda28f6f3ef 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1103,11 +1103,18 @@ SpellInfo::SpellInfo(SpellInfoLoadHelper const& data, SpellEffectEntryMap const& EquippedItemInventoryTypeMask = _equipped ? _equipped->EquippedItemInventoryTypeMask : -1; // SpellInterruptsEntry - SpellInterruptsEntry const* _interrupt = data.Interrupts; - InterruptFlags = _interrupt ? _interrupt->InterruptFlags : 0; - // TODO: 6.x these flags have 2 parts - AuraInterruptFlags = _interrupt ? _interrupt->AuraInterruptFlags[0] : 0; - ChannelInterruptFlags = _interrupt ? _interrupt->ChannelInterruptFlags[0] : 0; + 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()); + } + else + { + InterruptFlags = 0; + AuraInterruptFlags.fill(0); + ChannelInterruptFlags.fill(0); + } // SpellLevelsEntry SpellLevelsEntry const* _levels = data.Levels; @@ -2294,7 +2301,7 @@ void SpellInfo::_LoadSpellSpecific() case SPELLFAMILY_GENERIC: { // Food / Drinks (mostly) - if (AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) + if (HasAuraInterruptFlag(AURA_INTERRUPT_FLAG_NOT_SEATED)) { bool food = false; bool drink = false; diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 78e262b6bd8..2d2d93be773 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -198,6 +198,75 @@ enum SpellCustomAttributes SPELL_ATTR0_CU_NEGATIVE = SPELL_ATTR0_CU_NEGATIVE_EFF0 | SPELL_ATTR0_CU_NEGATIVE_EFF1 | SPELL_ATTR0_CU_NEGATIVE_EFF2 }; +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 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 + + 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 @@ -379,8 +448,8 @@ class TC_GAME_API SpellInfo uint32 StartRecoveryCategory; uint32 StartRecoveryTime; uint32 InterruptFlags; - uint32 AuraInterruptFlags; - uint32 ChannelInterruptFlags; + std::array<uint32, MAX_SPELL_AURA_INTERRUPT_FLAGS> AuraInterruptFlags; + std::array<uint32, MAX_SPELL_AURA_INTERRUPT_FLAGS> ChannelInterruptFlags; uint32 ProcFlags; uint32 ProcChance; uint32 ProcCharges; @@ -441,21 +510,27 @@ class TC_GAME_API SpellInfo bool HasAreaAuraEffect(uint32 difficulty) const; bool HasAreaAuraEffect() const; - inline bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); } - inline bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); } - inline bool HasAttribute(SpellAttr2 attribute) const { return !!(AttributesEx2 & attribute); } - inline bool HasAttribute(SpellAttr3 attribute) const { return !!(AttributesEx3 & attribute); } - inline bool HasAttribute(SpellAttr4 attribute) const { return !!(AttributesEx4 & attribute); } - inline bool HasAttribute(SpellAttr5 attribute) const { return !!(AttributesEx5 & attribute); } - inline bool HasAttribute(SpellAttr6 attribute) const { return !!(AttributesEx6 & attribute); } - inline bool HasAttribute(SpellAttr7 attribute) const { return !!(AttributesEx7 & attribute); } - inline bool HasAttribute(SpellAttr8 attribute) const { return !!(AttributesEx8 & attribute); } - inline bool HasAttribute(SpellAttr9 attribute) const { return !!(AttributesEx9 & attribute); } - inline bool HasAttribute(SpellAttr10 attribute) const { return !!(AttributesEx10 & attribute); } - inline bool HasAttribute(SpellAttr11 attribute) const { return !!(AttributesEx11 & attribute); } - inline bool HasAttribute(SpellAttr12 attribute) const { return !!(AttributesEx12 & attribute); } - inline bool HasAttribute(SpellAttr13 attribute) const { return !!(AttributesEx13 & attribute); } - inline bool HasAttribute(SpellCustomAttributes customAttribute) const { return !!(AttributesCu & customAttribute); } + bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); } + bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); } + bool HasAttribute(SpellAttr2 attribute) const { return !!(AttributesEx2 & attribute); } + bool HasAttribute(SpellAttr3 attribute) const { return !!(AttributesEx3 & attribute); } + bool HasAttribute(SpellAttr4 attribute) const { return !!(AttributesEx4 & attribute); } + bool HasAttribute(SpellAttr5 attribute) const { return !!(AttributesEx5 & attribute); } + bool HasAttribute(SpellAttr6 attribute) const { return !!(AttributesEx6 & attribute); } + bool HasAttribute(SpellAttr7 attribute) const { return !!(AttributesEx7 & attribute); } + bool HasAttribute(SpellAttr8 attribute) const { return !!(AttributesEx8 & attribute); } + bool HasAttribute(SpellAttr9 attribute) const { return !!(AttributesEx9 & attribute); } + bool HasAttribute(SpellAttr10 attribute) const { return !!(AttributesEx10 & attribute); } + bool HasAttribute(SpellAttr11 attribute) const { return !!(AttributesEx11 & attribute); } + bool HasAttribute(SpellAttr12 attribute) const { return !!(AttributesEx12 & attribute); } + bool HasAttribute(SpellAttr13 attribute) const { return !!(AttributesEx13 & attribute); } + bool HasAttribute(SpellCustomAttributes customAttribute) const { return !!(AttributesCu & customAttribute); } + + bool HasAnyAuraInterruptFlag() const { return std::find_if(AuraInterruptFlags.begin(), AuraInterruptFlags.end(), [](uint32 flag) { return flag != 0; }) != AuraInterruptFlags.end(); } + 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 HasChannelInterruptFlag(SpellChannelInterruptFlags flag) const { return (ChannelInterruptFlags[AuraInterruptFlagIndex<SpellAuraInterruptFlags>::value] & flag) != 0; } bool IsExplicitDiscovery() const; bool IsLootCrafting() const; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index ef9d7e6862e..302416e4885 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -2759,7 +2759,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 = AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE; + spellInfo->AuraInterruptFlags[0] = AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE; }); ApplySpellFix({ @@ -2924,7 +2924,7 @@ void SpellMgr::LoadSpellInfoCorrections() ApplySpellFix({ 63414 }, [](SpellInfo* spellInfo) { const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); - spellInfo->ChannelInterruptFlags = 0; + spellInfo->ChannelInterruptFlags.fill(0); }); // Rocket Strike (Mimiron) @@ -3292,7 +3292,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[0] |= AURA_INTERRUPT_FLAG_CAST | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_JUMP; }); // Tree of Life (Passive) @@ -3353,7 +3353,7 @@ void SpellMgr::LoadSpellInfoCorrections() // Blaze of Glory ApplySpellFix({ 99252 }, [](SpellInfo* spellInfo) { - spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CHANGE_MAP; + spellInfo->AuraInterruptFlags[0] |= AURA_INTERRUPT_FLAG_CHANGE_MAP; }); // ENDOF FIRELANDS SPELLS |