Core/Movement: Implemented cyclic waypoint movement

Port From (https://github.com/TrinityCore/TrinityCore/commit/222a80a6d62410eae6fa46dbdc60309f1728653a)
This commit is contained in:
Hondacrx
2024-11-10 21:52:46 -05:00
parent be74f514a1
commit 60ad9da7b5
3 changed files with 50 additions and 8 deletions
@@ -53,7 +53,7 @@ namespace Framework.Constants
// flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably // flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably
MaskNoMonsterMove = Done, MaskNoMonsterMove = Done,
// Unused, not suported flags // Unused, not suported flags
MaskUnused = NoSpline | EnterCycle | Frozen | Unknown_0x100 | Unknown_0x20000 | Unknown_0x40000 MaskUnused = NoSpline | Frozen | Unknown_0x100 | Unknown_0x20000 | Unknown_0x40000
| Unknown_0x800000 | FadeObject | UnlimitedSpeed | Unknown_0x40000000 | Unknown_0x80000000 | Unknown_0x800000 | FadeObject | UnlimitedSpeed | Unknown_0x40000000 | Unknown_0x80000000
} }
} }
@@ -31,6 +31,7 @@ namespace Game.Movement
TimeTracker _moveTimer; TimeTracker _moveTimer;
TimeTracker _nextMoveTime; TimeTracker _nextMoveTime;
List<int> _waypointTransitionSplinePoints = new(); List<int> _waypointTransitionSplinePoints = new();
int _waypointTransitionSplinePointsIndex;
bool _isReturningToStart; bool _isReturningToStart;
static TimeSpan SEND_NEXT_POINT_EARLY_DELTA = TimeSpan.FromMilliseconds(1500); static TimeSpan SEND_NEXT_POINT_EARLY_DELTA = TimeSpan.FromMilliseconds(1500);
@@ -223,7 +224,7 @@ namespace Game.Movement
} }
// if it's moving // if it's moving
if (!UpdateMoveTimer(diff)) if (!UpdateMoveTimer(diff) && !owner.MoveSpline.Finalized())
{ {
// set home position at place (every MotionMaster::UpdateMotion) // set home position at place (every MotionMaster::UpdateMotion)
if (owner.GetTransGUID().IsEmpty()) if (owner.GetTransGUID().IsEmpty())
@@ -232,10 +233,10 @@ namespace Game.Movement
// handle switching points in continuous segments // handle switching points in continuous segments
if (IsExactSplinePath()) if (IsExactSplinePath())
{ {
if (_waypointTransitionSplinePoints.Count > 1 && owner.MoveSpline.CurrentPathIdx() >= _waypointTransitionSplinePoints.First()) if (_waypointTransitionSplinePointsIndex < _waypointTransitionSplinePoints.Count && owner.MoveSpline.CurrentPathIdx() >= _waypointTransitionSplinePoints[_waypointTransitionSplinePointsIndex])
{ {
OnArrived(owner); OnArrived(owner);
_waypointTransitionSplinePoints.Remove(_waypointTransitionSplinePoints.First()); ++_waypointTransitionSplinePointsIndex;
if (ComputeNextNode()) if (ComputeNextNode())
{ {
CreatureAI ai = owner.GetAI(); CreatureAI ai = owner.GetAI();
@@ -423,18 +424,34 @@ namespace Game.Movement
Cypher.Assert(_currentNode < _path.Nodes.Count, $"WaypointMovementGenerator.StartMove: tried to reference a node id ({_currentNode}) which is not included in path ({_path.Id})"); Cypher.Assert(_currentNode < _path.Nodes.Count, $"WaypointMovementGenerator.StartMove: tried to reference a node id ({_currentNode}) which is not included in path ({_path.Id})");
WaypointNode lastWaypointForSegment = _path.Nodes[_currentNode]; WaypointNode lastWaypointForSegment = _path.Nodes[_currentNode];
bool isCyclic = IsCyclic();
List<Vector3> points = new(); List<Vector3> points = new();
if (IsExactSplinePath()) if (IsExactSplinePath())
CreateMergedPath(owner, _path, previousNode, _currentNode, _isReturningToStart, false, CreateMergedPath(owner, _path, previousNode, _currentNode, _isReturningToStart, false, isCyclic, points, _waypointTransitionSplinePoints, ref lastWaypointForSegment);
points, _waypointTransitionSplinePoints, ref lastWaypointForSegment);
else else
CreateSingularPointPath(owner, _path, _currentNode, _generatePath, points, _waypointTransitionSplinePoints); CreateSingularPointPath(owner, _path, _currentNode, _generatePath, points, _waypointTransitionSplinePoints);
_waypointTransitionSplinePointsIndex = 0;
RemoveFlag(MovementGeneratorFlags.Transitory | MovementGeneratorFlags.InformEnabled | MovementGeneratorFlags.TimedPaused); RemoveFlag(MovementGeneratorFlags.Transitory | MovementGeneratorFlags.InformEnabled | MovementGeneratorFlags.TimedPaused);
owner.AddUnitState(UnitState.RoamingMove); owner.AddUnitState(UnitState.RoamingMove);
if (isCyclic)
{
bool isFirstCycle = relaunch || owner.MoveSpline.Finalized() || !owner.MoveSpline.IsCyclic();
if (!isFirstCycle)
{
for (var i = 0; i < _waypointTransitionSplinePoints.Count; ++i)
--_waypointTransitionSplinePoints[i];
// cyclic paths are using identical duration to first cycle with EnterCycle
_moveTimer.Reset(TimeSpan.FromMilliseconds(owner.MoveSpline.Duration()));
return;
}
}
MoveSplineInit init = new(owner); MoveSplineInit init = new(owner);
//! If creature is on transport, we assume waypoints set in DB are already transport offsets //! If creature is on transport, we assume waypoints set in DB are already transport offsets
@@ -485,6 +502,9 @@ namespace Game.Movement
if (_speed.HasValue) if (_speed.HasValue)
init.SetVelocity(_speed.Value); init.SetVelocity(_speed.Value);
if (isCyclic)
init.SetCyclic();
if (IsExactSplinePath() && points.Count > 2 && owner.CanFly()) if (IsExactSplinePath() && points.Count > 2 && owner.CanFly())
init.SetSmooth(); init.SetSmooth();
@@ -549,6 +569,14 @@ namespace Game.Movement
return _path.Flags.HasFlag(WaypointPathFlags.ExactSplinePath); return _path.Flags.HasFlag(WaypointPathFlags.ExactSplinePath);
} }
bool IsCyclic()
{
return !IsFollowingPathBackwardsFromEndToStart()
&& IsExactSplinePath()
&& _repeating
&& _path.ContinuousSegments.Count == 1;
}
public override string GetDebugInfo() public override string GetDebugInfo()
{ {
return $"Current Node: {_currentNode}\n{base.GetDebugInfo()}"; return $"Current Node: {_currentNode}\n{base.GetDebugInfo()}";
@@ -595,7 +623,7 @@ namespace Game.Movement
waypointTransitionSplinePoints.Add(points.Count - 1); waypointTransitionSplinePoints.Add(points.Count - 1);
} }
void CreateMergedPath(Unit owner, WaypointPath path, int previousNode, int currentNode, bool isReturningToStart, bool generatePath, List<Vector3> points, List<int> waypointTransitionSplinePoints, ref WaypointNode lastWaypointOnPath) void CreateMergedPath(Unit owner, WaypointPath path, int previousNode, int currentNode, bool isReturningToStart, bool generatePath, bool isCyclic, List<Vector3> points, List<int> waypointTransitionSplinePoints, ref WaypointNode lastWaypointOnPath)
{ {
var segment = new Func<List<WaypointNode>>(() => var segment = new Func<List<WaypointNode>>(() =>
{ {
@@ -654,6 +682,14 @@ namespace Game.Movement
} }
}; };
if (isCyclic)
{
// create new cyclic path starting at current node
List<WaypointNode> cyclicPath = path.Nodes;
fillPath(cyclicPath[currentNode..].Concat(cyclicPath[0..currentNode]).ToList());
return;
}
if (!isReturningToStart) if (!isReturningToStart)
fillPath(segment); fillPath(segment);
else else
@@ -222,7 +222,13 @@ namespace Game.Networking.Packets
if (!moveSpline.IsCyclic()) // Destination if (!moveSpline.IsCyclic()) // Destination
data.WriteVector3(moveSpline.FinalDestination()); data.WriteVector3(moveSpline.FinalDestination());
else else
{
var spline = moveSpline.spline;
if (spline.GetPointCount() <= 1)
data.WriteVector3(Vector3.Zero); data.WriteVector3(Vector3.Zero);
else
data.WriteVector3(spline.GetPoint(spline.Last() - 1));
}
bool hasSplineMove = data.WriteBit(!moveSpline.Finalized() && !moveSpline.splineIsFacingOnly); bool hasSplineMove = data.WriteBit(!moveSpline.Finalized() && !moveSpline.splineIsFacingOnly);
data.FlushBits(); data.FlushBits();