aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Maps/Map.cpp
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2018-03-28 22:01:22 +0200
committerShauren <shauren.trinity@gmail.com>2020-06-27 20:23:30 +0200
commit0468c70dfe91794ad272594323dd7feb611d0a93 (patch)
treebb623c775fe215e4c0867fb2efa4bda0b360f7ec /src/server/game/Maps/Map.cpp
parent54c701cf0db81c0062e8c5020e07db18984d0ffa (diff)
Core/Maps: Implemented getting area id from gameobject spawns
Yes, you can now spawn LK platform anywhere and it will treat you as inside Icecrown Citadel (cherry picked from commit 42f9deb21ec68e169f7ed1c8cf14092f144b22da)
Diffstat (limited to 'src/server/game/Maps/Map.cpp')
-rw-r--r--src/server/game/Maps/Map.cpp116
1 files changed, 88 insertions, 28 deletions
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index e0378bfb7aa..bc23cc3ec5f 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -2446,7 +2446,7 @@ float Map::GetWaterOrGroundLevel(uint32 phasemask, float x, float y, float z, fl
LiquidData liquid_status;
- ZLiquidStatus res = GetLiquidStatus(x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status, collisionHeight);
+ ZLiquidStatus res = GetLiquidStatus(phasemask, x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status, collisionHeight);
switch (res)
{
case LIQUID_MAP_ABOVE_WATER:
@@ -2518,14 +2518,61 @@ float Map::GetMinHeight(float x, float y) const
static inline bool IsInWMOInterior(uint32 mogpFlags)
{
return (mogpFlags & 0x2000) != 0;
+}
+
+bool Map::GetAreaInfo(uint32 phaseMask, float x, float y, float z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const
+{
+ float vmap_z = z;
+ float dynamic_z = z;
+ float check_z = z;
+ VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
+ uint32 vflags;
+ int32 vadtId;
+ int32 vrootId;
+ int32 vgroupId;
+ uint32 dflags;
+ int32 dadtId;
+ int32 drootId;
+ int32 dgroupId;
+
+ bool hasVmapAreaInfo = vmgr->getAreaInfo(GetId(), x, y, vmap_z, vflags, vadtId, vrootId, vgroupId);
+ bool hasDynamicAreaInfo = _dynamicTree.getAreaInfo(x, y, dynamic_z, phaseMask, 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; };
+
+ if (hasVmapAreaInfo)
+ {
+ if (hasDynamicAreaInfo && dynamic_z > vmap_z)
+ useDyn();
+ else
+ useVmap();
+ }
+ else if (hasDynamicAreaInfo)
+ {
+ useDyn();
}
-uint32 Map::GetAreaId(float x, float y, float z) const
+ if (hasVmapAreaInfo || hasDynamicAreaInfo)
+ {
+ // 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);
+ // 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;
+ }
+ return false;
+}
+
+uint32 Map::GetAreaId(uint32 phaseMask, float x, float y, float z) const
{
uint32 mogpFlags;
int32 adtId, rootId, groupId;
float vmapZ = z;
- bool hasVmapArea = VMAP::VMapFactory::createOrGetVMapManager()->getAreaInfo(GetId(), x, y, vmapZ, mogpFlags, adtId, rootId, groupId);
+ bool hasVmapArea = GetAreaInfo(phaseMask, x, y, vmapZ, mogpFlags, adtId, rootId, groupId);
uint32 gridAreaId = 0;
float gridMapHeight = INVALID_HEIGHT;
@@ -2556,9 +2603,9 @@ uint32 Map::GetAreaId(float x, float y, float z) const
return areaId;
}
-uint32 Map::GetZoneId(float x, float y, float z) const
+uint32 Map::GetZoneId(uint32 phaseMask, float x, float y, float z) const
{
- uint32 areaId = GetAreaId(x, y, z);
+ uint32 areaId = GetAreaId(phaseMask, x, y, z);
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId))
if (area->zone)
return area->zone;
@@ -2566,15 +2613,15 @@ uint32 Map::GetZoneId(float x, float y, float z) const
return areaId;
}
-void Map::GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const
+void Map::GetZoneAndAreaId(uint32 phaseMask, uint32& zoneid, uint32& areaid, float x, float y, float z) const
{
- areaid = zoneid = GetAreaId(x, y, z);
+ areaid = zoneid = GetAreaId(phaseMask, x, y, z);
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaid))
if (area->zone)
zoneid = area->zone;
}
-ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data, float collisionHeight) const
+ZLiquidStatus Map::GetLiquidStatus(uint32 phaseMask, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data, float collisionHeight) const
{
ZLiquidStatus result = LIQUID_MAP_NO_WATER;
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
@@ -2603,7 +2650,7 @@ ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp
if (liquid_type && liquid_type < 21)
{
- if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId(x, y, z)))
+ if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId(phaseMask, x, y, z)))
{
uint32 overrideLiquid = area->LiquidTypeOverride[liquidFlagType];
if (!overrideLiquid && area->zone)
@@ -2665,12 +2712,15 @@ ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp
return result;
}
-void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType, float collisionHeight) const
+void Map::GetFullTerrainStatusForPosition(uint32 phaseMask, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType, float collisionHeight) const
{
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
VMAP::AreaAndLiquidData vmapData;
+ VMAP::AreaAndLiquidData dynData;
+ VMAP::AreaAndLiquidData* wmoData = nullptr;
GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y);
vmgr->getAreaAndLiquidData(GetId(), x, y, z, reqLiquidType, vmapData);
+ _dynamicTree.getAreaAndLiquidData(x, y, z, phaseMask, reqLiquidType, dynData);
uint32 gridAreaId = 0;
float gridMapHeight = INVALID_HEIGHT;
@@ -2680,7 +2730,6 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul
gridMapHeight = gmap->getHeight(x, y);
}
- bool vmapLocation = false;
bool useGridLiquid = true;
// floor is the height we are closer to (but only if above)
@@ -2692,17 +2741,28 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul
(G3D::fuzzyLt(z, gridMapHeight - GROUND_HEIGHT_TOLERANCE) || vmapData.floorZ > gridMapHeight))
{
data.floorZ = vmapData.floorZ;
- vmapLocation = true;
+ 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 (vmapLocation)
+ if (wmoData)
{
- if (vmapData.areaInfo)
+ if (wmoData->areaInfo)
{
- data.areaInfo = boost::in_place(vmapData.areaInfo->adtId, vmapData.areaInfo->rootId, vmapData.areaInfo->groupId, vmapData.areaInfo->mogpFlags);
+ data.areaInfo = boost::in_place(wmoData->areaInfo->adtId, wmoData->areaInfo->rootId, wmoData->areaInfo->groupId, wmoData->areaInfo->mogpFlags);
// wmo found
- WMOAreaTableEntry const* wmoEntry = GetWMOAreaTableEntryByTripple(vmapData.areaInfo->rootId, vmapData.areaInfo->adtId, vmapData.areaInfo->groupId);
- data.outdoors = (vmapData.areaInfo->mogpFlags & 0x8) != 0;
+ WMOAreaTableEntry const* wmoEntry = GetWMOAreaTableEntryByTripple(wmoData->areaInfo->rootId, wmoData->areaInfo->adtId, wmoData->areaInfo->groupId);
+ data.outdoors = (wmoData->areaInfo->mogpFlags & 0x8) != 0;
if (wmoEntry)
{
data.areaId = wmoEntry->areaId;
@@ -2715,7 +2775,7 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul
if (!data.areaId)
data.areaId = gridAreaId;
- useGridLiquid = !IsInWMOInterior(vmapData.areaInfo->mogpFlags);
+ useGridLiquid = !IsInWMOInterior(wmoData->areaInfo->mogpFlags);
}
}
else
@@ -2733,9 +2793,9 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul
// liquid processing
data.liquidStatus = LIQUID_MAP_NO_WATER;
- if (vmapLocation && vmapData.liquidInfo && vmapData.liquidInfo->level > 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;
@@ -2761,12 +2821,12 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul
}
data.liquidInfo = boost::in_place();
- data.liquidInfo->level = vmapData.liquidInfo->level;
- data.liquidInfo->depth_level = vmapData.floorZ;
+ data.liquidInfo->level = wmoData->liquidInfo->level;
+ data.liquidInfo->depth_level = wmoData->floorZ;
data.liquidInfo->entry = liquidType;
data.liquidInfo->type_flags = 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)
@@ -2781,7 +2841,7 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul
{
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;
@@ -2824,16 +2884,16 @@ bool Map::getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float
return result;
}
-bool Map::IsInWater(float x, float y, float pZ, LiquidData* data) const
+bool Map::IsInWater(uint32 phaseMask, float x, float y, float pZ, LiquidData* data) const
{
LiquidData liquid_status;
LiquidData* liquid_ptr = data ? data : &liquid_status;
- return (GetLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr) & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0;
+ return (GetLiquidStatus(phaseMask, x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr) & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0;
}
-bool Map::IsUnderWater(float x, float y, float z) const
+bool Map::IsUnderWater(uint32 phaseMask, float x, float y, float z) const
{
- return (GetLiquidStatus(x, y, z, MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN) & LIQUID_MAP_UNDER_WATER) != 0;
+ return (GetLiquidStatus(phaseMask, x, y, z, MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN) & LIQUID_MAP_UNDER_WATER) != 0;
}
bool Map::CheckGridIntegrity(Creature* c, bool moved) const