refactor(Core/Game): restyle game lib with astyle (#3466)

This commit is contained in:
Kargatum
2020-10-12 15:08:15 +07:00
committed by GitHub
parent e99b526e17
commit a2b26272d2
338 changed files with 52196 additions and 50944 deletions

View File

@@ -33,19 +33,19 @@ void ConfusedMovementGenerator<T>::DoInitialize(T* unit)
for (uint8 idx = 0; idx < MAX_CONF_WAYPOINTS + 1; ++idx)
{
float wanderX = x + (wander_distance * (float)rand_norm() - wander_distance/2);
float wanderY = y + (wander_distance * (float)rand_norm() - wander_distance/2);
float wanderX = x + (wander_distance * (float)rand_norm() - wander_distance / 2);
float wanderY = y + (wander_distance * (float)rand_norm() - wander_distance / 2);
// prevent invalid coordinates generation
acore::NormalizeMapCoord(wanderX);
acore::NormalizeMapCoord(wanderY);
float new_z = map->GetHeight(unit->GetPhaseMask(), wanderX, wanderY, z, true);
if (new_z <= INVALID_HEIGHT || fabs(z-new_z) > 3.0f) // pussywizard
if (new_z <= INVALID_HEIGHT || fabs(z - new_z) > 3.0f) // pussywizard
{
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x;
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y;
i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx-1][2] : z;
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx - 1][0] : x;
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx - 1][1] : y;
i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx - 1][2] : z;
continue;
}
else if (unit->IsWithinLOS(wanderX, wanderY, z))
@@ -55,19 +55,19 @@ void ConfusedMovementGenerator<T>::DoInitialize(T* unit)
if ((is_water && !is_water_ok) || (!is_water && !is_land_ok))
{
//! Cannot use coordinates outside our InhabitType. Use the current or previous position.
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x;
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y;
i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx-1][2] : z;
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx - 1][0] : x;
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx - 1][1] : y;
i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx - 1][2] : z;
continue;
}
}
else
{
//! Trying to access path outside line of sight. Skip this by using the current or previous position.
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x;
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y;
i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx-1][2] : z;
i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx - 1][0] : x;
i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx - 1][1] : y;
i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx - 1][2] : z;
continue;
}
@@ -89,14 +89,14 @@ void ConfusedMovementGenerator<T>::DoInitialize(T* unit)
}
template<>
void ConfusedMovementGenerator<Creature>::_InitSpecific(Creature* creature, bool &is_water_ok, bool &is_land_ok)
void ConfusedMovementGenerator<Creature>::_InitSpecific(Creature* creature, bool& is_water_ok, bool& is_land_ok)
{
is_water_ok = creature->CanSwim();
is_land_ok = creature->CanWalk();
}
template<>
void ConfusedMovementGenerator<Player>::_InitSpecific(Player* , bool &is_water_ok, bool &is_land_ok)
void ConfusedMovementGenerator<Player>::_InitSpecific(Player*, bool& is_water_ok, bool& is_land_ok)
{
is_water_ok = true;
is_land_ok = true;

View File

@@ -15,19 +15,19 @@
template<class T>
class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMovementGenerator<T> >
{
public:
explicit ConfusedMovementGenerator() : i_nextMoveTime(1) {}
public:
explicit ConfusedMovementGenerator() : i_nextMoveTime(1) {}
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
bool DoUpdate(T*, uint32);
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
bool DoUpdate(T*, uint32);
MovementGeneratorType GetMovementGeneratorType() { return CONFUSED_MOTION_TYPE; }
private:
void _InitSpecific(T*, bool &, bool &);
TimeTracker i_nextMoveTime;
float i_waypoints[MAX_CONF_WAYPOINTS+1][3];
uint32 i_nextMove;
MovementGeneratorType GetMovementGeneratorType() { return CONFUSED_MOTION_TYPE; }
private:
void _InitSpecific(T*, bool&, bool&);
TimeTracker i_nextMoveTime;
float i_waypoints[MAX_CONF_WAYPOINTS + 1][3];
uint32 i_nextMove;
};
#endif

View File

@@ -17,7 +17,7 @@ void EscortMovementGenerator<T>::DoInitialize(T* unit)
if (!unit->IsStopped())
unit->StopMoving();
unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
unit->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
i_recalculateSpeed = false;
Movement::MoveSplineInit init(unit);
@@ -80,7 +80,7 @@ bool EscortMovementGenerator<T>::DoUpdate(T* unit, uint32 /*diff*/)
template<class T>
void EscortMovementGenerator<T>::DoFinalize(T* unit)
{
unit->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
unit->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
}
template<class T>
@@ -89,7 +89,7 @@ void EscortMovementGenerator<T>::DoReset(T* unit)
if (!unit->IsStopped())
unit->StopMoving();
unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
unit->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
}
template void EscortMovementGenerator<Player>::DoInitialize(Player*);

View File

@@ -10,29 +10,29 @@ Written by Xinef
template<class T>
class EscortMovementGenerator : public MovementGeneratorMedium< T, EscortMovementGenerator<T> >
{
public:
EscortMovementGenerator(Movement::PointsArray* _path = nullptr) : i_recalculateSpeed(false)
{
if (_path)
m_precomputedPath = *_path;
}
public:
EscortMovementGenerator(Movement::PointsArray* _path = nullptr) : i_recalculateSpeed(false)
{
if (_path)
m_precomputedPath = *_path;
}
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
bool DoUpdate(T*, uint32);
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
bool DoUpdate(T*, uint32);
void unitSpeedChanged() { i_recalculateSpeed = true; }
void unitSpeedChanged() { i_recalculateSpeed = true; }
MovementGeneratorType GetMovementGeneratorType() { return ESCORT_MOTION_TYPE; }
MovementGeneratorType GetMovementGeneratorType() { return ESCORT_MOTION_TYPE; }
uint32 GetSplineId() const { return _splineId; }
uint32 GetSplineId() const { return _splineId; }
private:
bool i_recalculateSpeed;
Movement::PointsArray m_precomputedPath;
private:
bool i_recalculateSpeed;
Movement::PointsArray m_precomputedPath;
uint32 _splineId;
uint32 _splineId;
};
#endif

View File

@@ -35,10 +35,10 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T* owner)
// Add LOS check for target point
bool isInLOS = VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(owner->GetMapId(),
owner->GetPositionX(),
owner->GetPositionY(),
owner->GetPositionZ() + 2.0f,
x, y, z + 2.0f);
owner->GetPositionX(),
owner->GetPositionY(),
owner->GetPositionZ() + 2.0f,
x, y, z + 2.0f);
if (!isInLOS)
{
@@ -49,13 +49,13 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T* owner)
owner->AddUnitState(UNIT_STATE_FLEEING_MOVE);
Movement::MoveSplineInit init(owner);
init.MoveTo(x,y,z);
init.MoveTo(x, y, z);
init.SetWalk(false);
init.Launch();
}
template<class T>
bool FleeingMovementGenerator<T>::_getPoint(T* owner, float &x, float &y, float &z)
bool FleeingMovementGenerator<T>::_getPoint(T* owner, float& x, float& y, float& z)
{
if (!owner)
return false;
@@ -88,55 +88,55 @@ bool FleeingMovementGenerator<T>::_getPoint(T* owner, float &x, float &y, float
distance /= 4;
break;
case 3:
angle = i_cur_angle + static_cast<float>(M_PI/4);
angle = i_cur_angle + static_cast<float>(M_PI / 4);
break;
case 4:
angle = i_cur_angle - static_cast<float>(M_PI/4);
angle = i_cur_angle - static_cast<float>(M_PI / 4);
break;
case 5:
angle = i_cur_angle + static_cast<float>(M_PI/4);
angle = i_cur_angle + static_cast<float>(M_PI / 4);
distance /= 2;
break;
case 6:
angle = i_cur_angle - static_cast<float>(M_PI/4);
angle = i_cur_angle - static_cast<float>(M_PI / 4);
distance /= 2;
break;
case 7:
angle = i_cur_angle + static_cast<float>(M_PI/2);
angle = i_cur_angle + static_cast<float>(M_PI / 2);
break;
case 8:
angle = i_cur_angle - static_cast<float>(M_PI/2);
angle = i_cur_angle - static_cast<float>(M_PI / 2);
break;
case 9:
angle = i_cur_angle + static_cast<float>(M_PI/2);
angle = i_cur_angle + static_cast<float>(M_PI / 2);
distance /= 2;
break;
case 10:
angle = i_cur_angle - static_cast<float>(M_PI/2);
angle = i_cur_angle - static_cast<float>(M_PI / 2);
distance /= 2;
break;
case 11:
angle = i_cur_angle + static_cast<float>(M_PI/4);
angle = i_cur_angle + static_cast<float>(M_PI / 4);
distance /= 4;
break;
case 12:
angle = i_cur_angle - static_cast<float>(M_PI/4);
angle = i_cur_angle - static_cast<float>(M_PI / 4);
distance /= 4;
break;
case 13:
angle = i_cur_angle + static_cast<float>(M_PI/2);
angle = i_cur_angle + static_cast<float>(M_PI / 2);
distance /= 4;
break;
case 14:
angle = i_cur_angle - static_cast<float>(M_PI/2);
angle = i_cur_angle - static_cast<float>(M_PI / 2);
distance /= 4;
break;
case 15:
angle = i_cur_angle + static_cast<float>(3*M_PI/4);
angle = i_cur_angle + static_cast<float>(3 * M_PI / 4);
distance /= 2;
break;
case 16:
angle = i_cur_angle - static_cast<float>(3*M_PI/4);
angle = i_cur_angle - static_cast<float>(3 * M_PI / 4);
distance /= 2;
break;
case 17:
@@ -155,9 +155,9 @@ bool FleeingMovementGenerator<T>::_getPoint(T* owner, float &x, float &y, float
acore::NormalizeMapCoord(temp_y);
if (owner->IsWithinLOS(temp_x, temp_y, z))
{
bool is_water_now = _map->IsInWater(x,y,z);
bool is_water_now = _map->IsInWater(x, y, z);
if (is_water_now && _map->IsInWater(temp_x,temp_y,z))
if (is_water_now && _map->IsInWater(temp_x, temp_y, z))
{
x = temp_x;
y = temp_y;
@@ -165,7 +165,7 @@ bool FleeingMovementGenerator<T>::_getPoint(T* owner, float &x, float &y, float
}
float new_z = _map->GetHeight(owner->GetPhaseMask(), temp_x, temp_y, z, true);
if (new_z <= INVALID_HEIGHT || fabs(z-new_z) > 3.0f)
if (new_z <= INVALID_HEIGHT || fabs(z - new_z) > 3.0f)
continue;
bool is_water_next = _map->IsInWater(temp_x, temp_y, new_z);
@@ -175,8 +175,8 @@ bool FleeingMovementGenerator<T>::_getPoint(T* owner, float &x, float &y, float
if (!(new_z - z) || distance / fabs(new_z - z) > 1.0f)
{
float new_z_left = _map->GetHeight(owner->GetPhaseMask(), temp_x + 1.0f*cos(angle+static_cast<float>(M_PI/2)),temp_y + 1.0f*sin(angle+static_cast<float>(M_PI/2)),z,true);
float new_z_right = _map->GetHeight(owner->GetPhaseMask(), temp_x + 1.0f*cos(angle-static_cast<float>(M_PI/2)),temp_y + 1.0f*sin(angle-static_cast<float>(M_PI/2)),z,true);
float new_z_left = _map->GetHeight(owner->GetPhaseMask(), temp_x + 1.0f * cos(angle + static_cast<float>(M_PI / 2)), temp_y + 1.0f * sin(angle + static_cast<float>(M_PI / 2)), z, true);
float new_z_right = _map->GetHeight(owner->GetPhaseMask(), temp_x + 1.0f * cos(angle - static_cast<float>(M_PI / 2)), temp_y + 1.0f * sin(angle - static_cast<float>(M_PI / 2)), z, true);
if (fabs(new_z_left - new_z) < 1.2f && fabs(new_z_right - new_z) < 1.2f)
{
x = temp_x;
@@ -188,7 +188,7 @@ bool FleeingMovementGenerator<T>::_getPoint(T* owner, float &x, float &y, float
}
}
i_to_distance_from_caster = 0.0f;
i_nextCheckTime.Reset(urand(500,1000));
i_nextCheckTime.Reset(urand(500, 1000));
return false;
}
@@ -200,18 +200,18 @@ bool FleeingMovementGenerator<T>::_setMoveData(T* owner)
if (i_to_distance_from_caster > 0.0f)
{
if ((i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz < i_to_distance_from_caster) ||
// if we reach lower distance
(i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz > i_last_distance_from_caster) ||
// if we can't be close
(i_last_distance_from_caster < i_to_distance_from_caster && cur_dist_xyz > i_to_distance_from_caster) ||
// if we reach bigger distance
(cur_dist_xyz > MAX_QUIET_DISTANCE) || // if we are too far
(i_last_distance_from_caster > MIN_QUIET_DISTANCE && cur_dist_xyz < MIN_QUIET_DISTANCE))
// if we leave 'quiet zone'
// if we reach lower distance
(i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz > i_last_distance_from_caster) ||
// if we can't be close
(i_last_distance_from_caster < i_to_distance_from_caster && cur_dist_xyz > i_to_distance_from_caster) ||
// if we reach bigger distance
(cur_dist_xyz > MAX_QUIET_DISTANCE) || // if we are too far
(i_last_distance_from_caster > MIN_QUIET_DISTANCE && cur_dist_xyz < MIN_QUIET_DISTANCE))
// if we leave 'quiet zone'
{
// we are very far or too close, stopping
i_to_distance_from_caster = 0.0f;
i_nextCheckTime.Reset(urand(500,1000));
i_nextCheckTime.Reset(urand(500, 1000));
return false;
}
else
@@ -248,35 +248,35 @@ bool FleeingMovementGenerator<T>::_setMoveData(T* owner)
}
// if we too close may use 'path-finding' else just stop
i_only_forward = cur_dist >= MIN_QUIET_DISTANCE/3;
i_only_forward = cur_dist >= MIN_QUIET_DISTANCE / 3;
//get angle and 'distance from caster' to run
float angle;
if (i_cur_angle == 0.0f && i_last_distance_from_caster == 0.0f) //just started, first time
{
angle = (float)rand_norm()*(1.0f - cur_dist/MIN_QUIET_DISTANCE) * static_cast<float>(M_PI/3) + (float)rand_norm()*static_cast<float>(M_PI*2/3);
angle = (float)rand_norm() * (1.0f - cur_dist / MIN_QUIET_DISTANCE) * static_cast<float>(M_PI / 3) + (float)rand_norm() * static_cast<float>(M_PI * 2 / 3);
i_to_distance_from_caster = MIN_QUIET_DISTANCE;
i_only_forward = true;
}
else if (cur_dist < MIN_QUIET_DISTANCE)
{
angle = static_cast<float>(M_PI/6) + (float)rand_norm()*static_cast<float>(M_PI*2/3);
i_to_distance_from_caster = cur_dist*2/3 + (float)rand_norm()*(MIN_QUIET_DISTANCE - cur_dist*2/3);
angle = static_cast<float>(M_PI / 6) + (float)rand_norm() * static_cast<float>(M_PI * 2 / 3);
i_to_distance_from_caster = cur_dist * 2 / 3 + (float)rand_norm() * (MIN_QUIET_DISTANCE - cur_dist * 2 / 3);
}
else if (cur_dist > MAX_QUIET_DISTANCE)
{
angle = (float)rand_norm()*static_cast<float>(M_PI/3) + static_cast<float>(M_PI*2/3);
i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + (float)rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f);
angle = (float)rand_norm() * static_cast<float>(M_PI / 3) + static_cast<float>(M_PI * 2 / 3);
i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + (float)rand_norm() * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f);
}
else
{
angle = (float)rand_norm()*static_cast<float>(M_PI);
i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + (float)rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f);
angle = (float)rand_norm() * static_cast<float>(M_PI);
i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + (float)rand_norm() * (MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f);
}
int8 sign = (float)rand_norm() > 0.5f ? 1 : -1;
i_cur_angle = sign*angle + angle_to_caster;
i_cur_angle = sign * angle + angle_to_caster;
// current distance
i_last_distance_from_caster = cur_dist;
@@ -291,7 +291,7 @@ void FleeingMovementGenerator<T>::DoInitialize(T* owner)
return;
owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
owner->AddUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE);
owner->AddUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE);
_Init(owner);
@@ -337,14 +337,14 @@ template<>
void FleeingMovementGenerator<Player>::DoFinalize(Player* owner)
{
owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
owner->ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE);
owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE);
}
template<>
void FleeingMovementGenerator<Creature>::DoFinalize(Creature* owner)
{
owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
owner->ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE);
owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE);
if (owner->GetVictim())
owner->SetTarget(owner->GetVictim()->GetGUID());
}
@@ -390,7 +390,7 @@ template bool FleeingMovementGenerator<Creature>::DoUpdate(Creature*, uint32);
void TimedFleeingMovementGenerator::Finalize(Unit* owner)
{
owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
owner->ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE);
owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE);
if (owner->GetVictim())
owner->SetTarget(owner->GetVictim()->GetGUID());
}

