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 duration /*= {}*/, MovementSlot slot /*= MOTION_SLOT_DEFAULT*/, +void MotionMaster::MoveRandom(float wanderDistance /*= 0.0f*/, Optional duration /*= {}*/, Optional speed /*= {}*/, + MovementWalkRunSpeedSelectionMode speedSelectionMode /*= MovementWalkRunSpeedSelectionMode::ForceWalk*/, MovementSlot slot /*= MOTION_SLOT_DEFAULT*/, Optional>&& scriptResult /*= {}*/) { if (_owner->GetTypeId() == TYPEID_UNIT) { TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveRandom: '{}', started random movement (spawnDist: {})", _owner->GetGUID(), wanderDistance); - Add(new RandomMovementGenerator(wanderDistance, duration, std::move(scriptResult)), slot); + Add(new RandomMovementGenerator(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 duration = {}, MovementSlot slot = MOTION_SLOT_DEFAULT, + void MoveRandom(float wanderDistance = 0.0f, Optional duration = {}, Optional speed = {}, + MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::ForceWalk, MovementSlot slot = MOTION_SLOT_DEFAULT, Optional>&& scriptResult = {}); void MoveFollow(Unit* target, float dist, Optional angle = {}, Optional duration = {}, bool ignoreTargetWalk = false, MovementSlot slot = MOTION_SLOT_ACTIVE, Optional>&& 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 -RandomMovementGenerator::RandomMovementGenerator(float distance, Optional duration, - Optional>&& scriptResult /*= {}*/) : _timer(0), _reference(), _wanderDistance(distance), _wanderSteps(0) +RandomMovementGenerator::RandomMovementGenerator(float distance, Optional duration, Optional speed, + MovementWalkRunSpeedSelectionMode speedSelectionMode, + Optional>&& 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::RandomMovementGenerator(float distance, Optional::RandomMovementGenerator(float distance, Optional duration, - Optional>&& scriptResult); - template MovementGeneratorType RandomMovementGenerator::GetMovementGeneratorType() const { @@ -72,26 +70,18 @@ void RandomMovementGenerator::Resume(uint32 overrideTimer) this->RemoveFlag(MOVEMENTGENERATOR_FLAG_PAUSED); } -template MovementGeneratorType RandomMovementGenerator::GetMovementGeneratorType() const; - template -void RandomMovementGenerator::DoInitialize(T*) { } - -template<> -void RandomMovementGenerator::DoInitialize(Creature* owner) +void RandomMovementGenerator::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::DoInitialize(Creature* owner) } template -void RandomMovementGenerator::DoReset(T*) { } - -template<> -void RandomMovementGenerator::DoReset(Creature* owner) +void RandomMovementGenerator::DoReset(T* owner) { - RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); + this->RemoveFlag(MOVEMENTGENERATOR_FLAG_TRANSITORY | MOVEMENTGENERATOR_FLAG_DEACTIVATED); DoInitialize(owner); } template -void RandomMovementGenerator::SetRandomLocation(T*) { } - -template<> -void RandomMovementGenerator::SetRandomLocation(Creature* owner) +void RandomMovementGenerator::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::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::SetRandomLocation(Creature* owner) } template -bool RandomMovementGenerator::DoUpdate(T*, uint32) +bool RandomMovementGenerator::DoUpdate(T* owner, uint32 diff) { - return false; -} - -template<> -bool RandomMovementGenerator::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::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 -void RandomMovementGenerator::DoDeactivate(T*) { } - -template<> -void RandomMovementGenerator::DoDeactivate(Creature* owner) +void RandomMovementGenerator::DoDeactivate(T* owner) { - AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); + this->AddFlag(MOVEMENTGENERATOR_FLAG_DEACTIVATED); owner->ClearUnitState(UNIT_STATE_ROAMING_MOVE); } template -void RandomMovementGenerator::DoFinalize(T*, bool, bool) { } - -template<> -void RandomMovementGenerator::DoFinalize(Creature* owner, bool active, bool movementInform) +void RandomMovementGenerator::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::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* 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(object->ToCreature()->GetWanderDistance(), {}, {}, speedSelectionMode); } + +template class RandomMovementGenerator; 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 RandomMovementGenerator : public MovementGeneratorMedium> { public: - explicit RandomMovementGenerator(float distance = 0.0f, Optional duration = {}, + explicit RandomMovementGenerator(float distance, Optional duration = {}, Optional speed = {}, + MovementWalkRunSpeedSelectionMode speedSelectionMode = MovementWalkRunSpeedSelectionMode::Default, Optional>&& scriptResult = {}); MovementGeneratorType GetMovementGeneratorType() const override; @@ -51,6 +52,8 @@ class RandomMovementGenerator : public MovementGeneratorMedium _path; TimeTracker _timer; Optional _duration; + Optional _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