Get zone/area IDs from vmap data in the liquid update

* Add new method Map::getFullVMapDataForPosition to get area info and liquid info in a single vmap lookup
* Use this lookup in Map:: relocation methods to update m_areaId and m_zoneId fields on WorldObject
* Adjust GetZoneId/GetAreaId on WorldObject to always return these cached fields
* Clean up liquid state handling on Unit and Player
* Hand floor's Z coord up through GetFullTerrainStatusForPosition, use it to update a new field in WorldObject, and use that to feed a new GetFloorZ call on WorldObject.
This commit is contained in:
Aokromes
2017-06-09 13:20:37 +02:00
parent c700779949
commit f8d9d954d1
17 changed files with 315 additions and 145 deletions

View File

@@ -988,6 +988,7 @@ void Map::PlayerRelocation(Player* player, float x, float y, float z, float orie
AddToGrid(player, new_cell);
}
player->UpdatePositionData();
player->UpdateObjectVisibility(false);
}
@@ -1022,6 +1023,7 @@ void Map::CreatureRelocation(Creature* creature, float x, float y, float z, floa
if (creature->IsVehicle())
creature->GetVehicleKit()->RelocatePassengers();
creature->UpdateObjectVisibility(false);
creature->UpdatePositionData();
RemoveCreatureFromMoveList(creature);
}
@@ -1052,6 +1054,7 @@ void Map::GameObjectRelocation(GameObject* go, float x, float y, float z, float
{
go->Relocate(x, y, z, orientation);
go->UpdateModelPosition();
go->UpdatePositionData();
go->UpdateObjectVisibility(false);
RemoveGameObjectFromMoveList(go);
}
@@ -1084,6 +1087,7 @@ void Map::DynamicObjectRelocation(DynamicObject* dynObj, float x, float y, float
else
{
dynObj->Relocate(x, y, z, orientation);
dynObj->UpdatePositionData();
dynObj->UpdateObjectVisibility(false);
RemoveDynamicObjectFromMoveList(dynObj);
}
@@ -1177,6 +1181,7 @@ void Map::MoveAllCreaturesInMoveList()
if (c->IsVehicle())
c->GetVehicleKit()->RelocatePassengers();
//CreatureRelocationNotify(c, new_cell, new_cell.cellCoord());
c->UpdatePositionData();
c->UpdateObjectVisibility(false);
}
else
@@ -1231,6 +1236,7 @@ void Map::MoveAllGameObjectsInMoveList()
// update pos
go->Relocate(go->_newPosition);
go->UpdateModelPosition();
go->UpdatePositionData();
go->UpdateObjectVisibility(false);
}
else
@@ -1275,6 +1281,7 @@ void Map::MoveAllDynamicObjectsInMoveList()
{
// update pos
dynObj->Relocate(dynObj->_newPosition);
dynObj->UpdatePositionData();
dynObj->UpdateObjectVisibility(false);
}
else
@@ -1495,6 +1502,7 @@ bool Map::CreatureRespawnRelocation(Creature* c, bool diffGridOnly)
c->Relocate(resp_x, resp_y, resp_z, resp_o);
c->GetMotionMaster()->Initialize(); // prevent possible problems with default move generators
//CreatureRelocationNotify(c, resp_cell, resp_cell.GetCellCoord());
c->UpdatePositionData();
c->UpdateObjectVisibility(false);
return true;
}
@@ -1520,6 +1528,7 @@ bool Map::GameObjectRespawnRelocation(GameObject* go, bool diffGridOnly)
if (GameObjectCellRelocation(go, resp_cell))
{
go->Relocate(resp_x, resp_y, resp_z, resp_o);
go->UpdatePositionData();
go->UpdateObjectVisibility(false);
return true;
}
@@ -2123,7 +2132,7 @@ uint8 GridMap::getTerrainType(float x, float y) const
}
// Get water state on map
inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data)
inline ZLiquidStatus GridMap::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data)
{
// Check water type (if no water return)
if (!_liquidType && !_liquidFlags)
@@ -2392,11 +2401,6 @@ uint32 Map::GetAreaId(float x, float y, float z, bool *isOutdoors) const
return areaId;
}
uint32 Map::GetAreaId(float x, float y, float z) const
{
return GetAreaId(x, y, z, nullptr);
}
uint32 Map::GetZoneId(float x, float y, float z) const
{
uint32 areaId = GetAreaId(x, y, z);
@@ -2423,7 +2427,7 @@ uint8 Map::GetTerrainType(float x, float y) const
return 0;
}
ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data) const
ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data) const
{
ZLiquidStatus result = LIQUID_MAP_NO_WATER;
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
@@ -2432,7 +2436,7 @@ ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp
uint32 liquid_type = 0;
if (vmgr->GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type))
{
TC_LOG_DEBUG("maps", "getLiquidStatus(): vmap liquid level: %f ground: %f type: %u", liquid_level, ground_level, liquid_type);
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)
{
@@ -2490,7 +2494,7 @@ ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp
if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
{
LiquidData map_data;
ZLiquidStatus map_result = gmap->getLiquidStatus(x, y, z, ReqLiquidType, &map_data);
ZLiquidStatus map_result = gmap->GetLiquidStatus(x, y, z, ReqLiquidType, &map_data);
// Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER:
if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > ground_level))
{
@@ -2508,6 +2512,103 @@ 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) const
{
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
VMAP::AreaAndLiquidData vmapData;
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);
GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y);
float mapHeight = gmap->getHeight(x, y);
// area lookup
AreaTableEntry const* areaEntry = nullptr;
if (vmapData.areaInfo && (z + 2.0f <= mapHeight || mapHeight <= vmapData.floorZ))
if (WMOAreaTableEntry const* wmoEntry = GetWMOAreaTableEntryByTripple(vmapData.areaInfo->rootId, vmapData.areaInfo->adtId, vmapData.areaInfo->groupId))
areaEntry = sAreaTableStore.LookupEntry(wmoEntry->areaId);
if (areaEntry)
{
data.floorZ = vmapData.floorZ;
data.areaId = areaEntry->ID;
}
else
{
data.floorZ = mapHeight;
if (gmap)
data.areaId = gmap->getArea(x, y);
else
data.areaId = 0;
if (!data.areaId)
data.areaId = i_mapEntry->linked_zone;
if (data.areaId)
areaEntry = sAreaTableStore.LookupEntry(data.areaId);
}
// liquid processing
data.liquidStatus = LIQUID_MAP_NO_WATER;
if (vmapData.liquidInfo && vmapData.liquidInfo->level > vmapData.floorZ && z + 2.0f > vmapData.floorZ)
{
uint32 liquidType = vmapData.liquidInfo->type;
if (GetId() == 530 && liquidType == 2) // gotta love blizzard hacks
liquidType = 15;
uint32 liquidFlagType = 0;
if (LiquidTypeEntry const* liquidData = sLiquidTypeStore.LookupEntry(liquidType))
liquidFlagType = liquidData->Type;
if (liquidType && liquidType < 21 && areaEntry)
{
uint32 overrideLiquid = areaEntry->LiquidTypeOverride[liquidFlagType];
if (!overrideLiquid && areaEntry->zone)
{
AreaTableEntry const* zoneEntry = sAreaTableStore.LookupEntry(areaEntry->zone);
if (zoneEntry)
overrideLiquid = zoneEntry->LiquidTypeOverride[liquidFlagType];
}
if (LiquidTypeEntry const* overrideData = sLiquidTypeStore.LookupEntry(overrideLiquid))
{
liquidType = overrideLiquid;
liquidFlagType = overrideData->Type;
}
}
data.liquidInfo = boost::in_place();
data.liquidInfo->level = vmapData.liquidInfo->level;
data.liquidInfo->depth_level = vmapData.floorZ;
data.liquidInfo->entry = liquidType;
data.liquidInfo->type_flags = 1 << liquidFlagType;
float delta = vmapData.liquidInfo->level - z;
if (delta > 2.0f)
data.liquidStatus = LIQUID_MAP_UNDER_WATER;
else if (delta > 0.0f)
data.liquidStatus = LIQUID_MAP_IN_WATER;
else if (delta > -0.1f)
data.liquidStatus = LIQUID_MAP_WATER_WALK;
else
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))
{
LiquidData gridMapLiquid;
ZLiquidStatus gridMapStatus = gmap->GetLiquidStatus(x, y, z, reqLiquidType, &gridMapLiquid);
if (gridMapStatus != LIQUID_MAP_NO_WATER && (gridMapLiquid.level > vmapData.floorZ))
{
if (GetId() == 530 && gridMapLiquid.entry == 2)
gridMapLiquid.entry = 15;
data.liquidInfo = gridMapLiquid;
data.liquidStatus = gridMapStatus;
}
}
}
float Map::GetWaterLevel(float x, float y) const
{
if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
@@ -2545,12 +2646,12 @@ bool Map::IsInWater(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(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
{
return (getLiquidStatus(x, y, z, MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN) & LIQUID_MAP_UNDER_WATER) != 0;
return (GetLiquidStatus(x, y, z, MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN) & LIQUID_MAP_UNDER_WATER) != 0;
}
bool Map::CheckGridIntegrity(Creature* c, bool moved) const