View File

@@ -12,49 +12,49 @@
template<class T>
class FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovementGenerator<T> >
{
public:
FleeingMovementGenerator(uint64 fright) : i_frightGUID(fright), i_nextCheckTime(0) {}
public:
FleeingMovementGenerator(uint64 fright) : i_frightGUID(fright), i_nextCheckTime(0) {}
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
bool DoUpdate(T*, uint32);
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
bool DoUpdate(T*, uint32);
MovementGeneratorType GetMovementGeneratorType() { return FLEEING_MOTION_TYPE; }
MovementGeneratorType GetMovementGeneratorType() { return FLEEING_MOTION_TYPE; }
private:
void _setTargetLocation(T*);
bool _getPoint(T*, float &x, float &y, float &z);
bool _setMoveData(T* owner);
void _Init(T* );
private:
void _setTargetLocation(T*);
bool _getPoint(T*, float& x, float& y, float& z);
bool _setMoveData(T* owner);
void _Init(T* );
bool is_water_ok :1;
bool is_land_ok :1;
bool i_only_forward:1;
bool is_water_ok : 1;
bool is_land_ok : 1;
bool i_only_forward: 1;
float i_caster_x;
float i_caster_y;
float i_caster_z;
float i_last_distance_from_caster;
float i_to_distance_from_caster;
float i_cur_angle;
uint64 i_frightGUID;
TimeTracker i_nextCheckTime;
float i_caster_x;
float i_caster_y;
float i_caster_z;
float i_last_distance_from_caster;
float i_to_distance_from_caster;
float i_cur_angle;
uint64 i_frightGUID;
TimeTracker i_nextCheckTime;
};
class TimedFleeingMovementGenerator : public FleeingMovementGenerator<Creature>
{
public:
TimedFleeingMovementGenerator(uint64 fright, uint32 time) :
FleeingMovementGenerator<Creature>(fright),
i_totalFleeTime(time) {}
public:
TimedFleeingMovementGenerator(uint64 fright, uint32 time) :
FleeingMovementGenerator<Creature>(fright),
i_totalFleeTime(time) {}
MovementGeneratorType GetMovementGeneratorType() { return TIMED_FLEEING_MOTION_TYPE; }
bool Update(Unit*, uint32);
void Finalize(Unit*);
MovementGeneratorType GetMovementGeneratorType() { return TIMED_FLEEING_MOTION_TYPE; }
bool Update(Unit*, uint32);
void Finalize(Unit*);
private:
TimeTracker i_totalFleeTime;
private:
TimeTracker i_totalFleeTime;
};
#endif

View File

@@ -17,21 +17,21 @@ class HomeMovementGenerator;
template <>
class HomeMovementGenerator<Creature> : public MovementGeneratorMedium< Creature, HomeMovementGenerator<Creature> >
{
public:
public:
HomeMovementGenerator() : arrived(false), i_recalculateTravel(false) {}
~HomeMovementGenerator() {}
HomeMovementGenerator() : arrived(false), i_recalculateTravel(false) {}
~HomeMovementGenerator() {}
void DoInitialize(Creature*);
void DoFinalize(Creature*);
void DoReset(Creature*);
bool DoUpdate(Creature*, const uint32);
MovementGeneratorType GetMovementGeneratorType() { return HOME_MOTION_TYPE; }
void unitSpeedChanged() { i_recalculateTravel = true; }
void DoInitialize(Creature*);
void DoFinalize(Creature*);
void DoReset(Creature*);
bool DoUpdate(Creature*, const uint32);
MovementGeneratorType GetMovementGeneratorType() { return HOME_MOTION_TYPE; }
void unitSpeedChanged() { i_recalculateTravel = true; }
private:
void _setTargetLocation(Creature*);
bool arrived : 1;
bool i_recalculateTravel : 1;
private:
void _setTargetLocation(Creature*);
bool arrived : 1;
bool i_recalculateTravel : 1;
};
#endif

View File

@@ -64,7 +64,7 @@ void RotateMovementGenerator::Finalize(Unit* unit)
{
unit->ClearUnitState(UNIT_STATE_ROTATING);
if (unit->GetTypeId() == TYPEID_UNIT)
unit->ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, 0);
unit->ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, 0);
}
void DistractMovementGenerator::Initialize(Unit* owner)

View File

@@ -11,56 +11,56 @@
class IdleMovementGenerator : public MovementGenerator
{
public:
public:
void Initialize(Unit*);
void Finalize(Unit*) { }
void Reset(Unit*);
bool Update(Unit*, uint32) { return true; }
MovementGeneratorType GetMovementGeneratorType() { return IDLE_MOTION_TYPE; }
void Initialize(Unit*);
void Finalize(Unit*) { }
void Reset(Unit*);
bool Update(Unit*, uint32) { return true; }
MovementGeneratorType GetMovementGeneratorType() { return IDLE_MOTION_TYPE; }
};
extern IdleMovementGenerator si_idleMovement;
class RotateMovementGenerator : public MovementGenerator
{
public:
explicit RotateMovementGenerator(uint32 time, RotateDirection direction) : m_duration(time), m_maxDuration(time), m_direction(direction) {}
public:
explicit RotateMovementGenerator(uint32 time, RotateDirection direction) : m_duration(time), m_maxDuration(time), m_direction(direction) {}
void Initialize(Unit*);
void Finalize(Unit*);
void Reset(Unit* owner) { Initialize(owner); }
bool Update(Unit*, uint32);
MovementGeneratorType GetMovementGeneratorType() { return ROTATE_MOTION_TYPE; }
void Initialize(Unit*);
void Finalize(Unit*);
void Reset(Unit* owner) { Initialize(owner); }
bool Update(Unit*, uint32);
MovementGeneratorType GetMovementGeneratorType() { return ROTATE_MOTION_TYPE; }
private:
uint32 m_duration, m_maxDuration;
RotateDirection m_direction;
private:
uint32 m_duration, m_maxDuration;
RotateDirection m_direction;
};
class DistractMovementGenerator : public MovementGenerator
{
public:
explicit DistractMovementGenerator(uint32 timer) : m_timer(timer) {}
public:
explicit DistractMovementGenerator(uint32 timer) : m_timer(timer) {}
void Initialize(Unit*);
void Finalize(Unit*);
void Reset(Unit* owner) { Initialize(owner); }
bool Update(Unit*, uint32);
MovementGeneratorType GetMovementGeneratorType() { return DISTRACT_MOTION_TYPE; }
void Initialize(Unit*);
void Finalize(Unit*);
void Reset(Unit* owner) { Initialize(owner); }
bool Update(Unit*, uint32);
MovementGeneratorType GetMovementGeneratorType() { return DISTRACT_MOTION_TYPE; }
private:
uint32 m_timer;
private:
uint32 m_timer;
};
class AssistanceDistractMovementGenerator : public DistractMovementGenerator
{
public:
AssistanceDistractMovementGenerator(uint32 timer) :
DistractMovementGenerator(timer) {}
public:
AssistanceDistractMovementGenerator(uint32 timer) :
DistractMovementGenerator(timer) {}
MovementGeneratorType GetMovementGeneratorType() { return ASSISTANCE_DISTRACT_MOTION_TYPE; }
void Finalize(Unit*);
MovementGeneratorType GetMovementGeneratorType() { return ASSISTANCE_DISTRACT_MOTION_TYPE; }
void Finalize(Unit*);
};
#endif

View File

