diff options
Diffstat (limited to 'src')
19 files changed, 332 insertions, 926 deletions
diff --git a/src/server/collision/Management/MMapFactory.cpp b/src/server/collision/Management/MMapFactory.cpp index 6aa71d77ed8..28a1caf14ba 100644 --- a/src/server/collision/Management/MMapFactory.cpp +++ b/src/server/collision/Management/MMapFactory.cpp @@ -25,14 +25,14 @@ namespace MMAP { // ######################## MMapFactory ######################## // our global singleton copy - MMapManager* g_MMapManager = NULL; + MMapManager* _manager = NULL; - MMapManager* MMapFactory::createOrGetMMapManager() + MMapManager* MMapFactory::CreateOrGetMMapManager() { - if (g_MMapManager == NULL) - g_MMapManager = new MMapManager(); + if (_manager == NULL) + _manager = new MMapManager(); - return g_MMapManager; + return _manager; } bool MMapFactory::IsPathfindingEnabled(uint32 mapId) @@ -41,12 +41,12 @@ namespace MMAP && !DisableMgr::IsDisabledFor(DISABLE_TYPE_MMAP, mapId, NULL, MMAP_DISABLE_PATHFINDING); } - void MMapFactory::clear() + void MMapFactory::Clear() { - if (g_MMapManager) + if (_manager) { - delete g_MMapManager; - g_MMapManager = NULL; + delete _manager; + _manager = NULL; } } }
\ No newline at end of file diff --git a/src/server/collision/Management/MMapFactory.h b/src/server/collision/Management/MMapFactory.h index 038d44a941c..c7e3283d22d 100644 --- a/src/server/collision/Management/MMapFactory.h +++ b/src/server/collision/Management/MMapFactory.h @@ -20,10 +20,6 @@ #define _MMAP_FACTORY_H #include "MMapManager.h" -#include "UnorderedMap.h" -#include "DetourAlloc.h" -#include "DetourNavMesh.h" -#include "DetourNavMeshQuery.h" namespace MMAP { @@ -40,8 +36,8 @@ namespace MMAP class MMapFactory { public: - static MMapManager* createOrGetMMapManager(); - static void clear(); + static MMapManager* CreateOrGetMMapManager(); + static void Clear(); static bool IsPathfindingEnabled(uint32 mapId); }; } diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp index 65c13c07e66..71867ff5554 100644 --- a/src/server/collision/Management/MMapManager.cpp +++ b/src/server/collision/Management/MMapManager.cpp @@ -22,32 +22,29 @@ namespace MMAP { - // ######################## MMapManager ######################## MMapManager::~MMapManager() { - for (MMapDataSet::iterator i = loadedMMaps.begin(); i != loadedMMaps.end(); ++i) + for (MMapDataSet::iterator i = _loadedMaps.begin(); i != _loadedMaps.end(); ++i) delete i->second; - - // by now we should not have maps loaded - // if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost! } - bool MMapManager::loadMapData(uint32 mapId) + bool MMapManager::LoadMap(uint32 mapId) { - // we already have this map loaded? - if (loadedMMaps.find(mapId) != loadedMMaps.end()) + // Do not load a map twice. + if (_loadedMaps.find(mapId) != _loadedMaps.end()) return true; // load and init dtNavMesh - read parameters from file - uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i.mmap")+1; - char *fileName = new char[pathLen]; - snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i.mmap").c_str(), mapId); + std::string basePath = sWorld->GetDataPath(); + uint32 pathLen = basePath.length() + strlen("mmaps/%03i.mmap") + 1; + char* fileName = new char[pathLen]; + snprintf(fileName, pathLen, (basePath + "mmaps/%03i.mmap").c_str(), mapId); FILE* file = fopen(fileName, "rb"); if (!file) { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName); - delete [] fileName; + TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP::LoadMap: Error: Could not open mmap file '%s'", fileName); + delete[] fileName; return false; } @@ -56,80 +53,75 @@ namespace MMAP fclose(file); if (count != 1) { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP:loadMapData: Error: Could not read params from file '%s'", fileName); - delete [] fileName; + TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP::LoadMap: Error: Could not read params from file '%s'", fileName); + delete[] fileName; return false; } dtNavMesh* mesh = dtAllocNavMesh(); - ASSERT(mesh); if (dtStatusFailed(mesh->init(¶ms))) { dtFreeNavMesh(mesh); - TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName); - delete [] fileName; + TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP::LoadMap: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName); + delete[] fileName; return false; } - delete [] fileName; + delete[] fileName; - TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP:loadMapData: Loaded %03i.mmap", mapId); + TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP::LoadMap: Loaded %03i.mmap", mapId); // store inside our map list - MMapData* mmap_data = new MMapData(mesh); - mmap_data->mmapLoadedTiles.clear(); + MMapData* mmapData = new MMapData(mesh); + mmapData->_loadedTiles.clear(); - loadedMMaps.insert(std::pair<uint32, MMapData*>(mapId, mmap_data)); + _loadedMaps.insert(std::pair<uint32, MMapData*>(mapId, mmapData)); return true; } - uint32 MMapManager::packTileID(int32 x, int32 y) - { - return uint32(x << 16 | y); - } - - bool MMapManager::loadMap(const std::string& /*basePath*/, uint32 mapId, int32 x, int32 y) + bool MMapManager::LoadMapTile(uint32 mapId, int32 x, int32 y) { // make sure the mmap is loaded and ready to load tiles - if (!loadMapData(mapId)) + if (!LoadMap(mapId)) return false; // get this mmap data - MMapData* mmap = loadedMMaps[mapId]; + MMapData* mmap = _loadedMaps[mapId]; ASSERT(mmap->navMesh); - // check if we already have this tile loaded - uint32 packedGridPos = packTileID(x, y); - if (mmap->mmapLoadedTiles.find(packedGridPos) != mmap->mmapLoadedTiles.end()) + // Check if we already have this tile loaded + uint32 pos = PackTileId(x, y); + if (mmap->_loadedTiles.find(pos) != mmap->_loadedTiles.end()) return false; - // load this tile :: mmaps/MMMXXYY.mmtile - uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1; - char *fileName = new char[pathLen]; + std::string basePath = sWorld->GetDataPath(); + uint32 pathLen = basePath.length() + strlen("mmaps/%03i%02i%02i.mmtile") + 1; + char* fileName = new char[pathLen]; - snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y); + snprintf(fileName, pathLen, (basePath + "mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y); FILE* file = fopen(fileName, "rb"); if (!file) { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP:loadMap: Could not open mmtile file '%s'", fileName); - delete [] fileName; + TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP::LoadMapTile: Could not open mmtile file '%s'", fileName); + delete[] fileName; return false; } - delete [] fileName; + + delete[] fileName; // read header MmapTileHeader fileHeader; if (fread(&fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || fileHeader.mmapMagic != MMAP_MAGIC) { - TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y); + TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP::LoadMapTile: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y); fclose(file); return false; } if (fileHeader.mmapVersion != MMAP_VERSION) { - TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", + TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP::LoadMapTile: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION); fclose(file); return false; @@ -139,9 +131,9 @@ namespace MMAP ASSERT(data); size_t result = fread(data, fileHeader.size, 1, file); - if (!result) + if (result != 1) { - TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y); + TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP::LoadMapTile: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y); fclose(file); return false; } @@ -154,14 +146,14 @@ namespace MMAP // memory allocated for data is now managed by detour, and will be deallocated when the tile is removed if (dtStatusSucceed(mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef))) { - mmap->mmapLoadedTiles.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef)); - ++loadedTiles; - TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP:loadMap: Loaded mmtile %03i[%02i, %02i] into %03i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y); + mmap->_loadedTiles.insert(std::pair<uint32, dtTileRef>(pos, tileRef)); + ++_loadedTiles; + TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP::LoadMapTile: Loaded mmtile %03i[%02i, %02i] into %03i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y); return true; } else { - TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y); + TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP::LoadMapTile: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y); dtFree(data); return false; } @@ -169,28 +161,26 @@ namespace MMAP return false; } - bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y) + bool MMapManager::UnloadMapTile(uint32 mapId, int32 x, int32 y) { - // check if we have this map loaded - if (loadedMMaps.find(mapId) == loadedMMaps.end()) + // Do not attempt to remove tiles from a not-loaded map + if (_loadedMaps.find(mapId) == _loadedMaps.end()) { - // file may not exist, therefore not loaded - TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, x, y); + TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP::UnloadMapTile: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, x, y); return false; } - MMapData* mmap = loadedMMaps[mapId]; + MMapData* mmap = _loadedMaps[mapId]; // check if we have this tile loaded - uint32 packedGridPos = packTileID(x, y); - if (mmap->mmapLoadedTiles.find(packedGridPos) == mmap->mmapLoadedTiles.end()) + uint32 pos = PackTileId(x, y); + if (mmap->_loadedTiles.find(pos) == mmap->_loadedTiles.end()) { - // file may not exist, therefore not loaded - TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y); + TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP::UnloadMapTile: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y); return false; } - dtTileRef tileRef = mmap->mmapLoadedTiles[packedGridPos]; + dtTileRef tileRef = mmap->_loadedTiles[pos]; // unload, and mark as non loaded if (dtStatusFailed(mmap->navMesh->removeTile(tileRef, NULL, NULL))) @@ -198,107 +188,106 @@ namespace MMAP // this is technically a memory leak // if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used // we cannot recover from this error - assert out - TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); + TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP::UnloadMapTile: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); ASSERT(false); } else { - mmap->mmapLoadedTiles.erase(packedGridPos); - --loadedTiles; - TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId); + mmap->_loadedTiles.erase(pos); + --_loadedTiles; + TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP::UnloadMapTile: Unloaded mmtile [%02i, %02i] from %03i", x, y, mapId); return true; } return false; } - bool MMapManager::unloadMap(uint32 mapId) + bool MMapManager::UnloadMap(uint32 mapId) { - if (loadedMMaps.find(mapId) == loadedMMaps.end()) + if (_loadedMaps.find(mapId) == _loadedMaps.end()) { // file may not exist, therefore not loaded - TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh map %03u", mapId); + TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP::UnloadMap: Asked to unload not loaded navmesh map %03u", mapId); return false; } // unload all tiles from given map - MMapData* mmap = loadedMMaps[mapId]; - for (MMapTileSet::iterator i = mmap->mmapLoadedTiles.begin(); i != mmap->mmapLoadedTiles.end(); ++i) + MMapData* mmap = _loadedMaps[mapId]; + for (MMapTileSet::iterator i = mmap->_loadedTiles.begin(); i != mmap->_loadedTiles.end(); ++i) { uint32 x = (i->first >> 16); uint32 y = (i->first & 0x0000FFFF); if (dtStatusFailed(mmap->navMesh->removeTile(i->second, NULL, NULL))) - TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); + TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP::UnloadMap: Could not unload %03u%02u%02u.mmtile from navmesh", mapId, x, y); else { - --loadedTiles; - TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId); + --_loadedTiles; + TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP::UnloadMap: Unloaded mmtile [%02u, %02u] from %03u", mapId, x, y, mapId); } } delete mmap; - loadedMMaps.erase(mapId); - TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP:unloadMap: Unloaded %03i.mmap", mapId); + _loadedMaps.erase(mapId); + TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP::UnloadMap: Unloaded %03u.mmap", mapId); return true; } - bool MMapManager::unloadMapInstance(uint32 mapId, uint32 instanceId) + bool MMapManager::UnloadMapInstance(uint32 mapId, uint32 instanceId) { // check if we have this map loaded - if (loadedMMaps.find(mapId) == loadedMMaps.end()) + if (_loadedMaps.find(mapId) == _loadedMaps.end()) { // file may not exist, therefore not loaded - TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId); + TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP::UnloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId); return false; } - MMapData* mmap = loadedMMaps[mapId]; - if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) + MMapData* mmap = _loadedMaps[mapId]; + if (mmap->_navMeshQueries.find(instanceId) == mmap->_navMeshQueries.end()) { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId); + TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP::UnloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId); return false; } - dtNavMeshQuery* query = mmap->navMeshQueries[instanceId]; + dtNavMeshQuery* query = mmap->_navMeshQueries[instanceId]; dtFreeNavMeshQuery(query); - mmap->navMeshQueries.erase(instanceId); - TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId); + mmap->_navMeshQueries.erase(instanceId); + TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP::UnloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId); return true; } dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId) { - if (loadedMMaps.find(mapId) == loadedMMaps.end()) + if (_loadedMaps.find(mapId) == _loadedMaps.end()) return NULL; - return loadedMMaps[mapId]->navMesh; + return _loadedMaps[mapId]->navMesh; } dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId) { - if (loadedMMaps.find(mapId) == loadedMMaps.end()) + if (_loadedMaps.find(mapId) == _loadedMaps.end()) return NULL; - MMapData* mmap = loadedMMaps[mapId]; - if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) + MMapData* mmap = _loadedMaps[mapId]; + if (mmap->_navMeshQueries.find(instanceId) == mmap->_navMeshQueries.end()) { // allocate mesh query dtNavMeshQuery* query = dtAllocNavMeshQuery(); - ASSERT(query); - if (dtStatusFailed(query->init(mmap->navMesh, 1024))) + if (dtStatusFailed(query->init(mmap->navMesh, 2048))) { dtFreeNavMeshQuery(query); - TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); + TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP::GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); return NULL; } TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); - mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query)); + mmap->_navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query)); } - return mmap->navMeshQueries[instanceId]; + return mmap->_navMeshQueries[instanceId]; } } diff --git a/src/server/collision/Management/MMapManager.h b/src/server/collision/Management/MMapManager.h index 56b1b856d65..c23c12f9a49 100644 --- a/src/server/collision/Management/MMapManager.h +++ b/src/server/collision/Management/MMapManager.h @@ -36,7 +36,7 @@ namespace MMAP MMapData(dtNavMesh* mesh) : navMesh(mesh) {} ~MMapData() { - for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i) + for (NavMeshQuerySet::iterator i = _navMeshQueries.begin(); i != _navMeshQueries.end(); ++i) dtFreeNavMeshQuery(i->second); if (navMesh) @@ -46,8 +46,8 @@ namespace MMAP dtNavMesh* navMesh; // we have to use single dtNavMeshQuery for every instance, since those are not thread safe - NavMeshQuerySet navMeshQueries; // instanceId to query - MMapTileSet mmapLoadedTiles; // maps [map grid coords] to [dtTile] + NavMeshQuerySet _navMeshQueries; // instanceId to query + MMapTileSet _loadedTiles; // maps [map grid coords] to [dtTile] }; @@ -58,26 +58,26 @@ namespace MMAP class MMapManager { public: - MMapManager() : loadedTiles(0) {} + MMapManager() : _loadedTiles(0) {} ~MMapManager(); - bool loadMap(const std::string& basePath, uint32 mapId, int32 x, int32 y); - bool unloadMap(uint32 mapId, int32 x, int32 y); - bool unloadMap(uint32 mapId); - bool unloadMapInstance(uint32 mapId, uint32 instanceId); + bool LoadMapTile(uint32 mapId, int32 x, int32 y); + bool UnloadMapTile(uint32 mapId, int32 x, int32 y); + bool UnloadMap(uint32 mapId); + bool UnloadMapInstance(uint32 mapId, uint32 instanceId); // the returned [dtNavMeshQuery const*] is NOT threadsafe dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId); dtNavMesh const* GetNavMesh(uint32 mapId); - uint32 getLoadedTilesCount() const { return loadedTiles; } - uint32 getLoadedMapsCount() const { return loadedMMaps.size(); } + uint32 GetLoadedTilesCount() const { return _loadedTiles; } + uint32 GetLoadedMapsCount() const { return _loadedMaps.size(); } private: - bool loadMapData(uint32 mapId); - uint32 packTileID(int32 x, int32 y); + bool LoadMap(uint32 mapId); + uint32 PackTileId(int32 x, int32 y) { return uint32(x << 16 | y); } - MMapDataSet loadedMMaps; - uint32 loadedTiles; + MMapDataSet _loadedMaps; + uint32 _loadedTiles; }; } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 4660489004d..aaeb06462ef 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -66,7 +66,9 @@ Map::~Map() if (!m_scriptSchedule.empty()) sScriptMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size()); - MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(GetId(), i_InstanceId); + MMAP::MMapManager* manager = MMAP::MMapFactory::CreateOrGetMMapManager(); + manager->UnloadMapInstance(GetId(), i_InstanceId); // Delete the dtNavMeshQuery + manager->UnloadMap(GetId()); // Unload the loaded tiles and delete the dtNavMesh } bool Map::ExistMap(uint32 mapid, int gx, int gy) @@ -119,12 +121,16 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy) void Map::LoadMMap(int gx, int gy) { - bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gx, gy); + bool mmapLoadResult = false; + if (GetEntry()->Instanceable()) + mmapLoadResult = MMAP::MMapFactory::CreateOrGetMMapManager()->LoadMapTile(GetId(), 0, 0); // Ignore the tile entry for instances, as they only have 1 tile. + else + mmapLoadResult = MMAP::MMapFactory::CreateOrGetMMapManager()->LoadMapTile(GetId(), gx, gy); if (mmapLoadResult) - TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); + TC_LOG_INFO(LOG_FILTER_MAPS, "MMAP loaded name: %s, id: %d, x: %d, y: %d", GetMapName(), GetId(), gx, gy); else - TC_LOG_INFO(LOG_FILTER_MAPS, "Could not load MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); + TC_LOG_INFO(LOG_FILTER_MAPS, "Could not load MMAP name: %s, id: %d, x: %d, y: %d", GetMapName(), GetId(), gx, gy); } void Map::LoadVMap(int gx, int gy) @@ -224,9 +230,9 @@ m_activeNonPlayersIter(m_activeNonPlayers.end()), i_gridExpiry(expiry), i_scriptLock(false) { m_parentMap = (_parent ? _parent : this); - for (unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx) + for (unsigned int idx = 0; idx < MAX_NUMBER_OF_GRIDS; ++idx) { - for (unsigned int j=0; j < MAX_NUMBER_OF_GRIDS; ++j) + for (unsigned int j = 0; j < MAX_NUMBER_OF_GRIDS; ++j) { //z code GridMaps[idx][j] =NULL; @@ -1009,7 +1015,7 @@ bool Map::UnloadGrid(NGridType& ngrid, bool unloadAll) delete GridMaps[gx][gy]; } VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gx, gy); - MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(GetId(), gx, gy); + MMAP::MMapFactory::CreateOrGetMMapManager()->UnloadMapTile(GetId(), gx, gy); } else ((MapInstanced*)m_parentMap)->RemoveGridMapReference(GridCoord(gx, gy)); diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp index 385683d66af..05c430c4d00 100644 --- a/src/server/game/Maps/MapInstanced.cpp +++ b/src/server/game/Maps/MapInstanced.cpp @@ -260,7 +260,7 @@ bool MapInstanced::DestroyInstance(InstancedMaps::iterator &itr) if (m_InstancedMaps.size() <= 1 && sWorld->getBoolConfig(CONFIG_GRID_UNLOAD)) { VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(itr->second->GetId()); - MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(itr->second->GetId()); + MMAP::MMapFactory::CreateOrGetMMapManager()->UnloadMap(itr->second->GetId()); // in that case, unload grids of the base map, too // so in the next map creation, (EnsureGridCreated actually) VMaps will be reloaded Map::UnloadAll(); diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index e561d37ed36..6ed0982e631 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -3541,7 +3541,7 @@ enum PartyResult }; const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP' -#define MMAP_VERSION 4 +#define MMAP_VERSION 3 struct MmapTileHeader { diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index ef24b112253..63b1cf283a4 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -86,7 +86,6 @@ bool ConfusedMovementGenerator<T>::DoUpdate(T* unit, uint32 diff) unit->MovePositionToFirstCollision(pos, dest, 0.0f); PathGenerator path(unit); - path.SetPathLengthLimit(30.0f); bool result = path.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ); if (!result || (path.GetPathType() & PATHFIND_NOPATH)) { diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index f78411fc547..1c65499fe50 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -44,7 +44,6 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T* owner) _getPoint(owner, x, y, z); PathGenerator path(owner); - path.SetPathLengthLimit(30.0f); bool result = path.CalculatePath(x, y, z); if (!result || (path.GetPathType() & PATHFIND_NOPATH)) { diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index c902eb850f6..c5922156939 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify @@ -28,17 +29,15 @@ ////////////////// PathGenerator ////////////////// PathGenerator::PathGenerator(const Unit* owner) : - _polyLength(0), _type(PATHFIND_BLANK), _useStraightPath(false), - _forceDestination(false), _pointPathLimit(MAX_POINT_PATH_LENGTH), - _endPosition(G3D::Vector3::zero()), _sourceUnit(owner), _navMesh(NULL), - _navMeshQuery(NULL) + _type(PATHFIND_BLANK), _endPosition(G3D::Vector3::zero()), + _sourceUnit(owner), _navMesh(NULL), _navMeshQuery(NULL) { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUIDLow()); + TC_LOG_DEBUG(LOG_FILTER_MAPS, "PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUIDLow()); uint32 mapId = _sourceUnit->GetMapId(); if (MMAP::MMapFactory::IsPathfindingEnabled(mapId)) { - MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); + MMAP::MMapManager* mmap = MMAP::MMapFactory::CreateOrGetMMapManager(); _navMesh = mmap->GetNavMesh(mapId); _navMeshQuery = mmap->GetNavMeshQuery(mapId, _sourceUnit->GetInstanceId()); } @@ -48,7 +47,7 @@ PathGenerator::PathGenerator(const Unit* owner) : PathGenerator::~PathGenerator() { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ PathGenerator::~PathGenerator() for %u \n", _sourceUnit->GetGUIDLow()); + TC_LOG_DEBUG(LOG_FILTER_MAPS, "PathGenerator::~PathGenerator() for %u \n", _sourceUnit->GetGUIDLow()); } bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool forceDest) @@ -65,463 +64,88 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo G3D::Vector3 start(x, y, z); SetStartPosition(start); - _forceDestination = forceDest; - - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ PathGenerator::CalculatePath() for %u \n", _sourceUnit->GetGUIDLow()); + TC_LOG_DEBUG(LOG_FILTER_MAPS, "PathGenerator::CalculatePath() for %u \n", _sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) - if (!_navMesh || !_navMeshQuery || _sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) || - !HaveTile(start) || !HaveTile(dest)) + if (!_navMesh || !_navMeshQuery || _sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING)) { - BuildShortcut(); _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } UpdateFilter(); - BuildPolyPath(start, dest); - return true; -} - -dtPolyRef PathGenerator::GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 polyPathSize, float const* point, float* distance) const -{ - if (!polyPath || !polyPathSize) - return INVALID_POLYREF; - - dtPolyRef nearestPoly = INVALID_POLYREF; - float minDist2d = FLT_MAX; - float minDist3d = 0.0f; + float startPos[3]; + startPos[0] = -y; + startPos[1] = z; + startPos[2] = -x; - for (uint32 i = 0; i < polyPathSize; ++i) - { - float closestPoint[VERTEX_SIZE]; - if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint))) - continue; - - float d = dtVdist2DSqr(point, closestPoint); - if (d < minDist2d) - { - minDist2d = d; - nearestPoly = polyPath[i]; - minDist3d = dtVdistSqr(point, closestPoint); - } + float endPos[3]; + endPos[0] = -destY; + endPos[1] = destZ; + endPos[2] = -destX; - if (minDist2d < 1.0f) // shortcut out - close enough for us - break; - } + float polyPickExt[3]; + polyPickExt[0] = 2.5f; + polyPickExt[1] = 2.5f; + polyPickExt[2] = 2.5f; - if (distance) - *distance = dtSqrt(minDist3d); + // + dtPolyRef startRef; + dtPolyRef endRef; - return (minDist2d < 3.0f) ? nearestPoly : INVALID_POLYREF; -} + float nearestPt[3]; -dtPolyRef PathGenerator::GetPolyByLocation(float const* point, float* distance) const -{ - // first we check the current path - // if the current path doesn't contain the current poly, - // we need to use the expensive navMesh.findNearestPoly - dtPolyRef polyRef = GetPathPolyByPosition(_pathPolyRefs, _polyLength, point, distance); - if (polyRef != INVALID_POLYREF) - return polyRef; + _navMeshQuery->findNearestPoly(startPos, polyPickExt, &_filter, &startRef, nearestPt); + _navMeshQuery->findNearestPoly(endPos, polyPickExt, &_filter, &endRef, nearestPt); - // we don't have it in our old path - // try to get it by findNearestPoly() - // first try with low search box - float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; // bounds of poly search area - float closestPoint[VERTEX_SIZE] = {0.0f, 0.0f, 0.0f}; - if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF) + if (!startRef || !endRef) { - *distance = dtVdist(closestPoint, point); - return polyRef; - } - - // still nothing .. - // try with bigger search box - // Note that the extent should not overlap more than 128 polygons in the navmesh (see dtNavMeshQuery::findNearestPoly) - extents[1] = 50.0f; - - if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF) - { - *distance = dtVdist(closestPoint, point); - return polyRef; - } - - return INVALID_POLYREF; -} - -void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos) -{ - // *** getting start/end poly logic *** - - float distToStartPoly, distToEndPoly; - float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x}; - float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x}; - - dtPolyRef startPoly = GetPolyByLocation(startPoint, &distToStartPoly); - dtPolyRef endPoly = GetPolyByLocation(endPoint, &distToEndPoly); - - // we have a hole in our mesh - // make shortcut path and mark it as NOPATH ( with flying and swimming exception ) - // its up to caller how he will use this info - if (startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF) - { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n"); - BuildShortcut(); - bool path = _sourceUnit->GetTypeId() == TYPEID_UNIT && _sourceUnit->ToCreature()->CanFly(); - - bool waterPath = _sourceUnit->GetTypeId() == TYPEID_UNIT && _sourceUnit->ToCreature()->CanSwim(); - if (waterPath) - { - // 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) - { - ZLiquidStatus status = _sourceUnit->GetBaseMap()->getLiquidStatus(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, MAP_ALL_LIQUIDS, NULL); - // One of the points is not in the water, cancel movement. - if (status == LIQUID_MAP_NO_WATER) - { - waterPath = false; - break; - } - } - } - - _type = (path || waterPath) ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; - return; - } - - // we may need a better number here - bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f); - if (farFromPoly) - { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly); - - bool buildShotrcut = false; - if (_sourceUnit->GetTypeId() == TYPEID_UNIT) - { - Creature* owner = (Creature*)_sourceUnit; - - G3D::Vector3 const& p = (distToStartPoly > 7.0f) ? startPos : endPos; - if (_sourceUnit->GetBaseMap()->IsUnderWater(p.x, p.y, p.z)) - { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ BuildPolyPath :: underWater case\n"); - if (owner->CanSwim()) - buildShotrcut = true; - } - else - { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ BuildPolyPath :: flying case\n"); - if (owner->CanFly()) - buildShotrcut = true; - } - } - - if (buildShotrcut) - { - BuildShortcut(); - _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); - return; - } - else - { - float closestPoint[VERTEX_SIZE]; - // we may want to use closestPointOnPolyBoundary instead - if (dtStatusSucceed(_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint))) - { - dtVcopy(endPoint, closestPoint); - SetActualEndPosition(G3D::Vector3(endPoint[2], endPoint[0], endPoint[1])); - } - - _type = PATHFIND_INCOMPLETE; - } - } - - // *** poly path generating logic *** - - // start and end are on same polygon - // just need to move in straight line - if (startPoly == endPoly) - { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPoly == endPoly)\n"); - - BuildShortcut(); - - _pathPolyRefs[0] = startPoly; - _polyLength = 1; - - _type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL; - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ BuildPolyPath :: path type %d\n", _type); - return; - } - - // look for startPoly/endPoly in current path - /// @todo we can merge it with getPathPolyByPosition() loop - bool startPolyFound = false; - bool endPolyFound = false; - uint32 pathStartIndex = 0; - uint32 pathEndIndex = 0; - - if (_polyLength) - { - for (; pathStartIndex < _polyLength; ++pathStartIndex) - { - // here to carch few bugs - ASSERT(_pathPolyRefs[pathStartIndex] != INVALID_POLYREF); - - if (_pathPolyRefs[pathStartIndex] == startPoly) - { - startPolyFound = true; - break; - } - } - - for (pathEndIndex = _polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex) - if (_pathPolyRefs[pathEndIndex] == endPoly) - { - endPolyFound = true; - break; - } - } - - if (startPolyFound && endPolyFound) - { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPolyFound && endPolyFound)\n"); - - // we moved along the path and the target did not move out of our old poly-path - // our path is a simple subpath case, we have all the data we need - // just "cut" it out - - _polyLength = pathEndIndex - pathStartIndex + 1; - memmove(_pathPolyRefs, _pathPolyRefs + pathStartIndex, _polyLength * sizeof(dtPolyRef)); + TC_LOG_DEBUG(LOG_FILTER_MAPS, "PathGenerator::CalculatePath() for %u no polygons found for start and end locations\n", _sourceUnit->GetGUIDLow()); + _type = PATHFIND_NOPATH; + return false; } - else if (startPolyFound && !endPolyFound) - { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPolyFound && !endPolyFound)\n"); - - // we are moving on the old path but target moved out - // so we have atleast part of poly-path ready - - _polyLength -= pathStartIndex; - // try to adjust the suffix of the path instead of recalculating entire length - // at given interval the target cannot get too far from its last location - // thus we have less poly to cover - // sub-path of optimal path is optimal - - // take ~80% of the original length - /// @todo play with the values here - uint32 prefixPolyLength = uint32(_polyLength * 0.8f + 0.5f); - memmove(_pathPolyRefs, _pathPolyRefs+pathStartIndex, prefixPolyLength * sizeof(dtPolyRef)); - - dtPolyRef suffixStartPoly = _pathPolyRefs[prefixPolyLength-1]; - - // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data - float suffixEndPoint[VERTEX_SIZE]; - if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint))) - { - // we can hit offmesh connection as last poly - closestPointOnPoly() don't like that - // try to recover by using prev polyref - --prefixPolyLength; - suffixStartPoly = _pathPolyRefs[prefixPolyLength-1]; - if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint))) - { - // suffixStartPoly is still invalid, error state - BuildShortcut(); - _type = PATHFIND_NOPATH; - return; - } - } - - // generate suffix - uint32 suffixPolyLength = 0; - dtStatus dtResult = _navMeshQuery->findPath( - suffixStartPoly, // start polygon - endPoly, // end polygon - suffixEndPoint, // start position - endPoint, // end position - &_filter, // polygon search filter - _pathPolyRefs + prefixPolyLength - 1, // [out] path - (int*)&suffixPolyLength, - MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path - - if (!suffixPolyLength || dtStatusFailed(dtResult)) - { - // this is probably an error state, but we'll leave it - // and hopefully recover on the next Update - // we still need to copy our preffix - TC_LOG_ERROR(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", _sourceUnit->GetGUIDLow()); - } - - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n", _polyLength, prefixPolyLength, suffixPolyLength); - - // new path = prefix + suffix - overlap - _polyLength = prefixPolyLength + suffixPolyLength - 1; - } - else + int hops; + dtPolyRef* hopBuffer = new dtPolyRef[8192]; + dtStatus status = _navMeshQuery->findPath(startRef, endRef, startPos, endPos, &_filter, hopBuffer, &hops, 8192); + + if (!dtStatusSucceed(status)) { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ BuildPolyPath :: (!startPolyFound && !endPolyFound)\n"); - - // either we have no path at all -> first run - // or something went really wrong -> we aren't moving along the path to the target - // just generate new path - - // free and invalidate old path data - Clear(); - - dtStatus dtResult = _navMeshQuery->findPath( - startPoly, // start polygon - endPoly, // end polygon - startPoint, // start position - endPoint, // end position - &_filter, // polygon search filter - _pathPolyRefs, // [out] path - (int*)&_polyLength, - MAX_PATH_LENGTH); // max number of polygons in output path - - if (!_polyLength || dtStatusFailed(dtResult)) - { - // only happens if we passed bad data to findPath(), or navmesh is messed up - TC_LOG_ERROR(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", _sourceUnit->GetGUIDLow()); - BuildShortcut(); - _type = PATHFIND_NOPATH; - return; - } + TC_LOG_DEBUG(LOG_FILTER_MAPS, "PathGenerator::CalculatePath() for %u no path found for start and end locations\n", _sourceUnit->GetGUIDLow()); + _type = PATHFIND_NOPATH; + return false; } - // by now we know what type of path we can get - if (_pathPolyRefs[_polyLength - 1] == endPoly && !(_type & PATHFIND_INCOMPLETE)) - _type = PATHFIND_NORMAL; - else - _type = PATHFIND_INCOMPLETE; - - // generate the point-path out of our up-to-date poly-path - BuildPointPath(startPoint, endPoint); -} - -void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoint) -{ - float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE]; - uint32 pointCount = 0; - dtStatus dtResult = DT_FAILURE; - if (_useStraightPath) - { - dtResult = _navMeshQuery->findStraightPath( - startPoint, // start position - endPoint, // end position - _pathPolyRefs, // current path - _polyLength, // lenth of current path - pathPoints, // [out] path corner points - NULL, // [out] flags - NULL, // [out] shortened path - (int*)&pointCount, - _pointPathLimit); // maximum number of points/polygons to use - } - else - { - dtResult = FindSmoothPath( - startPoint, // start position - endPoint, // end position - _pathPolyRefs, // current path - _polyLength, // length of current path - pathPoints, // [out] path corner points - (int*)&pointCount, - _pointPathLimit); // maximum number of points - } + int resultHopCount; + float* straightPath = new float[2048 * 3]; + unsigned char* pathFlags = new unsigned char[2048]; + dtPolyRef* pathRefs = new dtPolyRef[2048]; - if (pointCount < 2 || dtStatusFailed(dtResult)) + status = _navMeshQuery->findStraightPath(startPos, endPos, hopBuffer, hops, straightPath, pathFlags, pathRefs, &resultHopCount, 2048); + if (!dtStatusSucceed(status)) { - // only happens if pass bad data to findStraightPath or navmesh is broken - // single point paths can be generated here - /// @todo check the exact cases - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ PathGenerator::BuildPointPath FAILED! path sized %d returned\n", pointCount); - BuildShortcut(); + TC_LOG_DEBUG(LOG_FILTER_MAPS, "PathGenerator::CalculatePath() for %u no straight path found for start and end locations\n", _sourceUnit->GetGUIDLow()); _type = PATHFIND_NOPATH; - return; - } - else if (pointCount == _pointPathLimit) - { - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ PathGenerator::BuildPointPath FAILED! path sized %d returned, lower than limit set to %d\n", pointCount, _pointPathLimit); - BuildShortcut(); - _type = PATHFIND_SHORT; - return; + return false; } - _pathPoints.resize(pointCount); - for (uint32 i = 0; i < pointCount; ++i) - _pathPoints[i] = G3D::Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); + for (uint32 i = 0; i < resultHopCount; ++i) + _pathPoints.push_back(G3D::Vector3(-straightPath[i * 3 + 2], -straightPath[i * 3 + 0], straightPath[i * 3 + 1])); - NormalizePath(); - - // first point is always our current location - we need the next one - SetActualEndPosition(_pathPoints[pointCount-1]); - - // force the given destination, if needed - if (_forceDestination && - (!(_type & PATHFIND_NORMAL) || !InRange(GetEndPosition(), GetActualEndPosition(), 1.0f, 1.0f))) - { - // we may want to keep partial subpath - if (Dist3DSqr(GetActualEndPosition(), GetEndPosition()) < 0.3f * Dist3DSqr(GetStartPosition(), GetEndPosition())) - { - SetActualEndPosition(GetEndPosition()); - _pathPoints[_pathPoints.size()-1] = GetEndPosition(); - } - else - { - SetActualEndPosition(GetEndPosition()); - BuildShortcut(); - } - - _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); - } - - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ PathGenerator::BuildPointPath path type %d size %d poly-size %d\n", _type, pointCount, _polyLength); -} - -void PathGenerator::NormalizePath() -{ - for (uint32 i = 0; i < _pathPoints.size(); ++i) - _sourceUnit->UpdateAllowedPositionZ(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z); -} - -void PathGenerator::BuildShortcut() -{ - TC_LOG_DEBUG(LOG_FILTER_MAPS, "++ BuildShortcut :: making shortcut\n"); - - Clear(); - - // make two point path, our curr pos is the start, and dest is the end - _pathPoints.resize(2); - - // set start and a default next position - _pathPoints[0] = GetStartPosition(); - _pathPoints[1] = GetActualEndPosition(); - - NormalizePath(); - - _type = PATHFIND_SHORTCUT; + return true; } void PathGenerator::CreateFilter() { - uint16 includeFlags = 0; + uint16 includeFlags = 1 | 2; uint16 excludeFlags = 0; - - if (_sourceUnit->GetTypeId() == TYPEID_UNIT) - { - Creature* creature = (Creature*)_sourceUnit; - if (creature->CanWalk()) - includeFlags |= NAV_GROUND; // walk - - // creatures don't take environmental damage - if (creature->CanSwim()) - includeFlags |= (NAV_WATER | NAV_MAGMA | NAV_SLIME); // swim - } - else // assume Player + + if (_sourceUnit->GetTypeId() == TYPEID_UNIT && !_sourceUnit->ToCreature()->CanSwim()) { - // perfect support not possible, just stay 'safe' - includeFlags |= (NAV_GROUND | NAV_WATER | NAV_MAGMA | NAV_SLIME); + includeFlags = 1; + excludeFlags = 2; } _filter.setIncludeFlags(includeFlags); @@ -532,275 +156,5 @@ void PathGenerator::CreateFilter() void PathGenerator::UpdateFilter() { - // allow creatures to cheat and use different movement types if they are moved - // forcefully into terrain they can't normally move in - if (_sourceUnit->IsInWater() || _sourceUnit->IsUnderWater()) - { - uint16 includedFlags = _filter.getIncludeFlags(); - includedFlags |= GetNavTerrain(_sourceUnit->GetPositionX(), - _sourceUnit->GetPositionY(), - _sourceUnit->GetPositionZ()); - - _filter.setIncludeFlags(includedFlags); - } -} - -NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) -{ - LiquidData data; - ZLiquidStatus liquidStatus = _sourceUnit->GetBaseMap()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data); - if (liquidStatus == LIQUID_MAP_NO_WATER) - return NAV_GROUND; - - switch (data.type_flags) - { - case MAP_LIQUID_TYPE_WATER: - case MAP_LIQUID_TYPE_OCEAN: - return NAV_WATER; - case MAP_LIQUID_TYPE_MAGMA: - return NAV_MAGMA; - case MAP_LIQUID_TYPE_SLIME: - return NAV_SLIME; - default: - return NAV_GROUND; - } -} - -bool PathGenerator::HaveTile(const G3D::Vector3& p) const -{ - int tx = -1, ty = -1; - float point[VERTEX_SIZE] = {p.y, p.z, p.x}; - - _navMesh->calcTileLoc(point, &tx, &ty); - - /// Workaround - /// For some reason, often the tx and ty variables wont get a valid value - /// Use this check to prevent getting negative tile coords and crashing on getTileAt - if (tx < 0 || ty < 0) - return false; - - return (_navMesh->getTileAt(tx, ty, 0) != NULL); -} - -uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited) -{ - int32 furthestPath = -1; - int32 furthestVisited = -1; - - // Find furthest common polygon. - for (int32 i = npath-1; i >= 0; --i) - { - bool found = false; - for (int32 j = nvisited-1; j >= 0; --j) - { - if (path[i] == visited[j]) - { - furthestPath = i; - furthestVisited = j; - found = true; - } - } - if (found) - break; - } - - // If no intersection found just return current path. - if (furthestPath == -1 || furthestVisited == -1) - return npath; - - // Concatenate paths. - - // Adjust beginning of the buffer to include the visited. - uint32 req = nvisited - furthestVisited; - uint32 orig = uint32(furthestPath + 1) < npath ? furthestPath + 1 : npath; - uint32 size = npath > orig ? npath - orig : 0; - if (req + size > maxPath) - size = maxPath-req; - - if (size) - memmove(path + req, path + orig, size * sizeof(dtPolyRef)); - - // Store visited - for (uint32 i = 0; i < req; ++i) - path[i] = visited[(nvisited - 1) - i]; - - return req+size; -} - -bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos, - float minTargetDist, dtPolyRef const* path, uint32 pathSize, - float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef) -{ - // Find steer target. - static const uint32 MAX_STEER_POINTS = 3; - float steerPath[MAX_STEER_POINTS*VERTEX_SIZE]; - unsigned char steerPathFlags[MAX_STEER_POINTS]; - dtPolyRef steerPathPolys[MAX_STEER_POINTS]; - uint32 nsteerPath = 0; - dtStatus dtResult = _navMeshQuery->findStraightPath(startPos, endPos, path, pathSize, - steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS); - if (!nsteerPath || dtStatusFailed(dtResult)) - return false; - - // Find vertex far enough to steer to. - uint32 ns = 0; - while (ns < nsteerPath) - { - // Stop at Off-Mesh link or when point is further than slop away. - if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) || - !InRangeYZX(&steerPath[ns*VERTEX_SIZE], startPos, minTargetDist, 1000.0f)) - break; - ns++; - } - // Failed to find good point to steer to. - if (ns >= nsteerPath) - return false; - - dtVcopy(steerPos, &steerPath[ns*VERTEX_SIZE]); - steerPos[1] = startPos[1]; // keep Z value - steerPosFlag = steerPathFlags[ns]; - steerPosRef = steerPathPolys[ns]; - - return true; -} - -dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPos, - dtPolyRef const* polyPath, uint32 polyPathSize, - float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize) -{ - *smoothPathSize = 0; - uint32 nsmoothPath = 0; - - dtPolyRef polys[MAX_PATH_LENGTH]; - memcpy(polys, polyPath, sizeof(dtPolyRef)*polyPathSize); - uint32 npolys = polyPathSize; - - float iterPos[VERTEX_SIZE], targetPos[VERTEX_SIZE]; - if (dtStatusFailed(_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos))) - return DT_FAILURE; - - if (dtStatusFailed(_navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos))) - return DT_FAILURE; - - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); - nsmoothPath++; - - // Move towards target a small advancement at a time until target reached or - // when ran out of memory to store the path. - while (npolys && nsmoothPath < maxSmoothPathSize) - { - // Find location to steer towards. - float steerPos[VERTEX_SIZE]; - unsigned char steerPosFlag; - dtPolyRef steerPosRef = INVALID_POLYREF; - - if (!GetSteerTarget(iterPos, targetPos, SMOOTH_PATH_SLOP, polys, npolys, steerPos, steerPosFlag, steerPosRef)) - break; - - bool endOfPath = (steerPosFlag & DT_STRAIGHTPATH_END); - bool offMeshConnection = (steerPosFlag & DT_STRAIGHTPATH_OFFMESH_CONNECTION); - - // Find movement delta. - float delta[VERTEX_SIZE]; - dtVsub(delta, steerPos, iterPos); - float len = dtSqrt(dtVdot(delta, delta)); - // If the steer target is end of path or off-mesh link, do not move past the location. - if ((endOfPath || offMeshConnection) && len < SMOOTH_PATH_STEP_SIZE) - len = 1.0f; - else - len = SMOOTH_PATH_STEP_SIZE / len; - - float moveTgt[VERTEX_SIZE]; - dtVmad(moveTgt, iterPos, delta, len); - - // Move - float result[VERTEX_SIZE]; - const static uint32 MAX_VISIT_POLY = 16; - dtPolyRef visited[MAX_VISIT_POLY]; - - uint32 nvisited = 0; - _navMeshQuery->moveAlongSurface(polys[0], iterPos, moveTgt, &_filter, result, visited, (int*)&nvisited, MAX_VISIT_POLY); - npolys = FixupCorridor(polys, npolys, MAX_PATH_LENGTH, visited, nvisited); - - _navMeshQuery->getPolyHeight(polys[0], result, &result[1]); - result[1] += 0.5f; - dtVcopy(iterPos, result); - - // Handle end of path and off-mesh links when close enough. - if (endOfPath && InRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) - { - // Reached end of path. - dtVcopy(iterPos, targetPos); - if (nsmoothPath < maxSmoothPathSize) - { - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); - nsmoothPath++; - } - break; - } - else if (offMeshConnection && InRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) - { - // Advance the path up to and over the off-mesh connection. - dtPolyRef prevRef = INVALID_POLYREF; - dtPolyRef polyRef = polys[0]; - uint32 npos = 0; - while (npos < npolys && polyRef != steerPosRef) - { - prevRef = polyRef; - polyRef = polys[npos]; - npos++; - } - - for (uint32 i = npos; i < npolys; ++i) - polys[i-npos] = polys[i]; - - npolys -= npos; - - // Handle the connection. - float startPos[VERTEX_SIZE], endPos[VERTEX_SIZE]; - if (dtStatusSucceed(_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos))) - { - if (nsmoothPath < maxSmoothPathSize) - { - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos); - nsmoothPath++; - } - // Move position at the other side of the off-mesh link. - dtVcopy(iterPos, endPos); - _navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]); - iterPos[1] += 0.5f; - } - } - - // Store results. - if (nsmoothPath < maxSmoothPathSize) - { - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); - nsmoothPath++; - } - } - - *smoothPathSize = nsmoothPath; - - // this is most likely a loop - return nsmoothPath < MAX_POINT_PATH_LENGTH ? DT_SUCCESS : DT_FAILURE; -} - -bool PathGenerator::InRangeYZX(const float* v1, const float* v2, float r, float h) const -{ - const float dx = v2[0] - v1[0]; - const float dy = v2[1] - v1[1]; // elevation - const float dz = v2[2] - v1[2]; - return (dx * dx + dz * dz) < r * r && fabsf(dy) < h; -} - -bool PathGenerator::InRange(G3D::Vector3 const& p1, G3D::Vector3 const& p2, float r, float h) const -{ - G3D::Vector3 d = p1 - p2; - return (d.x * d.x + d.y * d.y) < r * r && fabsf(d.z) < h; -} - -float PathGenerator::Dist3DSqr(G3D::Vector3 const& p1, G3D::Vector3 const& p2) const -{ - return (p1 - p2).squaredLength(); -} + +}
\ No newline at end of file diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h index ac66b7cec57..507f8e8defb 100644 --- a/src/server/game/Movement/PathGenerator.h +++ b/src/server/game/Movement/PathGenerator.h @@ -26,18 +26,6 @@ class Unit; -// 74*4.0f=296y number_of_points*interval = max_path_len -// this is way more than actual evade range -// I think we can safely cut those down even more -#define MAX_PATH_LENGTH 74 -#define MAX_POINT_PATH_LENGTH 74 - -#define SMOOTH_PATH_STEP_SIZE 4.0f -#define SMOOTH_PATH_SLOP 0.3f - -#define VERTEX_SIZE 3 -#define INVALID_POLYREF 0 - enum PathType { PATHFIND_BLANK = 0x00, // path not built yet @@ -59,10 +47,6 @@ class PathGenerator // return: true if new path was calculated, false otherwise (no change needed) bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false); - // option setters - use optional - void SetUseStraightPath(bool useStraightPath) { _useStraightPath = useStraightPath; } - void SetPathLengthLimit(float distance) { _pointPathLimit = std::min<uint32>(uint32(distance/SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); } - // result getters G3D::Vector3 const& GetStartPosition() const { return _startPosition; } G3D::Vector3 const& GetEndPosition() const { return _endPosition; } @@ -73,17 +57,9 @@ class PathGenerator PathType GetPathType() const { return _type; } private: - - dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references - uint32 _polyLength; // number of polygons in the path - Movement::PointsArray _pathPoints; // our actual (x,y,z) path to the target PathType _type; // tells what kind of path this is - bool _useStraightPath; // type of path will be generated - bool _forceDestination; // when set, we will always arrive at given point - uint32 _pointPathLimit; // limit point path size; min(this, MAX_POINT_PATH_LENGTH) - G3D::Vector3 _startPosition; // {x, y, z} of current location G3D::Vector3 _endPosition; // {x, y, z} of the destination G3D::Vector3 _actualEndPosition; // {x, y, z} of the closest possible point to given destination @@ -97,37 +73,9 @@ class PathGenerator void SetStartPosition(G3D::Vector3 const& point) { _startPosition = point; } void SetEndPosition(G3D::Vector3 const& point) { _actualEndPosition = point; _endPosition = point; } void SetActualEndPosition(G3D::Vector3 const& point) { _actualEndPosition = point; } - void NormalizePath(); - - void Clear() - { - _polyLength = 0; - _pathPoints.clear(); - } - - bool InRange(G3D::Vector3 const& p1, G3D::Vector3 const& p2, float r, float h) const; - float Dist3DSqr(G3D::Vector3 const& p1, G3D::Vector3 const& p2) const; - bool InRangeYZX(float const* v1, float const* v2, float r, float h) const; - dtPolyRef GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 polyPathSize, float const* Point, float* Distance = NULL) const; - dtPolyRef GetPolyByLocation(float const* Point, float* Distance) const; - bool HaveTile(G3D::Vector3 const& p) const; - - void BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos); - void BuildPointPath(float const* startPoint, float const* endPoint); - void BuildShortcut(); - - NavTerrain GetNavTerrain(float x, float y, float z); void CreateFilter(); void UpdateFilter(); - - // smooth path aux functions - uint32 FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited); - bool GetSteerTarget(float const* startPos, float const* endPos, float minTargetDist, dtPolyRef const* path, uint32 pathSize, float* steerPos, - unsigned char& steerPosFlag, dtPolyRef& steerPosRef); - dtStatus FindSmoothPath(float const* startPos, float const* endPos, - dtPolyRef const* polyPath, uint32 polyPathSize, - float* smoothPath, int* smoothPathSize, uint32 smoothPathMaxSize); }; #endif diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index b2e8a89c86d..804a7f25a12 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5162,7 +5162,6 @@ SpellCastResult Spell::CheckCast(bool strict) target->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); target->GetFirstCollisionPosition(pos, CONTACT_DISTANCE, target->GetRelativeAngle(m_caster)); - m_preGeneratedPath.SetPathLengthLimit(m_spellInfo->GetMaxRange(true) * 1.5f); bool result = m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize()); if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 8ca2e1db56e..d3258aa3401 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -137,7 +137,7 @@ World::~World() delete command; VMAP::VMapFactory::clear(); - MMAP::MMapFactory::clear(); + MMAP::MMapFactory::Clear(); /// @todo free addSessQueue } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 3d531cee1f5..9db75fb5477 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -187,7 +187,7 @@ public: uint32 haveMap = Map::ExistMap(mapId, gridX, gridY) ? 1 : 0; uint32 haveVMap = Map::ExistVMap(mapId, gridX, gridY) ? 1 : 0; - uint32 haveMMap = (MMAP::MMapFactory::IsPathfindingEnabled(mapId) && MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) ? 1 : 0; + uint32 haveMMap = (MMAP::MMapFactory::IsPathfindingEnabled(mapId) && MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) ? 1 : 0; if (haveVMap) { diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 690988ebac1..0beb10af4fc 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -35,6 +35,7 @@ #include "GridNotifiers.h" #include "GridNotifiersImpl.h" #include "CellImpl.h" +#include "MMapManager.h" class mmaps_commandscript : public CommandScript { @@ -63,7 +64,7 @@ public: static bool HandleMmapPathCommand(ChatHandler* handler, char const* args) { - if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) + if (!MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) { handler->PSendSysMessage("NavMesh not loaded for current map."); return true; @@ -91,10 +92,10 @@ public: player->GetPosition(x, y, z); // path - PathGenerator path(target); + /*PathGenerator path(target); path.SetUseStraightPath(useStraightPath); bool result = path.CalculatePath(x, y, z); - + Movement::PointsArray const& pointPath = path.GetPath(); handler->PSendSysMessage("%s's path to %s:", target->GetName().c_str(), player->GetName().c_str()); handler->PSendSysMessage("Building: %s", useStraightPath ? "StraightPath" : "SmoothPath"); @@ -107,13 +108,63 @@ public: handler->PSendSysMessage("StartPosition (%.3f, %.3f, %.3f)", start.x, start.y, start.z); handler->PSendSysMessage("EndPosition (%.3f, %.3f, %.3f)", end.x, end.y, end.z); handler->PSendSysMessage("ActualEndPosition (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z); + */ + float m_spos[3]; + m_spos[0] = -y; + m_spos[1] = z; + m_spos[2] = -x; + + // + float m_epos[3]; + m_epos[0] = -target->GetPositionY(); + m_epos[1] = target->GetPositionZ(); + m_epos[2] = -target->GetPositionX(); + + // + dtQueryFilter m_filter; + m_filter.setIncludeFlags(3); + m_filter.setExcludeFlags(2); + + // + float m_polyPickExt[3]; + m_polyPickExt[0] = 2.5f; + m_polyPickExt[1] = 2.5f; + m_polyPickExt[2] = 2.5f; + + // + dtPolyRef m_startRef; + dtPolyRef m_endRef; + + const dtNavMesh* navMesh = MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMesh(player->GetMapId()); + const dtNavMeshQuery* navMeshQuery = MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMeshQuery(player->GetMapId(), handler->GetSession()->GetPlayer()->GetInstanceId()); + + float nearestPt[3]; + + navMeshQuery->findNearestPoly(m_spos, m_polyPickExt, &m_filter, &m_startRef, nearestPt); + navMeshQuery->findNearestPoly(m_epos, m_polyPickExt, &m_filter, &m_endRef, nearestPt); + + if ( !m_startRef || !m_endRef ) + { + std::cerr << "Could not find any nearby poly's (" << m_startRef << "," << m_endRef << ")" << std::endl; + return 0; + } + + int hops; + dtPolyRef* hopBuffer = new dtPolyRef[8192]; + dtStatus status = navMeshQuery->findPath(m_startRef, m_endRef, m_spos, m_epos, &m_filter, hopBuffer, &hops, 8192); + + int resultHopCount; + float* straightPath = new float[2048*3]; + unsigned char* pathFlags = new unsigned char[2048]; + dtPolyRef* pathRefs = new dtPolyRef[2048]; + + status = navMeshQuery->findStraightPath(m_spos, m_epos, hopBuffer, hops, straightPath, pathFlags, pathRefs, &resultHopCount, 2048); + for (uint32 i = 0; i < resultHopCount; ++i) + player->SummonCreature(VISUAL_WAYPOINT, -straightPath[i * 3 + 2], -straightPath[i * 3 + 0], straightPath[i * 3 + 1], 0, TEMPSUMMON_TIMED_DESPAWN, 9000); if (!player->IsGameMaster()) handler->PSendSysMessage("Enable GM mode to see the path points."); - for (uint32 i = 0; i < pointPath.size(); ++i) - player->SummonCreature(VISUAL_WAYPOINT, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000); - return true; } @@ -131,8 +182,8 @@ public: handler->PSendSysMessage("gridloc [%i, %i]", gx, gy); // calculate navmesh tile location - dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()); - dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(handler->GetSession()->GetPlayer()->GetMapId(), player->GetInstanceId()); + dtNavMesh const* navmesh = MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()); + dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMeshQuery(handler->GetSession()->GetPlayer()->GetMapId(), player->GetInstanceId()); if (!navmesh || !navmeshquery) { handler->PSendSysMessage("NavMesh not loaded for current map."); @@ -142,8 +193,8 @@ public: float const* min = navmesh->getParams()->orig; float x, y, z; player->GetPosition(x, y, z); - float location[VERTEX_SIZE] = {y, z, x}; - float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; + float location[] = {y, z, x}; + float extents[] = {3.0f, 5.0f, 3.0f}; int32 tilex = int32((y - min[0]) / SIZE_OF_GRIDS); int32 tiley = int32((x - min[2]) / SIZE_OF_GRIDS); @@ -152,14 +203,14 @@ public: // navmesh poly -> navmesh tile location dtQueryFilter filter = dtQueryFilter(); - dtPolyRef polyRef = INVALID_POLYREF; + dtPolyRef polyRef = 0; if (dtStatusFailed(navmeshquery->findNearestPoly(location, extents, &filter, &polyRef, NULL))) { handler->PSendSysMessage("Dt [??,??] (invalid poly, probably no tile loaded)"); return true; } - if (polyRef == INVALID_POLYREF) + if (polyRef == 0) handler->PSendSysMessage("Dt [??, ??] (invalid poly, probably no tile loaded)"); else { @@ -183,8 +234,8 @@ public: static bool HandleMmapLoadedTilesCommand(ChatHandler* handler, char const* /*args*/) { uint32 mapid = handler->GetSession()->GetPlayer()->GetMapId(); - dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid); - dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(mapid, handler->GetSession()->GetPlayer()->GetInstanceId()); + dtNavMesh const* navmesh = MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMesh(mapid); + dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::CreateOrGetMMapManager()->GetNavMeshQuery(mapid, handler->GetSession()->GetPlayer()->GetInstanceId()); if (!navmesh || !navmeshquery) { handler->PSendSysMessage("NavMesh not loaded for current map."); @@ -211,8 +262,8 @@ public: handler->PSendSysMessage("mmap stats:"); handler->PSendSysMessage(" global mmap pathfinding is %sabled", MMAP::MMapFactory::IsPathfindingEnabled(mapId) ? "en" : "dis"); - MMAP::MMapManager* manager = MMAP::MMapFactory::createOrGetMMapManager(); - handler->PSendSysMessage(" %u maps loaded with %u tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount()); + MMAP::MMapManager* manager = MMAP::MMapFactory::CreateOrGetMMapManager(); + handler->PSendSysMessage(" %u maps loaded with %u tiles overall", manager->GetLoadedMapsCount(), manager->GetLoadedTilesCount()); dtNavMesh const* navmesh = manager->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()); if (!navmesh) diff --git a/src/tools/mesh_extractor/MPQManager.cpp b/src/tools/mesh_extractor/MPQManager.cpp index 4d3ab808a2e..950e284f92e 100644 --- a/src/tools/mesh_extractor/MPQManager.cpp +++ b/src/tools/mesh_extractor/MPQManager.cpp @@ -14,6 +14,12 @@ char const* MPQManager::Files[] = { "patch-3.MPQ" }; +char const* MPQManager::LocalePatchFiles[] = { + "Data/%s/patch-%s.MPQ", + "Data/%s/patch-%s-2.MPQ", + "Data/%s/patch-%s-3.MPQ" +}; + char const* MPQManager::Languages[] = { "enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; void MPQManager::Initialize() @@ -31,7 +37,6 @@ void MPQManager::Initialize() void MPQManager::InitializeDBC() { BaseLocale = -1; - std::string fileName; uint32 size = sizeof(Languages) / sizeof(char*); MPQArchive* _baseLocale = NULL; for (uint32 i = 0; i < size; ++i) @@ -41,20 +46,34 @@ void MPQManager::InitializeDBC() if (file) { if (BaseLocale == -1) - { BaseLocale = i; - _baseLocale = new MPQArchive(_fileName.c_str()); - fileName = _fileName; - LocaleFiles[i] = _baseLocale; + + // Load the base locale file + MPQArchive* arch = new MPQArchive(_fileName.c_str()); + LocaleFiles[i].push_front(arch); + + Archives.push_front(arch); // For lookup in GetFile + + // Load the locale patches + for (uint32 j = 0; j < sizeof(LocalePatchFiles) / sizeof(char*); ++j) + { + char patchName[100]; + sprintf(patchName, LocalePatchFiles[j], Languages[i], Languages[i]); + FILE* patch = fopen(patchName, "rb"); + if (file) + { + MPQArchive* archP = new MPQArchive(patchName); + LocaleFiles[i].push_front(archP); + Archives.push_front(archP); // For lookup in GetFile + fclose(patch); + } } - else - LocaleFiles[i] = new MPQArchive(_fileName.c_str()); AvailableLocales.insert(i); printf("Detected locale: %s\n", Languages[i]); } } - Archives.push_front(_baseLocale); + if (BaseLocale == -1) { printf("No locale data detected. Please make sure that the executable is in the same folder as your WoW installation.\n"); @@ -79,6 +98,46 @@ DBC* MPQManager::GetDBC(const std::string& name ) return new DBC(GetFile(path)); } +FILE* MPQManager::GetFileFromLocale( const std::string& path, uint32 locale ) +{ + ACE_GUARD_RETURN(ACE_Thread_Mutex, g, mutex, NULL); + std::deque<MPQArchive*> files = LocaleFiles[locale]; + FILE* ret = NULL; + for (std::deque<MPQArchive*>::iterator itr = files.begin(); itr != files.end(); ++itr) + { + mpq_archive* mpq_a = (*itr)->mpq_a; + + uint32_t filenum; + if(libmpq__file_number(mpq_a, path.c_str(), &filenum)) + continue; + libmpq__off_t transferred; + libmpq__off_t size = 0; + libmpq__file_unpacked_size(mpq_a, filenum, &size); + + // HACK: in patch.mpq some files don't want to open and give 1 for filesize + if (size <= 1) + continue; + + char* buffer = new char[size]; + + //libmpq_file_getdata + libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); + + // Pack the return into a FILE stream + ret = tmpfile(); + if (!ret) + { + printf("Could not create temporary file. Please run as Administrator or root\n"); + exit(1); + } + fwrite(buffer, sizeof(uint8), size, ret); + fseek(ret, 0, SEEK_SET); + delete[] buffer; + break; + } + return ret; +} + FILE* MPQManager::GetFileFrom(const std::string& path, MPQArchive* file ) { ACE_GUARD_RETURN(ACE_Thread_Mutex, g, mutex, NULL); diff --git a/src/tools/mesh_extractor/MPQManager.h b/src/tools/mesh_extractor/MPQManager.h index 7f9d675c4d4..3514674b9bf 100644 --- a/src/tools/mesh_extractor/MPQManager.h +++ b/src/tools/mesh_extractor/MPQManager.h @@ -16,15 +16,18 @@ public: void Initialize(); FILE* GetFile(const std::string& path); FILE* GetFileFrom(const std::string& path, MPQArchive* file); + FILE* GetFileFromLocale(const std::string& path, uint32 locale); + DBC* GetDBC(const std::string& name); std::vector<std::string> GetAllFiles(std::string extension); std::deque<MPQArchive*> Archives; int32 BaseLocale; std::set<uint32> AvailableLocales; - std::map<uint32, MPQArchive*> LocaleFiles; + std::map<uint32, std::deque<MPQArchive*> > LocaleFiles; static char const* Files[]; + static char const* LocalePatchFiles[]; static char const* Languages[]; protected: void InitializeDBC(); diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 0d9160a610b..51b13ce6fd0 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -58,9 +58,12 @@ void ExtractDBCs() // Populate list of DBC files // We get the DBC names by going over the (guaranteed to exist) default locale files // Then we look in other locale files in case that they are available. - for (std::vector<std::string>::iterator itr = MPQHandler->LocaleFiles[MPQHandler->BaseLocale]->Files.begin(); itr != MPQHandler->LocaleFiles[MPQHandler->BaseLocale]->Files.end(); ++itr) - if (itr->rfind(".dbc") == itr->length() - extLen) // Check if the extension is ".dbc" - DBCFiles.insert(*itr); + for (std::map<uint32, std::deque<MPQArchive*> >::iterator itr = MPQHandler->LocaleFiles.begin(); itr != MPQHandler->LocaleFiles.end(); ++itr) + for (std::deque<MPQArchive*>::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2) + for (std::vector<std::string>::iterator itr3 = (*itr2)->Files.begin(); itr3 != (*itr2)->Files.end(); ++itr3) + if (itr3->rfind(".dbc") == itr3->length() - extLen) // Check if the extension is ".dbc" + if (DBCFiles.find(*itr3) == DBCFiles.end()) + DBCFiles.insert(*itr3); const size_t folderLen = strlen("DBFilesClient\\"); // Iterate over all available locales @@ -76,10 +79,10 @@ void ExtractDBCs() std::string component = "component.wow-" + std::string(MPQManager::Languages[*itr]) + ".txt"; // Extract the component file - Utils::SaveToDisk(MPQHandler->GetFileFrom(component, MPQHandler->LocaleFiles[*itr]), path + component); + Utils::SaveToDisk(MPQHandler->GetFileFromLocale(component, *itr), path + component); // Extract the DBC files for the given locale for (std::set<std::string>::iterator itr2 = DBCFiles.begin(); itr2 != DBCFiles.end(); ++itr2) - Utils::SaveToDisk(MPQHandler->GetFileFrom(*itr2, MPQHandler->LocaleFiles[*itr]), path + (itr2->c_str() + folderLen)); + Utils::SaveToDisk(MPQHandler->GetFileFromLocale(*itr2, *itr), path + (itr2->c_str() + folderLen)); } printf("DBC extraction finished!\n"); } @@ -378,8 +381,8 @@ int main(int argc, char* argv[]) if (extractFlags & Constants::EXTRACT_FLAG_TEST) { - float start[] = { 16226.200195f, 16257.000000f, 13.202200f }; - float end[] = { 16245.725586f, 16382.465820f, 47.384956f }; + float start[] = { -1.37402868f, -21.7641087f, -20.1751060f }; + float end[] = { -22.756405f, -62.745014f, -21.371508f }; // float m_spos[3]; @@ -408,7 +411,7 @@ int main(int argc, char* argv[]) dtPolyRef m_startRef; dtPolyRef m_endRef; - FILE* mmap = fopen("mmaps/001.mmap", "rb"); + FILE* mmap = fopen("mmaps/389.mmap", "rb"); dtNavMeshParams params; int count = fread(¶ms, sizeof(dtNavMeshParams), 1, mmap); fclose(mmap); @@ -427,7 +430,7 @@ int main(int argc, char* argv[]) for (int j = 0; j <= 32; ++j) { char buff[100]; - sprintf(buff, "mmaps/001%02i%02i.mmtile", i, j); + sprintf(buff, "mmaps/389%02i%02i.mmtile", i, j); LoadTile(navMesh, buff); } } diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 51df91d2652..cdc3131b3db 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -42,13 +42,13 @@ TileBuilder::TileBuilder(ContinentBuilder* _cBuilder, std::string world, int x, InstanceConfig.mergeRegionArea = 100; InstanceConfig.walkableSlopeAngle = 50.0f; InstanceConfig.detailSampleDist = 3.0f; - InstanceConfig.detailSampleMaxError = 1.5f; + InstanceConfig.detailSampleMaxError = 1.25f; InstanceConfig.walkableClimb = 1.0f / InstanceConfig.ch; InstanceConfig.walkableHeight = 2.1f / InstanceConfig.ch; InstanceConfig.walkableRadius = 0.6f / InstanceConfig.cs; InstanceConfig.maxEdgeLen = 8 * InstanceConfig.walkableRadius; InstanceConfig.maxVertsPerPoly = 6; - InstanceConfig.maxSimplificationError = 1.25f; + InstanceConfig.maxSimplificationError = 1.3f; InstanceConfig.borderSize = 0; Context = new rcContext; |