diff options
13 files changed, 170 insertions, 123 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 6827bb29cd4..0864a9e6260 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -390,7 +390,7 @@ bool Creature::IsFormationLeader() const return m_formation->IsLeader(this); } -void Creature::SignalFormationMovement(Position const& destination, uint32 id/* = 0*/, uint32 moveType/* = 0*/, bool orientation/* = false*/) +void Creature::SignalFormationMovement() { if (!m_formation) return; @@ -398,7 +398,7 @@ void Creature::SignalFormationMovement(Position const& destination, uint32 id/* if (!m_formation->IsLeader(this)) return; - m_formation->LeaderMoveTo(destination, id, moveType, orientation); + m_formation->LeaderStartedMoving(); } bool Creature::IsFormationLeaderMoveAllowed() const diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index aa34ad2edfc..f3b084d52dd 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -322,7 +322,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma CreatureGroup* GetFormation() { return m_formation; } void SetFormation(CreatureGroup* formation) { m_formation = formation; } bool IsFormationLeader() const; - void SignalFormationMovement(Position const& destination, uint32 id = 0, uint32 moveType = 0, bool orientation = false); + void SignalFormationMovement(); bool IsFormationLeaderMoveAllowed() const; void SetDisableReputationGain(bool disable) { DisableReputationGain = disable; } diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index e54e3f33ec6..5b0e76dc084 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -23,6 +23,7 @@ #include "Log.h" #include "Map.h" #include "MotionMaster.h" +#include "MovementGenerator.h" #include "ObjectMgr.h" #define MAX_DESYNC 5.0f @@ -275,51 +276,23 @@ void CreatureGroup::FormationReset(bool dismiss) _formed = !dismiss; } -void CreatureGroup::LeaderMoveTo(Position const& destination, uint32 id /*= 0*/, uint32 moveType /*= 0*/, bool orientation /*= false*/) +void CreatureGroup::LeaderStartedMoving() { - //! To do: This should probably get its own movement generator or use WaypointMovementGenerator. - //! If the leader's path is known, member's path can be plotted as well using formation offsets. if (!_leader) return; - Position pos(destination); - float pathangle = std::atan2(_leader->GetPositionY() - pos.GetPositionY(), _leader->GetPositionX() - pos.GetPositionX()); - for (auto const& pair : _members) { Creature* member = pair.first; if (member == _leader || !member->IsAlive() || member->IsEngaged() || !(pair.second->GroupAI & FLAG_IDLE_IN_FORMATION)) continue; - if (pair.second->LeaderWaypointIDs[0]) - { - for (uint8 i = 0; i < 2; ++i) - { - if (_leader->GetCurrentWaypointInfo().first == pair.second->LeaderWaypointIDs[i]) - { - pair.second->FollowAngle = float(M_PI) * 2.f - pair.second->FollowAngle; - break; - } - } - } - - float angle = pair.second->FollowAngle; + float angle = pair.second->FollowAngle + float(M_PI); // for some reason, someone thought it was a great idea to invert relativ angles... float dist = pair.second->FollowDist; - float dx = pos.GetPositionX() + std::cos(angle + pathangle) * dist; - float dy = pos.GetPositionY() + std::sin(angle + pathangle) * dist; - float dz = pos.GetPositionZ(); - - Trinity::NormalizeMapCoord(dx); - Trinity::NormalizeMapCoord(dy); - - if (!member->IsFlying()) - member->UpdateGroundPositionZ(dx, dy, dz); - - member->SetHomePosition(dx, dy, dz, pathangle); - - Position point(dx, dy, dz, destination.GetOrientation()); - member->GetMotionMaster()->MoveFormation(id, point, moveType, !member->IsWithinDist(_leader, dist + MAX_DESYNC), orientation); + MovementGenerator const* moveGen = member->GetMotionMaster()->GetMovementGenerator([](MovementGenerator const* movement)->bool { return movement->GetMovementGeneratorType() == FORMATION_MOTION_TYPE; }, MOTION_SLOT_DEFAULT); + if (!moveGen) + member->GetMotionMaster()->MoveFormation(_leader, dist, angle, pair.second->LeaderWaypointIDs[0], pair.second->LeaderWaypointIDs[1]); } } diff --git a/src/server/game/Entities/Creature/CreatureGroups.h b/src/server/game/Entities/Creature/CreatureGroups.h index 2b4924774ec..748df579251 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.h +++ b/src/server/game/Entities/Creature/CreatureGroups.h @@ -92,7 +92,7 @@ class TC_GAME_API CreatureGroup void RemoveMember(Creature* member); void FormationReset(bool dismiss); - void LeaderMoveTo(Position const& destination, uint32 id = 0, uint32 moveType = 0, bool orientation = false); + void LeaderStartedMoving(); void MemberEngagingTarget(Creature* member, Unit* target); bool CanLeaderStartMoving() const; }; diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 3b21d0b4dec..d77ce6e9a73 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -1068,12 +1068,12 @@ void MotionMaster::MoveRotate(uint32 id, uint32 time, RotateDirection direction) Add(new RotateMovementGenerator(id, time, direction)); } -void MotionMaster::MoveFormation(uint32 id, Position destination, uint32 moveType, bool forceRun /*= false*/, bool forceOrientation /*= false*/) +void MotionMaster::MoveFormation(Unit* leader, float range, float angle, uint32 point1, uint32 point2) { - if (_owner->GetTypeId() == TYPEID_UNIT) + if (_owner->GetTypeId() == TYPEID_UNIT && leader) { - TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveFormation: '%s', targeted point Id: %u (X: %f, Y: %f, Z: %f)", _owner->GetGUID().ToString().c_str(), id, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ()); - Add(new FormationMovementGenerator(id, destination, moveType, forceRun, forceOrientation)); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveFormation: '%s', started to move in a formation with leader %s", _owner->GetGUID().ToString().c_str(), leader->GetGUID().ToString().c_str()); + Add(new FormationMovementGenerator(leader, range, angle, point1, point2), MOTION_SLOT_DEFAULT); } } diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index a72a5d70079..830d6ca8628 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -192,7 +192,7 @@ class TC_GAME_API MotionMaster void MovePath(uint32 pathId, bool repeatable); void MovePath(WaypointPath& path, bool repeatable); void MoveRotate(uint32 id, uint32 time, RotateDirection direction); - void MoveFormation(uint32 id, Position destination, uint32 moveType, bool forceRun = false, bool forceOrientation = false); + void MoveFormation(Unit* leader, float range, float angle, uint32 point1, uint32 point2); void LaunchMoveSpline(Movement::MoveSplineInit&& init, uint32 id = 0, MovementGeneratorPriority priority = MOTION_PRIORITY_NORMAL, MovementGeneratorType type = EFFECT_MOTION_TYPE); private: diff --git a/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.cpp index cebfc8bc449..9bc79afcee0 100644 --- a/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.cpp @@ -18,11 +18,14 @@ #include "FormationMovementGenerator.h" #include "Creature.h" #include "CreatureAI.h" +#include "CreatureGroups.h" +#include "G3DPosition.hpp" #include "MovementDefines.h" #include "MoveSpline.h" #include "MoveSplineInit.h" -FormationMovementGenerator::FormationMovementGenerator(uint32 id, Position destination, uint32 moveType, bool run, bool orientation) : _movementId(id), _destination(destination), _moveType(moveType), _run(run), _orientation(orientation) +FormationMovementGenerator::FormationMovementGenerator(Unit* leader, float range, float angle, uint32 point1, uint32 point2) : AbstractFollower(ASSERT_NOTNULL(leader)), + _range(range), _angle(angle), _point1(point1), _point2(point2), _lastLeaderSplineID(0), _hasPredictedDestination(false) { Mode = MOTION_MODE_DEFAULT; Priority = MOTION_PRIORITY_NORMAL; @@ -47,33 +50,7 @@ void FormationMovementGenerator::DoInitialize(Creature* owner) return; } - owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); - - Movement::MoveSplineInit init(owner); - init.MoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ()); - if (_orientation) - init.SetFacing(_destination.GetOrientation()); - - switch (_moveType) - { - case 2: // WAYPOINT_MOVE_TYPE_LAND - init.SetAnimation(Movement::ToGround); - break; - case 3: // WAYPOINT_MOVE_TYPE_TAKEOFF - init.SetAnimation(Movement::ToFly); - break; - case 1: // WAYPOINT_MOVE_TYPE_RUN - init.SetWalk(false); - break; - case 0: // WAYPOINT_MOVE_TYPE_WALK - init.SetWalk(true); - break; - } - - if (_run) - init.SetWalk(false); - - init.Launch(); + _nextMoveTimer.Reset(0); } void FormationMovementGenerator::DoReset(Creature* owner) @@ -83,59 +60,154 @@ void FormationMovementGenerator::DoReset(Creature* owner) DoInitialize(owner); } -bool FormationMovementGenerator::DoUpdate(Creature* owner, uint32 /*diff*/) +bool FormationMovementGenerator::DoUpdate(Creature* owner, uint32 diff) { - if (!owner) + Unit* target = GetTarget(); + + if (!owner || !target) return false; + // Owner cannot move. Reset all fields and wait for next action if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); owner->StopMoving(); return true; } - if ((HasFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED) && owner->movespline->Finalized()) || (HasFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING) && !owner->movespline->Finalized())) + // Leader has stopped moving, so do we as well + if (target->movespline->Finalized() && target->movespline->GetId() == _lastLeaderSplineID && _hasPredictedDestination) { - RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED | MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING); + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + owner->StopMoving(); + _nextMoveTimer.Reset(0); + _hasPredictedDestination = false; + return true; + } - owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); + // Update home position + owner->SetHomePosition(owner->GetPosition()); + if (HasFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED)) + RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); - Movement::MoveSplineInit init(owner); - init.MoveTo(_destination.GetPositionX(), _destination.GetPositionY(), _destination.GetPositionZ()); - if (_orientation) - init.SetFacing(_destination.GetOrientation()); + // Leader has stopped moving, so do we as well + if (owner->HasUnitState(UNIT_STATE_ROAMING_MOVE) && _hasPredictedDestination && target->movespline->Finalized() && target->movespline->GetId() == _lastLeaderSplineID) + { + owner->StopMoving(); + _nextMoveTimer.Reset(0); + _hasPredictedDestination = false; + return true; + } - switch (_moveType) + // Formation leader has launched a new spline, launch a new one for our member as well + // This action does not reset the regular movement launch cycle interval + if (!target->movespline->Finalized() && target->movespline->GetId() != _lastLeaderSplineID) + { + // Update formation angle + if (_point1 && target->GetTypeId() == TYPEID_UNIT) { - case 2: // WAYPOINT_MOVE_TYPE_LAND - init.SetAnimation(Movement::ToGround); - break; - case 3: // WAYPOINT_MOVE_TYPE_TAKEOFF - init.SetAnimation(Movement::ToFly); - break; - case 1: // WAYPOINT_MOVE_TYPE_RUN - init.SetWalk(false); - break; - case 0: // WAYPOINT_MOVE_TYPE_WALK - init.SetWalk(true); - break; + if (CreatureGroup* formation = target->ToCreature()->GetFormation()) + { + if (Creature* leader = formation->GetLeader()) + { + uint8 currentWaypoint = leader->GetCurrentWaypointInfo().first; + if (currentWaypoint == _point1 || currentWaypoint == _point2) + _angle = float(M_PI) * 2 - _angle; + } + } } - if (_run) - init.SetWalk(false); - init.Launch(); + LaunchMovement(owner, target); + _lastLeaderSplineID = target->movespline->GetId(); + return true; } - if (owner->movespline->Finalized()) + _nextMoveTimer.Update(diff); + if (_nextMoveTimer.Passed()) { - RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY); - AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); - return false; + _nextMoveTimer.Reset(FORMATION_MOVEMENT_INTERVAL); + + // Our leader has a different position than on our last check, launch movement. + if (_lastLeaderPosition != target->GetPosition()) + { + LaunchMovement(owner, target); + return true; + } } + + // We have reached our destination before launching a new movement. Alling facing with leader + if (owner->HasUnitState(UNIT_STATE_ROAMING_MOVE) && owner->movespline->Finalized()) + { + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + owner->SetFacingTo(target->GetOrientation()); + MovementInform(owner); + } + return true; } +void FormationMovementGenerator::LaunchMovement(Creature* owner, Unit* target) +{ + float relativeAngle = 0.f; + + // Determine our relative angle to our current spline destination point + if (!target->movespline->Finalized()) + relativeAngle = target->GetRelativeAngle(Vector3ToPosition(target->movespline->CurrentDestination())); + + // Destination calculation + /* + According to sniff data, formation members have a periodic move interal of 1,2s. + Each of these splines has a exact duration of 1650ms +- 1ms when no pathfinding is involved. + To get a representative result like that we have to predict our formation leader's path + and apply our formation shape based on that destination. + */ + Position dest = target->GetPosition(); + float velocity = 0.f; + + // Formation leader is moving. Predict our destination + if (!target->movespline->Finalized()) + { + // Pick up leader's spline velocity + velocity = target->movespline->Velocity(); + + // Calculate travel distance to get a 1650ms result + float travelDist = velocity * 1.65f; + + // Move destination ahead... + target->MovePositionToFirstCollision(dest, travelDist, relativeAngle); + // ... and apply formation shape + target->MovePositionToFirstCollision(dest, _range, _angle + relativeAngle); + + float distance = owner->GetExactDist(dest); + + // Calculate catchup speed mod (Limit to a maximum of 50% of our original velocity + float velocityMod = std::min<float>(distance / travelDist, 1.5f); + + // Now we will always stay synch with our leader + velocity *= velocityMod; + _hasPredictedDestination = true; + } + else + { + // Formation leader is not moving. Just apply the base formation shape on his position. + target->MovePositionToFirstCollision(dest, _range, _angle + relativeAngle); + _hasPredictedDestination = false; + } + + // Leader is not moving, so just pick up his default walk speed + if (velocity == 0.f) + velocity = target->GetSpeed(MOVE_WALK); + + Movement::MoveSplineInit init(owner); + init.MoveTo(PositionToVector3(dest)); + init.SetVelocity(velocity); + init.Launch(); + + _lastLeaderPosition = target->GetPosition(); + owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); +} + void FormationMovementGenerator::DoDeactivate(Creature* owner) { AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); @@ -155,5 +227,5 @@ void FormationMovementGenerator::DoFinalize(Creature* owner, bool active, bool m void FormationMovementGenerator::MovementInform(Creature* owner) { if (owner->AI()) - owner->AI()->MovementInform(FORMATION_MOTION_TYPE, _movementId); + owner->AI()->MovementInform(FORMATION_MOTION_TYPE, 0); } diff --git a/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.h index d00e6e3a73a..0b6d89b9b08 100644 --- a/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FormationMovementGenerator.h @@ -18,15 +18,17 @@ #ifndef TRINITY_FORMATIONMOVEMENTGENERATOR_H #define TRINITY_FORMATIONMOVEMENTGENERATOR_H +#include "AbstractFollower.h" #include "MovementGenerator.h" #include "Position.h" +#include "Timer.h" class Creature; -class FormationMovementGenerator : public MovementGeneratorMedium<Creature, FormationMovementGenerator> +class FormationMovementGenerator : public MovementGeneratorMedium<Creature, FormationMovementGenerator>, public AbstractFollower { public: - explicit FormationMovementGenerator(uint32 id, Position destination, uint32 moveType, bool run, bool orientation); + explicit FormationMovementGenerator(Unit* leader, float range, float angle, uint32 point1, uint32 point2); MovementGeneratorType GetMovementGeneratorType() const override; @@ -36,16 +38,21 @@ class FormationMovementGenerator : public MovementGeneratorMedium<Creature, Form void DoDeactivate(Creature*); void DoFinalize(Creature*, bool, bool); - void UnitSpeedChanged() override { AddFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING); } - private: void MovementInform(Creature*); - uint32 _movementId; - Position _destination; - uint32 _moveType; - bool _run; - bool _orientation; + void LaunchMovement(Creature* owner, Unit* target); + + static constexpr uint32 FORMATION_MOVEMENT_INTERVAL = 1200; // sniffed (3 batch update cycles) + float const _range; + float _angle; + uint32 const _point1; + uint32 const _point2; + uint32 _lastLeaderSplineID; + bool _hasPredictedDestination; + + Position _lastLeaderPosition; + TimeTrackerSmall _nextMoveTimer; }; #endif // TRINITY_FORMATIONMOVEMENTGENERATOR_H diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index 817f7d58933..494e1aaa8e5 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -81,7 +81,7 @@ void PointMovementGenerator<T>::DoInitialize(T* owner) // Call for creature group update if (Creature* creature = owner->ToCreature()) - creature->SignalFormationMovement(_destination, _movementId); + creature->SignalFormationMovement(); } template<class T> @@ -129,7 +129,7 @@ bool PointMovementGenerator<T>::DoUpdate(T* owner, uint32 /*diff*/) // Call for creature group update if (Creature* creature = owner->ToCreature()) - creature->SignalFormationMovement(_destination, _movementId); + creature->SignalFormationMovement(); } if (owner->movespline->Finalized()) diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index 464902624a6..2872683d58e 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -182,7 +182,7 @@ void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner) } // Call for creature group update - owner->SignalFormationMovement(position); + owner->SignalFormationMovement(); } template<class T> diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index 7d1fc1f133f..4278acc1841 100644 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -334,7 +334,6 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::StartMove: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id); WaypointNode const &waypoint = _path->nodes[_currentNode]; - Position formationDest(waypoint.x, waypoint.y, waypoint.z, (waypoint.orientation && waypoint.delay) ? waypoint.orientation : 0.0f); RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_INFORM_ENABLED | MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); @@ -344,15 +343,7 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun //! If creature is on transport, we assume waypoints set in DB are already transport offsets if (transportPath) - { init.DisableTransportPathTransformations(); - if (TransportBase* trans = owner->GetDirectTransport()) - { - float orientation = formationDest.GetOrientation(); - trans->CalculatePassengerPosition(formationDest.m_positionX, formationDest.m_positionY, formationDest.m_positionZ, &orientation); - formationDest.SetOrientation(orientation); - } - } //! Do not use formationDest here, MoveTo requires transport offsets due to DisableTransportPathTransformations() call //! but formationDest contains global coordinates @@ -383,7 +374,7 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun init.Launch(); // inform formation - owner->SignalFormationMovement(formationDest, waypoint.id, waypoint.moveType, (waypoint.orientation && waypoint.delay) ? true : false); + owner->SignalFormationMovement(); } bool WaypointMovementGenerator<Creature>::ComputeNextNode() diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp index 3b7939eb038..30618e96752 100644 --- a/src/server/game/Movement/Spline/MoveSpline.cpp +++ b/src/server/game/Movement/Spline/MoveSpline.cpp @@ -193,6 +193,8 @@ void MoveSpline::Initialize(MoveSplineInitArgs const& args) anim_tier = args.animTier; splineIsFacingOnly = args.path.size() == 2 && args.facing.type != MONSTER_MOVE_NORMAL && ((args.path[1] - args.path[0]).length() < 0.1f); + velocity = args.velocity; + // Check if its a stop spline if (args.flags.done) { @@ -223,7 +225,7 @@ void MoveSpline::Initialize(MoveSplineInitArgs const& args) } MoveSpline::MoveSpline() : m_Id(0), time_passed(0), - vertical_acceleration(0.f), initialOrientation(0.f), effect_start_time(0), point_Idx(0), point_Idx_offset(0), + vertical_acceleration(0.f), initialOrientation(0.f), effect_start_time(0), point_Idx(0), point_Idx_offset(0), velocity(0.f), onTransport(false), splineIsFacingOnly(false) { splineflags.done = true; diff --git a/src/server/game/Movement/Spline/MoveSpline.h b/src/server/game/Movement/Spline/MoveSpline.h index e9083eb6417..3eab8984260 100644 --- a/src/server/game/Movement/Spline/MoveSpline.h +++ b/src/server/game/Movement/Spline/MoveSpline.h @@ -80,6 +80,7 @@ namespace Movement int32 effect_start_time; int32 point_Idx; int32 point_Idx_offset; + float velocity; Optional<SpellEffectExtraData> spell_effect_extra; Optional<AnimTierTransition> anim_tier; @@ -101,6 +102,7 @@ namespace Movement int32 Duration() const { return spline.length(); } MySpline const& _Spline() const { return spline; } int32 _currentSplineIdx() const { return point_Idx; } + float Velocity() const { return velocity; } void _Finalize(); void _Interrupt() { splineflags.done = true; } |