@@ -57,7 +57,9 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo
if (!_sourceUnit->movespline->Finalized() && _sourceUnit->movespline->Initialized())
{
Movement::Location realpos = _sourceUnit->movespline->ComputePosition();
x = realpos.x; y = realpos.y; z = realpos.z;
x = realpos.x;
y = realpos.y;
z = realpos.z;
}
else
_sourceUnit->GetPosition(x, y, z);
@@ -91,8 +93,8 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo
// make sure navMesh works - we can run on map w/o mmap
// check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?)
if (!_navMesh || !_navMeshQuery || _sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) ||
_sourceUnit->GetObjectSize() >= SIZE_OF_GRIDS/2.0f || _sourceUnit->GetExactDistSq(destX, destY, destZ) >= (SIZE_OF_GRIDS*SIZE_OF_GRIDS/4.0f) ||
!HaveTile(start) || !HaveTile(dest))
_sourceUnit->GetObjectSize() >= SIZE_OF_GRIDS / 2.0f || _sourceUnit->GetExactDistSq(destX, destY, destZ) >= (SIZE_OF_GRIDS * SIZE_OF_GRIDS / 4.0f) ||
!HaveTile(start) || !HaveTile(dest))
{
BuildShortcut();
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
@@ -114,8 +116,8 @@ dtPolyRef PathGenerator::GetPathPolyByPosition(dtPolyRef const* polyPath, uint32
{
if (DT_SUCCESS != _navMeshQuery->getPolyHeight(polyPath[i], point, &polyHeight))
continue;
height = point[1]-polyHeight;
if (height > 0.0f && height < ALLOWED_DIST_FROM_POLY+ADDED_Z_FOR_POLY_LOOKUP)
height = point[1] - polyHeight;
if (height > 0.0f && height < ALLOWED_DIST_FROM_POLY + ADDED_Z_FOR_POLY_LOOKUP)
{
if (distance)
*distance = height;
@@ -164,7 +166,7 @@ dtPolyRef PathGenerator::GetPolyByLocation(float* point, float* distance) const
return INVALID_POLYREF;
}
G3D::Vector3 ClosestPointOnLine(const G3D::Vector3 & a, const G3D::Vector3 & b, const G3D::Vector3 & Point)
G3D::Vector3 ClosestPointOnLine(const G3D::Vector3& a, const G3D::Vector3& b, const G3D::Vector3& Point)
{
G3D::Vector3 c = Point - a; // Vector from a to Point
G3D::Vector3 v = (b - a).unit(); // Unit Vector from a to b
@@ -199,277 +201,306 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
bool cutToFirstHigher = false;
{
MutexReleaser<ACE_RW_Thread_Mutex> mutexReleaser(mmapLock);
MutexReleaser<ACE_RW_Thread_Mutex> mutexReleaser(mmapLock);
// *** getting start/end poly logic ***
// *** getting start/end poly logic ***
float distToStartPoly, distToEndPoly;
float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x};
float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x};
float distToStartPoly, distToEndPoly;
float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x};
float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x};
dtPolyRef startPoly = GetPolyByLocation(startPoint, &distToStartPoly);
dtPolyRef endPoly = GetPolyByLocation(endPoint, &distToEndPoly);
dtPolyRef startPoly = GetPolyByLocation(startPoint, &distToStartPoly);
dtPolyRef endPoly = GetPolyByLocation(endPoint, &distToEndPoly);
bool sourceIsFlying = (_sourceUnit->GetUnitMovementFlags() & (MOVEMENTFLAG_CAN_FLY|MOVEMENTFLAG_FLYING)) || (_sourceUnit->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY) && !_sourceUnit->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING)) || (_sourceUnit->GetTypeId() == TYPEID_UNIT && ((Creature*)_sourceUnit)->CanFly());
bool sourceCanSwim = _sourceUnit->GetTypeId() == TYPEID_UNIT ? _sourceUnit->ToCreature()->CanSwim() : true;
bool sourceCanWalk = _sourceUnit->GetTypeId() == TYPEID_UNIT ? _sourceUnit->ToCreature()->CanWalk() : true;
bool sourceIsFlying = (_sourceUnit->GetUnitMovementFlags() & (MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING)) || (_sourceUnit->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY) && !_sourceUnit->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING)) || (_sourceUnit->GetTypeId() == TYPEID_UNIT && ((Creature*)_sourceUnit)->CanFly());
bool sourceCanSwim = _sourceUnit->GetTypeId() == TYPEID_UNIT ? _sourceUnit->ToCreature()->CanSwim() : true;
bool sourceCanWalk = _sourceUnit->GetTypeId() == TYPEID_UNIT ? _sourceUnit->ToCreature()->CanWalk() : true;
// we have a hole in our mesh
// make shortcut path and mark it as NOPATH ( with flying and swimming exception )
// its up to caller how he will use this info
if (startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF)
{
BuildShortcut();
if (sourceIsFlying)
{
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
return;
}
if (sourceCanSwim)
{
if ((startPoly == INVALID_POLYREF && LIQUID_MAP_NO_WATER == _sourceUnit->GetBaseMap()->getLiquidStatus(startPos.x, startPos.y, startPos.z, MAP_ALL_LIQUIDS, nullptr)) ||
(endPoly == INVALID_POLYREF && LIQUID_MAP_NO_WATER == _sourceUnit->GetBaseMap()->getLiquidStatus(endPos.x, endPos.y, endPos.z, MAP_ALL_LIQUIDS, nullptr)))
{
_type = PATHFIND_NOPATH;
return;
}
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
return;
}
_type = PATHFIND_NOPATH;
return;
}
// we may need a better number here
bool farFromStartPoly = (distToStartPoly > ALLOWED_DIST_FROM_POLY);
bool farFromEndPoly = (distToEndPoly > ALLOWED_DIST_FROM_POLY);
if (farFromStartPoly)
{
if (sourceIsFlying)
// we have a hole in our mesh
// make shortcut path and mark it as NOPATH ( with flying and swimming exception )
// its up to caller how he will use this info
if (startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF)
{
BuildShortcut();
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
return;
}
if (sourceCanSwim)
{
if (LIQUID_MAP_NO_WATER == _sourceUnit->GetBaseMap()->getLiquidStatus(startPos.x, startPos.y, startPos.z, MAP_ALL_LIQUIDS, nullptr))
if (sourceIsFlying)
{
if (distToStartPoly > MAX_FIXABLE_Z_ERROR)
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
return;
}
if (sourceCanSwim)
{
if ((startPoly == INVALID_POLYREF && LIQUID_MAP_NO_WATER == _sourceUnit->GetBaseMap()->getLiquidStatus(startPos.x, startPos.y, startPos.z, MAP_ALL_LIQUIDS, nullptr)) ||
(endPoly == INVALID_POLYREF && LIQUID_MAP_NO_WATER == _sourceUnit->GetBaseMap()->getLiquidStatus(endPos.x, endPos.y, endPos.z, MAP_ALL_LIQUIDS, nullptr)))
{
BuildShortcut();
_type = PATHFIND_NOPATH;
return;
}
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
return;
}
_type = PATHFIND_NOPATH;
return;
}
if (farFromEndPoly)
// we may need a better number here
bool farFromStartPoly = (distToStartPoly > ALLOWED_DIST_FROM_POLY);
bool farFromEndPoly = (distToEndPoly > ALLOWED_DIST_FROM_POLY);
if (farFromStartPoly)
{
if (sourceIsFlying)
{
BuildShortcut();
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
return;
}
if (sourceCanSwim)
{
if (LIQUID_MAP_NO_WATER == _sourceUnit->GetBaseMap()->getLiquidStatus(startPos.x, startPos.y, startPos.z, MAP_ALL_LIQUIDS, nullptr))
{
if (LIQUID_MAP_NO_WATER == _sourceUnit->GetBaseMap()->getLiquidStatus(endPos.x, endPos.y, endPos.z, MAP_ALL_LIQUIDS, nullptr))
if (distToStartPoly > MAX_FIXABLE_Z_ERROR)
{
BuildShortcut();
_type = PATHFIND_NOPATH;
return;
}
if (farFromEndPoly)
{
if (LIQUID_MAP_NO_WATER == _sourceUnit->GetBaseMap()->getLiquidStatus(endPos.x, endPos.y, endPos.z, MAP_ALL_LIQUIDS, nullptr))
{
BuildShortcut();
_type = PATHFIND_NOPATH;
return;
}
}
}
else if (LIQUID_MAP_NO_WATER == _sourceUnit->GetBaseMap()->getLiquidStatus(endPos.x, endPos.y, endPos.z, MAP_ALL_LIQUIDS, nullptr))
{
if (farFromEndPoly)
{
BuildShortcut();
_type = PATHFIND_NOPATH;
return;
}
cutToFirstHigher = true;
}
else // starting and ending points are in water
{
BuildShortcut();
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
return;
}
}
else if (LIQUID_MAP_NO_WATER == _sourceUnit->GetBaseMap()->getLiquidStatus(endPos.x, endPos.y, endPos.z, MAP_ALL_LIQUIDS, nullptr))
else
{
if (farFromEndPoly)
if (distToStartPoly > MAX_FIXABLE_Z_ERROR || farFromEndPoly)
{
BuildShortcut();
_type = PATHFIND_NOPATH;
return;
}
}
}
else if (farFromEndPoly)
{
if (sourceIsFlying)
{
BuildShortcut();
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
return;
}
if (LIQUID_MAP_NO_WATER == _sourceUnit->GetBaseMap()->getLiquidStatus(endPos.x, endPos.y, endPos.z, MAP_ALL_LIQUIDS, nullptr))
{
if (!sourceCanWalk)
{
BuildShortcut();
_type = PATHFIND_NOPATH;
return;
}
}
else
{
if (!sourceCanSwim)
{
BuildShortcut();
_type = PATHFIND_NOPATH;
return;
}
cutToFirstHigher = true;
// if both points are in water
if (LIQUID_MAP_NO_WATER != _sourceUnit->GetBaseMap()->getLiquidStatus(startPos.x, startPos.y, startPos.z, MAP_ALL_LIQUIDS, nullptr))
{
BuildShortcut();
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
return;
}
endInWaterFar = true;
}
else // starting and ending points are in water
if (startPoly != endPoly || !endInWaterFar)
{
BuildShortcut();
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
return;
float closestPoint[VERTEX_SIZE];
if (dtStatusSucceed(_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint, nullptr)))
{
dtVcopy(endPoint, closestPoint);
SetActualEndPosition(G3D::Vector3(endPoint[2], endPoint[0], endPoint[1]));
}
_type = PATHFIND_INCOMPLETE;
}
}
else
{
if (distToStartPoly > MAX_FIXABLE_Z_ERROR || farFromEndPoly)
{
BuildShortcut();
_type = PATHFIND_NOPATH;
return;
}
}
}
else if (farFromEndPoly)
{
if (sourceIsFlying)
// *** poly path generating logic ***
if (startPoly == endPoly)
{
BuildShortcut();
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
_type = !farFromEndPoly || endInWaterFar ? PATHFIND_NORMAL : PATHFIND_INCOMPLETE;
_pathPolyRefs[0] = startPoly;
_polyLength = 1;
return;
}
if (LIQUID_MAP_NO_WATER == _sourceUnit->GetBaseMap()->getLiquidStatus(endPos.x, endPos.y, endPos.z, MAP_ALL_LIQUIDS, nullptr))
// look for startPoly/endPoly in current path
/// @todo we can merge it with getPathPolyByPosition() loop
bool startPolyFound = false;
bool endPolyFound = false;
uint32 pathStartIndex = 0;
uint32 pathEndIndex = 0;
if (_polyLength)
{
if (!sourceCanWalk)
for (; pathStartIndex < _polyLength; ++pathStartIndex)
{
BuildShortcut();
_type = PATHFIND_NOPATH;
return;
}
}
else
{
if (!sourceCanSwim)
{
BuildShortcut();
_type = PATHFIND_NOPATH;
return;
// here to catch few bugs
ASSERT(_pathPolyRefs[pathStartIndex] != INVALID_POLYREF);
if (_pathPolyRefs[pathStartIndex] == startPoly)
{
startPolyFound = true;
break;
}
}
// if both points are in water
if (LIQUID_MAP_NO_WATER != _sourceUnit->GetBaseMap()->getLiquidStatus(startPos.x, startPos.y, startPos.z, MAP_ALL_LIQUIDS, nullptr))
{
BuildShortcut();
_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
return;
}
endInWaterFar = true;
for (pathEndIndex = _polyLength - 1; pathEndIndex > pathStartIndex; --pathEndIndex)
if (_pathPolyRefs[pathEndIndex] == endPoly)
{
endPolyFound = true;
break;
}
}
if (startPoly != endPoly || !endInWaterFar)
if (startPolyFound && endPolyFound)
{
float closestPoint[VERTEX_SIZE];
if (dtStatusSucceed(_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint, nullptr)))
{
dtVcopy(endPoint, closestPoint);
SetActualEndPosition(G3D::Vector3(endPoint[2], endPoint[0], endPoint[1]));
}
_type = PATHFIND_INCOMPLETE;
_polyLength = pathEndIndex - pathStartIndex + 1;
memmove(_pathPolyRefs, _pathPolyRefs + pathStartIndex, _polyLength * sizeof(dtPolyRef));
}
}
// *** poly path generating logic ***
if (startPoly == endPoly)
{
BuildShortcut();
_type = !farFromEndPoly || endInWaterFar ? PATHFIND_NORMAL : PATHFIND_INCOMPLETE;
_pathPolyRefs[0] = startPoly;
_polyLength = 1;
return;
}
// look for startPoly/endPoly in current path
/// @todo we can merge it with getPathPolyByPosition() loop
bool startPolyFound = false;
bool endPolyFound = false;
uint32 pathStartIndex = 0;
uint32 pathEndIndex = 0;
if (_polyLength)
{
for (; pathStartIndex < _polyLength; ++pathStartIndex)
else if (startPolyFound && !endPolyFound && _polyLength - pathStartIndex >= 3 /*if (>=3) then 70% will return at least one more than just startPoly*/)
{
// here to catch few bugs
ASSERT(_pathPolyRefs[pathStartIndex] != INVALID_POLYREF);
// we are moving on the old path but target moved out
// so we have atleast part of poly-path ready
if (_pathPolyRefs[pathStartIndex] == startPoly)
_polyLength -= pathStartIndex;
// try to adjust the suffix of the path instead of recalculating entire length
// at given interval the target cannot get too far from its last location
// thus we have less poly to cover
// sub-path of optimal path is optimal
// take ~65% of the original length
/// @todo play with the values here
uint32 prefixPolyLength = uint32(_polyLength * 0.7f + 0.5f); // this should be always >= 1
memmove(_pathPolyRefs, _pathPolyRefs + pathStartIndex, prefixPolyLength * sizeof(dtPolyRef));
dtPolyRef suffixStartPoly = _pathPolyRefs[prefixPolyLength - 1];
bool error = false; // can't use a part of old path, generate whole new
// we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data
float suffixEndPoint[VERTEX_SIZE];
if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint, nullptr)))
{
startPolyFound = true;
break;
}
}
for (pathEndIndex = _polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex)
if (_pathPolyRefs[pathEndIndex] == endPoly)
{
endPolyFound = true;
break;
}
}
if (startPolyFound && endPolyFound)
{
_polyLength = pathEndIndex - pathStartIndex + 1;
memmove(_pathPolyRefs, _pathPolyRefs + pathStartIndex, _polyLength * sizeof(dtPolyRef));
}
else if (startPolyFound && !endPolyFound && _polyLength-pathStartIndex >= 3 /*if (>=3) then 70% will return at least one more than just startPoly*/)
{
// we are moving on the old path but target moved out
// so we have atleast part of poly-path ready
_polyLength -= pathStartIndex;
// try to adjust the suffix of the path instead of recalculating entire length
// at given interval the target cannot get too far from its last location
// thus we have less poly to cover
// sub-path of optimal path is optimal
// take ~65% of the original length
/// @todo play with the values here
uint32 prefixPolyLength = uint32(_polyLength * 0.7f + 0.5f); // this should be always >= 1
memmove(_pathPolyRefs, _pathPolyRefs+pathStartIndex, prefixPolyLength * sizeof(dtPolyRef));
dtPolyRef suffixStartPoly = _pathPolyRefs[prefixPolyLength-1];
bool error = false; // can't use a part of old path, generate whole new
// we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data
float suffixEndPoint[VERTEX_SIZE];
if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint, nullptr)))
{
// we can hit offmesh connection as last poly - closestPointOnPoly() don't like that
// try to recover by using prev polyref
--prefixPolyLength;
if (prefixPolyLength)
{
suffixStartPoly = _pathPolyRefs[prefixPolyLength-1];
if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint,NULL)))
// we can hit offmesh connection as last poly - closestPointOnPoly() don't like that
// try to recover by using prev polyref
--prefixPolyLength;
if (prefixPolyLength)
{
suffixStartPoly = _pathPolyRefs[prefixPolyLength - 1];
if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint, NULL)))
error = true;
}
else
error = true;
}
else
error = true;
}
if (!error)
{
// generate suffix
uint32 suffixPolyLength = 0;
dtStatus dtResult = _navMeshQuery->findPath(
suffixStartPoly, // start polygon
endPoly, // end polygon
suffixEndPoint, // start position
endPoint, // end position
&_filter, // polygon search filter
_pathPolyRefs + prefixPolyLength - 1, // [out] path
(int*)&suffixPolyLength,
MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path
if (!_polyLength || dtStatusFailed(dtResult))
if (!error)
{
// this is probably an error state, but we'll leave it
// and hopefully recover on the next Update
// we still need to copy our preffix
}
// generate suffix
uint32 suffixPolyLength = 0;
dtStatus dtResult = _navMeshQuery->findPath(
suffixStartPoly, // start polygon
endPoly, // end polygon
suffixEndPoint, // start position
endPoint, // end position
&_filter, // polygon search filter
_pathPolyRefs + prefixPolyLength - 1, // [out] path
(int*)&suffixPolyLength,
MAX_PATH_LENGTH - prefixPolyLength); // max number of polygons in output path
// new path = prefix + suffix - overlap
_polyLength = prefixPolyLength + suffixPolyLength - 1;
if (!_polyLength || dtStatusFailed(dtResult))
{
// this is probably an error state, but we'll leave it
// and hopefully recover on the next Update
// we still need to copy our preffix
}
// new path = prefix + suffix - overlap
_polyLength = prefixPolyLength + suffixPolyLength - 1;
}
else
{
// free and invalidate old path data
Clear();
dtStatus dtResult = _navMeshQuery->findPath(
startPoly, // start polygon
endPoly, // end polygon
startPoint, // start position
endPoint, // end position
&_filter, // polygon search filter
_pathPolyRefs, // [out] path
(int*)&_polyLength,
MAX_PATH_LENGTH); // max number of polygons in output path
if (!_polyLength || dtStatusFailed(dtResult))
{
// only happens if we passed bad data to findPath(), or navmesh is messed up
BuildShortcut();
_type = PATHFIND_NOPATH;
return;
}
}
}
else
{
// either we have no path at all -> first run
// or something went really wrong -> we aren't moving along the path to the target
// pussywizard: or knocked back away from our path, nothing special
// just generate new path
// free and invalidate old path data
Clear();
dtStatus dtResult = _navMeshQuery->findPath(
startPoly, // start polygon
endPoly, // end polygon
startPoint, // start position
endPoint, // end position
&_filter, // polygon search filter
_pathPolyRefs, // [out] path
(int*)&_polyLength,
MAX_PATH_LENGTH); // max number of polygons in output path
startPoly, // start polygon
endPoly, // end polygon
startPoint, // start position
endPoint, // end position
&_filter, // polygon search filter
_pathPolyRefs, // [out] path
(int*)&_polyLength,
MAX_PATH_LENGTH); // max number of polygons in output path
if (!_polyLength || dtStatusFailed(dtResult))
{
@@ -479,46 +510,17 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
return;
}
}
}
else
{
// either we have no path at all -> first run
// or something went really wrong -> we aren't moving along the path to the target
// pussywizard: or knocked back away from our path, nothing special
// just generate new path
// free and invalidate old path data
Clear();
// by now we know what type of path we can get
if (_pathPolyRefs[_polyLength - 1] == endPoly && !(_type & PATHFIND_INCOMPLETE))
_type = PATHFIND_NORMAL;
else
_type = PATHFIND_INCOMPLETE;
dtStatus dtResult = _navMeshQuery->findPath(
startPoly, // start polygon
endPoly, // end polygon
startPoint, // start position
endPoint, // end position
&_filter, // polygon search filter
_pathPolyRefs, // [out] path
(int*)&_polyLength,
MAX_PATH_LENGTH); // max number of polygons in output path
// generate the point-path out of our up-to-date poly-path
BuildPointPath(startPoint, endPoint);
if (!_polyLength || dtStatusFailed(dtResult))
{
// only happens if we passed bad data to findPath(), or navmesh is messed up
BuildShortcut();
_type = PATHFIND_NOPATH;
return;
}
}
// by now we know what type of path we can get
if (_pathPolyRefs[_polyLength - 1] == endPoly && !(_type & PATHFIND_INCOMPLETE))
_type = PATHFIND_NORMAL;
else
_type = PATHFIND_INCOMPLETE;
// generate the point-path out of our up-to-date poly-path
BuildPointPath(startPoint, endPoint);
// pussywizard: no mmap usage below, release mutex
// pussywizard: no mmap usage below, release mutex
} // end of scope (mutex released in object destructor)
if (_type == PATHFIND_NORMAL && cutToFirstHigher) // starting in water, far from bottom, target is on the ground (above starting Z) -> update beginning points that are lower than starting Z
@@ -526,17 +528,17 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
uint32 i = 0;
uint32 size = _pathPoints.size();
for (; i < size; ++i)
if (_pathPoints[i].z >= _sourceUnit->GetPositionZ()+0.1f)
if (_pathPoints[i].z >= _sourceUnit->GetPositionZ() + 0.1f)
break;
if (i && i != size && LIQUID_MAP_NO_WATER != _sourceUnit->GetBaseMap()->getLiquidStatus(_pathPoints[i-1].x, _pathPoints[i-1].y, _pathPoints[i-1].z, MAP_ALL_LIQUIDS, nullptr))
for (uint32 j=0; j<i; ++j)
if (i && i != size && LIQUID_MAP_NO_WATER != _sourceUnit->GetBaseMap()->getLiquidStatus(_pathPoints[i - 1].x, _pathPoints[i - 1].y, _pathPoints[i - 1].z, MAP_ALL_LIQUIDS, nullptr))
for (uint32 j = 0; j < i; ++j)
_pathPoints[j].z = _sourceUnit->GetPositionZ();
}
if (!_forceDestination)
if (uint32 lastIdx = _pathPoints.size())
{
lastIdx = lastIdx-1;
lastIdx = lastIdx - 1;
if (endInWaterFar)
{
SetActualEndPosition(GetEndPosition());
@@ -563,14 +565,14 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
if (i < size)
{
ok = true;
if ((_pathPoints[i] - _pathPoints[0]).squaredLength() > 15.0f*15.0f)
if ((_pathPoints[i] - _pathPoints[0]).squaredLength() > 15.0f * 15.0f)
ok = false;
else
for (uint32 j = 1; j < i; ++j)
{
float sqDist = (_pathPoints[j] - ClosestPointOnLine(_pathPoints[0], _pathPoints[i], _pathPoints[j])).squaredLength();
float oSize = _sourceUnit->GetObjectSize();
if (sqDist > 1.0f*1.0f || sqDist > oSize*oSize)
if (sqDist > 1.0f * 1.0f || sqDist > oSize * oSize)
{
ok = false;
break;
@@ -584,21 +586,21 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
{
// pussywizard: check additional 3 quarter points after last fitting poly point
G3D::Vector3 dir = _pathPoints[i] - _pathPoints[i-1];
G3D::Vector3 increment = (dir.length()/4.0f) * dir.unit();
G3D::Vector3 dir = _pathPoints[i] - _pathPoints[i - 1];
G3D::Vector3 increment = (dir.length() / 4.0f) * dir.unit();
for (uint8 k = 3; k > 0; --k)
{
G3D::Vector3 newPoint = _pathPoints[i-1] + ((float)k)*increment;
G3D::Vector3 newPoint = _pathPoints[i - 1] + ((float)k) * increment;
bool ok2 = true;
if ((newPoint - _pathPoints[0]).squaredLength() > 15.0f*15.0f)
if ((newPoint - _pathPoints[0]).squaredLength() > 15.0f * 15.0f)
ok2 = false;
else
for (uint32 j = 1; j < i; ++j)
{
float sqDist = (_pathPoints[j] - ClosestPointOnLine(_pathPoints[0], newPoint, _pathPoints[j])).squaredLength();
float oSize = _sourceUnit->GetObjectSize();
if (sqDist > 1.0f*1.0f || sqDist > oSize*oSize)
if (sqDist > 1.0f * 1.0f || sqDist > oSize * oSize)
{
ok2 = false;
break;
@@ -607,20 +609,20 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
if (ok2)
{
_pathPoints[i-1] = newPoint;
_pathPoints[i - 1] = newPoint;
break;
}
}
// pussywizard: memmove crashes o_O
// memmove(&_pathPoints + sizeof(G3D::Vector3), &_pathPoints + (i-1)*sizeof(G3D::Vector3), (size-i+1)*sizeof(G3D::Vector3));
for (uint8 k = 1; k <= size-i+1; ++k)
_pathPoints[k] = _pathPoints[k+i-2];
_pathPoints.resize(size-i+2);
for (uint8 k = 1; k <= size - i + 1; ++k)
_pathPoints[k] = _pathPoints[k + i - 2];
_pathPoints.resize(size - i + 2);
}
else if (size > 2)
{
_pathPoints[1] = _pathPoints[size-1];
_pathPoints[1] = _pathPoints[size - 1];
_pathPoints.resize(2);
}
@@ -629,34 +631,34 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
}
}
void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoint)
void PathGenerator::BuildPointPath(const float* startPoint, const float* endPoint)
{
float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE];
float pathPoints[MAX_POINT_PATH_LENGTH * VERTEX_SIZE];
uint32 pointCount = 0;
dtStatus dtResult = DT_FAILURE;
if (_useStraightPath)
{
dtResult = _navMeshQuery->findStraightPath(
startPoint, // start position
endPoint, // end position
_pathPolyRefs, // current path
_polyLength, // lenth of current path
pathPoints, // [out] path corner points
NULL, // [out] flags
NULL, // [out] shortened path
(int*)&pointCount,
_pointPathLimit); // maximum number of points/polygons to use
startPoint, // start position
endPoint, // end position
_pathPolyRefs, // current path
_polyLength, // lenth of current path
pathPoints, // [out] path corner points
NULL, // [out] flags
NULL, // [out] shortened path
(int*)&pointCount,
_pointPathLimit); // maximum number of points/polygons to use
}
else
{
dtResult = FindSmoothPath(
startPoint, // start position
endPoint, // end position
_pathPolyRefs, // current path
_polyLength, // length of current path
pathPoints, // [out] path corner points
(int*)&pointCount,
_pointPathLimit); // maximum number of points
startPoint, // start position
endPoint, // end position
_pathPolyRefs, // current path
_polyLength, // length of current path
pathPoints, // [out] path corner points
(int*)&pointCount,
_pointPathLimit); // maximum number of points
}
if (pointCount < 2 || dtStatusFailed(dtResult))
@@ -677,10 +679,10 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin
_pathPoints.resize(pointCount);
for (uint32 i = 0; i < pointCount; ++i)
_pathPoints[i] = G3D::Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]);
_pathPoints[i] = G3D::Vector3(pathPoints[i * VERTEX_SIZE + 2], pathPoints[i * VERTEX_SIZE], pathPoints[i * VERTEX_SIZE + 1]);
// first point is always our current location - we need the next one
SetActualEndPosition(_pathPoints[pointCount-1]);
SetActualEndPosition(_pathPoints[pointCount - 1]);
if (_forceDestination && (!(_type & PATHFIND_NORMAL) || !InRange(GetEndPosition(), GetActualEndPosition(), 0.75f, 0.75f)))
{
@@ -688,7 +690,7 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin
if (Dist3DSqr(GetActualEndPosition(), GetEndPosition()) < 0.33f * Dist3DSqr(GetStartPosition(), GetEndPosition()))
{
SetActualEndPosition(GetEndPosition());
_pathPoints[_pathPoints.size()-1] = GetEndPosition();
_pathPoints[_pathPoints.size() - 1] = GetEndPosition();
}
else
{
@@ -794,10 +796,10 @@ uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPat
int32 furthestVisited = -1;
// Find furthest common polygon.
for (int32 i = npath-1; i >= 0; --i)
for (int32 i = npath - 1; i >= 0; --i)
{
bool found = false;
for (int32 j = nvisited-1; j >= 0; --j)
for (int32 j = nvisited - 1; j >= 0; --j)
{
if (path[i] == visited[j])
{
@@ -821,7 +823,7 @@ uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPat
uint32 orig = uint32(furthestPath + 1) < npath ? furthestPath + 1 : npath;
uint32 size = npath > orig ? npath - orig : 0;
if (req + size > maxPath)
size = maxPath-req;
size = maxPath - req;
if (size)
memmove(path + req, path + orig, size * sizeof(dtPolyRef));
@@ -830,21 +832,21 @@ uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPat
for (uint32 i = 0; i < req; ++i)
path[i] = visited[(nvisited - 1) - i];
return req+size;
return req + size;
}
bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos,
float minTargetDist, dtPolyRef const* path, uint32 pathSize,
float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef)
float minTargetDist, dtPolyRef const* path, uint32 pathSize,
float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef)
{
// Find steer target.
static const uint32 MAX_STEER_POINTS = 3;
float steerPath[MAX_STEER_POINTS*VERTEX_SIZE];
float steerPath[MAX_STEER_POINTS * VERTEX_SIZE];
unsigned char steerPathFlags[MAX_STEER_POINTS];
dtPolyRef steerPathPolys[MAX_STEER_POINTS];
uint32 nsteerPath = 0;
dtStatus dtResult = _navMeshQuery->findStraightPath(startPos, endPos, path, pathSize,
steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS);
steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS);
if (!nsteerPath || dtStatusFailed(dtResult))
return false;
@@ -854,7 +856,7 @@ bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos,
{
// Stop at Off-Mesh link or when point is further than slop away.
if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ||
!InRangeYZX(&steerPath[ns*VERTEX_SIZE], startPos, minTargetDist, 1000.0f))
!InRangeYZX(&steerPath[ns * VERTEX_SIZE], startPos, minTargetDist, 1000.0f))
break;
ns++;
}
@@ -862,7 +864,7 @@ bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos,
if (ns >= nsteerPath)
return false;
dtVcopy(steerPos, &steerPath[ns*VERTEX_SIZE]);
dtVcopy(steerPos, &steerPath[ns * VERTEX_SIZE]);
steerPos[1] = startPos[1]; // keep Z value
steerPosFlag = steerPathFlags[ns];
steerPosRef = steerPathPolys[ns];
@@ -871,8 +873,8 @@ bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos,
}
dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPos,
dtPolyRef const* polyPath, uint32 polyPathSize,
float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize)
dtPolyRef const* polyPath, uint32 polyPathSize,
float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize)
{
*smoothPathSize = 0;
uint32 nsmoothPath = 0;
@@ -885,10 +887,10 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo
if (DT_SUCCESS != _navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos))
return DT_FAILURE;
if (DT_SUCCESS != _navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos))
if (DT_SUCCESS != _navMeshQuery->closestPointOnPolyBoundary(polys[npolys - 1], endPos, targetPos))
return DT_FAILURE;
dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
dtVcopy(&smoothPath[nsmoothPath * VERTEX_SIZE], iterPos);
nsmoothPath++;
// Move towards target a small advancement at a time until target reached or
@@ -939,7 +941,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo
dtVcopy(iterPos, targetPos);
if (nsmoothPath < maxSmoothPathSize)
{
dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
dtVcopy(&smoothPath[nsmoothPath * VERTEX_SIZE], iterPos);
nsmoothPath++;
}
break;
@@ -958,7 +960,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo
}
for (uint32 i = npos; i < npolys; ++i)
polys[i-npos] = polys[i];
polys[i - npos] = polys[i];
npolys -= npos;
@@ -968,7 +970,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo
{
if (nsmoothPath < maxSmoothPathSize)
{
dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos);
dtVcopy(&smoothPath[nsmoothPath * VERTEX_SIZE], startPos);
nsmoothPath++;
}
// Move position at the other side of the off-mesh link.
@@ -981,7 +983,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo
// Store results.
if (nsmoothPath < maxSmoothPathSize)
{
dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
dtVcopy(&smoothPath[nsmoothPath * VERTEX_SIZE], iterPos);
nsmoothPath++;
}
}

