diff options
author | Shauren <shauren.trinity@gmail.com> | 2018-04-07 00:21:51 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2018-04-07 21:36:15 +0200 |
commit | b9c6bbb51df0ed10f74617482740fedb91ff5366 (patch) | |
tree | 9b54a41e2a8fe0075983548d2a31977e6cdd2a58 /src | |
parent | 2dadbda24ac1c2e6ff3dad650c7e25f4b3322342 (diff) |
Core/Maps: Adjusted logic in GetFullTerrainStatusForPosition to closer match what the client does regarding being inside WMOs
Closes #21625
Closes #21624
Closes #21516
Diffstat (limited to 'src')
-rw-r--r-- | src/common/Collision/Management/IVMapManager.h | 4 | ||||
-rw-r--r-- | src/common/Collision/Management/VMapManager2.cpp | 5 | ||||
-rw-r--r-- | src/common/Collision/Management/VMapManager2.h | 6 | ||||
-rw-r--r-- | src/common/Collision/Models/WorldModel.cpp | 5 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 18 | ||||
-rw-r--r-- | src/server/game/Maps/Map.cpp | 263 | ||||
-rw-r--r-- | src/server/game/Maps/Map.h | 10 | ||||
-rw-r--r-- | src/server/game/Movement/PathGenerator.cpp | 3 |
8 files changed, 156 insertions, 158 deletions
diff --git a/src/common/Collision/Management/IVMapManager.h b/src/common/Collision/Management/IVMapManager.h index e9aae51a025..a2147918f5c 100644 --- a/src/common/Collision/Management/IVMapManager.h +++ b/src/common/Collision/Management/IVMapManager.h @@ -122,8 +122,8 @@ namespace VMAP Query world model area info. \param z gets adjusted to the ground height for which this are info is valid */ - virtual bool getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const=0; - virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const=0; + virtual bool getAreaInfo(uint32 mapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const=0; + virtual bool GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type, uint32& mogpFlags) const=0; // get both area + liquid data in a single vmap lookup virtual void getAreaAndLiquidData(unsigned int mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const=0; }; diff --git a/src/common/Collision/Management/VMapManager2.cpp b/src/common/Collision/Management/VMapManager2.cpp index 5b9cb34874b..98d47e43184 100644 --- a/src/common/Collision/Management/VMapManager2.cpp +++ b/src/common/Collision/Management/VMapManager2.cpp @@ -234,7 +234,7 @@ namespace VMAP return VMAP_INVALID_HEIGHT_VALUE; } - bool VMapManager2::getAreaInfo(unsigned int mapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const + bool VMapManager2::getAreaInfo(uint32 mapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const { if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG)) { @@ -252,7 +252,7 @@ namespace VMAP return false; } - bool VMapManager2::GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const + bool VMapManager2::GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type, uint32& mogpFlags) const { if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS)) { @@ -267,6 +267,7 @@ namespace VMAP ASSERT(floor < std::numeric_limits<float>::max()); ASSERT(info.hitModel); type = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc + mogpFlags = info.hitModel->GetMogpFlags(); if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType)) return false; ASSERT(info.hitInstance); diff --git a/src/common/Collision/Management/VMapManager2.h b/src/common/Collision/Management/VMapManager2.h index 831383ac555..10a450b65c5 100644 --- a/src/common/Collision/Management/VMapManager2.h +++ b/src/common/Collision/Management/VMapManager2.h @@ -116,9 +116,9 @@ namespace VMAP bool processCommand(char* /*command*/) override { return false; } // for debug and extensions - bool getAreaInfo(unsigned int pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const override; - bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const override; - void getAreaAndLiquidData(unsigned int mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const override; + bool getAreaInfo(uint32 mapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const override; + bool GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type, uint32& mogpFlags) const override; + void getAreaAndLiquidData(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const override; WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags = 0); void releaseModelInstance(const std::string& filename); diff --git a/src/common/Collision/Models/WorldModel.cpp b/src/common/Collision/Models/WorldModel.cpp index 8f207c66aa2..8aa697781e2 100644 --- a/src/common/Collision/Models/WorldModel.cpp +++ b/src/common/Collision/Models/WorldModel.cpp @@ -371,9 +371,7 @@ namespace VMAP vertices(vert.begin()), triangles(tris.begin()), hit(false) { } bool operator()(G3D::Ray const& ray, uint32 entry, float& distance, bool /*pStopAtFirstHit*/) { - bool result = IntersectTriangle(triangles[entry], vertices, ray, distance); - if (result) - hit = true; + hit = IntersectTriangle(triangles[entry], vertices, ray, distance) || hit; return hit; } std::vector<Vector3>::const_iterator vertices; @@ -395,7 +393,6 @@ namespace VMAP { if (triangles.empty() || !iBound.contains(pos)) return false; - GModelRayCallback callback(triangles, vertices); Vector3 rPos = pos - 0.1f * down; float dist = G3D::finf(); G3D::Ray ray(rPos, down); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 69164e260c7..f2e9aa022e8 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -3277,8 +3277,12 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float return; } + float halfHeight = GetCollisionHeight() * 0.5f; UpdateAllowedPositionZ(destx, desty, destz); - bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(GetMapId(), pos.m_positionX, pos.m_positionY, pos.m_positionZ, destx, desty, destz, destx, desty, destz, -0.5f); + bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(GetMapId(), + pos.m_positionX, pos.m_positionY, pos.m_positionZ + halfHeight, + destx, desty, destz + halfHeight, + destx, desty, destz, -0.5f); // collision occured if (col) @@ -3290,7 +3294,10 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float } // check dynamic collision - col = GetMap()->getObjectHitPos(GetPhaseMask(), pos.m_positionX, pos.m_positionY, pos.m_positionZ, destx, desty, destz, destx, desty, destz, -0.5f); + col = GetMap()->getObjectHitPos(GetPhaseMask(), + pos.m_positionX, pos.m_positionY, pos.m_positionZ + halfHeight, + destx, desty, destz + halfHeight, + destx, desty, destz, -0.5f); // Collided with a gameobject if (col) @@ -3507,10 +3514,9 @@ float WorldObject::GetFloorZ() const float WorldObject::GetMapWaterOrGroundLevel(float x, float y, float z, float* ground/* = nullptr*/) const { - if (Unit const* unit = ToUnit()) - return GetMap()->GetWaterOrGroundLevel(GetPhaseMask(), x, y, z, ground, !unit->HasAuraType(SPELL_AURA_WATER_WALK), GetCollisionHeight()); - - return z; + return GetMap()->GetWaterOrGroundLevel(GetPhaseMask(), x, y, z, ground, + isType(TYPEMASK_UNIT) ? !static_cast<Unit const*>(this)->HasAuraType(SPELL_AURA_WATER_WALK) : false, + GetCollisionHeight()); } float WorldObject::GetMapHeight(float x, float y, float z, bool vmap/* = true*/, float distanceToSearch/* = DEFAULT_HEIGHT_SEARCH*/) const diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index afe5e8d6727..e99d33e62c2 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -51,6 +51,9 @@ u_map_magic MapAreaMagic = { {'A','R','E','A'} }; u_map_magic MapHeightMagic = { {'M','H','G','T'} }; u_map_magic MapLiquidMagic = { {'M','L','I','Q'} }; +static uint16 const holetab_h[4] = { 0x1111, 0x2222, 0x4444, 0x8888 }; +static uint16 const holetab_v[4] = { 0x000F, 0x00F0, 0x0F00, 0xF000 }; + #define DEFAULT_GRID_EXPIRY 300 #define MAX_GRID_LOAD_TIME 50 #define MAX_CREATURE_ATTACK_RADIUS (45.0f * sWorld->getRate(RATE_CREATURE_AGGRO)) @@ -1746,6 +1749,7 @@ GridMap::GridMap() _liquidEntry = nullptr; _liquidFlags = nullptr; _liquidMap = nullptr; + _holes = nullptr; } GridMap::~GridMap() @@ -1793,6 +1797,13 @@ bool GridMap::loadData(char const* filename) fclose(in); return false; } + // loadup holes data (if any. check header.holesOffset) + if (header.holesSize && !loadHolesData(in, header.holesOffset, header.holesSize)) + { + TC_LOG_ERROR("maps", "Error loading map holes data\n"); + fclose(in); + return false; + } fclose(in); return true; } @@ -1813,6 +1824,7 @@ void GridMap::unloadData() delete[] _liquidEntry; delete[] _liquidFlags; delete[] _liquidMap; + delete[] _holes; _areaMap = nullptr; m_V9 = nullptr; m_V8 = nullptr; @@ -1821,6 +1833,7 @@ void GridMap::unloadData() _liquidEntry = nullptr; _liquidFlags = nullptr; _liquidMap = nullptr; + _holes = nullptr; _gridGetHeight = &GridMap::getHeightFromFlat; } @@ -1932,6 +1945,18 @@ bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/) return true; } +bool GridMap::loadHolesData(FILE* in, uint32 offset, uint32 size) +{ + if (fseek(in, offset, SEEK_SET) != 0) + return false; + + _holes = new uint16[16 * 16]; + if (fread(_holes, sizeof(uint16), 16 * 16, in) != 16 * 16) + return false; + + return true; +} + uint16 GridMap::getArea(float x, float y) const { if (!_areaMap) @@ -1964,6 +1989,9 @@ float GridMap::getHeightFromFloat(float x, float y) const x_int&=(MAP_RESOLUTION - 1); y_int&=(MAP_RESOLUTION - 1); + if (isHole(x_int, y_int)) + return INVALID_HEIGHT; + // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid // +--------------> X // | h1-------h2 Coordinates is: @@ -2046,6 +2074,9 @@ float GridMap::getHeightFromUint8(float x, float y) const x_int&=(MAP_RESOLUTION - 1); y_int&=(MAP_RESOLUTION - 1); + if (isHole(x_int, y_int)) + return INVALID_HEIGHT; + int32 a, b, c; uint8 *V9_h1_ptr = &m_uint8_V9[x_int*128 + x_int + y_int]; if (x+y < 1) @@ -2113,6 +2144,9 @@ float GridMap::getHeightFromUint16(float x, float y) const x_int&=(MAP_RESOLUTION - 1); y_int&=(MAP_RESOLUTION - 1); + if (isHole(x_int, y_int)) + return INVALID_HEIGHT; + int32 a, b, c; uint16 *V9_h1_ptr = &m_uint16_V9[x_int*128 + x_int + y_int]; if (x+y < 1) @@ -2165,6 +2199,21 @@ float GridMap::getHeightFromUint16(float x, float y) const return (float)((a * x) + (b * y) + c)*_gridIntHeightMultiplier + _gridHeight; } +bool GridMap::isHole(int row, int col) const +{ + if (!_holes) + return false; + + int cellRow = row / 8; // 8 squares per cell + int cellCol = col / 8; + int holeRow = row % 8 / 2; + int holeCol = (col - (cellCol * 8)) / 2; + + uint16 hole = _holes[cellRow * 16 + cellCol]; + + return (hole & holetab_h[holeCol] & holetab_v[holeRow]) != 0; +} + float GridMap::getMinHeight(float x, float y) const { if (!_minHeight) @@ -2244,19 +2293,6 @@ float GridMap::getLiquidLevel(float x, float y) const return _liquidMap[cx_int*_liquidWidth + cy_int]; } -// Why does this return LIQUID data? -uint8 GridMap::getTerrainType(float x, float y) const -{ - if (!_liquidFlags) - return 0; - - x = 16 * (CENTER_GRID_ID - x/SIZE_OF_GRIDS); - y = 16 * (CENTER_GRID_ID - y/SIZE_OF_GRIDS); - int lx = (int)x & 15; - int ly = (int)y & 15; - return _liquidFlags[lx*16 + ly]; -} - // Get water state on map inline ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data, float collisionHeight) { @@ -2398,7 +2434,7 @@ float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y)) { float gridHeight = gmap->getHeight(x, y); - if (z > gridHeight) + if (G3D::fuzzyGe(z, gridHeight - GROUND_HEIGHT_TOLERANCE)) mapHeight = gridHeight; } @@ -2440,101 +2476,44 @@ float Map::GetMinHeight(float x, float y) const return -500.0f; } -inline bool IsOutdoorWMO(uint32 mogpFlags, WMOAreaTableEntry const* wmoEntry, AreaTableEntry const* atEntry) -{ - if (wmoEntry && atEntry) - { - if (atEntry->flags & AREA_FLAG_OUTSIDE) - return true; - if (atEntry->flags & AREA_FLAG_INSIDE) - return false; - } - - if (wmoEntry) - { - if (wmoEntry->Flags & 4) - return true; - if (wmoEntry->Flags & 2) - return false; - } - - return (mogpFlags & 0x8); -} - -bool Map::IsOutdoors(float x, float y, float z) const -{ - uint32 mogpFlags; - int32 adtId, rootId, groupId; - - // no wmo found? -> outside by default - if (!GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId)) - return true; - - AreaTableEntry const* atEntry = nullptr; - WMOAreaTableEntry const* wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId); - if (wmoEntry) - { - TC_LOG_DEBUG("maps", "Got WMOAreaTableEntry! flag %u, areaid %u", wmoEntry->Flags, wmoEntry->areaId); - atEntry = sAreaTableStore.LookupEntry(wmoEntry->areaId); - } - return IsOutdoorWMO(mogpFlags, wmoEntry, atEntry); -} - -bool Map::GetAreaInfo(float x, float y, float z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const +static inline bool IsInWMOInterior(uint32 mogpFlags) { - float vmap_z = z; - VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); - if (vmgr->getAreaInfo(GetId(), 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)) - { - float _mapheight = gmap->getHeight(x, y); - if (z > _mapheight && _mapheight > vmap_z) - return false; - } - return true; + return (mogpFlags & 0x2000) != 0; } - return false; -} -uint32 Map::GetAreaId(float x, float y, float z, bool *isOutdoors) const +uint32 Map::GetAreaId(float x, float y, float z) const { uint32 mogpFlags; int32 adtId, rootId, groupId; - WMOAreaTableEntry const* wmoEntry = nullptr; - AreaTableEntry const* atEntry = nullptr; - bool haveAreaInfo = false; + float vmapZ; + bool hasVmapArea = VMAP::VMapFactory::createOrGetVMapManager()->getAreaInfo(GetId(), x, y, vmapZ, mogpFlags, adtId, rootId, groupId); - if (GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId)) + uint32 gridAreaId = 0; + float gridMapHeight = INVALID_HEIGHT; + if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y)) { - haveAreaInfo = true; - wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId); - if (wmoEntry) - atEntry = sAreaTableStore.LookupEntry(wmoEntry->areaId); + gridAreaId = gmap->getArea(x, y); + gridMapHeight = gmap->getHeight(x, y); } uint32 areaId = 0; - if (atEntry) - areaId = atEntry->ID; - else + // floor is the height we are closer to (but only if above) + if (hasVmapArea && G3D::fuzzyGe(z, vmapZ - GROUND_HEIGHT_TOLERANCE) && (G3D::fuzzyLt(z, gridMapHeight - GROUND_HEIGHT_TOLERANCE) || vmapZ > gridMapHeight)) { - if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y)) - areaId = gmap->getArea(x, y); + // wmo found + if (WMOAreaTableEntry const* wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId)) + areaId = wmoEntry->areaId; - // this used while not all *.map files generated (instances) if (!areaId) - areaId = i_mapEntry->linked_zone; + areaId = gridAreaId; } + else + areaId = gridAreaId; + + if (!areaId) + areaId = i_mapEntry->linked_zone; - if (isOutdoors) - { - if (haveAreaInfo) - *isOutdoors = IsOutdoorWMO(mogpFlags, wmoEntry, atEntry); - else - *isOutdoors = true; - } return areaId; } @@ -2556,14 +2535,6 @@ void Map::GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, flo zoneid = area->zone; } -uint8 Map::GetTerrainType(float x, float y) const -{ - if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y)) - return gmap->getTerrainType(x, y); - else - return 0; -} - ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data, float collisionHeight) const { ZLiquidStatus result = LIQUID_MAP_NO_WATER; @@ -2571,11 +2542,14 @@ ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp float liquid_level = INVALID_HEIGHT; float ground_level = INVALID_HEIGHT; uint32 liquid_type = 0; - if (vmgr->GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type)) + uint32 mogpFlags = 0; + bool useGridLiquid = true; + if (vmgr->GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type, mogpFlags)) { + useGridLiquid = !IsInWMOInterior(mogpFlags); 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 - if (liquid_level > ground_level && z > ground_level - 2) + if (liquid_level > ground_level && G3D::fuzzyGe(z, ground_level - GROUND_HEIGHT_TOLERANCE)) { // All ok in water -> store data if (data) @@ -2628,6 +2602,8 @@ ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp } } + if (useGridLiquid) + { if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y)) { LiquidData map_data; @@ -2646,6 +2622,7 @@ ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp return map_result; } } + } return result; } @@ -2653,55 +2630,71 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul { VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); VMAP::AreaAndLiquidData vmapData; + GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y); vmgr->getAreaAndLiquidData(GetId(), x, y, z, reqLiquidType, vmapData); - if (vmapData.areaInfo) - data.areaInfo = boost::in_place(vmapData.areaInfo->adtId, vmapData.areaInfo->rootId, vmapData.areaInfo->groupId, vmapData.areaInfo->mogpFlags); - float mapHeight = VMAP_INVALID_HEIGHT; - GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y); + uint32 gridAreaId = 0; + float gridMapHeight = INVALID_HEIGHT; if (gmap) - mapHeight = gmap->getHeight(x, y); - - // area lookup - AreaTableEntry const* areaEntry = nullptr; - WMOAreaTableEntry const* wmoEntry = nullptr; - // the vmap floor is our floor if either - // - the vmap floor is above the gridmap floor - // or - // - we are below the gridmap floor - if (vmapData.areaInfo && (G3D::fuzzyLt(z, mapHeight - GROUND_HEIGHT_TOLERANCE) || mapHeight <= vmapData.floorZ)) - if ((wmoEntry = GetWMOAreaTableEntryByTripple(vmapData.areaInfo->rootId, vmapData.areaInfo->adtId, vmapData.areaInfo->groupId))) - areaEntry = sAreaTableStore.LookupEntry(wmoEntry->areaId); + { + gridAreaId = gmap->getArea(x, y); + gridMapHeight = gmap->getHeight(x, y); + } - data.areaId = 0; + bool vmapLocation = false; + bool useGridLiquid = true; - if (areaEntry) + // floor is the height we are closer to (but only if above) + data.floorZ = VMAP_INVALID_HEIGHT; + if (gridMapHeight > INVALID_HEIGHT && G3D::fuzzyGe(z, gridMapHeight - GROUND_HEIGHT_TOLERANCE)) + data.floorZ = gridMapHeight; + if (vmapData.floorZ > VMAP_INVALID_HEIGHT && + G3D::fuzzyGe(z, vmapData.floorZ - GROUND_HEIGHT_TOLERANCE) && + (G3D::fuzzyLt(z, gridMapHeight - GROUND_HEIGHT_TOLERANCE) || vmapData.floorZ > gridMapHeight)) { - data.areaId = areaEntry->ID; data.floorZ = vmapData.floorZ; + vmapLocation = true; + } + + if (vmapLocation) + { + if (vmapData.areaInfo) + { + data.areaInfo = boost::in_place(vmapData.areaInfo->adtId, vmapData.areaInfo->rootId, vmapData.areaInfo->groupId, vmapData.areaInfo->mogpFlags); + // wmo found + WMOAreaTableEntry const* wmoEntry = GetWMOAreaTableEntryByTripple(vmapData.areaInfo->rootId, vmapData.areaInfo->adtId, vmapData.areaInfo->groupId); + data.outdoors = (vmapData.areaInfo->mogpFlags & 0x8) != 0; + if (wmoEntry) + { + data.areaId = wmoEntry->areaId; + if (wmoEntry->Flags & 4) + data.outdoors = true; + else if (wmoEntry->Flags & 2) + data.outdoors = false; + } + + if (!data.areaId) + data.areaId = gridAreaId; + + useGridLiquid = !IsInWMOInterior(vmapData.areaInfo->mogpFlags); + } } else { - if (gmap) - data.areaId = gmap->getArea(x, y); + data.outdoors = true; + data.areaId = gridAreaId; + if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(data.areaId)) + data.outdoors = (areaEntry->flags & (AREA_FLAG_INSIDE | AREA_FLAG_OUTSIDE)) != AREA_FLAG_INSIDE; + } if (!data.areaId) data.areaId = i_mapEntry->linked_zone; - if (data.areaId) - areaEntry = sAreaTableStore.LookupEntry(data.areaId); - - data.floorZ = mapHeight; - } - - if (vmapData.areaInfo) - data.outdoors = IsOutdoorWMO(vmapData.areaInfo->mogpFlags, wmoEntry, areaEntry); - else - data.outdoors = true; // @todo default true taken from old GetAreaId check, maybe review + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(data.areaId); // liquid processing data.liquidStatus = LIQUID_MAP_NO_WATER; - if (vmapData.liquidInfo && vmapData.liquidInfo->level > vmapData.floorZ && z > vmapData.floorZ) + if (vmapLocation && vmapData.liquidInfo && vmapData.liquidInfo->level > vmapData.floorZ) { uint32 liquidType = vmapData.liquidInfo->type; if (GetId() == 530 && liquidType == 2) // gotta love blizzard hacks @@ -2745,7 +2738,7 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul data.liquidStatus = LIQUID_MAP_ABOVE_WATER; } // look up liquid data from grid map - if (gmap && (data.liquidStatus == LIQUID_MAP_ABOVE_WATER || data.liquidStatus == LIQUID_MAP_NO_WATER)) + if (gmap && useGridLiquid) { LiquidData gridMapLiquid; ZLiquidStatus gridMapStatus = gmap->GetLiquidStatus(x, y, z, reqLiquidType, &gridMapLiquid, collisionHeight); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 4cfa53252fc..a962a761b60 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -219,10 +219,13 @@ class TC_GAME_API GridMap uint8 _liquidWidth; uint8 _liquidHeight; + uint16* _holes; bool loadAreaData(FILE* in, uint32 offset, uint32 size); bool loadHeightData(FILE* in, uint32 offset, uint32 size); bool loadLiquidData(FILE* in, uint32 offset, uint32 size); + bool loadHolesData(FILE* in, uint32 offset, uint32 size); + bool isHole(int row, int col) const; // Get height functions and pointers typedef float (GridMap::*GetHeightPtr) (float x, float y) const; @@ -242,7 +245,6 @@ public: inline float getHeight(float x, float y) const {return (this->*_gridGetHeight)(x, y);} float getMinHeight(float x, float y) const; 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, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h }; @@ -387,17 +389,13 @@ class TC_GAME_API Map : public GridRefManager<NGridType> void GetFullTerrainStatusForPosition(float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h - bool GetAreaInfo(float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const; - uint32 GetAreaId(float x, float y, float z, bool *isOutdoors = nullptr) const; + uint32 GetAreaId(float x, float y, float z) const; uint32 GetAreaId(Position const& pos) const { return GetAreaId(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } uint32 GetZoneId(float x, float y, float z) const; uint32 GetZoneId(Position const& pos) const { return GetZoneId(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const; void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, Position const& pos) const { GetZoneAndAreaId(zoneid, areaid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); } - bool IsOutdoors(float x, float y, float z) const; - - uint8 GetTerrainType(float x, float y) const; float GetWaterLevel(float x, float y) const; bool IsInWater(float x, float y, float z, LiquidData* data = nullptr) const; bool IsUnderWater(float x, float y, float z) const; diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 912de049261..03f383b2fd7 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -581,7 +581,10 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin void PathGenerator::NormalizePath() { for (uint32 i = 0; i < _pathPoints.size(); ++i) + { + _pathPoints[i].z += _sourceUnit->GetCollisionHeight(); _sourceUnit->UpdateAllowedPositionZ(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z); + } } void PathGenerator::BuildShortcut() |