aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Player/Player.cpp4
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp2
-rw-r--r--src/server/game/Maps/Map.cpp148
-rw-r--r--src/server/game/Maps/Map.h13
-rw-r--r--src/server/game/Maps/MapManager.cpp56
-rw-r--r--src/server/game/Maps/MapManager.h10
-rw-r--r--src/server/game/Phasing/PhasingHandler.cpp7
-rw-r--r--src/server/game/Phasing/PhasingHandler.h1
-rw-r--r--src/server/game/World/World.cpp2
-rw-r--r--src/server/scripts/Commands/cs_go.cpp9
-rw-r--r--src/server/scripts/Commands/cs_tele.cpp3
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp2
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp2
13 files changed, 184 insertions, 75 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 68d5024e959..ffe6349e161 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -2132,7 +2132,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)
@@ -6946,7 +6946,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 737f1952348..dc8604fa2e8 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -6252,7 +6252,7 @@ WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveYard(WorldLocation const& lo
uint32 MapId = location.GetMapId();
// 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 6ece7791b6e..c3e1aa744d3 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -85,6 +85,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);
}
@@ -171,42 +174,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/%04u_%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<MapInstanced*>(map->m_parentMap)->RemoveGridMapReference(GridCoord(gx, gy));
+
+ map->GridMaps[gx][gy] = nullptr;
}
void Map::LoadMapAndVMap(int gx, int gy)
@@ -229,10 +255,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()
@@ -252,14 +278,24 @@ m_activeNonPlayersIter(m_activeNonPlayers.end()), _transportsUpdateIter(_transpo
i_gridExpiry(expiry),
i_scriptLock(false), _defaultLight(DB2Manager::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<Map*>();
+ }
+
+ 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);
}
}
@@ -1782,20 +1818,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;
@@ -1881,6 +1913,7 @@ GridMap::GridMap()
_liquidEntry = nullptr;
_liquidFlags = nullptr;
_liquidMap = nullptr;
+ _fileExists = false;
}
GridMap::~GridMap()
@@ -1899,6 +1932,7 @@ bool GridMap::loadData(const char* filename)
if (!in)
return true;
+ _fileExists = true;
if (fread(&header, sizeof(header), 1, in) != 1)
{
fclose(in);
@@ -1957,6 +1991,7 @@ void GridMap::unloadData()
_liquidFlags = nullptr;
_liquidMap = nullptr;
_gridGetHeight = &GridMap::getHeightFromFlat;
+ _fileExists = false;
}
bool GridMap::loadAreaData(FILE* in, uint32 offset, uint32 /*size*/)
@@ -2500,6 +2535,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<Map*>(this)->GetGrid(x, y))
@@ -2522,7 +2577,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<Map*>(this)->GetGrid(x, y))
+ uint32 terrainMapId = phaseShift.GetTerrainMapId(GetId(), x, y);
+ if (GridMap* gmap = const_cast<Map*>(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
@@ -2535,7 +2591,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
@@ -2614,11 +2670,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<Map*>(this)->GetGrid(x, y))
+ if (GridMap* gmap = const_cast<Map*>(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...
@@ -2652,7 +2709,7 @@ uint32 Map::GetAreaId(PhaseShift const& phaseShift, float x, float y, float z, b
if (!areaId)
{
- if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
+ if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(phaseShift.GetTerrainMapId(GetId(), x, y), x, y))
areaId = gmap->getArea(x, y);
// this used while not all *.map files generated (instances)
@@ -2693,9 +2750,9 @@ void Map::GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32&
zoneid = area->ParentAreaID;
}
-uint8 Map::GetTerrainType(float x, float y) const
+uint8 Map::GetTerrainType(PhaseShift const& phaseShift, float x, float y) const
{
- if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
+ if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(phaseShift.GetTerrainMapId(GetId(), x, y), x, y))
return gmap->getTerrainType(x, y);
else
return 0;
@@ -2708,7 +2765,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
@@ -2765,7 +2823,7 @@ ZLiquidStatus Map::getLiquidStatus(PhaseShift const& phaseShift, float x, float
}
}
- if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
+ if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(terrainMapId, x, y))
{
LiquidData map_data;
ZLiquidStatus map_result = gmap->getLiquidStatus(x, y, z, ReqLiquidType, &map_data);
@@ -2786,9 +2844,9 @@ ZLiquidStatus Map::getLiquidStatus(PhaseShift const& phaseShift, float x, float
return result;
}
-float Map::GetWaterLevel(float x, float y) const
+float Map::GetWaterLevel(PhaseShift const& phaseShift, float x, float y) const
{
- if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
+ if (GridMap* gmap = const_cast<Map*>(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 065efc203ad..b2a0cb91551 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -198,7 +198,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);
@@ -224,6 +224,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)
@@ -330,6 +331,8 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
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
@@ -346,8 +349,8 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
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;
@@ -571,8 +574,11 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
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; }
@@ -672,6 +678,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
//used for fast base_map (e.g. MapInstanced class object) search for
//InstanceMaps and BattlegroundMaps...
Map* m_parentMap;
+ std::vector<Map*>* 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 d380e1be018..0b6bec91781 100644
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -55,10 +55,15 @@ void MapManager::Initialize()
m_updater.activate(num_threads);
}
+void MapManager::InitializeParentMapData(std::unordered_map<uint32, std::vector<uint32>> 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()
@@ -71,29 +76,46 @@ Map* MapManager::CreateBaseMap(uint32 id)
{
Map* map = FindBaseMap(id);
- if (map == NULL)
+ if (!map)
{
- std::lock_guard<std::mutex> 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->ParentMapID != -1)
{
- map = new Map(id, i_gridCleanUpDelay, 0, DIFFICULTY_NONE);
- map->LoadRespawnTimes();
- map->LoadCorpseData();
+ CreateBaseMap(entry->ParentMapID);
+
+ // must have been created by parent map
+ map = FindBaseMap(id);
+ return ASSERT_NOTNULL(map);
}
- i_maps[id] = map;
+ std::lock_guard<std::mutex> 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->ID, i_gridCleanUpDelay);
+ else
+ {
+ map = new Map(mapEntry->ID, i_gridCleanUpDelay, 0, DIFFICULTY_NONE);
+ map->LoadRespawnTimes();
+ map->LoadCorpseData();
+ }
+
+ i_maps[mapEntry->ID] = map;
+
+ for (uint32 childMapId : _parentMapData[mapEntry->ID])
+ map->AddChildTerrainMap(CreateBaseMap_i(sMapStore.AssertEntry(childMapId)));
+
+ return map;
+}
+
Map* MapManager::FindBaseNonInstanceMap(uint32 mapId) const
{
Map* map = FindBaseMap(mapId);
@@ -257,6 +279,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 892756db0d4..a8c4007118e 100644
--- a/src/server/game/Maps/MapManager.h
+++ b/src/server/game/Maps/MapManager.h
@@ -56,6 +56,7 @@ class TC_GAME_API MapManager
}
void Initialize(void);
+ void InitializeParentMapData(std::unordered_map<uint32, std::vector<uint32>> const& mapData);
void Update(uint32);
void SetGridCleanUpDelay(uint32 t)
@@ -145,8 +146,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;
@@ -159,6 +162,9 @@ class TC_GAME_API MapManager
// atomic op counter for active scripts amount
std::atomic<std::size_t> _scheduledScripts;
+
+ // parent map links
+ std::unordered_map<uint32, std::vector<uint32>> _parentMapData;
};
template<typename Worker>
diff --git a/src/server/game/Phasing/PhasingHandler.cpp b/src/server/game/Phasing/PhasingHandler.cpp
index 08ed3f729b0..44f0a9ff753 100644
--- a/src/server/game/Phasing/PhasingHandler.cpp
+++ b/src/server/game/Phasing/PhasingHandler.cpp
@@ -31,6 +31,8 @@
namespace
{
+PhaseShift const Empty;
+
inline PhaseFlags GetPhaseFlags(uint32 phaseId)
{
if (PhaseEntry const* phase = sPhaseStore.LookupEntry(phaseId))
@@ -420,6 +422,11 @@ void PhasingHandler::FillPartyMemberPhase(WorldPackets::Party::PartyMemberPhaseS
[](PhaseShift::PhaseRef const& phase) -> WorldPackets::Party::PartyMemberPhase { return { phase.Flags.AsUnderlyingType(), phase.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 e759f2e68e1..9ee408ad26c 100644
--- a/src/server/game/Phasing/PhasingHandler.h
+++ b/src/server/game/Phasing/PhasingHandler.h
@@ -55,6 +55,7 @@ public:
static void SendToPlayer(Player const* player);
static void FillPartyMemberPhase(WorldPackets::Party::PartyMemberPhaseStates* partyMemberPhases, 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 125e9036e64..9e73cc8d532 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1585,6 +1585,8 @@ void World::SetInitialWorldSettings()
mapData[mapEntry->ParentMapID].push_back(mapEntry->ID);
}
+ sMapMgr->InitializeParentMapData(mapData);
+
if (VMAP::VMapManager2* vmmgr2 = dynamic_cast<VMAP::VMapManager2*>(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 09a31c885b7..cbd594f6682 100644
--- a/src/server/scripts/Commands/cs_go.cpp
+++ b/src/server/scripts/Commands/cs_go.cpp
@@ -29,6 +29,7 @@ EndScriptData */
#include "MapManager.h"
#include "MotionMaster.h"
#include "ObjectMgr.h"
+#include "PhasingHandler.h"
#include "Player.h"
#include "RBAC.h"
#include "SupportMgr.h"
@@ -247,7 +248,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;
@@ -369,7 +370,7 @@ public:
player->SaveRecallPosition();
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));
player->TeleportTo(mapId, x, y, z, 0.0f);
return true;
@@ -532,7 +533,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->ContinentID, x, y, z, player->GetOrientation());
return true;
@@ -580,7 +581,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 79113971fe4..658a0ed446b 100644
--- a/src/server/scripts/Commands/cs_tele.cpp
+++ b/src/server/scripts/Commands/cs_tele.cpp
@@ -31,6 +31,7 @@ EndScriptData */
#include "MapManager.h"
#include "MotionMaster.h"
#include "ObjectMgr.h"
+#include "PhasingHandler.h"
#include "Player.h"
#include "RBAC.h"
#include "WorldSession.h"
@@ -207,7 +208,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 1bfd96f0e35..7154bd11a9d 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
@@ -272,7 +272,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 64c8bb0db1d..2f6b624bc08 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp
@@ -309,7 +309,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)))