View File

@@ -56,101 +56,105 @@ enum PathType
class PathGenerator
{
public:
explicit PathGenerator(Unit const* owner);
~PathGenerator();
public:
explicit PathGenerator(Unit const* owner);
~PathGenerator();
// Calculate the path from owner to given destination
// return: true if new path was calculated, false otherwise (no change needed)
bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false);
// Calculate the path from owner to given destination
// return: true if new path was calculated, false otherwise (no change needed)
bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false);
// option setters - use optional
void SetUseStraightPath(bool useStraightPath) { _useStraightPath = useStraightPath; }
void SetPathLengthLimit(float distance) { _pointPathLimit = std::min<uint32>(uint32(distance/SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); }
// option setters - use optional
void SetUseStraightPath(bool useStraightPath) { _useStraightPath = useStraightPath; }
void SetPathLengthLimit(float distance) { _pointPathLimit = std::min<uint32>(uint32(distance / SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); }
// result getters
G3D::Vector3 const& GetStartPosition() const { return _startPosition; }
G3D::Vector3 const& GetEndPosition() const { return _endPosition; }
G3D::Vector3 const& GetActualEndPosition() const { return _actualEndPosition; }
// result getters
G3D::Vector3 const& GetStartPosition() const { return _startPosition; }
G3D::Vector3 const& GetEndPosition() const { return _endPosition; }
G3D::Vector3 const& GetActualEndPosition() const { return _actualEndPosition; }
Movement::PointsArray const& GetPath() const { return _pathPoints; }
Movement::PointsArray const& GetPath() const { return _pathPoints; }
PathType GetPathType() const { return _type; }
float getPathLength() const
PathType GetPathType() const { return _type; }
float getPathLength() const
{
float len = 0.0f;
float dx, dy, dz;
uint32 size = _pathPoints.size();
if (size)
{
float len = 0.0f;
float dx, dy, dz;
uint32 size = _pathPoints.size();
if (size)
{
dx = _pathPoints[0].x - _startPosition.x; dy = _pathPoints[0].y - _startPosition.y; dz = _pathPoints[0].z - _startPosition.z;
len += sqrt( dx*dx + dy*dy + dz*dz );
}
else
return len;
for (uint32 i=1; i<size; ++i)
{
dx = _pathPoints[i].x - _pathPoints[i-1].x; dy = _pathPoints[i].y - _pathPoints[i-1].y; dz = _pathPoints[i].z - _pathPoints[i-1].z;
len += sqrt( dx*dx + dy*dy + dz*dz );
}
dx = _pathPoints[0].x - _startPosition.x;
dy = _pathPoints[0].y - _startPosition.y;
dz = _pathPoints[0].z - _startPosition.z;
len += sqrt( dx * dx + dy * dy + dz * dz );
}
else
return len;
}
private:
dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references
uint32 _polyLength; // number of polygons in the path
Movement::PointsArray _pathPoints; // our actual (x,y,z) path to the target
PathType _type; // tells what kind of path this is
bool _useStraightPath; // type of path will be generated
bool _forceDestination; // when set, we will always arrive at given point
uint32 _pointPathLimit; // limit point path size; min(this, MAX_POINT_PATH_LENGTH)
G3D::Vector3 _startPosition; // {x, y, z} of current location
G3D::Vector3 _endPosition; // {x, y, z} of the destination
G3D::Vector3 _actualEndPosition; // {x, y, z} of the closest possible point to given destination
Unit const* const _sourceUnit; // the unit that is moving
dtNavMesh const* _navMesh; // the nav mesh
dtNavMeshQuery const* _navMeshQuery; // the nav mesh query used to find the path
dtQueryFilter _filter; // use single filter for all movements, update it when needed
void SetStartPosition(G3D::Vector3 const& point) { _startPosition = point; }
void SetEndPosition(G3D::Vector3 const& point) { _actualEndPosition = point; _endPosition = point; }
void SetActualEndPosition(G3D::Vector3 const& point) { _actualEndPosition = point; }
void Clear()
for (uint32 i = 1; i < size; ++i)
{
_polyLength = 0;
_pathPoints.clear();
dx = _pathPoints[i].x - _pathPoints[i - 1].x;
dy = _pathPoints[i].y - _pathPoints[i - 1].y;
dz = _pathPoints[i].z - _pathPoints[i - 1].z;
len += sqrt( dx * dx + dy * dy + dz * dz );
}
return len;
}
bool InRange(G3D::Vector3 const& p1, G3D::Vector3 const& p2, float r, float h) const;
float Dist3DSqr(G3D::Vector3 const& p1, G3D::Vector3 const& p2) const;
bool InRangeYZX(float const* v1, float const* v2, float r, float h) const;
private:
dtPolyRef GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 polyPathSize, float const* Point, float* Distance = nullptr) const;
dtPolyRef GetPolyByLocation(float* Point, float* Distance) const;
bool HaveTile(G3D::Vector3 const& p) const;
dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references
uint32 _polyLength; // number of polygons in the path
void BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, ACE_RW_Thread_Mutex& lock);
void BuildPointPath(float const* startPoint, float const* endPoint);
void BuildShortcut();
Movement::PointsArray _pathPoints; // our actual (x,y,z) path to the target
PathType _type; // tells what kind of path this is
NavTerrain GetNavTerrain(float x, float y, float z);
void CreateFilter();
void UpdateFilter();
bool _useStraightPath; // type of path will be generated
bool _forceDestination; // when set, we will always arrive at given point
uint32 _pointPathLimit; // limit point path size; min(this, MAX_POINT_PATH_LENGTH)
// smooth path aux functions
uint32 FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited);
bool GetSteerTarget(float const* startPos, float const* endPos, float minTargetDist, dtPolyRef const* path, uint32 pathSize, float* steerPos,
unsigned char& steerPosFlag, dtPolyRef& steerPosRef);
dtStatus FindSmoothPath(float const* startPos, float const* endPos,
dtPolyRef const* polyPath, uint32 polyPathSize,
float* smoothPath, int* smoothPathSize, uint32 smoothPathMaxSize);
G3D::Vector3 _startPosition; // {x, y, z} of current location
G3D::Vector3 _endPosition; // {x, y, z} of the destination
G3D::Vector3 _actualEndPosition; // {x, y, z} of the closest possible point to given destination
Unit const* const _sourceUnit; // the unit that is moving
dtNavMesh const* _navMesh; // the nav mesh
dtNavMeshQuery const* _navMeshQuery; // the nav mesh query used to find the path
dtQueryFilter _filter; // use single filter for all movements, update it when needed
void SetStartPosition(G3D::Vector3 const& point) { _startPosition = point; }
void SetEndPosition(G3D::Vector3 const& point) { _actualEndPosition = point; _endPosition = point; }
void SetActualEndPosition(G3D::Vector3 const& point) { _actualEndPosition = point; }
void Clear()
{
_polyLength = 0;
_pathPoints.clear();
}
bool InRange(G3D::Vector3 const& p1, G3D::Vector3 const& p2, float r, float h) const;
float Dist3DSqr(G3D::Vector3 const& p1, G3D::Vector3 const& p2) const;
bool InRangeYZX(float const* v1, float const* v2, float r, float h) const;
dtPolyRef GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 polyPathSize, float const* Point, float* Distance = nullptr) const;
dtPolyRef GetPolyByLocation(float* Point, float* Distance) const;
bool HaveTile(G3D::Vector3 const& p) const;
void BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, ACE_RW_Thread_Mutex& lock);
void BuildPointPath(float const* startPoint, float const* endPoint);
void BuildShortcut();
NavTerrain GetNavTerrain(float x, float y, float z);
void CreateFilter();
void UpdateFilter();
// smooth path aux functions
uint32 FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited);
bool GetSteerTarget(float const* startPos, float const* endPos, float minTargetDist, dtPolyRef const* path, uint32 pathSize, float* steerPos,
unsigned char& steerPosFlag, dtPolyRef& steerPosRef);
dtStatus FindSmoothPath(float const* startPos, float const* endPos,
dtPolyRef const* polyPath, uint32 polyPathSize,
float* smoothPath, int* smoothPathSize, uint32 smoothPathMaxSize);
};
#endif

