Improve confused, random and fleeing movement generators.
Improve random movement generator. (c2607) @cyberium Now creatures will have possibility to move up/down on swim/fly situation. Random groundpoint will have more accurracy and the creature have less chance to go throught object. Note: - Some creature may have invalid value like inhabit type and other flags in relation of movement in water. If its the case the result is not so good. DB must be corrected for these creatures. - we have to find a way to handle correctly movement flags. Make sure player stop moving when confused aura is removed. (c2629) @cyberium modified version of @kvipka work Improve confused movement generator. (c2630) @cyberium Improve fleeing movement generator. (c2631) @cyberium
This commit is contained in:
parent
fec7b5cd5f
commit
c6210ba12c
@ -1 +1 @@
|
||||
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
|
@ -89,25 +89,21 @@ bool ConfusedMovementGenerator<T>::Update(T& unit, const uint32& diff)
|
||||
// start moving
|
||||
unit.addUnitState(UNIT_STAT_CONFUSED_MOVE);
|
||||
|
||||
float x = i_x + 10.0f * (rand_norm_f() - 0.5f);
|
||||
float y = i_y + 10.0f * (rand_norm_f() - 0.5f);
|
||||
float z = i_z;
|
||||
float destX = i_x;
|
||||
float destY = i_y;
|
||||
float destZ = i_z;
|
||||
|
||||
unit.UpdateAllowedPositionZ(x, y, z);
|
||||
|
||||
PathFinder path(&unit);
|
||||
path.setPathLengthLimit(30.0f);
|
||||
path.calculate(x, y, z);
|
||||
if (path.getPathType() & PATHFIND_NOPATH)
|
||||
// check if new random position is assigned, GetReachableRandomPosition may fail
|
||||
if (unit.GetMap()->GetReachableRandomPosition(&unit, destX, destY, destZ, 10.0f))
|
||||
{
|
||||
i_nextMoveTime.Reset(urand(800, 1000));
|
||||
return true;
|
||||
Movement::MoveSplineInit init(unit);
|
||||
init.MoveTo(destX, destY, destZ, true);
|
||||
init.SetWalk(true);
|
||||
init.Launch();
|
||||
i_nextMoveTime.Reset(urand(800, 1000)); // Keep a short wait time
|
||||
}
|
||||
|
||||
Movement::MoveSplineInit init(unit);
|
||||
init.MovebyPath(path.getPath());
|
||||
init.SetWalk(true);
|
||||
init.Launch();
|
||||
else
|
||||
i_nextMoveTime.Reset(50); // Retry later
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,7 +114,7 @@ template<>
|
||||
void ConfusedMovementGenerator<Player>::Finalize(Player& unit)
|
||||
{
|
||||
unit.clearUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_CONFUSED_MOVE);
|
||||
unit.StopMoving();
|
||||
unit.StopMoving(true);
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -46,7 +46,11 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T& owner)
|
||||
|
||||
float x, y, z;
|
||||
if (!_getPoint(owner, x, y, z))
|
||||
{ return; }
|
||||
{
|
||||
// random point not found recheck later
|
||||
i_nextCheckTime.Reset(50);
|
||||
return;
|
||||
}
|
||||
|
||||
owner.addUnitState(UNIT_STAT_FLEEING_MOVE);
|
||||
|
||||
@ -55,7 +59,8 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T& owner)
|
||||
path.calculate(x, y, z);
|
||||
if (path.getPathType() & PATHFIND_NOPATH)
|
||||
{
|
||||
i_nextCheckTime.Reset(urand(1000, 1500));
|
||||
// path not found recheck later
|
||||
i_nextCheckTime.Reset(50);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -109,12 +114,23 @@ bool FleeingMovementGenerator<T>::_getPoint(T& owner, float& x, float& y, float&
|
||||
|
||||
x = curr_x + dist * cos(angle);
|
||||
y = curr_y + dist * sin(angle);
|
||||
z = curr_z;
|
||||
z = curr_z + 0.5f;
|
||||
|
||||
// try to fix z
|
||||
if (!owner.GetMap()->GetHeightInRange(x, y, z))
|
||||
return false;
|
||||
|
||||
if (owner.GetTypeId() == TYPEID_PLAYER)
|
||||
{ owner.GetMap()->GetHitPosition(curr_x, curr_y, curr_z, x, y, z, -0.1f); }
|
||||
|
||||
owner.UpdateAllowedPositionZ(x, y, z);
|
||||
{
|
||||
// check any collision
|
||||
float testZ = z + 0.5f; // needed to avoid some false positive hit detection of terrain or passable little object
|
||||
if (owner.GetMap()->GetHitPosition(curr_x, curr_y, curr_z + 0.5f, x, y, testZ, -0.1f))
|
||||
{
|
||||
z = testZ;
|
||||
if (!owner.GetMap()->GetHeightInRange(x, y, z))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -40,39 +40,32 @@ RandomMovementGenerator<Creature>::RandomMovementGenerator(const Creature& creat
|
||||
i_y = respY;
|
||||
i_z = respZ;
|
||||
i_radius = wander_distance;
|
||||
// TODO - add support for flying mobs using some distance
|
||||
i_verticalZ = 0.0f;
|
||||
}
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature& creature)
|
||||
{
|
||||
const float angle = rand_norm_f() * (M_PI_F * 2.0f);
|
||||
const float range = rand_norm_f() * i_radius;
|
||||
|
||||
const float maxPathRange = range * 1.5f;
|
||||
|
||||
float destX = i_x + range * cos(angle);
|
||||
float destY = i_y + range * sin(angle);
|
||||
float destZ = i_z + frand(-1, 1) * i_verticalZ;
|
||||
creature.UpdateAllowedPositionZ(destX, destY, destZ);
|
||||
float destX = i_x;
|
||||
float destY = i_y;
|
||||
float destZ = i_z;
|
||||
|
||||
creature.addUnitState(UNIT_STAT_ROAMING_MOVE);
|
||||
|
||||
Movement::MoveSplineInit init(creature);
|
||||
init.MoveTo(destX, destY, destZ, true, false, maxPathRange);
|
||||
init.SetWalk(true);
|
||||
init.Launch();
|
||||
|
||||
if (creature.CanFly())
|
||||
{ i_nextMoveTime.Reset(0); }
|
||||
else
|
||||
// check if new random position is assigned, GetReachableRandomPosition may fail
|
||||
if (creature.GetMap()->GetReachableRandomPosition(&creature, destX, destY, destZ, i_radius))
|
||||
{
|
||||
Movement::MoveSplineInit init(creature);
|
||||
init.MoveTo(destX, destY, destZ, true);
|
||||
init.SetWalk(true);
|
||||
init.Launch();
|
||||
if (roll_chance_i(MOVEMENT_RANDOM_MMGEN_CHANCE_NO_BREAK))
|
||||
i_nextMoveTime.Reset(50);
|
||||
else
|
||||
i_nextMoveTime.Reset(urand(3000, 10000)); // keep a short wait time
|
||||
i_nextMoveTime.Reset(urand(3000, 10000)); // Keep a short wait time
|
||||
}
|
||||
else
|
||||
i_nextMoveTime.Reset(50); // Retry later
|
||||
return;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -2050,6 +2050,61 @@ bool Map::GetHitPosition(float srcX, float srcY, float srcZ, float& destX, float
|
||||
return result0 || result1;
|
||||
}
|
||||
|
||||
// Find an height within a reasonable range of provided Z. This method may fail so we have to handle that case.
|
||||
bool Map::GetHeightInRange(float x, float y, float& z, float maxSearchDist /*= 4.0f*/) const
|
||||
{
|
||||
float height, vmapHeight, mapHeight;
|
||||
vmapHeight = VMAP_INVALID_HEIGHT_VALUE;
|
||||
|
||||
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
|
||||
if (!vmgr->isLineOfSightCalcEnabled())
|
||||
vmgr = NULL;
|
||||
|
||||
if (vmgr)
|
||||
{
|
||||
// pure vmap search
|
||||
vmapHeight = vmgr->getHeight(i_id, x, y, z + 2.0f, maxSearchDist + 2.0f);
|
||||
}
|
||||
|
||||
// find raw height from .map file on X,Y coordinates
|
||||
if (GridMap* gmap = const_cast<TerrainInfo*>(m_TerrainData)->GetGrid(x, y)) // TODO:: find a way to remove that const_cast
|
||||
mapHeight = gmap->getHeight(x, y);
|
||||
|
||||
float diffMaps = fabs(fabs(z) - fabs(mapHeight));
|
||||
float diffVmaps = fabs(fabs(z) - fabs(vmapHeight));
|
||||
if (diffVmaps < maxSearchDist)
|
||||
{
|
||||
if (diffMaps < maxSearchDist)
|
||||
{
|
||||
// well we simply have to take the highest as normally there we cannot be on top of cavern is maxSearchDist is not too big
|
||||
if (vmapHeight > mapHeight)
|
||||
height = vmapHeight;
|
||||
else
|
||||
height = mapHeight;
|
||||
|
||||
//sLog.outString("vmap %5.4f, map %5.4f, height %5.4f", vmapHeight, mapHeight, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
//sLog.outString("vmap %5.4f", vmapHeight);
|
||||
height = vmapHeight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (diffMaps < maxSearchDist)
|
||||
{
|
||||
//sLog.outString("map %5.4f", mapHeight);
|
||||
height = mapHeight;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
z = std::max<float>(height, m_dyn_tree.getHeight(x, y, height + 1.0f, maxSearchDist));
|
||||
return true;
|
||||
}
|
||||
|
||||
float Map::GetHeight(float x, float y, float z) const
|
||||
{
|
||||
float staticHeight = m_TerrainData->GetHeightStatic(x, y, z);
|
||||
@ -2073,3 +2128,178 @@ bool Map::ContainsGameObjectModel(const GameObjectModel& mdl) const
|
||||
{
|
||||
return m_dyn_tree.contains(mdl);
|
||||
}
|
||||
|
||||
// This will generate a random point to all directions in water for the provided point in radius range.
|
||||
bool Map::GetRandomPointUnderWater(float& x, float& y, float& z, float radius, GridMapLiquidData& liquid_status)
|
||||
{
|
||||
const float angle = rand_norm_f() * (M_PI_F * 2.0f);
|
||||
const float range = rand_norm_f() * radius;
|
||||
|
||||
float i_x = x + range * cos(angle);
|
||||
float i_y = y + range * sin(angle);
|
||||
|
||||
// get real ground of new point
|
||||
// the code consider cylinder instead of sphere for possible z
|
||||
float ground = GetHeight(i_x, i_y, z);
|
||||
if (ground > INVALID_HEIGHT) // GetHeight can fail
|
||||
{
|
||||
float min_z = z - 0.7f * radius; // 0.7 to have a bit a "flat" cylinder, TODO which value looks nicest
|
||||
if (min_z < ground)
|
||||
min_z = ground + 0.5f; // Get some space to prevent under map
|
||||
|
||||
float liquidLevel = liquid_status.level - 2.0f; // just to make the generated point is in water and not on surface or a bit above
|
||||
|
||||
// if not enough space to fit the creature better is to return from here
|
||||
if (min_z > liquidLevel)
|
||||
return false;
|
||||
|
||||
float max_z = std::max(z + 0.7f * radius, min_z);
|
||||
max_z = std::min(max_z, liquidLevel);
|
||||
x = i_x;
|
||||
y = i_y;
|
||||
z = min_z + rand_norm_f() * (max_z - min_z);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// This will generate a random point to all directions in air for the provided point in radius range.
|
||||
bool Map::GetRandomPointInTheAir(float& x, float& y, float& z, float radius)
|
||||
{
|
||||
const float angle = rand_norm_f() * (M_PI_F * 2.0f);
|
||||
const float range = rand_norm_f() * radius;
|
||||
|
||||
float i_x = x + range * cos(angle);
|
||||
float i_y = y + range * sin(angle);
|
||||
|
||||
// get real ground of new point
|
||||
// the code consider cylinder instead of sphere for possible z
|
||||
float ground = GetHeight(i_x, i_y, z);
|
||||
if (ground > INVALID_HEIGHT) // GetHeight can fail
|
||||
{
|
||||
float min_z = z - 0.7f * radius; // 0.7 to have a bit a "flat" cylinder, TODO which value looks nicest
|
||||
if (min_z < ground)
|
||||
min_z = ground + 2.5f; // Get some space to prevent landing
|
||||
float max_z = std::max(z + 0.7f * radius, min_z);
|
||||
x = i_x;
|
||||
y = i_y;
|
||||
z = min_z + rand_norm_f() * (max_z - min_z);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// supposed to be used for not big radius, usually less than 20.0f
|
||||
bool Map::GetReachableRandomPointOnGround(float& x, float& y, float& z, float radius)
|
||||
{
|
||||
// Generate a random range and direction for the new point
|
||||
const float angle = rand_norm_f() * (M_PI_F * 2.0f);
|
||||
const float range = rand_norm_f() * radius;
|
||||
|
||||
float i_x = x + range * cos(angle);
|
||||
float i_y = y + range * sin(angle);
|
||||
float i_z = z + 1.0f;
|
||||
|
||||
GetHitPosition(x, y, z + 1.0f, i_x, i_y, i_z, -0.5f);
|
||||
i_z = z; // reset i_z to z value to avoid too much difference from original point before GetHeightInRange
|
||||
if (!GetHeightInRange(i_x, i_y, i_z)) // GetHeight can fail
|
||||
return false;
|
||||
|
||||
// here we have a valid position but the point can have a big Z in some case
|
||||
// next code will check angle from 2 points
|
||||
// c
|
||||
// /|
|
||||
// / |
|
||||
// b/__|a
|
||||
|
||||
// project vector to get only positive value
|
||||
float ab = fabs(x - i_x);
|
||||
float ac = fabs(z - i_z);
|
||||
|
||||
// slope represented by c angle (in radian)
|
||||
float slope = 0;
|
||||
const float MAX_SLOPE_IN_RADIAN = 50.0f / 180.0f * M_PI_F; // 50(degree) max seem best value for walkable slope
|
||||
|
||||
// check ab vector to avoid divide by 0
|
||||
if (ab > 0.0f)
|
||||
{
|
||||
// compute c angle and convert it from radian to degree
|
||||
slope = atan(ac / ab);
|
||||
if (slope < MAX_SLOPE_IN_RADIAN)
|
||||
{
|
||||
x = i_x;
|
||||
y = i_y;
|
||||
z = i_z;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get random point by handling different situation depending of if the unit is flying/swimming/walking
|
||||
bool Map::GetReachableRandomPosition(Unit* unit, float& x, float& y, float& z, float radius)
|
||||
{
|
||||
|
||||
float i_x = x;
|
||||
float i_y = y;
|
||||
float i_z = z;
|
||||
|
||||
bool newDestAssigned = false; // used to check if new random destination is found
|
||||
|
||||
bool isFlying = false;
|
||||
bool isSwimming = true;
|
||||
switch (unit->GetTypeId())
|
||||
{
|
||||
case TYPEID_PLAYER:
|
||||
isFlying = static_cast<Player*>(unit)->IsFlying();
|
||||
break;
|
||||
case TYPEID_UNIT:
|
||||
isFlying = static_cast<Creature*>(unit)->IsFlying();
|
||||
isSwimming = static_cast<Creature*>(unit)->IsSwimming();
|
||||
break;
|
||||
default:
|
||||
sLog.outError("Map::GetReachableRandomPosition> Unsupported unit type is passed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (radius < 0.1f)
|
||||
{
|
||||
sLog.outError("Map::GetReachableRandomPosition> Unsupported unit type is passed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isFlying)
|
||||
{
|
||||
newDestAssigned = GetRandomPointInTheAir(i_x, i_y, i_z, radius);
|
||||
/*if (newDestAssigned)
|
||||
sLog.outString("Generating air random point for %s", GetGuidStr().c_str());*/
|
||||
}
|
||||
else
|
||||
{
|
||||
GridMapLiquidData liquid_status;
|
||||
GridMapLiquidStatus res = m_TerrainData->getLiquidStatus(i_x, i_y, i_z, MAP_ALL_LIQUIDS, &liquid_status);
|
||||
if (isSwimming && (res & (LIQUID_MAP_UNDER_WATER | LIQUID_MAP_IN_WATER)))
|
||||
{
|
||||
newDestAssigned = GetRandomPointUnderWater(i_x, i_y, i_z, radius, liquid_status);
|
||||
/*if (newDestAssigned)
|
||||
sLog.outString("Generating swim random point for %s", GetGuidStr().c_str());*/
|
||||
}
|
||||
else
|
||||
{
|
||||
newDestAssigned = GetReachableRandomPointOnGround(i_x, i_y, i_z, radius);
|
||||
/*if (newDestAssigned)
|
||||
sLog.outString("Generating ground random point for %s", GetGuidStr().c_str());*/
|
||||
}
|
||||
}
|
||||
|
||||
if (newDestAssigned)
|
||||
{
|
||||
x = i_x;
|
||||
y = i_y;
|
||||
z = i_z;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -292,6 +292,11 @@ class Map : public GridRefManager<NGridType>
|
||||
*/
|
||||
void SetWeather(uint32 zoneId, WeatherType type, float grade, bool permanently);
|
||||
|
||||
// Random on map generation
|
||||
bool GetReachableRandomPosition(Unit* unit, float& x, float& y, float& z, float radius);
|
||||
bool GetReachableRandomPointOnGround(float& x, float& y, float& z, float radius);
|
||||
bool GetRandomPointInTheAir(float& x, float& y, float& z, float radius);
|
||||
bool GetRandomPointUnderWater(float& x, float& y, float& z, float radius, GridMapLiquidData& liquid_status);
|
||||
|
||||
private:
|
||||
void LoadMapAndVMap(int gx, int gy);
|
||||
|
Loading…
x
Reference in New Issue
Block a user