//-------------------------------------------------------------------------------------------------------- void CFuncNavBlocker::UpdateBlocked() { NavAreaCollector collector( true ); Extent extent; extent.Init( this ); TheNavMesh->ForAllAreasOverlappingExtent( collector, extent ); for ( int i=0; i<collector.m_area.Count(); ++i ) { CNavArea *area = collector.m_area[i]; area->UpdateBlocked( true ); } }
//-------------------------------------------------------------------------------------------------------- // Reevaluate all func_nav_cost entities and update the nav decoration accordingly. // This is required to handle overlapping func_nav_cost entities. void CFuncNavCost::UpdateAllNavCostDecoration( void ) { int i, j; // first, clear all avoid decoration from the mesh for( i=0; i<TheNavAreas.Count(); ++i ) { TheNavAreas[i]->ClearAllNavCostEntities(); } // now, mark all areas with active cost entities overlapping them for( i=0; i<gm_masterCostVector.Count(); ++i ) { CFuncNavCost *cost = gm_masterCostVector[i]; if ( !cost || !cost->IsEnabled() ) { continue; } Extent extent; extent.Init( cost ); CUtlVector< CNavArea * > overlapVector; TheNavMesh->CollectAreasOverlappingExtent( extent, &overlapVector ); Ray_t ray; trace_t tr; ICollideable *pCollide = cost->CollisionProp(); for( j=0; j<overlapVector.Count(); ++j ) { ray.Init( overlapVector[j]->GetCenter(), overlapVector[j]->GetCenter() ); enginetrace->ClipRayToCollideable( ray, MASK_ALL, pCollide, &tr ); if ( tr.startsolid ) { overlapVector[j]->AddFuncNavCostEntity( cost ); } } } }
//-------------------------------------------------------------------------------------------------------- void CFuncNavBlocker::BlockNav( void ) { if ( m_blockedTeamNumber == TEAM_ANY ) { for ( int i=0; i<MAX_NAV_TEAMS; ++i ) { m_isBlockingNav[ i ] = true; } } else { int teamNumber = m_blockedTeamNumber % MAX_NAV_TEAMS; m_isBlockingNav[ teamNumber ] = true; } Extent extent; extent.Init( this ); TheNavMesh->ForAllAreasOverlappingExtent( *this, extent ); }
//----------------------------------------------------------------------------------------------------- int CFuncNavBlocker::DrawDebugTextOverlays( void ) { int offset = BaseClass::DrawDebugTextOverlays(); if (m_debugOverlays & OVERLAY_TEXT_BIT) { CFmtStr str; // FIRST_GAME_TEAM skips TEAM_SPECTATOR and TEAM_UNASSIGNED, so we can print // useful team names in a non-game-specific fashion. for ( int i=FIRST_GAME_TEAM; i<FIRST_GAME_TEAM + MAX_NAV_TEAMS; ++i ) { if ( IsBlockingNav( i ) ) { CTeam *team = GetGlobalTeam( i ); if ( team ) { EntityText( offset++, str.sprintf( "blocking team %s", team->GetName() ), 0 ); } else { EntityText( offset++, str.sprintf( "blocking team %d", i ), 0 ); } } } NavAreaCollector collector( true ); Extent extent; extent.Init( this ); TheNavMesh->ForAllAreasOverlappingExtent( collector, extent ); for ( int i=0; i<collector.m_area.Count(); ++i ) { CNavArea *area = collector.m_area[i]; Extent areaExtent; area->GetExtent( &areaExtent ); debugoverlay->AddBoxOverlay( vec3_origin, areaExtent.lo, areaExtent.hi, vec3_angle, 0, 255, 0, 10, NDEBUG_PERSIST_TILL_NEXT_SERVER ); } } return offset; }
UpgradeStationInfo(CUpgrades *station, CTFBot *actor, CNavArea *start_area, CTFBotPathCost& cost_func) : station(station) { Extent extent; extent.Init(station); CUtlVector<CTFNavArea *> overlapping; TheNavMesh->CollectAreasOverlappingExtent(extent, &overlapping); FOR_EACH_VEC(overlapping, i) { auto area = overlapping[i]; Extent ext_nav; area->GetExtent(&ext_nav); constexpr float bloat = 0.0f; Vector bloat_mins(-bloat, -bloat, -bloat); Vector bloat_maxs( bloat, bloat, bloat); Extent ext_vol = ext_nav; ext_vol.lo += (VEC_HULL_MIN_SCALED(actor) + bloat_mins); ext_vol.hi += (VEC_HULL_MAX_SCALED(actor) + bloat_maxs); Vector center = (ext_vol.hi + ext_vol.lo) * 0.5f; Vector mins = -(ext_vol.hi - center); Vector maxs = (ext_vol.hi - center); Ray_t ray; ray.Init(center, center, mins, maxs); trace_t tr; enginetrace->ClipRayToEntity(ray, CONTENTS_SOLID, reinterpret_cast<IHandleEntity *>(station), &tr); if ((tr.contents & CONTENTS_SOLID) == 0) continue; constexpr float unit_size = 25.0f; int units_x = (int)(ext_nav.SizeX() / unit_size); int units_y = (int)(ext_nav.SizeY() / unit_size); std::vector<Vector> spots_edges; std::vector<Vector> spots_middle; for (int i = 0; i <= units_x; ++i) { for (int j = 0; j <= units_y; ++j) { float x = i * (ext_nav.SizeX() / units_x); float y = j * (ext_nav.SizeY() / units_y); // TODO: use area->GetZ for this part float z = ext_nav.lo.z; if (i == 0 || j == 0 || i == units_x || j == units_y) { spots_edges.emplace_back(ext_nav.lo.x + x, ext_nav.lo.y + y, z); } else { spots_middle.emplace_back(ext_nav.lo.x + x, ext_nav.lo.y + y, z); } } } std::random_shuffle(spots_edges.begin(), spots_edges.end()); std::random_shuffle(spots_middle.begin(), spots_middle.end()); #if 0 int idx = 0; for (const auto& spot : spots_edges) { bool would_touch = WouldPlayerAtLocationTouchTrigger(spot, actor, station); NDebugOverlay::Box(spot, Vector(-1.0f, -1.0f, -1.0f), Vector(1.0f, 1.0f, 1.0f), (would_touch ? 0x00 : 0xff), (would_touch ? 0xff : 0x00), 0x00, 0xff, 60.0f); ++idx; } idx = 0; for (const auto& spot : spots_middle) { bool would_touch = WouldPlayerAtLocationTouchTrigger(spot, actor, station); NDebugOverlay::Box(spot, Vector(-1.0f, -1.0f, -1.0f), Vector(1.0f, 1.0f, 1.0f), (would_touch ? 0x00 : 0xff), (would_touch ? 0xff : 0x00), 0x00, 0xff, 60.0f); ++idx; } #endif bool found_spot = false; for (const auto& spot : spots_edges) { if (found_spot) break; if (WouldPlayerAtLocationTouchTrigger(spot, actor, station)) { // NDebugOverlay::Box(spot, Vector(-2.0f, -2.0f, -2.0f), Vector(2.0f, 2.0f, 2.0f), 0x00, 0xff, 0x00, 0xff, 3600.0f); this->spots.emplace_back(area, spot); found_spot = true; } } for (const auto& spot : spots_middle) { if (found_spot) break; if (WouldPlayerAtLocationTouchTrigger(spot, actor, station)) { // NDebugOverlay::Box(spot, Vector(-2.0f, -2.0f, -2.0f), Vector(2.0f, 2.0f, 2.0f), 0xff, 0x00, 0x00, 0xff, 3600.0f); this->spots.emplace_back(area, spot); found_spot = true; } } if (found_spot) { NDebugOverlay::Box(ext_nav.lo, vec3_origin, (ext_nav.hi - ext_nav.lo), 0xff, 0xff, 0xff, 0x80, 60.0f); } }