aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2018-04-07 00:21:51 +0200
committerShauren <shauren.trinity@gmail.com>2018-04-07 21:36:15 +0200
commitb9c6bbb51df0ed10f74617482740fedb91ff5366 (patch)
tree9b54a41e2a8fe0075983548d2a31977e6cdd2a58 /src
parent2dadbda24ac1c2e6ff3dad650c7e25f4b3322342 (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.h4
-rw-r--r--src/common/Collision/Management/VMapManager2.cpp5
-rw-r--r--src/common/Collision/Management/VMapManager2.h6
-rw-r--r--src/common/Collision/Models/WorldModel.cpp5
-rw-r--r--src/server/game/Entities/Object/Object.cpp18
-rw-r--r--src/server/game/Maps/Map.cpp263
-rw-r--r--src/server/game/Maps/Map.h10
-rw-r--r--src/server/game/Movement/PathGenerator.cpp3
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()