aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server/ai_localnavigator.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/server/ai_localnavigator.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/server/ai_localnavigator.cpp')
-rw-r--r--mp/src/game/server/ai_localnavigator.cpp896
1 files changed, 448 insertions, 448 deletions
diff --git a/mp/src/game/server/ai_localnavigator.cpp b/mp/src/game/server/ai_localnavigator.cpp
index e3e19625..48f8f9b9 100644
--- a/mp/src/game/server/ai_localnavigator.cpp
+++ b/mp/src/game/server/ai_localnavigator.cpp
@@ -1,448 +1,448 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================//
-
-#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[2] = { 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 )
-{
- m_pMoveProbe = NULL;
- m_pPlaneSolver = new CAI_PlaneSolver( pOuter );
-
- m_fLastWasClear = false;
- memset( &m_LastMoveGoal, 0, sizeof(m_LastMoveGoal) );
-}
-
-//-------------------------------------
-
-CAI_LocalNavigator::~CAI_LocalNavigator()
-{
- delete m_pPlaneSolver;
-}
-
-//-------------------------------------
-
-void CAI_LocalNavigator::Init( IAI_MovementSink *pMovementServices )
-{
- CAI_ProxyMovementSink::Init( pMovementServices );
- m_pMoveProbe = GetOuter()->GetMoveProbe(); // @TODO (toml 03-30-03): this is a "bad" way to grab this pointer. Components should have an explcit "init" phase.
-}
-
-//-------------------------------------
-
-void CAI_LocalNavigator::ResetMoveCalculations()
-{
- m_FullDirectTimer.Force();
- m_pPlaneSolver->Reset();
-}
-
-//-------------------------------------
-
-void CAI_LocalNavigator::AddObstacle( const Vector &pos, float radius, AI_MoveSuggType_t type )
-{
- m_pPlaneSolver->AddObstacle( pos, radius, NULL, type );
-}
-
-//-------------------------------------
-
-bool CAI_LocalNavigator::HaveObstacles()
-{
- return m_pPlaneSolver->HaveObstacles();
-}
-
-//-------------------------------------
-
-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,
- MASK_NPCSOLID, 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,
- MASK_NPCSOLID, 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;
-}
-
-//-------------------------------------
-
-ConVar ai_no_steer( "ai_no_steer", "0" );
-
-bool CAI_LocalNavigator::MoveCalcSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult )
-{
- if ( (pMoveGoal->flags & AILMG_NO_STEER) )
- return false;
-
- if ( ai_no_steer.GetBool() )
- return false;
-
- if ( GetOuter()->IsFlaggedEfficient() )
- return false;
-
- AI_PROFILE_SCOPE(CAI_Motor_MoveCalcSteer);
- Vector moveSolution;
- if ( m_pPlaneSolver->Solve( *pMoveGoal, distClear, &moveSolution ) )
- {
- if ( moveSolution != pMoveGoal->dir )
- {
- float dot = moveSolution.AsVector2D().Dot( pMoveGoal->dir.AsVector2D() );
-
- const float COS_HALF_30 = 0.966;
- if ( dot > COS_HALF_30 )
- {
- float probeDist = m_pPlaneSolver->CalcProbeDist( pMoveGoal->speed );
- if ( pMoveGoal->maxDist < probeDist * 0.33333 && distClear > probeDist * 0.6666)
- {
- // A waypoint is coming up, but there's probably time to steer
- // away after hitting it
- *pResult = AIMR_OK;
- return true;
- }
- }
-
- pMoveGoal->facing = pMoveGoal->dir = moveSolution;
- }
- *pResult = AIMR_OK;
- return true;
- }
-
- return false;
-}
-
-//-------------------------------------
-
-bool CAI_LocalNavigator::MoveCalcStop( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult )
-{
- if (distClear < pMoveGoal->maxDist)
- {
- if ( distClear < 0.1 )
- {
- DebugNoteMovementFailure();
- *pResult = AIMR_ILLEGAL;
- }
- else
- {
- pMoveGoal->maxDist = distClear;
- *pResult = AIMR_OK;
- }
-
- return true;
- }
- *pResult = AIMR_OK;
- return true;
-}
-
-//-------------------------------------
-
-#ifdef DEBUG
-#define SetSolveCookie() pMoveGoal->solveCookie = __LINE__;
-#else
-#define SetSolveCookie() ((void)0)
-#endif
-
-
-AIMoveResult_t CAI_LocalNavigator::MoveCalcRaw( AILocalMoveGoal_t *pMoveGoal, bool bOnlyCurThink )
-{
- AI_PROFILE_SCOPE(CAI_Motor_MoveCalc);
-
- AIMoveResult_t result = AIMR_OK; // Assume success
- AIMoveTrace_t directTrace;
- float distClear;
-
- // --------------------------------------------------
-
- bool bDirectClear = MoveCalcDirect( pMoveGoal, bOnlyCurThink, &distClear, &result);
- if ( OnCalcBaseMove( pMoveGoal, distClear, &result ) )
- {
- SetSolveCookie();
- return DbgResult( result );
- }
-
- bool bShouldSteer = ( !(pMoveGoal->flags & AILMG_NO_STEER) && ( !bDirectClear || HaveObstacles() ) );
-
- if ( bDirectClear && !bShouldSteer )
- {
- SetSolveCookie();
- return DbgResult( result );
- }
-
- // --------------------------------------------------
-
- if ( bShouldSteer )
- {
- if ( !bDirectClear )
- {
- if ( OnObstructionPreSteer( pMoveGoal, distClear, &result ) )
- {
- SetSolveCookie();
- return DbgResult( result );
- }
- }
-
- if ( MoveCalcSteer( pMoveGoal, distClear, &result ) )
- {
- SetSolveCookie();
- return DbgResult( result );
- }
- }
-
- if ( OnFailedSteer( pMoveGoal, distClear, &result ) )
- {
- SetSolveCookie();
- return DbgResult( result );
- }
-
- // --------------------------------------------------
-
- if ( OnFailedLocalNavigation( pMoveGoal, distClear, &result ) )
- {
- SetSolveCookie();
- return DbgResult( result );
- }
-
- if ( distClear < GetOuter()->GetMotor()->MinStoppingDist() )
- {
- if ( OnInsufficientStopDist( pMoveGoal, distClear, &result ) )
- {
- SetSolveCookie();
- return DbgResult( result );
- }
-
- if ( MoveCalcStop( pMoveGoal, distClear, &result) )
- {
- SetSolveCookie();
- return DbgResult( result );
- }
- }
-
- // A hopeful result... may get in trouble at next waypoint and obstruction is still there
- if ( distClear > pMoveGoal->curExpectedDist )
- {
- SetSolveCookie();
- return DbgResult( AIMR_OK );
- }
-
- // --------------------------------------------------
-
- DebugNoteMovementFailure();
- SetSolveCookie();
- return DbgResult( IsMoveBlocked( pMoveGoal->directTrace.fStatus ) ? pMoveGoal->directTrace.fStatus : AIMR_ILLEGAL );
-}
-
-//-------------------------------------
-
-AIMoveResult_t CAI_LocalNavigator::MoveCalc( AILocalMoveGoal_t *pMoveGoal, bool bPreviouslyValidated )
-{
- bool bOnlyCurThink = ( bPreviouslyValidated && !HaveObstacles() );
-
- AIMoveResult_t result = MoveCalcRaw( pMoveGoal, bOnlyCurThink );
-
- if ( pMoveGoal->curExpectedDist > pMoveGoal->maxDist )
- pMoveGoal->curExpectedDist = pMoveGoal->maxDist;
-
- // If success, try to dampen really fast turning movement
- if ( result == AIMR_OK)
- {
- float interval = GetOuter()->GetMotor()->GetMoveInterval();
- float currentYaw = UTIL_AngleMod( GetLocalAngles().y );
- float goalYaw;
- float deltaYaw;
- float speed;
- float clampedYaw;
-
- // Clamp yaw
- goalYaw = UTIL_VecToYaw( pMoveGoal->facing );
- deltaYaw = fabs( UTIL_AngleDiff( goalYaw, currentYaw ) );
- if ( deltaYaw > 15 )
- {
- speed = deltaYaw * 4.0; // i.e., any maneuver takes a quarter a second
- clampedYaw = AI_ClampYaw( speed, currentYaw, goalYaw, interval );
-
- if ( clampedYaw != goalYaw )
- {
- pMoveGoal->facing = UTIL_YawToVector( clampedYaw );
- }
- }
- }
-
- return result;
-}
-//-----------------------------------------------------------------------------
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#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[2] = { 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 )
+{
+ m_pMoveProbe = NULL;
+ m_pPlaneSolver = new CAI_PlaneSolver( pOuter );
+
+ m_fLastWasClear = false;
+ memset( &m_LastMoveGoal, 0, sizeof(m_LastMoveGoal) );
+}
+
+//-------------------------------------
+
+CAI_LocalNavigator::~CAI_LocalNavigator()
+{
+ delete m_pPlaneSolver;
+}
+
+//-------------------------------------
+
+void CAI_LocalNavigator::Init( IAI_MovementSink *pMovementServices )
+{
+ CAI_ProxyMovementSink::Init( pMovementServices );
+ m_pMoveProbe = GetOuter()->GetMoveProbe(); // @TODO (toml 03-30-03): this is a "bad" way to grab this pointer. Components should have an explcit "init" phase.
+}
+
+//-------------------------------------
+
+void CAI_LocalNavigator::ResetMoveCalculations()
+{
+ m_FullDirectTimer.Force();
+ m_pPlaneSolver->Reset();
+}
+
+//-------------------------------------
+
+void CAI_LocalNavigator::AddObstacle( const Vector &pos, float radius, AI_MoveSuggType_t type )
+{
+ m_pPlaneSolver->AddObstacle( pos, radius, NULL, type );
+}
+
+//-------------------------------------
+
+bool CAI_LocalNavigator::HaveObstacles()
+{
+ return m_pPlaneSolver->HaveObstacles();
+}
+
+//-------------------------------------
+
+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,
+ MASK_NPCSOLID, 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,
+ MASK_NPCSOLID, 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;
+}
+
+//-------------------------------------
+
+ConVar ai_no_steer( "ai_no_steer", "0" );
+
+bool CAI_LocalNavigator::MoveCalcSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult )
+{
+ if ( (pMoveGoal->flags & AILMG_NO_STEER) )
+ return false;
+
+ if ( ai_no_steer.GetBool() )
+ return false;
+
+ if ( GetOuter()->IsFlaggedEfficient() )
+ return false;
+
+ AI_PROFILE_SCOPE(CAI_Motor_MoveCalcSteer);
+ Vector moveSolution;
+ if ( m_pPlaneSolver->Solve( *pMoveGoal, distClear, &moveSolution ) )
+ {
+ if ( moveSolution != pMoveGoal->dir )
+ {
+ float dot = moveSolution.AsVector2D().Dot( pMoveGoal->dir.AsVector2D() );
+
+ const float COS_HALF_30 = 0.966;
+ if ( dot > COS_HALF_30 )
+ {
+ float probeDist = m_pPlaneSolver->CalcProbeDist( pMoveGoal->speed );
+ if ( pMoveGoal->maxDist < probeDist * 0.33333 && distClear > probeDist * 0.6666)
+ {
+ // A waypoint is coming up, but there's probably time to steer
+ // away after hitting it
+ *pResult = AIMR_OK;
+ return true;
+ }
+ }
+
+ pMoveGoal->facing = pMoveGoal->dir = moveSolution;
+ }
+ *pResult = AIMR_OK;
+ return true;
+ }
+
+ return false;
+}
+
+//-------------------------------------
+
+bool CAI_LocalNavigator::MoveCalcStop( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult )
+{
+ if (distClear < pMoveGoal->maxDist)
+ {
+ if ( distClear < 0.1 )
+ {
+ DebugNoteMovementFailure();
+ *pResult = AIMR_ILLEGAL;
+ }
+ else
+ {
+ pMoveGoal->maxDist = distClear;
+ *pResult = AIMR_OK;
+ }
+
+ return true;
+ }
+ *pResult = AIMR_OK;
+ return true;
+}
+
+//-------------------------------------
+
+#ifdef DEBUG
+#define SetSolveCookie() pMoveGoal->solveCookie = __LINE__;
+#else
+#define SetSolveCookie() ((void)0)
+#endif
+
+
+AIMoveResult_t CAI_LocalNavigator::MoveCalcRaw( AILocalMoveGoal_t *pMoveGoal, bool bOnlyCurThink )
+{
+ AI_PROFILE_SCOPE(CAI_Motor_MoveCalc);
+
+ AIMoveResult_t result = AIMR_OK; // Assume success
+ AIMoveTrace_t directTrace;
+ float distClear;
+
+ // --------------------------------------------------
+
+ bool bDirectClear = MoveCalcDirect( pMoveGoal, bOnlyCurThink, &distClear, &result);
+ if ( OnCalcBaseMove( pMoveGoal, distClear, &result ) )
+ {
+ SetSolveCookie();
+ return DbgResult( result );
+ }
+
+ bool bShouldSteer = ( !(pMoveGoal->flags & AILMG_NO_STEER) && ( !bDirectClear || HaveObstacles() ) );
+
+ if ( bDirectClear && !bShouldSteer )
+ {
+ SetSolveCookie();
+ return DbgResult( result );
+ }
+
+ // --------------------------------------------------
+
+ if ( bShouldSteer )
+ {
+ if ( !bDirectClear )
+ {
+ if ( OnObstructionPreSteer( pMoveGoal, distClear, &result ) )
+ {
+ SetSolveCookie();
+ return DbgResult( result );
+ }
+ }
+
+ if ( MoveCalcSteer( pMoveGoal, distClear, &result ) )
+ {
+ SetSolveCookie();
+ return DbgResult( result );
+ }
+ }
+
+ if ( OnFailedSteer( pMoveGoal, distClear, &result ) )
+ {
+ SetSolveCookie();
+ return DbgResult( result );
+ }
+
+ // --------------------------------------------------
+
+ if ( OnFailedLocalNavigation( pMoveGoal, distClear, &result ) )
+ {
+ SetSolveCookie();
+ return DbgResult( result );
+ }
+
+ if ( distClear < GetOuter()->GetMotor()->MinStoppingDist() )
+ {
+ if ( OnInsufficientStopDist( pMoveGoal, distClear, &result ) )
+ {
+ SetSolveCookie();
+ return DbgResult( result );
+ }
+
+ if ( MoveCalcStop( pMoveGoal, distClear, &result) )
+ {
+ SetSolveCookie();
+ return DbgResult( result );
+ }
+ }
+
+ // A hopeful result... may get in trouble at next waypoint and obstruction is still there
+ if ( distClear > pMoveGoal->curExpectedDist )
+ {
+ SetSolveCookie();
+ return DbgResult( AIMR_OK );
+ }
+
+ // --------------------------------------------------
+
+ DebugNoteMovementFailure();
+ SetSolveCookie();
+ return DbgResult( IsMoveBlocked( pMoveGoal->directTrace.fStatus ) ? pMoveGoal->directTrace.fStatus : AIMR_ILLEGAL );
+}
+
+//-------------------------------------
+
+AIMoveResult_t CAI_LocalNavigator::MoveCalc( AILocalMoveGoal_t *pMoveGoal, bool bPreviouslyValidated )
+{
+ bool bOnlyCurThink = ( bPreviouslyValidated && !HaveObstacles() );
+
+ AIMoveResult_t result = MoveCalcRaw( pMoveGoal, bOnlyCurThink );
+
+ if ( pMoveGoal->curExpectedDist > pMoveGoal->maxDist )
+ pMoveGoal->curExpectedDist = pMoveGoal->maxDist;
+
+ // If success, try to dampen really fast turning movement
+ if ( result == AIMR_OK)
+ {
+ float interval = GetOuter()->GetMotor()->GetMoveInterval();
+ float currentYaw = UTIL_AngleMod( GetLocalAngles().y );
+ float goalYaw;
+ float deltaYaw;
+ float speed;
+ float clampedYaw;
+
+ // Clamp yaw
+ goalYaw = UTIL_VecToYaw( pMoveGoal->facing );
+ deltaYaw = fabs( UTIL_AngleDiff( goalYaw, currentYaw ) );
+ if ( deltaYaw > 15 )
+ {
+ speed = deltaYaw * 4.0; // i.e., any maneuver takes a quarter a second
+ clampedYaw = AI_ClampYaw( speed, currentYaw, goalYaw, interval );
+
+ if ( clampedYaw != goalYaw )
+ {
+ pMoveGoal->facing = UTIL_YawToVector( clampedYaw );
+ }
+ }
+ }
+
+ return result;
+}
+//-----------------------------------------------------------------------------