View File

@@ -20,7 +20,7 @@ void PointMovementGenerator<T>::DoInitialize(T* unit)
if (!unit->IsStopped())
unit->StopMoving();
unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
unit->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
i_recalculateSpeed = false;
Movement::MoveSplineInit init(unit);
if (m_precomputedPath.size() > 2) // pussywizard: for charge
@@ -39,8 +39,8 @@ void PointMovementGenerator<T>::DoInitialize(T* unit)
// Xinef: fix strange client visual bug, moving on z coordinate only switches orientation by 180 degrees (visual only)
if (G3D::fuzzyEq(unit->GetPositionX(), i_x) && G3D::fuzzyEq(unit->GetPositionY(), i_y))
{
i_x += 0.2f*cos(unit->GetOrientation());
i_y += 0.2f*sin(unit->GetOrientation());
i_x += 0.2f * cos(unit->GetOrientation());
i_y += 0.2f * sin(unit->GetOrientation());
}
init.MoveTo(i_x, i_y, i_z);
@@ -51,8 +51,8 @@ void PointMovementGenerator<T>::DoInitialize(T* unit)
// Xinef: fix strange client visual bug, moving on z coordinate only switches orientation by 180 degrees (visual only)
if (G3D::fuzzyEq(unit->GetPositionX(), i_x) && G3D::fuzzyEq(unit->GetPositionY(), i_y))
{
i_x += 0.2f*cos(unit->GetOrientation());
i_y += 0.2f*sin(unit->GetOrientation());
i_x += 0.2f * cos(unit->GetOrientation());
i_y += 0.2f * sin(unit->GetOrientation());
}
init.MoveTo(i_x, i_y, i_z);
@@ -134,7 +134,7 @@ void PointMovementGenerator<T>::DoReset(T* unit)
if (!unit->IsStopped())
unit->StopMoving();
unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
unit->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
}
template<class T>

