summaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-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
5 files changed, 122 insertions, 46 deletions
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...