Core/Movement: Implemented cyclic waypoint movement
Port From (https://github.com/TrinityCore/TrinityCore/commit/222a80a6d62410eae6fa46dbdc60309f1728653a)
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user