fix(Core/MMaps): fix Blade's Edge Arena falling/edge pathing (bump mmap version to 20) (#25720)
This commit is contained in:
committed by
GitHub
parent
98b06f6723
commit
f839009e9a
@@ -155,7 +155,7 @@ function inst_simple_restarter {
|
|||||||
|
|
||||||
function inst_download_client_data {
|
function inst_download_client_data {
|
||||||
# change the following version when needed
|
# change the following version when needed
|
||||||
local VERSION=v19
|
local VERSION=v20
|
||||||
|
|
||||||
echo "#######################"
|
echo "#######################"
|
||||||
echo "Client data downloader"
|
echo "Client data downloader"
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define SIZE_OF_GRIDS 533.3333f
|
#define SIZE_OF_GRIDS 533.3333f
|
||||||
|
|
||||||
#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
|
#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
|
||||||
#define MMAP_VERSION 19
|
#define MMAP_VERSION 20
|
||||||
|
|
||||||
struct MmapTileRecastConfig
|
struct MmapTileRecastConfig
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -236,6 +236,7 @@ enum MapIDs : uint32
|
|||||||
MAP_AUCHINDOUN_MANA_TOMBS = 557,
|
MAP_AUCHINDOUN_MANA_TOMBS = 557,
|
||||||
MAP_AUCHINDOUN_AUCHENAI_CRYPTS = 558,
|
MAP_AUCHINDOUN_AUCHENAI_CRYPTS = 558,
|
||||||
MAP_THE_ESCAPE_FROM_DURNHOLDE = 560,
|
MAP_THE_ESCAPE_FROM_DURNHOLDE = 560,
|
||||||
|
MAP_BLADES_EDGE_ARENA = 562,
|
||||||
MAP_BLACK_TEMPLE = 564,
|
MAP_BLACK_TEMPLE = 564,
|
||||||
MAP_GRUULS_LAIR = 565,
|
MAP_GRUULS_LAIR = 565,
|
||||||
MAP_EYE_OF_THE_STORM = 566,
|
MAP_EYE_OF_THE_STORM = 566,
|
||||||
|
|||||||
@@ -24,6 +24,104 @@
|
|||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
#include "Metric.h"
|
#include "Metric.h"
|
||||||
|
|
||||||
|
// Blades Edge Arena Ropes normalization
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr float BLADE_EDGE_ROPE_SNAP_DIST = 1.5f;
|
||||||
|
constexpr float BLADE_EDGE_ROPE_SNAP_DIST2 = BLADE_EDGE_ROPE_SNAP_DIST * BLADE_EDGE_ROPE_SNAP_DIST;
|
||||||
|
|
||||||
|
struct BladeEdgeArenaRope
|
||||||
|
{
|
||||||
|
G3D::Vector3 Start;
|
||||||
|
G3D::Vector3 End;
|
||||||
|
float Sag;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::array<BladeEdgeArenaRope, 2> BladeEdgeArenaRopes =
|
||||||
|
{{
|
||||||
|
{
|
||||||
|
{6243.1523f, 267.53094f, 10.929295f},
|
||||||
|
{6245.9717f, 271.29346f, 10.879172f},
|
||||||
|
0.43f
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{6234.3213f, 256.29733f, 11.002348f},
|
||||||
|
{6231.3247f, 252.58781f, 10.976968f},
|
||||||
|
0.46f
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
bool IsOutsideExpandedXYBounds(G3D::Vector3 const& point, BladeEdgeArenaRope const& rope)
|
||||||
|
{
|
||||||
|
float const minX = std::min(rope.Start.x, rope.End.x) - BLADE_EDGE_ROPE_SNAP_DIST;
|
||||||
|
float const maxX = std::max(rope.Start.x, rope.End.x) + BLADE_EDGE_ROPE_SNAP_DIST;
|
||||||
|
float const minY = std::min(rope.Start.y, rope.End.y) - BLADE_EDGE_ROPE_SNAP_DIST;
|
||||||
|
float const maxY = std::max(rope.Start.y, rope.End.y) + BLADE_EDGE_ROPE_SNAP_DIST;
|
||||||
|
|
||||||
|
return point.x < minX || point.x > maxX || point.y < minY || point.y > maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetClosestPointOnBladeEdgeArenaRope(G3D::Vector3 const& point, BladeEdgeArenaRope const& rope, G3D::Vector3& closestPoint)
|
||||||
|
{
|
||||||
|
G3D::Vector3 const ropeVector = rope.End - rope.Start;
|
||||||
|
|
||||||
|
float const ropeLength2XY = ropeVector.x * ropeVector.x + ropeVector.y * ropeVector.y;
|
||||||
|
if (ropeLength2XY < 0.00001f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
G3D::Vector3 const pointVector = point - rope.Start;
|
||||||
|
|
||||||
|
float t = (pointVector.x * ropeVector.x + pointVector.y * ropeVector.y) / ropeLength2XY;
|
||||||
|
t = std::clamp(t, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
float const closestX = rope.Start.x + ropeVector.x * t;
|
||||||
|
float const closestY = rope.Start.y + ropeVector.y * t;
|
||||||
|
|
||||||
|
float const dx = point.x - closestX;
|
||||||
|
float const dy = point.y - closestY;
|
||||||
|
|
||||||
|
// If the point is already too far in XY, it cannot be within the 3D snap radius.
|
||||||
|
if (dx * dx + dy * dy >= BLADE_EDGE_ROPE_SNAP_DIST2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float const linearZ = rope.Start.z + (rope.End.z - rope.Start.z) * t;
|
||||||
|
float const sagZ = rope.Sag * std::sin(M_PI * t);
|
||||||
|
|
||||||
|
closestPoint = { closestX, closestY, linearZ - sagZ };
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TrySnapToBladeEdgeArenaRope(G3D::Vector3& point)
|
||||||
|
{
|
||||||
|
bool snapped = false;
|
||||||
|
float bestDist2 = BLADE_EDGE_ROPE_SNAP_DIST2;
|
||||||
|
G3D::Vector3 bestPoint;
|
||||||
|
|
||||||
|
for (BladeEdgeArenaRope const& rope : BladeEdgeArenaRopes)
|
||||||
|
{
|
||||||
|
if (IsOutsideExpandedXYBounds(point, rope))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
G3D::Vector3 closestPoint;
|
||||||
|
if (!GetClosestPointOnBladeEdgeArenaRope(point, rope, closestPoint))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float const dist2 = (point - closestPoint).squaredLength();
|
||||||
|
if (dist2 < bestDist2)
|
||||||
|
{
|
||||||
|
bestDist2 = dist2;
|
||||||
|
bestPoint = closestPoint;
|
||||||
|
snapped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapped)
|
||||||
|
point = bestPoint;
|
||||||
|
|
||||||
|
return snapped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////// PathGenerator //////////////////
|
////////////////// PathGenerator //////////////////
|
||||||
PathGenerator::PathGenerator(WorldObject const* owner) :
|
PathGenerator::PathGenerator(WorldObject const* owner) :
|
||||||
_polyLength(0), _type(PATHFIND_BLANK), _useStraightPath(false), _forceDestination(false),
|
_polyLength(0), _type(PATHFIND_BLANK), _useStraightPath(false), _forceDestination(false),
|
||||||
@@ -622,9 +720,13 @@ void PathGenerator::BuildPointPath(const float* startPoint, const float* endPoin
|
|||||||
|
|
||||||
void PathGenerator::NormalizePath()
|
void PathGenerator::NormalizePath()
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < _pathPoints.size(); ++i)
|
bool const snapBladeEdgeArenaRopes = _source->GetMapId() == MAP_BLADES_EDGE_ARENA;
|
||||||
|
for (G3D::Vector3& point : _pathPoints)
|
||||||
{
|
{
|
||||||
_source->UpdateAllowedPositionZ(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z);
|
if (snapBladeEdgeArenaRopes && TrySnapToBladeEdgeArenaRope(point))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_source->UpdateAllowedPositionZ(point.x, point.y, point.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -191,6 +191,15 @@ namespace MMAP
|
|||||||
tryBoolean(mmapsNode, "skipBattlegrounds", _skipBattlegrounds);
|
tryBoolean(mmapsNode, "skipBattlegrounds", _skipBattlegrounds);
|
||||||
tryBoolean(mmapsNode, "debugOutput", _debugOutput);
|
tryBoolean(mmapsNode, "debugOutput", _debugOutput);
|
||||||
|
|
||||||
|
if (mmapsNode.contains("offmeshConnections") && mmapsNode["offmeshConnections"].is_sequence())
|
||||||
|
{
|
||||||
|
_offmeshConnections = mmapsNode["offmeshConnections"].get_value<std::vector<std::string>>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_offmeshConnections.clear();
|
||||||
|
}
|
||||||
|
|
||||||
std::string dataDirPath;
|
std::string dataDirPath;
|
||||||
tryString(mmapsNode, "dataDir", dataDirPath);
|
tryString(mmapsNode, "dataDir", dataDirPath);
|
||||||
_dataDir = dataDirPath;
|
_dataDir = dataDirPath;
|
||||||
@@ -202,8 +211,8 @@ namespace MMAP
|
|||||||
tryInt(mmapsNode, "walkableHeight", _global.walkableHeight);
|
tryInt(mmapsNode, "walkableHeight", _global.walkableHeight);
|
||||||
tryInt(mmapsNode, "walkableClimb", _global.walkableClimb);
|
tryInt(mmapsNode, "walkableClimb", _global.walkableClimb);
|
||||||
tryInt(mmapsNode, "walkableRadius", _global.walkableRadius);
|
tryInt(mmapsNode, "walkableRadius", _global.walkableRadius);
|
||||||
tryInt(mmapsNode, "vertexPerMapEdge", _global.vertexPerMapEdge);
|
tryInt(mmapsNode, "verticesPerMapEdge", _global.vertexPerMapEdge);
|
||||||
tryInt(mmapsNode, "vertexPerTileEdge", _global.vertexPerTileEdge);
|
tryInt(mmapsNode, "verticesPerTileEdge", _global.vertexPerTileEdge);
|
||||||
tryFloat(mmapsNode, "maxSimplificationError", _global.maxSimplificationError);
|
tryFloat(mmapsNode, "maxSimplificationError", _global.maxSimplificationError);
|
||||||
|
|
||||||
// Map overrides
|
// Map overrides
|
||||||
@@ -225,8 +234,10 @@ namespace MMAP
|
|||||||
override.walkableHeight = mapNode["walkableHeight"].get_value<int>();
|
override.walkableHeight = mapNode["walkableHeight"].get_value<int>();
|
||||||
if (mapNode.contains("walkableClimb"))
|
if (mapNode.contains("walkableClimb"))
|
||||||
override.walkableClimb = mapNode["walkableClimb"].get_value<int>();
|
override.walkableClimb = mapNode["walkableClimb"].get_value<int>();
|
||||||
if (mapNode.contains("vertexPerMapEdge"))
|
if (mapNode.contains("verticesPerMapEdge"))
|
||||||
override.vertexPerMapEdge = mapNode["vertexPerMapEdge"].get_value<int>();
|
override.vertexPerMapEdge = mapNode["verticesPerMapEdge"].get_value<int>();
|
||||||
|
if (mapNode.contains("verticesPerTileEdge"))
|
||||||
|
override.vertexPerTileEdge = mapNode["verticesPerTileEdge"].get_value<int>();
|
||||||
if (mapNode.contains("cellSizeHorizontal"))
|
if (mapNode.contains("cellSizeHorizontal"))
|
||||||
override.cellSizeHorizontal = mapNode["cellSizeHorizontal"].get_value<float>();
|
override.cellSizeHorizontal = mapNode["cellSizeHorizontal"].get_value<float>();
|
||||||
if (mapNode.contains("cellSizeVertical"))
|
if (mapNode.contains("cellSizeVertical"))
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ namespace MMAP
|
|||||||
std::string MMapsPath() const { return (_dataDir / "mmaps").string(); }
|
std::string MMapsPath() const { return (_dataDir / "mmaps").string(); }
|
||||||
std::string DataDirPath() const { return _dataDir.string(); }
|
std::string DataDirPath() const { return _dataDir.string(); }
|
||||||
|
|
||||||
|
std::vector<std::string> const& OffMeshConnections() const { return _offmeshConnections; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Config();
|
explicit Config();
|
||||||
|
|
||||||
@@ -153,6 +155,8 @@ namespace MMAP
|
|||||||
bool _debugOutput;
|
bool _debugOutput;
|
||||||
|
|
||||||
std::filesystem::path _dataDir;
|
std::filesystem::path _dataDir;
|
||||||
|
|
||||||
|
std::vector<std::string> _offmeshConnections;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,6 @@ Generator command line args
|
|||||||
--threads [#] Max number of threads used by the generator
|
--threads [#] Max number of threads used by the generator
|
||||||
Default: 3
|
Default: 3
|
||||||
|
|
||||||
--offMeshInput [file.*] Path to file containing off mesh connections data.
|
|
||||||
Format must be: (see offmesh_example.txt)
|
|
||||||
"map_id tile_x,tile_y (start_x start_y start_z) (end_x end_y end_z) size //optional comments"
|
|
||||||
Single mesh connection per line.
|
|
||||||
|
|
||||||
--silent [] Make us script friendly. Do not wait for user input
|
--silent [] Make us script friendly. Do not wait for user input
|
||||||
on error or completion.
|
on error or completion.
|
||||||
|
|
||||||
|
|||||||
@@ -55,10 +55,9 @@ namespace MMAP
|
|||||||
m_workerThread.join();
|
m_workerThread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
MapBuilder::MapBuilder(Config* config, int mapid, const char* offMeshFilePath, unsigned int threads) :
|
MapBuilder::MapBuilder(Config* config, int mapid, unsigned int threads) :
|
||||||
m_config (config),
|
m_config (config),
|
||||||
m_debugOutput (config->IsDebugOutputEnabled()),
|
m_debugOutput (config->IsDebugOutputEnabled()),
|
||||||
m_offMeshFilePath (offMeshFilePath),
|
|
||||||
m_threads (threads),
|
m_threads (threads),
|
||||||
m_skipContinents (config->ShouldSkipContinents()),
|
m_skipContinents (config->ShouldSkipContinents()),
|
||||||
m_skipJunkMaps (config->ShouldSkipJunkMaps()),
|
m_skipJunkMaps (config->ShouldSkipJunkMaps()),
|
||||||
@@ -497,8 +496,7 @@ namespace MMAP
|
|||||||
// get bounds of current tile
|
// get bounds of current tile
|
||||||
float bmin[3], bmax[3];
|
float bmin[3], bmax[3];
|
||||||
m_mapBuilder->getTileBounds(tileX, tileY, allVerts.getCArray(), allVerts.size() / 3, bmin, bmax);
|
m_mapBuilder->getTileBounds(tileX, tileY, allVerts.getCArray(), allVerts.size() / 3, bmin, bmax);
|
||||||
|
m_terrainBuilder->loadOffMeshConnections(mapID, tileX, tileY, meshData, m_mapBuilder->getConfig().OffMeshConnections());
|
||||||
m_terrainBuilder->loadOffMeshConnections(mapID, tileX, tileY, meshData, m_mapBuilder->m_offMeshFilePath);
|
|
||||||
|
|
||||||
// build navmesh tile
|
// build navmesh tile
|
||||||
buildMoveMapTile(mapID, tileX, tileY, meshData, bmin, bmax, navMesh);
|
buildMoveMapTile(mapID, tileX, tileY, meshData, bmin, bmax, navMesh);
|
||||||
@@ -818,7 +816,7 @@ namespace MMAP
|
|||||||
}
|
}
|
||||||
if (params.vertCount >= 0xffff)
|
if (params.vertCount >= 0xffff)
|
||||||
{
|
{
|
||||||
printf("%s Too many vertices! \n", tileString);
|
printf("%s Too many vertices! %d out of %d! \n", tileString, params.vertCount, 0xffff);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!params.vertCount || !params.verts)
|
if (!params.vertCount || !params.verts)
|
||||||
|
|||||||
@@ -125,7 +125,6 @@ namespace MMAP
|
|||||||
public:
|
public:
|
||||||
MapBuilder(Config* config,
|
MapBuilder(Config* config,
|
||||||
int mapid,
|
int mapid,
|
||||||
char const* offMeshFilePath,
|
|
||||||
unsigned int threads);
|
unsigned int threads);
|
||||||
|
|
||||||
~MapBuilder();
|
~MapBuilder();
|
||||||
@@ -167,7 +166,6 @@ namespace MMAP
|
|||||||
|
|
||||||
bool m_debugOutput;
|
bool m_debugOutput;
|
||||||
|
|
||||||
const char* m_offMeshFilePath;
|
|
||||||
unsigned int m_threads;
|
unsigned int m_threads;
|
||||||
bool m_skipContinents;
|
bool m_skipContinents;
|
||||||
bool m_skipJunkMaps;
|
bool m_skipJunkMaps;
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ bool handleArgs(int argc, char** argv,
|
|||||||
int& tileY,
|
int& tileY,
|
||||||
std::string& configFilePath,
|
std::string& configFilePath,
|
||||||
bool& silent,
|
bool& silent,
|
||||||
char*& offMeshInputPath,
|
|
||||||
char*& file,
|
char*& file,
|
||||||
unsigned int& threads)
|
unsigned int& threads)
|
||||||
{
|
{
|
||||||
@@ -120,14 +119,6 @@ bool handleArgs(int argc, char** argv,
|
|||||||
{
|
{
|
||||||
silent = true;
|
silent = true;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i], "--offMeshInput") == 0)
|
|
||||||
{
|
|
||||||
param = argv[++i];
|
|
||||||
if (!param)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
offMeshInputPath = param;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int map = atoi(argv[i]);
|
int map = atoi(argv[i]);
|
||||||
@@ -174,11 +165,10 @@ int main(int argc, char** argv)
|
|||||||
int mapnum = -1;
|
int mapnum = -1;
|
||||||
int tileX = -1, tileY = -1;
|
int tileX = -1, tileY = -1;
|
||||||
bool silent = false;
|
bool silent = false;
|
||||||
char* offMeshInputPath = nullptr;
|
|
||||||
char* file = nullptr;
|
char* file = nullptr;
|
||||||
std::string configFilePath = "mmaps-config.yaml";
|
std::string configFilePath = "mmaps-config.yaml";
|
||||||
bool validParam = handleArgs(argc, argv, mapnum,
|
bool validParam = handleArgs(argc, argv, mapnum,
|
||||||
tileX, tileY, configFilePath, silent, offMeshInputPath, file, threads);
|
tileX, tileY, configFilePath, silent, file, threads);
|
||||||
|
|
||||||
if (!validParam)
|
if (!validParam)
|
||||||
return silent ? -1 : finish("You have specified invalid parameters", -1);
|
return silent ? -1 : finish("You have specified invalid parameters", -1);
|
||||||
@@ -202,7 +192,7 @@ int main(int argc, char** argv)
|
|||||||
if (!checkDirectories(config->DataDirPath(), config->IsDebugOutputEnabled()))
|
if (!checkDirectories(config->DataDirPath(), config->IsDebugOutputEnabled()))
|
||||||
return silent ? -3 : finish("Press ENTER to close...", -3);
|
return silent ? -3 : finish("Press ENTER to close...", -3);
|
||||||
|
|
||||||
MapBuilder builder(&config.value(), mapnum, offMeshInputPath, threads);
|
MapBuilder builder(&config.value(), mapnum, threads);
|
||||||
|
|
||||||
uint32 start = getMSTime();
|
uint32 start = getMSTime();
|
||||||
if (file)
|
if (file)
|
||||||
|
|||||||
@@ -927,30 +927,29 @@ namespace MMAP
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void TerrainBuilder::loadOffMeshConnections(uint32 mapID, uint32 tileX, uint32 tileY, MeshData& meshData, const char* offMeshFilePath)
|
void TerrainBuilder::loadOffMeshConnections(uint32 mapID, uint32 tileX, uint32 tileY,
|
||||||
|
MeshData& meshData,
|
||||||
|
const std::vector<std::string>& offMeshLines)
|
||||||
{
|
{
|
||||||
// no meshfile input given?
|
if (offMeshLines.empty())
|
||||||
if (!offMeshFilePath)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
FILE* fp = fopen(offMeshFilePath, "rb");
|
for (const std::string& line : offMeshLines)
|
||||||
if (!fp)
|
|
||||||
{
|
|
||||||
printf(" loadOffMeshConnections:: input file %s not found!\n", offMeshFilePath);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// pretty silly thing, as we parse entire file and load only the tile we need
|
|
||||||
// but we don't expect this file to be too large
|
|
||||||
char* buf = new char[512];
|
|
||||||
while (fgets(buf, 512, fp))
|
|
||||||
{
|
{
|
||||||
float p0[3], p1[3];
|
float p0[3], p1[3];
|
||||||
uint32 mid, tx, ty;
|
uint32 mid, tx, ty;
|
||||||
float size;
|
float size;
|
||||||
if (sscanf(buf, "%u %u,%u (%f %f %f) (%f %f %f) %f", &mid, &tx, &ty,
|
|
||||||
&p0[0], &p0[1], &p0[2], &p1[0], &p1[1], &p1[2], &size) != 10)
|
if (sscanf(line.c_str(),
|
||||||
|
"%u %u,%u (%f %f %f) (%f %f %f) %f",
|
||||||
|
&mid, &tx, &ty,
|
||||||
|
&p0[0], &p0[1], &p0[2],
|
||||||
|
&p1[0], &p1[1], &p1[2],
|
||||||
|
&size) != 10)
|
||||||
|
{
|
||||||
|
printf("Skipped off-mesh connection '%s': invalid format\n", line.c_str());
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (mapID == mid && tileX == tx && tileY == ty)
|
if (mapID == mid && tileX == tx && tileY == ty)
|
||||||
{
|
{
|
||||||
@@ -962,15 +961,11 @@ namespace MMAP
|
|||||||
meshData.offMeshConnections.append(p1[2]);
|
meshData.offMeshConnections.append(p1[2]);
|
||||||
meshData.offMeshConnections.append(p1[0]);
|
meshData.offMeshConnections.append(p1[0]);
|
||||||
|
|
||||||
meshData.offMeshConnectionDirs.append(1); // 1 - both direction, 0 - one sided
|
meshData.offMeshConnectionDirs.append(1); // 1 - both direction, 0 - one sided
|
||||||
meshData.offMeshConnectionRads.append(size); // agent size equivalent
|
meshData.offMeshConnectionRads.append(size); // agent radius equivalent
|
||||||
// can be used same way as polygon flags
|
|
||||||
meshData.offMeshConnectionsAreas.append((unsigned char)0xFF);
|
meshData.offMeshConnectionsAreas.append((unsigned char)0xFF);
|
||||||
meshData.offMeshConnectionsFlags.append((unsigned short)0xFF); // all movement masks can make this path
|
meshData.offMeshConnectionsFlags.append((unsigned short)0xFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] buf;
|
|
||||||
fclose(fp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ namespace MMAP
|
|||||||
|
|
||||||
void loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData& meshData);
|
void loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData& meshData);
|
||||||
bool loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData& meshData);
|
bool loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData& meshData);
|
||||||
void loadOffMeshConnections(uint32 mapID, uint32 tileX, uint32 tileY, MeshData& meshData, const char* offMeshFilePath);
|
void loadOffMeshConnections(uint32 mapID, uint32 tileX, uint32 tileY, MeshData& meshData, const std::vector<std::string>& offMeshLines);
|
||||||
|
|
||||||
[[nodiscard]] bool usesLiquids() const { return !m_skipLiquid; }
|
[[nodiscard]] bool usesLiquids() const { return !m_skipLiquid; }
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,24 @@ mmapsConfig:
|
|||||||
# and is also where the "mmaps" folder will be created or located.
|
# and is also where the "mmaps" folder will be created or located.
|
||||||
dataDir: "./"
|
dataDir: "./"
|
||||||
|
|
||||||
|
# Off-mesh connections define manual navigation links that are not part of the generated navmesh.
|
||||||
|
# They are used to connect two arbitrary points in the world where normal pathfinding cannot reach,
|
||||||
|
# such as jumps, ropes, ladders, teleports, elevators, or special scripted movement paths.
|
||||||
|
#
|
||||||
|
# Format:
|
||||||
|
# mapID tileX,tileY (start_x start_y start_z) (end_x end_y end_z) size
|
||||||
|
#
|
||||||
|
# Fields:
|
||||||
|
# mapID - Map identifier where this connection exists.
|
||||||
|
# tileX,tileY- Navmesh tile coordinates the connection belongs to.
|
||||||
|
# start - World position where the connection begins.
|
||||||
|
# end - World position where the connection ends.
|
||||||
|
# size - Effective radius of the connection (agent clearance / usability width).
|
||||||
|
offmeshConnections:
|
||||||
|
# Make Blades Edge Arena Ropes wider
|
||||||
|
- "562 31,20 (6234.474121 256.563721 11.063726) (6230.162598 251.681976 11.199670) 2.1"
|
||||||
|
- "562 31,20 (6242.273926 266.697540 11.090456) (6246.688965 272.064819 11.235604) 2.1"
|
||||||
|
|
||||||
meshSettings:
|
meshSettings:
|
||||||
# Here we have global config for recast navigation.
|
# Here we have global config for recast navigation.
|
||||||
# It's possible to override these data on map or tile level (see mapsOverrides).
|
# It's possible to override these data on map or tile level (see mapsOverrides).
|
||||||
@@ -106,9 +124,6 @@ mmapsConfig:
|
|||||||
# All parameters defined globally are eligible for override.
|
# All parameters defined globally are eligible for override.
|
||||||
# Just specify the parameter name and new value in the override section.
|
# Just specify the parameter name and new value in the override section.
|
||||||
mapsOverrides:
|
mapsOverrides:
|
||||||
"562": # Blade's Edge Arena
|
|
||||||
walkableRadius: 0 # This allows walking on the ropes to the pillars
|
|
||||||
|
|
||||||
"48": # Blackfathom Deeps
|
"48": # Blackfathom Deeps
|
||||||
cellSizeVertical: 0.5334 # ch*2 = 0.2667 * 2 ≈ 0.5334. Reduce the chance to have underground levels.
|
cellSizeVertical: 0.5334 # ch*2 = 0.2667 * 2 ≈ 0.5334. Reduce the chance to have underground levels.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user