Exemplo n.º 1
0
float CAI_PlaneSolver::CalcProbeDist( float speed )	
{ 
	// one second or one hull
	float result = GetLookaheadTime() * speed;
	if ( result < m_pNpc->GetMoveProbe()->GetHullWidth() )
		return m_pNpc->GetMoveProbe()->GetHullWidth();
	if ( result > MAX_PROBE_DIST[AIStrongOpt()] )
		return MAX_PROBE_DIST[AIStrongOpt()];
	return result;
}
Exemplo n.º 2
0
CAI_PlaneSolver::CAI_PlaneSolver( CAI_BaseNPC *pNpc ) 
 :	m_pNpc( pNpc ),
	m_fSolvedPrev( false ),
	m_PrevTarget( FLT_MAX, FLT_MAX, FLT_MAX ),
	m_PrevSolution( 0 ),
	m_ClosestHaveBeenToCurrent( FLT_MAX ),
	m_TimeLastProgress( FLT_MAX ),
	m_fCannotSolveCurrent( false ),
	m_RefreshSamplesTimer( PLANE_SOLVER_THINK_FREQUENCY[AIStrongOpt()] - 0.05 )
{
}
Exemplo n.º 3
0
bool CAI_LocalNavigator::MoveCalcDirect( AILocalMoveGoal_t *pMoveGoal, bool bOnlyCurThink, float *pDistClear, AIMoveResult_t *pResult )
{
	AI_PROFILE_SCOPE(CAI_LocalNavigator_MoveCalcDirect);

	bool bRetVal = false;
	
	if ( pMoveGoal->speed )
	{
		CAI_Motor *pMotor = GetOuter()->GetMotor();
		float  minCheckDist = pMotor->MinCheckDist();
		float  probeDist	= m_pPlaneSolver->CalcProbeDist( pMoveGoal->speed ); // having this match steering allows one fewer traces
		float  checkDist	= MAX( minCheckDist, probeDist );
		float  checkStepDist = MAX( 16.0, probeDist * 0.5 );

		if ( pMoveGoal->flags & ( AILMG_TARGET_IS_TRANSITION | AILMG_TARGET_IS_GOAL ) )
		{
			// clamp checkDist to be no farther than MAX distance to goal
			checkDist = MIN( checkDist, pMoveGoal->maxDist );
		}

		if ( checkDist <= 0.0 )
		{
			*pResult = AIMR_OK;
			return true;
		}

		float moveThisInterval = pMotor->CalcIntervalMove();
		bool bExpectingArrival = (moveThisInterval >= checkDist);

		if ( !m_FullDirectTimer.Expired() )
		{
			if ( !m_fLastWasClear || 
				 ( !VectorsAreEqual(pMoveGoal->target, m_LastMoveGoal.target, 0.1) || 
				   !VectorsAreEqual(pMoveGoal->dir, m_LastMoveGoal.dir, 0.1) ) ||
				 bExpectingArrival )
			{
				m_FullDirectTimer.Force();
			}
		}

		if ( bOnlyCurThink ) // Outer code claims to have done a validation (probably a simplify operation)
		{
			m_FullDirectTimer.Set( TIME_DELAY_FULL_DIRECT_PROBE[AIStrongOpt()] );
		}

		// First, check the probable move for this cycle
		bool bTraceClear = true;
		Vector testPos;

		if ( !bExpectingArrival )
		{
			testPos = GetLocalOrigin() + pMoveGoal->dir * moveThisInterval;
			bTraceClear = GetMoveProbe()->MoveLimit( pMoveGoal->navType, GetLocalOrigin(), testPos, 
													 GetOuter()->GetAITraceMask(), pMoveGoal->pMoveTarget, 
													 100.0, 
													 ( pMoveGoal->navType == NAV_GROUND ) ? AIMLF_2D : AIMLF_DEFAULT, 
													 &pMoveGoal->directTrace );

			if ( !bTraceClear )
			{
				// Adjust probe top match expected probe dist (relied on later in process)
				pMoveGoal->directTrace.flDistObstructed = (checkDist - moveThisInterval) + pMoveGoal->directTrace.flDistObstructed;

			}

			if ( !IsRetail() && ai_debug_directnavprobe.GetBool() )
			{
				if ( !bTraceClear )
				{
					DevMsg( GetOuter(), "Close obstruction %f\n", checkDist - pMoveGoal->directTrace.flDistObstructed );
					NDebugOverlay::Line( WorldSpaceCenter(), Vector( testPos.x, testPos.y, WorldSpaceCenter().z ), 255, 0, 0, false, 0.1 );
					if ( pMoveGoal->directTrace.pObstruction )
						NDebugOverlay::Line( WorldSpaceCenter(), pMoveGoal->directTrace.pObstruction->WorldSpaceCenter(), 255, 0, 255, false, 0.1 );

				}
				else
				{
					NDebugOverlay::Line( WorldSpaceCenter(), Vector( testPos.x, testPos.y, WorldSpaceCenter().z ), 0, 255, 0, false, 0.1 );
				}
			}

			pMoveGoal->thinkTrace = pMoveGoal->directTrace;
		}

		// Now project out for future obstructions
		if ( bTraceClear )
		{
			if ( m_FullDirectTimer.Expired() )
			{
				testPos = GetLocalOrigin() + pMoveGoal->dir * checkDist;
				float checkStepPct = (checkStepDist / checkDist) * 100.0;
				if ( checkStepPct > 100.0 )
					checkStepPct = 100.0;
				
				bTraceClear = GetMoveProbe()->MoveLimit( pMoveGoal->navType, GetLocalOrigin(), testPos, 
														 GetOuter()->GetAITraceMask(), pMoveGoal->pMoveTarget, 
														 checkStepPct, 
														 ( pMoveGoal->navType == NAV_GROUND ) ? AIMLF_2D : AIMLF_DEFAULT, 
														 &pMoveGoal->directTrace );
				if ( bExpectingArrival )
					pMoveGoal->thinkTrace = pMoveGoal->directTrace;

				if (ai_debug_directnavprobe.GetBool() )
				{
					if ( !bTraceClear )
					{
						NDebugOverlay::Line( GetOuter()->EyePosition(), Vector( testPos.x, testPos.y, GetOuter()->EyePosition().z ), 255, 0, 0, false, 0.1 );
						DevMsg( GetOuter(), "Obstruction %f\n", checkDist - pMoveGoal->directTrace.flDistObstructed );
					}
					else
					{
						NDebugOverlay::Line( GetOuter()->EyePosition(), Vector( testPos.x, testPos.y, GetOuter()->EyePosition().z ), 0, 255, 0, false, 0.1 );
						DevMsg( GetOuter(), "No obstruction\n" );
					}
				}
			}
			else
			{
				if ( ai_debug_directnavprobe.GetBool() )
					DevMsg( GetOuter(), "No obstruction (Near probe only)\n" );
			}
		}

		pMoveGoal->bHasTraced = true;
	
		float distClear = checkDist - pMoveGoal->directTrace.flDistObstructed;
		if (distClear < 0.001)
			distClear = 0;
		
		if ( bTraceClear )
		{
			*pResult = AIMR_OK;
			bRetVal = true;
			m_fLastWasClear = true;
		}
		else if ( ( pMoveGoal->flags & ( AILMG_TARGET_IS_TRANSITION | AILMG_TARGET_IS_GOAL ) ) && 
			 pMoveGoal->maxDist < distClear )
		{
			*pResult = AIMR_OK;
			bRetVal = true;
			m_fLastWasClear = true;
		}
		else
		{
			*pDistClear = distClear;
			m_fLastWasClear = false;
		}
	}
	else
	{
		// Should never end up in this function with speed of zero. Probably an activity problem.
		*pResult = AIMR_ILLEGAL;
		bRetVal = true;
	}

	m_LastMoveGoal = *pMoveGoal;
	if ( bRetVal && m_FullDirectTimer.Expired() )
		m_FullDirectTimer.Set( TIME_DELAY_FULL_DIRECT_PROBE[AIStrongOpt()] );

	return bRetVal;
}
Exemplo n.º 4
0
AI_SuggestorResult_t CAI_PlaneSolver::GenerateObstacleSuggestions( const AILocalMoveGoal_t &goal, const AIMoveTrace_t &directTrace, 
																   float distClear, float probeDist, float degreesToProbe, int nProbes )
{
	Assert( nProbes % 2 == 1 );
	
	PLANESOLVER_PROFILE_SCOPE( CAI_PlaneSolver_GenerateObstacleSuggestions );
	
	AI_SuggestorResult_t seekResult = SR_NONE;
	bool				 fNewTarget = ( !m_fSolvedPrev || m_PrevTarget != goal.target );
	
	if ( fNewTarget )
		m_RefreshSamplesTimer.Force();

	if ( PLANE_SOLVER_THINK_FREQUENCY[AIStrongOpt()] == 0.0 || m_RefreshSamplesTimer.Expired() )
	{
		m_Solver.ClearRegulations();
	
		if ( !ProbeForNpcs() )
			GenerateObstacleNpcs( goal, probeDist );
			
		if ( GenerateCircleObstacleSuggestions( goal, probeDist ) )
			seekResult = SR_OK;
		
		float spanPerProbe = degreesToProbe / nProbes;
		int   nSideProbes  = (nProbes - 1) / 2;
		float yawGoalDir   = UTIL_VecToYaw( goal.dir );
		
		Vector 		  probeTarget;
		AIMoveTrace_t moveTrace;
		int			  i;
		
		// Generate suggestion from direct trace, or probe if direct trace doesn't match
		if ( fabs( probeDist - ( distClear + directTrace.flDistObstructed ) ) < 0.1 && 
			 ( ProbeForNpcs() || directTrace.fStatus != AIMR_BLOCKED_NPC ) )
		{
			if ( directTrace.fStatus != AIMR_OK )
			{
				seekResult = SR_OK;
				GenerateSuggestionFromTrace( goal, directTrace, probeDist, yawGoalDir, spanPerProbe, 0 );
			}
		}
		else if ( GenerateObstacleSuggestion( goal, yawGoalDir, probeDist, spanPerProbe, 0 ) == SR_OK )
		{
			seekResult = SR_OK;
		}
		
		// Scan left. Note that in the left and right scan, the algorithm stops as soon
		// as there is a clear path. This is an optimization in anticipation of the
		// behavior of the underlying solver. This will break more often the higher
		// PLANE_SOLVER_THINK_FREQUENCY becomes
		bool foundClear = false;

		for ( i = 1; i <= nSideProbes; i++ )
		{
			if ( !foundClear )
			{
				AI_SuggestorResult_t curSeekResult = GenerateObstacleSuggestion( goal, yawGoalDir, probeDist, 
																				 spanPerProbe, i );
				if ( curSeekResult == SR_OK )
				{
					seekResult = SR_OK;
				}
				else
					foundClear = true;
			}
			else
			{
				float ignored;
				float arcCenter;
				CalcYawsFromOffset( yawGoalDir, spanPerProbe, i, &ignored, &arcCenter );
				m_Solver.AddRegulation( AI_MoveSuggestion_t( AIMST_NO_KNOWLEDGE, 1, arcCenter, spanPerProbe ) );
			}
		}

		// Scan right
		foundClear = false;

		for ( i = -1; i >= -nSideProbes; i-- )
		{
			if ( !foundClear )
			{
				AI_SuggestorResult_t curSeekResult = GenerateObstacleSuggestion( goal, yawGoalDir, probeDist, 
																				 spanPerProbe, i );
				if ( curSeekResult == SR_OK )
				{
					seekResult = SR_OK;
				}
				else
					foundClear = true;
			}
			else
			{
				float ignored;
				float arcCenter;
				CalcYawsFromOffset( yawGoalDir, spanPerProbe, i, &ignored, &arcCenter );
				m_Solver.AddRegulation( AI_MoveSuggestion_t( AIMST_NO_KNOWLEDGE, 1, arcCenter, spanPerProbe ) );
			}
		}

		if ( seekResult == SR_OK )
		{
			float arcCenter = yawGoalDir - 180;
			if ( arcCenter < 0 )
				arcCenter += 360;
				
			// Since these are not sampled every think, place a negative arc in all directions not sampled
			m_Solver.AddRegulation( AI_MoveSuggestion_t( AIMST_NO_KNOWLEDGE, 1, arcCenter, 360 - degreesToProbe ) );

		}

		m_RefreshSamplesTimer.Reset( PLANE_SOLVER_THINK_FREQUENCY[AIStrongOpt()] );
	}
	else if ( m_Solver.HaveRegulations() )
		seekResult = SR_OK;

	return seekResult;
}
Exemplo n.º 5
0
#include "cbase.h"

#include "ai_localnavigator.h"

#include "ai_basenpc.h"
#include "ai_planesolver.h"
#include "ai_moveprobe.h"
#include "ai_motor.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

ConVar ai_debug_directnavprobe("ai_debug_directnavprobe", "0");

const float TIME_DELAY_FULL_DIRECT_PROBE = ( !AIStrongOpt() ) ? 0.25 : 0.35;

//-----------------------------------------------------------------------------

BEGIN_SIMPLE_DATADESC(CAI_LocalNavigator)
	//						m_fLastWasClear	(not saved)
	//						m_LastMoveGoal	(not saved)
	//						m_FullDirectTimer	(not saved)
	//						m_pPlaneSolver	(not saved)
	//						m_pMoveProbe	(not saved)
END_DATADESC();

//-------------------------------------

CAI_LocalNavigator::CAI_LocalNavigator(CAI_BaseNPC *pOuter) : CAI_Component( pOuter ) 
{