From 1feeb35a5016ab4071d5f1a52c713ea60b52c5db Mon Sep 17 00:00:00 2001 From: 3nei <63229870+3nei@users.noreply.github.com> Date: Fri, 4 Oct 2024 06:36:00 +0300 Subject: [PATCH] Core/Movement: Pet follow movement code improvements. (#43) * added some missing methods from TrinityCore Co-authored-by: 3nei <3nei@users.noreply.github.com> --- src/server/game/Entities/Unit/Unit.cpp | 16 ++++++++++ src/server/game/Entities/Unit/Unit.h | 2 ++ .../TargetedMovementGenerator.cpp | 29 ++----------------- src/server/game/Spells/SpellInfo.cpp | 5 ++++ src/server/game/Spells/SpellInfo.h | 1 + 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 74723cd6..84894f5b 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -4283,6 +4283,22 @@ int32 Unit::GetCurrentSpellCastTime(uint32 spell_id) const return 0; } +bool Unit::IsMovementPreventedByCasting() const +{ + // can always move when not casting + if (!HasUnitState(UNIT_STATE_CASTING)) + return false; + + // channeled spells during channel stage (after the initial cast timer) allow movement with a specific spell attribute + if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) + if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive()) + if (spell->GetSpellInfo()->IsMoveAllowedChannel()) + return false; + + // prohibit movement for all other spell casts + return true; +} + bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const { return IsWithinDistInMap(target, distance) && HasInArc(arc, target); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 62320bb3..f97f12db 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1551,6 +1551,7 @@ class Unit : public WorldObject bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);} bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);} + bool IsHovering() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_HOVER);} bool SetWalk(bool enable); bool SetDisableGravity(bool disable, bool isPlayer = false); bool SetFall(bool enable, bool isPlayer = false); @@ -1894,6 +1895,7 @@ class Unit : public WorldObject Spell* GetCurrentSpell(uint32 spellType) const { return m_currentSpells[spellType]; } Spell* FindCurrentSpellBySpellId(uint32 spell_id) const; int32 GetCurrentSpellCastTime(uint32 spell_id) const; + bool IsMovementPreventedByCasting() const; SpellInfo const* GetCastSpellInfo(SpellInfo const* spellInfo) const; void SendSpellCreateVisual(SpellInfo const* spellInfo, Position const* position = nullptr, Unit* target = nullptr, uint32 type = 0, uint32 visualId = 0); void CancelSpellVisualKit(int32 spellVisualKitID); diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 7eb8d13e..5dd432f9 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -569,30 +569,6 @@ static Position const PredictPosition(Unit* target) return pos; } -bool IsMovementPreventedByCasting(Creature* owner) -{ - Spell* spell = owner->GetCurrentSpell(CURRENT_CHANNELED_SPELL); - // first check if currently a movement allowed channel is active and we're not casting - if (spell && spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive() && - (spell->GetSpellInfo() && spell->GetSpellInfo()->IsChanneled() && spell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_USABLE_WHILE_MOVING)) - ) - { - return false; - } - - /*if (owner->HasSpellFocus()) - { - return true; - }*/ - - if (owner->HasUnitState(UNIT_STATE_CASTING)) - { - return true; - } - - return false; -} - template bool FollowMovementGenerator::DoUpdate(T& owner, uint32 time_diff) { @@ -606,7 +582,7 @@ bool FollowMovementGenerator::DoUpdate(T& owner, uint32 time_diff) Unit* target = this->i_target.getTarget(); // the owner might be unable to move (rooted or casting), or we have lost the target, pause movement - if (owner.HasUnitState(UNIT_STATE_NOT_MOVE) || (cOwner && IsMovementPreventedByCasting(owner.ToCreature()))) + if (owner.HasUnitState(UNIT_STATE_NOT_MOVE) || (cOwner && owner.IsMovementPreventedByCasting())) { i_path = nullptr; owner.StopMoving(); @@ -676,8 +652,7 @@ bool FollowMovementGenerator::DoUpdate(T& owner, uint32 time_diff) float x, y, z; targetPosition.GetPosition(x, y, z); - //if (owner->IsHovering()) - if (owner.m_movementInfo.HasMovementFlag(MOVEMENTFLAG_HOVER)) // alt: owner.isHover() + if (owner.IsHovering()) owner.UpdateAllowedPositionZ(x, y, z); bool success = i_path->CalculatePath(x, y, z, forceDest); diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 67461bf6..bba34e8b 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1854,6 +1854,11 @@ bool SpellInfo::IsChanneled() const return (GetMisc()->MiscData.Attributes[1] & (SPELL_ATTR1_CHANNELED_1 | SPELL_ATTR1_CHANNELED_2)) != 0; } +bool SpellInfo::IsMoveAllowedChannel() const +{ + return IsChanneled() && HasAttribute(SPELL_ATTR5_USABLE_WHILE_MOVING); +} + bool SpellInfo::IsBreakingStealth() const { return !HasAttribute(SPELL_ATTR1_NOT_BREAK_STEALTH); diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 07f7fdf9..fb1c202c 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -758,6 +758,7 @@ class SpellInfo bool IsPositive() const; bool IsPositiveEffect(uint8 effIndex, bool caster = false) const; bool IsChanneled() const; + bool IsMoveAllowedChannel() const; bool IsBreakingStealth() const; bool IsRangedWeaponSpell() const; bool IsRangedSpell() const;