mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-21 17:54:48 +01:00
Core/Movement: ported missing random movement changes from movement generator cleanup
This commit is contained in:
@@ -16,166 +16,134 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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<class T>
|
||||
RandomMovementGenerator<T>::~RandomMovementGenerator() { }
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
|
||||
RandomMovementGenerator<Creature>::~RandomMovementGenerator()
|
||||
{
|
||||
if (creature->IsMovementPreventedByCasting())
|
||||
delete _path;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void RandomMovementGenerator<T>::DoInitialize(T*) { }
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::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<class T>
|
||||
void RandomMovementGenerator<T>::DoFinalize(T*) { }
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::DoFinalize(Creature* owner)
|
||||
{
|
||||
owner->ClearUnitState(UNIT_STATE_ROAMING);
|
||||
owner->StopMoving();
|
||||
owner->SetWalk(false);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void RandomMovementGenerator<T>::DoReset(T*) { }
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::DoReset(Creature* owner)
|
||||
{
|
||||
DoInitialize(owner);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void RandomMovementGenerator<T>::SetRandomLocation(T*) { }
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::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<float>(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<class T>
|
||||
bool RandomMovementGenerator<T>::DoUpdate(T*, uint32)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::DoInitialize(Creature* creature)
|
||||
bool RandomMovementGenerator<Creature>::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<Creature>::DoReset(Creature* creature)
|
||||
{
|
||||
DoInitialize(creature);
|
||||
}
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::DoFinalize(Creature* creature)
|
||||
{
|
||||
creature->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
|
||||
creature->SetWalk(false);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool RandomMovementGenerator<Creature>::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<Creature>::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;
|
||||
}
|
||||
|
||||
@@ -26,18 +26,24 @@ template<class T>
|
||||
class RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovementGenerator<T> >
|
||||
{
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user