feat(Core/Mmaps): Handle different slopes in mmaps and Add some more input parameters to improve (#10974)

This commit is contained in:
IntelligentQuantum
2022-04-25 00:14:50 +04:30
committed by GitHub
parent 090cc5e2c6
commit b544eb420e
10 changed files with 274 additions and 182 deletions
+4 -1
View File
@@ -224,6 +224,9 @@ struct rcConfig
/// 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; float walkableSlopeAngle;
/// The maximum slope that is considered walkable but not steep. It should be lower/equal than walkableSlopeAngle. [Limits: 0 <= value < 90] [Units: Degrees]
float walkableSlopeAngleNotSteep;
/// Minimum floor to 'ceiling' height that will still allow the floor area to /// Minimum floor to 'ceiling' height that will still allow the floor area to
/// be considered walkable. [Limit: >= 3] [Units: vx] /// be considered walkable. [Limit: >= 3] [Units: vx]
int walkableHeight; int walkableHeight;
@@ -810,7 +813,7 @@ bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int heigh
/// @param[in] nt The number of triangles. /// @param[in] nt The number of triangles.
/// @param[out] areas The triangle area ids. [Length: >= @p nt] /// @param[out] areas The triangle area ids. [Length: >= @p nt]
void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, 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. /// Sets the area id of all triangles with a slope greater than or equal to the specified value to #RC_NULL_AREA.
/// @ingroup recast /// @ingroup recast
+2 -2
View File
@@ -334,7 +334,7 @@ static void calcTriNormal(const float* v0, const float* v1, const float* v2, flo
void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle,
const float* verts, int nv, const float* verts, int nv,
const int* tris, int nt, const int* tris, int nt,
unsigned char* areas) unsigned char* areas, unsigned char areaType)
{ {
rcIgnoreUnused(ctx); rcIgnoreUnused(ctx);
rcIgnoreUnused(nv); rcIgnoreUnused(nv);
@@ -349,7 +349,7 @@ void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle,
calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm); calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm);
// Check if the face is walkable. // Check if the face is walkable.
if (norm[1] > walkableThr) if (norm[1] > walkableThr)
areas[i] = RC_WALKABLE_AREA; areas[i] = areaType;
} }
} }
+20 -11
View File
@@ -36,18 +36,27 @@ static_assert(sizeof(MmapTileHeader) == (sizeof(MmapTileHeader::mmapMagic) +
sizeof(MmapTileHeader::usesLiquids) + sizeof(MmapTileHeader::usesLiquids) +
sizeof(MmapTileHeader::padding)), "MmapTileHeader has uninitialized padding fields"); sizeof(MmapTileHeader::padding)), "MmapTileHeader has uninitialized padding fields");
enum NavTerrain enum NavArea
{ {
NAV_EMPTY = 0x00, NAV_AREA_EMPTY = 0,
NAV_GROUND = 0x01, // areas 1-60 will be used for destructible areas (currently skipped in vmaps, WMO with flag 1)
NAV_MAGMA = 0x02, // 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_SLIME = 0x04, NAV_AREA_GROUND_STEEP = 11,
NAV_WATER = 0x08, NAV_AREA_GROUND = 10,
NAV_UNUSED1 = 0x10, NAV_AREA_WATER = 9,
NAV_UNUSED2 = 0x20, NAV_AREA_MAGMA_SLIME = 8, // don't need to differentiate between them
NAV_UNUSED3 = 0x40, NAV_AREA_MAX_VALUE = NAV_AREA_GROUND_STEEP,
NAV_UNUSED4 = 0x80 NAV_AREA_MIN_VALUE = NAV_AREA_MAGMA_SLIME,
// we only have 8 bits 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 #endif
@@ -641,12 +641,12 @@ void PathGenerator::CreateFilter()
// creatures don't take environmental damage // creatures don't take environmental damage
if (creature->CanEnterWater()) if (creature->CanEnterWater())
includeFlags |= (NAV_WATER | NAV_MAGMA); includeFlags |= (NAV_WATER | NAV_MAGMA_SLIME);
} }
else // assume Player else // assume Player
{ {
// perfect support not possible, just stay 'safe' // 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); _filter.setIncludeFlags(includeFlags);
@@ -671,13 +671,17 @@ void PathGenerator::UpdateFilter()
_filter.setIncludeFlags(includedFlags); _filter.setIncludeFlags(includedFlags);
} }
/*if (Creature const* _sourceCreature = _source->ToCreature()) if (Creature const* _sourceCreature = _source->ToCreature())
{
if (_sourceCreature->IsInCombat() || _sourceCreature->IsInEvadeMode()) 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 data;
LiquidData const& liquidData = _source->GetMap()->GetLiquidData(_source->GetPhaseMask(), x, y, z, _source->GetCollisionHeight(), MAP_ALL_LIQUIDS); 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; return NAV_WATER;
case MAP_LIQUID_TYPE_MAGMA: case MAP_LIQUID_TYPE_MAGMA:
case MAP_LIQUID_TYPE_SLIME: case MAP_LIQUID_TYPE_SLIME:
return NAV_MAGMA; return NAV_MAGMA_SLIME;
default: default:
return NAV_GROUND; 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 // 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) 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 // 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; waterPath = false;
break; break;
@@ -168,7 +168,7 @@ class PathGenerator
void BuildPointPath(float const* startPoint, float const* endPoint); void BuildPointPath(float const* startPoint, float const* endPoint);
void BuildShortcut(); 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 CreateFilter();
void UpdateFilter(); void UpdateFilter();
+32 -6
View File
@@ -26,7 +26,7 @@
namespace MMAP 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 skipContinents, bool skipJunkMaps, bool skipBattlegrounds,
bool debugOutput, bool bigBaseUnit, int mapid, const char* offMeshFilePath) : bool debugOutput, bool bigBaseUnit, int mapid, const char* offMeshFilePath) :
@@ -36,6 +36,7 @@ namespace MMAP
m_skipJunkMaps (skipJunkMaps), m_skipJunkMaps (skipJunkMaps),
m_skipBattlegrounds (skipBattlegrounds), m_skipBattlegrounds (skipBattlegrounds),
m_maxWalkableAngle (maxWalkableAngle), m_maxWalkableAngle (maxWalkableAngle),
m_maxWalkableAngleNotSteep (maxWalkableAngleNotSteep),
m_bigBaseUnit (bigBaseUnit), m_bigBaseUnit (bigBaseUnit),
m_mapid (mapid), m_mapid (mapid),
m_totalTiles (0u), m_totalTiles (0u),
@@ -587,9 +588,17 @@ namespace MMAP
} }
// mark all walkable tiles, both liquids and solids // 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]; 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); 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); rcRasterizeTriangles(m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.solid, config.walkableClimb);
delete[] triFlags; delete[] triFlags;
@@ -597,6 +606,7 @@ namespace MMAP
rcFilterLedgeSpans(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid); rcFilterLedgeSpans(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid);
rcFilterWalkableLowHeightSpans(m_rcContext, tileCfg.walkableHeight, *tile.solid); rcFilterWalkableLowHeightSpans(m_rcContext, tileCfg.walkableHeight, *tile.solid);
// add liquid triangles
rcRasterizeTriangles(m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *tile.solid, config.walkableClimb); rcRasterizeTriangles(m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *tile.solid, config.walkableClimb);
// compact heightfield spans // compact heightfield spans
@@ -694,8 +704,15 @@ namespace MMAP
// set polygons as walkable // set polygons as walkable
// TODO: special flags for DYNAMIC polygons, ie surfaces that can be turned on and off // TODO: special flags for DYNAMIC polygons, ie surfaces that can be turned on and off
for (int i = 0; i < iv.polyMesh->npolys; ++i) 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 // setup mesh parameters
dtNavMeshCreateParams params; dtNavMeshCreateParams params;
@@ -984,7 +1001,10 @@ namespace MMAP
config.maxVertsPerPoly = DT_VERTS_PER_POLYGON; config.maxVertsPerPoly = DT_VERTS_PER_POLYGON;
config.cs = tileConfig.BASE_UNIT_DIM; config.cs = tileConfig.BASE_UNIT_DIM;
config.ch = 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.tileSize = tileConfig.VERTEX_PER_TILE;
config.walkableRadius = m_bigBaseUnit ? 1 : 2; config.walkableRadius = m_bigBaseUnit ? 1 : 2;
config.borderSize = config.walkableRadius + 3; config.borderSize = config.walkableRadius + 3;
@@ -992,7 +1012,7 @@ namespace MMAP
config.walkableHeight = m_bigBaseUnit ? 3 : 6; config.walkableHeight = m_bigBaseUnit ? 3 : 6;
// a value >= 3|6 allows npcs to walk over some fences // a value >= 3|6 allows npcs to walk over some fences
// a value >= 4|8 allows npcs to walk over all 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.minRegionArea = rcSqr(60);
config.mergeRegionArea = rcSqr(50); config.mergeRegionArea = rcSqr(50);
config.maxSimplificationError = 1.8f; // eliminates most jagged edges (tiny polygons) config.maxSimplificationError = 1.8f; // eliminates most jagged edges (tiny polygons)
@@ -1003,8 +1023,14 @@ namespace MMAP
{ {
// Blade's Edge Arena // Blade's Edge Arena
case 562: case 562:
// This allows to walk on the ropes to the pillars
config.walkableRadius = 0; config.walkableRadius = 0;
break; break;
// Blackfathom Deeps
case 48:
// Reduce the chance to have underground levels
config.ch *= 2;
break;
default: default:
break; break;
} }
+5 -2
View File
@@ -26,6 +26,7 @@
#include <vector> #include <vector>
#include "IntermediateValues.h" #include "IntermediateValues.h"
#include "Optional.h"
#include "TerrainBuilder.h" #include "TerrainBuilder.h"
#include "DetourNavMesh.h" #include "DetourNavMesh.h"
@@ -96,7 +97,8 @@ namespace MMAP
class MapBuilder class MapBuilder
{ {
public: public:
MapBuilder(float maxWalkableAngle = 60.f, MapBuilder(Optional<float> maxWalkableAngle,
Optional<float> maxWalkableAngleNotSteep,
bool skipLiquid = false, bool skipLiquid = false,
bool skipContinents = false, bool skipContinents = false,
bool skipJunkMaps = true, bool skipJunkMaps = true,
@@ -161,7 +163,8 @@ namespace MMAP
bool m_skipJunkMaps; bool m_skipJunkMaps;
bool m_skipBattlegrounds; bool m_skipBattlegrounds;
float m_maxWalkableAngle; Optional<float> m_maxWalkableAngle;
Optional<float> m_maxWalkableAngleNotSteep;
bool m_bigBaseUnit; bool m_bigBaseUnit;
int32 m_mapid; int32 m_mapid;
+1 -1
View File
@@ -105,7 +105,7 @@ namespace MMAP
errno = 0; errno = 0;
if ((dp = readdir(dirp)) != nullptr) 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); fileList.emplace_back(dp->d_name);
} }
else else
+56 -5
View File
@@ -18,9 +18,24 @@
#include "MapBuilder.h" #include "MapBuilder.h"
#include "PathCommon.h" #include "PathCommon.h"
#include "Timer.h" #include "Timer.h"
#include "DBCFileLoader.h"
#include "PathCommon.h"
#include <boost/filesystem.hpp>
#include <unordered_map>
using namespace MMAP; 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) bool checkDirectories(bool debugOutput)
{ {
std::vector<std::string> dirFiles; std::vector<std::string> dirFiles;
@@ -62,7 +77,8 @@ bool handleArgs(int argc, char** argv,
int& mapnum, int& mapnum,
int& tileX, int& tileX,
int& tileY, int& tileY,
float& maxAngle, Optional<float>& maxAngle,
Optional<float>& maxAngleNotSteep,
bool& skipLiquid, bool& skipLiquid,
bool& skipContinents, bool& skipContinents,
bool& skipJunkMaps, bool& skipJunkMaps,
@@ -84,11 +100,23 @@ bool handleArgs(int argc, char** argv,
return false; return false;
float maxangle = atof(param); float maxangle = atof(param);
if (maxangle <= 90.f && maxangle >= 45.f) if (maxangle <= 90.f && maxangle >= 0.f)
maxAngle = maxangle; maxAngle = maxangle;
else else
printf("invalid option for '--maxAngle', using default\n"); 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) else if (strcmp(argv[i], "--threads") == 0)
{ {
param = argv[++i]; param = argv[++i];
@@ -238,12 +266,29 @@ int finish(const char* message, int returnValue)
return 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) int main(int argc, char** argv)
{ {
unsigned int threads = std::thread::hardware_concurrency(); unsigned int threads = std::thread::hardware_concurrency();
int mapnum = -1; int mapnum = -1;
float maxAngle = 60.0f;
int tileX = -1, tileY = -1; int tileX = -1, tileY = -1;
Optional<float> maxAngle, maxAngleNotSteep;
bool skipLiquid = false, bool skipLiquid = false,
skipContinents = false, skipContinents = false,
skipJunkMaps = true, skipJunkMaps = true,
@@ -255,7 +300,7 @@ int main(int argc, char** argv)
char* file = nullptr; char* file = nullptr;
bool validParam = handleArgs(argc, argv, mapnum, bool validParam = handleArgs(argc, argv, mapnum,
tileX, tileY, maxAngle, tileX, tileY, maxAngle, maxAngleNotSteep,
skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds, skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds,
debugOutput, silent, bigBaseUnit, offMeshInputPath, file, threads); debugOutput, silent, bigBaseUnit, offMeshInputPath, file, threads);
@@ -277,7 +322,13 @@ int main(int argc, char** argv)
if (!checkDirectories(debugOutput)) if (!checkDirectories(debugOutput))
return silent ? -3 : finish("Press ENTER to close...", -3); 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); skipBattlegrounds, debugOutput, bigBaseUnit, mapnum, offMeshInputPath);
uint32 start = getMSTime(); uint32 start = getMSTime();
+28 -32
View File
@@ -77,6 +77,8 @@ struct map_liquidHeader
#define MAP_LIQUID_TYPE_DARK_WATER 0x10 #define MAP_LIQUID_TYPE_DARK_WATER 0x10
#define MAP_LIQUID_TYPE_WMO_WATER 0x20 #define MAP_LIQUID_TYPE_WMO_WATER 0x20
uint32 GetLiquidFlags(uint32 liquidId);
namespace MMAP namespace MMAP
{ {
@@ -392,31 +394,29 @@ namespace MMAP
// if there is no liquid, don't use liquid // if there is no liquid, don't use liquid
if (!meshData.liquidVerts.size() || !ltriangles.size()) if (!meshData.liquidVerts.size() || !ltriangles.size())
{
useLiquid = false; useLiquid = false;
}
else else
{ {
liquidType = getLiquidType(i, liquid_type); liquidType = getLiquidType(i, liquid_type);
switch (liquidType) if (liquidType & MAP_LIQUID_TYPE_DARK_WATER)
{ {
default: // players should not be here, so logically neither should creatures
useLiquid = false; useTerrain = false;
break; useLiquid = false;
case MAP_LIQUID_TYPE_WATER: }
case MAP_LIQUID_TYPE_OCEAN: else if ((liquidType & (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN)) != 0)
// merge different types of water {
liquidType = NAV_WATER; liquidType = NAV_AREA_WATER;
break; }
case MAP_LIQUID_TYPE_MAGMA: else if ((liquidType & (MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)) != 0)
liquidType = NAV_MAGMA; {
break; liquidType = NAV_AREA_MAGMA_SLIME;
case MAP_LIQUID_TYPE_SLIME: }
liquidType = NAV_SLIME; else
break; {
case MAP_LIQUID_TYPE_DARK_WATER: useLiquid = false;
// players should not be here, so logically neither should creatures
useTerrain = false;
useLiquid = false;
break;
} }
} }
@@ -719,21 +719,17 @@ namespace MMAP
vertsY = tilesY + 1; vertsY = tilesY + 1;
uint8* flags = liquid->GetFlagsStorage(); uint8* flags = liquid->GetFlagsStorage();
float* data = liquid->GetHeightStorage(); float* data = liquid->GetHeightStorage();
uint8 type = NAV_EMPTY; uint8 type = NAV_AREA_EMPTY;
// convert liquid type to NavTerrain // 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)
{ {
case 0: type = NAV_AREA_WATER;
case 1: }
type = NAV_WATER; else if ((liquidFlags & (MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)) != 0)
break; {
case 2: type = NAV_AREA_MAGMA_SLIME;
type = NAV_MAGMA;
break;
case 3:
type = NAV_SLIME;
break;
} }
// indexing is weird... // indexing is weird...