mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
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
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -57,5 +57,5 @@ WaypointMovementFactory::WaypointMovementFactory() : MovementGeneratorCreator(WA
|
||||
|
||||
MovementGenerator* WaypointMovementFactory::Create(Unit* /*object*/) const
|
||||
{
|
||||
return new WaypointMovementGenerator<Creature>();
|
||||
return new WaypointMovementGenerator<Creature>(0, true);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user