From 40f80fc0ed8d4928de021230acd6b75f7f3ec7b4 Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 11 Jun 2020 01:35:27 +0200 Subject: [PATCH] Core/Maps: Improvements to terrain swap handling * Fixed memory leak when unloading grids * Handle child maps being entered * Allow chaining more child maps (Draenor -> Tanaan Jungle -> Tanaan Jungle - No Hubs Phase) --- src/common/Collision/Maps/MapTree.cpp | 6 +- src/server/game/Entities/Player/Player.cpp | 4 +- src/server/game/Handlers/MovementHandler.cpp | 2 +- src/server/game/Handlers/QueryHandler.cpp | 2 +- src/server/game/Maps/Map.cpp | 205 ++++++++++-------- src/server/game/Maps/Map.h | 59 ++--- src/server/game/Maps/MapManager.cpp | 15 +- src/server/game/Maps/MapManager.h | 26 +-- src/server/game/Phasing/PhasingHandler.cpp | 13 +- src/server/scripts/Commands/cs_go.cpp | 6 +- src/server/scripts/Commands/cs_list.cpp | 2 +- src/server/scripts/Commands/cs_misc.cpp | 2 +- .../Deadmines/boss_foe_reaper_5000.cpp | 2 +- 13 files changed, 185 insertions(+), 159 deletions(-) diff --git a/src/common/Collision/Maps/MapTree.cpp b/src/common/Collision/Maps/MapTree.cpp index 686765cf84..ffe564d0fe 100644 --- a/src/common/Collision/Maps/MapTree.cpp +++ b/src/common/Collision/Maps/MapTree.cpp @@ -242,10 +242,14 @@ namespace VMAP if (!result.File) { int32 parentMapId = vm->getParentMapId(mapID); - if (parentMapId != -1) + while (parentMapId != -1) { result.Name = basePath + getTileFileName(parentMapId, tileX, tileY); result.File = fopen(result.Name.c_str(), "rb"); + if (result.File) + break; + + parentMapId = vm->getParentMapId(uint32(parentMapId)); } } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 75282793f5..6cb5c05895 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -4671,7 +4671,7 @@ void Player::RepopAtGraveyard() AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetAreaId()); // Such zones are considered unreachable as a ghost and the player must be automatically revived - if ((!IsAlive() && zone && zone->Flags & AREA_FLAG_NEED_FLY) || GetTransport() || GetPositionZ() < GetMap()->GetMinHeight(GetPositionX(), GetPositionY())) + if ((!IsAlive() && zone && zone->Flags & AREA_FLAG_NEED_FLY) || GetTransport() || GetPositionZ() < GetMap()->GetMinHeight(GetPhaseShift(), GetPositionX(), GetPositionY())) { ResurrectPlayer(0.5f); SpawnCorpseBones(); @@ -4709,7 +4709,7 @@ void Player::RepopAtGraveyard() SendDirectMessage(&data); } } - else if (GetPositionZ() < GetMap()->GetMinHeight(GetPositionX(), GetPositionY())) + else if (GetPositionZ() < GetMap()->GetMinHeight(GetPhaseShift(), GetPositionX(), GetPositionY())) TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation()); RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_IS_OUT_OF_BOUNDS); diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 994da0b2fb..df3f780688 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -442,7 +442,7 @@ void WorldSession::HandleMovementOpcode(uint16 opcode, MovementInfo& movementInf plrMover->UpdateFallInformationIfNeed(movementInfo, opcode); - if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY())) + if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(plrMover->GetPhaseShift(), movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY())) { if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player))) { diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index 6cbca1b863..f260821e41 100644 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -266,7 +266,7 @@ void WorldSession::HandleCorpseQueryOpcode(WorldPacket& /*recvData*/) if (corpseMapEntry->IsDungeon() && corpseMapEntry->CorpseMapID >= 0) { // if corpse map have entrance - if (Map const* entranceMap = sMapMgr->CreateBaseMap(corpseMapEntry->CorpseMapID)) + if (Map* entranceMap = sMapMgr->CreateBaseMap(corpseMapEntry->CorpseMapID)) { mapID = corpseMapEntry->CorpseMapID; x = corpseMapEntry->Corpse.X; diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index e12de6f44a..0e6cc0c7a6 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -96,7 +96,23 @@ Map::~Map() MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(GetId(), i_InstanceId); } -bool Map::ExistMap(uint32 mapid, int gx, int gy) +void Map::DiscoverGridMapFiles() +{ + for (uint32 gx = 0; gx < MAX_NUMBER_OF_GRIDS; ++gx) + for (uint32 gy = 0; gy < MAX_NUMBER_OF_GRIDS; ++gy) + i_gridFileExists[gx * MAX_NUMBER_OF_GRIDS + gy] = ExistMap(GetId(), gx, gy, false); +} + +Map* Map::GetRootParentTerrainMap() +{ + Map* map = this; + while (map != map->m_parentTerrainMap) + map = map->m_parentTerrainMap; + + return map; +} + +bool Map::ExistMap(uint32 mapid, int gx, int gy, bool log /*= true*/) { std::string fileName = Trinity::StringFormat("%smaps/%03u%02u%02u.map", sWorld->GetDataPath().c_str(), mapid, gx, gy); @@ -104,8 +120,11 @@ bool Map::ExistMap(uint32 mapid, int gx, int gy) FILE* file = fopen(fileName.c_str(), "rb"); if (!file) { - TC_LOG_ERROR("maps", "Map file '%s' does not exist!", fileName.c_str()); - TC_LOG_ERROR("maps", "Please place MAP-files (*.map) in the appropriate directory (%s), or correct the DataDir setting in your worldserver.conf file.", (sWorld->GetDataPath()+"maps/").c_str()); + if (log) + { + TC_LOG_ERROR("maps", "Map file '%s' does not exist!", fileName.c_str()); + TC_LOG_ERROR("maps", "Please place MAP-files (*.map) in the appropriate directory (%s), or correct the DataDir setting in your worldserver.conf file.", (sWorld->GetDataPath()+"maps/").c_str()); + } } else { @@ -113,8 +132,11 @@ bool Map::ExistMap(uint32 mapid, int gx, int gy) if (fread(&header, sizeof(header), 1, file) == 1) { if (header.mapMagic.asUInt != MapMagic.asUInt || header.versionMagic.asUInt != MapVersionMagic.asUInt) - TC_LOG_ERROR("maps", "Map file '%s' is from an incompatible map version (%.*s %.*s), %.*s %.*s is expected. Please pull your source, recompile tools and recreate maps using the updated mapextractor, then replace your old map files with new files. If you still have problems search on forum for error TCE00018.", - fileName.c_str(), 4, header.mapMagic.asChar, 4, header.versionMagic.asChar, 4, MapMagic.asChar, 4, MapVersionMagic.asChar); + { + if (log) + TC_LOG_ERROR("maps", "Map file '%s' is from an incompatible map version (%.*s %.*s), %.*s %.*s is expected. Please pull your source, recompile tools and recreate maps using the updated mapextractor, then replace your old map files with new files. If you still have problems search on forum for error TCE00018.", + fileName.c_str(), 4, header.mapMagic.asChar, 4, header.versionMagic.asChar, 4, MapMagic.asChar, 4, MapVersionMagic.asChar); + } else ret = true; } @@ -187,6 +209,7 @@ void Map::LoadVMap(int gx, int gy) void Map::LoadMap(int gx, int gy) { LoadMapImpl(this, gx, gy); + for (Map* childBaseMap : *m_childTerrainMaps) childBaseMap->LoadMap(gx, gy); } @@ -196,29 +219,32 @@ void Map::LoadMapImpl(Map* map, int gx, int gy) if (map->GridMaps[gx][gy]) return; - Map* parent = map->m_parentMap; - ++parent->GridMapReference[gx][gy]; - - // load grid map for base map - if (parent != map) - { - GridCoord ngridCoord = GridCoord((MAX_NUMBER_OF_GRIDS - 1) - gx, (MAX_NUMBER_OF_GRIDS - 1) - gy); - if (!parent->GridMaps[gx][gy]) - parent->EnsureGridCreated(ngridCoord); - - map->GridMaps[gx][gy] = parent->GridMaps[gx][gy]; - return; - } - // map file name std::string fileName = Trinity::StringFormat("%smaps/%03u%02u%02u.map", sWorld->GetDataPath().c_str(), map->GetId(), gx, gy); TC_LOG_DEBUG("maps", "Loading map %s", fileName.c_str()); // loading data - map->GridMaps[gx][gy] = new GridMap(); - if (!map->GridMaps[gx][gy]->loadData(fileName.c_str())) - TC_LOG_ERROR("maps", "Error loading map file: %s", fileName.c_str()); + std::shared_ptr gridMap = std::make_shared(); + GridMap::LoadResult gridMapLoadResult = gridMap->loadData(fileName.c_str()); + if (gridMapLoadResult == GridMap::LoadResult::Ok) + map->GridMaps[gx][gy] = std::move(gridMap); + else + { + map->i_gridFileExists[gx * MAX_NUMBER_OF_GRIDS + gy] = false; + Map* parentTerrain = map; + while (parentTerrain != parentTerrain->m_parentTerrainMap) + { + map->GridMaps[gx][gy] = parentTerrain->m_parentTerrainMap->GridMaps[gx][gy]; + if (map->GridMaps[gx][gy]) + break; - sScriptMgr->OnLoadGridMap(map, map->GridMaps[gx][gy], gx, gy); + parentTerrain = parentTerrain->m_parentTerrainMap; + } + } + + if (map->GridMaps[gx][gy]) + sScriptMgr->OnLoadGridMap(map, map->GridMaps[gx][gy].get(), gx, gy); + else if (gridMapLoadResult == GridMap::LoadResult::InvalidFile) + TC_LOG_ERROR("maps", "Error loading map file: %s", fileName.c_str()); } void Map::UnloadMap(int gx, int gy) @@ -231,25 +257,18 @@ void Map::UnloadMap(int gx, int gy) void Map::UnloadMapImpl(Map* map, int gx, int gy) { - if (map->GridMaps[gx][gy]) - { - Map* parent = map->m_parentMap; - if (!--parent->GridMapReference[gx][gy]) - { - parent->GridMaps[gx][gy]->unloadData(); - delete parent->GridMaps[gx][gy]; - parent->GridMaps[gx][gy] = nullptr; - } - } - map->GridMaps[gx][gy] = nullptr; } void Map::LoadMapAndVMap(int gx, int gy) { LoadMap(gx, gy); - LoadVMap(gx, gy); - LoadMMap(gx, gy); + // Only load the data for the base map + if (this == m_parentMap) + { + LoadVMap(gx, gy); + LoadMMap(gx, gy); + } } void Map::LoadAllCells() @@ -518,7 +537,7 @@ void Map::EnsureGridCreated_i(const GridCoord &p) { TC_LOG_DEBUG("maps", "Creating grid[%u, %u] for map %u instance %u", p.x_coord, p.y_coord, GetId(), i_InstanceId); - NGridType* ngrid = new NGridType(p.x_coord*MAX_NUMBER_OF_GRIDS + p.y_coord, p.x_coord, p.y_coord, i_gridExpiry, sWorld->getBoolConfig(CONFIG_GRID_UNLOAD)); + NGridType* ngrid = new NGridType(p.x_coord * MAX_NUMBER_OF_GRIDS + p.y_coord, p.x_coord, p.y_coord, i_gridExpiry, sWorld->getBoolConfig(CONFIG_GRID_UNLOAD)); setNGrid(ngrid, p.x_coord, p.y_coord); // build a linkage between this map and NGridType @@ -531,7 +550,22 @@ void Map::EnsureGridCreated_i(const GridCoord &p) int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord; if (!GridMaps[gx][gy]) - m_parentTerrainMap->LoadMapAndVMap(gx, gy); + { + Map* rootParentTerrainMap = m_parentMap->GetRootParentTerrainMap(); + // because LoadMapAndVMap is always entered using rootParentTerrainMap, we can only lock that once and not have to do it for every child map + std::unique_lock lock(rootParentTerrainMap->_gridLock, std::defer_lock); + if (this != rootParentTerrainMap) + lock.lock(); + + if (!m_parentMap->GridMaps[gx][gy]) + rootParentTerrainMap->LoadMapAndVMap(gx, gy); + + if (m_parentMap->GridMaps[gx][gy]) + { + GridMaps[gx][gy] = m_parentMap->GridMaps[gx][gy]; + ++rootParentTerrainMap->GridMapReference[gx][gy]; + } + } } } @@ -1732,9 +1766,13 @@ bool Map::UnloadGrid(NGridType& ngrid, bool unloadAll) // delete grid map, but don't delete if it is from parent map (and thus only reference) if (GridMaps[gx][gy]) { - m_parentTerrainMap->UnloadMap(gx, gy); - VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(m_parentTerrainMap->GetId(), gx, gy); - MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(m_parentTerrainMap->GetId(), gx, gy); + Map* terrainRoot = m_parentMap->GetRootParentTerrainMap(); + if (!--terrainRoot->GridMapReference[gx][gy]) + { + m_parentMap->GetRootParentTerrainMap()->UnloadMap(gx, gy); + VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(terrainRoot->GetId(), gx, gy); + MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(terrainRoot->GetId(), gx, gy); + } } TC_LOG_DEBUG("maps", "Unloading grid[%u, %u] for map %u finished", x, y, GetId()); @@ -1822,7 +1860,6 @@ GridMap::GridMap() _liquidFlags = nullptr; _liquidMap = nullptr; _holes = nullptr; - _fileExists = false; } GridMap::~GridMap() @@ -1830,7 +1867,7 @@ GridMap::~GridMap() unloadData(); } -bool GridMap::loadData(char const* filename) +GridMap::LoadResult GridMap::loadData(const char* filename) { // Unload old data if exist unloadData(); @@ -1839,13 +1876,12 @@ bool GridMap::loadData(char const* filename) // Not return error if file not found FILE* in = fopen(filename, "rb"); if (!in) - return true; + return LoadResult::FileDoesNotExist; - _fileExists = true; if (fread(&header, sizeof(header), 1, in) != 1) { fclose(in); - return false; + return LoadResult::InvalidFile; } if (header.mapMagic.asUInt == MapMagic.asUInt && header.versionMagic.asUInt == MapVersionMagic.asUInt) @@ -1855,37 +1891,37 @@ bool GridMap::loadData(char const* filename) { TC_LOG_ERROR("maps", "Error loading map area data\n"); fclose(in); - return false; + return LoadResult::InvalidFile; } // load up height data if (header.heightMapOffset && !loadHeightData(in, header.heightMapOffset, header.heightMapSize)) { TC_LOG_ERROR("maps", "Error loading map height data\n"); fclose(in); - return false; + return LoadResult::InvalidFile; } // load up liquid data if (header.liquidMapOffset && !loadLiquidData(in, header.liquidMapOffset, header.liquidMapSize)) { TC_LOG_ERROR("maps", "Error loading map liquids data\n"); fclose(in); - return false; + return LoadResult::InvalidFile; } // loadup holes data (if any. check header.holesOffset) if (header.holesSize && !loadHolesData(in, header.holesOffset, header.holesSize)) { TC_LOG_ERROR("maps", "Error loading map holes data\n"); fclose(in); - return false; + return LoadResult::InvalidFile; } fclose(in); - return true; + return LoadResult::Ok; } TC_LOG_ERROR("maps", "Map file '%s' is from an incompatible map version (%.*s %.*s), %.*s %.*s is expected. Please pull your source, recompile tools and recreate maps using the updated mapextractor, then replace your old map files with new files. If you still have problems search on forum for error TCE00018.", filename, 4, header.mapMagic.asChar, 4, header.versionMagic.asChar, 4, MapMagic.asChar, 4, MapVersionMagic.asChar); fclose(in); - return false; + return LoadResult::InvalidFile; } void GridMap::unloadData() @@ -1907,7 +1943,6 @@ void GridMap::unloadData() _liquidMap = nullptr; _holes = nullptr; _gridGetHeight = &GridMap::getHeightFromFlat; - _fileExists = false; } bool GridMap::loadAreaData(FILE* in, uint32 offset, uint32 /*size*/) @@ -2463,23 +2498,8 @@ inline ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, uint8 R return LIQUID_MAP_ABOVE_WATER; } -inline GridMap* Map::GetGrid(float x, float y) -{ - // half opt method - int gx=(int)(CENTER_GRID_ID - x/SIZE_OF_GRIDS); //grid x - int gy=(int)(CENTER_GRID_ID - y/SIZE_OF_GRIDS); //grid y - - // ensure GridMap is loaded - EnsureGridCreated(GridCoord((MAX_NUMBER_OF_GRIDS - 1) - gx, (MAX_NUMBER_OF_GRIDS - 1) - gy)); - - return GridMaps[gx][gy]; -} - GridMap* Map::GetGrid(uint32 mapId, float x, float y) { - if (GetId() == mapId) - return GetGrid(x, y); - // half opt method int gx = (int)(CENTER_GRID_ID - x / SIZE_OF_GRIDS); //grid x int gy = (int)(CENTER_GRID_ID - y / SIZE_OF_GRIDS); //grid y @@ -2487,24 +2507,23 @@ GridMap* Map::GetGrid(uint32 mapId, float x, float y) // ensure GridMap is loaded EnsureGridCreated(GridCoord((MAX_NUMBER_OF_GRIDS - 1) - gx, (MAX_NUMBER_OF_GRIDS - 1) - gy)); - GridMap* grid = GridMaps[gx][gy]; - + GridMap* grid = GridMaps[gx][gy].get(); auto childMapItr = std::find_if(m_childTerrainMaps->begin(), m_childTerrainMaps->end(), [mapId](Map* childTerrainMap) { return childTerrainMap->GetId() == mapId; }); - if (childMapItr != m_childTerrainMaps->end() && (*childMapItr)->GridMaps[gx][gy] && (*childMapItr)->GridMaps[gx][gy]->fileExists()) - grid = (*childMapItr)->GridMaps[gx][gy]; + if (childMapItr != m_childTerrainMaps->end() && (*childMapItr)->GridMaps[gx][gy]) + grid = (*childMapItr)->GridMaps[gx][gy].get(); return grid; } -bool Map::HasGrid(uint32 mapId, int32 gx, int32 gy) const +bool Map::HasChildMapGridFile(uint32 mapId, int32 gx, int32 gy) const { auto childMapItr = std::find_if(m_childTerrainMaps->begin(), m_childTerrainMaps->end(), [mapId](Map* childTerrainMap) { return childTerrainMap->GetId() == mapId; }); - return childMapItr != m_childTerrainMaps->end() && (*childMapItr)->GridMaps[gx][gy] && (*childMapItr)->GridMaps[gx][gy]->fileExists(); + return childMapItr != m_childTerrainMaps->end() && (*childMapItr)->i_gridFileExists[gx * MAX_NUMBER_OF_GRIDS + gy]; } -float Map::GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground /*= nullptr*/, bool /*swim = false*/, float collisionHeight /*= DEFAULT_COLLISION_HEIGHT*/) const +float Map::GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground /*= nullptr*/, bool /*swim = false*/, float collisionHeight /*= DEFAULT_COLLISION_HEIGHT*/) { - if (m_parentTerrainMap->GetGrid(x, y)) + if (GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, this, x, y), x, y)) { // we need ground level (including grid height version) for proper return water level in point float ground_z = GetHeight(phaseShift, x, y, z + collisionHeight); @@ -2528,7 +2547,7 @@ float Map::GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, return VMAP_INVALID_HEIGHT_VALUE; } -float Map::GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float z, bool checkVMap /*= true*/, float maxSearchDist /*= DEFAULT_HEIGHT_SEARCH*/) const +float Map::GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float z, bool checkVMap /*= true*/, float maxSearchDist /*= DEFAULT_HEIGHT_SEARCH*/) { // find raw .map surface under Z coordinates uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, this, x, y); @@ -2567,17 +2586,17 @@ float Map::GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float return mapHeight; // explicitly use map data } -float Map::GetMinHeight(float x, float y) const +float Map::GetMinHeight(PhaseShift const& phaseShift, float x, float y) { - if (GridMap const* grid = const_cast(this)->GetGrid(x, y)) + if (GridMap const* grid = GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, this, x, y), x, y)) return grid->getMinHeight(x, y); return -500.0f; } -float Map::GetGridHeight(uint32 mapId, float x, float y) const +float Map::GetGridHeight(uint32 mapId, float x, float y) { - if (GridMap* gmap = m_parentTerrainMap->GetGrid(mapId, x, y)) + if (GridMap* gmap = GetGrid(mapId, x, y)) return gmap->getHeight(x, y); return VMAP_INVALID_HEIGHT_VALUE; @@ -2588,7 +2607,7 @@ static inline bool IsInWMOInterior(uint32 mogpFlags) return (mogpFlags & 0x2000) != 0; } -uint32 Map::GetAreaId(PhaseShift const& phaseShift, float x, float y, float z) const +uint32 Map::GetAreaId(PhaseShift const& phaseShift, float x, float y, float z) { uint32 mogpFlags; int32 adtId, rootId, groupId; @@ -2598,7 +2617,7 @@ uint32 Map::GetAreaId(PhaseShift const& phaseShift, float x, float y, float z) c uint32 gridAreaId = 0; float gridMapHeight = INVALID_HEIGHT; - if (GridMap* gmap = m_parentTerrainMap->GetGrid(terrainMapId, x, y)) + if (GridMap* gmap = GetGrid(terrainMapId, x, y)) { gridAreaId = gmap->getArea(x, y); gridMapHeight = gmap->getHeight(x, y); @@ -2625,7 +2644,7 @@ uint32 Map::GetAreaId(PhaseShift const& phaseShift, float x, float y, float z) c return areaId; } -uint32 Map::GetZoneId(PhaseShift const& phaseShift, float x, float y, float z) const +uint32 Map::GetZoneId(PhaseShift const& phaseShift, float x, float y, float z) { uint32 areaId = GetAreaId(phaseShift, x, y, z); if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId)) @@ -2635,7 +2654,7 @@ uint32 Map::GetZoneId(PhaseShift const& phaseShift, float x, float y, float z) c return areaId; } -void Map::GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, float x, float y, float z) const +void Map::GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, float x, float y, float z) { areaid = zoneid = GetAreaId(phaseShift, x, y, z); if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaid)) @@ -2643,7 +2662,7 @@ void Map::GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& zoneid = area->ParentAreaID; } -ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data, float collisionHeight) const +ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data, float collisionHeight) { ZLiquidStatus result = LIQUID_MAP_NO_WATER; VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); @@ -2713,7 +2732,7 @@ ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float if (useGridLiquid) { - if (GridMap* gmap = m_parentTerrainMap->GetGrid(terrainMapId, x, y)) + if (GridMap* gmap = GetGrid(terrainMapId, x, y)) { LiquidData map_data; ZLiquidStatus map_result = gmap->GetLiquidStatus(x, y, z, ReqLiquidType, &map_data, collisionHeight); @@ -2735,12 +2754,12 @@ ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float return result; } -void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType, float collisionHeight) const +void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType, float collisionHeight) { VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); VMAP::AreaAndLiquidData vmapData; uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, this, x, y); - GridMap* gmap = m_parentTerrainMap->GetGrid(terrainMapId, x, y); + GridMap* gmap = GetGrid(terrainMapId, x, y); vmgr->getAreaAndLiquidData(terrainMapId, x, y, z, reqLiquidType, vmapData); uint32 gridAreaId = 0; @@ -2862,9 +2881,9 @@ void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x, } } -float Map::GetWaterLevel(PhaseShift const& phaseShift, float x, float y) const +float Map::GetWaterLevel(PhaseShift const& phaseShift, float x, float y) { - if (GridMap* gmap = m_parentTerrainMap->GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, this, x, y), x, y)) + if (GridMap* gmap = GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, this, x, y), x, y)) return gmap->getLiquidLevel(x, y); else return 0; @@ -2895,14 +2914,14 @@ bool Map::getObjectHitPos(PhaseShift const& phaseShift, float x1, float y1, floa return result; } -bool Map::IsInWater(PhaseShift const& phaseShift, float x, float y, float pZ, LiquidData* data) const +bool Map::IsInWater(PhaseShift const& phaseShift, float x, float y, float pZ, LiquidData* data) { LiquidData liquid_status; LiquidData* liquid_ptr = data ? data : &liquid_status; return (GetLiquidStatus(phaseShift, x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr) & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0; } -bool Map::IsUnderWater(PhaseShift const& phaseShift, float x, float y, float z) const +bool Map::IsUnderWater(PhaseShift const& phaseShift, float x, float y, float z) { return (GetLiquidStatus(phaseShift, x, y, z, MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN) & LIQUID_MAP_UNDER_WATER) != 0; } diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index bba374e8df..b4b78868b7 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -224,8 +224,6 @@ class TC_GAME_API GridMap uint16* _holes; - bool _fileExists; - bool loadAreaData(FILE* in, uint32 offset, uint32 size); bool loadHeightData(FILE* in, uint32 offset, uint32 size); bool loadLiquidData(FILE* in, uint32 offset, uint32 size); @@ -243,7 +241,15 @@ class TC_GAME_API GridMap public: GridMap(); ~GridMap(); - bool loadData(char const* filename); + + enum class LoadResult + { + Ok, + FileDoesNotExist, + InvalidFile + }; + + LoadResult loadData(const char* filename); void unloadData(); uint16 getArea(float x, float y) const; @@ -251,7 +257,6 @@ public: float getMinHeight(float x, float y) const; float getLiquidLevel(float x, float y) const; ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h - bool fileExists() const { return _fileExists; } }; #pragma pack(push, 1) @@ -385,46 +390,50 @@ class TC_GAME_API Map : public GridRefManager time_t GetGridExpiry(void) const { return i_gridExpiry; } uint32 GetId() const; - bool HasGrid(uint32 mapId, int32 gx, int32 gy) const; - static bool ExistMap(uint32 mapid, int gx, int gy); + bool HasChildMapGridFile(uint32 mapId, int32 gx, int32 gy) const; + static bool ExistMap(uint32 mapid, int gx, int gy, bool log = true); static bool ExistVMap(uint32 mapid, int gx, int gy); static void InitStateMachine(); static void DeleteStateMachine(); Map const* GetParent() const { return m_parentMap; } + + void DiscoverGridMapFiles(); + + Map* GetRootParentTerrainMap(); void AddChildTerrainMap(Map* map) { m_childTerrainMaps->push_back(map); map->m_parentTerrainMap = this; } void UnlinkAllChildTerrainMaps() { m_childTerrainMaps->clear(); } // some calls like isInWater should not use vmaps due to processor power // can return INVALID_HEIGHT if under z+2 z coord not found height - float GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const; - float GetMinHeight(float x, float y) const; + float GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH); + float GetMinHeight(PhaseShift const& phaseShift, float x, float y); - void GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h - ZLiquidStatus GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h + void GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h + ZLiquidStatus GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h - uint32 GetAreaId(PhaseShift const& phaseShift, float x, float y, float z) const; - uint32 GetAreaId(PhaseShift const& phaseShift, Position const& pos) const + uint32 GetAreaId(PhaseShift const& phaseShift, float x, float y, float z); + uint32 GetAreaId(PhaseShift const& phaseShift, Position const& pos) { return GetAreaId(phaseShift, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } - uint32 GetZoneId(PhaseShift const& phaseShift, float x, float y, float z) const; - uint32 GetZoneId(PhaseShift const& phaseShift, Position const& pos) const + uint32 GetZoneId(PhaseShift const& phaseShift, float x, float y, float z); + uint32 GetZoneId(PhaseShift const& phaseShift, Position const& pos) { return GetZoneId(phaseShift, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } - void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, float x, float y, float z) const; - void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, Position const& pos) const + void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, float x, float y, float z); + void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, Position const& pos) { GetZoneAndAreaId(phaseShift, zoneid, areaid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } - float GetWaterLevel(PhaseShift const& phaseShift, float x, float y) const; - bool IsInWater(PhaseShift const& phaseShift, float x, float y, float z, LiquidData* data = nullptr) const; - bool IsUnderWater(PhaseShift const& phaseShift, float x, float y, float z) const; + float GetWaterLevel(PhaseShift const& phaseShift, float x, float y); + bool IsInWater(PhaseShift const& phaseShift, float x, float y, float z, LiquidData* data = nullptr); + bool IsUnderWater(PhaseShift const& phaseShift, float x, float y, float z); void MoveAllCreaturesInMoveList(); void MoveAllGameObjectsInMoveList(); @@ -578,11 +587,11 @@ class TC_GAME_API Map : public GridRefManager BattlegroundMap* ToBattlegroundMap() { if (IsBattlegroundOrArena()) return reinterpret_cast(this); else return nullptr; } BattlegroundMap const* ToBattlegroundMap() const { if (IsBattlegroundOrArena()) return reinterpret_cast(this); return nullptr; } - float GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground = nullptr, bool swim = false, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h - float GetGridHeight(uint32 mapId, float x, float y) const; + float GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground = nullptr, bool swim = false, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h + float GetGridHeight(uint32 mapId, float x, float y); - float GetHeight(PhaseShift const& phaseShift, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const { return std::max(GetStaticHeight(phaseShift, x, y, z, vmap, maxSearchDist), GetGameObjectFloor(phaseShift, x, y, z, maxSearchDist)); } - float GetHeight(PhaseShift const& phaseShift, Position const& pos, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const { return GetHeight(phaseShift, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), vmap, maxSearchDist); } + float GetHeight(PhaseShift const& phaseShift, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) { return std::max(GetStaticHeight(phaseShift, x, y, z, vmap, maxSearchDist), GetGameObjectFloor(phaseShift, x, y, z, maxSearchDist)); } + float GetHeight(PhaseShift const& phaseShift, Position const& pos, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) { return GetHeight(phaseShift, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), vmap, maxSearchDist); } bool isInLineOfSight(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const; void Balance() { _dynamicTree.balance(); } @@ -673,7 +682,6 @@ class TC_GAME_API Map : public GridRefManager void UnloadMap(int gx, int gy); static void UnloadMapImpl(Map* map, int gx, int gy); void LoadMMap(int gx, int gy); - GridMap* GetGrid(float x, float y); GridMap* GetGrid(uint32 mapId, float x, float y); void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; } @@ -767,8 +775,9 @@ class TC_GAME_API Map : public GridRefManager std::vector* m_childTerrainMaps; // contains m_parentMap of maps that have MapEntry::ParentMapID == GetId() NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; - GridMap* GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; + std::shared_ptr GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; uint16 GridMapReference[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; + std::bitset i_gridFileExists; // cache what grids are available for this map (not including parent/child maps) std::bitset marked_cells; //these functions used to process player/mob aggro reactions and diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index 938adae50b..6dd058a69e 100644 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -104,6 +104,8 @@ Map* MapManager::CreateBaseMap_i(MapEntry const* mapEntry) else map = new Map(mapEntry->ID, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY); + map->DiscoverGridMapFiles(); + i_maps[mapEntry->ID] = map; for (uint32 childMapId : _parentMapData[mapEntry->ID]) @@ -287,16 +289,15 @@ bool MapManager::IsValidMAP(uint32 mapid, bool startUp) void MapManager::UnloadAll() { - // first unlink child maps + // first unload maps for (auto iter = i_maps.begin(); iter != i_maps.end(); ++iter) - iter->second->UnlinkAllChildTerrainMaps(); - - for (MapMapType::iterator iter = i_maps.begin(); iter != i_maps.end();) - { iter->second->UnloadAll(); + + // then delete them + for (auto iter = i_maps.begin(); iter != i_maps.end(); ++iter) delete iter->second; - i_maps.erase(iter++); - } + + i_maps.clear(); if (m_updater.activated()) m_updater.deactivate(); diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h index afea2163e8..07a680079d 100644 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -39,29 +39,29 @@ class TC_GAME_API MapManager Map* CreateMap(uint32 mapId, Player* player, uint32 loginInstanceId=0); Map* FindMap(uint32 mapId, uint32 instanceId) const; - uint32 GetAreaId(PhaseShift const& phaseShift, uint32 mapid, float x, float y, float z) const + uint32 GetAreaId(PhaseShift const& phaseShift, uint32 mapid, float x, float y, float z) { - Map const* m = const_cast(this)->CreateBaseMap(mapid); + Map* m = const_cast(this)->CreateBaseMap(mapid); return m->GetAreaId(phaseShift, x, y, z); } - uint32 GetAreaId(PhaseShift const& phaseShift, uint32 mapid, Position const& pos) const { return GetAreaId(phaseShift, mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } - uint32 GetAreaId(PhaseShift const& phaseShift, WorldLocation const& loc) const { return GetAreaId(phaseShift, loc.GetMapId(), loc); } - uint32 GetZoneId(PhaseShift const& phaseShift, uint32 mapid, float x, float y, float z) const + uint32 GetAreaId(PhaseShift const& phaseShift, uint32 mapid, Position const& pos) { return GetAreaId(phaseShift, mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } + uint32 GetAreaId(PhaseShift const& phaseShift, WorldLocation const& loc) { return GetAreaId(phaseShift, loc.GetMapId(), loc); } + uint32 GetZoneId(PhaseShift const& phaseShift, uint32 mapid, float x, float y, float z) { - Map const* m = const_cast(this)->CreateBaseMap(mapid); + Map* m = const_cast(this)->CreateBaseMap(mapid); return m->GetZoneId(phaseShift, x, y, z); } - uint32 GetZoneId(PhaseShift const& phaseShift, uint32 mapid, Position const& pos) const { return GetZoneId(phaseShift, mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } - uint32 GetZoneId(PhaseShift const& phaseShift, WorldLocation const& loc) const { return GetZoneId(phaseShift, loc.GetMapId(), loc); } - void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z) const + uint32 GetZoneId(PhaseShift const& phaseShift, uint32 mapid, Position const& pos) { return GetZoneId(phaseShift, mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } + uint32 GetZoneId(PhaseShift const& phaseShift, WorldLocation const& loc) { return GetZoneId(phaseShift, loc.GetMapId(), loc); } + void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z) { - Map const* m = const_cast(this)->CreateBaseMap(mapid); + Map* m = const_cast(this)->CreateBaseMap(mapid); m->GetZoneAndAreaId(phaseShift, zoneid, areaid, x, y, z); } - void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, uint32 mapid, Position const& pos) const { GetZoneAndAreaId(phaseShift, zoneid, areaid, mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } - void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, WorldLocation const& loc) const { GetZoneAndAreaId(phaseShift, zoneid, areaid, loc.GetMapId(), loc); } + void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, uint32 mapid, Position const& pos) { GetZoneAndAreaId(phaseShift, zoneid, areaid, mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } + void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, WorldLocation const& loc) { GetZoneAndAreaId(phaseShift, zoneid, areaid, loc.GetMapId(), loc); } - void Initialize(void); + void Initialize(); void InitializeParentMapData(std::unordered_map> const& mapData); void Update(uint32); diff --git a/src/server/game/Phasing/PhasingHandler.cpp b/src/server/game/Phasing/PhasingHandler.cpp index 69aba609be..ee07f0507e 100644 --- a/src/server/game/Phasing/PhasingHandler.cpp +++ b/src/server/game/Phasing/PhasingHandler.cpp @@ -483,16 +483,9 @@ uint32 PhasingHandler::GetTerrainMapId(PhaseShift const& phaseShift, Map const* int32 gx = (MAX_NUMBER_OF_GRIDS - 1) - gridCoord.x_coord; int32 gy = (MAX_NUMBER_OF_GRIDS - 1) - gridCoord.y_coord; - int32 gxbegin = std::max(gx - 1, 0); - int32 gxend = std::min(gx + 1, MAX_NUMBER_OF_GRIDS); - int32 gybegin = std::max(gy - 1, 0); - int32 gyend = std::min(gy + 1, MAX_NUMBER_OF_GRIDS); - - for (auto itr = phaseShift.VisibleMapIds.rbegin(); itr != phaseShift.VisibleMapIds.rend(); ++itr) - for (int32 gxi = gxbegin; gxi < gxend; ++gxi) - for (int32 gyi = gybegin; gyi < gyend; ++gyi) - if (map->HasGrid(itr->first, gxi, gyi)) - return itr->first; + for (std::pair const& visibleMap : phaseShift.VisibleMapIds) + if (map->HasChildMapGridFile(visibleMap.first, gx, gy)) + return visibleMap.first; return map->GetId(); } diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index b7b20ffdf7..2a7312ef7f 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -242,7 +242,7 @@ public: else player->SaveRecallPosition(); - Map const* map = sMapMgr->CreateBaseMap(mapId); + Map* map = sMapMgr->CreateBaseMap(mapId); float z = std::max(map->GetHeight(PhasingHandler::GetEmptyPhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(PhasingHandler::GetEmptyPhaseShift(), x, y)); player->TeleportTo(mapId, x, y, z, player->GetOrientation()); @@ -314,7 +314,7 @@ public: AreaTableEntry const* zoneEntry = areaEntry->ParentAreaID ? sAreaTableStore.LookupEntry(areaEntry->ParentAreaID) : areaEntry; ASSERT(zoneEntry); - Map const* map = sMapMgr->CreateBaseMap(zoneEntry->ContinentID); + Map* map = sMapMgr->CreateBaseMap(zoneEntry->ContinentID); if (map->Instanceable()) { @@ -371,7 +371,7 @@ public: handler->SetSentErrorMessage(true); return false; } - Map const* map = sMapMgr->CreateBaseMap(mapId); + Map* map = sMapMgr->CreateBaseMap(mapId); z = std::max(map->GetHeight(PhasingHandler::GetEmptyPhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(PhasingHandler::GetEmptyPhaseShift(), x, y)); } diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp index d16d90cbb0..4e2d1ca2fe 100644 --- a/src/server/scripts/Commands/cs_list.cpp +++ b/src/server/scripts/Commands/cs_list.cpp @@ -688,7 +688,7 @@ public: static bool HandleListRespawnsCommand(ChatHandler* handler, char const* args) { Player const* player = handler->GetSession()->GetPlayer(); - Map const* map = player->GetMap(); + Map* map = player->GetMap(); uint32 range = 0; if (*args) diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index f8b04b198d..856b12f4f2 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -252,7 +252,7 @@ public: sDBCManager.Map2ZoneCoordinates(zoneX, zoneY, zoneId); - Map const* map = object->GetMap(); + Map* map = object->GetMap(); float groundZ = object->GetMapHeight(object->GetPositionX(), object->GetPositionY(), MAX_HEIGHT); float floorZ = object->GetMapHeight(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ()); diff --git a/src/server/scripts/EasternKingdoms/Deadmines/boss_foe_reaper_5000.cpp b/src/server/scripts/EasternKingdoms/Deadmines/boss_foe_reaper_5000.cpp index eaca3eade3..71c060e2cb 100644 --- a/src/server/scripts/EasternKingdoms/Deadmines/boss_foe_reaper_5000.cpp +++ b/src/server/scripts/EasternKingdoms/Deadmines/boss_foe_reaper_5000.cpp @@ -327,7 +327,7 @@ class boss_foe_reaper_5000 : public CreatureScript // and use our own position instead of our home position float respX, respY, respZ, respO, destX, destY, destZ, travelDistZ; me->GetPosition(respX, respY, respZ, respO); - Map const* map = me->GetMap(); + Map* map = me->GetMap(); const float angle = float(rand_norm()) * static_cast(M_PI * 2.0f); const float range = 15.0f; const float distanceX = range * std::cos(angle);