mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Maps: Adjusted logic in GetFullTerrainStatusForPosition to closer match what the client does regarding being inside WMOs
Closes #21625
Closes #21624
Closes #21516
(cherry picked from commit b9c6bbb51d)
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
@@ -286,7 +286,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))
|
||||
{
|
||||
@@ -304,7 +304,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))
|
||||
{
|
||||
@@ -319,6 +319,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);
|
||||
|
||||
@@ -107,9 +107,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);
|
||||
|
||||
@@ -398,9 +398,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;
|
||||
@@ -422,7 +420,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);
|
||||
|
||||
@@ -3130,9 +3130,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(PhasingHandler::GetTerrainMapId(GetPhaseShift(), GetMap(), pos.m_positionX, pos.m_positionY),
|
||||
pos.m_positionX, pos.m_positionY, pos.m_positionZ, destx, desty, destz, destx, desty, destz, -0.5f);
|
||||
pos.m_positionX, pos.m_positionY, pos.m_positionZ + halfHeight,
|
||||
destx, desty, destz + halfHeight,
|
||||
destx, desty, destz, -0.5f);
|
||||
|
||||
// collision occured
|
||||
if (col)
|
||||
@@ -3144,7 +3147,10 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float
|
||||
}
|
||||
|
||||
// check dynamic collision
|
||||
col = GetMap()->getObjectHitPos(GetPhaseShift(), pos.m_positionX, pos.m_positionY, pos.m_positionZ, destx, desty, destz, destx, desty, destz, -0.5f);
|
||||
col = GetMap()->getObjectHitPos(GetPhaseShift(),
|
||||
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)
|
||||
@@ -3342,10 +3348,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(GetPhaseShift(), x, y, z, ground, !unit->HasAuraType(SPELL_AURA_WATER_WALK), GetCollisionHeight());
|
||||
|
||||
return z;
|
||||
return GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), 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
|
||||
|
||||
@@ -1833,6 +1833,7 @@ GridMap::GridMap()
|
||||
_liquidEntry = nullptr;
|
||||
_liquidFlags = nullptr;
|
||||
_liquidMap = nullptr;
|
||||
_holes = nullptr;
|
||||
}
|
||||
|
||||
GridMap::~GridMap()
|
||||
@@ -1880,6 +1881,13 @@ GridMap::LoadResult GridMap::loadData(char const* filename)
|
||||
fclose(in);
|
||||
return LoadResult::InvalidFile;
|
||||
}
|
||||
// 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 LoadResult::InvalidFile;
|
||||
}
|
||||
fclose(in);
|
||||
return LoadResult::Ok;
|
||||
}
|
||||
@@ -1899,6 +1907,7 @@ void GridMap::unloadData()
|
||||
delete[] _liquidEntry;
|
||||
delete[] _liquidFlags;
|
||||
delete[] _liquidMap;
|
||||
delete[] _holes;
|
||||
_areaMap = nullptr;
|
||||
m_V9 = nullptr;
|
||||
m_V8 = nullptr;
|
||||
@@ -1906,6 +1915,7 @@ void GridMap::unloadData()
|
||||
_liquidEntry = nullptr;
|
||||
_liquidFlags = nullptr;
|
||||
_liquidMap = nullptr;
|
||||
_holes = nullptr;
|
||||
_gridGetHeight = &GridMap::getHeightFromFlat;
|
||||
}
|
||||
|
||||
@@ -2051,6 +2061,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 uint8[16 * 16 * 8];
|
||||
if (fread(_holes, sizeof(uint8), 16 * 16 * 8, in) != 16 * 16 * 8)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16 GridMap::getArea(float x, float y) const
|
||||
{
|
||||
if (!_areaMap)
|
||||
@@ -2083,6 +2105,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:
|
||||
@@ -2165,6 +2190,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)
|
||||
@@ -2232,6 +2260,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)
|
||||
@@ -2284,6 +2315,19 @@ 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;
|
||||
int holeCol = col % 8;
|
||||
|
||||
return (_holes[cellRow * 16 * 8 + cellCol * 8 + holeRow] & (1 << holeCol)) != 0;
|
||||
}
|
||||
|
||||
float GridMap::getMinHeight(float x, float y) const
|
||||
{
|
||||
if (!_minHeightPlanes)
|
||||
@@ -2333,19 +2377,6 @@ float GridMap::getLiquidLevel(float x, float y) const
|
||||
return _liquidMap[cx_int*_liquidWidth + cy_int];
|
||||
}
|
||||
|
||||
// Why does this return LIQUID data?
|
||||
map_liquidHeaderTypeFlags GridMap::getTerrainType(float x, float y) const
|
||||
{
|
||||
if (!_liquidFlags)
|
||||
return map_liquidHeaderTypeFlags::NoWater;
|
||||
|
||||
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, Optional<map_liquidHeaderTypeFlags> ReqLiquidType, LiquidData* data, float collisionHeight)
|
||||
{
|
||||
@@ -2495,7 +2526,7 @@ float Map::GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float
|
||||
if (GridMap* gmap = GetGrid(terrainMapId, x, y))
|
||||
{
|
||||
float gridHeight = gmap->getHeight(x, y);
|
||||
if (z > gridHeight)
|
||||
if (G3D::fuzzyGe(z, gridHeight - GROUND_HEIGHT_TOLERANCE))
|
||||
mapHeight = gridHeight;
|
||||
}
|
||||
|
||||
@@ -2537,46 +2568,12 @@ float Map::GetMinHeight(PhaseShift const& phaseShift, float x, float y)
|
||||
return -500.0f;
|
||||
}
|
||||
|
||||
inline bool IsOutdoorWMO(uint32 mogpFlags, WMOAreaTableEntry const* wmoEntry, AreaTableEntry const* atEntry)
|
||||
static inline bool IsInWMOInterior(uint32 mogpFlags)
|
||||
{
|
||||
if (wmoEntry && atEntry)
|
||||
{
|
||||
if (atEntry->Flags[0] & AREA_FLAG_OUTSIDE)
|
||||
return true;
|
||||
if (atEntry->Flags[0] & AREA_FLAG_INSIDE)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wmoEntry)
|
||||
{
|
||||
if (wmoEntry->Flags & 4)
|
||||
return true;
|
||||
if (wmoEntry->Flags & 2)
|
||||
return false;
|
||||
}
|
||||
return (mogpFlags & 0x8);
|
||||
return (mogpFlags & 0x2000) != 0;
|
||||
}
|
||||
|
||||
bool Map::IsOutdoors(PhaseShift const& phaseShift, float x, float y, float z)
|
||||
{
|
||||
uint32 mogpFlags;
|
||||
int32 adtId, rootId, groupId;
|
||||
|
||||
// no wmo found? -> outside by default
|
||||
if (!GetAreaInfo(phaseShift, x, y, z, mogpFlags, adtId, rootId, groupId))
|
||||
return true;
|
||||
|
||||
AreaTableEntry const* atEntry = nullptr;
|
||||
WMOAreaTableEntry const* wmoEntry = sDB2Manager.GetWMOAreaTable(rootId, adtId, groupId);
|
||||
if (wmoEntry)
|
||||
{
|
||||
TC_LOG_DEBUG("maps", "Got WMOAreaTableEntry! flag %u, areaid %u", wmoEntry->Flags, wmoEntry->AreaTableID);
|
||||
atEntry = sAreaTableStore.LookupEntry(wmoEntry->AreaTableID);
|
||||
}
|
||||
return IsOutdoorWMO(mogpFlags, wmoEntry, atEntry);
|
||||
}
|
||||
|
||||
bool Map::GetAreaInfo(PhaseShift const& phaseShift, float x, float y, float z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId)
|
||||
bool Map::GetAreaInfo(PhaseShift const& phaseShift, float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId)
|
||||
{
|
||||
float vmap_z = z;
|
||||
float dynamic_z = z;
|
||||
@@ -2594,8 +2591,8 @@ bool Map::GetAreaInfo(PhaseShift const& phaseShift, float x, float y, float z, u
|
||||
|
||||
bool hasVmapAreaInfo = vmgr->getAreaInfo(terrainMapId, x, y, vmap_z, vflags, vadtId, vrootId, vgroupId);
|
||||
bool hasDynamicAreaInfo = _dynamicTree.getAreaInfo(x, y, dynamic_z, phaseShift, dflags, dadtId, drootId, dgroupId);
|
||||
auto useVmap = [&]() { check_z = vmap_z; flags = vflags; adtId = vadtId; rootId = vrootId; groupId = vgroupId; };
|
||||
auto useDyn = [&]() { check_z = dynamic_z; flags = dflags; adtId = dadtId; rootId = drootId; groupId = dgroupId; };
|
||||
auto useVmap = [&]() { check_z = vmap_z; mogpflags = vflags; adtId = vadtId; rootId = vrootId; groupId = vgroupId; };
|
||||
auto useDyn = [&]() { check_z = dynamic_z; mogpflags = dflags; adtId = dadtId; rootId = drootId; groupId = dgroupId; };
|
||||
|
||||
if (hasVmapAreaInfo)
|
||||
{
|
||||
@@ -2615,7 +2612,8 @@ bool Map::GetAreaInfo(PhaseShift const& phaseShift, float x, float y, float z, u
|
||||
if (GridMap* gmap = GetGrid(terrainMapId, x, y))
|
||||
{
|
||||
float mapHeight = gmap->getHeight(x, y);
|
||||
if (z > mapHeight && mapHeight > vmap_z)
|
||||
// z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice...
|
||||
if (z + 2.0f > mapHeight && mapHeight > check_z)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -2623,43 +2621,39 @@ bool Map::GetAreaInfo(PhaseShift const& phaseShift, float x, float y, float z, u
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 Map::GetAreaId(PhaseShift const& phaseShift, float x, float y, float z, bool *isOutdoors)
|
||||
uint32 Map::GetAreaId(PhaseShift const& phaseShift, float x, float y, float z)
|
||||
{
|
||||
uint32 mogpFlags;
|
||||
int32 adtId, rootId, groupId;
|
||||
WMOAreaTableEntry const* wmoEntry = nullptr;
|
||||
AreaTableEntry const* atEntry = nullptr;
|
||||
bool haveAreaInfo = false;
|
||||
float vmapZ = z;
|
||||
bool hasVmapArea = GetAreaInfo(phaseShift, x, y, vmapZ, mogpFlags, adtId, rootId, groupId);
|
||||
|
||||
uint32 gridAreaId = 0;
|
||||
float gridMapHeight = INVALID_HEIGHT;
|
||||
if (GridMap* gmap = GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, this, x, y), x, y))
|
||||
{
|
||||
gridAreaId = gmap->getArea(x, y);
|
||||
gridMapHeight = gmap->getHeight(x, y);
|
||||
}
|
||||
|
||||
uint32 areaId = 0;
|
||||
|
||||
if (GetAreaInfo(phaseShift, x, y, z, mogpFlags, adtId, rootId, groupId))
|
||||
// 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))
|
||||
{
|
||||
haveAreaInfo = true;
|
||||
wmoEntry = sDB2Manager.GetWMOAreaTable(rootId, adtId, groupId);
|
||||
if (wmoEntry)
|
||||
{
|
||||
// wmo found
|
||||
if (WMOAreaTableEntry const* wmoEntry = sDB2Manager.GetWMOAreaTable(rootId, adtId, groupId))
|
||||
areaId = wmoEntry->AreaTableID;
|
||||
atEntry = sAreaTableStore.LookupEntry(wmoEntry->AreaTableID);
|
||||
}
|
||||
|
||||
if (!areaId)
|
||||
areaId = gridAreaId;
|
||||
}
|
||||
else
|
||||
areaId = gridAreaId;
|
||||
|
||||
if (!areaId)
|
||||
{
|
||||
if (GridMap* gmap = GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, this, x, y), x, y))
|
||||
areaId = gmap->getArea(x, y);
|
||||
areaId = i_mapEntry->AreaTableID;
|
||||
|
||||
// this used while not all *.map files generated (instances)
|
||||
if (!areaId)
|
||||
areaId = i_mapEntry->AreaTableID;
|
||||
}
|
||||
|
||||
if (isOutdoors)
|
||||
{
|
||||
if (haveAreaInfo)
|
||||
*isOutdoors = IsOutdoorWMO(mogpFlags, wmoEntry, atEntry);
|
||||
else
|
||||
*isOutdoors = true;
|
||||
}
|
||||
return areaId;
|
||||
}
|
||||
|
||||
@@ -2681,14 +2675,6 @@ void Map::GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32&
|
||||
zoneid = area->ParentAreaID;
|
||||
}
|
||||
|
||||
map_liquidHeaderTypeFlags Map::GetTerrainType(PhaseShift const& phaseShift, float x, float y)
|
||||
{
|
||||
if (GridMap* gmap = GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, this, x, y), x, y))
|
||||
return gmap->getTerrainType(x, y);
|
||||
else
|
||||
return map_liquidHeaderTypeFlags::NoWater;
|
||||
}
|
||||
|
||||
ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, map_liquidHeaderTypeFlags ReqLiquidType, LiquidData* data, float collisionHeight)
|
||||
{
|
||||
ZLiquidStatus result = LIQUID_MAP_NO_WATER;
|
||||
@@ -2696,12 +2682,15 @@ ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float
|
||||
float liquid_level = INVALID_HEIGHT;
|
||||
float ground_level = INVALID_HEIGHT;
|
||||
uint32 liquid_type = 0;
|
||||
uint32 mogpFlags = 0;
|
||||
bool useGridLiquid = true;
|
||||
uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, this, x, y);
|
||||
if (vmgr->GetLiquidLevel(terrainMapId, x, y, z, AsUnderlyingType(ReqLiquidType), liquid_level, ground_level, liquid_type))
|
||||
if (vmgr->GetLiquidLevel(terrainMapId, x, y, z, AsUnderlyingType(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)
|
||||
@@ -2754,22 +2743,25 @@ ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float
|
||||
}
|
||||
}
|
||||
|
||||
if (GridMap* gmap = GetGrid(terrainMapId, x, y))
|
||||
if (useGridLiquid)
|
||||
{
|
||||
LiquidData map_data;
|
||||
ZLiquidStatus map_result = gmap->GetLiquidStatus(x, y, z, ReqLiquidType, &map_data, collisionHeight);
|
||||
// Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER:
|
||||
if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > ground_level))
|
||||
if (GridMap* gmap = GetGrid(terrainMapId, x, y))
|
||||
{
|
||||
if (data)
|
||||
LiquidData map_data;
|
||||
ZLiquidStatus map_result = gmap->GetLiquidStatus(x, y, z, ReqLiquidType, &map_data, collisionHeight);
|
||||
// Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER:
|
||||
if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > ground_level))
|
||||
{
|
||||
// hardcoded in client like this
|
||||
if (GetId() == 530 && map_data.entry == 2)
|
||||
map_data.entry = 15;
|
||||
if (data)
|
||||
{
|
||||
// hardcoded in client like this
|
||||
if (GetId() == 530 && map_data.entry == 2)
|
||||
map_data.entry = 15;
|
||||
|
||||
*data = map_data;
|
||||
*data = map_data;
|
||||
}
|
||||
return map_result;
|
||||
}
|
||||
return map_result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -2779,58 +2771,87 @@ void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x,
|
||||
{
|
||||
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
|
||||
VMAP::AreaAndLiquidData vmapData;
|
||||
VMAP::AreaAndLiquidData dynData;
|
||||
VMAP::AreaAndLiquidData* wmoData = nullptr;
|
||||
uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, this, x, y);
|
||||
vmgr->getAreaAndLiquidData(terrainMapId, x, y, z, AsUnderlyingType(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 = GetGrid(terrainMapId, x, y);
|
||||
vmgr->getAreaAndLiquidData(terrainMapId, x, y, z, AsUnderlyingType(reqLiquidType), vmapData);
|
||||
_dynamicTree.getAreaAndLiquidData(x, y, z, phaseShift, AsUnderlyingType(reqLiquidType), dynData);
|
||||
|
||||
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 = sDB2Manager.GetWMOAreaTable(vmapData.areaInfo->rootId, vmapData.areaInfo->adtId, vmapData.areaInfo->groupId)))
|
||||
areaEntry = sAreaTableStore.LookupEntry(wmoEntry->AreaTableID);
|
||||
|
||||
if (areaEntry)
|
||||
{
|
||||
data.areaId = areaEntry->ID;
|
||||
gridAreaId = gmap->getArea(x, y);
|
||||
gridMapHeight = gmap->getHeight(x, y);
|
||||
}
|
||||
|
||||
bool useGridLiquid = true;
|
||||
|
||||
// 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.floorZ = vmapData.floorZ;
|
||||
wmoData = &vmapData;
|
||||
}
|
||||
// NOTE: Objects will not detect a case when a wmo providing area/liquid despawns from under them
|
||||
// but this is fine as these kind of objects are not meant to be spawned and despawned a lot
|
||||
// example: Lich King platform
|
||||
if (dynData.floorZ > VMAP_INVALID_HEIGHT &&
|
||||
G3D::fuzzyGe(z, dynData.floorZ - GROUND_HEIGHT_TOLERANCE) &&
|
||||
(G3D::fuzzyLt(z, gridMapHeight - GROUND_HEIGHT_TOLERANCE) || dynData.floorZ > gridMapHeight) &&
|
||||
(G3D::fuzzyLt(z, vmapData.floorZ - GROUND_HEIGHT_TOLERANCE) || dynData.floorZ > vmapData.floorZ))
|
||||
{
|
||||
data.floorZ = dynData.floorZ;
|
||||
wmoData = &dynData;
|
||||
}
|
||||
|
||||
if (wmoData)
|
||||
{
|
||||
if (wmoData->areaInfo)
|
||||
{
|
||||
data.areaInfo.emplace(wmoData->areaInfo->adtId, wmoData->areaInfo->rootId, wmoData->areaInfo->groupId, wmoData->areaInfo->mogpFlags);
|
||||
// wmo found
|
||||
WMOAreaTableEntry const* wmoEntry = sDB2Manager.GetWMOAreaTable(wmoData->areaInfo->rootId, wmoData->areaInfo->adtId, wmoData->areaInfo->groupId);
|
||||
data.outdoors = (wmoData->areaInfo->mogpFlags & 0x8) != 0;
|
||||
if (wmoEntry)
|
||||
{
|
||||
data.areaId = wmoEntry->AreaTableID;
|
||||
if (wmoEntry->Flags & 4)
|
||||
data.outdoors = true;
|
||||
else if (wmoEntry->Flags & 2)
|
||||
data.outdoors = false;
|
||||
}
|
||||
|
||||
if (!data.areaId)
|
||||
data.areaId = gridAreaId;
|
||||
|
||||
useGridLiquid = !IsInWMOInterior(wmoData->areaInfo->mogpFlags);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gmap)
|
||||
data.areaId = gmap->getArea(x, y);
|
||||
else
|
||||
data.areaId = 0;
|
||||
|
||||
if (!data.areaId)
|
||||
data.areaId = i_mapEntry->AreaTableID;
|
||||
|
||||
if (data.areaId)
|
||||
areaEntry = sAreaTableStore.LookupEntry(data.areaId);
|
||||
|
||||
data.floorZ = mapHeight;
|
||||
data.outdoors = true;
|
||||
data.areaId = gridAreaId;
|
||||
if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(data.areaId))
|
||||
data.outdoors = (areaEntry->Flags[0] & (AREA_FLAG_INSIDE | AREA_FLAG_OUTSIDE)) != AREA_FLAG_INSIDE;
|
||||
}
|
||||
|
||||
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
|
||||
if (!data.areaId)
|
||||
data.areaId = i_mapEntry->AreaTableID;
|
||||
|
||||
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 (wmoData && wmoData->liquidInfo && wmoData->liquidInfo->level > wmoData->floorZ)
|
||||
{
|
||||
uint32 liquidType = vmapData.liquidInfo->type;
|
||||
uint32 liquidType = wmoData->liquidInfo->type;
|
||||
if (GetId() == 530 && liquidType == 2) // gotta love blizzard hacks
|
||||
liquidType = 15;
|
||||
|
||||
@@ -2855,13 +2876,13 @@ void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x,
|
||||
}
|
||||
}
|
||||
|
||||
data.liquidInfo = boost::in_place();
|
||||
data.liquidInfo->level = vmapData.liquidInfo->level;
|
||||
data.liquidInfo->depth_level = vmapData.floorZ;
|
||||
data.liquidInfo.emplace();
|
||||
data.liquidInfo->level = wmoData->liquidInfo->level;
|
||||
data.liquidInfo->depth_level = wmoData->floorZ;
|
||||
data.liquidInfo->entry = liquidType;
|
||||
data.liquidInfo->type_flags = map_liquidHeaderTypeFlags(1 << liquidFlagType);
|
||||
|
||||
float delta = vmapData.liquidInfo->level - z;
|
||||
float delta = wmoData->liquidInfo->level - z;
|
||||
if (delta > collisionHeight)
|
||||
data.liquidStatus = LIQUID_MAP_UNDER_WATER;
|
||||
else if (delta > 0.0f)
|
||||
@@ -2872,11 +2893,11 @@ void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x,
|
||||
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);
|
||||
if (gridMapStatus != LIQUID_MAP_NO_WATER && (gridMapLiquid.level > vmapData.floorZ))
|
||||
if (gridMapStatus != LIQUID_MAP_NO_WATER && (!wmoData || gridMapLiquid.level > wmoData->floorZ))
|
||||
{
|
||||
if (GetId() == 530 && gridMapLiquid.entry == 2)
|
||||
gridMapLiquid.entry = 15;
|
||||
|
||||
@@ -155,9 +155,13 @@ class TC_GAME_API GridMap
|
||||
uint8 _liquidWidth;
|
||||
uint8 _liquidHeight;
|
||||
|
||||
uint8* _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;
|
||||
@@ -185,7 +189,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;
|
||||
map_liquidHeaderTypeFlags getTerrainType(float x, float y) const;
|
||||
ZLiquidStatus GetLiquidStatus(float x, float y, float z, Optional<map_liquidHeaderTypeFlags> ReqLiquidType, LiquidData* data = nullptr, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h
|
||||
};
|
||||
|
||||
@@ -334,16 +337,13 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
|
||||
ZLiquidStatus GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, map_liquidHeaderTypeFlags ReqLiquidType, LiquidData* data = nullptr, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h
|
||||
|
||||
bool GetAreaInfo(PhaseShift const& phaseShift, float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId);
|
||||
uint32 GetAreaId(PhaseShift const& phaseShift, float x, float y, float z, bool *isOutdoors = nullptr);
|
||||
uint32 GetAreaId(PhaseShift const& phaseShift, float x, float y, float z);
|
||||
uint32 GetAreaId(PhaseShift const& phaseShift, Position const& pos) { return GetAreaId(phaseShift, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); }
|
||||
uint32 GetZoneId(PhaseShift const& phaseShift, float x, float y, float z);
|
||||
uint32 GetZoneId(PhaseShift const& phaseShift, Position const& pos) { return GetZoneId(phaseShift, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); }
|
||||
void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, float x, float y, float z);
|
||||
void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, Position const& pos) { GetZoneAndAreaId(phaseShift, zoneid, areaid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); }
|
||||
|
||||
bool IsOutdoors(PhaseShift const& phaseShift, float x, float y, float z);
|
||||
|
||||
map_liquidHeaderTypeFlags GetTerrainType(PhaseShift const& phaseShift, float x, float y);
|
||||
float GetWaterLevel(PhaseShift const& phaseShift, float x, float y);
|
||||
bool IsInWater(PhaseShift const& phaseShift, float x, float y, float z, LiquidData* data = nullptr);
|
||||
bool IsUnderWater(PhaseShift const& phaseShift, float x, float y, float z);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -1827,7 +1827,7 @@ private:
|
||||
{
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id, difficulty);
|
||||
|
||||
if (requireOutdoors && !targetPlayer->GetMap()->IsOutdoors(targetPlayer->GetPhaseShift(), targetPlayer->GetPositionX(), targetPlayer->GetPositionY(), targetPlayer->GetPositionZ()))
|
||||
if (requireOutdoors && !targetPlayer->IsOutdoors())
|
||||
return SPELL_FAILED_ONLY_OUTDOORS;
|
||||
|
||||
return spellInfo->CheckLocation(targetPlayer->GetMapId(), targetPlayer->GetZoneId(), targetPlayer->GetAreaId(), targetPlayer);
|
||||
|
||||
@@ -568,7 +568,7 @@ namespace MMAP
|
||||
int cellRow = row / 8; // 8 squares per cell
|
||||
int cellCol = col / 8;
|
||||
int holeRow = row % 8;
|
||||
int holeCol = (square - (row * 128 + cellCol * 8));
|
||||
int holeCol = col % 8;
|
||||
|
||||
return (holes[cellRow][cellCol][holeRow] & (1 << holeCol)) != 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user