diff options
author | Giacomo Pozzoni <giacomopoz@gmail.com> | 2020-06-17 20:20:26 +0000 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-01-04 20:44:02 +0100 |
commit | d58d0e895c6e22bcf40be5c38ff828c98a7600e6 (patch) | |
tree | 5c628e1a49f9884934d24ab884896cfaa9f18471 | |
parent | bafd22104cd7b12056e2ea3060ddc778375ae60c (diff) |
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 995a443da219ec773febd7dd29d18f3cefaa1f3b)
-rw-r--r-- | dep/recastnavigation/Recast/Include/Recast.h | 5 | ||||
-rw-r--r-- | dep/recastnavigation/Recast/Source/Recast.cpp | 4 | ||||
-rw-r--r-- | src/common/Collision/Maps/MMapDefines.h | 19 | ||||
-rw-r--r-- | src/server/game/Movement/PathGenerator.cpp | 6 | ||||
-rw-r--r-- | src/tools/mmaps_generator/MapBuilder.cpp | 26 | ||||
-rw-r--r-- | src/tools/mmaps_generator/MapBuilder.h | 4 | ||||
-rw-r--r-- | src/tools/mmaps_generator/PathGenerator.cpp | 20 |
7 files changed, 46 insertions, 38 deletions
diff --git a/dep/recastnavigation/Recast/Include/Recast.h b/dep/recastnavigation/Recast/Include/Recast.h index fa25a98bd2a..19c26e20c4a 100644 --- a/dep/recastnavigation/Recast/Include/Recast.h +++ b/dep/recastnavigation/Recast/Include/Recast.h @@ -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 diff --git a/dep/recastnavigation/Recast/Source/Recast.cpp b/dep/recastnavigation/Recast/Source/Recast.cpp index 1b71710cdc8..a33ca5cf2fc 100644 --- a/dep/recastnavigation/Recast/Source/Recast.cpp +++ b/dep/recastnavigation/Recast/Source/Recast.cpp @@ -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; } } diff --git a/src/common/Collision/Maps/MMapDefines.h b/src/common/Collision/Maps/MMapDefines.h index e12c8cac49e..6298775ba6f 100644 --- a/src/common/Collision/Maps/MMapDefines.h +++ b/src/common/Collision/Maps/MMapDefines.h @@ -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__ diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 0effe2a5d87..a4b15baadb3 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -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) diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 6e3adc79a04..1b83daf1c1c 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -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; diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h index f2fd5d296d7..312d3c07786 100644 --- a/src/tools/mmaps_generator/MapBuilder.h +++ b/src/tools/mmaps_generator/MapBuilder.h @@ -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; diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp index 9625b1d7f1f..2e9f3913edf 100644 --- a/src/tools/mmaps_generator/PathGenerator.cpp +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -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(); |