mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Handle different slopes in mmaps (#24765)
* Tools/MMAPs: Remove input argument --maxAngle
Remove input argument --maxAngle . This should be just hardcoded in MapBuilder::GetMapSpecificConfig() so all settings are easily found in the same place instead of being spread around.
* Tools/MMAPs: Add new area type NAV_AREA_GROUND_STEEP
Add new area type NAV_AREA_GROUND_STEEP for ground with slope in the range (55, 70] .
NAV_AREA_GROUND is used for ground with range [0, 55] .
NAV_AREA_GROUND_STEEP takes priority over NAV_AREA_GROUND.
* Tools/MMAPs: Fix NAV_GROUND_STEEP flag not being saved in the mmtile
* Core/PathFinding: Implement NAV_GROUND_STEEP flag
Implement NAV_GROUND_STEEP flag, used only by Creatures that are in combat or evading.
* Distinguish between RC_WALKABLE_AREA and NAV_AREA_GROUND.
* Allow mobs in combat to walk on steeps up to 80°
* Allow mobs in combat to walk on steeps up to 85°.
Disable rcFilterLedgeSpans() filter as it removed long steep spans.
* Increase cost of steep spans to try making creatures walk around obstacles instead of walking on them
* Revert last commit
(cherry picked from commit 995a443da2)
This commit is contained in:
@@ -224,6 +224,9 @@ struct rcConfig
|
||||
/// The maximum slope that is considered walkable. [Limits: 0 <= value < 90] [Units: Degrees]
|
||||
float walkableSlopeAngle;
|
||||
|
||||
/// The maximum slope that is considered walkable but not steep. It should be lower/equal than walkableSlopeAngle. [Limits: 0 <= value < 90] [Units: Degrees]
|
||||
float walkableSlopeAngleNotSteep;
|
||||
|
||||
/// Minimum floor to 'ceiling' height that will still allow the floor area to
|
||||
/// be considered walkable. [Limit: >= 3] [Units: vx]
|
||||
int walkableHeight;
|
||||
@@ -810,7 +813,7 @@ bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int heigh
|
||||
/// @param[in] nt The number of triangles.
|
||||
/// @param[out] areas The triangle area ids. [Length: >= @p nt]
|
||||
void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv,
|
||||
const int* tris, int nt, unsigned char* areas);
|
||||
const int* tris, int nt, unsigned char* areas, unsigned char areaType = RC_WALKABLE_AREA);
|
||||
|
||||
/// Sets the area id of all triangles with a slope greater than or equal to the specified value to #RC_NULL_AREA.
|
||||
/// @ingroup recast
|
||||
|
||||
@@ -334,7 +334,7 @@ static void calcTriNormal(const float* v0, const float* v1, const float* v2, flo
|
||||
void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle,
|
||||
const float* verts, int nv,
|
||||
const int* tris, int nt,
|
||||
unsigned char* areas)
|
||||
unsigned char* areas, unsigned char areaType)
|
||||
{
|
||||
rcIgnoreUnused(ctx);
|
||||
rcIgnoreUnused(nv);
|
||||
@@ -349,7 +349,7 @@ void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle,
|
||||
calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm);
|
||||
// Check if the face is walkable.
|
||||
if (norm[1] > walkableThr)
|
||||
areas[i] = RC_WALKABLE_AREA;
|
||||
areas[i] = areaType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,17 +51,22 @@ enum NavArea
|
||||
NAV_AREA_EMPTY = 0,
|
||||
// areas 1-60 will be used for destructible areas (currently skipped in vmaps, WMO with flag 1)
|
||||
// ground is the highest value to make recast choose ground over water when merging surfaces very close to each other (shallow water would be walkable)
|
||||
NAV_AREA_GROUND = 63,
|
||||
NAV_AREA_WATER = 62,
|
||||
NAV_AREA_MAGMA_SLIME = 61 // don't need to differentiate between them
|
||||
NAV_AREA_GROUND_STEEP = 11,
|
||||
NAV_AREA_GROUND = 10,
|
||||
NAV_AREA_WATER = 9,
|
||||
NAV_AREA_MAGMA_SLIME = 8, // don't need to differentiate between them
|
||||
NAV_AREA_MAX_VALUE = NAV_AREA_GROUND_STEEP,
|
||||
NAV_AREA_MIN_VALUE = NAV_AREA_MAGMA_SLIME,
|
||||
NAV_AREA_ALL_MASK = 0x3F // max allowed value
|
||||
};
|
||||
|
||||
enum NavTerrainFlag
|
||||
{
|
||||
NAV_EMPTY = 0x00,
|
||||
NAV_GROUND = 1 << (63 - NAV_AREA_GROUND),
|
||||
NAV_WATER = 1 << (63 - NAV_AREA_WATER),
|
||||
NAV_MAGMA_SLIME = 1 << (63 - NAV_AREA_MAGMA_SLIME)
|
||||
NAV_EMPTY = 0x00,
|
||||
NAV_GROUND_STEEP = 1 << (NAV_AREA_MAX_VALUE - NAV_AREA_GROUND_STEEP),
|
||||
NAV_GROUND = 1 << (NAV_AREA_MAX_VALUE - NAV_AREA_GROUND),
|
||||
NAV_WATER = 1 << (NAV_AREA_MAX_VALUE - NAV_AREA_WATER),
|
||||
NAV_MAGMA_SLIME = 1 << (NAV_AREA_MAX_VALUE - NAV_AREA_MAGMA_SLIME)
|
||||
};
|
||||
|
||||
#endif // MMapDefines_h__
|
||||
|
||||
@@ -679,6 +679,7 @@ void PathGenerator::UpdateFilter()
|
||||
// allow creatures to cheat and use different movement types if they are moved
|
||||
// forcefully into terrain they can't normally move in
|
||||
if (Unit const* _sourceUnit = _source->ToUnit())
|
||||
{
|
||||
if (_sourceUnit->IsInWater() || _sourceUnit->IsUnderWater())
|
||||
{
|
||||
uint16 includedFlags = _filter.getIncludeFlags();
|
||||
@@ -688,6 +689,11 @@ void PathGenerator::UpdateFilter()
|
||||
|
||||
_filter.setIncludeFlags(includedFlags);
|
||||
}
|
||||
|
||||
if (Creature const* _sourceCreature = _source->ToCreature())
|
||||
if (_sourceCreature->IsInCombat() || _sourceCreature->IsInEvadeMode())
|
||||
_filter.setIncludeFlags(_filter.getIncludeFlags() | NAV_GROUND_STEEP);
|
||||
}
|
||||
}
|
||||
|
||||
NavTerrainFlag PathGenerator::GetNavTerrain(float x, float y, float z)
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
namespace MMAP
|
||||
{
|
||||
MapBuilder::MapBuilder(float maxWalkableAngle, bool skipLiquid,
|
||||
MapBuilder::MapBuilder(bool skipLiquid,
|
||||
bool skipContinents, bool skipJunkMaps, bool skipBattlegrounds,
|
||||
bool debugOutput, bool bigBaseUnit, int mapid, char const* offMeshFilePath) :
|
||||
m_terrainBuilder (nullptr),
|
||||
@@ -40,7 +40,6 @@ namespace MMAP
|
||||
m_skipContinents (skipContinents),
|
||||
m_skipJunkMaps (skipJunkMaps),
|
||||
m_skipBattlegrounds (skipBattlegrounds),
|
||||
m_maxWalkableAngle (maxWalkableAngle),
|
||||
m_bigBaseUnit (bigBaseUnit),
|
||||
m_mapid (mapid),
|
||||
m_totalTiles (0u),
|
||||
@@ -588,16 +587,26 @@ namespace MMAP
|
||||
}
|
||||
|
||||
// mark all walkable tiles, both liquids and solids
|
||||
|
||||
/* we want to have triangles with slope less than walkableSlopeAngleNotSteep (<= 55) to have NAV_AREA_GROUND
|
||||
* and with slope between walkableSlopeAngleNotSteep and walkableSlopeAngle (55 < .. <= 70) to have NAV_AREA_GROUND_STEEP.
|
||||
* we achieve this using recast API: memset everything to NAV_AREA_GROUND_STEEP, call rcClearUnwalkableTriangles with 70 so
|
||||
* any area above that will get RC_NULL_AREA (unwalkable), then call rcMarkWalkableTriangles with 55 to set NAV_AREA_GROUND
|
||||
* on anything below 55 . Players and idle Creatures can use NAV_AREA_GROUND, while Creatures in combat can use NAV_AREA_GROUND_STEEP.
|
||||
*/
|
||||
unsigned char* triFlags = new unsigned char[tTriCount];
|
||||
memset(triFlags, NAV_AREA_GROUND, tTriCount*sizeof(unsigned char));
|
||||
memset(triFlags, NAV_AREA_GROUND_STEEP, tTriCount*sizeof(unsigned char));
|
||||
rcClearUnwalkableTriangles(m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags);
|
||||
rcMarkWalkableTriangles(m_rcContext, tileCfg.walkableSlopeAngleNotSteep, tVerts, tVertCount, tTris, tTriCount, triFlags, NAV_AREA_GROUND);
|
||||
rcRasterizeTriangles(m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.solid, config.walkableClimb);
|
||||
delete[] triFlags;
|
||||
|
||||
rcFilterLowHangingWalkableObstacles(m_rcContext, config.walkableClimb, *tile.solid);
|
||||
rcFilterLedgeSpans(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid);
|
||||
// disabled as it ignores walkableSlopeAngle settings
|
||||
//rcFilterLedgeSpans(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid);
|
||||
rcFilterWalkableLowHeightSpans(m_rcContext, tileCfg.walkableHeight, *tile.solid);
|
||||
|
||||
// add liquid triangles
|
||||
rcRasterizeTriangles(m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *tile.solid, config.walkableClimb);
|
||||
|
||||
// compact heightfield spans
|
||||
@@ -702,10 +711,10 @@ namespace MMAP
|
||||
// TODO: special flags for DYNAMIC polygons, ie surfaces that can be turned on and off
|
||||
for (int i = 0; i < iv.polyMesh->npolys; ++i)
|
||||
{
|
||||
if (uint8 area = iv.polyMesh->areas[i] & RC_WALKABLE_AREA)
|
||||
if (uint8 area = iv.polyMesh->areas[i] & NAV_AREA_ALL_MASK)
|
||||
{
|
||||
if (area >= NAV_AREA_MAGMA_SLIME)
|
||||
iv.polyMesh->flags[i] = 1 << (63 - area);
|
||||
if (area >= NAV_AREA_MIN_VALUE)
|
||||
iv.polyMesh->flags[i] = 1 << (NAV_AREA_MAX_VALUE - area);
|
||||
else
|
||||
iv.polyMesh->flags[i] = NAV_GROUND; // TODO: these will be dynamic in future
|
||||
}
|
||||
@@ -978,7 +987,8 @@ namespace MMAP
|
||||
config.maxVertsPerPoly = DT_VERTS_PER_POLYGON;
|
||||
config.cs = tileConfig.BASE_UNIT_DIM;
|
||||
config.ch = tileConfig.BASE_UNIT_DIM;
|
||||
config.walkableSlopeAngle = m_maxWalkableAngle;
|
||||
config.walkableSlopeAngle = 85;
|
||||
config.walkableSlopeAngleNotSteep = 55;
|
||||
config.tileSize = tileConfig.VERTEX_PER_TILE;
|
||||
config.walkableRadius = m_bigBaseUnit ? 1 : 2;
|
||||
config.borderSize = config.walkableRadius + 3;
|
||||
|
||||
@@ -96,8 +96,7 @@ namespace MMAP
|
||||
class MapBuilder
|
||||
{
|
||||
public:
|
||||
MapBuilder(float maxWalkableAngle = 70.f,
|
||||
bool skipLiquid = false,
|
||||
MapBuilder(bool skipLiquid = false,
|
||||
bool skipContinents = false,
|
||||
bool skipJunkMaps = true,
|
||||
bool skipBattlegrounds = false,
|
||||
@@ -164,7 +163,6 @@ namespace MMAP
|
||||
bool m_skipJunkMaps;
|
||||
bool m_skipBattlegrounds;
|
||||
|
||||
float m_maxWalkableAngle;
|
||||
bool m_bigBaseUnit;
|
||||
|
||||
int32 m_mapid;
|
||||
|
||||
@@ -99,7 +99,6 @@ bool handleArgs(int argc, char** argv,
|
||||
int &mapnum,
|
||||
int &tileX,
|
||||
int &tileY,
|
||||
float &maxAngle,
|
||||
bool &skipLiquid,
|
||||
bool &skipContinents,
|
||||
bool &skipJunkMaps,
|
||||
@@ -114,19 +113,7 @@ bool handleArgs(int argc, char** argv,
|
||||
char* param = nullptr;
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
if (strcmp(argv[i], "--maxAngle") == 0)
|
||||
{
|
||||
param = argv[++i];
|
||||
if (!param)
|
||||
return false;
|
||||
|
||||
float maxangle = atof(param);
|
||||
if (maxangle <= 90.f && maxangle >= 45.f)
|
||||
maxAngle = maxangle;
|
||||
else
|
||||
printf("invalid option for '--maxAngle', using default\n");
|
||||
}
|
||||
else if (strcmp(argv[i], "--threads") == 0)
|
||||
if (strcmp(argv[i], "--threads") == 0)
|
||||
{
|
||||
param = argv[++i];
|
||||
if (!param)
|
||||
@@ -353,7 +340,6 @@ int main(int argc, char** argv)
|
||||
|
||||
unsigned int threads = std::thread::hardware_concurrency();
|
||||
int mapnum = -1;
|
||||
float maxAngle = 70.0f;
|
||||
int tileX = -1, tileY = -1;
|
||||
bool skipLiquid = false,
|
||||
skipContinents = false,
|
||||
@@ -366,7 +352,7 @@ int main(int argc, char** argv)
|
||||
char* file = nullptr;
|
||||
|
||||
bool validParam = handleArgs(argc, argv, mapnum,
|
||||
tileX, tileY, maxAngle,
|
||||
tileX, tileY,
|
||||
skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds,
|
||||
debugOutput, silent, bigBaseUnit, offMeshInputPath, file, threads);
|
||||
|
||||
@@ -400,7 +386,7 @@ int main(int argc, char** argv)
|
||||
return itr != _liquidTypes.end() ? (1 << itr->second) : 0;
|
||||
};
|
||||
|
||||
MapBuilder builder(maxAngle, skipLiquid, skipContinents, skipJunkMaps,
|
||||
MapBuilder builder(skipLiquid, skipContinents, skipJunkMaps,
|
||||
skipBattlegrounds, debugOutput, bigBaseUnit, mapnum, offMeshInputPath);
|
||||
|
||||
uint32 start = getMSTime();
|
||||
|
||||
Reference in New Issue
Block a user