From cf2e0e2faad78617012e8259352d08e7a62e6026 Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 7 Mar 2023 20:13:28 +0100 Subject: Core/Movement: New waypoint movement features * Allow going backwards on a repeatable waypoint path (instead of going directly to first point) * Allow triggering random movement on path ends * Max duration of waypoint movement * Skipping mmap usage * Forced speed for whole path * Forced run/walk for whole path --- src/server/game/Movement/MotionMaster.cpp | 24 ++++-- src/server/game/Movement/MotionMaster.h | 12 ++- src/server/game/Movement/MovementGenerator.cpp | 2 +- .../WaypointMovementGenerator.cpp | 89 +++++++++++++++++++++- .../MovementGenerators/WaypointMovementGenerator.h | 24 +++++- 5 files changed, 131 insertions(+), 20 deletions(-) (limited to 'src/server') diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 036182a5131..8066b635e0b 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -596,12 +596,12 @@ void MotionMaster::MoveTargetedHome() } } -void MotionMaster::MoveRandom(float wanderDistance, Optional duration) +void MotionMaster::MoveRandom(float wanderDistance, Optional duration, MovementSlot slot /*= MOTION_SLOT_DEFAULT*/) { if (_owner->GetTypeId() == TYPEID_UNIT) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveRandom: '{}', started random movement (spawnDist: {})", _owner->GetGUID().ToString(), wanderDistance); - Add(new RandomMovementGenerator(wanderDistance, duration), MOTION_SLOT_DEFAULT); + Add(new RandomMovementGenerator(wanderDistance, duration), slot); } } @@ -1075,19 +1075,27 @@ void MotionMaster::MoveDistract(uint32 timer, float orientation) Add(new DistractMovementGenerator(timer, orientation)); } -void MotionMaster::MovePath(uint32 pathId, bool repeatable) +void MotionMaster::MovePath(uint32 pathId, bool repeatable, Optional duration, Optional speed, + MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional> waitTimeRangeAtPathEnd, + Optional wanderDistanceAtPathEnds, bool followPathBackwardsFromEndToStart, bool generatePath) { if (!pathId) return; - TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePath: '{}', starts moving over path Id: {} (repeatable: {})", _owner->GetGUID().ToString(), pathId, repeatable ? "YES" : "NO"); - Add(new WaypointMovementGenerator(pathId, repeatable), MOTION_SLOT_DEFAULT); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePath: '{}', starts moving over path Id: {} (repeatable: {})", + _owner->GetGUID().ToString(), pathId, repeatable ? "YES" : "NO"); + Add(new WaypointMovementGenerator(pathId, repeatable, duration, speed, speedSelectionMode, waitTimeRangeAtPathEnd, + wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, generatePath), MOTION_SLOT_DEFAULT); } -void MotionMaster::MovePath(WaypointPath& path, bool repeatable) +void MotionMaster::MovePath(WaypointPath const& path, bool repeatable, Optional duration, Optional speed, + MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional> waitTimeRangeAtPathEnd, + Optional wanderDistanceAtPathEnds, bool followPathBackwardsFromEndToStart, bool generatePath) { - TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePath: '{}', starts moving over path Id: {} (repeatable: {})", _owner->GetGUID().ToString(), path.id, repeatable ? "YES" : "NO"); - Add(new WaypointMovementGenerator(path, repeatable), MOTION_SLOT_DEFAULT); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MovePath: '{}', starts moving over path Id: {} (repeatable: {})", + _owner->GetGUID().ToString(), path.id, repeatable ? "YES" : "NO"); + Add(new WaypointMovementGenerator(path, repeatable, duration, speed, speedSelectionMode, waitTimeRangeAtPathEnd, + wanderDistanceAtPathEnds, followPathBackwardsFromEndToStart, generatePath), MOTION_SLOT_DEFAULT); } void MotionMaster::MoveRotate(uint32 id, uint32 time, RotateDirection direction) diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 326d166dd0e..743f988ac22 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -156,7 +156,7 @@ class TC_GAME_API MotionMaster void MoveIdle(); void MoveTargetedHome(); - void MoveRandom(float wanderDistance = 0.0f, Optional duration = {}); + void MoveRandom(float wanderDistance = 0.0f, Optional duration = {}, MovementSlot slot = MOTION_SLOT_DEFAULT); void MoveFollow(Unit* target, float dist, ChaseAngle angle, Optional duration = {}, MovementSlot slot = MOTION_SLOT_ACTIVE); void MoveChase(Unit* target, Optional dist = {}, Optional angle = {}); void MoveChase(Unit* target, float dist, float angle) { MoveChase(target, ChaseRange(dist), ChaseAngle(angle)); } @@ -194,8 +194,14 @@ class TC_GAME_API MotionMaster void MoveSeekAssistanceDistract(uint32 timer); void MoveTaxiFlight(uint32 path, uint32 pathnode); void MoveDistract(uint32 time, float orientation); - void MovePath(uint32 pathId, bool repeatable); - void MovePath(WaypointPath& path, bool repeatable); + void MovePath(uint32 pathId, bool repeatable, Optional duration = {}, Optional speed = {}, + MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default, + Optional> waitTimeRangeAtPathEnd = {}, Optional wanderDistanceAtPathEnds = {}, + bool followPathBackwardsFromEndToStart = false, bool generatePath = true); + void MovePath(WaypointPath const& path, bool repeatable, Optional duration = {}, Optional speed = {}, + MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default, + Optional> waitTimeRangeAtPathEnd = {}, Optional wanderDistanceAtPathEnds = {}, + bool followPathBackwardsFromEndToStart = false, bool generatePath = true); void MoveRotate(uint32 id, uint32 time, RotateDirection direction); void MoveFormation(Unit* leader, float range, float angle, uint32 point1, uint32 point2); diff --git a/src/server/game/Movement/MovementGenerator.cpp b/src/server/game/Movement/MovementGenerator.cpp index b98f9fa6bb1..455f91795a5 100644 --- a/src/server/game/Movement/MovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerator.cpp @@ -57,5 +57,5 @@ WaypointMovementFactory::WaypointMovementFactory() : MovementGeneratorCreator(WA MovementGenerator* WaypointMovementFactory::Create(Unit* /*object*/) const { - return new WaypointMovementGenerator(); + return new WaypointMovementGenerator(0, true); } diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index 8dc59342aae..5b67247eff0 100644 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -21,6 +21,7 @@ #include "Errors.h" #include "Log.h" #include "Map.h" +#include "MotionMaster.h" #include "MovementDefines.h" #include "MoveSpline.h" #include "MoveSplineInit.h" @@ -29,15 +30,29 @@ #include "WaypointManager.h" #include -WaypointMovementGenerator::WaypointMovementGenerator(uint32 pathId, bool repeating) : _nextMoveTime(0), _pathId(pathId), _repeating(repeating), _loadedFromDB(true) +WaypointMovementGenerator::WaypointMovementGenerator(uint32 pathId, bool repeating, Optional duration, Optional speed, + MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional> waitTimeRangeAtPathEnd, + Optional wanderDistanceAtPathEnds, bool followPathBackwardsFromEndToStart, bool generatePath) + : _nextMoveTime(0), _pathId(pathId), _repeating(repeating), _loadedFromDB(true), + _speed(speed), _speedSelectionMode(speedSelectionMode), _waitTimeRangeAtPathEnd(std::move(waitTimeRangeAtPathEnd)), + _wanderDistanceAtPathEnds(wanderDistanceAtPathEnds), _followPathBackwardsFromEndToStart(followPathBackwardsFromEndToStart), _isReturningToStart(false), + _generatePath(generatePath) { Mode = MOTION_MODE_DEFAULT; Priority = MOTION_PRIORITY_NORMAL; Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; BaseUnitState = UNIT_STATE_ROAMING; + if (duration) + _duration.emplace(*duration); } -WaypointMovementGenerator::WaypointMovementGenerator(WaypointPath& path, bool repeating) : _nextMoveTime(0), _pathId(0), _repeating(repeating), _loadedFromDB(false) +WaypointMovementGenerator::WaypointMovementGenerator(WaypointPath const& path, bool repeating, Optional duration, Optional speed, + MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional> waitTimeRangeAtPathEnd, + Optional wanderDistanceAtPathEnds, bool followPathBackwardsFromEndToStart, bool generatePath) + : _nextMoveTime(0), _pathId(0), _repeating(repeating), _loadedFromDB(false), + _speed(speed), _speedSelectionMode(speedSelectionMode), _waitTimeRangeAtPathEnd(std::move(waitTimeRangeAtPathEnd)), + _wanderDistanceAtPathEnds(wanderDistanceAtPathEnds), _followPathBackwardsFromEndToStart(followPathBackwardsFromEndToStart), _isReturningToStart(false), + _generatePath(generatePath) { _path = &path; @@ -45,8 +60,12 @@ WaypointMovementGenerator::WaypointMovementGenerator(WaypointPath& pat Priority = MOTION_PRIORITY_NORMAL; Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; BaseUnitState = UNIT_STATE_ROAMING; + if (duration) + _duration.emplace(*duration); } +WaypointMovementGenerator::~WaypointMovementGenerator() = default; + MovementGeneratorType WaypointMovementGenerator::GetMovementGeneratorType() const { return WAYPOINT_MOTION_TYPE; @@ -139,6 +158,17 @@ bool WaypointMovementGenerator::DoUpdate(Creature* owner, uint32 diff) if (HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED | MOVEMENTGENERATOR_FLAG_PAUSED) || !_path || _path->nodes.empty()) return true; + if (_duration) + { + _duration->Update(diff); + if (_duration->Passed()) + { + RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY); + AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); + return false; + } + } + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE | UNIT_STATE_LOST_CONTROL) || owner->IsMovementPreventedByCasting()) { AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); @@ -248,6 +278,20 @@ void WaypointMovementGenerator::OnArrived(Creature* owner) _nextMoveTime.Reset(waypoint.delay); } + if (_waitTimeRangeAtPathEnd && _followPathBackwardsFromEndToStart + && ((_isReturningToStart && _currentNode == 0) || (!_isReturningToStart && _currentNode == _path->nodes.size() - 1))) + { + owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + Milliseconds waitTime = randtime(_waitTimeRangeAtPathEnd->first, _waitTimeRangeAtPathEnd->second); + if (_duration) + _duration->Update(waitTime); // count the random movement time as part of waypoing movement action + + if (_wanderDistanceAtPathEnds) + owner->GetMotionMaster()->MoveRandom(*_wanderDistanceAtPathEnds, waitTime, MOTION_SLOT_ACTIVE); + else + _nextMoveTime.Reset(waitTime); + } + if (waypoint.eventId && urand(0, 99) < waypoint.eventChance) { TC_LOG_DEBUG("maps.script", "Creature movement start script {} at point {} for {}.", waypoint.eventId, _currentNode, owner->GetGUID().ToString()); @@ -343,7 +387,7 @@ void WaypointMovementGenerator::StartMove(Creature* owner, bool relaun //! Do not use formationDest here, MoveTo requires transport offsets due to DisableTransportPathTransformations() call //! but formationDest contains global coordinates - init.MoveTo(waypoint.x, waypoint.y, waypoint.z); + init.MoveTo(waypoint.x, waypoint.y, waypoint.z, _generatePath); if (waypoint.orientation.has_value() && waypoint.delay > 0) init.SetFacing(*waypoint.orientation); @@ -365,6 +409,22 @@ void WaypointMovementGenerator::StartMove(Creature* owner, bool relaun default: break; } + switch (_speedSelectionMode) // overrides move type from each waypoint if set + { + case MovementWalkRunSpeedSelectionMode::Default: + break; + case MovementWalkRunSpeedSelectionMode::ForceRun: + init.SetWalk(false); + break; + case MovementWalkRunSpeedSelectionMode::ForceWalk: + init.SetWalk(true); + break; + default: + break; + } + + if (_speed) + init.SetVelocity(*_speed); init.Launch(); @@ -377,7 +437,28 @@ bool WaypointMovementGenerator::ComputeNextNode() if ((_currentNode == _path->nodes.size() - 1) && !_repeating) return false; - _currentNode = (_currentNode + 1) % _path->nodes.size(); + if (!_followPathBackwardsFromEndToStart || _path->nodes.size() < 2) + _currentNode = (_currentNode + 1) % _path->nodes.size(); + else + { + if (!_isReturningToStart) + { + if (++_currentNode >= _path->nodes.size()) + { + _currentNode -= 2; + _isReturningToStart = true; + } + } + else + { + if (_currentNode-- == 0) + { + _currentNode = 1; + _isReturningToStart = false; + } + } + } + return true; } diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h index e265c62522b..3764a9629f0 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h @@ -30,12 +30,19 @@ template class WaypointMovementGenerator; template<> -class WaypointMovementGenerator : public MovementGeneratorMedium>, public PathMovementBase +class WaypointMovementGenerator : public MovementGeneratorMedium>, + public PathMovementBase { public: - explicit WaypointMovementGenerator(uint32 pathId = 0, bool repeating = true); - explicit WaypointMovementGenerator(WaypointPath& path, bool repeating = true); - ~WaypointMovementGenerator() { _path = nullptr; } + explicit WaypointMovementGenerator(uint32 pathId, bool repeating, Optional duration = {}, Optional speed = {}, + MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default, + Optional> waitTimeRangeAtPathEnd = {}, Optional wanderDistanceAtPathEnds = {}, + bool followPathBackwardsFromEndToStart = false, bool generatePath = true); + explicit WaypointMovementGenerator(WaypointPath const& path, bool repeating, Optional duration, Optional speed, + MovementWalkRunSpeedSelectionMode speedSelectionMode, + Optional> waitTimeRangeAtPathEnd, Optional wanderDistanceAtPathEnds, + bool followPathBackwardsFromEndToStart, bool generatePath); + ~WaypointMovementGenerator(); MovementGeneratorType GetMovementGeneratorType() const override; @@ -72,6 +79,15 @@ class WaypointMovementGenerator : public MovementGeneratorMedium _duration; + Optional _speed; + MovementWalkRunSpeedSelectionMode _speedSelectionMode; + Optional> _waitTimeRangeAtPathEnd; + Optional _wanderDistanceAtPathEnds; + bool _followPathBackwardsFromEndToStart; + bool _isReturningToStart; + bool _generatePath; }; #endif -- cgit v1.2.3