View File

@@ -13,59 +13,59 @@
template<class T>
class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementGenerator<T> >
{
public:
PointMovementGenerator(uint32 _id, float _x, float _y, float _z, float _speed = 0.0f, float orientation = 0.0f, const Movement::PointsArray* _path = nullptr, bool generatePath = false, bool forceDestination = false) : id(_id),
i_x(_x), i_y(_y), i_z(_z), speed(_speed), i_orientation(orientation), _generatePath(generatePath), _forceDestination(forceDestination)
{
if (_path)
m_precomputedPath = *_path;
}
public:
PointMovementGenerator(uint32 _id, float _x, float _y, float _z, float _speed = 0.0f, float orientation = 0.0f, const Movement::PointsArray* _path = nullptr, bool generatePath = false, bool forceDestination = false) : id(_id),
i_x(_x), i_y(_y), i_z(_z), speed(_speed), i_orientation(orientation), _generatePath(generatePath), _forceDestination(forceDestination)
{
if (_path)
m_precomputedPath = *_path;
}
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
bool DoUpdate(T*, uint32);
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
bool DoUpdate(T*, uint32);
void MovementInform(T*);
void MovementInform(T*);
void unitSpeedChanged() { i_recalculateSpeed = true; }
void unitSpeedChanged() { i_recalculateSpeed = true; }
MovementGeneratorType GetMovementGeneratorType() { return POINT_MOTION_TYPE; }
MovementGeneratorType GetMovementGeneratorType() { return POINT_MOTION_TYPE; }
bool GetDestination(float& x, float& y, float& z) const { x=i_x; y=i_y; z=i_z; return true; }
private:
uint32 id;
float i_x, i_y, i_z;
float speed;
float i_orientation;
bool i_recalculateSpeed;
Movement::PointsArray m_precomputedPath;
bool _generatePath;
bool _forceDestination;
bool GetDestination(float& x, float& y, float& z) const { x = i_x; y = i_y; z = i_z; return true; }
private:
uint32 id;
float i_x, i_y, i_z;
float speed;
float i_orientation;
bool i_recalculateSpeed;
Movement::PointsArray m_precomputedPath;
bool _generatePath;
bool _forceDestination;
};
class AssistanceMovementGenerator : public PointMovementGenerator<Creature>
{
public:
AssistanceMovementGenerator(float _x, float _y, float _z) :
PointMovementGenerator<Creature>(0, _x, _y, _z) {}
public:
AssistanceMovementGenerator(float _x, float _y, float _z) :
PointMovementGenerator<Creature>(0, _x, _y, _z) {}
MovementGeneratorType GetMovementGeneratorType() { return ASSISTANCE_MOTION_TYPE; }
void Finalize(Unit*);
MovementGeneratorType GetMovementGeneratorType() { return ASSISTANCE_MOTION_TYPE; }
void Finalize(Unit*);
};
// Does almost nothing - just doesn't allows previous movegen interrupt current effect.
class EffectMovementGenerator : public MovementGenerator
{
public:
explicit EffectMovementGenerator(uint32 Id) : m_Id(Id) {}
void Initialize(Unit*) {}
void Finalize(Unit*);
void Reset(Unit*) {}
bool Update(Unit*, uint32);
MovementGeneratorType GetMovementGeneratorType() { return EFFECT_MOTION_TYPE; }
private:
uint32 m_Id;
public:
explicit EffectMovementGenerator(uint32 Id) : m_Id(Id) {}
void Initialize(Unit*) {}
void Finalize(Unit*);
void Reset(Unit*) {}
bool Update(Unit*, uint32);
MovementGeneratorType GetMovementGeneratorType() { return EFFECT_MOTION_TYPE; }
private:
uint32 m_Id;
};
#endif

View File

