From b9d0ab6ed815a95380a7526010946ddaf6837774 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Sat, 10 Mar 2018 13:52:56 +0100 Subject: [PATCH] Core/Maps: Implemented loading swapped maps --- src/server/game/Entities/Player/Player.cpp | 4 +- src/server/game/Globals/ObjectMgr.cpp | 2 +- src/server/game/Maps/Map.cpp | 149 ++++++++++++------ src/server/game/Maps/Map.h | 13 +- src/server/game/Maps/MapManager.cpp | 56 +++++-- src/server/game/Maps/MapManager.h | 10 +- src/server/game/Phasing/PhasingHandler.cpp | 7 + src/server/game/Phasing/PhasingHandler.h | 1 + src/server/game/World/World.cpp | 2 + src/server/scripts/Commands/cs_go.cpp | 7 +- src/server/scripts/Commands/cs_tele.cpp | 3 +- .../instance_the_black_morass.cpp | 2 +- .../TheBlackMorass/the_black_morass.cpp | 2 +- 13 files changed, 184 insertions(+), 74 deletions(-) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index b75dd0a1e1..00f4a87ada 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2561,7 +2561,7 @@ GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid const& guid, Gameo bool Player::IsUnderWater() const { return IsInWater() && - GetPositionZ() < (GetBaseMap()->GetWaterLevel(GetPositionX(), GetPositionY())-2); + GetPositionZ() < (GetBaseMap()->GetWaterLevel(GetPhaseShift(), GetPositionX(), GetPositionY())-2); } void Player::SetInWater(bool apply) @@ -7357,7 +7357,7 @@ uint32 Player::GetZoneIdFromDB(ObjectGuid guid) if (!sMapStore.LookupEntry(map)) return 0; - zone = sMapMgr->GetZoneId(PhaseShift(), map, posx, posy, posz); + zone = sMapMgr->GetZoneId(PhasingHandler::GetEmptyPhaseShift(), map, posx, posy, posz); if (zone > 0) { diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 505cd405b5..836b141487 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -6338,7 +6338,7 @@ WorldSafeLocsEntry const* ObjectMgr::GetDefaultGraveYard(uint32 team) const WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveYard(float x, float y, float z, uint32 MapId, uint32 team) const { // search for zone associated closest graveyard - uint32 zoneId = sMapMgr->GetZoneId(PhaseShift(), MapId, x, y, z); + uint32 zoneId = sMapMgr->GetZoneId(PhasingHandler::GetEmptyPhaseShift(), MapId, x, y, z); if (!zoneId) { diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 9fbb2a2da4..efede81689 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -67,6 +67,9 @@ Map::~Map() if (!m_scriptSchedule.empty()) sMapMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size()); + if (m_parentMap != this) + delete m_childTerrainMaps; + MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(GetId(), i_InstanceId); } @@ -160,42 +163,65 @@ void Map::LoadVMap(int gx, int gy) void Map::LoadMap(int gx, int gy, bool reload) { - if (i_InstanceId != 0) + LoadMapImpl(this, gx, gy, reload); + for (Map* childBaseMap : *m_childTerrainMaps) + LoadMapImpl(childBaseMap, gx, gy, reload); +} + +void Map::LoadMapImpl(Map* map, int gx, int gy, bool reload) +{ + if (map->i_InstanceId != 0) { - if (GridMaps[gx][gy]) + if (map->GridMaps[gx][gy]) return; // load grid map for base map - if (!m_parentMap->GridMaps[gx][gy]) - m_parentMap->EnsureGridCreated(GridCoord((MAX_NUMBER_OF_GRIDS - 1) - gx, (MAX_NUMBER_OF_GRIDS - 1) - gy)); + if (!map->m_parentMap->GridMaps[gx][gy]) + map->m_parentMap->EnsureGridCreated(GridCoord((MAX_NUMBER_OF_GRIDS - 1) - gx, (MAX_NUMBER_OF_GRIDS - 1) - gy)); - ((MapInstanced*)(m_parentMap))->AddGridMapReference(GridCoord(gx, gy)); - GridMaps[gx][gy] = m_parentMap->GridMaps[gx][gy]; + map->m_parentMap->ToMapInstanced()->AddGridMapReference(GridCoord(gx, gy)); + map->GridMaps[gx][gy] = map->m_parentMap->GridMaps[gx][gy]; return; } - if (GridMaps[gx][gy] && !reload) + if (map->GridMaps[gx][gy] && !reload) return; //map already load, delete it before reloading (Is it necessary? Do we really need the ability the reload maps during runtime?) - if (GridMaps[gx][gy]) + if (map->GridMaps[gx][gy]) { - TC_LOG_DEBUG("maps", "Unloading previously loaded map %u before reloading.", GetId()); - sScriptMgr->OnUnloadGridMap(this, GridMaps[gx][gy], gx, gy); + TC_LOG_DEBUG("maps", "Unloading previously loaded map %u before reloading.", map->GetId()); + sScriptMgr->OnUnloadGridMap(map, map->GridMaps[gx][gy], gx, gy); - delete (GridMaps[gx][gy]); - GridMaps[gx][gy]=NULL; + delete map->GridMaps[gx][gy]; + map->GridMaps[gx][gy] = nullptr; } // map file name - std::string fileName = Trinity::StringFormat("%smaps/%03u%02u%02u.map", sWorld->GetDataPath().c_str(), GetId(), gx, gy); + std::string fileName = Trinity::StringFormat("%smaps/%04u_%02u_%02u.map", sWorld->GetDataPath().c_str(), map->GetId(), gx, gy); TC_LOG_DEBUG("maps", "Loading map %s", fileName.c_str()); // loading data - GridMaps[gx][gy] = new GridMap(); - if (!GridMaps[gx][gy]->loadData(fileName.c_str())) + 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()); - sScriptMgr->OnLoadGridMap(this, GridMaps[gx][gy], gx, gy); + sScriptMgr->OnLoadGridMap(map, map->GridMaps[gx][gy], gx, gy); +} + +void Map::UnloadMap(Map* map, int gx, int gy) +{ + if (map->i_InstanceId == 0) + { + if (map->GridMaps[gx][gy]) + { + map->GridMaps[gx][gy]->unloadData(); + delete map->GridMaps[gx][gy]; + } + } + else + static_cast(map->m_parentMap)->RemoveGridMapReference(GridCoord(gx, gy)); + + map->GridMaps[gx][gy] = nullptr; } void Map::LoadMapAndVMap(int gx, int gy) @@ -218,10 +244,10 @@ void Map::LoadAllCells() void Map::InitStateMachine() { - si_GridStates[GRID_STATE_INVALID] = new InvalidState; - si_GridStates[GRID_STATE_ACTIVE] = new ActiveState; - si_GridStates[GRID_STATE_IDLE] = new IdleState; - si_GridStates[GRID_STATE_REMOVAL] = new RemovalState; + si_GridStates[GRID_STATE_INVALID] = new InvalidState(); + si_GridStates[GRID_STATE_ACTIVE] = new ActiveState(); + si_GridStates[GRID_STATE_IDLE] = new IdleState(); + si_GridStates[GRID_STATE_REMOVAL] = new RemovalState(); } void Map::DeleteStateMachine() @@ -241,14 +267,24 @@ m_activeNonPlayersIter(m_activeNonPlayers.end()), _transportsUpdateIter(_transpo i_gridExpiry(expiry), i_scriptLock(false), _defaultLight(GetDefaultMapLight(id)) { - m_parentMap = (_parent ? _parent : this); - for (unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx) + if (_parent) { - for (unsigned int j=0; j < MAX_NUMBER_OF_GRIDS; ++j) + m_parentMap = _parent; + m_childTerrainMaps = m_parentMap->m_childTerrainMaps; + } + else + { + m_parentMap = this; + m_childTerrainMaps = new std::vector(); + } + + for (uint32 x = 0; x < MAX_NUMBER_OF_GRIDS; ++x) + { + for (uint32 y = 0; y < MAX_NUMBER_OF_GRIDS; ++y) { //z code - GridMaps[idx][j] =NULL; - setNGrid(NULL, idx, j); + GridMaps[x][y] = nullptr; + setNGrid(nullptr, x, y); } } @@ -1594,20 +1630,16 @@ 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]) don't check for GridMaps[gx][gy], we might have to unload vmaps { + for (Map* childBaseMap : *m_childTerrainMaps) + UnloadMap(childBaseMap, gx, gy); + + UnloadMap(this, gx, gy); + if (i_InstanceId == 0) { - if (GridMaps[gx][gy]) - { - GridMaps[gx][gy]->unloadData(); - delete GridMaps[gx][gy]; - } VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gx, gy); MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(GetId(), gx, gy); } - else - ((MapInstanced*)m_parentMap)->RemoveGridMapReference(GridCoord(gx, gy)); - - GridMaps[gx][gy] = NULL; } TC_LOG_DEBUG("maps", "Unloading grid[%u, %u] for map %u finished", x, y, GetId()); return true; @@ -1691,6 +1723,7 @@ GridMap::GridMap() _liquidEntry = nullptr; _liquidFlags = nullptr; _liquidMap = nullptr; + _fileExists = false; } GridMap::~GridMap() @@ -1709,6 +1742,8 @@ bool GridMap::loadData(const char* filename) if (!in) return true; + _fileExists = true; + if (fread(&header, sizeof(header), 1, in) != 1) { fclose(in); @@ -1763,6 +1798,7 @@ void GridMap::unloadData() _liquidFlags = nullptr; _liquidMap = nullptr; _gridGetHeight = &GridMap::getHeightFromFlat; + _fileExists = false; } bool GridMap::loadAreaData(FILE* in, uint32 offset, uint32 /*size*/) @@ -2237,6 +2273,26 @@ inline GridMap* Map::GetGrid(float x, float y) 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 + + // ensure GridMap is loaded + EnsureGridCreated(GridCoord((MAX_NUMBER_OF_GRIDS - 1) - gx, (MAX_NUMBER_OF_GRIDS - 1) - gy)); + + GridMap* grid = GridMaps[gx][gy]; + 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]->fileExists()) + grid = (*childMapItr)->GridMaps[gx][gy]; + + return grid; +} + float Map::GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground /*= nullptr*/, bool /*swim = false*/) const { if (const_cast(this)->GetGrid(x, y)) @@ -2267,7 +2323,8 @@ float Map::GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float { // find raw .map surface under Z coordinates float mapHeight = VMAP_INVALID_HEIGHT_VALUE; - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + uint32 terrainMapId = phaseShift.GetTerrainMapId(GetId(), x, y); + if (GridMap* gmap = const_cast(this)->GetGrid(terrainMapId, x, y)) { float gridHeight = gmap->getHeight(x, y); // look from a bit higher pos to find the floor, ignore under surface case @@ -2280,7 +2337,7 @@ float Map::GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float { VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); if (vmgr->isHeightCalcEnabled()) - vmapHeight = vmgr->getHeight(phaseShift.GetTerrainMapId(GetId(), x, y), x, y, z + 2.0f, maxSearchDist); // look from a bit higher pos to find the floor + vmapHeight = vmgr->getHeight(terrainMapId, x, y, z + 2.0f, maxSearchDist); // look from a bit higher pos to find the floor } // mapHeight set for any above raw ground Z or <= INVALID_HEIGHT @@ -2351,11 +2408,12 @@ bool Map::IsOutdoors(PhaseShift const& phaseShift, float x, float y, float z) co bool Map::GetAreaInfo(PhaseShift const& phaseShift, float x, float y, float z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const { float vmap_z = z; + uint32 terrainMapId = phaseShift.GetTerrainMapId(GetId(), x, y); VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); - if (vmgr->getAreaInfo(phaseShift.GetTerrainMapId(GetId(), x, y), x, y, vmap_z, flags, adtId, rootId, groupId)) + if (vmgr->getAreaInfo(terrainMapId, x, y, vmap_z, flags, adtId, rootId, groupId)) { // check if there's terrain between player height and object height - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridMap* gmap = const_cast(this)->GetGrid(terrainMapId, x, y)) { float _mapheight = gmap->getHeight(x, y); // z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice... @@ -2389,7 +2447,7 @@ uint32 Map::GetAreaId(PhaseShift const& phaseShift, float x, float y, float z, b areaId = atEntry->ID; else { - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridMap* gmap = const_cast(this)->GetGrid(phaseShift.GetTerrainMapId(GetId(), x, y), x, y)) areaId = gmap->getArea(x, y); // this used while not all *.map files generated (instances) @@ -2425,9 +2483,9 @@ void Map::GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& zoneid = area->zone; } -uint8 Map::GetTerrainType(float x, float y) const +uint8 Map::GetTerrainType(PhaseShift const& phaseShift, float x, float y) const { - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridMap* gmap = const_cast(this)->GetGrid(phaseShift.GetTerrainMapId(GetId(), x, y), x, y)) return gmap->getTerrainType(x, y); else return 0; @@ -2440,7 +2498,8 @@ ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float float liquid_level = INVALID_HEIGHT; float ground_level = INVALID_HEIGHT; uint32 liquid_type = 0; - if (vmgr->GetLiquidLevel(phaseShift.GetTerrainMapId(GetId(), x, y), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type)) + uint32 terrainMapId = phaseShift.GetTerrainMapId(GetId(), x, y); + if (vmgr->GetLiquidLevel(terrainMapId, x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type)) { TC_LOG_DEBUG("maps", "GetLiquidStatus(): vmap liquid level: %f ground: %f type: %u", liquid_level, ground_level, liquid_type); // Check water level and ground level @@ -2497,7 +2556,7 @@ ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float } } - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridMap* gmap = const_cast(this)->GetGrid(terrainMapId, x, y)) { LiquidData map_data; ZLiquidStatus map_result = gmap->GetLiquidStatus(x, y, z, ReqLiquidType, &map_data); @@ -2619,9 +2678,9 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul } } -float Map::GetWaterLevel(float x, float y) const +float Map::GetWaterLevel(PhaseShift const& phaseShift, float x, float y) const { - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridMap* gmap = const_cast(this)->GetGrid(phaseShift.GetTerrainMapId(GetId(), x, y), x, y)) return gmap->getLiquidLevel(x, y); else return 0; diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 8fd5e27cd3..794bc7e0df 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -215,7 +215,7 @@ class TC_GAME_API GridMap uint8 _liquidOffY; uint8 _liquidWidth; uint8 _liquidHeight; - + bool _fileExists; bool loadAreaData(FILE* in, uint32 offset, uint32 size); bool loadHeightData(FILE* in, uint32 offset, uint32 size); @@ -240,6 +240,7 @@ public: float getLiquidLevel(float x, float y) const; uint8 getTerrainType(float x, float y) const; ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0); + bool fileExists() const { return _fileExists; } }; #pragma pack(push, 1) @@ -356,6 +357,8 @@ class TC_GAME_API Map : public GridRefManager static void DeleteStateMachine(); Map const* GetParent() const { return m_parentMap; } + void AddChildTerrainMap(Map* map) { m_childTerrainMaps->push_back(map); } + 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 @@ -371,8 +374,8 @@ class TC_GAME_API Map : public GridRefManager bool IsOutdoors(PhaseShift const& phaseShift, float x, float y, float z) const; - uint8 GetTerrainType(float x, float y) const; - float GetWaterLevel(float x, float y) const; + uint8 GetTerrainType(PhaseShift const& phaseShift, float x, float y) const; + 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; @@ -607,8 +610,11 @@ class TC_GAME_API Map : public GridRefManager void LoadMapAndVMap(int gx, int gy); void LoadVMap(int gx, int gy); void LoadMap(int gx, int gy, bool reload = false); + static void LoadMapImpl(Map* map, int gx, int gy, bool reload); + static void UnloadMap(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; } @@ -701,6 +707,7 @@ class TC_GAME_API Map : public GridRefManager //used for fast base_map (e.g. MapInstanced class object) search for //InstanceMaps and BattlegroundMaps... Map* m_parentMap; + std::vector* m_childTerrainMaps; NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; GridMap* GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index a3bf5179a6..f34349496d 100644 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -56,10 +56,15 @@ void MapManager::Initialize() m_updater.activate(num_threads); } +void MapManager::InitializeParentMapData(std::unordered_map> const& mapData) +{ + _parentMapData = mapData; +} + void MapManager::InitializeVisibilityDistanceInfo() { - for (MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) - (*iter).second->InitVisibilityDistance(); + for (auto iter = i_maps.begin(); iter != i_maps.end(); ++iter) + iter->second->InitVisibilityDistance(); } MapManager* MapManager::instance() @@ -72,29 +77,46 @@ Map* MapManager::CreateBaseMap(uint32 id) { Map* map = FindBaseMap(id); - if (map == NULL) + if (!map) { - std::lock_guard lock(_mapsLock); - - MapEntry const* entry = sMapStore.LookupEntry(id); - ASSERT(entry); - - if (entry->Instanceable()) - map = new MapInstanced(id, i_gridCleanUpDelay); - else + MapEntry const* entry = sMapStore.AssertEntry(id); + if (entry->rootPhaseMap != -1) { - map = new Map(id, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY); - map->LoadRespawnTimes(); - map->LoadCorpseData(); + CreateBaseMap(entry->rootPhaseMap); + + // must have been created by parent map + map = FindBaseMap(id); + return ASSERT_NOTNULL(map); } - i_maps[id] = map; + std::lock_guard lock(_mapsLock); + map = CreateBaseMap_i(entry); } ASSERT(map); return map; } +Map* MapManager::CreateBaseMap_i(MapEntry const* mapEntry) +{ + Map* map; + if (mapEntry->Instanceable()) + map = new MapInstanced(mapEntry->MapID, i_gridCleanUpDelay); + else + { + map = new Map(mapEntry->MapID, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY); + map->LoadRespawnTimes(); + map->LoadCorpseData(); + } + + i_maps[mapEntry->MapID] = map; + + for (uint32 childMapId : _parentMapData[mapEntry->MapID]) + map->AddChildTerrainMap(CreateBaseMap_i(sMapStore.AssertEntry(childMapId))); + + return map; +} + Map* MapManager::FindBaseNonInstanceMap(uint32 mapId) const { Map* map = FindBaseMap(mapId); @@ -258,6 +280,10 @@ bool MapManager::IsValidMAP(uint32 mapid, bool startUp) void MapManager::UnloadAll() { + // first unlink child 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(); diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h index f875cc2e12..12cf7c0c9c 100644 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -57,6 +57,7 @@ class TC_GAME_API MapManager } void Initialize(void); + void InitializeParentMapData(std::unordered_map> const& mapData); void Update(uint32); void SetGridCleanUpDelay(uint32 t) @@ -143,8 +144,10 @@ class TC_GAME_API MapManager return (iter == i_maps.end() ? NULL : iter->second); } - MapManager(const MapManager &); - MapManager& operator=(const MapManager &); + Map* CreateBaseMap_i(MapEntry const* mapEntry); + + MapManager(MapManager const&) = delete; + MapManager& operator=(MapManager const&) = delete; std::mutex _mapsLock; uint32 i_gridCleanUpDelay; @@ -157,6 +160,9 @@ class TC_GAME_API MapManager // atomic op counter for active scripts amount std::atomic _scheduledScripts; + + // parent map links + std::unordered_map> _parentMapData; }; template diff --git a/src/server/game/Phasing/PhasingHandler.cpp b/src/server/game/Phasing/PhasingHandler.cpp index ef1f2d8008..1a07d1e5ec 100644 --- a/src/server/game/Phasing/PhasingHandler.cpp +++ b/src/server/game/Phasing/PhasingHandler.cpp @@ -29,6 +29,8 @@ namespace { +PhaseShift const Empty; + inline PhaseFlags GetPhaseFlags(uint32 phaseId) { if (PhaseEntry const* phase = sPhaseStore.LookupEntry(phaseId)) @@ -444,6 +446,11 @@ void PhasingHandler::FillPartyMemberPhase(WorldPacket* data, PhaseShift const& p *data << uint16(itr->Id); } +PhaseShift const& PhasingHandler::GetEmptyPhaseShift() +{ + return Empty; +} + void PhasingHandler::InitDbPhaseShift(PhaseShift& phaseShift, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId) { phaseShift.ClearPhases(); diff --git a/src/server/game/Phasing/PhasingHandler.h b/src/server/game/Phasing/PhasingHandler.h index 1c6bf11788..579d7f9de1 100644 --- a/src/server/game/Phasing/PhasingHandler.h +++ b/src/server/game/Phasing/PhasingHandler.h @@ -48,6 +48,7 @@ public: static void SendToPlayer(Player const* player); static void FillPartyMemberPhase(WorldPacket* data, PhaseShift const& phaseShift); + static PhaseShift const& GetEmptyPhaseShift(); static void InitDbPhaseShift(PhaseShift& phaseShift, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId); static void InitDbVisibleMapId(PhaseShift& phaseShift, int32 visibleMapId); static bool InDbPhaseShift(WorldObject const* object, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index cae28cae6f..e2cc1bdbb7 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1512,6 +1512,8 @@ void World::SetInitialWorldSettings() mapData[mapEntry->rootPhaseMap].push_back(mapEntry->MapID); } + sMapMgr->InitializeParentMapData(mapData); + if (VMAP::VMapManager2* vmmgr2 = dynamic_cast(VMAP::VMapFactory::createOrGetVMapManager())) vmmgr2->InitializeThreadUnsafe(mapData); diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index c9aec14d8a..f5d05e927d 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -24,6 +24,7 @@ EndScriptData */ #include "ScriptMgr.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "MapManager.h" #include "TicketMgr.h" #include "Chat.h" @@ -245,7 +246,7 @@ public: player->SaveRecallPosition(); Map const* map = sMapMgr->CreateBaseMap(mapId); - float z = std::max(map->GetStaticHeight(PhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + float z = std::max(map->GetStaticHeight(PhasingHandler::GetEmptyPhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(PhasingHandler::GetEmptyPhaseShift(), x, y)); player->TeleportTo(mapId, x, y, z, player->GetOrientation()); return true; @@ -465,7 +466,7 @@ public: else player->SaveRecallPosition(); - float z = std::max(map->GetStaticHeight(PhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + float z = std::max(map->GetStaticHeight(PhasingHandler::GetEmptyPhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(PhasingHandler::GetEmptyPhaseShift(), x, y)); player->TeleportTo(zoneEntry->mapid, x, y, z, player->GetOrientation()); return true; @@ -513,7 +514,7 @@ public: return false; } Map const* map = sMapMgr->CreateBaseMap(mapId); - z = std::max(map->GetStaticHeight(PhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + z = std::max(map->GetStaticHeight(PhasingHandler::GetEmptyPhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(PhasingHandler::GetEmptyPhaseShift(), x, y)); } // stop flight if need diff --git a/src/server/scripts/Commands/cs_tele.cpp b/src/server/scripts/Commands/cs_tele.cpp index f584254abc..4eb2c7da7c 100644 --- a/src/server/scripts/Commands/cs_tele.cpp +++ b/src/server/scripts/Commands/cs_tele.cpp @@ -27,6 +27,7 @@ EndScriptData */ #include "Language.h" #include "MapManager.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "Player.h" #include "ScriptMgr.h" @@ -202,7 +203,7 @@ public: SQLTransaction dummy; Player::SavePositionInDB(WorldLocation(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation), - sMapMgr->GetZoneId(PhaseShift(), tele->mapId, tele->position_x, tele->position_y, tele->position_z), target_guid, dummy); + sMapMgr->GetZoneId(PhasingHandler::GetEmptyPhaseShift(), tele->mapId, tele->position_x, tele->position_y, tele->position_z), target_guid, dummy); } return true; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp index 7f06698360..789dd0189a 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp @@ -270,7 +270,7 @@ public: Position pos = me->GetRandomNearPosition(10.0f); //normalize Z-level if we can, if rift is not at ground level. - pos.m_positionZ = std::max(me->GetMap()->GetHeight(me->GetPhaseShift(), pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); + pos.m_positionZ = std::max(me->GetMap()->GetHeight(me->GetPhaseShift(), pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(me->GetPhaseShift(), pos.m_positionX, pos.m_positionY)); if (Creature* summon = me->SummonCreature(entry, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000)) return summon; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp index d25214cc73..36a53162a2 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp @@ -305,7 +305,7 @@ public: Position pos = me->GetRandomNearPosition(10.0f); //normalize Z-level if we can, if rift is not at ground level. - pos.m_positionZ = std::max(me->GetMap()->GetHeight(me->GetPhaseShift(), pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); + pos.m_positionZ = std::max(me->GetMap()->GetHeight(me->GetPhaseShift(), pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(me->GetPhaseShift(), pos.m_positionX, pos.m_positionY)); if (Unit* Summon = DoSummon(creature_entry, pos, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) if (Unit* temp = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_MEDIVH)))