TrinityCore
TerrainMgr.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "TerrainMgr.h"
19#include "DB2Stores.h"
20#include "DisableMgr.h"
21#include "DynamicTree.h"
22#include "GridMap.h"
23#include "Log.h"
24#include "Memory.h"
25#include "MMapFactory.h"
26#include "PhasingHandler.h"
27#include "Random.h"
28#include "ScriptMgr.h"
29#include "Util.h"
30#include "VMapFactory.h"
31#include "VMapManager2.h"
32#include "World.h"
33#include <G3D/g3dmath.h>
34
35TerrainInfo::TerrainInfo(uint32 mapId) : _mapId(mapId), _parentTerrain(nullptr), _cleanupTimer(randtime(CleanupInterval / 2, CleanupInterval))
36{
37}
38
40{
43}
44
45char const* TerrainInfo::GetMapName() const
46{
47 return sMapStore.AssertEntry(GetId())->MapName[sWorld->GetDefaultDbcLocale()];
48}
49
51{
52 std::string tileListName = Trinity::StringFormat("{}maps/{:04}.tilelist", sWorld->GetDataPath(), GetId());
53 // tile list is optional
54 if (auto tileList = Trinity::make_unique_ptr_with_deleter(fopen(tileListName.c_str(), "rb"), &::fclose))
55 {
56 u_map_magic mapMagic = { };
57 uint32 versionMagic = { };
58 uint32 build;
59 char tilesData[MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS] = { };
60 if (fread(mapMagic.data(), mapMagic.size(), 1, tileList.get()) == 1
61 && mapMagic == MapMagic
62 && fread(&versionMagic, sizeof(versionMagic), 1, tileList.get()) == 1
63 && versionMagic == MapVersionMagic
64 && fread(&build, sizeof(build), 1, tileList.get()) == 1
65 && fread(&tilesData[0], MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS, 1, tileList.get()) == 1)
66 {
67 _gridFileExists = std::bitset<MAX_NUMBER_OF_GRIDS* MAX_NUMBER_OF_GRIDS>(tilesData, std::size(tilesData));
68 return;
69 }
70 }
71
72 for (int32 gx = 0; gx < MAX_NUMBER_OF_GRIDS; ++gx)
73 for (int32 gy = 0; gy < MAX_NUMBER_OF_GRIDS; ++gy)
74 _gridFileExists[GetBitsetIndex(gx, gy)] = ExistMap(GetId(), gx, gy, false);
75}
76
77bool TerrainInfo::ExistMap(uint32 mapid, int32 gx, int32 gy, bool log /*= true*/)
78{
79 std::string fileName = Trinity::StringFormat("{}maps/{:04}_{:02}_{:02}.map", sWorld->GetDataPath(), mapid, gx, gy);
80
81 bool ret = false;
82 auto file = Trinity::make_unique_ptr_with_deleter(fopen(fileName.c_str(), "rb"), &::fclose);
83 if (!file)
84 {
85 if (log)
86 {
87 TC_LOG_ERROR("maps", "Map file '{}' does not exist!", fileName);
88 TC_LOG_ERROR("maps", "Please place MAP-files (*.map) in the appropriate directory ({}), or correct the DataDir setting in your worldserver.conf file.", (sWorld->GetDataPath() + "maps/"));
89 }
90 }
91 else
92 {
93 map_fileheader header{ };
94 if (fread(&header, sizeof(header), 1, file.get()) == 1)
95 {
96 if (header.mapMagic != MapMagic || header.versionMagic != MapVersionMagic)
97 {
98 if (log)
99 TC_LOG_ERROR("maps", "Map file '{}' is from an incompatible map version (%.*s v{}), %.*s v{} 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.",
100 fileName, 4, header.mapMagic.data(), header.versionMagic, 4, MapMagic.data(), MapVersionMagic);
101 }
102 else
103 ret = true;
104 }
105 }
106
107 return ret;
108}
109
111{
113 {
114 if (vmgr->isMapLoadingEnabled())
115 {
116 VMAP::LoadResult result = vmgr->existsMap((sWorld->GetDataPath() + "vmaps").c_str(), mapid, gx, gy);
117 std::string name = vmgr->getDirFileName(mapid, gx, gy);
118 switch (result)
119 {
121 break;
123 TC_LOG_ERROR("maps", "VMap file '{}' does not exist", (sWorld->GetDataPath() + "vmaps/" + name));
124 TC_LOG_ERROR("maps", "Please place VMAP files (*.vmtree and *.vmtile) in the vmap directory ({}), or correct the DataDir setting in your worldserver.conf file.", (sWorld->GetDataPath() + "vmaps/"));
125 return false;
127 TC_LOG_ERROR("maps", "VMap file '{}' couldn't be loaded", (sWorld->GetDataPath() + "vmaps/" + name));
128 TC_LOG_ERROR("maps", "This is because the version of the VMap file and the version of this module are different, please re-extract the maps with the tools compiled with this module.");
129 return false;
131 TC_LOG_ERROR("maps", "VMap file '{}' couldn't be loaded", (sWorld->GetDataPath() + "vmaps/" + name));
132 TC_LOG_ERROR("maps", "This is because VMAP files are corrupted, please re-extract the maps with the tools compiled with this module.");
133 return false;
135 TC_LOG_ERROR("maps", "VMap file '{}' couldn't be loaded", (sWorld->GetDataPath() + "vmaps/" + name));
136 TC_LOG_ERROR("maps", "This is because VMAP is disabled in config file.");
137 return false;
138 }
139 }
140 }
141
142 return true;
143}
144
146{
147 auto childMapItr = std::find_if(_childTerrain.begin(), _childTerrain.end(), [mapId](std::shared_ptr<TerrainInfo> const& childTerrain) { return childTerrain->GetId() == mapId; });
148 return childMapItr != _childTerrain.end() && (*childMapItr)->_gridFileExists[GetBitsetIndex(gx, gy)];
149}
150
151void TerrainInfo::AddChildTerrain(std::shared_ptr<TerrainInfo> childTerrain)
152{
153 childTerrain->_parentTerrain = this;
154 _childTerrain.emplace_back(std::move(childTerrain));
155}
156
158{
159 if (++_referenceCountFromMap[gx][gy] != 1) // check if already loaded
160 return;
161
162 std::lock_guard<std::mutex> lock(_loadMutex);
163 LoadMapAndVMapImpl(gx, gy);
164}
165
167{
168 LoadMMapInstanceImpl(mapId, instanceId);
169
170 for (std::shared_ptr<TerrainInfo> const& childTerrain : _childTerrain)
171 childTerrain->LoadMMapInstanceImpl(mapId, instanceId);
172}
173
175{
176 LoadMap(gx, gy);
177 LoadVMap(gx, gy);
178 LoadMMap(gx, gy);
179
180 for (std::shared_ptr<TerrainInfo> const& childTerrain : _childTerrain)
181 childTerrain->LoadMapAndVMapImpl(gx, gy);
182
183 _loadedGrids[GetBitsetIndex(gx, gy)] = true;
184}
185
187{
188 MMAP::MMapFactory::createOrGetMMapManager()->loadMapInstance(sWorld->GetDataPath(), _mapId, mapId, instanceId);
189}
190
192{
193 if (_gridMap[gx][gy])
194 return;
195
196 if (!_gridFileExists[GetBitsetIndex(gx, gy)])
197 return;
198
199 // map file name
200 std::string fileName = Trinity::StringFormat("{}maps/{:04}_{:02}_{:02}.map", sWorld->GetDataPath(), GetId(), gx, gy);
201 TC_LOG_DEBUG("maps", "Loading map {}", fileName);
202 // loading data
203 std::unique_ptr<GridMap> gridMap = std::make_unique<GridMap>();
204 GridMap::LoadResult gridMapLoadResult = gridMap->loadData(fileName.c_str());
205 if (gridMapLoadResult == GridMap::LoadResult::Ok)
206 _gridMap[gx][gy] = std::move(gridMap);
207 else
208 _gridFileExists[GetBitsetIndex(gx, gy)] = false;
209
210 if (gridMapLoadResult == GridMap::LoadResult::InvalidFile)
211 TC_LOG_ERROR("maps", "Error loading map file: {}", fileName);
212}
213
215{
216 if (!VMAP::VMapFactory::createOrGetVMapManager()->isMapLoadingEnabled())
217 return;
218 // x and y are swapped !!
219 VMAP::LoadResult vmapLoadResult = VMAP::VMapFactory::createOrGetVMapManager()->loadMap((sWorld->GetDataPath() + "vmaps").c_str(), GetId(), gx, gy);
220 switch (vmapLoadResult)
221 {
223 TC_LOG_DEBUG("maps", "VMAP loaded name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy);
224 break;
227 TC_LOG_ERROR("maps", "Could not load VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy);
228 break;
230 TC_LOG_DEBUG("maps", "Ignored VMAP name:{}, id:{}, x:{}, y:{} (vmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy);
231 break;
232 default:
233 break;
234 }
235}
236
238{
240 return;
241
242 bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap(sWorld->GetDataPath(), GetId(), gx, gy);
243
244 if (mmapLoadResult)
245 TC_LOG_DEBUG("mmaps.tiles", "MMAP loaded name:{}, id:{}, x:{}, y:{} (mmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy);
246 else
247 TC_LOG_WARN("mmaps.tiles", "Could not load MMAP name:{}, id:{}, x:{}, y:{} (mmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy);
248}
249
251{
252 --_referenceCountFromMap[gx][gy];
253 // unload later
254}
255
257{
258 UnloadMMapInstanceImpl(mapId, instanceId);
259
260 for (std::shared_ptr<TerrainInfo> const& childTerrain : _childTerrain)
261 childTerrain->UnloadMMapInstanceImpl(mapId, instanceId);
262}
263
265{
266 _gridMap[gx][gy] = nullptr;
269
270 for (std::shared_ptr<TerrainInfo> const& childTerrain : _childTerrain)
271 childTerrain->UnloadMapImpl(gx, gy);
272
273 _loadedGrids[GetBitsetIndex(gx, gy)] = false;
274}
275
277{
279}
280
281GridMap* TerrainInfo::GetGrid(uint32 mapId, float x, float y, bool loadIfMissing /*= true*/)
282{
283 // half opt method
284 int32 gx = (int)(CENTER_GRID_ID - x / SIZE_OF_GRIDS); //grid x
285 int32 gy = (int)(CENTER_GRID_ID - y / SIZE_OF_GRIDS); //grid y
286
287 // ensure GridMap is loaded
288 if (!_loadedGrids[GetBitsetIndex(gx, gy)] && loadIfMissing)
289 {
290 std::lock_guard<std::mutex> lock(_loadMutex);
291 LoadMapAndVMapImpl(gx, gy);
292 }
293
294 GridMap* grid = _gridMap[gx][gy].get();
295 if (mapId != GetId())
296 {
297 auto childMapItr = std::find_if(_childTerrain.begin(), _childTerrain.end(), [mapId](std::shared_ptr<TerrainInfo> const& childTerrain) { return childTerrain->GetId() == mapId; });
298 if (childMapItr != _childTerrain.end() && (*childMapItr)->_gridMap[gx][gy])
299 grid = (*childMapItr)->GetGrid(mapId, x, y, false);
300 }
301
302 return grid;
303}
304
306{
307 _cleanupTimer.Update(diff);
308 if (!_cleanupTimer.Passed())
309 return;
310
311 // delete those GridMap objects which have refcount = 0
312 for (int32 x = 0; x < MAX_NUMBER_OF_GRIDS; ++x)
313 for (int32 y = 0; y < MAX_NUMBER_OF_GRIDS; ++y)
315 UnloadMapImpl(x, y);
316
318}
319
320static bool IsInWMOInterior(uint32 mogpFlags)
321{
322 return (mogpFlags & 0x2000) != 0;
323}
324
325void TerrainInfo::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, uint32 mapId, float x, float y, float z, PositionFullTerrainStatus& data,
326 Optional<map_liquidHeaderTypeFlags> reqLiquidType, float collisionHeight, DynamicMapTree const* dynamicMapTree)
327{
331 VMAP::AreaAndLiquidData* wmoData = nullptr;
332 uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, mapId, this, x, y);
333 GridMap* gmap = GetGrid(terrainMapId, x, y);
334 vmgr->getAreaAndLiquidData(terrainMapId, x, y, z, reqLiquidType ? AsUnderlyingType(*reqLiquidType) : Optional<uint8>(), vmapData);
335 if (dynamicMapTree)
336 dynamicMapTree->getAreaAndLiquidData(x, y, z, phaseShift, reqLiquidType ? AsUnderlyingType(*reqLiquidType) : Optional<uint8>(), dynData);
337
338 uint32 gridAreaId = 0;
339 float gridMapHeight = INVALID_HEIGHT;
340 if (gmap)
341 {
342 gridAreaId = gmap->getArea(x, y);
343 gridMapHeight = gmap->getHeight(x, y);
344 }
345
346 bool useGridLiquid = true;
347
348 // floor is the height we are closer to (but only if above)
350 if (gridMapHeight > INVALID_HEIGHT && G3D::fuzzyGe(z, gridMapHeight - GROUND_HEIGHT_TOLERANCE))
351 data.floorZ = gridMapHeight;
352 if (vmapData.floorZ > VMAP_INVALID_HEIGHT &&
353 G3D::fuzzyGe(z, vmapData.floorZ - GROUND_HEIGHT_TOLERANCE) &&
354 (G3D::fuzzyLt(z, gridMapHeight - GROUND_HEIGHT_TOLERANCE) || vmapData.floorZ > gridMapHeight))
355 {
356 data.floorZ = vmapData.floorZ;
357 wmoData = &vmapData;
358 }
359 // NOTE: Objects will not detect a case when a wmo providing area/liquid despawns from under them
360 // but this is fine as these kind of objects are not meant to be spawned and despawned a lot
361 // example: Lich King platform
362 if (dynData.floorZ > VMAP_INVALID_HEIGHT &&
363 G3D::fuzzyGe(z, dynData.floorZ - GROUND_HEIGHT_TOLERANCE) &&
364 (G3D::fuzzyLt(z, gridMapHeight - GROUND_HEIGHT_TOLERANCE) || dynData.floorZ > gridMapHeight) &&
365 (G3D::fuzzyLt(z, vmapData.floorZ - GROUND_HEIGHT_TOLERANCE) || dynData.floorZ > vmapData.floorZ))
366 {
367 data.floorZ = dynData.floorZ;
368 wmoData = &dynData;
369 }
370
371 if (wmoData)
372 {
373 if (wmoData->areaInfo)
374 {
375 data.wmoLocation.emplace(wmoData->areaInfo->groupId, wmoData->areaInfo->adtId, wmoData->areaInfo->rootId, wmoData->areaInfo->uniqueId);
376 // wmo found
377 WMOAreaTableEntry const* wmoEntry = sDB2Manager.GetWMOAreaTable(wmoData->areaInfo->rootId, wmoData->areaInfo->adtId, wmoData->areaInfo->groupId);
378 if (!wmoEntry)
379 wmoEntry = sDB2Manager.GetWMOAreaTable(wmoData->areaInfo->rootId, wmoData->areaInfo->adtId, -1);
380
381 data.outdoors = (wmoData->areaInfo->mogpFlags & 0x8) != 0;
382 if (wmoEntry)
383 {
384 data.areaId = wmoEntry->AreaTableID;
385 if (wmoEntry->Flags & 4)
386 data.outdoors = true;
387 else if (wmoEntry->Flags & 2)
388 data.outdoors = false;
389 }
390
391 if (!data.areaId)
392 data.areaId = gridAreaId;
393
394 useGridLiquid = !IsInWMOInterior(wmoData->areaInfo->mogpFlags);
395 }
396 }
397 else
398 {
399 data.outdoors = true;
400 data.areaId = gridAreaId;
401 if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(data.areaId))
402 data.outdoors = areaEntry->GetFlags().HasFlag(AreaFlags::ForceOutdoors) || !areaEntry->GetFlags().HasFlag(AreaFlags::ForceIndoors);
403 }
404
405 if (!data.areaId)
406 data.areaId = sMapStore.AssertEntry(GetId())->AreaTableID;
407
408 AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(data.areaId);
409
410 // liquid processing
412 if (wmoData && wmoData->liquidInfo && wmoData->liquidInfo->level > wmoData->floorZ)
413 {
414 uint32 liquidType = wmoData->liquidInfo->type;
415 if (GetId() == 530 && liquidType == 2) // gotta love hacks
416 liquidType = 15;
417
418 uint32 liquidFlagType = 0;
419 if (LiquidTypeEntry const* liquidData = sLiquidTypeStore.LookupEntry(liquidType))
420 liquidFlagType = liquidData->SoundBank;
421
422 if (liquidType && liquidType < 21 && areaEntry)
423 {
424 uint32 overrideLiquid = areaEntry->LiquidTypeID[liquidFlagType];
425 if (!overrideLiquid && areaEntry->ParentAreaID)
426 {
427 AreaTableEntry const* zoneEntry = sAreaTableStore.LookupEntry(areaEntry->ParentAreaID);
428 if (zoneEntry)
429 overrideLiquid = zoneEntry->LiquidTypeID[liquidFlagType];
430 }
431
432 if (LiquidTypeEntry const* overrideData = sLiquidTypeStore.LookupEntry(overrideLiquid))
433 {
434 liquidType = overrideLiquid;
435 liquidFlagType = overrideData->SoundBank;
436 }
437 }
438
439 data.liquidInfo.emplace();
440 data.liquidInfo->level = wmoData->liquidInfo->level;
441 data.liquidInfo->depth_level = wmoData->floorZ;
442 data.liquidInfo->entry = liquidType;
443 data.liquidInfo->type_flags = map_liquidHeaderTypeFlags(1 << liquidFlagType);
444
445 float delta = wmoData->liquidInfo->level - z;
447 if (delta > collisionHeight)
448 status = LIQUID_MAP_UNDER_WATER;
449 else if (delta > 0.0f)
450 status = LIQUID_MAP_IN_WATER;
451 else if (delta > -0.1f)
452 status = LIQUID_MAP_WATER_WALK;
453
454 if (status != LIQUID_MAP_ABOVE_WATER)
455 if (std::fabs(wmoData->floorZ - z) <= GROUND_HEIGHT_TOLERANCE)
456 status |= LIQUID_MAP_OCEAN_FLOOR;
457
458 data.liquidStatus = static_cast<ZLiquidStatus>(status);
459 }
460 // look up liquid data from grid map
461 if (gmap && useGridLiquid)
462 {
463 LiquidData gridMapLiquid;
464 ZLiquidStatus gridMapStatus = gmap->GetLiquidStatus(x, y, z, reqLiquidType, &gridMapLiquid, collisionHeight);
465 if (gridMapStatus != LIQUID_MAP_NO_WATER && (!wmoData || gridMapLiquid.level > wmoData->floorZ))
466 {
467 if (GetId() == 530 && gridMapLiquid.entry == 2)
468 gridMapLiquid.entry = 15;
469 data.liquidInfo = gridMapLiquid;
470 data.liquidStatus = gridMapStatus;
471 }
472 }
473}
474
475ZLiquidStatus TerrainInfo::GetLiquidStatus(PhaseShift const& phaseShift, uint32 mapId, float x, float y, float z, Optional<map_liquidHeaderTypeFlags> ReqLiquidType, LiquidData* data, float collisionHeight)
476{
480 bool useGridLiquid = true;
481 uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, mapId, this, x, y);
482 if (vmgr->getAreaAndLiquidData(terrainMapId, x, y, z, ReqLiquidType ? AsUnderlyingType(*ReqLiquidType) : Optional<uint8>(), vmapData) && vmapData.liquidInfo)
483 {
484 useGridLiquid = !vmapData.areaInfo || !IsInWMOInterior(vmapData.areaInfo->mogpFlags);
485 TC_LOG_DEBUG("maps", "GetLiquidStatus(): vmap liquid level: {} ground: {} type: {}", vmapData.liquidInfo->level, vmapData.floorZ, vmapData.liquidInfo->type);
486 // Check water level and ground level
487 if (vmapData.liquidInfo->level > vmapData.floorZ && G3D::fuzzyGe(z, vmapData.floorZ - GROUND_HEIGHT_TOLERANCE))
488 {
489 // All ok in water -> store data
490 if (data)
491 {
492 // hardcoded in client like this
493 if (GetId() == 530 && vmapData.liquidInfo->type == 2)
494 vmapData.liquidInfo->type = 15;
495
496 uint32 liquidFlagType = 0;
497 if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(vmapData.liquidInfo->type))
498 liquidFlagType = liq->SoundBank;
499
500 if (vmapData.liquidInfo->type && vmapData.liquidInfo->type < 21)
501 {
502 if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId(phaseShift, mapId, x, y, z)))
503 {
504 uint32 overrideLiquid = area->LiquidTypeID[liquidFlagType];
505 if (!overrideLiquid && area->ParentAreaID)
506 {
507 area = sAreaTableStore.LookupEntry(area->ParentAreaID);
508 if (area)
509 overrideLiquid = area->LiquidTypeID[liquidFlagType];
510 }
511
512 if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
513 {
514 vmapData.liquidInfo->type = overrideLiquid;
515 liquidFlagType = liq->SoundBank;
516 }
517 }
518 }
519
520 data->level = vmapData.liquidInfo->level;
521 data->depth_level = vmapData.floorZ;
522
523 data->entry = vmapData.liquidInfo->type;
524 data->type_flags = map_liquidHeaderTypeFlags(1 << liquidFlagType);
525 }
526
527 float delta = vmapData.liquidInfo->level - z;
528
529 // Get position delta
531 if (delta > collisionHeight) // Under water
532 status = LIQUID_MAP_UNDER_WATER;
533 else if (delta > 0.0f) // In water
534 status = LIQUID_MAP_IN_WATER;
535 else if (delta > -0.1f) // Walk on water
536 status = LIQUID_MAP_WATER_WALK;
537
538 if (status != LIQUID_MAP_ABOVE_WATER)
539 {
540 if (status != LIQUID_MAP_ABOVE_WATER)
541 if (std::fabs(vmapData.floorZ - z) <= GROUND_HEIGHT_TOLERANCE)
542 status |= LIQUID_MAP_OCEAN_FLOOR;
543
544 return static_cast<ZLiquidStatus>(status);
545 }
546
547 result = LIQUID_MAP_ABOVE_WATER;
548 }
549 }
550
551 if (useGridLiquid)
552 {
553 if (GridMap const* gmap = GetGrid(terrainMapId, x, y))
554 {
555 LiquidData map_data;
556 ZLiquidStatus map_result = gmap->GetLiquidStatus(x, y, z, ReqLiquidType, &map_data, collisionHeight);
557 // Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER:
558 if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > vmapData.floorZ))
559 {
560 if (data)
561 {
562 // hardcoded in client like this
563 if (GetId() == 530 && map_data.entry == 2)
564 map_data.entry = 15;
565
566 *data = map_data;
567 }
568 return map_result;
569 }
570 }
571 }
572 return result;
573}
574
575bool TerrainInfo::GetAreaInfo(PhaseShift const& phaseShift, uint32 mapId, float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId, DynamicMapTree const* dynamicMapTree)
576{
577 float check_z = z;
578 uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, mapId, this, x, y);
582
583 bool hasVmapAreaInfo = vmgr->getAreaAndLiquidData(terrainMapId, x, y, z, {}, vdata) && vdata.areaInfo.has_value();
584 bool hasDynamicAreaInfo = dynamicMapTree ? dynamicMapTree->getAreaAndLiquidData(x, y, z, phaseShift, {}, ddata) && ddata.areaInfo.has_value() : false;
585 auto useVmap = [&] { check_z = vdata.floorZ; groupId = vdata.areaInfo->groupId; adtId = vdata.areaInfo->adtId; rootId = vdata.areaInfo->rootId; mogpflags = vdata.areaInfo->mogpFlags; };
586 auto useDyn = [&] { check_z = ddata.floorZ; groupId = ddata.areaInfo->groupId; adtId = ddata.areaInfo->adtId; rootId = ddata.areaInfo->rootId; mogpflags = ddata.areaInfo->mogpFlags; };
587
588 if (hasVmapAreaInfo)
589 {
590 if (hasDynamicAreaInfo && ddata.floorZ > vdata.floorZ)
591 useDyn();
592 else
593 useVmap();
594 }
595 else if (hasDynamicAreaInfo)
596 {
597 useDyn();
598 }
599
600 if (hasVmapAreaInfo || hasDynamicAreaInfo)
601 {
602 // check if there's terrain between player height and object height
603 if (GridMap* gmap = GetGrid(terrainMapId, x, y))
604 {
605 float mapHeight = gmap->getHeight(x, y);
606 // z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice...
607 if (z + 2.0f > mapHeight && mapHeight > check_z)
608 return false;
609 }
610 return true;
611 }
612 return false;
613}
614
615uint32 TerrainInfo::GetAreaId(PhaseShift const& phaseShift, uint32 mapId, float x, float y, float z, DynamicMapTree const* dynamicMapTree)
616{
617 uint32 mogpFlags;
618 int32 adtId, rootId, groupId;
619 float vmapZ = z;
620 bool hasVmapArea = GetAreaInfo(phaseShift, mapId, x, y, vmapZ, mogpFlags, adtId, rootId, groupId, dynamicMapTree);
621
622 uint32 gridAreaId = 0;
623 float gridMapHeight = INVALID_HEIGHT;
624 if (GridMap* gmap = GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, mapId, this, x, y), x, y))
625 {
626 gridAreaId = gmap->getArea(x, y);
627 gridMapHeight = gmap->getHeight(x, y);
628 }
629
630 uint32 areaId = 0;
631
632 // floor is the height we are closer to (but only if above)
633 if (hasVmapArea && G3D::fuzzyGe(z, vmapZ - GROUND_HEIGHT_TOLERANCE) && (G3D::fuzzyLt(z, gridMapHeight - GROUND_HEIGHT_TOLERANCE) || vmapZ > gridMapHeight))
634 {
635 // wmo found
636 if (WMOAreaTableEntry const* wmoEntry = sDB2Manager.GetWMOAreaTable(rootId, adtId, groupId))
637 areaId = wmoEntry->AreaTableID;
638
639 if (!areaId)
640 areaId = gridAreaId;
641 }
642 else
643 areaId = gridAreaId;
644
645 if (!areaId)
646 areaId = sMapStore.AssertEntry(GetId())->AreaTableID;
647
648 return areaId;
649}
650
651uint32 TerrainInfo::GetZoneId(PhaseShift const& phaseShift, uint32 mapId, float x, float y, float z, DynamicMapTree const* dynamicMapTree)
652{
653 uint32 areaId = GetAreaId(phaseShift, mapId, x, y, z, dynamicMapTree);
654 if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId))
655 if (area->ParentAreaID && area->GetFlags().HasFlag(AreaFlags::IsSubzone))
656 return area->ParentAreaID;
657
658 return areaId;
659}
660
661void TerrainInfo::GetZoneAndAreaId(PhaseShift const& phaseShift, uint32 mapId, uint32& zoneid, uint32& areaid, float x, float y, float z, DynamicMapTree const* dynamicMapTree)
662{
663 areaid = zoneid = GetAreaId(phaseShift, mapId, x, y, z, dynamicMapTree);
664 if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaid))
665 if (area->ParentAreaID && area->GetFlags().HasFlag(AreaFlags::IsSubzone))
666 zoneid = area->ParentAreaID;
667}
668
669float TerrainInfo::GetMinHeight(PhaseShift const& phaseShift, uint32 mapId, float x, float y)
670{
671 if (GridMap const* grid = GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, mapId, this, x, y), x, y))
672 return grid->getMinHeight(x, y);
673
674 return -500.0f;
675}
676
677float TerrainInfo::GetGridHeight(PhaseShift const& phaseShift, uint32 mapId, float x, float y)
678{
679 if (GridMap* gmap = GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, mapId, this, x, y), x, y))
680 return gmap->getHeight(x, y);
681
683}
684
685float TerrainInfo::GetStaticHeight(PhaseShift const& phaseShift, uint32 mapId, float x, float y, float z, bool checkVMap /*= true*/, float maxSearchDist /*= DEFAULT_HEIGHT_SEARCH*/)
686{
687 // find raw .map surface under Z coordinates
688 float mapHeight = VMAP_INVALID_HEIGHT_VALUE;
689 uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, mapId, this, x, y);
690 float gridHeight = GetGridHeight(phaseShift, mapId, x, y);
691 if (G3D::fuzzyGe(z, gridHeight - GROUND_HEIGHT_TOLERANCE))
692 mapHeight = gridHeight;
693
694 float vmapHeight = VMAP_INVALID_HEIGHT_VALUE;
695 if (checkVMap)
696 {
698 if (vmgr->isHeightCalcEnabled())
699 vmapHeight = vmgr->getHeight(terrainMapId, x, y, z, maxSearchDist);
700 }
701
702 // mapHeight set for any above raw ground Z or <= INVALID_HEIGHT
703 // vmapheight set for any under Z value or <= INVALID_HEIGHT
704 if (vmapHeight > INVALID_HEIGHT)
705 {
706 if (mapHeight > INVALID_HEIGHT)
707 {
708 // we have mapheight and vmapheight and must select more appropriate
709
710 // vmap height above map height
711 // or if the distance of the vmap height is less the land height distance
712 if (vmapHeight > mapHeight || std::fabs(mapHeight - z) > std::fabs(vmapHeight - z))
713 return vmapHeight;
714
715 return mapHeight; // better use .map surface height
716 }
717
718 return vmapHeight; // we have only vmapHeight (if have)
719 }
720
721 return mapHeight; // explicitly use map data
722}
723
724float TerrainInfo::GetWaterLevel(PhaseShift const& phaseShift, uint32 mapId, float x, float y)
725{
726 if (GridMap* gmap = GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, mapId, this, x, y), x, y))
727 return gmap->getLiquidLevel(x, y);
728
729 return 0;
730}
731
732bool TerrainInfo::IsInWater(PhaseShift const& phaseShift, uint32 mapId, float x, float y, float pZ, LiquidData* data)
733{
734 LiquidData liquid_status;
735 LiquidData* liquid_ptr = data ? data : &liquid_status;
736 return (GetLiquidStatus(phaseShift, mapId, x, y, pZ, {}, liquid_ptr) & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0;
737}
738
739bool TerrainInfo::IsUnderWater(PhaseShift const& phaseShift, uint32 mapId, float x, float y, float z)
740{
742}
743
744float TerrainInfo::GetWaterOrGroundLevel(PhaseShift const& phaseShift, uint32 mapId, float x, float y, float z, float* ground /*= nullptr*/, bool /*swim = false*/, float collisionHeight /*= DEFAULT_COLLISION_HEIGHT*/, DynamicMapTree const* dynamicMapTree /*= nullptr*/)
745{
746 if (GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, mapId, this, x, y), x, y))
747 {
748 // we need ground level (including grid height version) for proper return water level in point
749 float ground_z = GetStaticHeight(phaseShift, mapId, x, y, z + Z_OFFSET_FIND_HEIGHT, true, 50.0f);
750 if (dynamicMapTree)
751 ground_z = std::max(ground_z, dynamicMapTree->getHeight(x, y, z + Z_OFFSET_FIND_HEIGHT, 50.0f, phaseShift));
752
753 if (ground)
754 *ground = ground_z;
755
756 LiquidData liquid_status;
757
758 ZLiquidStatus res = GetLiquidStatus(phaseShift, mapId, x, y, ground_z, {}, &liquid_status, collisionHeight);
759 switch (res)
760 {
762 return std::max<float>(liquid_status.level, ground_z);
764 return ground_z;
765 default:
766 return liquid_status.level;
767 }
768 }
769
771}
772
773TerrainMgr::TerrainMgr() = default;
774
775TerrainMgr::~TerrainMgr() = default;
776
778{
779 static TerrainMgr instance;
780 return instance;
781}
782
783void TerrainMgr::InitializeParentMapData(std::unordered_map<uint32, std::vector<uint32>> const& mapData)
784{
785 _parentMapData = mapData;
786}
787
788std::shared_ptr<TerrainInfo> TerrainMgr::LoadTerrain(uint32 mapId)
789{
790 MapEntry const* entry = sMapStore.LookupEntry(mapId);
791 if (!entry)
792 return nullptr;
793
794 while (entry->ParentMapID != -1 || entry->CosmeticParentMapID != -1)
795 {
796 uint32 parentMapId = entry->ParentMapID != -1 ? entry->ParentMapID : entry->CosmeticParentMapID;
797 entry = sMapStore.LookupEntry(parentMapId);
798 if (!entry)
799 break;
800
801 mapId = parentMapId;
802 }
803
804 auto itr = _terrainMaps.find(mapId);
805 if (itr != _terrainMaps.end())
806 if (std::shared_ptr<TerrainInfo> terrain = itr->second.lock())
807 return terrain;
808
809 std::shared_ptr<TerrainInfo> terrainInfo = LoadTerrainImpl(mapId);
810 _terrainMaps[mapId] = terrainInfo;
811 return terrainInfo;
812}
813
815{
816 _terrainMaps.clear();
817}
818
820{
821 // global garbage collection
822 for (auto& [mapId, terrainRef] : _terrainMaps)
823 if (std::shared_ptr<TerrainInfo> terrain = terrainRef.lock())
824 terrain->CleanUpGrids(diff);
825}
826
827uint32 TerrainMgr::GetAreaId(PhaseShift const& phaseShift, uint32 mapid, float x, float y, float z)
828{
829 if (std::shared_ptr<TerrainInfo> t = LoadTerrain(mapid))
830 return t->GetAreaId(phaseShift, mapid, x, y, z);
831 return 0;
832}
833
834uint32 TerrainMgr::GetZoneId(PhaseShift const& phaseShift, uint32 mapid, float x, float y, float z)
835{
836 if (std::shared_ptr<TerrainInfo> t = LoadTerrain(mapid))
837 return t->GetZoneId(phaseShift, mapid, x, y, z);
838 return 0;
839}
840
841void TerrainMgr::GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z)
842{
843 if (std::shared_ptr<TerrainInfo> t = LoadTerrain(mapid))
844 t->GetZoneAndAreaId(phaseShift, mapid, zoneid, areaid, x, y, z);
845}
846
847std::shared_ptr<TerrainInfo> TerrainMgr::LoadTerrainImpl(uint32 mapId)
848{
849 std::shared_ptr<TerrainInfo> rootTerrain(new TerrainInfo(mapId)); // intentionally not using make_shared, don't want control block allocated together, will be relying on weak_ptr
850
851 rootTerrain->DiscoverGridMapFiles();
852
853 for (uint32 childMapId : _parentMapData[mapId])
854 rootTerrain->AddChildTerrain(LoadTerrainImpl(childMapId));
855
856 return rootTerrain;
857}
858
859bool TerrainMgr::ExistMapAndVMap(uint32 mapid, float x, float y)
860{
862
863 int32 gx = (MAX_NUMBER_OF_GRIDS - 1) - p.x_coord;
864 int32 gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord;
865
866 return TerrainInfo::ExistMap(mapid, gx, gy) && TerrainInfo::ExistVMap(mapid, gx, gy);
867}
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
DB2Storage< LiquidTypeEntry > sLiquidTypeStore("LiquidType.db2", &LiquidTypeLoadInfo::Instance)
DB2Storage< AreaTableEntry > sAreaTableStore("AreaTable.db2", &AreaTableLoadInfo::Instance)
#define sDB2Manager
Definition: DB2Stores.h:538
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
#define SIZE_OF_GRIDS
Definition: GridDefines.h:40
#define MAX_NUMBER_OF_GRIDS
Definition: GridDefines.h:38
#define CENTER_GRID_ID
Definition: GridDefines.h:41
#define INVALID_HEIGHT
Definition: GridDefines.h:61
#define VMAP_INVALID_HEIGHT_VALUE
Definition: IVMapManager.h:44
#define VMAP_INVALID_HEIGHT
Definition: IVMapManager.h:43
#define TC_LOG_WARN(filterType__,...)
Definition: Log.h:162
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
uint32 const MapVersionMagic
Definition: MapDefines.cpp:21
u_map_magic const MapMagic
Definition: MapDefines.cpp:20
std::array< char, 4 > u_map_magic
Represents a map magic value of 4 bytes (used in versions)
Definition: MapDefines.h:27
ZLiquidStatus
Definition: MapDefines.h:125
@ LIQUID_MAP_UNDER_WATER
Definition: MapDefines.h:130
@ LIQUID_MAP_OCEAN_FLOOR
Definition: MapDefines.h:131
@ LIQUID_MAP_NO_WATER
Definition: MapDefines.h:126
@ LIQUID_MAP_IN_WATER
Definition: MapDefines.h:129
@ LIQUID_MAP_ABOVE_WATER
Definition: MapDefines.h:127
@ LIQUID_MAP_WATER_WALK
Definition: MapDefines.h:128
map_liquidHeaderTypeFlags
Definition: MapDefines.h:97
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
Milliseconds randtime(Milliseconds min, Milliseconds max)
Definition: Random.cpp:62
float const GROUND_HEIGHT_TOLERANCE
Definition: SharedDefines.h:25
constexpr float Z_OFFSET_FIND_HEIGHT
Definition: SharedDefines.h:26
static bool IsInWMOInterior(uint32 mogpFlags)
Definition: TerrainMgr.cpp:320
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition: Util.h:491
float getHeight(float x, float y, float z, float maxSearchDist, PhaseShift const &phaseShift) const
bool getAreaAndLiquidData(float x, float y, float z, PhaseShift const &phaseShift, Optional< uint8 > reqLiquidType, VMAP::AreaAndLiquidData &data) const
LoadResult
Definition: GridMap.h:87
uint16 getArea(float x, float y) const
Definition: GridMap.cpp:292
float getHeight(float x, float y) const
Definition: GridMap.h:97
ZLiquidStatus GetLiquidStatus(float x, float y, float z, Optional< map_liquidHeaderTypeFlags > ReqLiquidType, LiquidData *data=nullptr, float collisionHeight=2.03128f) const
Definition: GridMap.cpp:599
static MMapManager * createOrGetMMapManager()
Definition: MMapFactory.cpp:26
bool unloadMap(uint32 mapId, int32 x, int32 y)
bool loadMapInstance(std::string const &basePath, uint32 meshMapId, uint32 instanceMapId, uint32 instanceId)
bool loadMap(std::string const &basePath, uint32 mapId, int32 x, int32 y)
bool unloadMapInstance(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId)
static uint32 GetTerrainMapId(PhaseShift const &phaseShift, uint32 mapId, TerrainInfo const *terrain, float x, float y)
void LoadMMap(int32 gx, int32 gy)
Definition: TerrainMgr.cpp:237
void UnloadMMapInstanceImpl(uint32 mapId, uint32 instanceId)
Definition: TerrainMgr.cpp:276
float GetMinHeight(PhaseShift const &phaseShift, uint32 mapId, float x, float y)
Definition: TerrainMgr.cpp:669
bool GetAreaInfo(PhaseShift const &phaseShift, uint32 mapId, float x, float y, float z, uint32 &mogpflags, int32 &adtId, int32 &rootId, int32 &groupId, DynamicMapTree const *dynamicMapTree=nullptr)
Definition: TerrainMgr.cpp:575
float GetWaterLevel(PhaseShift const &phaseShift, uint32 mapId, float x, float y)
Definition: TerrainMgr.cpp:724
std::atomic< uint16 > _referenceCountFromMap[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]
Definition: TerrainMgr.h:113
static constexpr Milliseconds CleanupInterval
Definition: TerrainMgr.h:117
void LoadMMapInstance(uint32 mapId, uint32 instanceId)
Definition: TerrainMgr.cpp:166
float GetStaticHeight(PhaseShift const &phaseShift, uint32 mapId, float x, float y, float z, bool checkVMap=true, float maxSearchDist=DEFAULT_HEIGHT_SEARCH)
Definition: TerrainMgr.cpp:685
ZLiquidStatus GetLiquidStatus(PhaseShift const &phaseShift, uint32 mapId, float x, float y, float z, Optional< map_liquidHeaderTypeFlags > ReqLiquidType={}, LiquidData *data=nullptr, float collisionHeight=2.03128f)
Definition: TerrainMgr.cpp:475
bool HasChildTerrainGridFile(uint32 mapId, int32 gx, int32 gy) const
Definition: TerrainMgr.cpp:145
void LoadMap(int32 gx, int32 gy)
Definition: TerrainMgr.cpp:191
bool IsInWater(PhaseShift const &phaseShift, uint32 mapId, float x, float y, float z, LiquidData *data=nullptr)
Definition: TerrainMgr.cpp:732
uint32 GetId() const
Definition: TerrainMgr.h:47
void LoadVMap(int32 gx, int32 gy)
Definition: TerrainMgr.cpp:214
std::mutex _loadMutex
Definition: TerrainMgr.h:111
TimeTracker _cleanupTimer
Definition: TerrainMgr.h:120
void DiscoverGridMapFiles()
Definition: TerrainMgr.cpp:50
void UnloadMapImpl(int32 gx, int32 gy)
Definition: TerrainMgr.cpp:264
void LoadMMapInstanceImpl(uint32 mapId, uint32 instanceId)
Definition: TerrainMgr.cpp:186
uint32 GetAreaId(PhaseShift const &phaseShift, uint32 mapId, float x, float y, float z, DynamicMapTree const *dynamicMapTree=nullptr)
Definition: TerrainMgr.cpp:615
void UnloadMMapInstance(uint32 mapId, uint32 instanceId)
Definition: TerrainMgr.cpp:256
TerrainInfo(uint32 mapId)
Definition: TerrainMgr.cpp:35
std::bitset< MAX_NUMBER_OF_GRIDS *MAX_NUMBER_OF_GRIDS > _loadedGrids
Definition: TerrainMgr.h:114
GridMap * GetGrid(uint32 mapId, float x, float y, bool loadIfMissing=true)
Definition: TerrainMgr.cpp:281
std::vector< std::shared_ptr< TerrainInfo > > _childTerrain
Definition: TerrainMgr.h:109
void GetZoneAndAreaId(PhaseShift const &phaseShift, uint32 mapId, uint32 &zoneid, uint32 &areaid, float x, float y, float z, DynamicMapTree const *dynamicMapTree=nullptr)
Definition: TerrainMgr.cpp:661
static bool ExistVMap(uint32 mapid, int32 gx, int32 gy)
Definition: TerrainMgr.cpp:110
void GetFullTerrainStatusForPosition(PhaseShift const &phaseShift, uint32 mapId, float x, float y, float z, PositionFullTerrainStatus &data, Optional< map_liquidHeaderTypeFlags > reqLiquidType={}, float collisionHeight=2.03128f, DynamicMapTree const *dynamicMapTree=nullptr)
Definition: TerrainMgr.cpp:325
void LoadMapAndVMap(int32 gx, int32 gy)
Definition: TerrainMgr.cpp:157
char const * GetMapName() const
Definition: TerrainMgr.cpp:45
std::bitset< MAX_NUMBER_OF_GRIDS *MAX_NUMBER_OF_GRIDS > _gridFileExists
Definition: TerrainMgr.h:115
void CleanUpGrids(uint32 diff)
Definition: TerrainMgr.cpp:305
void UnloadMap(int32 gx, int32 gy)
Definition: TerrainMgr.cpp:250
static bool ExistMap(uint32 mapid, int32 gx, int32 gy, bool log=true)
Definition: TerrainMgr.cpp:77
void LoadMapAndVMapImpl(int32 gx, int32 gy)
Definition: TerrainMgr.cpp:174
float GetWaterOrGroundLevel(PhaseShift const &phaseShift, uint32 mapId, float x, float y, float z, float *ground=nullptr, bool swim=false, float collisionHeight=2.03128f, DynamicMapTree const *dynamicMapTree=nullptr)
Definition: TerrainMgr.cpp:744
uint32 _mapId
Definition: TerrainMgr.h:106
static constexpr int32 GetBitsetIndex(int32 gx, int32 gy)
Definition: TerrainMgr.h:104
std::unique_ptr< GridMap > _gridMap[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]
Definition: TerrainMgr.h:112
uint32 GetZoneId(PhaseShift const &phaseShift, uint32 mapId, float x, float y, float z, DynamicMapTree const *dynamicMapTree=nullptr)
Definition: TerrainMgr.cpp:651
bool IsUnderWater(PhaseShift const &phaseShift, uint32 mapId, float x, float y, float z)
Definition: TerrainMgr.cpp:739
void AddChildTerrain(std::shared_ptr< TerrainInfo > childTerrain)
Definition: TerrainMgr.cpp:151
float GetGridHeight(PhaseShift const &phaseShift, uint32 mapId, float x, float y)
Definition: TerrainMgr.cpp:677
void Update(uint32 diff)
Definition: TerrainMgr.cpp:819
std::shared_ptr< TerrainInfo > LoadTerrainImpl(uint32 mapId)
Definition: TerrainMgr.cpp:847
void InitializeParentMapData(std::unordered_map< uint32, std::vector< uint32 > > const &mapData)
Definition: TerrainMgr.cpp:783
void UnloadAll()
Definition: TerrainMgr.cpp:814
uint32 GetAreaId(PhaseShift const &phaseShift, uint32 mapid, float x, float y, float z)
Definition: TerrainMgr.cpp:827
void GetZoneAndAreaId(PhaseShift const &phaseShift, uint32 &zoneid, uint32 &areaid, uint32 mapid, float x, float y, float z)
Definition: TerrainMgr.cpp:841
static TerrainMgr & Instance()
Definition: TerrainMgr.cpp:777
uint32 GetZoneId(PhaseShift const &phaseShift, uint32 mapid, float x, float y, float z)
Definition: TerrainMgr.cpp:834
static bool ExistMapAndVMap(uint32 mapid, float x, float y)
Definition: TerrainMgr.cpp:859
std::unordered_map< uint32, std::weak_ptr< TerrainInfo > > _terrainMaps
Definition: TerrainMgr.h:159
std::shared_ptr< TerrainInfo > LoadTerrain(uint32 mapId)
Definition: TerrainMgr.cpp:788
std::unordered_map< uint32, std::vector< uint32 > > _parentMapData
Definition: TerrainMgr.h:162
virtual float getHeight(unsigned int pMapId, float x, float y, float z, float maxSearchDist)=0
bool isHeightCalcEnabled() const
Definition: IVMapManager.h:114
virtual bool getAreaAndLiquidData(unsigned int mapId, float x, float y, float z, Optional< uint8 > reqLiquidType, AreaAndLiquidData &data) const =0
static VMapManager2 * createOrGetVMapManager()
Definition: VMapFactory.cpp:27
LoadResult loadMap(char const *pBasePath, unsigned int mapId, int x, int y) override
void unloadMap(unsigned int mapId, int x, int y) override
#define sWorld
Definition: World.h:931
bool IsPathfindingEnabled(uint32 mapId)
Definition: DisableMgr.cpp:401
auto make_unique_ptr_with_deleter(T ptr, Del &&deleter)
Definition: Memory.h:41
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
Definition: StringFormat.h:38
GridCoord ComputeGridCoord(float x, float y)
Definition: GridDefines.h:194
constexpr std::size_t size()
Definition: UpdateField.h:796
LoadResult
Definition: IVMapManager.h:35
uint16 ParentAreaID
Definition: DB2Structure.h:131
std::array< uint16, 4 > LiquidTypeID
Definition: DB2Structure.h:150
uint32 x_coord
Definition: GridDefines.h:173
uint32 y_coord
Definition: GridDefines.h:174
uint32 entry
Definition: MapDefines.h:140
EnumFlag< map_liquidHeaderTypeFlags > type_flags
Definition: MapDefines.h:139
float depth_level
Definition: MapDefines.h:142
float level
Definition: MapDefines.h:141
int16 CosmeticParentMapID
int16 ParentMapID
Optional< LiquidData > liquidInfo
Definition: MapDefines.h:165
Optional< WmoLocation > wmoLocation
Definition: MapDefines.h:164
ZLiquidStatus liquidStatus
Definition: MapDefines.h:163
void Update(int32 diff)
Definition: Timer.h:121
bool Passed() const
Definition: Timer.h:131
void Reset(int32 expiry)
Definition: Timer.h:136
Optional< AreaInfo > areaInfo
Definition: IVMapManager.h:68
Optional< LiquidInfo > liquidInfo
Definition: IVMapManager.h:69