bool UTIL_ASW_BrushBlockingRoute( AI_Waypoint_t *pRoute, const int nCollisionMask, const int nCollisionGroup ) { if ( !pRoute ) return false; AI_Waypoint_t *pLastPoint = pRoute; pRoute = pRoute->GetNext(); trace_t tr; Vector vecShiftUp = Vector( 0, 0, 20 ); while ( pRoute ) { CTraceFilterSimple traceFilter( NULL, nCollisionGroup ); UTIL_TraceLine( pLastPoint->GetPos() + vecShiftUp, pRoute->GetPos() + vecShiftUp, nCollisionMask, &traceFilter, &tr ); if ( asw_blink_debug.GetBool() ) { DebugDrawLine( pLastPoint->GetPos() + vecShiftUp, pRoute->GetPos() + vecShiftUp, 255, 0, 0, true, 30.0f ); } if ( tr.DidHit() ) { return true; } pLastPoint = pRoute; pRoute = pRoute->GetNext(); } return false; }
// traces along an AI network route to see if a door is blocking the way CASW_Door* UTIL_ASW_DoorBlockingRoute( AI_Waypoint_t *pRoute, bool bRequireLockedOrSealed ) { if ( !pRoute ) return NULL; AI_Waypoint_t *pLastPoint = pRoute; pRoute = pRoute->GetNext(); trace_t tr; Vector vecShiftUp = Vector( 0, 0, 20 ); while ( pRoute ) { CASW_Trace_Filter_Doors traceFilter( NULL, COLLISION_GROUP_NONE, bRequireLockedOrSealed ); UTIL_TraceLine( pLastPoint->GetPos() + vecShiftUp, pRoute->GetPos() + vecShiftUp, MASK_NPCSOLID, &traceFilter, &tr ); if ( asw_blink_debug.GetBool() ) { DebugDrawLine( pLastPoint->GetPos() + vecShiftUp, pRoute->GetPos() + vecShiftUp, 0, 0, 255, true, 30.0f ); } if ( tr.DidHit() ) { return dynamic_cast<CASW_Door*>(tr.m_pEnt); } pLastPoint = pRoute; pRoute = pRoute->GetNext(); } return NULL; }
int CASW_Marine_Hint_Manager::FindHints(const Vector &position, CASW_Marine *pLeader, const float flMinDistance, const float flMaxDistance, CUtlVector<HintData_t *> &result) { VPROF_BUDGET("CASW_Marine_Hint_Manager::FindHints", "SquadFormation"); Assert(pLeader); const float flMinDistSqr = Square(flMinDistance); const float flMaxDistSqr = Square(flMaxDistance); int nCount = m_Hints.Count(); for ( int i = 0; i < nCount; i++ ) { HintData_t *pHint = m_Hints[i]; float flDistSqr = position.DistToSqr(pHint->m_vecPosition); if (flDistSqr < flMinDistSqr || flDistSqr > flMaxDistSqr) { continue; } AI_Waypoint_t *pPath = pLeader->GetPathfinder()->BuildRoute(position, pHint->m_vecPosition, NULL, 0, NAV_GROUND, bits_BUILD_NO_LOCAL_NAV); if (!pPath) { continue; } pHint->m_flDistance = position.DistTo(pPath->GetPos()); AI_Waypoint_t *pCur = pPath; while (pCur->GetNext()) { AI_Waypoint_t *pNext = pCur->GetNext(); pHint->m_flDistance += pCur->GetPos().DistTo(pNext->GetPos()); pCur = pNext; } DeleteAll(pPath); if (pHint->m_flDistance > flMaxDistance) { continue; } result.AddToTail( pHint ); } return result.Count(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CAI_LeadBehavior::GetClosestPointOnRoute( const Vector &targetPos, Vector *pVecClosestPoint ) { AI_Waypoint_t *waypoint = GetOuter()->GetNavigator()->GetPath()->GetCurWaypoint(); AI_Waypoint_t *builtwaypoints = NULL; if ( !waypoint ) { // We arrive here twice when lead behaviour starts: // - When the lead behaviour is first enabled. We have no schedule. We want to know if the player is ahead of us. // - A frame later when we've chosen to lead the player, but we still haven't built our route. We know that the // the player isn't lagging, so it's safe to go ahead and simply say he's ahead of us. This avoids building // the temp route twice. if ( IsCurSchedule( SCHED_LEAD_PLAYER, false ) ) return true; // Build a temp route to the gold and use that builtwaypoints = GetOuter()->GetPathfinder()->BuildRoute( GetOuter()->GetAbsOrigin(), m_goal, NULL, GetOuter()->GetDefaultNavGoalTolerance(), GetOuter()->GetNavType(), true ); if ( !builtwaypoints ) return false; GetOuter()->GetPathfinder()->UnlockRouteNodes( builtwaypoints ); waypoint = builtwaypoints; } // Find the nearest node to the target (going forward) float flNearestDist2D = 999999999; float flNearestDist = 999999999; float flPathDist, flPathDist2D; Vector vecNearestPoint(0, 0, 0); Vector vecPrevPos = GetOuter()->GetAbsOrigin(); for ( ; (waypoint != NULL) ; waypoint = waypoint->GetNext() ) { // Find the closest point on the line segment on the path Vector vecClosest; CalcClosestPointOnLineSegment( targetPos, vecPrevPos, waypoint->GetPos(), vecClosest ); /* if ( builtwaypoints ) { NDebugOverlay::Line( vecPrevPos, waypoint->GetPos(), 0,0,255,true, 10.0 ); } */ vecPrevPos = waypoint->GetPos(); // Find the distance between this test point and our goal point flPathDist2D = vecClosest.AsVector2D().DistToSqr( targetPos.AsVector2D() ); if ( flPathDist2D > flNearestDist2D ) continue; flPathDist = vecClosest.z - targetPos.z; flPathDist *= flPathDist; flPathDist += flPathDist2D; if (( flPathDist2D == flNearestDist2D ) && ( flPathDist >= flNearestDist )) continue; flNearestDist2D = flPathDist2D; flNearestDist = flPathDist; vecNearestPoint = vecClosest; } if ( builtwaypoints ) { //NDebugOverlay::Line( vecNearestPoint, targetPos, 0,255,0,true, 10.0 ); DeleteAll( builtwaypoints ); } *pVecClosestPoint = vecNearestPoint; return true; }
bool CASW_Weapon_Blink::SetBlinkDestination() { CASW_Player *pPlayer = GetCommander(); if ( !pPlayer ) return false; CASW_Marine *pMarine = GetMarine(); if ( !pMarine ) return false; Vector vecStart = pPlayer->GetCrosshairTracePos() + Vector( 0, 0, 30 ); Vector vecEnd = pPlayer->GetCrosshairTracePos() - Vector( 0, 0, 30 ); trace_t tr; UTIL_TraceHull( vecStart, vecEnd, pMarine->WorldAlignMins(), pMarine->WorldAlignMaxs(), MASK_PLAYERSOLID_BRUSHONLY, pMarine, COLLISION_GROUP_PLAYER_MOVEMENT, &tr ); if ( tr.startsolid || tr.allsolid ) { m_vecInvalidDestination = vecStart; return false; } if ( pMarine->GetAbsOrigin().DistTo( tr.endpos ) > asw_blink_range.GetFloat() ) { m_vecInvalidDestination = tr.endpos; return false; } Vector vecDest = tr.endpos; // now see if we can build an AI path from the marine to this spot bool bValidRoute = false; if ( !pMarine->GetPathfinder() ) { m_vecInvalidDestination = vecDest; return false; } AI_Waypoint_t *pRoute = pMarine->GetPathfinder()->BuildRoute( pMarine->GetAbsOrigin(), vecDest, NULL, 30, NAV_GROUND, bits_BUILD_GROUND | bits_BUILD_IGNORE_NPCS ); if ( pRoute && !UTIL_ASW_DoorBlockingRoute( pRoute, true ) ) { if ( !UTIL_ASW_BrushBlockingRoute( pRoute, MASK_PLAYERSOLID_BRUSHONLY, COLLISION_GROUP_PLAYER_MOVEMENT ) ) { // if end node of the route is too Z different, then abort, to stop people jumping on top of walls AI_Waypoint_t *pLast = pRoute->GetLast(); if ( pLast ) { AI_Waypoint_t *pNode = pLast->GetPrev(); if ( !pNode || fabs( pNode->GetPos().z - pLast->GetPos().z ) < 80.0f ) { bValidRoute = true; } } } } if ( !bValidRoute ) { // find the closest node to the dest and try to path there instead CAI_Network *pNetwork = pMarine->GetNavigator() ? pMarine->GetNavigator()->GetNetwork() : NULL; if ( pNetwork ) { int nNode = pNetwork->NearestNodeToPoint( vecDest, false ); if ( nNode != NO_NODE ) { CAI_Node *pNode = pNetwork->GetNode( nNode ); if ( pNode && pNode->GetType() == NODE_GROUND ) { vecDest = pNode->GetOrigin(); if ( pRoute ) { ASWPathUtils()->DeleteRoute( pRoute ); pRoute = NULL; } pRoute = pMarine->GetPathfinder()->BuildRoute( pMarine->GetAbsOrigin(), vecDest, NULL, 30, NAV_GROUND, bits_BUILD_GROUND | bits_BUILD_IGNORE_NPCS ); if ( pRoute && !UTIL_ASW_DoorBlockingRoute( pRoute, true ) ) { if ( !UTIL_ASW_BrushBlockingRoute( pRoute, MASK_PLAYERSOLID_BRUSHONLY, COLLISION_GROUP_PLAYER_MOVEMENT ) ) { bValidRoute = true; } } if ( !bValidRoute ) { m_vecInvalidDestination = vecDest; } } } } } if ( !bValidRoute ) { if ( pRoute ) { ASWPathUtils()->DeleteRoute( pRoute ); pRoute = NULL; } return false; } if ( asw_blink_debug.GetBool() ) { ASWPathUtils()->DebugDrawRoute( pMarine->GetAbsOrigin(), pRoute ); } m_vecAbilityDestination = vecDest; if ( pRoute ) { ASWPathUtils()->DeleteRoute( pRoute ); pRoute = NULL; } return true; }