summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deps/recastnavigation/Recast/Include/Recast.h175
-rw-r--r--deps/recastnavigation/Recast/Source/Recast.cpp60
-rw-r--r--src/common/Collision/Maps/MapDefines.h31
-rw-r--r--src/server/game/Movement/MovementGenerators/PathGenerator.cpp20
-rw-r--r--src/server/game/Movement/MovementGenerators/PathGenerator.h2
-rw-r--r--src/tools/mmaps_generator/MapBuilder.cpp38
-rw-r--r--src/tools/mmaps_generator/MapBuilder.h7
-rw-r--r--src/tools/mmaps_generator/PathCommon.h2
-rw-r--r--src/tools/mmaps_generator/PathGenerator.cpp61
-rw-r--r--src/tools/mmaps_generator/TerrainBuilder.cpp60
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...