Counter Strike : Global Offensive Source Code
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.

672 lines
20 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: An NPC's memory of potential enemies
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "isaverestore.h"
  8. #include "ai_debug.h"
  9. #include "ai_memory.h"
  10. #include "ai_basenpc.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. #define EMEMORY_POOL_SIZE 64
  14. #define AI_FREE_KNOWLEDGE_DURATION 1.75
  15. //-----------------------------------------------------------------------------
  16. // AI_EnemyInfo_t
  17. //
  18. //-----------------------------------------------------------------------------
  19. //-----------------------------------------------------------------------------
  20. AI_EnemyInfo_t::AI_EnemyInfo_t(void)
  21. {
  22. hEnemy = NULL;
  23. vLastKnownLocation = vec3_origin;
  24. vLastSeenLocation = vec3_origin;
  25. timeLastSeen = 0;
  26. timeFirstSeen = 0;
  27. timeLastReacquired = 0;
  28. timeValidEnemy = 0;
  29. timeLastReceivedDamageFrom = 0;
  30. timeAtFirstHand = AI_INVALID_TIME;
  31. nFaction = FACTION_NONE;
  32. bDangerMemory = 0;
  33. bEludedMe = 0;
  34. bUnforgettable = 0;
  35. bMobbedMe = 0;
  36. }
  37. //-----------------------------------------------------------------------------
  38. // CAI_EnemiesListSaveRestoreOps
  39. //
  40. // Purpose: Handles save and load for enemy memories
  41. //
  42. //-----------------------------------------------------------------------------
  43. class CAI_EnemiesListSaveRestoreOps : public CDefSaveRestoreOps
  44. {
  45. public:
  46. CAI_EnemiesListSaveRestoreOps()
  47. {
  48. }
  49. virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave )
  50. {
  51. CAI_Enemies::CMemMap *pMemMap = (CAI_Enemies::CMemMap *)fieldInfo.pField;
  52. int nMemories = pMemMap->Count();
  53. pSave->WriteInt( &nMemories );
  54. for ( CAI_Enemies::CMemMap::IndexType_t i = pMemMap->FirstInorder(); i != pMemMap->InvalidIndex(); i = pMemMap->NextInorder( i ) )
  55. {
  56. pSave->WriteAll( (*pMemMap)[i] );
  57. }
  58. }
  59. virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore )
  60. {
  61. CAI_Enemies::CMemMap *pMemMap = (CAI_Enemies::CMemMap *)fieldInfo.pField;
  62. Assert( pMemMap->Count() == 0 );
  63. int nMemories = pRestore->ReadInt();
  64. while ( nMemories-- )
  65. {
  66. AI_EnemyInfo_t *pAddMemory = new AI_EnemyInfo_t;
  67. pRestore->ReadAll( pAddMemory );
  68. if ( pAddMemory->hEnemy != NULL )
  69. {
  70. pMemMap->Insert( pAddMemory->hEnemy, pAddMemory );
  71. }
  72. else
  73. delete pAddMemory;
  74. }
  75. }
  76. virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo )
  77. {
  78. CAI_Enemies::CMemMap *pMemMap = (CAI_Enemies::CMemMap *)fieldInfo.pField;
  79. for ( CAI_Enemies::CMemMap::IndexType_t i = pMemMap->FirstInorder(); i != pMemMap->InvalidIndex(); i = pMemMap->NextInorder( i ) )
  80. {
  81. delete (*pMemMap)[i];
  82. }
  83. pMemMap->RemoveAll();
  84. }
  85. virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo )
  86. {
  87. CAI_Enemies::CMemMap *pMemMap = (CAI_Enemies::CMemMap *)fieldInfo.pField;
  88. return ( pMemMap->Count() == 0 );
  89. }
  90. } g_AI_MemoryListSaveRestoreOps;
  91. //-----------------------------------------------------------------------------
  92. // CAI_Enemies
  93. //
  94. // Purpose: Stores a set of AI_EnemyInfo_t's
  95. //
  96. //-----------------------------------------------------------------------------
  97. BEGIN_SIMPLE_DATADESC( CAI_Enemies )
  98. DEFINE_CUSTOM_FIELD( m_Map, &g_AI_MemoryListSaveRestoreOps ),
  99. DEFINE_FIELD( m_flFreeKnowledgeDuration, FIELD_FLOAT ),
  100. DEFINE_FIELD( m_flEnemyDiscardTime, FIELD_FLOAT ),
  101. DEFINE_FIELD( m_vecDefaultLKP, FIELD_POSITION_VECTOR ),
  102. DEFINE_FIELD( m_vecDefaultLSP, FIELD_POSITION_VECTOR ),
  103. DEFINE_FIELD( m_serial, FIELD_INTEGER ),
  104. END_DATADESC()
  105. BEGIN_SIMPLE_DATADESC( AI_EnemyInfo_t )
  106. DEFINE_FIELD( vLastKnownLocation, FIELD_POSITION_VECTOR ),
  107. DEFINE_FIELD( vLastSeenLocation, FIELD_POSITION_VECTOR ),
  108. DEFINE_FIELD( hEnemy, FIELD_EHANDLE ),
  109. DEFINE_FIELD( timeLastSeen, FIELD_TIME ),
  110. DEFINE_FIELD( timeFirstSeen, FIELD_TIME ),
  111. DEFINE_FIELD( timeLastReacquired, FIELD_TIME ),
  112. DEFINE_FIELD( timeValidEnemy, FIELD_TIME ),
  113. DEFINE_FIELD( timeLastReceivedDamageFrom, FIELD_TIME ),
  114. DEFINE_FIELD( timeAtFirstHand, FIELD_TIME ),
  115. DEFINE_FIELD( nFaction, FIELD_INTEGER ),
  116. DEFINE_FIELD( bDangerMemory, FIELD_BOOLEAN ),
  117. DEFINE_FIELD( bEludedMe, FIELD_BOOLEAN ),
  118. DEFINE_FIELD( bUnforgettable, FIELD_BOOLEAN ),
  119. DEFINE_FIELD( bMobbedMe, FIELD_BOOLEAN ),
  120. // NOT SAVED nextEMemory
  121. END_DATADESC()
  122. //-----------------------------------------------------------------------------
  123. CAI_Enemies::CAI_Enemies(void)
  124. {
  125. m_flFreeKnowledgeDuration = AI_FREE_KNOWLEDGE_DURATION;
  126. m_flEnemyDiscardTime = AI_DEF_ENEMY_DISCARD_TIME;
  127. m_vecDefaultLKP = vec3_invalid;
  128. m_vecDefaultLSP = vec3_invalid;
  129. m_serial = 0;
  130. SetDefLessFunc( m_Map );
  131. }
  132. //-----------------------------------------------------------------------------
  133. CAI_Enemies::~CAI_Enemies()
  134. {
  135. for ( CMemMap::IndexType_t i = m_Map.FirstInorder(); i != m_Map.InvalidIndex(); i = m_Map.NextInorder( i ) )
  136. {
  137. delete m_Map[i];
  138. }
  139. }
  140. //-----------------------------------------------------------------------------
  141. // Purpose: Purges any dead enemies from memory
  142. //-----------------------------------------------------------------------------
  143. AI_EnemyInfo_t *CAI_Enemies::GetFirst( AIEnemiesIter_t *pIter )
  144. {
  145. CMemMap::IndexType_t i = m_Map.FirstInorder();
  146. *pIter = (AIEnemiesIter_t)(uintp)i;
  147. if ( i == m_Map.InvalidIndex() )
  148. return NULL;
  149. if ( m_Map[i]->hEnemy == NULL )
  150. return GetNext( pIter );
  151. return m_Map[i];
  152. }
  153. //-----------------------------------------------------------------------------
  154. AI_EnemyInfo_t *CAI_Enemies::GetNext( AIEnemiesIter_t *pIter )
  155. {
  156. CMemMap::IndexType_t i = size_cast< CMemMap::IndexType_t >( (uintp)(*pIter) );
  157. if ( i == m_Map.InvalidIndex() )
  158. return NULL;
  159. i = m_Map.NextInorder( i );
  160. *pIter = size_cast< AIEnemiesIter_t >( (uintp)i );
  161. if ( i == m_Map.InvalidIndex() )
  162. return NULL;
  163. if ( m_Map[i]->hEnemy == NULL )
  164. return GetNext( pIter );
  165. return m_Map[i];
  166. }
  167. //-----------------------------------------------------------------------------
  168. AI_EnemyInfo_t *CAI_Enemies::Find( CBaseEntity *pEntity, bool bTryDangerMemory )
  169. {
  170. if ( pEntity == AI_UNKNOWN_ENEMY )
  171. pEntity = NULL;
  172. CMemMap::IndexType_t i = m_Map.Find( pEntity );
  173. if ( i == m_Map.InvalidIndex() )
  174. {
  175. if ( !bTryDangerMemory || ( i = m_Map.Find( NULL ) ) == m_Map.InvalidIndex() )
  176. return NULL;
  177. Assert(m_Map[i]->bDangerMemory == true);
  178. }
  179. return m_Map[i];
  180. }
  181. //-----------------------------------------------------------------------------
  182. AI_EnemyInfo_t *CAI_Enemies::GetDangerMemory()
  183. {
  184. CMemMap::IndexType_t i = m_Map.Find( NULL );
  185. if ( i == m_Map.InvalidIndex() )
  186. return NULL;
  187. Assert(m_Map[i]->bDangerMemory == true);
  188. return m_Map[i];
  189. }
  190. //-----------------------------------------------------------------------------
  191. bool CAI_Enemies::ShouldDiscardMemory( AI_EnemyInfo_t *pMemory )
  192. {
  193. CBaseEntity *pEnemy = pMemory->hEnemy;
  194. if ( pEnemy )
  195. {
  196. CAI_BaseNPC *pEnemyNPC = pEnemy->MyNPCPointer();
  197. if ( pEnemyNPC )
  198. {
  199. if ( pEnemyNPC->GetState() == NPC_STATE_DEAD )
  200. return true;
  201. // forget about the enemy if he changes faction
  202. if ( pEnemyNPC->GetFaction() != pMemory->nFaction )
  203. return true;
  204. }
  205. }
  206. else
  207. {
  208. if ( !pMemory->bDangerMemory )
  209. return true;
  210. }
  211. if ( !pMemory->bUnforgettable &&
  212. gpGlobals->curtime > pMemory->timeLastSeen + m_flEnemyDiscardTime )
  213. {
  214. return true;
  215. }
  216. return false;
  217. }
  218. //-----------------------------------------------------------------------------
  219. void CAI_Enemies::RefreshMemories(void)
  220. {
  221. AI_PROFILE_SCOPE(CAI_Enemies_RefreshMemories);
  222. if ( m_flFreeKnowledgeDuration >= m_flEnemyDiscardTime )
  223. {
  224. m_flFreeKnowledgeDuration = m_flEnemyDiscardTime - .1;
  225. }
  226. // -------------------
  227. // Check each record
  228. // -------------------
  229. CMemMap::IndexType_t i = m_Map.FirstInorder();
  230. while ( i != m_Map.InvalidIndex() )
  231. {
  232. AI_EnemyInfo_t *pMemory = m_Map[i];
  233. CMemMap::IndexType_t iNext = m_Map.NextInorder( i ); // save so can remove
  234. if ( ShouldDiscardMemory( pMemory ) )
  235. {
  236. delete pMemory;
  237. m_Map.RemoveAt(i);
  238. }
  239. else if ( pMemory->hEnemy )
  240. {
  241. if ( gpGlobals->curtime <= pMemory->timeLastSeen + m_flFreeKnowledgeDuration )
  242. {
  243. // Free knowledge is ignored if the target has notarget on
  244. if ( !(pMemory->hEnemy->GetFlags() & FL_NOTARGET) )
  245. {
  246. pMemory->vLastKnownLocation = pMemory->hEnemy->GetAbsOrigin();
  247. }
  248. }
  249. if ( gpGlobals->curtime <= pMemory->timeLastSeen )
  250. {
  251. pMemory->vLastSeenLocation = pMemory->hEnemy->GetAbsOrigin();
  252. }
  253. }
  254. i = iNext;
  255. }
  256. }
  257. //-----------------------------------------------------------------------------
  258. // Purpose: Updates information about our enemies
  259. // Output : Returns true if new enemy, false if already know of enemy
  260. //-----------------------------------------------------------------------------
  261. bool CAI_Enemies::UpdateMemory(CAI_Network* pAINet, CBaseEntity *pEnemy, const Vector &vPosition, float reactionDelay, bool firstHand )
  262. {
  263. if ( pEnemy == AI_UNKNOWN_ENEMY )
  264. pEnemy = NULL;
  265. const float DIST_TRIGGER_REACQUIRE_SQ = Square(20.0 * 12.0);
  266. const float TIME_TRIGGER_REACQUIRE = 4.0;
  267. const float MIN_DIST_TIME_TRIGGER_REACQUIRE_SQ = Square(4.0 * 12.0);
  268. AI_EnemyInfo_t *pMemory = Find( pEnemy );
  269. // -------------------------------------------
  270. // Otherwise just update my own
  271. // -------------------------------------------
  272. // Update enemy information
  273. if ( pMemory )
  274. {
  275. Assert(pEnemy || pMemory->bDangerMemory == true);
  276. if ( firstHand )
  277. pMemory->timeLastSeen = gpGlobals->curtime;
  278. pMemory->bEludedMe = false;
  279. float deltaDist = (pMemory->vLastKnownLocation - vPosition).LengthSqr();
  280. if (deltaDist>DIST_TRIGGER_REACQUIRE_SQ || ( deltaDist>MIN_DIST_TIME_TRIGGER_REACQUIRE_SQ && ( gpGlobals->curtime - pMemory->timeLastSeen ) > TIME_TRIGGER_REACQUIRE ) )
  281. {
  282. pMemory->timeLastReacquired = gpGlobals->curtime;
  283. }
  284. // Only update if the enemy has moved
  285. if (deltaDist>Square(12.0))
  286. {
  287. pMemory->vLastKnownLocation = vPosition;
  288. }
  289. // Update the time at which we first saw him firsthand
  290. if ( firstHand && pMemory->timeAtFirstHand == AI_INVALID_TIME )
  291. {
  292. pMemory->timeAtFirstHand = gpGlobals->curtime;
  293. }
  294. return false;
  295. }
  296. // If not on my list of enemies add it
  297. AI_EnemyInfo_t *pAddMemory = new AI_EnemyInfo_t;
  298. pAddMemory->vLastKnownLocation = vPosition;
  299. if ( firstHand )
  300. {
  301. pAddMemory->timeLastReacquired = pAddMemory->timeFirstSeen = pAddMemory->timeLastSeen = pAddMemory->timeAtFirstHand = gpGlobals->curtime;
  302. }
  303. else
  304. {
  305. // Block free knowledge
  306. pAddMemory->timeLastReacquired = pAddMemory->timeFirstSeen = pAddMemory->timeLastSeen = ( gpGlobals->curtime - (m_flFreeKnowledgeDuration + 0.01) );
  307. pAddMemory->timeAtFirstHand = AI_INVALID_TIME;
  308. }
  309. if ( reactionDelay > 0.0 )
  310. pAddMemory->timeValidEnemy = gpGlobals->curtime + reactionDelay;
  311. pAddMemory->bEludedMe = false;
  312. // I'm either remembering a position of an enemy or just a danger position
  313. pAddMemory->hEnemy = pEnemy;
  314. pAddMemory->bDangerMemory = ( pEnemy == NULL );
  315. if ( pEnemy )
  316. {
  317. CAI_BaseNPC *pEnemyNPC = pEnemy->MyNPCPointer();
  318. if ( pEnemyNPC )
  319. pAddMemory->nFaction = pEnemyNPC->GetFaction();
  320. }
  321. // add to the list
  322. m_Map.Insert( pEnemy, pAddMemory );
  323. m_serial++;
  324. return true;
  325. }
  326. //------------------------------------------------------------------------------
  327. // Purpose : Returns true if this enemy is part of my memory
  328. //------------------------------------------------------------------------------
  329. void CAI_Enemies::OnTookDamageFrom( CBaseEntity *pEnemy )
  330. {
  331. AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
  332. if ( pMemory )
  333. pMemory->timeLastReceivedDamageFrom = gpGlobals->curtime;
  334. }
  335. //------------------------------------------------------------------------------
  336. // Purpose : Returns true if this enemy is part of my memory
  337. //------------------------------------------------------------------------------
  338. bool CAI_Enemies::HasMemory( CBaseEntity *pEnemy )
  339. {
  340. return ( Find( pEnemy ) != NULL );
  341. }
  342. //-----------------------------------------------------------------------------
  343. // Purpose: Clear information about our enemy
  344. //-----------------------------------------------------------------------------
  345. void CAI_Enemies::ClearMemory(CBaseEntity *pEnemy)
  346. {
  347. CMemMap::IndexType_t i = m_Map.Find( pEnemy );
  348. if ( i != m_Map.InvalidIndex() )
  349. {
  350. delete m_Map[i];
  351. m_Map.RemoveAt( i );
  352. }
  353. }
  354. //-----------------------------------------------------------------------------
  355. // Purpose: Notes that the given enemy has eluded me
  356. //-----------------------------------------------------------------------------
  357. void CAI_Enemies::MarkAsEluded( CBaseEntity *pEnemy )
  358. {
  359. AI_EnemyInfo_t *pMemory = Find( pEnemy );
  360. if ( pMemory )
  361. {
  362. pMemory->bEludedMe = true;
  363. }
  364. }
  365. //-----------------------------------------------------------------------------
  366. // Purpose: Returns last known posiiton of given enemy
  367. //-----------------------------------------------------------------------------
  368. const Vector &CAI_Enemies::LastKnownPosition( CBaseEntity *pEnemy )
  369. {
  370. AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
  371. if ( pMemory )
  372. {
  373. m_vecDefaultLKP = pMemory->vLastKnownLocation;
  374. }
  375. else
  376. {
  377. DevWarning( 2,"Asking LastKnownPosition for enemy that's not in my memory!!\n");
  378. }
  379. return m_vecDefaultLKP;
  380. }
  381. //-----------------------------------------------------------------------------
  382. // Purpose: Returns the last position the enemy was SEEN at. This will always be
  383. // different than LastKnownPosition() when the enemy is out of sight, because
  384. // the last KNOWN position will be updated for a number of seconds after the
  385. // player disappears.
  386. //-----------------------------------------------------------------------------
  387. const Vector &CAI_Enemies::LastSeenPosition( CBaseEntity *pEnemy )
  388. {
  389. AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
  390. if ( pMemory )
  391. {
  392. m_vecDefaultLSP = pMemory->vLastSeenLocation;
  393. }
  394. else
  395. {
  396. DevWarning( 2,"Asking LastSeenPosition for enemy that's not in my memory!!\n");
  397. }
  398. return m_vecDefaultLSP;
  399. }
  400. float CAI_Enemies::TimeLastReacquired( CBaseEntity *pEnemy )
  401. {
  402. // I've never seen something that doesn't exist
  403. if (!pEnemy)
  404. return 0;
  405. AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
  406. if ( pMemory )
  407. return pMemory->timeLastReacquired;
  408. if ( pEnemy != AI_UNKNOWN_ENEMY )
  409. DevWarning( 2,"Asking TimeLastReacquired for enemy that's not in my memory!!\n");
  410. return AI_INVALID_TIME;
  411. }
  412. //-----------------------------------------------------------------------------
  413. // Purpose: Sets position to the last known position of an enemy. If enemy
  414. // was not found returns last memory of danger position if it exists
  415. // Output : Returns false is no position is known
  416. //-----------------------------------------------------------------------------
  417. float CAI_Enemies::LastTimeSeen( CBaseEntity *pEnemy, bool bCheckDangerMemory /*= true*/ )
  418. {
  419. // I've never seen something that doesn't exist
  420. if (!pEnemy)
  421. return 0;
  422. AI_EnemyInfo_t *pMemory = Find( pEnemy, bCheckDangerMemory );
  423. if ( pMemory )
  424. return pMemory->timeLastSeen;
  425. if ( pEnemy != AI_UNKNOWN_ENEMY )
  426. DevWarning( 2,"Asking LastTimeSeen for enemy that's not in my memory!!\n");
  427. return AI_INVALID_TIME;
  428. }
  429. //-----------------------------------------------------------------------------
  430. // Purpose: Get the time at which the enemy was first seen.
  431. // Output : Returns false is no position is known
  432. //-----------------------------------------------------------------------------
  433. float CAI_Enemies::FirstTimeSeen( CBaseEntity *pEnemy)
  434. {
  435. // I've never seen something that doesn't exist
  436. if (!pEnemy)
  437. return 0;
  438. AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
  439. if ( pMemory )
  440. return pMemory->timeFirstSeen;
  441. if ( pEnemy != AI_UNKNOWN_ENEMY )
  442. DevWarning( 2,"Asking FirstTimeSeen for enemy that's not in my memory!!\n");
  443. return AI_INVALID_TIME;
  444. }
  445. //-----------------------------------------------------------------------------
  446. // Purpose:
  447. // Input : *pEnemy -
  448. // Output : Returns true on success, false on failure.
  449. //-----------------------------------------------------------------------------
  450. bool CAI_Enemies::HasFreeKnowledgeOf( CBaseEntity *pEnemy )
  451. {
  452. // I've never seen something that doesn't exist
  453. if (!pEnemy)
  454. return 0;
  455. AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
  456. if ( pMemory )
  457. {
  458. float flFreeKnowledgeTime = pMemory->timeLastSeen + m_flFreeKnowledgeDuration;
  459. return ( gpGlobals->curtime < flFreeKnowledgeTime );
  460. }
  461. if ( pEnemy != AI_UNKNOWN_ENEMY )
  462. DevWarning( 2,"Asking HasFreeKnowledgeOf for enemy that's not in my memory!!\n");
  463. return AI_INVALID_TIME;
  464. }
  465. //-----------------------------------------------------------------------------
  466. float CAI_Enemies::LastTimeTookDamageFrom( CBaseEntity *pEnemy)
  467. {
  468. // I've never seen something that doesn't exist
  469. if (!pEnemy)
  470. return 0;
  471. AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
  472. if ( pMemory )
  473. return pMemory->timeLastReceivedDamageFrom;
  474. if ( pEnemy != AI_UNKNOWN_ENEMY )
  475. DevWarning( 2,"Asking LastTimeTookDamageFrom for enemy that's not in my memory!!\n");
  476. return AI_INVALID_TIME;
  477. }
  478. //-----------------------------------------------------------------------------
  479. // Purpose: Returns the time at which the enemy was first seen firsthand
  480. // Input : *pEnemy -
  481. // Output : float
  482. //-----------------------------------------------------------------------------
  483. float CAI_Enemies::TimeAtFirstHand( CBaseEntity *pEnemy )
  484. {
  485. // I've never seen something that doesn't exist
  486. if (!pEnemy)
  487. return 0;
  488. AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
  489. if ( pMemory )
  490. return pMemory->timeAtFirstHand;
  491. if ( pEnemy != AI_UNKNOWN_ENEMY )
  492. DevWarning( 2,"Asking TimeAtFirstHand for enemy that's not in my memory!!\n");
  493. return AI_INVALID_TIME;
  494. }
  495. //-----------------------------------------------------------------------------
  496. // Purpose: Sets position to the last known position of an enemy. If enemy
  497. // was not found returns last memory of danger position if it exists
  498. // Output : Returns false is no position is known
  499. //-----------------------------------------------------------------------------
  500. bool CAI_Enemies::HasEludedMe( CBaseEntity *pEnemy )
  501. {
  502. AI_EnemyInfo_t *pMemory = Find( pEnemy );
  503. if ( pMemory )
  504. return pMemory->bEludedMe;
  505. return false;
  506. }
  507. void CAI_Enemies::SetTimeValidEnemy( CBaseEntity *pEnemy, float flTime )
  508. {
  509. AI_EnemyInfo_t *pMemory = Find( pEnemy );
  510. if ( pMemory )
  511. pMemory->timeValidEnemy = flTime;
  512. }
  513. //-----------------------------------------------------------------------------
  514. void CAI_Enemies::SetUnforgettable( CBaseEntity *pEnemy, bool bUnforgettable )
  515. {
  516. AI_EnemyInfo_t *pMemory = Find( pEnemy );
  517. if ( pMemory )
  518. pMemory->bUnforgettable = bUnforgettable;
  519. }
  520. //-----------------------------------------------------------------------------
  521. void CAI_Enemies::SetMobbedMe( CBaseEntity *pEnemy, bool bMobbedMe )
  522. {
  523. AI_EnemyInfo_t *pMemory = Find( pEnemy );
  524. if ( pMemory )
  525. pMemory->bMobbedMe = bMobbedMe;
  526. }
  527. //-----------------------------------------------------------------------------
  528. void CAI_Enemies::SetFreeKnowledgeDuration( float flDuration )
  529. {
  530. m_flFreeKnowledgeDuration = flDuration;
  531. if ( m_flFreeKnowledgeDuration >= m_flEnemyDiscardTime )
  532. {
  533. // If your free knowledge time is greater than your discard time,
  534. // you'll forget about secondhand enemies passed to you by squadmates
  535. // as soon as you're given them.
  536. Assert( m_flFreeKnowledgeDuration < m_flEnemyDiscardTime );
  537. m_flFreeKnowledgeDuration = m_flEnemyDiscardTime - .1;
  538. }
  539. }
  540. //-----------------------------------------------------------------------------
  541. void CAI_Enemies::SetEnemyDiscardTime( float flTime )
  542. {
  543. m_flEnemyDiscardTime = flTime;
  544. if ( m_flFreeKnowledgeDuration >= m_flEnemyDiscardTime )
  545. {
  546. // If your free knowledge time is greater than your discard time,
  547. // you'll forget about secondhand enemies passed to you by squadmates
  548. // as soon as you're given them.
  549. Assert( m_flFreeKnowledgeDuration < m_flEnemyDiscardTime );
  550. m_flFreeKnowledgeDuration = m_flEnemyDiscardTime - .1;
  551. }
  552. }