diff options
author | Shauren <shauren.trinity@gmail.com> | 2024-04-21 00:16:57 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2024-04-21 00:16:57 +0200 |
commit | cf1ab7b4142f1d070d999c4141109a6c6c46d06d (patch) | |
tree | d47cfe303fcd1cd14309f9cdca4216caaf1b3946 /src | |
parent | 6929df0f0b1fc995cc27f6973277047ed4976d3b (diff) |
Core/Movement: Implemented alternative method of smoothing waypoint paths (send new point 1.5 before arrival) and make that the default
* Sending whole path at once is still supported with WaypointPathFlags::ExactSplinePath
Diffstat (limited to 'src')
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); |