diff options
-rw-r--r-- | deps/recastnavigation/Recast/Include/Recast.h | 175 | ||||
-rw-r--r-- | deps/recastnavigation/Recast/Source/Recast.cpp | 60 | ||||
-rw-r--r-- | src/common/Collision/Maps/MapDefines.h | 31 | ||||
-rw-r--r-- | src/server/game/Movement/MovementGenerators/PathGenerator.cpp | 20 | ||||
-rw-r--r-- | src/server/game/Movement/MovementGenerators/PathGenerator.h | 2 | ||||
-rw-r--r-- | src/tools/mmaps_generator/MapBuilder.cpp | 38 | ||||
-rw-r--r-- | src/tools/mmaps_generator/MapBuilder.h | 7 | ||||
-rw-r--r-- | src/tools/mmaps_generator/PathCommon.h | 2 | ||||
-rw-r--r-- | src/tools/mmaps_generator/PathGenerator.cpp | 61 | ||||
-rw-r--r-- | src/tools/mmaps_generator/TerrainBuilder.cpp | 60 |
10 files changed, 274 insertions, 182 deletions
diff --git a/deps/recastnavigation/Recast/Include/Recast.h b/deps/recastnavigation/Recast/Include/Recast.h index fa25a98bd2..2c0c72a83c 100644 --- a/deps/recastnavigation/Recast/Include/Recast.h +++ b/deps/recastnavigation/Recast/Include/Recast.h @@ -15,7 +15,7 @@ // misrepresented as being the original software. // 3. This notice may not be removed or altered from any source distribution. // - + #ifndef RECAST_H #define RECAST_H @@ -86,7 +86,7 @@ enum rcTimerLabel /// The time to filter out small regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone) RC_TIMER_BUILD_REGIONS_FILTER, /// The time to build heightfield layers. (See: #rcBuildHeightfieldLayers) - RC_TIMER_BUILD_LAYERS, + RC_TIMER_BUILD_LAYERS, /// The time to build the polygon mesh detail. (See: #rcBuildPolyMeshDetail) RC_TIMER_BUILD_POLYMESHDETAIL, /// The time to merge polygon mesh details. (See: #rcMergePolyMeshDetails) @@ -95,7 +95,7 @@ enum rcTimerLabel RC_MAX_TIMERS }; -/// Provides an interface for optional logging and performance tracking of the Recast +/// Provides an interface for optional logging and performance tracking of the Recast /// build process. /// @ingroup recast class rcContext @@ -165,7 +165,7 @@ protected: /// @param[in] label The category of the timer. /// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started. virtual int doGetAccumulatedTime(const rcTimerLabel /*label*/) const { return -1; } - + /// True if logging is enabled. bool m_logEnabled; @@ -188,7 +188,7 @@ private: // Explicitly disabled copy constructor and copy assignment operator. rcScopedTimer(const rcScopedTimer&); rcScopedTimer& operator=(const rcScopedTimer&); - + rcContext* const m_ctx; const rcTimerLabel m_label; }; @@ -202,63 +202,66 @@ struct rcConfig /// The height of the field along the z-axis. [Limit: >= 0] [Units: vx] int height; - + /// The width/height size of tile's on the xz-plane. [Limit: >= 0] [Units: vx] int tileSize; - + /// The size of the non-navigable border around the heightfield. [Limit: >=0] [Units: vx] int borderSize; - /// The xz-plane cell size to use for fields. [Limit: > 0] [Units: wu] + /// The xz-plane cell size to use for fields. [Limit: > 0] [Units: wu] float cs; /// The y-axis cell size to use for fields. [Limit: > 0] [Units: wu] float ch; /// The minimum bounds of the field's AABB. [(x, y, z)] [Units: wu] - float bmin[3]; + float bmin[3]; /// The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu] float bmax[3]; - /// The maximum slope that is considered walkable. [Limits: 0 <= value < 90] [Units: Degrees] + /// The maximum slope that is considered walkable. [Limits: 0 <= value < 90] [Units: Degrees] float walkableSlopeAngle; - /// Minimum floor to 'ceiling' height that will still allow the floor area to - /// be considered walkable. [Limit: >= 3] [Units: vx] + /// 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; - - /// Maximum ledge height that is considered to still be traversable. [Limit: >=0] [Units: vx] + + /// Maximum ledge height that is considered to still be traversable. [Limit: >=0] [Units: vx] int walkableClimb; - - /// The distance to erode/shrink the walkable area of the heightfield away from - /// obstructions. [Limit: >=0] [Units: vx] + + /// The distance to erode/shrink the walkable area of the heightfield away from + /// obstructions. [Limit: >=0] [Units: vx] int walkableRadius; - - /// The maximum allowed length for contour edges along the border of the mesh. [Limit: >=0] [Units: vx] + + /// The maximum allowed length for contour edges along the border of the mesh. [Limit: >=0] [Units: vx] int maxEdgeLen; - - /// The maximum distance a simplfied contour's border edges should deviate + + /// The maximum distance a simplfied contour's border edges should deviate /// the original raw contour. [Limit: >=0] [Units: vx] float maxSimplificationError; - - /// The minimum number of cells allowed to form isolated island areas. [Limit: >=0] [Units: vx] + + /// The minimum number of cells allowed to form isolated island areas. [Limit: >=0] [Units: vx] int minRegionArea; - - /// Any regions with a span count smaller than this value will, if possible, - /// be merged with larger regions. [Limit: >=0] [Units: vx] + + /// Any regions with a span count smaller than this value will, if possible, + /// be merged with larger regions. [Limit: >=0] [Units: vx] int mergeRegionArea; - - /// The maximum number of vertices allowed for polygons generated during the - /// contour to polygon conversion process. [Limit: >= 3] + + /// The maximum number of vertices allowed for polygons generated during the + /// contour to polygon conversion process. [Limit: >= 3] int maxVertsPerPoly; - + /// Sets the sampling distance to use when generating the detail mesh. - /// (For height detail only.) [Limits: 0 or >= 0.9] [Units: wu] + /// (For height detail only.) [Limits: 0 or >= 0.9] [Units: wu] float detailSampleDist; - + /// The maximum distance the detail mesh surface should deviate from heightfield - /// data. (For height detail only.) [Limit: >=0] [Units: wu] + /// data. (For height detail only.) [Limit: >=0] [Units: wu] float detailSampleMaxError; }; @@ -312,7 +315,7 @@ private: rcHeightfield& operator=(const rcHeightfield&); }; -/// Provides information on the content of a cell column in a compact heightfield. +/// Provides information on the content of a cell column in a compact heightfield. struct rcCompactCell { unsigned int index : 24; ///< Index to the first span in the column. @@ -340,8 +343,8 @@ struct rcCompactHeightfield int walkableHeight; ///< The walkable height used during the build of the field. (See: rcConfig::walkableHeight) int walkableClimb; ///< The walkable climb used during the build of the field. (See: rcConfig::walkableClimb) int borderSize; ///< The AABB border size used during the build of the field. (See: rcConfig::borderSize) - unsigned short maxDistance; ///< The maximum distance value of any span within the field. - unsigned short maxRegions; ///< The maximum region id of any span within the field. + unsigned short maxDistance; ///< The maximum distance value of any span within the field. + unsigned short maxRegions; ///< The maximum region id of any span within the field. float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)] float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)] float cs; ///< The size of each cell. (On the xz-plane.) @@ -375,7 +378,7 @@ struct rcHeightfieldLayer /// Represents a set of heightfield layers. /// @ingroup recast -/// @see rcAllocHeightfieldLayerSet, rcFreeHeightfieldLayerSet +/// @see rcAllocHeightfieldLayerSet, rcFreeHeightfieldLayerSet struct rcHeightfieldLayerSet { rcHeightfieldLayerSet(); @@ -388,9 +391,9 @@ struct rcHeightfieldLayerSet struct rcContour { int* verts; ///< Simplified contour vertex and connection data. [Size: 4 * #nverts] - int nverts; ///< The number of vertices in the simplified contour. + int nverts; ///< The number of vertices in the simplified contour. int* rverts; ///< Raw contour vertex and connection data. [Size: 4 * #nrverts] - int nrverts; ///< The number of vertices in the raw contour. + int nrverts; ///< The number of vertices in the raw contour. unsigned short reg; ///< The region id of the contour. unsigned char area; ///< The area id of the contour. }; @@ -407,13 +410,13 @@ struct rcContourSet float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)] float cs; ///< The size of each cell. (On the xz-plane.) float ch; ///< The height of each cell. (The minimum increment along the y-axis.) - int width; ///< The width of the set. (Along the x-axis in cell units.) - int height; ///< The height of the set. (Along the z-axis in cell units.) + int width; ///< The width of the set. (Along the x-axis in cell units.) + int height; ///< The height of the set. (Along the z-axis in cell units.) int borderSize; ///< The AABB border size used to generate the source data from which the contours were derived. float maxError; ///< The max edge error that this contour set was simplified with. }; -/// Represents a polygon mesh suitable for use in building a navigation mesh. +/// Represents a polygon mesh suitable for use in building a navigation mesh. /// @ingroup recast struct rcPolyMesh { @@ -436,14 +439,14 @@ struct rcPolyMesh float maxEdgeError; ///< The max error of the polygon edges in the mesh. }; -/// Contains triangle meshes that represent detailed height data associated +/// Contains triangle meshes that represent detailed height data associated /// with the polygons in its associated polygon mesh object. /// @ingroup recast struct rcPolyMeshDetail { - unsigned int* meshes; ///< The sub-mesh data. [Size: 4*#nmeshes] - float* verts; ///< The mesh vertices. [Size: 3*#nverts] - unsigned char* tris; ///< The mesh triangles. [Size: 4*#ntris] + unsigned int* meshes; ///< The sub-mesh data. [Size: 4*#nmeshes] + float* verts; ///< The mesh vertices. [Size: 3*#nverts] + unsigned char* tris; ///< The mesh triangles. [Size: 4*#ntris] int nmeshes; ///< The number of sub-meshes defined by #meshes. int nverts; ///< The number of vertices in #verts. int ntris; ///< The number of triangles in #tris. @@ -529,7 +532,7 @@ void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh); /// @} /// Heighfield border flag. -/// If a heightfield region ID has this bit set, then the region is a border +/// If a heightfield region ID has this bit set, then the region is a border /// region and its spans are considered unwalkable. /// (Used during the region and contour build process.) /// @see rcCompactSpan::reg @@ -538,15 +541,15 @@ static const unsigned short RC_BORDER_REG = 0x8000; /// Polygon touches multiple regions. /// If a polygon has this region ID it was merged with or created /// from polygons of different regions during the polymesh -/// build step that removes redundant border vertices. +/// build step that removes redundant border vertices. /// (Used during the polymesh and detail polymesh build processes) /// @see rcPolyMesh::regs static const unsigned short RC_MULTIPLE_REGS = 0; /// Border vertex flag. /// If a region ID has this bit set, then the associated element lies on -/// a tile border. If a contour vertex's region ID has this bit set, the -/// vertex will later be removed in order to match the segments and vertices +/// a tile border. If a contour vertex's region ID has this bit set, the +/// vertex will later be removed in order to match the segments and vertices /// at tile boundaries. /// (Used during the build process.) /// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts @@ -579,13 +582,13 @@ static const int RC_CONTOUR_REG_MASK = 0xffff; static const unsigned short RC_MESH_NULL_IDX = 0xffff; /// Represents the null area. -/// When a data element is given this value it is considered to no longer be +/// When a data element is given this value it is considered to no longer be /// assigned to a usable area. (E.g. It is unwalkable.) static const unsigned char RC_NULL_AREA = 0; -/// The default area id used to indicate a walkable polygon. -/// This is also the maximum allowed area id, and the only non-null area id -/// recognized by some steps in the build process. +/// The default area id used to indicate a walkable polygon. +/// This is also the maximum allowed area id, and the only non-null area id +/// recognized by some steps in the build process. static const unsigned char RC_WALKABLE_AREA = 63; /// The value returned by #rcGetCon if the specified direction is not connected @@ -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 @@ -823,7 +826,7 @@ void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, con /// @param[in] nt The number of triangles. /// @param[out] areas The triangle area ids. [Length: >= @p nt] void rcClearUnwalkableTriangles(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); /// Adds a span to the specified heightfield. /// @ingroup recast @@ -866,7 +869,7 @@ bool rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const /// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt] /// @param[in] nt The number of triangles. /// @param[in,out] solid An initialized heightfield. -/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. +/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. /// [Limit: >= 0] [Units: vx] /// @returns True if the operation completed successfully. bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, @@ -882,7 +885,7 @@ bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, /// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt] /// @param[in] nt The number of triangles. /// @param[in,out] solid An initialized heightfield. -/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. +/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. /// [Limit: >= 0] [Units: vx] /// @returns True if the operation completed successfully. bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, @@ -896,35 +899,35 @@ bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, /// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt] /// @param[in] nt The number of triangles. /// @param[in,out] solid An initialized heightfield. -/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. +/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. /// [Limit: >= 0] [Units: vx] /// @returns True if the operation completed successfully. bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt, rcHeightfield& solid, const int flagMergeThr = 1); -/// Marks non-walkable spans as walkable if their maximum is within @p walkableClimp of a walkable neighbor. +/// Marks non-walkable spans as walkable if their maximum is within @p walkableClimp of a walkable neighbor. /// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. -/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable. +/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable. /// [Limit: >=0] [Units: vx] /// @param[in,out] solid A fully built heightfield. (All spans have been added.) void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid); -/// Marks spans that are ledges as not-walkable. +/// Marks spans that are ledges as not-walkable. /// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. -/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area to +/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area to /// be considered walkable. [Limit: >= 3] [Units: vx] -/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable. +/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable. /// [Limit: >=0] [Units: vx] /// @param[in,out] solid A fully built heightfield. (All spans have been added.) void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walkableClimb, rcHeightfield& solid); -/// Marks walkable spans as not walkable if the clearence above the span is less than the specified height. +/// Marks walkable spans as not walkable if the clearence above the span is less than the specified height. /// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. -/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area to +/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area to /// be considered walkable. [Limit: >= 3] [Units: vx] /// @param[in,out] solid A fully built heightfield. (All spans have been added.) void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid); @@ -944,9 +947,9 @@ int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf); /// Builds a compact heightfield representing open space, from a heightfield representing solid space. /// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. -/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area +/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area /// to be considered walkable. [Limit: >= 3] [Units: vx] -/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable. +/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable. /// [Limit: >=0] [Units: vx] /// @param[in] hf The heightfield to be compacted. /// @param[out] chf The resulting compact heightfield. (Must be pre-allocated.) @@ -954,7 +957,7 @@ int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf); bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb, rcHeightfield& hf, rcCompactHeightfield& chf); -/// Erodes the walkable area within the heightfield by the specified radius. +/// Erodes the walkable area within the heightfield by the specified radius. /// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. /// @param[in] radius The radius of erosion. [Limits: 0 < value < 255] [Units: vx] @@ -969,7 +972,7 @@ bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf); /// @returns True if the operation completed successfully. bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf); -/// Applies an area id to all spans within the specified bounding box. (AABB) +/// Applies an area id to all spans within the specified bounding box. (AABB) /// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. /// @param[in] bmin The minimum of the bounding box. [(x, y, z)] @@ -979,7 +982,7 @@ bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf); void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId, rcCompactHeightfield& chf); -/// Applies the area id to the all spans within the specified convex polygon. +/// Applies the area id to the all spans within the specified convex polygon. /// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. /// @param[in] verts The vertices of the polygon [Fomr: (x, y, z) * @p nverts] @@ -1005,7 +1008,7 @@ int rcOffsetPoly(const float* verts, const int nverts, const float offset, /// Applies the area id to all spans within the specified cylinder. /// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. -/// @param[in] pos The center of the base of the cylinder. [Form: (x, y, z)] +/// @param[in] pos The center of the base of the cylinder. [Form: (x, y, z)] /// @param[in] r The radius of the cylinder. /// @param[in] h The height of the cylinder. /// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA] @@ -1014,7 +1017,7 @@ void rcMarkCylinderArea(rcContext* ctx, const float* pos, const float r, const float h, unsigned char areaId, rcCompactHeightfield& chf); -/// Builds the distance field for the specified compact heightfield. +/// Builds the distance field for the specified compact heightfield. /// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. /// @param[in,out] chf A populated compact heightfield. @@ -1030,7 +1033,7 @@ bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf); /// @param[in] minRegionArea The minimum number of cells allowed to form isolated island areas. /// [Limit: >=0] [Units: vx]. /// @param[in] mergeRegionArea Any regions with a span count smaller than this value will, if possible, -/// be merged with larger regions. [Limit: >=0] [Units: vx] +/// be merged with larger regions. [Limit: >=0] [Units: vx] /// @returns True if the operation completed successfully. bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionArea, const int mergeRegionArea); @@ -1048,15 +1051,15 @@ bool rcBuildLayerRegions(rcContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionArea); /// Builds region data for the heightfield using simple monotone partitioning. -/// @ingroup recast +/// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. /// @param[in,out] chf A populated compact heightfield. /// @param[in] borderSize The size of the non-navigable border around the heightfield. /// [Limit: >=0] [Units: vx] /// @param[in] minRegionArea The minimum number of cells allowed to form isolated island areas. /// [Limit: >=0] [Units: vx]. -/// @param[in] mergeRegionArea Any regions with a span count smaller than this value will, if possible, -/// be merged with larger regions. [Limit: >=0] [Units: vx] +/// @param[in] mergeRegionArea Any regions with a span count smaller than this value will, if possible, +/// be merged with larger regions. [Limit: >=0] [Units: vx] /// @returns True if the operation completed successfully. bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionArea, const int mergeRegionArea); @@ -1122,13 +1125,13 @@ inline int rcGetDirForOffset(int x, int y) /// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. /// @param[in] chf A fully built compact heightfield. -/// @param[in] borderSize The size of the non-navigable border around the heightfield. [Limit: >=0] +/// @param[in] borderSize The size of the non-navigable border around the heightfield. [Limit: >=0] /// [Units: vx] -/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area +/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area /// to be considered walkable. [Limit: >= 3] [Units: vx] /// @param[out] lset The resulting layer set. (Must be pre-allocated.) /// @returns True if the operation completed successfully. -bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf, +bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int walkableHeight, rcHeightfieldLayerSet& lset); @@ -1136,9 +1139,9 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf, /// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. /// @param[in] chf A fully built compact heightfield. -/// @param[in] maxError The maximum distance a simplfied contour's border edges should deviate +/// @param[in] maxError The maximum distance a simplfied contour's border edges should deviate /// the original raw contour. [Limit: >=0] [Units: wu] -/// @param[in] maxEdgeLen The maximum allowed length for contour edges along the border of the mesh. +/// @param[in] maxEdgeLen The maximum allowed length for contour edges along the border of the mesh. /// [Limit: >=0] [Units: vx] /// @param[out] cset The resulting contour set. (Must be pre-allocated.) /// @param[in] buildFlags The build flags. (See: #rcBuildContoursFlags) @@ -1151,8 +1154,8 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, /// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. /// @param[in] cset A fully built contour set. -/// @param[in] nvp The maximum number of vertices allowed for polygons generated during the -/// contour to polygon conversion process. [Limit: >= 3] +/// @param[in] nvp The maximum number of vertices allowed for polygons generated during the +/// contour to polygon conversion process. [Limit: >= 3] /// @param[out] mesh The resulting polygon mesh. (Must be re-allocated.) /// @returns True if the operation completed successfully. bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh); @@ -1172,7 +1175,7 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r /// @param[in] mesh A fully built polygon mesh. /// @param[in] chf The compact heightfield used to build the polygon mesh. /// @param[in] sampleDist Sets the distance to use when samping the heightfield. [Limit: >=0] [Units: wu] -/// @param[in] sampleMaxError The maximum distance the detail mesh surface should deviate from +/// @param[in] sampleMaxError The maximum distance the detail mesh surface should deviate from /// heightfield data. [Limit: >=0] [Units: wu] /// @param[out] dmesh The resulting detail mesh. (Must be pre-allocated.) /// @returns True if the operation completed successfully. @@ -1203,6 +1206,6 @@ bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int /////////////////////////////////////////////////////////////////////////// -// Due to the large amount of detail documentation for this file, +// Due to the large amount of detail documentation for this file, // the content normally located at the end of the header file has been separated // out to a file in /Docs/Extern. diff --git a/deps/recastnavigation/Recast/Source/Recast.cpp b/deps/recastnavigation/Recast/Source/Recast.cpp index 1b71710cdc..584b76a068 100644 --- a/deps/recastnavigation/Recast/Source/Recast.cpp +++ b/deps/recastnavigation/Recast/Source/Recast.cpp @@ -59,13 +59,13 @@ float rcSqrt(float x) /// @class rcContext /// @par /// -/// This class does not provide logging or timer functionality on its -/// own. Both must be provided by a concrete implementation -/// by overriding the protected member functions. Also, this class does not -/// provide an interface for extracting log messages. (Only adding them.) +/// This class does not provide logging or timer functionality on its +/// own. Both must be provided by a concrete implementation +/// by overriding the protected member functions. Also, this class does not +/// provide an interface for extracting log messages. (Only adding them.) /// So concrete implementations must provide one. /// -/// If no logging or timers are required, just pass an instance of this +/// If no logging or timers are required, just pass an instance of this /// class through the Recast build process. /// @@ -293,14 +293,14 @@ void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* /// @par /// /// See the #rcConfig documentation for more information on the configuration parameters. -/// -/// @see rcAllocHeightfield, rcHeightfield +/// +/// @see rcAllocHeightfield, rcHeightfield bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int height, const float* bmin, const float* bmax, float cs, float ch) { rcIgnoreUnused(ctx); - + hf.width = width; hf.height = height; rcVcopy(hf.bmin, bmin); @@ -327,29 +327,29 @@ static void calcTriNormal(const float* v0, const float* v1, const float* v2, flo /// /// Only sets the area id's for the walkable triangles. Does not alter the /// area id's for unwalkable triangles. -/// +/// /// See the #rcConfig documentation for more information on the configuration parameters. -/// +/// /// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles 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); - + const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI); float norm[3]; - + for (int i = 0; i < nt; ++i) { const int* tri = &tris[i*3]; 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; } } @@ -357,9 +357,9 @@ void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, /// /// Only sets the area id's for the unwalkable triangles. Does not alter the /// area id's for walkable triangles. -/// +/// /// See the #rcConfig documentation for more information on the configuration parameters. -/// +/// /// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int /*nv*/, @@ -367,11 +367,11 @@ void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, unsigned char* areas) { rcIgnoreUnused(ctx); - + const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI); - + float norm[3]; - + for (int i = 0; i < nt; ++i) { const int* tri = &tris[i*3]; @@ -385,7 +385,7 @@ void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf) { rcIgnoreUnused(ctx); - + const int w = hf.width; const int h = hf.height; int spanCount = 0; @@ -416,9 +416,9 @@ bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const i rcHeightfield& hf, rcCompactHeightfield& chf) { rcAssert(ctx); - + rcScopedTimer timer(ctx, RC_TIMER_BUILD_COMPACTHEIGHTFIELD); - + const int w = hf.width; const int h = hf.height; const int spanCount = rcGetHeightFieldSpanCount(ctx, hf); @@ -456,9 +456,9 @@ bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const i return false; } memset(chf.areas, RC_NULL_AREA, sizeof(unsigned char)*spanCount); - + const int MAX_HEIGHT = 0xffff; - + // Fill in cells and spans. int idx = 0; for (int y = 0; y < h; ++y) @@ -499,7 +499,7 @@ bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const i for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) { rcCompactSpan& s = chf.spans[i]; - + for (int dir = 0; dir < 4; ++dir) { rcSetCon(s, dir, RC_NOT_CONNECTED); @@ -508,7 +508,7 @@ bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const i // First check that the neighbour cell is in bounds. if (nx < 0 || ny < 0 || nx >= w || ny >= h) continue; - + // Iterate over all neighbour spans and check if any of the is // accessible from current cell. const rcCompactCell& nc = chf.cells[nx+ny*w]; @@ -533,18 +533,18 @@ bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const i break; } } - + } } } } - + if (tooHighNeighbour > MAX_LAYERS) { ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Heightfield has too many layers %d (max: %d)", tooHighNeighbour, MAX_LAYERS); } - + return true; } @@ -554,7 +554,7 @@ static int getHeightfieldMemoryUsage(const rcHeightfield& hf) int size = 0; size += sizeof(hf); size += hf.width * hf.height * sizeof(rcSpan*); - + rcSpanPool* pool = hf.pools; while (pool) { diff --git a/src/common/Collision/Maps/MapDefines.h b/src/common/Collision/Maps/MapDefines.h index 743321377d..203d62a55c 100644 --- a/src/common/Collision/Maps/MapDefines.h +++ b/src/common/Collision/Maps/MapDefines.h @@ -36,18 +36,27 @@ static_assert(sizeof(MmapTileHeader) == (sizeof(MmapTileHeader::mmapMagic) + sizeof(MmapTileHeader::usesLiquids) + sizeof(MmapTileHeader::padding)), "MmapTileHeader has uninitialized padding fields"); -enum NavTerrain +enum NavArea { - NAV_EMPTY = 0x00, - NAV_GROUND = 0x01, - NAV_MAGMA = 0x02, - NAV_SLIME = 0x04, - NAV_WATER = 0x08, - NAV_UNUSED1 = 0x10, - NAV_UNUSED2 = 0x20, - NAV_UNUSED3 = 0x40, - NAV_UNUSED4 = 0x80 - // we only have 8 bits + 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_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_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 diff --git a/src/server/game/Movement/MovementGenerators/PathGenerator.cpp b/src/server/game/Movement/MovementGenerators/PathGenerator.cpp index b07a0c9e41..b9b615983e 100644 --- a/src/server/game/Movement/MovementGenerators/PathGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PathGenerator.cpp @@ -641,12 +641,12 @@ void PathGenerator::CreateFilter() // creatures don't take environmental damage if (creature->CanEnterWater()) - includeFlags |= (NAV_WATER | NAV_MAGMA); + includeFlags |= (NAV_WATER | NAV_MAGMA_SLIME); } else // assume Player { // perfect support not possible, just stay 'safe' - includeFlags |= (NAV_GROUND | NAV_WATER | NAV_MAGMA); + includeFlags |= (NAV_GROUND | NAV_WATER | NAV_MAGMA_SLIME); } _filter.setIncludeFlags(includeFlags); @@ -671,13 +671,17 @@ void PathGenerator::UpdateFilter() _filter.setIncludeFlags(includedFlags); } - /*if (Creature const* _sourceCreature = _source->ToCreature()) + if (Creature const* _sourceCreature = _source->ToCreature()) + { if (_sourceCreature->IsInCombat() || _sourceCreature->IsInEvadeMode()) - _filter.setIncludeFlags(_filter.getIncludeFlags() | NAV_GROUND_STEEP);*/ + { + _filter.setIncludeFlags(_filter.getIncludeFlags() | NAV_GROUND_STEEP); + } + } } } -NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) const +NavTerrainFlag PathGenerator::GetNavTerrain(float x, float y, float z) const { LiquidData data; LiquidData const& liquidData = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), x, y, z, _source->GetCollisionHeight(), MAP_ALL_LIQUIDS); @@ -691,7 +695,7 @@ NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) const return NAV_WATER; case MAP_LIQUID_TYPE_MAGMA: case MAP_LIQUID_TYPE_SLIME: - return NAV_MAGMA; + return NAV_MAGMA_SLIME; default: return NAV_GROUND; } @@ -1139,9 +1143,9 @@ bool PathGenerator::IsWaterPath(Movement::PointsArray pathPoints) const // Check both start and end points, if they're both in water, then we can *safely* let the creature move for (uint32 i = 0; i < pathPoints.size(); ++i) { - NavTerrain terrain = GetNavTerrain(pathPoints[i].x, pathPoints[i].y, pathPoints[i].z); + NavTerrainFlag terrain = GetNavTerrain(pathPoints[i].x, pathPoints[i].y, pathPoints[i].z); // One of the points is not in the water - if (terrain != NAV_MAGMA && terrain != NAV_WATER) + if (terrain != NAV_MAGMA_SLIME && terrain != NAV_WATER) { waterPath = false; break; diff --git a/src/server/game/Movement/MovementGenerators/PathGenerator.h b/src/server/game/Movement/MovementGenerators/PathGenerator.h index 92f82c283c..8744bdf592 100644 --- a/src/server/game/Movement/MovementGenerators/PathGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PathGenerator.h @@ -168,7 +168,7 @@ class PathGenerator void BuildPointPath(float const* startPoint, float const* endPoint); void BuildShortcut(); - [[nodiscard]] NavTerrain GetNavTerrain(float x, float y, float z) const; + [[nodiscard]] NavTerrainFlag GetNavTerrain(float x, float y, float z) const; void CreateFilter(); void UpdateFilter(); diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 089e81970c..dcf7f05c50 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -26,7 +26,7 @@ namespace MMAP { - MapBuilder::MapBuilder(float maxWalkableAngle, bool skipLiquid, + MapBuilder::MapBuilder(Optional<float> maxWalkableAngle, Optional<float> maxWalkableAngleNotSteep, bool skipLiquid, bool skipContinents, bool skipJunkMaps, bool skipBattlegrounds, bool debugOutput, bool bigBaseUnit, int mapid, const char* offMeshFilePath) : @@ -36,6 +36,7 @@ namespace MMAP m_skipJunkMaps (skipJunkMaps), m_skipBattlegrounds (skipBattlegrounds), m_maxWalkableAngle (maxWalkableAngle), + m_maxWalkableAngleNotSteep (maxWalkableAngleNotSteep), m_bigBaseUnit (bigBaseUnit), m_mapid (mapid), m_totalTiles (0u), @@ -587,9 +588,17 @@ 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_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; @@ -597,6 +606,7 @@ namespace MMAP 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 @@ -694,8 +704,15 @@ namespace MMAP // set polygons as walkable // 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 (iv.polyMesh->areas[i] & RC_WALKABLE_AREA) - iv.polyMesh->flags[i] = iv.polyMesh->areas[i]; + { + if (uint8 area = iv.polyMesh->areas[i] & NAV_AREA_ALL_MASK) + { + 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 + } + } // setup mesh parameters dtNavMeshCreateParams params; @@ -984,7 +1001,10 @@ namespace MMAP config.maxVertsPerPoly = DT_VERTS_PER_POLYGON; config.cs = tileConfig.BASE_UNIT_DIM; config.ch = tileConfig.BASE_UNIT_DIM; - config.walkableSlopeAngle = m_maxWalkableAngle; + // Keeping these 2 slope angles the same reduces a lot the number of polys. + // 55 should be the minimum, maybe 70 is ok (keep in mind blink uses mmaps), 85 is too much for players + config.walkableSlopeAngle = m_maxWalkableAngle ? *m_maxWalkableAngle : 55; + config.walkableSlopeAngleNotSteep = m_maxWalkableAngleNotSteep ? *m_maxWalkableAngleNotSteep : 55; config.tileSize = tileConfig.VERTEX_PER_TILE; config.walkableRadius = m_bigBaseUnit ? 1 : 2; config.borderSize = config.walkableRadius + 3; @@ -992,7 +1012,7 @@ namespace MMAP config.walkableHeight = m_bigBaseUnit ? 3 : 6; // a value >= 3|6 allows npcs to walk over some fences // a value >= 4|8 allows npcs to walk over all fences - config.walkableClimb = m_bigBaseUnit ? 4 : 8; + config.walkableClimb = m_bigBaseUnit ? 3 : 6; config.minRegionArea = rcSqr(60); config.mergeRegionArea = rcSqr(50); config.maxSimplificationError = 1.8f; // eliminates most jagged edges (tiny polygons) @@ -1003,8 +1023,14 @@ namespace MMAP { // Blade's Edge Arena case 562: + // This allows to walk on the ropes to the pillars config.walkableRadius = 0; break; + // Blackfathom Deeps + case 48: + // Reduce the chance to have underground levels + config.ch *= 2; + break; default: break; } diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h index d7c43a6460..239553891d 100644 --- a/src/tools/mmaps_generator/MapBuilder.h +++ b/src/tools/mmaps_generator/MapBuilder.h @@ -26,6 +26,7 @@ #include <vector> #include "IntermediateValues.h" +#include "Optional.h" #include "TerrainBuilder.h" #include "DetourNavMesh.h" @@ -96,7 +97,8 @@ namespace MMAP class MapBuilder { public: - MapBuilder(float maxWalkableAngle = 60.f, + MapBuilder(Optional<float> maxWalkableAngle, + Optional<float> maxWalkableAngleNotSteep, bool skipLiquid = false, bool skipContinents = false, bool skipJunkMaps = true, @@ -161,7 +163,8 @@ namespace MMAP bool m_skipJunkMaps; bool m_skipBattlegrounds; - float m_maxWalkableAngle; + Optional<float> m_maxWalkableAngle; + Optional<float> m_maxWalkableAngleNotSteep; bool m_bigBaseUnit; int32 m_mapid; diff --git a/src/tools/mmaps_generator/PathCommon.h b/src/tools/mmaps_generator/PathCommon.h index 483b4783d9..36743eedb0 100644 --- a/src/tools/mmaps_generator/PathCommon.h +++ b/src/tools/mmaps_generator/PathCommon.h @@ -105,7 +105,7 @@ namespace MMAP errno = 0; if ((dp = readdir(dirp)) != nullptr) { - if (matchWildcardFilter(filter.c_str(), dp->d_name)) + if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0 && matchWildcardFilter(filter.c_str(), dp->d_name)) fileList.emplace_back(dp->d_name); } else diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp index 62e10c13e6..1e59a3d201 100644 --- a/src/tools/mmaps_generator/PathGenerator.cpp +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -18,9 +18,24 @@ #include "MapBuilder.h" #include "PathCommon.h" #include "Timer.h" +#include "DBCFileLoader.h" +#include "PathCommon.h" +#include <boost/filesystem.hpp> +#include <unordered_map> using namespace MMAP; +namespace +{ + std::unordered_map<uint32, uint8> _liquidTypes; +} + +uint32 GetLiquidFlags(uint32 liquidId) +{ + auto itr = _liquidTypes.find(liquidId); + return itr != _liquidTypes.end() ? (1 << itr->second) : 0; +} + bool checkDirectories(bool debugOutput) { std::vector<std::string> dirFiles; @@ -62,7 +77,8 @@ bool handleArgs(int argc, char** argv, int& mapnum, int& tileX, int& tileY, - float& maxAngle, + Optional<float>& maxAngle, + Optional<float>& maxAngleNotSteep, bool& skipLiquid, bool& skipContinents, bool& skipJunkMaps, @@ -84,11 +100,23 @@ bool handleArgs(int argc, char** argv, return false; float maxangle = atof(param); - if (maxangle <= 90.f && maxangle >= 45.f) + if (maxangle <= 90.f && maxangle >= 0.f) maxAngle = maxangle; else printf("invalid option for '--maxAngle', using default\n"); } + else if (strcmp(argv[i], "--maxAngleNotSteep") == 0) + { + param = argv[++i]; + if (!param) + return false; + + float maxangle = atof(param); + if (maxangle <= 90.f && maxangle >= 0.f) + maxAngleNotSteep = maxangle; + else + printf("invalid option for '--maxAngleNotSteep', using default\n"); + } else if (strcmp(argv[i], "--threads") == 0) { param = argv[++i]; @@ -238,12 +266,29 @@ int finish(const char* message, int returnValue) return returnValue; } +std::unordered_map<uint32, uint8> LoadLiquid() +{ + DBCFileLoader liquidDbc; + std::unordered_map<uint32, uint8> liquidData; + // format string doesnt matter as long as it has correct length (only used for mapping to structures in worldserver) + if (liquidDbc.Load((boost::filesystem::path("dbc") / "LiquidType.dbc").string().c_str(), "nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")) + { + for (uint32 x = 0; x < liquidDbc.GetNumRows(); ++x) + { + DBCFileLoader::Record record = liquidDbc.getRecord(x); + liquidData[record.getUInt(0)] = record.getUInt(3); + } + } + + return liquidData; +} + int main(int argc, char** argv) { unsigned int threads = std::thread::hardware_concurrency(); int mapnum = -1; - float maxAngle = 60.0f; int tileX = -1, tileY = -1; + Optional<float> maxAngle, maxAngleNotSteep; bool skipLiquid = false, skipContinents = false, skipJunkMaps = true, @@ -255,7 +300,7 @@ int main(int argc, char** argv) char* file = nullptr; bool validParam = handleArgs(argc, argv, mapnum, - tileX, tileY, maxAngle, + tileX, tileY, maxAngle, maxAngleNotSteep, skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds, debugOutput, silent, bigBaseUnit, offMeshInputPath, file, threads); @@ -277,7 +322,13 @@ int main(int argc, char** argv) if (!checkDirectories(debugOutput)) return silent ? -3 : finish("Press ENTER to close...", -3); - MapBuilder builder(maxAngle, skipLiquid, skipContinents, skipJunkMaps, + _liquidTypes = LoadLiquid(); + if (_liquidTypes.empty()) + { + return silent ? -5 : finish("Failed to load LiquidType.dbc", -5); + } + + MapBuilder builder(maxAngle, maxAngleNotSteep, skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds, debugOutput, bigBaseUnit, mapnum, offMeshInputPath); uint32 start = getMSTime(); diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index d5e2a9a4c3..fa0581f98c 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -77,6 +77,8 @@ struct map_liquidHeader #define MAP_LIQUID_TYPE_DARK_WATER 0x10 #define MAP_LIQUID_TYPE_WMO_WATER 0x20 +uint32 GetLiquidFlags(uint32 liquidId); + namespace MMAP { @@ -392,31 +394,29 @@ namespace MMAP // if there is no liquid, don't use liquid if (!meshData.liquidVerts.size() || !ltriangles.size()) + { useLiquid = false; + } else { liquidType = getLiquidType(i, liquid_type); - switch (liquidType) + if (liquidType & MAP_LIQUID_TYPE_DARK_WATER) { - default: - useLiquid = false; - break; - case MAP_LIQUID_TYPE_WATER: - case MAP_LIQUID_TYPE_OCEAN: - // merge different types of water - liquidType = NAV_WATER; - break; - case MAP_LIQUID_TYPE_MAGMA: - liquidType = NAV_MAGMA; - break; - case MAP_LIQUID_TYPE_SLIME: - liquidType = NAV_SLIME; - break; - case MAP_LIQUID_TYPE_DARK_WATER: - // players should not be here, so logically neither should creatures - useTerrain = false; - useLiquid = false; - break; + // players should not be here, so logically neither should creatures + useTerrain = false; + useLiquid = false; + } + else if ((liquidType & (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN)) != 0) + { + liquidType = NAV_AREA_WATER; + } + else if ((liquidType & (MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)) != 0) + { + liquidType = NAV_AREA_MAGMA_SLIME; + } + else + { + useLiquid = false; } } @@ -719,21 +719,17 @@ namespace MMAP vertsY = tilesY + 1; uint8* flags = liquid->GetFlagsStorage(); float* data = liquid->GetHeightStorage(); - uint8 type = NAV_EMPTY; + uint8 type = NAV_AREA_EMPTY; // convert liquid type to NavTerrain - switch (liquid->GetType() & 3) + uint32 liquidFlags = GetLiquidFlags(liquid->GetType()); + if ((liquidFlags & (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN)) != 0) + { + type = NAV_AREA_WATER; + } + else if ((liquidFlags & (MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)) != 0) { - case 0: - case 1: - type = NAV_WATER; - break; - case 2: - type = NAV_MAGMA; - break; - case 3: - type = NAV_SLIME; - break; + type = NAV_AREA_MAGMA_SLIME; } // indexing is weird... |