From 62efe280b70cc51749774b84d9831cd4e393b3a6 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Thu, 2 Aug 2018 13:29:22 +0200 Subject: [PATCH] Core/Movement: ported missing random movement changes from movement generator cleanup --- .../RandomMovementGenerator.cpp | 224 ++++++++---------- .../RandomMovementGenerator.h | 20 +- 2 files changed, 109 insertions(+), 135 deletions(-) diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index 00eac7db712..5affa7a4e23 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -16,166 +16,134 @@ * with this program. If not, see . */ -#include "RandomMovementGenerator.h" #include "Creature.h" #include "CreatureGroups.h" #include "Map.h" -#include "MoveSpline.h" #include "MoveSplineInit.h" +#include "MoveSpline.h" +#include "PathGenerator.h" +#include "RandomMovementGenerator.h" #include "Random.h" -#include "Util.h" -#define RUNNING_CHANCE_RANDOMMV 20 //will be "1 / RUNNING_CHANCE_RANDOMMV" +template +RandomMovementGenerator::~RandomMovementGenerator() { } template<> -void RandomMovementGenerator::_setRandomLocation(Creature* creature) +RandomMovementGenerator::~RandomMovementGenerator() { - if (creature->IsMovementPreventedByCasting()) + delete _path; +} + +template +void RandomMovementGenerator::DoInitialize(T*) { } + +template<> +void RandomMovementGenerator::DoInitialize(Creature* owner) +{ + if (!owner || !owner->IsAlive()) + return; + + owner->AddUnitState(UNIT_STATE_ROAMING); + owner->GetPosition(_reference.x, _reference.y, _reference.z); + owner->StopMoving(); + + if (!_wanderDistance) + _wanderDistance = owner->GetRespawnRadius(); + + _timer.Reset(0); +} + +template +void RandomMovementGenerator::DoFinalize(T*) { } + +template<> +void RandomMovementGenerator::DoFinalize(Creature* owner) +{ + owner->ClearUnitState(UNIT_STATE_ROAMING); + owner->StopMoving(); + owner->SetWalk(false); +} + +template +void RandomMovementGenerator::DoReset(T*) { } + +template<> +void RandomMovementGenerator::DoReset(Creature* owner) +{ + DoInitialize(owner); +} + +template +void RandomMovementGenerator::SetRandomLocation(T*) { } + +template<> +void RandomMovementGenerator::SetRandomLocation(Creature* owner) +{ + if (!owner) + return; + + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - creature->CastStop(); + _interrupt = true; + owner->StopMoving(); return; } - float respX, respY, respZ, respO, destX, destY, destZ, travelDistZ; - creature->GetHomePosition(respX, respY, respZ, respO); - Map const* map = creature->GetMap(); + owner->AddUnitState(UNIT_STATE_ROAMING_MOVE); - // For 2D/3D system selection - //bool is_land_ok = creature.CanWalk(); // not used? - //bool is_water_ok = creature.CanSwim(); // not used? - bool is_air_ok = creature->CanFly(); + Position position(_reference.x, _reference.y, _reference.z); + float distance = frand(0.f, 1.f) * _wanderDistance; + float angle = frand(0.f, 1.f) * float(M_PI) * 2.f; + owner->MovePositionToFirstCollision(position, distance, angle); - const float angle = float(rand_norm()) * static_cast(M_PI*2.0f); - const float range = float(rand_norm()) * wander_distance; - const float distanceX = range * std::cos(angle); - const float distanceY = range * std::sin(angle); + uint32 resetTimer = roll_chance_i(50) ? urand(5000, 10000) : urand(1000, 2000); - destX = respX + distanceX; - destY = respY + distanceY; + if (!_path) + _path = new PathGenerator(owner); - // prevent invalid coordinates generation - Trinity::NormalizeMapCoord(destX); - Trinity::NormalizeMapCoord(destY); - - travelDistZ = range; // sin^2+cos^2=1, so travelDistZ=range^2; no need for sqrt below - - if (is_air_ok) // 3D system above ground and above water (flying mode) + _path->SetPathLengthLimit(30.0f); + bool result = _path->CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ()); + if (!result || (_path->GetPathType() & PATHFIND_NOPATH)) { - // Limit height change - const float distanceZ = float(rand_norm()) * travelDistZ/2.0f; - destZ = respZ + distanceZ; - float levelZ = map->GetWaterOrGroundLevel(creature->GetPhaseShift(), destX, destY, destZ-2.5f); - - // Problem here, we must fly above the ground and water, not under. Let's try on next tick - if (levelZ >= destZ) - return; - } - //else if (is_water_ok) // 3D system under water and above ground (swimming mode) - else // 2D only - { - // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE) - travelDistZ = travelDistZ >= 10.0f ? 10.0f : travelDistZ; - - // The fastest way to get an accurate result 90% of the time. - // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long. - destZ = map->GetHeight(creature->GetPhaseShift(), destX, destY, respZ+travelDistZ-2.0f, false); - - if (std::fabs(destZ - respZ) > travelDistZ) // Map check - { - // Vmap Horizontal or above - destZ = map->GetHeight(creature->GetPhaseShift(), destX, destY, respZ - 2.0f, true); - - if (std::fabs(destZ - respZ) > travelDistZ) - { - // Vmap Higher - destZ = map->GetHeight(creature->GetPhaseShift(), destX, destY, respZ+travelDistZ-2.0f, true); - - // let's forget this bad coords where a z cannot be find and retry at next tick - if (std::fabs(destZ - respZ) > travelDistZ) - return; - } - } + _timer.Reset(100); + return; } - if (is_air_ok) - i_nextMoveTime.Reset(0); - else - { - if (roll_chance_i(50)) - i_nextMoveTime.Reset(urand(5000, 10000)); - else - i_nextMoveTime.Reset(urand(50, 400)); - } - - creature->AddUnitState(UNIT_STATE_ROAMING_MOVE); - - Movement::MoveSplineInit init(creature); - init.MoveTo(destX, destY, destZ); + Movement::MoveSplineInit init(owner); + init.MovebyPath(_path->GetPath()); init.SetWalk(true); - init.Launch(); + int32 traveltime = init.Launch(); + _timer.Reset(traveltime + resetTimer); - //Call for creature group update - if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature) - creature->GetFormation()->LeaderMoveTo(destX, destY, destZ); + // Call for creature group update + if (owner->GetFormation() && owner->GetFormation()->getLeader() == owner) + owner->GetFormation()->LeaderMoveTo(position.m_positionX, position.m_positionY, position.m_positionZ); +} + +template +bool RandomMovementGenerator::DoUpdate(T*, uint32) +{ + return false; } template<> -void RandomMovementGenerator::DoInitialize(Creature* creature) +bool RandomMovementGenerator::DoUpdate(Creature* owner, uint32 diff) { - if (!creature->IsAlive()) - return; - - if (!wander_distance) - wander_distance = creature->GetRespawnRadius(); - - creature->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); - _setRandomLocation(creature); -} - -template<> -void RandomMovementGenerator::DoReset(Creature* creature) -{ - DoInitialize(creature); -} - -template<> -void RandomMovementGenerator::DoFinalize(Creature* creature) -{ - creature->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); - creature->SetWalk(false); -} - -template<> -bool RandomMovementGenerator::DoUpdate(Creature* creature, const uint32 diff) -{ - if (!creature || !creature->IsAlive()) + if (!owner || !owner->IsAlive()) return false; - if (creature->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED)) + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting()) { - i_nextMoveTime.Reset(0); // Expire the timer - creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE); + _interrupt = true; + owner->StopMoving(); return true; } + else + _interrupt = false; - if (creature->movespline->Finalized()) - { - i_nextMoveTime.Update(diff); - if (i_nextMoveTime.Passed()) - _setRandomLocation(creature); - } - return true; -} - -template<> -bool RandomMovementGenerator::GetResetPos(Creature* creature, float& x, float& y, float& z) -{ - float radius; - creature->GetRespawnPosition(x, y, z, nullptr, &radius); - - // use current if in range - if (creature->IsWithinDist2d(x, y, radius)) - creature->GetPosition(x, y, z); + _timer.Update(diff); + if (!_interrupt && _timer.Passed() && owner->movespline->Finalized()) + SetRandomLocation(owner); return true; } diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h index 99edbaa2efd..88485dcaed3 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h @@ -26,18 +26,24 @@ template class RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovementGenerator > { public: - RandomMovementGenerator(float spawn_dist = 0.0f) : i_nextMoveTime(0), wander_distance(spawn_dist) { } + explicit RandomMovementGenerator(float distance = 0.0f) : _path(nullptr), _timer(0), _reference(0.f, 0.f, 0.f), _wanderDistance(distance), _interrupt(false) { } + ~RandomMovementGenerator(); + + MovementGeneratorType GetMovementGeneratorType() const override { return RANDOM_MOTION_TYPE; } - void _setRandomLocation(T*); void DoInitialize(T*); void DoFinalize(T*); void DoReset(T*); bool DoUpdate(T*, uint32); - bool GetResetPos(T*, float& x, float& y, float& z); - MovementGeneratorType GetMovementGeneratorType() const override { return RANDOM_MOTION_TYPE; } - private: - TimeTrackerSmall i_nextMoveTime; - float wander_distance; + private: + void SetRandomLocation(T*); + + PathGenerator* _path; + TimeTracker _timer; + G3D::Vector3 _reference; + float _wanderDistance; + bool _interrupt; }; + #endif