@@ -36,10 +36,10 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
return;
}
uint8 random = urand(0, _validPointsVector[_currentPoint].size()-1);
uint8 random = urand(0, _validPointsVector[_currentPoint].size() - 1);
std::vector<uint8>::iterator randomIter = _validPointsVector[_currentPoint].begin() + random;
uint8 newPoint = *randomIter;
uint16 pathIdx = uint16(_currentPoint*RANDOM_POINTS_NUMBER + newPoint);
uint16 pathIdx = uint16(_currentPoint * RANDOM_POINTS_NUMBER + newPoint);
// cant go anywhere from new point, so dont go there to not be stuck
if (_validPointsVector[newPoint].empty())
@@ -62,12 +62,12 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
}
float ground = INVALID_HEIGHT;
float levelZ = map->GetWaterOrGroundLevel(creature->GetPhaseMask(), x, y, z+4.0f, &ground);
float levelZ = map->GetWaterOrGroundLevel(creature->GetPhaseMask(), x, y, z + 4.0f, &ground);
float newZ = INVALID_HEIGHT;
// flying creature
if (creature->CanFly())
newZ = std::max<float>(levelZ, z + rand_norm()*_wanderDistance/2.0f);
newZ = std::max<float>(levelZ, z + rand_norm() * _wanderDistance / 2.0f);
// point underwater
else if (ground < levelZ)
{
@@ -84,7 +84,7 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
else
{
if (levelZ > INVALID_HEIGHT)
newZ = std::min<float>(levelZ-2.0f, z + rand_norm()*_wanderDistance/2.0f);
newZ = std::min<float>(levelZ - 2.0f, z + rand_norm() * _wanderDistance / 2.0f);
newZ = std::max<float>(ground, newZ);
}
}
@@ -119,7 +119,7 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
{
// generated path is too long
float pathLen = _pathGenerator->getPathLength();
if (pathLen*pathLen > creature->GetExactDistSq(x, y, levelZ) * MAX_PATH_LENGHT_FACTOR*MAX_PATH_LENGHT_FACTOR)
if (pathLen * pathLen > creature->GetExactDistSq(x, y, levelZ) * MAX_PATH_LENGHT_FACTOR * MAX_PATH_LENGHT_FACTOR)
{
_validPointsVector[_currentPoint].erase(randomIter);
_preComputedPaths.erase(pathIdx);
@@ -128,24 +128,24 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
finalPath = _pathGenerator->GetPath();
Movement::PointsArray::iterator itr = finalPath.begin();
Movement::PointsArray::iterator itrNext = finalPath.begin()+1;
Movement::PointsArray::iterator itrNext = finalPath.begin() + 1;
float zDiff, distDiff;
for (; itrNext != finalPath.end(); ++itr, ++itrNext)
{
distDiff = sqrt(((*itr).x-(*itrNext).x)*((*itr).x-(*itrNext).x) + ((*itr).y-(*itrNext).y)*((*itr).y-(*itrNext).y));
distDiff = sqrt(((*itr).x - (*itrNext).x) * ((*itr).x - (*itrNext).x) + ((*itr).y - (*itrNext).y) * ((*itr).y - (*itrNext).y));
zDiff = fabs((*itr).z - (*itrNext).z);
// Xinef: tree climbing, cut as much as we can
if (zDiff > 2.0f ||
(G3D::fuzzyNe(zDiff, 0.0f) && distDiff / zDiff < 2.15f)) // ~25˚
(G3D::fuzzyNe(zDiff, 0.0f) && distDiff / zDiff < 2.15f)) // ~25˚
{
_validPointsVector[_currentPoint].erase(randomIter);
_preComputedPaths.erase(pathIdx);
return;
}
if (!map->isInLineOfSight((*itr).x, (*itr).y, (*itr).z+2.f, (*itrNext).x, (*itrNext).y, (*itrNext).z+2.f, creature->GetPhaseMask(), LINEOFSIGHT_ALL_CHECKS))
if (!map->isInLineOfSight((*itr).x, (*itr).y, (*itr).z + 2.f, (*itrNext).x, (*itrNext).y, (*itrNext).z + 2.f, creature->GetPhaseMask(), LINEOFSIGHT_ALL_CHECKS))
{
_validPointsVector[_currentPoint].erase(randomIter);
_preComputedPaths.erase(pathIdx);
@@ -171,7 +171,7 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
}
_currentPoint = newPoint;
G3D::Vector3& finalPoint = finalPath[finalPath.size()-1];
G3D::Vector3& finalPoint = finalPath[finalPath.size() - 1];
_currDestPosition.Relocate(finalPoint.x, finalPoint.y, finalPoint.z);
creature->AddUnitState(UNIT_STATE_ROAMING_MOVE);
@@ -213,9 +213,9 @@ void RandomMovementGenerator<Creature>::DoInitialize(Creature* creature)
_destinationPoints.clear();
for (uint8 i = 0; i < RANDOM_POINTS_NUMBER; ++i)
{
float angle = (M_PI*2.0f/(float)RANDOM_POINTS_NUMBER)*i;
float factor = 0.5f + rand_norm()*0.5f;
_destinationPoints.push_back(G3D::Vector3(_initialPosition.GetPositionX() + _wanderDistance*cos(angle)*factor, _initialPosition.GetPositionY() + _wanderDistance*sin(angle)*factor, _initialPosition.GetPositionZ()));
float angle = (M_PI * 2.0f / (float)RANDOM_POINTS_NUMBER) * i;
float factor = 0.5f + rand_norm() * 0.5f;
_destinationPoints.push_back(G3D::Vector3(_initialPosition.GetPositionX() + _wanderDistance * cos(angle)*factor, _initialPosition.GetPositionY() + _wanderDistance * sin(angle)*factor, _initialPosition.GetPositionZ()));
}
}
@@ -233,7 +233,7 @@ void RandomMovementGenerator<Creature>::DoReset(Creature* creature)
template<>
void RandomMovementGenerator<Creature>::DoFinalize(Creature* creature)
{
creature->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
creature->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
creature->SetWalk(false);
}

View File

@@ -17,41 +17,41 @@
template<class T>
class RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovementGenerator<T> >
{
public:
RandomMovementGenerator(float wanderDistance = 0.0f) : _nextMoveTime(0), _moveCount(0), _wanderDistance(wanderDistance), _pathGenerator(nullptr), _currentPoint(RANDOM_POINTS_NUMBER)
public:
RandomMovementGenerator(float wanderDistance = 0.0f) : _nextMoveTime(0), _moveCount(0), _wanderDistance(wanderDistance), _pathGenerator(nullptr), _currentPoint(RANDOM_POINTS_NUMBER)
{
_initialPosition.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
_destinationPoints.reserve(RANDOM_POINTS_NUMBER);
for (uint8 i = 0; i < RANDOM_POINTS_NUMBER; ++i)
{
_initialPosition.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
_destinationPoints.reserve(RANDOM_POINTS_NUMBER);
for (uint8 i = 0; i < RANDOM_POINTS_NUMBER; ++i)
{
_validPointsVector[i].reserve(RANDOM_LINKS_COUNT);
for (uint8 j = 0; j < RANDOM_LINKS_COUNT; ++j)
_validPointsVector[i].push_back((i + j + RANDOM_POINTS_NUMBER/2 - RANDOM_LINKS_COUNT/2) % RANDOM_POINTS_NUMBER);
}
_validPointsVector[RANDOM_POINTS_NUMBER].reserve(RANDOM_POINTS_NUMBER);
for (uint8 i = 0; i < RANDOM_POINTS_NUMBER; ++i)
_validPointsVector[RANDOM_POINTS_NUMBER].push_back(i);
_validPointsVector[i].reserve(RANDOM_LINKS_COUNT);
for (uint8 j = 0; j < RANDOM_LINKS_COUNT; ++j)
_validPointsVector[i].push_back((i + j + RANDOM_POINTS_NUMBER / 2 - RANDOM_LINKS_COUNT / 2) % RANDOM_POINTS_NUMBER);
}
void _setRandomLocation(T*);
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
bool DoUpdate(T*, const uint32);
bool GetResetPosition(float& x, float& y, float& z);
MovementGeneratorType GetMovementGeneratorType() { return RANDOM_MOTION_TYPE; }
_validPointsVector[RANDOM_POINTS_NUMBER].reserve(RANDOM_POINTS_NUMBER);
for (uint8 i = 0; i < RANDOM_POINTS_NUMBER; ++i)
_validPointsVector[RANDOM_POINTS_NUMBER].push_back(i);
}
private:
TimeTrackerSmall _nextMoveTime;
uint8 _moveCount;
float _wanderDistance;
PathGenerator* _pathGenerator;
std::vector<G3D::Vector3> _destinationPoints;
std::vector<uint8> _validPointsVector[RANDOM_POINTS_NUMBER+1];
uint8 _currentPoint;
std::map<uint16, Movement::PointsArray> _preComputedPaths;
Position _initialPosition, _currDestPosition;
void _setRandomLocation(T*);
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
bool DoUpdate(T*, const uint32);
bool GetResetPosition(float& x, float& y, float& z);
MovementGeneratorType GetMovementGeneratorType() { return RANDOM_MOTION_TYPE; }
private:
TimeTrackerSmall _nextMoveTime;
uint8 _moveCount;
float _wanderDistance;
PathGenerator* _pathGenerator;
std::vector<G3D::Vector3> _destinationPoints;
std::vector<uint8> _validPointsVector[RANDOM_POINTS_NUMBER + 1];
uint8 _currentPoint;
std::map<uint16, Movement::PointsArray> _preComputedPaths;
Position _initialPosition, _currDestPosition;
};
#endif

View File

@@ -22,9 +22,9 @@
#include <cmath>
template<class T, typename D>
void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool initial)
void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool initial)
{
if (!i_target.isValid() || !i_target->IsInWorld() || !owner->IsInMap(i_target.getTarget()))
if (!i_target.isValid() || !i_target->IsInWorld() || !owner->IsInMap(i_target.getTarget()))
return;
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE))
@@ -41,7 +41,7 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool ini
bool useMMaps = MMAP::MMapFactory::IsPathfindingEnabled(owner->FindMap()) && !sameTransport;
bool forceDest = (owner->FindMap() && owner->FindMap()->IsDungeon() && !isPlayerPet) || // force in instances to prevent exploiting
(owner->GetTypeId() == TYPEID_UNIT && ((owner->IsPet() && owner->HasUnitState(UNIT_STATE_FOLLOW)) || // allow pets following their master to cheat while generating paths
((Creature*)owner)->isWorldBoss() || ((Creature*)owner)->IsDungeonBoss())) || // force for all bosses, even not in instances
((Creature*)owner)->isWorldBoss() || ((Creature*)owner)->IsDungeonBoss())) || // force for all bosses, even not in instances
(owner->GetMapId() == 572 && (owner->GetPositionX() < 1275.0f || i_target->GetPositionX() < 1275.0f)) || // pussywizard: Ruins of Lordaeron - special case (acid)
sameTransport || // nothing to comment, can't find path on transports so allow it
(i_target->GetTypeId() == TYPEID_PLAYER && i_target->ToPlayer()->IsGameMaster()); // for .npc follow
@@ -63,10 +63,10 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool ini
return;
bool inRange = i_target->GetRandomContactPoint(owner, x, y, z, forcePoint);
if (useMMaps && !inRange && (!isPlayerPet || i_target->GetPositionZ()-z > 50.0f))
if (useMMaps && !inRange && (!isPlayerPet || i_target->GetPositionZ() - z > 50.0f))
{
//useMMaps = false;
owner->m_targetsNotAcceptable[i_target->GetGUID()] = MMapTargetData(sWorld->GetGameTime()+DISALLOW_TIME_AFTER_FAIL, owner, i_target.getTarget());
owner->m_targetsNotAcceptable[i_target->GetGUID()] = MMapTargetData(sWorld->GetGameTime() + DISALLOW_TIME_AFTER_FAIL, owner, i_target.getTarget());
return;
}
@@ -115,7 +115,7 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool ini
// Xinef: Fix follow angle for hostile units
if (angle == 0.0f && owner->GetVictim() && owner->GetVictim()->GetGUID() == i_target->GetGUID())
angle = MapManager::NormalizeOrientation(i_target->GetAngle(owner)-i_target->GetOrientation());
angle = MapManager::NormalizeOrientation(i_target->GetAngle(owner) - i_target->GetOrientation());
// to at i_offset distance from target and i_angle from target facing
bool inRange = i_target->GetClosePoint(x, y, z, size, dist, angle, owner, forcePoint);
if (!inRange && (forceDest || !useMMaps) && owner->HasUnitState(UNIT_STATE_FOLLOW) && fabs(i_target->GetPositionZ() - z) > 25.0f)
@@ -154,7 +154,7 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool ini
else
z = i_target->GetPositionZ();
init.MoveTo(x,y,z);
init.MoveTo(x, y, z);
if (i_angle == 0.f)
init.SetFacing(i_target.getTarget());
init.SetWalk(((D*)this)->EnableWalking());
@@ -164,7 +164,7 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool ini
if (pillar->GetGoState() == GO_STATE_ACTIVE || (pillar->GetGoState() == GO_STATE_READY && pillar->ToTransport()->GetPathProgress() > 0))
{
Position pos;
owner->GetFirstCollisionPositionForTotem(pos, owner->GetExactDist2d(i_target.getTarget()), owner->GetAngle(i_target.getTarget())-owner->GetOrientation(), false);
owner->GetFirstCollisionPositionForTotem(pos, owner->GetExactDist2d(i_target.getTarget()), owner->GetAngle(i_target.getTarget()) - owner->GetOrientation(), false);
x = pos.GetPositionX();
y = pos.GetPositionY();
z = 28.28f;
@@ -184,10 +184,10 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool ini
if (result)
{
float maxDist = MELEE_RANGE + owner->GetMeleeReach() + i_target->GetMeleeReach();
if (!forceDest && (i_path->GetPathType() & PATHFIND_NOPATH || (!i_offset && !isPlayerPet && i_target->GetExactDistSq(i_path->GetActualEndPosition().x, i_path->GetActualEndPosition().y, i_path->GetActualEndPosition().z) > maxDist*maxDist)))
if (!forceDest && (i_path->GetPathType() & PATHFIND_NOPATH || (!i_offset && !isPlayerPet && i_target->GetExactDistSq(i_path->GetActualEndPosition().x, i_path->GetActualEndPosition().y, i_path->GetActualEndPosition().z) > maxDist * maxDist)))
{
lastPathingFailMSTime = World::GetGameTimeMS();
owner->m_targetsNotAcceptable[i_target->GetGUID()] = MMapTargetData(sWorld->GetGameTime()+DISALLOW_TIME_AFTER_FAIL, owner, i_target.getTarget());
owner->m_targetsNotAcceptable[i_target->GetGUID()] = MMapTargetData(sWorld->GetGameTime() + DISALLOW_TIME_AFTER_FAIL, owner, i_target.getTarget());
return;
}
else
@@ -209,7 +209,7 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool ini
owner->AddUnitState(UNIT_STATE_CHASE);
init.MoveTo(x,y,z);
init.MoveTo(x, y, z);
// Using the same condition for facing target as the one that is used for SetInFront on movement end
// - applies to ChaseMovementGenerator mostly
if (i_angle == 0.f)
@@ -220,7 +220,7 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool ini
}
template<class T, typename D>
bool TargetedMovementGeneratorMedium<T,D>::DoUpdate(T* owner, uint32 time_diff)
bool TargetedMovementGeneratorMedium<T, D>::DoUpdate(T* owner, uint32 time_diff)
{
if (!i_target.isValid() || !i_target->IsInWorld())
return false;
@@ -288,10 +288,10 @@ bool TargetedMovementGeneratorMedium<T,D>::DoUpdate(T* owner, uint32 time_diff)
if (TransportBase* transport = owner->GetDirectTransport())
transport->CalculatePassengerPosition(dest.x, dest.y, dest.z);
float dist = (dest - G3D::Vector3(i_target->GetPositionX(),i_target->GetPositionY(),i_target->GetPositionZ())).squaredLength();
float dist = (dest - G3D::Vector3(i_target->GetPositionX(), i_target->GetPositionY(), i_target->GetPositionZ())).squaredLength();
float targetMoveDistSq = i_target->GetExactDistSq(&lastTargetXYZ);
if (dist >= allowed_dist_sq || (!i_offset && targetMoveDistSq >= 1.5f*1.5f))
if (targetMoveDistSq >= 0.1f*0.1f || owner->GetExactDistSq(&lastOwnerXYZ) >= 0.1f*0.1f)
if (dist >= allowed_dist_sq || (!i_offset && targetMoveDistSq >= 1.5f * 1.5f))
if (targetMoveDistSq >= 0.1f * 0.1f || owner->GetExactDistSq(&lastOwnerXYZ) >= 0.1f * 0.1f)
_setTargetLocation(owner, false);
}
@@ -332,7 +332,7 @@ template<class T>
void ChaseMovementGenerator<T>::_reachTarget(T* owner)
{
if (owner->IsWithinMeleeRange(this->i_target.getTarget()))
owner->Attack(this->i_target.getTarget(),true);
owner->Attack(this->i_target.getTarget(), true);
}
template<>
@@ -450,14 +450,14 @@ void FollowMovementGenerator<Creature>::MovementInform(Creature* unit)
}
//-----------------------------------------------//
template void TargetedMovementGeneratorMedium<Player,ChaseMovementGenerator<Player> >::_setTargetLocation(Player*, bool initial);
template void TargetedMovementGeneratorMedium<Player,FollowMovementGenerator<Player> >::_setTargetLocation(Player*, bool initial);
template void TargetedMovementGeneratorMedium<Creature,ChaseMovementGenerator<Creature> >::_setTargetLocation(Creature*, bool initial);
template void TargetedMovementGeneratorMedium<Creature,FollowMovementGenerator<Creature> >::_setTargetLocation(Creature*, bool initial);
template bool TargetedMovementGeneratorMedium<Player,ChaseMovementGenerator<Player> >::DoUpdate(Player*, uint32);
template bool TargetedMovementGeneratorMedium<Player,FollowMovementGenerator<Player> >::DoUpdate(Player*, uint32);
template bool TargetedMovementGeneratorMedium<Creature,ChaseMovementGenerator<Creature> >::DoUpdate(Creature*, uint32);
template bool TargetedMovementGeneratorMedium<Creature,FollowMovementGenerator<Creature> >::DoUpdate(Creature*, uint32);
template void TargetedMovementGeneratorMedium<Player, ChaseMovementGenerator<Player> >::_setTargetLocation(Player*, bool initial);
template void TargetedMovementGeneratorMedium<Player, FollowMovementGenerator<Player> >::_setTargetLocation(Player*, bool initial);
template void TargetedMovementGeneratorMedium<Creature, ChaseMovementGenerator<Creature> >::_setTargetLocation(Creature*, bool initial);
template void TargetedMovementGeneratorMedium<Creature, FollowMovementGenerator<Creature> >::_setTargetLocation(Creature*, bool initial);
template bool TargetedMovementGeneratorMedium<Player, ChaseMovementGenerator<Player> >::DoUpdate(Player*, uint32);
template bool TargetedMovementGeneratorMedium<Player, FollowMovementGenerator<Player> >::DoUpdate(Player*, uint32);
template bool TargetedMovementGeneratorMedium<Creature, ChaseMovementGenerator<Creature> >::DoUpdate(Creature*, uint32);
template bool TargetedMovementGeneratorMedium<Creature, FollowMovementGenerator<Creature> >::DoUpdate(Creature*, uint32);
template void ChaseMovementGenerator<Player>::_reachTarget(Player*);
template void ChaseMovementGenerator<Creature>::_reachTarget(Creature*);

View File

