Tools/mmaps_generator: Give land priority during area merges over liquids
authorShauren <shauren.trinity@gmail.com>
Sat, 21 Apr 2018 23:01:48 +0000 (01:01 +0200)
committerShauren <shauren.trinity@gmail.com>
Sat, 21 Apr 2018 23:01:48 +0000 (01:01 +0200)
Closes #21700

src/common/Collision/Maps/MapDefines.h
src/common/Collision/Maps/TileAssembler.cpp
src/common/Collision/Maps/TileAssembler.h
src/server/game/Movement/PathGenerator.cpp
src/server/game/Movement/PathGenerator.h
src/tools/mmaps_generator/MapBuilder.cpp
src/tools/mmaps_generator/PathGenerator.cpp
src/tools/mmaps_generator/TerrainBuilder.cpp

index 84c5d9a010a060eda59b489a355d9d8032d1fd2b..4935e991259711cb1a10715a567246678f820e0f 100644 (file)
@@ -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 */
index e9203ca737875817560cb61742a09eadab38a7c1..8a17dcb14fae4ccee0374abe20a198b7b1684289 100644 (file)
@@ -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);
index 8c3b3f5b88dc7b04b11a3d7ac0d8725297b6c270..0a9f1f7f1a45d67d0c2d6bfede7cc35ddd6fb421 100644 (file)
@@ -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
index 86151360e900b1fce0474fe1c7d9caa4bd19d8d9..94561531a8f9bc160b7e2c56764f81afc8695190 100644 (file)
@@ -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;
     }
index 2884f8a12208f176a29c89896089a16db244bb1c..684537e7841b33423059930f88b610615c163a7e 100644 (file)
@@ -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();
 
index 279d1fe7afcf5d59953d3a4029b11ba5bdb1eba8..e569693a3173d144bf4c5d9a68e616a5d271bfa9 100644 (file)
@@ -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;
index 035bddd90633aa1378294fd3436229196b63b4df..185fe287848e53f3051e50ab543b28a6cca5f1ff 100644 (file)
 
 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;
-    {
-        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);
+    _liquidTypes = LoadLiquid(dbcLocales[0]);
+    if (_liquidTypes.empty())
+        return silent ? -5 : finish("Failed to load LiquidType.db2", -5);
 
-            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());
-        }
+    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())->InitializeThreadUnsafe(mapData);
+    static_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager())->GetLiquidFlagsPtr = [](uint32 liquidId) -> uint32
+    {
+        auto itr = _liquidTypes.find(liquidId);
+        return itr != _liquidTypes.end() ? (1 << itr->second) : 0;
+    };
 
     MapBuilder builder(maxAngle, skipLiquid, skipContinents, skipJunkMaps,
                        skipBattlegrounds, debugOutput, bigBaseUnit, mapnum, offMeshInputPath);
index 91ada500f97b68af3070ac8bccb1253ea1517b73..1921cb9af2dd47acc68561ff4d1fd92c8bedfcae 100644 (file)
@@ -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: