diff options
| author | Shauren <shauren.trinity@gmail.com> | 2026-01-04 19:34:22 +0100 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2026-01-04 19:34:22 +0100 |
| commit | 0b85b1b0bc5743f65101b44abc6f5e6ca05b0632 (patch) | |
| tree | 57fdc28f9f1e34b2b9db5e8d3ac42bb5ce8ec86c /src/server | |
| parent | e8a702930e68caa0229040245a38da9669ea1469 (diff) | |
Core/Movement: Add forced speed and movement type parameters to random movement generator
Diffstat (limited to 'src/server')
5 files changed, 70 insertions, 74 deletions
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index af61fd0a27f..768d7004c97 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -593,13 +593,14 @@ void MotionMaster::MoveTargetedHome() } } -void MotionMaster::MoveRandom(float wanderDistance /*= 0.0f*/, Optional<Milliseconds> duration /*= {}*/, MovementSlot slot /*= MOTION_SLOT_DEFAULT*/, +void MotionMaster::MoveRandom(float wanderDistance /*= 0.0f*/, Optional<Milliseconds> duration /*= {}*/, Optional<float> speed /*= {}*/, + MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::ForceWalk*/, MovementSlot slot /*= MOTION_SLOT_DEFAULT*/, Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { if (_owner->GetTypeId() == TYPEID_UNIT) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveRandom: '{}', started random movement (spawnDist: {})", _owner->GetGUID(), wanderDistance); - Add(new RandomMovementGenerator<Creature>(wanderDistance, duration, std::move(scriptResult)), slot); + Add(new RandomMovementGenerator<Creature>(wanderDistance, duration, speed, speedSelectionMode, std::move(scriptResult)), slot); } else if (scriptResult) scriptResult->SetResult(MovementStopReason::Interrupted); diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 1126b6a5cab..d8696cbb44a 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -157,7 +157,8 @@ class TC_GAME_API MotionMaster void MoveIdle(); void MoveTargetedHome(); - void MoveRandom(float wanderDistance = 0.0f, Optional<Milliseconds> duration = {}, MovementSlot slot = MOTION_SLOT_DEFAULT, + void MoveRandom(float wanderDistance = 0.0f, Optional<Milliseconds> duration = {}, Optional<float> speed = {}, + MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::ForceWalk, MovementSlot slot = MOTION_SLOT_DEFAULT, Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); void MoveFollow(Unit* target, float dist, Optional<ChaseAngle> angle = {}, Optional<Milliseconds> duration = {}, bool ignoreTargetWalk = false, MovementSlot slot = MOTION_SLOT_ACTIVE, Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index ff705836a88..12dcb0dda19 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -25,8 +25,10 @@ #include "Random.h" template<class T> -RandomMovementGenerator<T>::RandomMovementGenerator(float distance, Optional<Milliseconds> duration, - Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) : _timer(0), _reference(), _wanderDistance(distance), _wanderSteps(0) +RandomMovementGenerator<T>::RandomMovementGenerator(float distance, Optional<Milliseconds> duration, Optional<float> speed, + MovementWalkRunSpeedSelectionMode speedSelectionMode, + Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) + : _timer(0), _speed(speed), _speedSelectionMode(speedSelectionMode), _wanderDistance(distance), _wanderSteps(0) { this->Mode = MOTION_MODE_DEFAULT; this->Priority = MOTION_PRIORITY_NORMAL; @@ -37,10 +39,6 @@ RandomMovementGenerator<T>::RandomMovementGenerator(float distance, Optional<Mil _duration.emplace(*duration); } -template -RandomMovementGenerator<Creature>::RandomMovementGenerator(float distance, Optional<Milliseconds> duration, - Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult); - template<class T> MovementGeneratorType RandomMovementGenerator<T>::GetMovementGeneratorType() const { @@ -72,26 +70,18 @@ void RandomMovementGenerator<T>::Resume(uint32 overrideTimer) this->RemoveFlag(MOVEMENTGENERATOR_FLAG_PAUSED); } -template MovementGeneratorType RandomMovementGenerator<Creature>::GetMovementGeneratorType() const; - template<class T> -void RandomMovementGenerator<T>::DoInitialize(T*) { } - -template<> -void RandomMovementGenerator<Creature>::DoInitialize(Creature* owner) +void RandomMovementGenerator<T>::DoInitialize(T* owner) { - RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING | MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED | MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); - AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_INITIALIZATION_PENDING | MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED | MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); + this->AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED); - if (!owner || !owner->IsAlive()) + if (!owner->IsAlive()) return; _reference = owner->GetPosition(); owner->StopMoving(); - if (_wanderDistance == 0.f) - _wanderDistance = owner->GetWanderDistance(); - // Retail seems to let a creature walk 2 up to 10 splines before triggering a pause _wanderSteps = urand(2, 10); @@ -100,28 +90,19 @@ void RandomMovementGenerator<Creature>::DoInitialize(Creature* owner) } template<class T> -void RandomMovementGenerator<T>::DoReset(T*) { } - -template<> -void RandomMovementGenerator<Creature>::DoReset(Creature* owner) +void RandomMovementGenerator<T>::DoReset(T* owner) { - RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); DoInitialize(owner); } template<class T> -void RandomMovementGenerator<T>::SetRandomLocation(T*) { } - -template<> -void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner) +void RandomMovementGenerator<T>::SetRandomLocation(T* owner) { - if (!owner) - return; - if (owner->HasUnitState(UNIT_STATE_NOT_MOVE | UNIT_STATE_LOST_CONTROL) || owner->IsMovementPreventedByCasting()) { - AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); + this->AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); owner->StopMoving(); _path = nullptr; return; @@ -163,26 +144,30 @@ void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner) return; } - RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_TIMED_PAUSED); owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); - bool walk = true; - switch (owner->GetMovementTemplate().GetRandom()) + Movement::MoveSplineInit init(owner); + init.MovebyPath(_path->GetPath()); + + switch (_speedSelectionMode) { - case CreatureRandomMovementType::CanRun: - walk = owner->IsWalking(); + case MovementWalkRunSpeedSelectionMode::Default: break; - case CreatureRandomMovementType::AlwaysRun: - walk = false; + case MovementWalkRunSpeedSelectionMode::ForceRun: + init.SetWalk(false); + break; + case MovementWalkRunSpeedSelectionMode::ForceWalk: + init.SetWalk(true); break; default: break; } - Movement::MoveSplineInit init(owner); - init.MovebyPath(_path->GetPath()); - init.SetWalk(walk); + if (_speed) + init.SetVelocity(*_speed); + int32 splineDuration = init.Launch(); --_wanderSteps; @@ -200,18 +185,12 @@ void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner) } template<class T> -bool RandomMovementGenerator<T>::DoUpdate(T*, uint32) +bool RandomMovementGenerator<T>::DoUpdate(T* owner, uint32 diff) { - return false; -} - -template<> -bool RandomMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 diff) -{ - if (!owner || !owner->IsAlive()) + if (!owner->IsAlive()) return true; - if (HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED | MOVEMENTGENERATOR_FLAG_PAUSED)) + if (this->HasFlag(MOVEMENTGENERATOR_FLAG_FINALIZED | MOVEMENTGENERATOR_FLAG_PAUSED)) return true; if (_duration) @@ -219,46 +198,40 @@ bool RandomMovementGenerator<Creature>::DoUpdate(Creature* owner, uint32 diff) _duration->Update(diff); if (_duration->Passed()) { - RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY); - AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY); + this->AddFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED); return false; } } if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); + this->AddFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); owner->StopMoving(); _path = nullptr; return true; } else - RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_INTERRUPTED); _timer.Update(diff); - if ((HasFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING) && !owner->movespline->Finalized()) || (_timer.Passed() && owner->movespline->Finalized())) + if ((this->HasFlag(MOVEMENTGENERATOR_FLAG_SPEED_UPDATE_PENDING) && !owner->movespline->Finalized()) || (_timer.Passed() && owner->movespline->Finalized())) SetRandomLocation(owner); return true; } template<class T> -void RandomMovementGenerator<T>::DoDeactivate(T*) { } - -template<> -void RandomMovementGenerator<Creature>::DoDeactivate(Creature* owner) +void RandomMovementGenerator<T>::DoDeactivate(T* owner) { - AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + this->AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); } template<class T> -void RandomMovementGenerator<T>::DoFinalize(T*, bool, bool) { } - -template<> -void RandomMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, bool movementInform) +void RandomMovementGenerator<T>::DoFinalize(T* owner, bool active, bool movementInform) { - AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); + this->AddFlag(MOVEMENTGENERATOR_FLAG_FINALIZED); if (active) { owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); @@ -268,15 +241,33 @@ void RandomMovementGenerator<Creature>::DoFinalize(Creature* owner, bool active, owner->SetWalk(false); } - if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) + if (movementInform && this->HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED)) { - SetScriptResult(MovementStopReason::Finished); + this->SetScriptResult(MovementStopReason::Finished); if (owner->IsAIEnabled()) owner->AI()->MovementInform(RANDOM_MOTION_TYPE, 0); } } -MovementGenerator* RandomMovementFactory::Create(Unit* /*object*/) const +MovementGenerator* RandomMovementFactory::Create(Unit* object) const { - return new RandomMovementGenerator<Creature>(); + Creature* owner = object->ToCreature(); + MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default; + switch (owner->GetMovementTemplate().GetRandom()) + { + case CreatureRandomMovementType::Walk: + speedSelectionMode = MovementWalkRunSpeedSelectionMode::ForceWalk; + break; + case CreatureRandomMovementType::CanRun: + break; + case CreatureRandomMovementType::AlwaysRun: + speedSelectionMode = MovementWalkRunSpeedSelectionMode::ForceRun; + break; + default: + break; + } + + return new RandomMovementGenerator<Creature>(object->ToCreature()->GetWanderDistance(), {}, {}, speedSelectionMode); } + +template class RandomMovementGenerator<Creature>; diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h index f67b4096e70..51dcd19f8e8 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h @@ -29,7 +29,8 @@ template<class T> class RandomMovementGenerator : public MovementGeneratorMedium<T, RandomMovementGenerator<T>> { public: - explicit RandomMovementGenerator(float distance = 0.0f, Optional<Milliseconds> duration = {}, + explicit RandomMovementGenerator(float distance, Optional<Milliseconds> duration = {}, Optional<float> speed = {}, + MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default, Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); MovementGeneratorType GetMovementGeneratorType() const override; @@ -51,6 +52,8 @@ class RandomMovementGenerator : public MovementGeneratorMedium<T, RandomMovement std::unique_ptr<PathGenerator> _path; TimeTracker _timer; Optional<TimeTracker> _duration; + Optional<float> _speed; + MovementWalkRunSpeedSelectionMode _speedSelectionMode; Position _reference; float _wanderDistance; uint8 _wanderSteps; diff --git a/src/server/scripts/Zandalar/Underrot/boss_cragmaw_the_infested.cpp b/src/server/scripts/Zandalar/Underrot/boss_cragmaw_the_infested.cpp index 4c174e055a3..163cc81128c 100644 --- a/src/server/scripts/Zandalar/Underrot/boss_cragmaw_the_infested.cpp +++ b/src/server/scripts/Zandalar/Underrot/boss_cragmaw_the_infested.cpp @@ -155,7 +155,7 @@ struct boss_cragmaw_the_infested : public BossAI void MovementInform(uint32 /*type*/, uint32 id) override { if (id == POINT_TANTRUM_START_RND_MOVEMENT) - me->GetMotionMaster()->MoveRandom(20.0f); + me->GetMotionMaster()->MoveRandom(20.0f, {}, {}, MovementWalkRunSpeedSelectionMode::ForceRun); } void OnChannelFinished(SpellInfo const* spell) override |
