diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index ca2452ad8..0f508756e 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -396,6 +396,17 @@ ChatCommand * ChatHandler::getCommandTable() { NULL, 0, false, NULL, "", NULL } }; + static ChatCommand mmapCommandTable[] = + { + { "path", SEC_GAMEMASTER, false, &ChatHandler::HandleMmapPathCommand, "", NULL }, + { "loc", SEC_GAMEMASTER, false, &ChatHandler::HandleMmapLocCommand, "", NULL }, + { "loadedtiles", SEC_GAMEMASTER, false, &ChatHandler::HandleMmapLoadedTilesCommand, "", NULL }, + { "stats", SEC_GAMEMASTER, false, &ChatHandler::HandleMmapStatsCommand, "", NULL }, + { "testarea", SEC_GAMEMASTER, false, &ChatHandler::HandleMmapTestArea, "", NULL }, + { "", SEC_ADMINISTRATOR, false, &ChatHandler::HandleMmap, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + static ChatCommand modifyCommandTable[] = { { "hp", SEC_MODERATOR, false, &ChatHandler::HandleModifyHPCommand, "", NULL }, @@ -813,6 +824,7 @@ ChatCommand * ChatHandler::getCommandTable() { "waterwalk", SEC_GAMEMASTER, false, &ChatHandler::HandleWaterwalkCommand, "", NULL }, { "quit", SEC_CONSOLE, true, &ChatHandler::HandleQuitCommand, "", NULL }, { "gearscore", SEC_ADMINISTRATOR, false, &ChatHandler::HandleShowGearScoreCommand, "", NULL }, + { "mmap", SEC_GAMEMASTER, false, NULL, "", mmapCommandTable }, { NULL, 0, false, NULL, "", NULL } }; diff --git a/src/game/Chat.h b/src/game/Chat.h index 5dcf58d22..7e72cdcb6 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -598,6 +598,13 @@ class MANGOS_DLL_SPEC ChatHandler bool HandleQuitCommand(char* args); bool HandleShowGearScoreCommand(char* args); + bool HandleMmapPathCommand(char* args); + bool HandleMmapLocCommand(char* args); + bool HandleMmapLoadedTilesCommand(char* args); + bool HandleMmapStatsCommand(char* args); + bool HandleMmap(char* args); + bool HandleMmapTestArea(char* args); + //! Development Commands bool HandleSaveAllCommand(char* args); diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 4025e9595..3ec845f3d 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -49,6 +49,8 @@ #include #include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand +#include "MoveMap.h" // for mmap manager +#include "PathFinder.h" // for mmap commands static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] = { @@ -5287,3 +5289,193 @@ bool ChatHandler::HandleTitlesCurrentCommand(char* args) return true; } + +bool ChatHandler::HandleMmapPathCommand(char* args) +{ + if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(m_session->GetPlayer()->GetMapId())) + { + PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + PSendSysMessage("mmap path:"); + + // units + Player* player = m_session->GetPlayer(); + Unit* target = getSelectedUnit(); + if (!player || !target) + { + PSendSysMessage("Invalid target/source selection."); + return true; + } + + char* para = strtok(args, " "); + + bool useStraightPath = false; + if (para && strcmp(para, "true") == 0) + useStraightPath = true; + + // unit locations + float x, y, z; + player->GetPosition(x, y, z); + + // path + PathFinder path(target); + path.setUseStrightPath(useStraightPath); + path.calculate(x, y, z); + + PointsArray pointPath = path.getPath(); + PSendSysMessage("%s's path to %s:", target->GetName(), player->GetName()); + PSendSysMessage("Building %s", useStraightPath ? "StraightPath" : "SmoothPath"); + PSendSysMessage("length %i type %u", pointPath.size(), path.getPathType()); + + Vector3 start = path.getStartPosition(); + Vector3 end = path.getEndPosition(); + Vector3 actualEnd = path.getActualEndPosition(); + + PSendSysMessage("start (%.3f, %.3f, %.3f)", start.x, start.y, start.z); + PSendSysMessage("end (%.3f, %.3f, %.3f)", end.x, end.y, end.z); + PSendSysMessage("actual end (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z); + + if (!player->isGameMaster()) + PSendSysMessage("Enable GM mode to see the path points."); + + // this entry visible only to GM's with "gm on" + static const uint32 WAYPOINT_NPC_ENTRY = 1; + Creature* wp = NULL; + for (uint32 i = 0; i < pointPath.size(); ++i) + { + wp = player->SummonCreature(WAYPOINT_NPC_ENTRY, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000); + // TODO: make creature not sink/fall + } + + return true; +} + +bool ChatHandler::HandleMmapLocCommand(char* /*args*/) +{ + PSendSysMessage("mmap tileloc:"); + + // grid tile location + Player* player = m_session->GetPlayer(); + + int32 gx = 32 - player->GetPositionX() / SIZE_OF_GRIDS; + int32 gy = 32 - player->GetPositionY() / SIZE_OF_GRIDS; + + PSendSysMessage("%03u%02i%02i.mmtile", player->GetMapId(), gy, gx); + PSendSysMessage("gridloc [%i,%i]", gx, gy); + + // calculate navmesh tile location + const dtNavMesh* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(player->GetMapId()); + const dtNavMeshQuery* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(player->GetMapId(), player->GetInstanceId()); + if (!navmesh || !navmeshquery) + { + PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + const float* 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}; + + int32 tilex = int32((y - min[0]) / SIZE_OF_GRIDS); + int32 tiley = int32((x - min[2]) / SIZE_OF_GRIDS); + + PSendSysMessage("Calc [%02i,%02i]", tilex, tiley); + + // navmesh poly -> navmesh tile location + dtQueryFilter filter = dtQueryFilter(); + dtPolyRef polyRef = INVALID_POLYREF; + navmeshquery->findNearestPoly(location, extents, &filter, &polyRef, NULL); + + if (polyRef == INVALID_POLYREF) + PSendSysMessage("Dt [??,??] (invalid poly, probably no tile loaded)"); + else + { + const dtMeshTile* tile; + const dtPoly* poly; + navmesh->getTileAndPolyByRef(polyRef, &tile, &poly); + if (tile) + PSendSysMessage("Dt [%02i,%02i]", tile->header->x, tile->header->y); + else + PSendSysMessage("Dt [??,??] (no tile loaded)"); + } + + return true; +} + +bool ChatHandler::HandleMmapLoadedTilesCommand(char* /*args*/) +{ + uint32 mapid = m_session->GetPlayer()->GetMapId(); + + const dtNavMesh* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid); + const dtNavMeshQuery* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(mapid, m_session->GetPlayer()->GetInstanceId()); + if (!navmesh || !navmeshquery) + { + PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + PSendSysMessage("mmap loadedtiles:"); + + for (int32 i = 0; i < navmesh->getMaxTiles(); ++i) + { + const dtMeshTile* tile = navmesh->getTile(i); + if (!tile || !tile->header) + continue; + + PSendSysMessage("[%02i,%02i]", tile->header->x, tile->header->y); + } + + return true; +} + +bool ChatHandler::HandleMmapStatsCommand(char* /*args*/) +{ + PSendSysMessage("mmap stats:"); + PSendSysMessage(" global mmap pathfinding is %sabled", sWorld.getConfig(CONFIG_BOOL_MMAP_ENABLED) ? "en" : "dis"); + + MMAP::MMapManager *manager = MMAP::MMapFactory::createOrGetMMapManager(); + PSendSysMessage(" %u maps loaded with %u tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount()); + + const dtNavMesh* navmesh = manager->GetNavMesh(m_session->GetPlayer()->GetMapId()); + if (!navmesh) + { + PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + uint32 tileCount = 0; + uint32 nodeCount = 0; + uint32 polyCount = 0; + uint32 vertCount = 0; + uint32 triCount = 0; + uint32 triVertCount = 0; + uint32 dataSize = 0; + for (int32 i = 0; i < navmesh->getMaxTiles(); ++i) + { + const dtMeshTile* tile = navmesh->getTile(i); + if (!tile || !tile->header) + continue; + + tileCount ++; + nodeCount += tile->header->bvNodeCount; + polyCount += tile->header->polyCount; + vertCount += tile->header->vertCount; + triCount += tile->header->detailTriCount; + triVertCount += tile->header->detailVertCount; + dataSize += tile->dataSize; + } + + PSendSysMessage("Navmesh stats on current map:"); + PSendSysMessage(" %u tiles loaded", tileCount); + PSendSysMessage(" %u BVTree nodes", nodeCount); + PSendSysMessage(" %u polygons (%u vertices)", polyCount, vertCount); + PSendSysMessage(" %u triangles (%u vertices)", triCount, triVertCount); + PSendSysMessage(" %.2f MB of data (not including pointers)", ((float)dataSize / sizeof(unsigned char)) / 1048576); + + return true; +} diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index e9858b616..2fc760345 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -41,6 +41,7 @@ #include "CellImpl.h" #include "Weather.h" #include "PointMovementGenerator.h" +#include "PathFinder.h" #include "TargetedMovementGenerator.h" #include "SkillDiscovery.h" #include "SkillExtraItems.h" @@ -7091,4 +7092,73 @@ bool ChatHandler::HandleShowGearScoreCommand(char *args) PSendSysMessage(LANG_GEARSCORE, GetNameLink(player).c_str(), gearScore); return true; -} \ No newline at end of file +} + +bool ChatHandler::HandleMmap(char* args) +{ + bool on; + if (ExtractOnOff(&args, on)) + { + if (on) + { + sWorld.setConfig(CONFIG_BOOL_MMAP_ENABLED, true); + SendSysMessage("WORLD: mmaps are now ENABLED (individual map settings still in effect)"); + } + else + { + sWorld.setConfig(CONFIG_BOOL_MMAP_ENABLED, false); + SendSysMessage("WORLD: mmaps are now DISABLED"); + } + return true; + } + + on = sWorld.getConfig(CONFIG_BOOL_MMAP_ENABLED); + PSendSysMessage("mmaps are %sabled", on ? "en" : "dis"); + + return true; +} + +bool ChatHandler::HandleMmapTestArea(char* args) +{ + float radius = 40.0f; + ExtractFloat(&args, radius); + + CellPair pair(MaNGOS::ComputeCellPair( m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY()) ); + Cell cell(pair); + cell.SetNoCreate(); + + std::list creatureList; + + MaNGOS::AnyUnitInObjectRangeCheck go_check(m_session->GetPlayer(), radius); + MaNGOS::CreatureListSearcher go_search(creatureList, go_check); + TypeContainerVisitor, GridTypeMapContainer> go_visit(go_search); + + // Get Creatures + cell.Visit(pair, go_visit, *(m_session->GetPlayer()->GetMap()), *(m_session->GetPlayer()), radius); + + if (!creatureList.empty()) + { + PSendSysMessage("Found %i Creatures.", creatureList.size()); + + uint32 paths = 0; + uint32 uStartTime = WorldTimer::getMSTime(); + + float gx,gy,gz; + m_session->GetPlayer()->GetPosition(gx,gy,gz); + for (std::list::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) + { + PathFinder path(*itr); + path.calculate(gx, gy, gz); + ++paths; + } + + uint32 uPathLoadTime = WorldTimer::getMSTimeDiff(uStartTime, WorldTimer::getMSTime()); + PSendSysMessage("Generated %i paths in %i ms", paths, uPathLoadTime); + } + else + { + PSendSysMessage("No creatures in %f yard range.", radius); + } + + return true; +} diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 505f5cd3d..93a10ebd5 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "11912" + #define REVISION_NR "11913" #endif // __REVISION_NR_H__