diff options
5 files changed, 131 insertions, 20 deletions
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<Milliseconds> duration) +void MotionMaster::MoveRandom(float wanderDistance, Optional<Milliseconds> 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<Creature>(wanderDistance, duration), MOTION_SLOT_DEFAULT); + Add(new RandomMovementGenerator<Creature>(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<Milliseconds> duration, Optional<float> speed, + MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd, + Optional<float> 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<Creature>(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<Creature>(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<Milliseconds> duration, Optional<float> speed, + MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd, + Optional<float> 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<Creature>(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<Creature>(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<Milliseconds> duration = {}); + void MoveRandom(float wanderDistance = 0.0f, Optional<Milliseconds> duration = {}, MovementSlot slot = MOTION_SLOT_DEFAULT); void MoveFollow(Unit* target, float dist, ChaseAngle angle, Optional<Milliseconds> duration = {}, MovementSlot slot = MOTION_SLOT_ACTIVE); void MoveChase(Unit* target, Optional<ChaseRange> dist = {}, Optional<ChaseAngle> 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<Milliseconds> duration = {}, Optional<float> speed = {}, + MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default, + Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd = {}, Optional<float> wanderDistanceAtPathEnds = {}, + bool followPathBackwardsFromEndToStart = false, bool generatePath = true); + 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 = {}, + 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<Creature>(); + return new WaypointMovementGenerator<Creature>(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 <sstream> -WaypointMovementGenerator<Creature>::WaypointMovementGenerator(uint32 pathId, bool repeating) : _nextMoveTime(0), _pathId(pathId), _repeating(repeating), _loadedFromDB(true) +WaypointMovementGenerator<Creature>::WaypointMovementGenerator(uint32 pathId, bool repeating, Optional<Milliseconds> duration, Optional<float> speed, + MovementWalkRunSpeedSelectionMode speedSelectionMode, Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd, + Optional<float> 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<Creature>::WaypointMovementGenerator(WaypointPath& path, bool repeating) : _nextMoveTime(0), _pathId(0), _repeating(repeating), _loadedFromDB(false) +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, 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<Creature>::WaypointMovementGenerator(WaypointPath& pat Priority = MOTION_PRIORITY_NORMAL; Flags = MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING; BaseUnitState = UNIT_STATE_ROAMING; + if (duration) + _duration.emplace(*duration); } +WaypointMovementGenerator<Creature>::~WaypointMovementGenerator() = default; + MovementGeneratorType WaypointMovementGenerator<Creature>::GetMovementGeneratorType() const { return WAYPOINT_MOTION_TYPE; @@ -139,6 +158,17 @@ bool WaypointMovementGenerator<Creature>::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<Creature>::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<Creature>::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<Creature>::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<Creature>::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 T> class WaypointMovementGenerator; template<> -class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium<Creature, WaypointMovementGenerator<Creature>>, public PathMovementBase<Creature, WaypointPath const*> +class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium<Creature, WaypointMovementGenerator<Creature>>, + public PathMovementBase<Creature, WaypointPath const*> { 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<Milliseconds> duration = {}, Optional<float> speed = {}, + MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default, + Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd = {}, Optional<float> wanderDistanceAtPathEnds = {}, + bool followPathBackwardsFromEndToStart = false, bool generatePath = true); + explicit WaypointMovementGenerator(WaypointPath const& path, bool repeating, Optional<Milliseconds> duration, Optional<float> speed, + MovementWalkRunSpeedSelectionMode speedSelectionMode, + Optional<std::pair<Milliseconds, Milliseconds>> waitTimeRangeAtPathEnd, Optional<float> wanderDistanceAtPathEnds, + bool followPathBackwardsFromEndToStart, bool generatePath); + ~WaypointMovementGenerator(); MovementGeneratorType GetMovementGeneratorType() const override; @@ -72,6 +79,15 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium<Creat uint32 _pathId; bool _repeating; bool _loadedFromDB; + + Optional<TimeTracker> _duration; + Optional<float> _speed; + MovementWalkRunSpeedSelectionMode _speedSelectionMode; + Optional<std::pair<Milliseconds, Milliseconds>> _waitTimeRangeAtPathEnd; + Optional<float> _wanderDistanceAtPathEnds; + bool _followPathBackwardsFromEndToStart; + bool _isReturningToStart; + bool _generatePath; }; #endif |