float TerrainInfo::GetHeight(float x, float y, float z, bool pUseVmaps, float maxSearchDist) const { // find raw .map surface under Z coordinates float mapHeight; float z2 = z + 2.f; if (GridMap *gmap = const_cast<TerrainInfo*>(this)->GetGrid(x, y)) { float _mapheight = gmap->getHeight(x,y); // look from a bit higher pos to find the floor, ignore under surface case if (z2 > _mapheight) mapHeight = _mapheight; else mapHeight = VMAP_INVALID_HEIGHT_VALUE; } else mapHeight = VMAP_INVALID_HEIGHT_VALUE; float vmapHeight; if (pUseVmaps) { VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); if (vmgr->isHeightCalcEnabled()) { // if mapHeight has been found search vmap height at least until mapHeight point // this prevent case when original Z "too high above ground and vmap height search fail" // this will not affect most normal cases (no map in instance, or stay at ground at continent) if (mapHeight > INVALID_HEIGHT && z2 - mapHeight > maxSearchDist) maxSearchDist = z2 - mapHeight + 1.0f; // 1.0 make sure that we not fail for case when map height near but above for vamp height // look from a bit higher pos to find the floor vmapHeight = vmgr->getHeight(GetMapId(), x, y, z2, maxSearchDist); } else vmapHeight = VMAP_INVALID_HEIGHT_VALUE; } else vmapHeight = VMAP_INVALID_HEIGHT_VALUE; // mapHeight set for any above raw ground Z or <= INVALID_HEIGHT // vmapheight set for any under Z value or <= INVALID_HEIGHT if (vmapHeight > INVALID_HEIGHT) { if (mapHeight > INVALID_HEIGHT) { // we have mapheight and vmapheight and must select more appropriate // we are already under the surface or vmap height above map heigt // or if the distance of the vmap height is less the land height distance if (z < mapHeight || vmapHeight > mapHeight || fabs(mapHeight-z) > fabs(vmapHeight-z)) return vmapHeight; else return mapHeight; // better use .map surface height } else return vmapHeight; // we have only vmapHeight (if have) } return mapHeight; }
void ConfusedMovementGenerator<T>::Initialize(T &unit) { const float wander_distance = 11; float x,y,z; x = unit.GetPositionX(); y = unit.GetPositionY(); z = unit.GetPositionZ(); Map const* map = unit.GetBaseMap(); i_nextMove = 1; bool is_water_ok, is_land_ok; _InitSpecific(unit, is_water_ok, is_land_ok); VMAP::IVMapManager *vMaps = VMAP::VMapFactory::createOrGetVMapManager(); for (uint8 idx = 0; idx <= MAX_CONF_WAYPOINTS; ++idx) { float wanderX = x + wander_distance*rand_norm() - wander_distance/2; float wanderY = y + wander_distance*rand_norm() - wander_distance/2; BlizzLike::NormalizeMapCoord(wanderX); BlizzLike::NormalizeMapCoord(wanderY); float new_z = map->GetHeight(wanderX, wanderY, z, true); if (new_z > INVALID_HEIGHT && unit.IsWithinLOS(wanderX, wanderY, new_z)) { // Don't move in water if we're not already in // Don't move on land if we're not already on it either bool is_water_now = map->IsInWater(x, y, z); bool is_water_next = map->IsInWater(wanderX, wanderY, new_z); if ((is_water_now && !is_water_next && !is_land_ok) || (!is_water_now && is_water_next && !is_water_ok)) { i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x; // Back to previous location i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y; i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx-1][2] : z; continue; } i_waypoints[idx][0] = wanderX; i_waypoints[idx][1] = wanderY; i_waypoints[idx][2] = new_z; // prevent falling down over an edge and check vmap if possible if (z > i_waypoints[idx][2] + 3.0f || (vMaps && !vMaps->isInLineOfSight(map->GetId(), x, y, z + 2.0f, i_waypoints[idx][0], i_waypoints[idx][1], i_waypoints[idx][2]))) { i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x; i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y; i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx-1][2] : z; } } else // Back to previous location { i_waypoints[idx][0] = idx > 0 ? i_waypoints[idx-1][0] : x; i_waypoints[idx][1] = idx > 0 ? i_waypoints[idx-1][1] : y; i_waypoints[idx][2] = idx > 0 ? i_waypoints[idx-1][2] : z; continue; } } unit.SetUInt64Value(UNIT_FIELD_TARGET, 0); unit.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); unit.CastStop(); unit.StopMoving(); unit.RemoveUnitMovementFlag(MOVEFLAG_WALK_MODE); unit.addUnitState(UNIT_STAT_CONFUSED); }
GridMapLiquidStatus TerrainInfo::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, GridMapLiquidData* data) const { GridMapLiquidStatus result = LIQUID_MAP_NO_WATER; VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); float liquid_level = INVALID_HEIGHT_VALUE; float ground_level = INVALID_HEIGHT_VALUE; uint32 liquid_type = 0; ground_level = GetHeightStatic(x,y,z,true,DEFAULT_WATER_SEARCH); if (vmgr->GetLiquidLevel(GetMapId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type)) { // DEBUG_LOG("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) { // All ok in water -> store data if (data) { // hardcoded in client like this if (GetMapId() == 530 && liquid_type == 2) liquid_type = 15; uint32 liquidFlagType = 0; if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(liquid_type)) liquidFlagType = liq->Type; if (liquid_type && liquid_type < 21) { if (AreaTableEntry const* area = GetAreaEntryByAreaFlagAndMap(GetAreaFlag(x, y, z), GetMapId())) { uint32 overrideLiquid = area->LiquidTypeOverride[liquidFlagType]; if (!overrideLiquid && area->zone) { area = GetAreaEntryByAreaID(area->zone); if (area) overrideLiquid = area->LiquidTypeOverride[liquidFlagType]; } if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid)) { liquid_type = overrideLiquid; liquidFlagType = liq->Type; } } } data->level = liquid_level; data->depth_level = ground_level; data->entry = liquid_type; data->type_flags = 1 << liquidFlagType; } // For speed check as int values int delta = int((liquid_level - z) * 10); // Get position delta if (delta > 20) // Under water return LIQUID_MAP_UNDER_WATER; if (delta > 0) // In water return LIQUID_MAP_IN_WATER; if (delta > -1) // Walk on water return LIQUID_MAP_WATER_WALK; result = LIQUID_MAP_ABOVE_WATER; } } else if (GridMap* gmap = const_cast<TerrainInfo*>(this)->GetGrid(x, y)) { GridMapLiquidData map_data; GridMapLiquidStatus 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)) { if (data) { // hardcoded in client like this if (GetMapId() == 530 && map_data.entry == 2) map_data.entry = 15; *data = map_data; } return map_result; } } return result; }
bool TerrainHolder::InLineOfSight(float x, float y, float z, float x2, float y2, float z2) { VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); return vmgr->isInLineOfSight(m_mapid, x, y, z, x2, y2, z2); }