aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp2
-rw-r--r--src/server/game/Movement/MotionMaster.cpp10
-rw-r--r--src/server/game/Movement/MotionMaster.h4
-rw-r--r--src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp222
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h27
-rw-r--r--src/server/game/Movement/Waypoints/WaypointDefines.h1
6 files changed, 168 insertions, 98 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 88810a68851..0620d231a87 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -72,7 +72,7 @@ void SmartAI::StartPath(uint32 pathId/* = 0*/, bool repeat/* = false*/, Unit* in
me->ReplaceAllNpcFlags(UNIT_NPC_FLAG_NONE);
}
- me->GetMotionMaster()->MovePath(pathId, _repeatWaypointPath, {}, {}, MovementWalkRunSpeedSelectionMode::Default, {}, {}, {}, true, std::move(scriptResult));
+ me->GetMotionMaster()->MovePath(pathId, _repeatWaypointPath, {}, {}, MovementWalkRunSpeedSelectionMode::Default, {}, {}, {}, {}, true, std::move(scriptResult));
}
WaypointPath const* SmartAI::LoadPath(uint32 entry)
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index aec3bc208a8..e60f30741b6 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -1157,7 +1157,8 @@ void MotionMaster::MoveDistract(uint32 timer, float orientation)
void MotionMaster::MovePath(uint32 pathId, bool repeatable, Optional<Milliseconds> duration /*= {}*/, Optional<float> speed /*= {}*/,
MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/,
Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd /*= {}*/,
- Optional<float> wanderDistanceAtPathEnds /*= {}*/, Optional<bool> followPathBackwardsFromEndToStart /*= {}*/, bool generatePath /*= true*/,
+ Optional<float> wanderDistanceAtPathEnds /*= {}*/, Optional<bool> followPathBackwardsFromEndToStart /*= {}*/,
+ Optional<bool> exactSplinePath /*= {}*/, bool generatePath /*= true*/,
Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/)
{
if (!pathId)
@@ -1170,19 +1171,20 @@ void MotionMaster::MovePath(uint32 pathId, bool repeatable, Optional<Millisecond
TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePath: '{}', starts moving over path Id: {} (repeatable: {})",
_owner->GetGUID(), pathId, repeatable ? "YES" : "NO");
Add(new WaypointMovementGenerator<Creature>(pathId, repeatable, duration, speed, speedSelectionMode, waitTimeRangeAtPathEnd,
- wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, generatePath, std::move(scriptResult)), MOTION_SLOT_DEFAULT);
+ wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, exactSplinePath, generatePath, std::move(scriptResult)), MOTION_SLOT_DEFAULT);
}
void MotionMaster::MovePath(WaypointPath const& path, bool repeatable, Optional<Milliseconds> duration /*= {}*/, Optional<float> speed /*= {}*/,
MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::Default*/,
Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd /*= {}*/,
- Optional<float> wanderDistanceAtPathEnds /*= {}*/, Optional<bool> followPathBackwardsFromEndToStart /*= {}*/, bool generatePath /*= true*/,
+ Optional<float> wanderDistanceAtPathEnds /*= {}*/, Optional<bool> followPathBackwardsFromEndToStart /*= {}*/,
+ Optional<bool> exactSplinePath /*= {}*/, bool generatePath /*= true*/,
Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/)
{
TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePath: '{}', starts moving over path Id: {} (repeatable: {})",
_owner->GetGUID(), path.Id, repeatable ? "YES" : "NO");
Add(new WaypointMovementGenerator<Creature>(path, repeatable, duration, speed, speedSelectionMode, waitTimeRangeAtPathEnd,
- wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, generatePath, std::move(scriptResult)), MOTION_SLOT_DEFAULT);
+ wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, exactSplinePath, generatePath, std::move(scriptResult)), MOTION_SLOT_DEFAULT);
}
void MotionMaster::MoveRotate(uint32 id, RotateDirection direction, Optional<Milliseconds> time /*= {}*/,
diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
index 2f2d4d9d6da..4fed7e9ea07 100644
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -216,12 +216,12 @@ class TC_GAME_API MotionMaster
void MovePath(uint32 pathId, bool repeatable, Optional<Milliseconds> duration = {}, Optional<float> speed = {},
MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default,
Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd = {}, Optional<float> wanderDistanceAtPathEnds = {},
- Optional<bool> followPathBackwardsFromEndToStart = {}, bool generatePath = true,
+ Optional<bool> followPathBackwardsFromEndToStart = {}, Optional<bool> exactSplinePath = {}, bool generatePath = true,
Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {});
void MovePath(WaypointPath const& path, bool repeatable, Optional<Milliseconds> duration = {}, Optional<float> speed = {},
MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default,
Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd = {}, Optional<float> wanderDistanceAtPathEnds = {},
- Optional<bool> followPathBackwardsFromEndToStart = {}, bool generatePath = true,
+ Optional<bool> followPathBackwardsFromEndToStart = {}, Optional<bool> exactSplinePath = {}, bool generatePath = true,
Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {});
/**
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index fa87733d6f9..55f09435618 100644
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -29,14 +29,19 @@
#include "WaypointManager.h"
#include <span>
+namespace
+{
+constexpr Milliseconds SEND_NEXT_POINT_EARLY_DELTA = 1500ms;
+}
+
WaypointMovementGenerator<Creature>::WaypointMovementGenerator(uint32 pathId, bool repeating, Optional<Milliseconds> duration, Optional<float> speed,
MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd,
- Optional<float> wanderDistanceAtPathEnds, Optional<bool> followPathBackwardsFromEndToStart, bool generatePath,
+ Optional<float> wanderDistanceAtPathEnds, Optional<bool> followPathBackwardsFromEndToStart, Optional<bool> exactSplinePath, bool generatePath,
Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/)
- : PathMovementBase(PathType(std::in_place_type<WaypointPath const*>)), _nextMoveTime(0), _pathId(pathId), _repeating(repeating),
- _speed(speed), _speedSelectionMode(speedSelectionMode), _waitTimeRangeAtPathEnd(std::move(waitTimeRangeAtPathEnd)),
- _wanderDistanceAtPathEnds(wanderDistanceAtPathEnds), _followPathBackwardsFromEndToStart(followPathBackwardsFromEndToStart), _isReturningToStart(false),
- _generatePath(generatePath)
+ : 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)
{
Mode = MOTION_MODE_DEFAULT;
Priority = MOTION_PRIORITY_NORMAL;
@@ -49,12 +54,12 @@ WaypointMovementGenerator<Creature>::WaypointMovementGenerator(uint32 pathId, bo
WaypointMovementGenerator<Creature>::WaypointMovementGenerator(WaypointPath const& path, bool repeating, Optional<Milliseconds> duration, Optional<float> speed,
MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd,
- Optional<float> wanderDistanceAtPathEnds, Optional<bool> followPathBackwardsFromEndToStart, bool generatePath,
+ Optional<float> wanderDistanceAtPathEnds, Optional<bool> followPathBackwardsFromEndToStart, Optional<bool> exactSplinePath, bool generatePath,
Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/)
- : PathMovementBase(std::make_unique<WaypointPath>(path)), _nextMoveTime(0), _pathId(0), _repeating(repeating),
- _speed(speed), _speedSelectionMode(speedSelectionMode), _waitTimeRangeAtPathEnd(std::move(waitTimeRangeAtPathEnd)),
- _wanderDistanceAtPathEnds(wanderDistanceAtPathEnds), _followPathBackwardsFromEndToStart(followPathBackwardsFromEndToStart), _isReturningToStart(false),
- _generatePath(generatePath)
+ : 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)
{
Mode = MOTION_MODE_DEFAULT;
Priority = MOTION_PRIORITY_NORMAL;
@@ -213,20 +218,23 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 diff)
}
// if it's moving
- if (!owner->movespline->Finalized())
+ if (!UpdateMoveTimer(diff))
{
// set home position at place (every MotionMaster::UpdateMotion)
if (owner->GetTransGUID().IsEmpty())
owner->SetHomePosition(owner->GetPosition());
// handle switching points in continuous segments
- if (_waypointTransitionSplinePoints.size() > 1 && owner->movespline->currentPathIdx() >= _waypointTransitionSplinePoints.front())
+ if (IsExactSplinePath())
{
- OnArrived(owner);
- _waypointTransitionSplinePoints.erase(_waypointTransitionSplinePoints.begin());
- if (ComputeNextNode())
- if (CreatureAI* ai = owner->AI())
- ai->WaypointStarted(path->Nodes[_currentNode].Id, path->Id);
+ if (_waypointTransitionSplinePoints.size() > 1 && owner->movespline->currentPathIdx() >= _waypointTransitionSplinePoints.front())
+ {
+ OnArrived(owner);
+ _waypointTransitionSplinePoints.erase(_waypointTransitionSplinePoints.begin());
+ if (ComputeNextNode())
+ if (CreatureAI* ai = owner->AI())
+ ai->WaypointStarted(path->Nodes[_currentNode].Id, path->Id);
+ }
}
// relaunch movement if its speed has changed
@@ -235,7 +243,7 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 diff)
}
else if (!_nextMoveTime.Passed()) // it's not moving, is there a timer?
{
- if (UpdateTimer(diff))
+ if (UpdateWaitTimer(diff))
{
if (!HasFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED)) // initial movement call
{
@@ -332,6 +340,96 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature* owner)
owner->UpdateCurrentWaypointInfo(waypoint.Id, path->Id);
}
+namespace
+{
+void CreateSingularPointPath(Unit const* owner, WaypointPath const* path, uint32 currentNode, bool generatePath,
+ Movement::PointsArray* points, std::vector<int32>* waypointTransitionSplinePoints)
+{
+ WaypointNode const& waypoint = path->Nodes[currentNode];
+ points->emplace_back(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ());
+
+ if (generatePath)
+ {
+ PathGenerator generator(owner);
+ bool result = generator.CalculatePath(waypoint.X, waypoint.Y, waypoint.Z);
+ if (result && !(generator.GetPathType() & PATHFIND_NOPATH))
+ points->insert(points->end(), generator.GetPath().begin() + 1, generator.GetPath().end());
+ else
+ points->emplace_back(waypoint.X, waypoint.Y, waypoint.Z);
+ }
+ else
+ points->emplace_back(waypoint.X, waypoint.Y, waypoint.Z);
+
+ waypointTransitionSplinePoints->push_back(points->size() - 1);
+}
+
+void CreateMergedPath(Unit const* owner, WaypointPath const* path, uint32 previousNode, uint32 currentNode, bool isReturningToStart, bool generatePath,
+ 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 isInSegmentRange = [&](uint32 node) { return node >= segmentRange.first && node < segmentRange.first + segmentRange.second; };
+ return isInSegmentRange(currentNode) && isInSegmentRange(previousNode);
+ });
+
+ // handle path returning directly from last point to first
+ if (segmentItr == path->ContinuousSegments.end())
+ {
+ if (currentNode != 0 || previousNode != path->Nodes.size() - 1)
+ return std::span(&path->Nodes[currentNode], 1);
+
+ segmentItr = path->ContinuousSegments.begin();
+ }
+
+ if (!isReturningToStart)
+ return std::span(&path->Nodes[currentNode], segmentItr->second - (currentNode - segmentItr->first));
+
+ return std::span(&path->Nodes[segmentItr->first], currentNode - segmentItr->first + 1);
+ }();
+
+ *lastWaypointOnPath = !isReturningToStart ? &segment.back() : &segment.front();
+
+ waypointTransitionSplinePoints->clear();
+ auto fillPath = [&]<typename iterator>(iterator itr, iterator end)
+ {
+ Optional<PathGenerator> generator;
+ if (generatePath)
+ generator.emplace(owner);
+
+ Position source = owner->GetPosition();
+ points->emplace_back(source.GetPositionX(), source.GetPositionY(), source.GetPositionZ());
+
+ while (itr != end)
+ {
+ if (generator)
+ {
+ bool result = generator->CalculatePath(source.GetPositionX(), source.GetPositionY(), source.GetPositionZ(), itr->X, itr->Y, itr->Z);
+ if (result && !(generator->GetPathType() & PATHFIND_NOPATH))
+ points->insert(points->end(), generator->GetPath().begin() + 1, generator->GetPath().end());
+ else
+ generator.reset(); // when path generation to a waypoint fails, add all remaining points without pathfinding (preserve legacy behavior of MoveSplineInit::MoveTo)
+ }
+
+ if (!generator)
+ points->emplace_back(itr->X, itr->Y, itr->Z);
+
+ waypointTransitionSplinePoints->push_back(points->size() - 1);
+
+ source.Relocate(itr->X, itr->Y, itr->Z);
+ ++itr;
+ }
+ };
+
+ if (!isReturningToStart)
+ fillPath(segment.begin(), segment.end());
+ else
+ fillPath(segment.rbegin(), segment.rend());
+}
+}
+
void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaunch/* = false*/)
{
// sanity checks
@@ -403,69 +501,15 @@ 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];
- 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 isInSegmentRange = [&](uint32 node) { return node >= segmentRange.first && node < segmentRange.first + segmentRange.second; };
- return isInSegmentRange(_currentNode) && isInSegmentRange(previousNode);
- });
-
- // handle path returning directly from last point to first
- if (segmentItr == path->ContinuousSegments.end())
- {
- if (_currentNode != 0 || previousNode != path->Nodes.size() - 1)
- return std::span(&path->Nodes[_currentNode], 1);
-
- segmentItr = path->ContinuousSegments.begin();
- }
-
- if (!_isReturningToStart)
- return std::span(&path->Nodes[_currentNode], segmentItr->second - (_currentNode - segmentItr->first));
-
- return std::span(&path->Nodes[segmentItr->first], _currentNode - segmentItr->first + 1);
- }();
-
- WaypointNode const& lastWaypointForSegment = !_isReturningToStart ? segment.back() : segment.front();
-
- _waypointTransitionSplinePoints.clear();
Movement::PointsArray points;
- auto fillPath = [this, owner, &points]<typename iterator>(iterator itr, iterator end)
- {
- Optional<PathGenerator> generator;
- if (_generatePath)
- generator.emplace(owner);
-
- Position source = owner->GetPosition();
- points.emplace_back(source.GetPositionX(), source.GetPositionY(), source.GetPositionZ());
-
- while (itr != end)
- {
- if (generator)
- {
- bool result = generator->CalculatePath(source.GetPositionX(), source.GetPositionY(), source.GetPositionZ(), itr->X, itr->Y, itr->Z);
- if (result && !(generator->GetPathType() & PATHFIND_NOPATH))
- points.insert(points.end(), generator->GetPath().begin() + 1, generator->GetPath().end());
- else
- generator.reset(); // when path generation to a waypoint fails, add all remaining points without pathfinding (preserve legacy behavior of MoveSplineInit::MoveTo)
- }
-
- if (!generator)
- points.emplace_back(itr->X, itr->Y, itr->Z);
- _waypointTransitionSplinePoints.push_back(points.size() - 1);
-
- source.Relocate(itr->X, itr->Y, itr->Z);
- ++itr;
- }
- };
-
- if (!_isReturningToStart)
- fillPath(segment.begin(), segment.end());
+ if (IsExactSplinePath())
+ CreateMergedPath(owner, path, previousNode, _currentNode, _isReturningToStart, false,
+ &points, &_waypointTransitionSplinePoints, &lastWaypointForSegment);
else
- fillPath(segment.rbegin(), segment.rend());
+ CreateSingularPointPath(owner, path, _currentNode, _generatePath, &points, &_waypointTransitionSplinePoints);
RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_INFORM_ENABLED | MOVEMENTGENERATOR_FLAG_TIMED_PAUSED);
@@ -483,8 +527,9 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun
init.MovebyPath(points);
- if (lastWaypointForSegment.Orientation.has_value() && (lastWaypointForSegment.Delay || _currentNode == path->Nodes.size() - 1))
- init.SetFacing(*lastWaypointForSegment.Orientation);
+ if (lastWaypointForSegment->Orientation.has_value()
+ && (lastWaypointForSegment->Delay || (_isReturningToStart ? _currentNode == 0 : _currentNode == path->Nodes.size() - 1)))
+ init.SetFacing(*lastWaypointForSegment->Orientation);
switch (path->MoveType)
{
@@ -545,7 +590,16 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun
}
}
- init.Launch();
+ Milliseconds duration(init.Launch());
+
+ if (!IsExactSplinePath()
+ && duration > 2 * SEND_NEXT_POINT_EARLY_DELTA
+ && !lastWaypointForSegment->Delay
+ // don't cut movement short at ends of path if its not a looping path or if it can be traversed backwards
+ && ((_currentNode != 0 && _currentNode != path->Nodes.size() - 1) || (!IsFollowingPathBackwardsFromEndToStart() && _repeating)))
+ duration -= SEND_NEXT_POINT_EARLY_DELTA;
+
+ _moveTimer.Reset(duration);
// inform formation
owner->SignalFormationMovement();
@@ -590,6 +644,14 @@ bool WaypointMovementGenerator<Creature>::IsFollowingPathBackwardsFromEndToStart
return GetPath()->Flags.HasFlag(WaypointPathFlags::FollowPathBackwardsFromEndToStart);
}
+bool WaypointMovementGenerator<Creature>::IsExactSplinePath() const
+{
+ if (_exactSplinePath)
+ return *_exactSplinePath;
+
+ return GetPath()->Flags.HasFlag(WaypointPathFlags::ExactSplinePath);
+}
+
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 29b1b48354a..a214734db83 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
@@ -38,12 +38,12 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium<Creat
explicit WaypointMovementGenerator(uint32 pathId, bool repeating, Optional<Milliseconds> duration = {}, Optional<float> speed = {},
MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default,
Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd = {}, Optional<float> wanderDistanceAtPathEnds = {},
- Optional<bool> followPathBackwardsFromEndToStart = {}, bool generatePath = true,
+ Optional<bool> followPathBackwardsFromEndToStart = {}, Optional<bool> exactSplinePath = {}, bool generatePath = true,
Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {});
explicit WaypointMovementGenerator(WaypointPath const& path, bool repeating, Optional<Milliseconds> duration, Optional<float> speed,
MovementWalkRunSpeedSelectionMode speedSelectionMode,
Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd, Optional<float> wanderDistanceAtPathEnds,
- Optional<bool> followPathBackwardsFromEndToStart, bool generatePath,
+ Optional<bool> followPathBackwardsFromEndToStart, Optional<bool> exactSplinePath, bool generatePath,
Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {});
~WaypointMovementGenerator();
@@ -69,34 +69,39 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium<Creat
void OnArrived(Creature*);
void StartMove(Creature*, bool relaunch = false);
bool ComputeNextNode();
- bool UpdateTimer(uint32 diff)
+ bool UpdateMoveTimer(uint32 diff) { return UpdateTimer(_moveTimer, diff); }
+ bool UpdateWaitTimer(uint32 diff) { return UpdateTimer(_nextMoveTime, diff); }
+ static bool UpdateTimer(TimeTracker& timer, uint32 diff)
{
- _nextMoveTime.Update(diff);
- if (_nextMoveTime.Passed())
+ timer.Update(Milliseconds(diff));
+ if (timer.Passed())
{
- _nextMoveTime.Reset(0);
+ timer.Reset(0);
return true;
}
return false;
}
bool IsFollowingPathBackwardsFromEndToStart() const;
+ bool IsExactSplinePath() const;
bool IsLoadedFromDB() const { return std::holds_alternative<WaypointPath const*>(_path); }
- std::vector<int32> _waypointTransitionSplinePoints;
- TimeTracker _nextMoveTime;
uint32 _pathId;
- bool _repeating;
-
Optional<TimeTracker> _duration;
Optional<float> _speed;
MovementWalkRunSpeedSelectionMode _speedSelectionMode;
Optional<std::pair<Milliseconds, Milliseconds>> _waitTimeRangeAtPathEnd;
Optional<float> _wanderDistanceAtPathEnds;
Optional<bool> _followPathBackwardsFromEndToStart;
- bool _isReturningToStart;
+ Optional<bool> _exactSplinePath;
+ bool _repeating;
bool _generatePath;
+
+ TimeTracker _moveTimer;
+ TimeTracker _nextMoveTime;
+ std::vector<int32> _waypointTransitionSplinePoints;
+ bool _isReturningToStart;
};
#endif
diff --git a/src/server/game/Movement/Waypoints/WaypointDefines.h b/src/server/game/Movement/Waypoints/WaypointDefines.h
index cf5c85a1161..b49ebc8a1d2 100644
--- a/src/server/game/Movement/Waypoints/WaypointDefines.h
+++ b/src/server/game/Movement/Waypoints/WaypointDefines.h
@@ -40,6 +40,7 @@ enum class WaypointPathFlags : uint8
{
None = 0x00,
FollowPathBackwardsFromEndToStart = 0x01,
+ ExactSplinePath = 0x02, // Points are going to be merged into single packets and pathfinding is disabled
};
DEFINE_ENUM_FLAG(WaypointPathFlags);