mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Tools/mmaps_generator: Give land priority during area merges over liquids
Closes #21700
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
#include "DetourNavMesh.h"
|
||||
|
||||
const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP'
|
||||
#define MMAP_VERSION 8
|
||||
#define MMAP_VERSION 9
|
||||
|
||||
struct MmapTileHeader
|
||||
{
|
||||
@@ -29,18 +29,22 @@ 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 = 63,
|
||||
NAV_AREA_WATER = 62,
|
||||
NAV_AREA_MAGMA_SLIME = 61 // don't need to differentiate between them
|
||||
};
|
||||
|
||||
enum NavTerrainFlag
|
||||
{
|
||||
NAV_EMPTY = 0x00,
|
||||
NAV_GROUND = 1 << (63 - NAV_AREA_GROUND),
|
||||
NAV_WATER = 1 << (63 - NAV_AREA_WATER),
|
||||
NAV_MAGMA_SLIME = 1 << (63 - NAV_AREA_MAGMA_SLIME)
|
||||
};
|
||||
|
||||
#endif /* _MAPDEFINES_H */
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace VMAP
|
||||
//=================================================================
|
||||
|
||||
TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName)
|
||||
: iDestDir(pDestDirName), iSrcDir(pSrcDirName), iFilterMethod(NULL), iCurrentUniqueNameId(0)
|
||||
: iDestDir(pDestDirName), iSrcDir(pSrcDirName), iCurrentUniqueNameId(0)
|
||||
{
|
||||
boost::filesystem::create_directory(iDestDir);
|
||||
//init();
|
||||
@@ -243,8 +243,10 @@ namespace VMAP
|
||||
printf("spawning Map %u\n", mapID);
|
||||
mapData[mapID] = current = new MapSpawns();
|
||||
}
|
||||
else current = map_iter->second;
|
||||
current->UniqueEntries.insert(pair<uint32, ModelSpawn>(spawn.ID, spawn));
|
||||
else
|
||||
current = map_iter->second;
|
||||
|
||||
current->UniqueEntries.emplace(spawn.ID, spawn);
|
||||
current->TileEntries.insert(pair<uint32, TileSpawn>(StaticMapTree::packTileID(tileX, tileY), TileSpawn{ spawn.ID, spawn.flags }));
|
||||
}
|
||||
bool success = (ferror(dirf) == 0);
|
||||
|
||||
@@ -101,7 +101,6 @@ namespace VMAP
|
||||
private:
|
||||
std::string iDestDir;
|
||||
std::string iSrcDir;
|
||||
bool (*iFilterMethod)(char *pName);
|
||||
G3D::Table<std::string, unsigned int > iUniqueNameIds;
|
||||
unsigned int iCurrentUniqueNameId;
|
||||
MapData mapData;
|
||||
@@ -117,8 +116,6 @@ namespace VMAP
|
||||
void exportGameobjectModels();
|
||||
|
||||
bool convertRawFile(const std::string& pModelFilename);
|
||||
void setModelNameFilterMethod(bool (*pFilterMethod)(char *pName)) { iFilterMethod = pFilterMethod; }
|
||||
std::string getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName);
|
||||
};
|
||||
|
||||
} // VMAP
|
||||
|
||||
@@ -617,12 +617,12 @@ void PathGenerator::CreateFilter()
|
||||
|
||||
// creatures don't take environmental damage
|
||||
if (creature->CanSwim())
|
||||
includeFlags |= (NAV_WATER | NAV_MAGMA | NAV_SLIME); // swim
|
||||
includeFlags |= (NAV_WATER | NAV_MAGMA_SLIME); // swim
|
||||
}
|
||||
else // assume Player
|
||||
{
|
||||
// perfect support not possible, just stay 'safe'
|
||||
includeFlags |= (NAV_GROUND | NAV_WATER | NAV_MAGMA | NAV_SLIME);
|
||||
includeFlags |= (NAV_GROUND | NAV_WATER | NAV_MAGMA_SLIME);
|
||||
}
|
||||
|
||||
_filter.setIncludeFlags(includeFlags);
|
||||
@@ -646,7 +646,7 @@ void PathGenerator::UpdateFilter()
|
||||
}
|
||||
}
|
||||
|
||||
NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z)
|
||||
NavTerrainFlag PathGenerator::GetNavTerrain(float x, float y, float z)
|
||||
{
|
||||
LiquidData data;
|
||||
ZLiquidStatus liquidStatus = _sourceUnit->GetMap()->getLiquidStatus(_sourceUnit->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &data);
|
||||
@@ -660,9 +660,8 @@ NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z)
|
||||
case MAP_LIQUID_TYPE_OCEAN:
|
||||
return NAV_WATER;
|
||||
case MAP_LIQUID_TYPE_MAGMA:
|
||||
return NAV_MAGMA;
|
||||
case MAP_LIQUID_TYPE_SLIME:
|
||||
return NAV_SLIME;
|
||||
return NAV_MAGMA_SLIME;
|
||||
default:
|
||||
return NAV_GROUND;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ class TC_GAME_API PathGenerator
|
||||
void BuildPointPath(float const* startPoint, float const* endPoint);
|
||||
void BuildShortcut();
|
||||
|
||||
NavTerrain GetNavTerrain(float x, float y, float z);
|
||||
NavTerrainFlag GetNavTerrain(float x, float y, float z);
|
||||
void CreateFilter();
|
||||
void UpdateFilter();
|
||||
|
||||
|
||||
@@ -618,7 +618,7 @@ namespace MMAP
|
||||
|
||||
// mark all walkable tiles, both liquids and solids
|
||||
unsigned char* triFlags = new unsigned char[tTriCount];
|
||||
memset(triFlags, NAV_GROUND, tTriCount*sizeof(unsigned char));
|
||||
memset(triFlags, NAV_AREA_GROUND, tTriCount*sizeof(unsigned char));
|
||||
rcClearUnwalkableTriangles(m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags);
|
||||
rcRasterizeTriangles(m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.solid, config.walkableClimb);
|
||||
delete[] triFlags;
|
||||
@@ -724,8 +724,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] & RC_WALKABLE_AREA)
|
||||
{
|
||||
if (area >= NAV_AREA_MAGMA_SLIME)
|
||||
iv.polyMesh->flags[i] = 1 << (63 - area);
|
||||
else
|
||||
iv.polyMesh->flags[i] = NAV_GROUND; // TODO: these will be dynamic in future
|
||||
}
|
||||
}
|
||||
|
||||
// setup mesh parameters
|
||||
dtNavMeshCreateParams params;
|
||||
|
||||
@@ -31,6 +31,11 @@
|
||||
|
||||
using namespace MMAP;
|
||||
|
||||
namespace
|
||||
{
|
||||
std::unordered_map<uint32, uint8> _liquidTypes;
|
||||
}
|
||||
|
||||
bool checkDirectories(bool debugOutput, std::vector<std::string>& dbcLocales)
|
||||
{
|
||||
if (getDirContents(dbcLocales, "dbc") == LISTFILE_DIRECTORY_NOT_FOUND || dbcLocales.empty())
|
||||
@@ -260,6 +265,43 @@ int finish(const char* message, int returnValue)
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
std::unordered_map<uint32, uint8> LoadLiquid(std::string const& locale)
|
||||
{
|
||||
DB2FileLoader liquidDb2;
|
||||
std::unordered_map<uint32, uint8> liquidData;
|
||||
DB2FileSystemSource liquidTypeSource((boost::filesystem::path("dbc") / locale / "LiquidType.db2").string());
|
||||
if (liquidDb2.Load(&liquidTypeSource, LiquidTypeLoadInfo::Instance()))
|
||||
{
|
||||
for (uint32 x = 0; x < liquidDb2.GetRecordCount(); ++x)
|
||||
{
|
||||
DB2Record record = liquidDb2.GetRecord(x);
|
||||
liquidData[record.GetId()] = record.GetUInt8("SoundBank");
|
||||
}
|
||||
}
|
||||
|
||||
return liquidData;
|
||||
}
|
||||
|
||||
std::unordered_map<uint32, std::vector<uint32>> LoadMap(std::string const& locale)
|
||||
{
|
||||
DB2FileLoader mapDb2;
|
||||
std::unordered_map<uint32, std::vector<uint32>> mapData;
|
||||
DB2FileSystemSource mapSource((boost::filesystem::path("dbc") / locale / "Map.db2").string());
|
||||
if (mapDb2.Load(&mapSource, MapLoadInfo::Instance()))
|
||||
{
|
||||
for (uint32 x = 0; x < mapDb2.GetRecordCount(); ++x)
|
||||
{
|
||||
DB2Record record = mapDb2.GetRecord(x);
|
||||
mapData.emplace(std::piecewise_construct, std::forward_as_tuple(record.GetId()), std::forward_as_tuple());
|
||||
int16 parentMapId = int16(record.GetUInt16("ParentMapID"));
|
||||
if (parentMapId != -1)
|
||||
mapData[parentMapId].push_back(record.GetId());
|
||||
}
|
||||
}
|
||||
|
||||
return mapData;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Trinity::Banner::Show("MMAP generator", [](char const* text) { printf("%s\n", text); }, nullptr);
|
||||
@@ -302,25 +344,20 @@ int main(int argc, char** argv)
|
||||
if (!checkDirectories(debugOutput, dbcLocales))
|
||||
return silent ? -3 : finish("Press ENTER to close...", -3);
|
||||
|
||||
DB2FileLoader mapDb2;
|
||||
std::unordered_map<uint32, std::vector<uint32>> mapData;
|
||||
_liquidTypes = LoadLiquid(dbcLocales[0]);
|
||||
if (_liquidTypes.empty())
|
||||
return silent ? -5 : finish("Failed to load LiquidType.db2", -5);
|
||||
|
||||
std::unordered_map<uint32, std::vector<uint32>> mapData = LoadMap(dbcLocales[0]);
|
||||
if (mapData.empty())
|
||||
return silent ? -4 : finish("Failed to load Map.db2", -4);
|
||||
|
||||
static_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager())->InitializeThreadUnsafe(mapData);
|
||||
static_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager())->GetLiquidFlagsPtr = [](uint32 liquidId) -> uint32
|
||||
{
|
||||
DB2FileSystemSource mapSource((boost::filesystem::path("dbc") / dbcLocales[0] / "Map.db2").string());
|
||||
if (!mapDb2.Load(&mapSource, MapLoadInfo::Instance()))
|
||||
return silent ? -4 : finish("Failed to load Map.db2", -4);
|
||||
|
||||
for (uint32 x = 0; x < mapDb2.GetRecordCount(); ++x)
|
||||
{
|
||||
DB2Record record = mapDb2.GetRecord(x);
|
||||
|
||||
mapData.emplace(std::piecewise_construct, std::forward_as_tuple(record.GetId()), std::forward_as_tuple());
|
||||
int16 parentMapId = int16(record.GetUInt16("ParentMapID"));
|
||||
if (parentMapId != -1)
|
||||
mapData[parentMapId].push_back(record.GetId());
|
||||
}
|
||||
|
||||
static_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager())->InitializeThreadUnsafe(mapData);
|
||||
}
|
||||
auto itr = _liquidTypes.find(liquidId);
|
||||
return itr != _liquidTypes.end() ? (1 << itr->second) : 0;
|
||||
};
|
||||
|
||||
MapBuilder builder(maxAngle, skipLiquid, skipContinents, skipJunkMaps,
|
||||
skipBattlegrounds, debugOutput, bigBaseUnit, mapnum, offMeshInputPath);
|
||||
|
||||
@@ -425,11 +425,9 @@ namespace MMAP
|
||||
useLiquid = false;
|
||||
}
|
||||
else if ((liquidType & (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN)) != 0)
|
||||
liquidType = NAV_WATER;
|
||||
else if (liquidType & MAP_LIQUID_TYPE_MAGMA)
|
||||
liquidType = NAV_MAGMA;
|
||||
else if (liquidType & MAP_LIQUID_TYPE_SLIME)
|
||||
liquidType = NAV_SLIME;
|
||||
liquidType = NAV_AREA_WATER;
|
||||
else if ((liquidType & (MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)) != 0)
|
||||
liquidType = NAV_AREA_MAGMA_SLIME;
|
||||
else
|
||||
useLiquid = false;
|
||||
}
|
||||
@@ -716,22 +714,14 @@ 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)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
type = NAV_WATER;
|
||||
break;
|
||||
case 2:
|
||||
type = NAV_MAGMA;
|
||||
break;
|
||||
case 3:
|
||||
type = NAV_SLIME;
|
||||
break;
|
||||
}
|
||||
uint32 liquidFlags = vmapManager->GetLiquidFlagsPtr(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)
|
||||
type = NAV_AREA_MAGMA_SLIME;
|
||||
|
||||
// indexing is weird...
|
||||
// after a lot of trial and error, this is what works:
|
||||
|
||||
Reference in New Issue
Block a user