Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

683 lines
18 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "ai_link.h"
  8. #include "ai_navtype.h"
  9. #include "ai_waypoint.h"
  10. #include "ai_pathfinder.h"
  11. #include "ai_navgoaltype.h"
  12. #include "ai_routedist.h"
  13. #include "ai_route.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. BEGIN_SIMPLE_DATADESC(CAI_Path)
  17. // m_Waypoints (reconsititute on load)
  18. DEFINE_FIELD( m_goalTolerance, FIELD_FLOAT ),
  19. DEFINE_CUSTOM_FIELD( m_activity, ActivityDataOps() ),
  20. DEFINE_FIELD( m_target, FIELD_EHANDLE ),
  21. DEFINE_FIELD( m_sequence, FIELD_INTEGER ),
  22. DEFINE_FIELD( m_vecTargetOffset, FIELD_VECTOR ),
  23. DEFINE_FIELD( m_waypointTolerance, FIELD_FLOAT ),
  24. DEFINE_CUSTOM_FIELD( m_arrivalActivity, ActivityDataOps() ),
  25. DEFINE_FIELD( m_arrivalSequence, FIELD_INTEGER ),
  26. // m_iLastNodeReached
  27. DEFINE_FIELD( m_bGoalPosSet, FIELD_BOOLEAN ),
  28. DEFINE_FIELD( m_goalPos, FIELD_POSITION_VECTOR),
  29. DEFINE_FIELD( m_bGoalTypeSet, FIELD_BOOLEAN ),
  30. DEFINE_FIELD( m_goalType, FIELD_INTEGER ),
  31. DEFINE_FIELD( m_goalFlags, FIELD_INTEGER ),
  32. DEFINE_FIELD( m_routeStartTime, FIELD_TIME ),
  33. DEFINE_FIELD( m_goalDirection, FIELD_VECTOR ),
  34. DEFINE_FIELD( m_goalDirectionTarget, FIELD_EHANDLE ),
  35. DEFINE_FIELD( m_goalSpeed, FIELD_FLOAT ),
  36. DEFINE_FIELD( m_goalSpeedTarget, FIELD_EHANDLE ),
  37. DEFINE_FIELD( m_goalStoppingDistance, FIELD_FLOAT ),
  38. END_DATADESC()
  39. //-----------------------------------------------------------------------------
  40. AI_Waypoint_t CAI_Path::gm_InvalidWaypoint( Vector(0,0,0), 0, NAV_NONE, 0, 0 );
  41. //-----------------------------------------------------------------------------
  42. void CAI_Path::SetWaypoints(AI_Waypoint_t* route, bool fSetGoalFromLast)
  43. {
  44. m_Waypoints.Set(route);
  45. AI_Waypoint_t *pLast = m_Waypoints.GetLast();
  46. if ( pLast )
  47. {
  48. pLast->flPathDistGoal = -1;
  49. if ( fSetGoalFromLast )
  50. {
  51. if ( pLast )
  52. {
  53. m_bGoalPosSet = false;
  54. pLast->ModifyFlags( bits_WP_TO_GOAL, true );
  55. SetGoalPosition(pLast->GetPos());
  56. }
  57. }
  58. }
  59. AssertRouteValid( m_Waypoints.GetFirst() );
  60. }
  61. //-----------------------------------------------------------------------------
  62. void CAI_Path::PrependWaypoints( AI_Waypoint_t *pWaypoints )
  63. {
  64. m_Waypoints.PrependWaypoints( pWaypoints );
  65. AI_Waypoint_t *pLast = m_Waypoints.GetLast();
  66. pLast->flPathDistGoal = -1;
  67. AssertRouteValid( m_Waypoints.GetFirst() );
  68. }
  69. //-----------------------------------------------------------------------------
  70. void CAI_Path::PrependWaypoint( const Vector &newPoint, Navigation_t navType, unsigned waypointFlags )
  71. {
  72. m_Waypoints.PrependWaypoint( newPoint, navType, waypointFlags );
  73. AI_Waypoint_t *pLast = m_Waypoints.GetLast();
  74. pLast->flPathDistGoal = -1;
  75. AssertRouteValid( m_Waypoints.GetFirst() );
  76. }
  77. //-----------------------------------------------------------------------------
  78. float CAI_Path::GetPathLength()
  79. {
  80. AI_Waypoint_t *pLast = m_Waypoints.GetLast();
  81. if ( pLast && pLast->flPathDistGoal == -1 )
  82. {
  83. ComputeRouteGoalDistances( pLast );
  84. }
  85. AI_Waypoint_t *pCurrent = GetCurWaypoint();
  86. return ( ( pCurrent ) ? pCurrent->flPathDistGoal : 0 );
  87. }
  88. //-----------------------------------------------------------------------------
  89. float CAI_Path::GetPathDistanceToGoal( const Vector &startPos )
  90. {
  91. AI_Waypoint_t *pCurrent = GetCurWaypoint();
  92. if ( pCurrent )
  93. {
  94. return ( GetPathLength() + ComputePathDistance(pCurrent->NavType(), startPos, pCurrent->GetPos()) );
  95. }
  96. return 0;
  97. }
  98. //-----------------------------------------------------------------------------
  99. Activity CAI_Path::SetMovementActivity(Activity activity)
  100. {
  101. Assert( activity != ACT_RESET && activity != ACT_INVALID );
  102. //Msg("Set movement to %s\n", ActivityList_NameForIndex(activity) );
  103. m_sequence = ACT_INVALID;
  104. return (m_activity = activity);
  105. }
  106. //-----------------------------------------------------------------------------
  107. Activity CAI_Path::GetArrivalActivity( ) const
  108. {
  109. if ( !m_Waypoints.IsEmpty() )
  110. {
  111. return m_arrivalActivity;
  112. }
  113. return ACT_INVALID;
  114. }
  115. //-----------------------------------------------------------------------------
  116. void CAI_Path::SetArrivalActivity(Activity activity)
  117. {
  118. m_arrivalActivity = activity;
  119. m_arrivalSequence = ACT_INVALID;
  120. }
  121. //-----------------------------------------------------------------------------
  122. int CAI_Path::GetArrivalSequence( ) const
  123. {
  124. if ( !m_Waypoints.IsEmpty() )
  125. {
  126. return m_arrivalSequence;
  127. }
  128. return ACT_INVALID;
  129. }
  130. //-----------------------------------------------------------------------------
  131. void CAI_Path::SetArrivalSequence( int sequence )
  132. {
  133. m_arrivalSequence = sequence;
  134. }
  135. //-----------------------------------------------------------------------------
  136. void CAI_Path::SetGoalDirection( const Vector &goalDirection )
  137. {
  138. m_goalDirectionTarget = NULL;
  139. m_goalDirection = goalDirection;
  140. VectorNormalize( m_goalDirection );
  141. /*
  142. AI_Waypoint_t *pLast = m_Waypoints.GetLast();
  143. if ( pLast )
  144. {
  145. NDebugOverlay::Box( pLast->vecLocation, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 0,0,255, 0, 2.0 );
  146. NDebugOverlay::Line( pLast->vecLocation, pLast->vecLocation + m_goalDirection * 32, 0,0,255, true, 2.0 );
  147. }
  148. */
  149. }
  150. //-----------------------------------------------------------------------------
  151. void CAI_Path::SetGoalDirection( CBaseEntity *pTarget )
  152. {
  153. m_goalDirectionTarget = pTarget;
  154. if (pTarget)
  155. {
  156. AI_Waypoint_t *pLast = m_Waypoints.GetLast();
  157. if ( pLast )
  158. {
  159. m_goalDirection = pTarget->GetAbsOrigin() - pLast->vecLocation;
  160. VectorNormalize( m_goalDirection );
  161. /*
  162. NDebugOverlay::Box( pLast->vecLocation, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 0,0,255, 0, 2.0 );
  163. NDebugOverlay::Line( pLast->vecLocation, pLast->vecLocation + m_goalDirection * 32, 0,0,255, true, 2.0 );
  164. */
  165. }
  166. }
  167. }
  168. //-----------------------------------------------------------------------------
  169. Vector CAI_Path::GetGoalDirection( const Vector &startPos )
  170. {
  171. if (m_goalDirectionTarget)
  172. {
  173. AI_Waypoint_t *pLast = m_Waypoints.GetLast();
  174. if ( pLast )
  175. {
  176. AI_Waypoint_t *pPrev = pLast->GetPrev();
  177. if (pPrev)
  178. {
  179. Vector goalDirection = m_goalDirectionTarget->GetAbsOrigin() - pPrev->vecLocation;
  180. VectorNormalize( goalDirection );
  181. return goalDirection;
  182. }
  183. else
  184. {
  185. Vector goalDirection = m_goalDirectionTarget->GetAbsOrigin() - startPos;
  186. VectorNormalize( goalDirection );
  187. return goalDirection;
  188. }
  189. }
  190. }
  191. else if (m_goalDirection == vec3_origin)
  192. {
  193. // Assert(0); // comment out the default directions in SetGoal() to find test cases for missing initialization
  194. AI_Waypoint_t *pLast = m_Waypoints.GetLast();
  195. if ( pLast )
  196. {
  197. AI_Waypoint_t *pPrev = pLast->GetPrev();
  198. if (pPrev)
  199. {
  200. Vector goalDirection = pLast->vecLocation - pPrev->vecLocation;
  201. VectorNormalize( goalDirection );
  202. return goalDirection;
  203. }
  204. else
  205. {
  206. Vector goalDirection =pLast->vecLocation - startPos;
  207. VectorNormalize( goalDirection );
  208. return goalDirection;
  209. }
  210. }
  211. }
  212. return m_goalDirection;
  213. }
  214. //-----------------------------------------------------------------------------
  215. void CAI_Path::SetGoalSpeed( float flSpeed )
  216. {
  217. m_goalSpeed = flSpeed;
  218. }
  219. //-----------------------------------------------------------------------------
  220. void CAI_Path::SetGoalSpeed( CBaseEntity *pTarget )
  221. {
  222. m_goalSpeedTarget = pTarget;
  223. }
  224. //-----------------------------------------------------------------------------
  225. float CAI_Path::GetGoalSpeed( const Vector &startPos )
  226. {
  227. if (m_goalSpeedTarget)
  228. {
  229. Vector goalDirection = GetGoalDirection( startPos );
  230. Vector targetVelocity = m_goalSpeedTarget->GetSmoothedVelocity();
  231. float dot = DotProduct( goalDirection, targetVelocity );
  232. dot = MAX( 0.0f, dot );
  233. // return a relative impact speed of m_goalSpeed
  234. if (m_goalSpeed > 0.0)
  235. {
  236. return dot + m_goalSpeed;
  237. }
  238. return dot;
  239. }
  240. return m_goalSpeed;
  241. }
  242. //-----------------------------------------------------------------------------
  243. void CAI_Path::SetGoalStoppingDistance( float flDistance )
  244. {
  245. m_goalStoppingDistance = flDistance;
  246. }
  247. //-----------------------------------------------------------------------------
  248. float CAI_Path::GetGoalStoppingDistance( ) const
  249. {
  250. return m_goalStoppingDistance;
  251. }
  252. //-----------------------------------------------------------------------------
  253. const Vector &CAI_Path::CurWaypointPos() const
  254. {
  255. if ( GetCurWaypoint() )
  256. return GetCurWaypoint()->GetPos();
  257. AssertMsg(0, "Invalid call to CurWaypointPos()");
  258. return gm_InvalidWaypoint.GetPos();
  259. }
  260. //-----------------------------------------------------------------------------
  261. const Vector &CAI_Path::NextWaypointPos() const
  262. {
  263. if ( GetCurWaypoint() && GetCurWaypoint()->GetNext())
  264. return GetCurWaypoint()->GetNext()->GetPos();
  265. static Vector invalid( 0, 0, 0 );
  266. AssertMsg(0, "Invalid call to NextWaypointPos()");
  267. return gm_InvalidWaypoint.GetPos();
  268. }
  269. //-----------------------------------------------------------------------------
  270. float CAI_Path::CurWaypointYaw() const
  271. {
  272. return GetCurWaypoint()->flYaw;
  273. }
  274. //-----------------------------------------------------------------------------
  275. // Purpose:
  276. // Input :
  277. // Output :
  278. //-----------------------------------------------------------------------------
  279. void CAI_Path::SetGoalPosition(const Vector &goalPos)
  280. {
  281. #ifdef _DEBUG
  282. // Make sure goal position isn't set more than once
  283. if (m_bGoalPosSet == true)
  284. {
  285. DevMsg( "GetCurWaypoint Goal Position Set Twice!\n");
  286. }
  287. #endif
  288. m_bGoalPosSet = true;
  289. VectorAdd( goalPos, m_vecTargetOffset, m_goalPos );
  290. }
  291. //-----------------------------------------------------------------------------
  292. // Purpose: Sets last node as goal and goal position
  293. // Input :
  294. // Output :
  295. //-----------------------------------------------------------------------------
  296. void CAI_Path::SetLastNodeAsGoal(bool bReset)
  297. {
  298. #ifdef _DEBUG
  299. // Make sure goal position isn't set more than once
  300. if (!bReset && m_bGoalPosSet == true)
  301. {
  302. DevMsg( "GetCurWaypoint Goal Position Set Twice!\n");
  303. }
  304. #endif
  305. // Find the last node
  306. if (GetCurWaypoint())
  307. {
  308. AI_Waypoint_t* waypoint = GetCurWaypoint();
  309. while (waypoint)
  310. {
  311. if (!waypoint->GetNext())
  312. {
  313. m_goalPos = waypoint->GetPos();
  314. m_bGoalPosSet = true;
  315. waypoint->ModifyFlags( bits_WP_TO_GOAL, true );
  316. return;
  317. }
  318. waypoint = waypoint->GetNext();
  319. }
  320. }
  321. }
  322. //-----------------------------------------------------------------------------
  323. // Purpose: Explicitly change the goal position w/o check
  324. // Input :
  325. // Output :
  326. //-----------------------------------------------------------------------------
  327. void CAI_Path::ResetGoalPosition(const Vector &goalPos)
  328. {
  329. m_bGoalPosSet = true;
  330. VectorAdd( goalPos, m_vecTargetOffset, m_goalPos );
  331. }
  332. //-----------------------------------------------------------------------------
  333. // Returns the *base* goal position (without the offset applied)
  334. //-----------------------------------------------------------------------------
  335. const Vector& CAI_Path::BaseGoalPosition() const
  336. {
  337. #ifdef _DEBUG
  338. // Make sure goal position was set
  339. if (m_bGoalPosSet == false)
  340. {
  341. DevMsg( "GetCurWaypoint Goal Position Never Set!\n");
  342. }
  343. #endif
  344. // FIXME: A little risky; store the base if this becomes a problem
  345. static Vector vecResult;
  346. VectorSubtract( m_goalPos, m_vecTargetOffset, vecResult );
  347. return vecResult;
  348. }
  349. //-----------------------------------------------------------------------------
  350. // Returns the *actual* goal position (with the offset applied)
  351. //-----------------------------------------------------------------------------
  352. const Vector & CAI_Path::ActualGoalPosition(void) const
  353. {
  354. #ifdef _DEBUG
  355. // Make sure goal position was set
  356. if (m_bGoalPosSet == false)
  357. {
  358. DevMsg( "GetCurWaypoint Goal Position Never Set!\n");
  359. }
  360. #endif
  361. return m_goalPos;
  362. }
  363. //-----------------------------------------------------------------------------
  364. // Purpose:
  365. // Input :
  366. // Output :
  367. //-----------------------------------------------------------------------------
  368. void CAI_Path::SetGoalType(GoalType_t goalType)
  369. {
  370. #ifdef _DEBUG
  371. // Make sure goal position isn't set more than once
  372. if (m_goalType != GOALTYPE_NONE && goalType != GOALTYPE_NONE )
  373. {
  374. DevMsg( "GetCurWaypoint Goal Type Set Twice!\n");
  375. }
  376. #endif
  377. if (m_goalType != GOALTYPE_NONE)
  378. {
  379. m_routeStartTime = gpGlobals->curtime;
  380. m_bGoalTypeSet = true;
  381. }
  382. else
  383. m_bGoalTypeSet = false;
  384. m_goalType = goalType;
  385. }
  386. //-----------------------------------------------------------------------------
  387. // Purpose:
  388. // Input :
  389. // Output :
  390. //-----------------------------------------------------------------------------
  391. GoalType_t CAI_Path::GoalType(void) const
  392. {
  393. return m_goalType;
  394. }
  395. //-----------------------------------------------------------------------------
  396. void CAI_Path::Advance( void )
  397. {
  398. if ( CurWaypointIsGoal() )
  399. return;
  400. // -------------------------------------------------------
  401. // If I have another waypoint advance my path
  402. // -------------------------------------------------------
  403. if (GetCurWaypoint()->GetNext())
  404. {
  405. AI_Waypoint_t *pNext = GetCurWaypoint()->GetNext();
  406. // If waypoint was a node take note of it
  407. if (GetCurWaypoint()->Flags() & bits_WP_TO_NODE)
  408. {
  409. m_iLastNodeReached = GetCurWaypoint()->iNodeID;
  410. }
  411. delete GetCurWaypoint();
  412. SetWaypoints(pNext);
  413. return;
  414. }
  415. // -------------------------------------------------
  416. // This is an error catch that should *not* happen
  417. // It means a route was created with no goal
  418. // -------------------------------------------------
  419. else
  420. {
  421. DevMsg( "!!ERROR!! Force end of route with no goal!\n");
  422. GetCurWaypoint()->ModifyFlags( bits_WP_TO_GOAL, true );
  423. }
  424. AssertRouteValid( m_Waypoints.GetFirst() );
  425. }
  426. //-----------------------------------------------------------------------------
  427. // Purpose: Clears the route and resets all its fields to default values
  428. // Input :
  429. // Output :
  430. //-----------------------------------------------------------------------------
  431. void CAI_Path::Clear( void )
  432. {
  433. m_Waypoints.RemoveAll();
  434. m_goalType = GOALTYPE_NONE; // Type of goal
  435. m_goalPos = vec3_origin; // Our ultimate goal position
  436. m_bGoalPosSet = false; // Was goal position set
  437. m_bGoalTypeSet = false; // Was goal position set
  438. m_goalFlags = false;
  439. m_vecTargetOffset = vec3_origin;
  440. m_routeStartTime = FLT_MAX;
  441. m_goalTolerance = 0.0; // How close do we need to get to the goal
  442. // FIXME: split m_goalTolerance into m_buildTolerance and m_moveTolerance, let them be seperatly controllable.
  443. m_activity = ACT_INVALID;
  444. m_sequence = ACT_INVALID;
  445. m_target = NULL;
  446. m_arrivalActivity = ACT_INVALID;
  447. m_arrivalSequence = ACT_INVALID;
  448. m_goalDirectionTarget = NULL;
  449. m_goalDirection = vec3_origin;
  450. m_goalSpeedTarget = NULL;
  451. m_goalSpeed = -1.0f; // init to an invalid speed
  452. m_goalStoppingDistance = 0.0; // How close to we want to get to the goal
  453. }
  454. //-----------------------------------------------------------------------------
  455. // Purpose:
  456. // Input :
  457. // Output :
  458. //-----------------------------------------------------------------------------
  459. Navigation_t CAI_Path::CurWaypointNavType() const
  460. {
  461. if (!GetCurWaypoint())
  462. {
  463. return NAV_NONE;
  464. }
  465. else
  466. {
  467. return GetCurWaypoint()->NavType();
  468. }
  469. }
  470. int CAI_Path::CurWaypointFlags() const
  471. {
  472. if (!GetCurWaypoint())
  473. {
  474. return 0;
  475. }
  476. else
  477. {
  478. return GetCurWaypoint()->Flags();
  479. }
  480. }
  481. //-----------------------------------------------------------------------------
  482. // Purpose: Get the goal's flags
  483. // Output : unsigned
  484. //-----------------------------------------------------------------------------
  485. unsigned CAI_Path::GoalFlags( void ) const
  486. {
  487. return m_goalFlags;
  488. }
  489. //-----------------------------------------------------------------------------
  490. // Purpose: Returns true if current waypoint is my goal
  491. // Input :
  492. // Output :
  493. //-----------------------------------------------------------------------------
  494. bool CAI_Path::CurWaypointIsGoal( void ) const
  495. {
  496. // Assert( GetCurWaypoint() );
  497. if( !GetCurWaypoint() )
  498. return false;
  499. if ( GetCurWaypoint()->Flags() & bits_WP_TO_GOAL )
  500. {
  501. #ifdef _DEBUG
  502. if (GetCurWaypoint()->GetNext())
  503. {
  504. DevMsg( "!!ERROR!! Goal is not last waypoint!\n");
  505. }
  506. if ((GetCurWaypoint()->GetPos() - m_goalPos).Length() > 0.1)
  507. {
  508. DevMsg( "!!ERROR!! Last waypoint isn't in goal position!\n");
  509. }
  510. #endif
  511. return true;
  512. }
  513. if ( GetCurWaypoint()->Flags() & bits_WP_TO_PATHCORNER )
  514. {
  515. // UNDONE: Refresh here or somewhere else?
  516. }
  517. #ifdef _DEBUG
  518. if (!GetCurWaypoint()->GetNext())
  519. {
  520. DevMsg( "!!ERROR!! GetCurWaypoint has no goal!\n");
  521. }
  522. #endif
  523. return false;
  524. }
  525. //-----------------------------------------------------------------------------
  526. // Computes the goal distance for each waypoint along the route
  527. //-----------------------------------------------------------------------------
  528. void CAI_Path::ComputeRouteGoalDistances(AI_Waypoint_t *pGoalWaypoint)
  529. {
  530. // The goal distance is the distance from any waypoint to the goal waypoint
  531. // Backup through the list and calculate distance to goal
  532. AI_Waypoint_t *pPrev;
  533. AI_Waypoint_t *pCurWaypoint = pGoalWaypoint;
  534. pCurWaypoint->flPathDistGoal = 0;
  535. while (pCurWaypoint->GetPrev())
  536. {
  537. pPrev = pCurWaypoint->GetPrev();
  538. float flWaypointDist = ComputePathDistance(pCurWaypoint->NavType(), pPrev->GetPos(), pCurWaypoint->GetPos());
  539. pPrev->flPathDistGoal = pCurWaypoint->flPathDistGoal + flWaypointDist;
  540. pCurWaypoint = pPrev;
  541. }
  542. }
  543. //-----------------------------------------------------------------------------
  544. // Purpose: Constructor
  545. // Input :
  546. // Output :
  547. //-----------------------------------------------------------------------------
  548. CAI_Path::CAI_Path()
  549. {
  550. m_goalType = GOALTYPE_NONE; // Type of goal
  551. m_goalPos = vec3_origin; // Our ultimate goal position
  552. m_goalTolerance = 0.0; // How close do we need to get to the goal
  553. m_activity = ACT_INVALID; // The activity to use during motion
  554. m_sequence = ACT_INVALID;
  555. m_target = NULL;
  556. m_goalFlags = 0;
  557. m_routeStartTime = FLT_MAX;
  558. m_arrivalActivity = ACT_INVALID;
  559. m_arrivalSequence = ACT_INVALID;
  560. m_iLastNodeReached = NO_NODE;
  561. m_waypointTolerance = DEF_WAYPOINT_TOLERANCE;
  562. }
  563. CAI_Path::~CAI_Path()
  564. {
  565. DeleteAll( GetCurWaypoint() );
  566. }