|
|
@@ -0,0 +1,70 @@ |
|
|
template<> |
|
|
bool RandomMovementGenerator<Creature>::GeneratePosition(Creature* creature, float& x, float& y, float& z) |
|
|
{ |
|
|
float respX, respY, respZ, destX, destY, destZ, travelDistZ; |
|
|
creature->GetCreatureMovementPath().GetCurrentPath()->position.GetPosition(respX, respY, respZ); |
|
|
|
|
|
Map const* map = creature->GetBaseMap(); |
|
|
|
|
|
// For 2D/3D system selection |
|
|
//bool is_land_ok = creature.CanWalk(); // not used? |
|
|
//bool is_water_ok = creature.CanSwim(); // not used? |
|
|
bool is_air_ok = creature->CanFly(); |
|
|
|
|
|
const float angle = float(rand_norm()) * static_cast<float>(M_PI*2.0f); |
|
|
const float range = float(rand_norm()) * wander_distance; |
|
|
const float distanceX = range * std::cos(angle); |
|
|
const float distanceY = range * std::sin(angle); |
|
|
|
|
|
destX = respX + distanceX; |
|
|
destY = respY + distanceY; |
|
|
|
|
|
Trinity::NormalizeMapCoord(destX); |
|
|
Trinity::NormalizeMapCoord(destY); |
|
|
|
|
|
travelDistZ = range; // sin^2+cos^2=1, so travelDistZ=range^2; no need for sqrt below |
|
|
|
|
|
if (is_air_ok) // 3D system above ground and above water (flying mode) |
|
|
{ |
|
|
// Limit height change |
|
|
const float distanceZ = float(rand_norm()) * travelDistZ / 2.0f; |
|
|
destZ = respZ + distanceZ; |
|
|
float levelZ = map->GetWaterOrGroundLevel(creature->GetPhaseMask(), destX, destY, destZ - 2.0f); |
|
|
|
|
|
// Problem here, we must fly above the ground and water, not under. Let's try on next tick |
|
|
if (levelZ >= destZ) |
|
|
return false; |
|
|
} |
|
|
//else if (is_water_ok) // 3D system under water and above ground (swimming mode) |
|
|
else // 2D only |
|
|
{ |
|
|
// 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE) |
|
|
travelDistZ = travelDistZ >= 10.0f ? 10.0f : travelDistZ; |
|
|
|
|
|
// The fastest way to get an accurate result 90% of the time. |
|
|
// Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long. |
|
|
destZ = map->GetHeight(creature->GetPhaseMask(), destX, destY, respZ + travelDistZ - 2.0f, false); |
|
|
|
|
|
if (std::fabs(destZ - respZ) > travelDistZ) // Map check |
|
|
{ |
|
|
// Vmap Horizontal or above |
|
|
destZ = map->GetHeight(creature->GetPhaseMask(), destX, destY, respZ - 2.0f, true); |
|
|
|
|
|
if (std::fabs(destZ - respZ) > travelDistZ) |
|
|
{ |
|
|
// Vmap Higher |
|
|
destZ = map->GetHeight(creature->GetPhaseMask(), destX, destY, respZ + travelDistZ - 2.0f, true); |
|
|
|
|
|
// let's forget this bad coords where a z cannot be find and retry at next tick |
|
|
if (std::fabs(destZ - respZ) > travelDistZ) |
|
|
return false; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
x = destX; |
|
|
y = destY; |
|
|
z = destZ; |
|
|
|
|
|
return true; |
|
|
} |