aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorModoX <moardox@gmail.com>2024-10-07 20:29:02 +0200
committerOvahlord <dreadkiller@gmx.de>2024-10-12 23:47:22 +0200
commit0844438ad32afedba6473e82810f1714068a1abc (patch)
tree400e31926510af2ba6657702089c5963b76db442 /src
parent7c425b8970e0066b16d2b3f5f1ddc76807a5f730 (diff)
Core/Movement: Implemented cyclic waypoint movement (#29923)
Co-authored-by: Shauren <shauren.trinity@gmail.com> (cherry picked from commit 222a80a6d62410eae6fa46dbdc60309f1728653a)
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp57
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h2
-rw-r--r--src/server/game/Movement/Spline/MoveSplineFlag.h2
-rw-r--r--src/server/game/Server/Packets/MovementPackets.cpp8
4 files changed, 58 insertions, 11 deletions
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index 84a1871a5c1..232ad771b16 100644
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -41,7 +41,7 @@ WaypointMovementGenerator<Creature>::WaypointMovementGenerator(uint32 pathId, bo
: PathMovementBase(PathType(std::in_place_type<WaypointPath const*>)), _pathId(pathId), _speed(speed), _speedSelectionMode(speedSelectionMode),
_waitTimeRangeAtPathEnd(std::move(waitTimeRangeAtPathEnd)), _wanderDistanceAtPathEnds(wanderDistanceAtPathEnds),
_followPathBackwardsFromEndToStart(followPathBackwardsFromEndToStart), _exactSplinePath(exactSplinePath), _repeating(repeating), _generatePath(generatePath),
- _moveTimer(0), _nextMoveTime(0), _isReturningToStart(false)
+ _moveTimer(0), _nextMoveTime(0), _waypointTransitionSplinePointsIndex(0), _isReturningToStart(false)
{
Mode = MOTION_MODE_DEFAULT;
Priority = MOTION_PRIORITY_NORMAL;
@@ -59,7 +59,7 @@ WaypointMovementGenerator<Creature>::WaypointMovementGenerator(WaypointPath cons
: PathMovementBase(std::make_unique<WaypointPath>(path)), _pathId(0), _speed(speed), _speedSelectionMode(speedSelectionMode),
_waitTimeRangeAtPathEnd(std::move(waitTimeRangeAtPathEnd)), _wanderDistanceAtPathEnds(wanderDistanceAtPathEnds),
_followPathBackwardsFromEndToStart(followPathBackwardsFromEndToStart), _exactSplinePath(exactSplinePath), _repeating(repeating), _generatePath(generatePath),
- _moveTimer(0), _nextMoveTime(0), _isReturningToStart(false)
+ _moveTimer(0), _nextMoveTime(0), _waypointTransitionSplinePointsIndex(0), _isReturningToStart(false)
{
Mode = MOTION_MODE_DEFAULT;
Priority = MOTION_PRIORITY_NORMAL;
@@ -218,7 +218,7 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 diff)
}
// if it's moving
- if (!UpdateMoveTimer(diff))
+ if (!UpdateMoveTimer(diff) && !owner->movespline->Finalized())
{
// set home position at place (every MotionMaster::UpdateMotion)
if (owner->GetTransGUID().IsEmpty())
@@ -227,10 +227,11 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 diff)
// handle switching points in continuous segments
if (IsExactSplinePath())
{
- if (_waypointTransitionSplinePoints.size() > 1 && owner->movespline->currentPathIdx() >= _waypointTransitionSplinePoints.front())
+ if (_waypointTransitionSplinePointsIndex < _waypointTransitionSplinePoints.size()
+ && owner->movespline->currentPathIdx() >= _waypointTransitionSplinePoints[_waypointTransitionSplinePointsIndex])
{
OnArrived(owner);
- _waypointTransitionSplinePoints.erase(_waypointTransitionSplinePoints.begin());
+ ++_waypointTransitionSplinePointsIndex;
if (ComputeNextNode())
if (CreatureAI* ai = owner->AI())
ai->WaypointStarted(path->Nodes[_currentNode].Id, path->Id);
@@ -363,13 +364,14 @@ void CreateSingularPointPath(Unit const* owner, WaypointPath const* path, uint32
waypointTransitionSplinePoints->push_back(points->size() - 1);
}
-void CreateMergedPath(Unit const* owner, WaypointPath const* path, uint32 previousNode, uint32 currentNode, bool isReturningToStart, bool generatePath,
+void CreateMergedPath(Unit const* owner, WaypointPath const* path, uint32 previousNode, uint32 currentNode,
+ bool isReturningToStart, bool generatePath, bool isCyclic,
Movement::PointsArray* points, std::vector<int32>* waypointTransitionSplinePoints, WaypointNode const** lastWaypointOnPath)
{
std::span<WaypointNode const> segment = [&]
{
// find the continuous segment that our destination waypoint is on
- auto segmentItr = std::ranges::find_if(path->ContinuousSegments, [&](std::pair<std::size_t, std::size_t> segmentRange)
+ auto segmentItr = std::ranges::find_if(path->ContinuousSegments, [&](std::pair<std::size_t, std::size_t> const& segmentRange)
{
auto isInSegmentRange = [&](uint32 node) { return node >= segmentRange.first && node < segmentRange.first + segmentRange.second; };
return isInSegmentRange(currentNode) && isInSegmentRange(previousNode);
@@ -423,6 +425,15 @@ void CreateMergedPath(Unit const* owner, WaypointPath const* path, uint32 previo
}
};
+ if (isCyclic)
+ {
+ // create new cyclic path starting at current node
+ std::vector<WaypointNode> cyclicPath = path->Nodes;
+ std::rotate(cyclicPath.begin(), cyclicPath.begin() + currentNode, cyclicPath.end());
+ fillPath(cyclicPath.begin(), cyclicPath.end());
+ return;
+ }
+
if (!isReturningToStart)
fillPath(segment.begin(), segment.end());
else
@@ -503,18 +514,35 @@ 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* lastWaypointForSegment = &path->Nodes[_currentNode];
+ bool isCyclic = IsCyclic();
Movement::PointsArray points;
if (IsExactSplinePath())
- CreateMergedPath(owner, path, previousNode, _currentNode, _isReturningToStart, false,
+ CreateMergedPath(owner, path, previousNode, _currentNode, _isReturningToStart, false, isCyclic,
&points, &_waypointTransitionSplinePoints, &lastWaypointForSegment);
else
CreateSingularPointPath(owner, path, _currentNode, _generatePath, &points, &_waypointTransitionSplinePoints);
+ _waypointTransitionSplinePointsIndex = 0;
+
RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_INFORM_ENABLED | MOVEMENTGENERATOR_FLAG_TIMED_PAUSED);
owner->AddUnitState(UNIT_STATE_ROAMING_MOVE);
+ if (isCyclic)
+ {
+ bool isFirstCycle = relaunch || owner->movespline->Finalized() || !owner->movespline->isCyclic();
+ if (!isFirstCycle)
+ {
+ for (int32& point : _waypointTransitionSplinePoints)
+ --point;
+
+ // cyclic paths are using identical duration to first cycle with EnterCycle
+ _moveTimer.Reset(Milliseconds(owner->movespline->Duration()));
+ return;
+ }
+ }
+
Movement::MoveSplineInit init(owner);
//! If creature is on transport, we assume waypoints set in DB are already transport offsets
@@ -567,7 +595,10 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun
if (_speed)
init.SetVelocity(*_speed);
- if (IsExactSplinePath() && points.size() > 2 && owner->CanFly())
+ if (isCyclic)
+ init.SetCyclic();
+
+ if (IsExactSplinePath() && (points.size() > 2 && owner->CanFly()))
init.SetSmooth();
Milliseconds duration(init.Launch());
@@ -633,6 +664,14 @@ bool WaypointMovementGenerator<Creature>::IsExactSplinePath() const
return GetPath()->Flags.HasFlag(WaypointPathFlags::ExactSplinePath);
}
+bool WaypointMovementGenerator<Creature>::IsCyclic() const
+{
+ return !IsFollowingPathBackwardsFromEndToStart()
+ && IsExactSplinePath()
+ && _repeating
+ && GetPath()->ContinuousSegments.size() == 1;
+}
+
std::string WaypointMovementGenerator<Creature>::GetDebugInfo() const
{
return Trinity::StringFormat("{}\n{}",
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
index a214734db83..fb981f400cd 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
@@ -84,6 +84,7 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium<Creat
bool IsFollowingPathBackwardsFromEndToStart() const;
bool IsExactSplinePath() const;
+ bool IsCyclic() const;
bool IsLoadedFromDB() const { return std::holds_alternative<WaypointPath const*>(_path); }
@@ -101,6 +102,7 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium<Creat
TimeTracker _moveTimer;
TimeTracker _nextMoveTime;
std::vector<int32> _waypointTransitionSplinePoints;
+ uint32 _waypointTransitionSplinePointsIndex;
bool _isReturningToStart;
};
diff --git a/src/server/game/Movement/Spline/MoveSplineFlag.h b/src/server/game/Movement/Spline/MoveSplineFlag.h
index 7a8317aa04d..c33711c951c 100644
--- a/src/server/game/Movement/Spline/MoveSplineFlag.h
+++ b/src/server/game/Movement/Spline/MoveSplineFlag.h
@@ -65,7 +65,7 @@ namespace Movement
// flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably
Mask_No_Monster_Move = Done, // SKIP
// Unused, not suported flags
- Mask_Unused = No_Spline | Enter_Cycle | Frozen | Unknown_0x100 | Unknown_0x20000 | Unknown_0x40000
+ Mask_Unused = No_Spline | Frozen | Unknown_0x100 | Unknown_0x20000 | Unknown_0x40000
| Unknown_0x800000 | FadeObject | UnlimitedSpeed | Unknown_0x40000000 | Unknown_0x80000000 // SKIP
};
diff --git a/src/server/game/Server/Packets/MovementPackets.cpp b/src/server/game/Server/Packets/MovementPackets.cpp
index 7020519bffa..c9f9338cbc8 100644
--- a/src/server/game/Server/Packets/MovementPackets.cpp
+++ b/src/server/game/Server/Packets/MovementPackets.cpp
@@ -356,7 +356,13 @@ void WorldPackets::Movement::CommonMovement::WriteCreateObjectSplineDataBlock(::
if (!moveSpline.isCyclic()) // Destination
dest = moveSpline.FinalDestination();
else
- dest = G3D::Vector3::zero();
+ {
+ ::Movement::MoveSpline::MySpline const& spline = moveSpline._Spline();
+ if (spline.getPointCount() <= 1)
+ dest = G3D::Vector3::zero();
+ else
+ dest = spline.getPoint(spline.last() - 1);
+ }
data << dest.x << dest.y << dest.z;