@@ -15,95 +15,95 @@
class TargetedMovementGeneratorBase
{
public:
TargetedMovementGeneratorBase(Unit* target) { i_target.link(target, this); }
void stopFollowing() { }
protected:
FollowerReference i_target;
Position lastOwnerXYZ;
Position lastTargetXYZ;
public:
TargetedMovementGeneratorBase(Unit* target) { i_target.link(target, this); }
void stopFollowing() { }
protected:
FollowerReference i_target;
Position lastOwnerXYZ;
Position lastTargetXYZ;
};
template<class T, typename D>
class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, public TargetedMovementGeneratorBase
{
protected:
TargetedMovementGeneratorMedium(Unit* target, float offset, float angle) :
TargetedMovementGeneratorBase(target), i_path(nullptr), lastPathingFailMSTime(0),
i_recheckDistance(0), i_recheckDistanceForced(2500), i_offset(offset), i_angle(angle),
i_recalculateTravel(false), i_targetReached(false)
{
}
~TargetedMovementGeneratorMedium() { delete i_path; }
protected:
TargetedMovementGeneratorMedium(Unit* target, float offset, float angle) :
TargetedMovementGeneratorBase(target), i_path(nullptr), lastPathingFailMSTime(0),
i_recheckDistance(0), i_recheckDistanceForced(2500), i_offset(offset), i_angle(angle),
i_recalculateTravel(false), i_targetReached(false)
{
}
~TargetedMovementGeneratorMedium() { delete i_path; }
public:
bool DoUpdate(T*, uint32);
Unit* GetTarget() const { return i_target.getTarget(); }
public:
bool DoUpdate(T*, uint32);
Unit* GetTarget() const { return i_target.getTarget(); }
void unitSpeedChanged() { i_recalculateTravel = true; }
bool IsReachable() const { return (i_path) ? (i_path->GetPathType() & PATHFIND_NORMAL) : true; }
void unitSpeedChanged() { i_recalculateTravel = true; }
bool IsReachable() const { return (i_path) ? (i_path->GetPathType() & PATHFIND_NORMAL) : true; }
protected:
void _setTargetLocation(T* owner, bool initial);
protected:
void _setTargetLocation(T* owner, bool initial);
PathGenerator* i_path;
uint32 lastPathingFailMSTime;
TimeTrackerSmall i_recheckDistance;
TimeTrackerSmall i_recheckDistanceForced;
float i_offset;
float i_angle;
bool i_recalculateTravel : 1;
bool i_targetReached : 1;
PathGenerator* i_path;
uint32 lastPathingFailMSTime;
TimeTrackerSmall i_recheckDistance;
TimeTrackerSmall i_recheckDistanceForced;
float i_offset;
float i_angle;
bool i_recalculateTravel : 1;
bool i_targetReached : 1;
};
template<class T>
class ChaseMovementGenerator : public TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >
{
public:
ChaseMovementGenerator(Unit* target)
: TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >(target) {}
ChaseMovementGenerator(Unit* target, float offset, float angle)
: TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >(target, offset, angle) {}
~ChaseMovementGenerator() {}
public:
ChaseMovementGenerator(Unit* target)
: TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >(target) {}
ChaseMovementGenerator(Unit* target, float offset, float angle)
: TargetedMovementGeneratorMedium<T, ChaseMovementGenerator<T> >(target, offset, angle) {}
~ChaseMovementGenerator() {}
MovementGeneratorType GetMovementGeneratorType() { return CHASE_MOTION_TYPE; }
MovementGeneratorType GetMovementGeneratorType() { return CHASE_MOTION_TYPE; }
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
void MovementInform(T*);
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
void MovementInform(T*);
static void _clearUnitStateMove(T* u) { u->ClearUnitState(UNIT_STATE_CHASE_MOVE); }
static void _addUnitStateMove(T* u) { u->AddUnitState(UNIT_STATE_CHASE_MOVE); }
bool EnableWalking() const { return false;}
bool _lostTarget(T* u) const { return u->GetVictim() != this->GetTarget(); }
void _reachTarget(T*);
static void _clearUnitStateMove(T* u) { u->ClearUnitState(UNIT_STATE_CHASE_MOVE); }
static void _addUnitStateMove(T* u) { u->AddUnitState(UNIT_STATE_CHASE_MOVE); }
bool EnableWalking() const { return false;}
bool _lostTarget(T* u) const { return u->GetVictim() != this->GetTarget(); }
void _reachTarget(T*);
};
template<class T>
class FollowMovementGenerator : public TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >
{
public:
FollowMovementGenerator(Unit* target)
: TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >(target){}
FollowMovementGenerator(Unit* target, float offset, float angle)
: TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >(target, offset, angle) {}
~FollowMovementGenerator() {}
public:
FollowMovementGenerator(Unit* target)
: TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >(target) {}
FollowMovementGenerator(Unit* target, float offset, float angle)
: TargetedMovementGeneratorMedium<T, FollowMovementGenerator<T> >(target, offset, angle) {}
~FollowMovementGenerator() {}
MovementGeneratorType GetMovementGeneratorType() { return FOLLOW_MOTION_TYPE; }
MovementGeneratorType GetMovementGeneratorType() { return FOLLOW_MOTION_TYPE; }
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
void MovementInform(T*);
void DoInitialize(T*);
void DoFinalize(T*);
void DoReset(T*);
void MovementInform(T*);
static void _clearUnitStateMove(T* u) { u->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); }
static void _addUnitStateMove(T* u) { u->AddUnitState(UNIT_STATE_FOLLOW_MOVE); }
bool EnableWalking() const;
bool _lostTarget(T*) const { return false; }
void _reachTarget(T*) {}
private:
void _updateSpeed(T* owner);
static void _clearUnitStateMove(T* u) { u->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); }
static void _addUnitStateMove(T* u) { u->AddUnitState(UNIT_STATE_FOLLOW_MOVE); }
bool EnableWalking() const;
bool _lostTarget(T*) const { return false; }
void _reachTarget(T*) {}
private:
void _updateSpeed(T* owner);
};
#endif

View File

@@ -41,18 +41,18 @@ void WaypointMovementGenerator<Creature>::LoadPath(Creature* creature)
void WaypointMovementGenerator<Creature>::DoInitialize(Creature* creature)
{
LoadPath(creature);
creature->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
creature->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
}
void WaypointMovementGenerator<Creature>::DoFinalize(Creature* creature)
{
creature->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
creature->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
creature->SetWalk(false);
}
void WaypointMovementGenerator<Creature>::DoReset(Creature* creature)
{
creature->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE);
creature->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE);
StartMoveNow(creature);
}
@@ -134,7 +134,7 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
return false;
}
i_currentNode = (i_currentNode+1) % i_path->size();
i_currentNode = (i_currentNode + 1) % i_path->size();
}
// xinef: do not initialize motion if we got stunned in movementinform
@@ -240,7 +240,7 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di
// xinef: do not start pre-empetive movement if current node has delay or we are ending waypoint movement
bool finished = creature->movespline->Finalized();
if (!finished && !i_path->at(i_currentNode)->delay && ((i_currentNode != i_path->size() - 1) || repeating))
finished = (creature->movespline->_Spline().length(creature->movespline->_currentSplineIdx()+1) - creature->movespline->timePassed()) < 200;
finished = (creature->movespline->_Spline().length(creature->movespline->_currentSplineIdx() + 1) - creature->movespline->timePassed()) < 200;
if (finished)
{
@@ -249,8 +249,8 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di
}
}
}
return true;
}
return true;
}
void WaypointMovementGenerator<Creature>::MovementInform(Creature* creature)
{
@@ -277,7 +277,7 @@ void FlightPathMovementGenerator::LoadPath(Player* player)
{
_pointsForPathSwitch.clear();
std::vector<uint32> const& taxi = player->m_taxi.GetPath();
for (uint32 src = player->m_taxi.GetTaxiSegment(), dst = player->m_taxi.GetTaxiSegment()+1; dst < taxi.size(); src = dst++)
for (uint32 src = player->m_taxi.GetTaxiSegment(), dst = player->m_taxi.GetTaxiSegment() + 1; dst < taxi.size(); src = dst++)
{
uint32 path, cost;
sObjectMgr->GetTaxiPath(taxi[src], taxi[dst], path, cost);
@@ -397,7 +397,7 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/)
departureEvent = !departureEvent;
// xinef: map should be switched, do not rely on client packets QQ
if (i_currentNode + 1 < i_path.size() && i_path[i_currentNode+1]->mapid != player->GetMapId())
if (i_currentNode + 1 < i_path.size() && i_path[i_currentNode + 1]->mapid != player->GetMapId())
{
++i_currentNode;
_mapSwitch = true;
@@ -415,8 +415,7 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/)
return false;
}
}
while (true);
} while (true);
}
return i_currentNode < (i_path.size() - 1);
@@ -481,11 +480,12 @@ void FlightPathMovementGenerator::PreloadEndGrid()
if (endMap)
{
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
sLog->outDetail("Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path.size()-1));
sLog->outDetail("Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path.size() - 1));
#endif
endMap->LoadGrid(_endGridX, _endGridY);
}
else {
else
{
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
sLog->outDetail("Unable to determine map to preload flightmaster grid");
#endif

View File

@@ -24,16 +24,16 @@
template<class T, class P>
class PathMovementBase
{
public:
PathMovementBase() : i_path(), i_currentNode(0) {}
PathMovementBase(P path) : i_path(path), i_currentNode(0) {}
virtual ~PathMovementBase() {};
public:
PathMovementBase() : i_path(), i_currentNode(0) {}
PathMovementBase(P path) : i_path(path), i_currentNode(0) {}
virtual ~PathMovementBase() {};
uint32 GetCurrentNode() const { return i_currentNode; }
uint32 GetCurrentNode() const { return i_currentNode; }
protected:
P i_path;
uint32 i_currentNode;
protected:
P i_path;
uint32 i_currentNode;
};
template<class T>
@@ -43,47 +43,47 @@ template<>
class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Creature, WaypointMovementGenerator<Creature> >,
public PathMovementBase<Creature, WaypointPath const*>
{
public:
WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true)
: PathMovementBase((WaypointPath const*)NULL), i_nextMoveTime(0), m_isArrivalDone(false), path_id(_path_id), repeating(_repeating) {}
~WaypointMovementGenerator() { i_path = nullptr; }
void DoInitialize(Creature*);
void DoFinalize(Creature*);
void DoReset(Creature*);
bool DoUpdate(Creature*, uint32 diff);
public:
WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true)
: PathMovementBase((WaypointPath const*)NULL), i_nextMoveTime(0), m_isArrivalDone(false), path_id(_path_id), repeating(_repeating) {}
~WaypointMovementGenerator() { i_path = nullptr; }
void DoInitialize(Creature*);
void DoFinalize(Creature*);
void DoReset(Creature*);
bool DoUpdate(Creature*, uint32 diff);
void MovementInform(Creature*);
void MovementInform(Creature*);
MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; }
MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; }
// now path movement implmementation
void LoadPath(Creature*);
// now path movement implmementation
void LoadPath(Creature*);
private:
private:
void Stop(int32 time) { i_nextMoveTime.Reset(time);}
void Stop(int32 time) { i_nextMoveTime.Reset(time);}
bool Stopped() { return !i_nextMoveTime.Passed();}
bool Stopped() { return !i_nextMoveTime.Passed();}
bool CanMove(int32 diff)
{
i_nextMoveTime.Update(diff);
return i_nextMoveTime.Passed();
}
bool CanMove(int32 diff)
{
i_nextMoveTime.Update(diff);
return i_nextMoveTime.Passed();
}
void OnArrived(Creature*);
bool StartMove(Creature*);
void OnArrived(Creature*);
bool StartMove(Creature*);
void StartMoveNow(Creature* creature)
{
i_nextMoveTime.Reset(0);
StartMove(creature);
}
void StartMoveNow(Creature* creature)
{
i_nextMoveTime.Reset(0);
StartMove(creature);
}
TimeTrackerSmall i_nextMoveTime;
bool m_isArrivalDone;
uint32 path_id;
bool repeating;
TimeTrackerSmall i_nextMoveTime;
bool m_isArrivalDone;
uint32 path_id;
bool repeating;
};
/** FlightPathMovementGenerator generates movement of the player for the paths
@@ -92,40 +92,40 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Crea
class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, FlightPathMovementGenerator >,
public PathMovementBase<Player, TaxiPathNodeList>
{
public:
explicit FlightPathMovementGenerator(uint32 startNode = 0)
{
i_currentNode = startNode;
_endGridX = 0.0f;
_endGridY = 0.0f;
_endMapId = 0;
_preloadTargetNode = 0;
_mapSwitch = false;
}
void LoadPath(Player* player);
void DoInitialize(Player*);
void DoReset(Player*);
void DoFinalize(Player*);
bool DoUpdate(Player*, uint32);
MovementGeneratorType GetMovementGeneratorType() { return FLIGHT_MOTION_TYPE; }
public:
explicit FlightPathMovementGenerator(uint32 startNode = 0)
{
i_currentNode = startNode;
_endGridX = 0.0f;
_endGridY = 0.0f;
_endMapId = 0;
_preloadTargetNode = 0;
_mapSwitch = false;
}
void LoadPath(Player* player);
void DoInitialize(Player*);
void DoReset(Player*);
void DoFinalize(Player*);
bool DoUpdate(Player*, uint32);
MovementGeneratorType GetMovementGeneratorType() { return FLIGHT_MOTION_TYPE; }
TaxiPathNodeList const& GetPath() { return i_path; }
uint32 GetPathAtMapEnd() const;
bool HasArrived() const { return (i_currentNode >= i_path.size()); }
void SetCurrentNodeAfterTeleport();
void SkipCurrentNode() { ++i_currentNode; }
void DoEventIfAny(Player* player, TaxiPathNodeEntry const* node, bool departure);
TaxiPathNodeList const& GetPath() { return i_path; }
uint32 GetPathAtMapEnd() const;
bool HasArrived() const { return (i_currentNode >= i_path.size()); }
void SetCurrentNodeAfterTeleport();
void SkipCurrentNode() { ++i_currentNode; }
void DoEventIfAny(Player* player, TaxiPathNodeEntry const* node, bool departure);
void InitEndGridInfo();
void PreloadEndGrid();
void InitEndGridInfo();
void PreloadEndGrid();
private:
float _endGridX; //! X coord of last node location
float _endGridY; //! Y coord of last node location
uint32 _endMapId; //! map Id of last node location
uint32 _preloadTargetNode; //! node index where preloading starts
bool _mapSwitch;
private:
float _endGridX; //! X coord of last node location
float _endGridY; //! Y coord of last node location
uint32 _endMapId; //! map Id of last node location
uint32 _preloadTargetNode; //! node index where preloading starts
bool _mapSwitch;
std::deque<uint32> _pointsForPathSwitch; //! node indexes and costs where TaxiPath changes
std::deque<uint32> _pointsForPathSwitch; //! node indexes and costs where TaxiPath changes
};
#endif