diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/server/ai_memory.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/server/ai_memory.cpp')
| -rw-r--r-- | mp/src/game/server/ai_memory.cpp | 656 |
1 files changed, 656 insertions, 0 deletions
diff --git a/mp/src/game/server/ai_memory.cpp b/mp/src/game/server/ai_memory.cpp new file mode 100644 index 00000000..2464a825 --- /dev/null +++ b/mp/src/game/server/ai_memory.cpp @@ -0,0 +1,656 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: An NPC's memory of potential enemies
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "isaverestore.h"
+#include "ai_debug.h"
+#include "ai_memory.h"
+#include "ai_basenpc.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+#define EMEMORY_POOL_SIZE 64
+#define AI_FREE_KNOWLEDGE_DURATION 1.75
+
+//-----------------------------------------------------------------------------
+// AI_EnemyInfo_t
+//
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+
+AI_EnemyInfo_t::AI_EnemyInfo_t(void)
+{
+ hEnemy = NULL;
+ vLastKnownLocation = vec3_origin;
+ vLastSeenLocation = vec3_origin;
+ timeLastSeen = 0;
+ timeFirstSeen = 0;
+ timeLastReacquired = 0;
+ timeValidEnemy = 0;
+ timeLastReceivedDamageFrom = 0;
+ timeAtFirstHand = AI_INVALID_TIME;
+ bDangerMemory = 0;
+ bEludedMe = 0;
+ bUnforgettable = 0;
+ bMobbedMe = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// CAI_EnemiesListSaveRestoreOps
+//
+// Purpose: Handles save and load for enemy memories
+//
+//-----------------------------------------------------------------------------
+
+class CAI_EnemiesListSaveRestoreOps : public CDefSaveRestoreOps
+{
+public:
+ CAI_EnemiesListSaveRestoreOps()
+ {
+ }
+
+ virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave )
+ {
+ CAI_Enemies::CMemMap *pMemMap = (CAI_Enemies::CMemMap *)fieldInfo.pField;
+
+ int nMemories = pMemMap->Count();
+ pSave->WriteInt( &nMemories );
+
+ for ( CAI_Enemies::CMemMap::IndexType_t i = pMemMap->FirstInorder(); i != pMemMap->InvalidIndex(); i = pMemMap->NextInorder( i ) )
+ {
+ pSave->WriteAll( (*pMemMap)[i] );
+ }
+ }
+
+ virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore )
+ {
+ CAI_Enemies::CMemMap *pMemMap = (CAI_Enemies::CMemMap *)fieldInfo.pField;
+ Assert( pMemMap->Count() == 0 );
+
+ int nMemories = pRestore->ReadInt();
+
+ while ( nMemories-- )
+ {
+ AI_EnemyInfo_t *pAddMemory = new AI_EnemyInfo_t;
+
+ pRestore->ReadAll( pAddMemory );
+
+ if ( pAddMemory->hEnemy != NULL )
+ {
+ pMemMap->Insert( pAddMemory->hEnemy, pAddMemory );
+ }
+ else
+ delete pAddMemory;
+ }
+ }
+
+ virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo )
+ {
+ CAI_Enemies::CMemMap *pMemMap = (CAI_Enemies::CMemMap *)fieldInfo.pField;
+
+ for ( CAI_Enemies::CMemMap::IndexType_t i = pMemMap->FirstInorder(); i != pMemMap->InvalidIndex(); i = pMemMap->NextInorder( i ) )
+ {
+ delete (*pMemMap)[i];
+ }
+
+ pMemMap->RemoveAll();
+ }
+
+ virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo )
+ {
+ CAI_Enemies::CMemMap *pMemMap = (CAI_Enemies::CMemMap *)fieldInfo.pField;
+ return ( pMemMap->Count() == 0 );
+ }
+
+} g_AI_MemoryListSaveRestoreOps;
+
+//-----------------------------------------------------------------------------
+// CAI_Enemies
+//
+// Purpose: Stores a set of AI_EnemyInfo_t's
+//
+//-----------------------------------------------------------------------------
+
+BEGIN_SIMPLE_DATADESC( CAI_Enemies )
+
+ DEFINE_CUSTOM_FIELD( m_Map, &g_AI_MemoryListSaveRestoreOps ),
+ DEFINE_FIELD( m_flFreeKnowledgeDuration, FIELD_FLOAT ),
+ DEFINE_FIELD( m_flEnemyDiscardTime, FIELD_FLOAT ),
+ DEFINE_FIELD( m_vecDefaultLKP, FIELD_POSITION_VECTOR ),
+ DEFINE_FIELD( m_vecDefaultLSP, FIELD_POSITION_VECTOR ),
+ DEFINE_FIELD( m_serial, FIELD_INTEGER ),
+
+END_DATADESC()
+
+BEGIN_SIMPLE_DATADESC( AI_EnemyInfo_t )
+ DEFINE_FIELD( vLastKnownLocation, FIELD_POSITION_VECTOR ),
+ DEFINE_FIELD( vLastSeenLocation, FIELD_POSITION_VECTOR ),
+ DEFINE_FIELD( hEnemy, FIELD_EHANDLE ),
+ DEFINE_FIELD( timeLastSeen, FIELD_TIME ),
+ DEFINE_FIELD( timeFirstSeen, FIELD_TIME ),
+ DEFINE_FIELD( timeLastReacquired, FIELD_TIME ),
+ DEFINE_FIELD( timeValidEnemy, FIELD_TIME ),
+ DEFINE_FIELD( timeLastReceivedDamageFrom, FIELD_TIME ),
+ DEFINE_FIELD( timeAtFirstHand, FIELD_TIME ),
+ DEFINE_FIELD( bDangerMemory, FIELD_BOOLEAN ),
+ DEFINE_FIELD( bEludedMe, FIELD_BOOLEAN ),
+ DEFINE_FIELD( bUnforgettable, FIELD_BOOLEAN ),
+ DEFINE_FIELD( bMobbedMe, FIELD_BOOLEAN ),
+ // NOT SAVED nextEMemory
+END_DATADESC()
+
+//-----------------------------------------------------------------------------
+
+CAI_Enemies::CAI_Enemies(void)
+{
+ m_flFreeKnowledgeDuration = AI_FREE_KNOWLEDGE_DURATION;
+ m_flEnemyDiscardTime = AI_DEF_ENEMY_DISCARD_TIME;
+ m_vecDefaultLKP = vec3_invalid;
+ m_vecDefaultLSP = vec3_invalid;
+ m_serial = 0;
+ SetDefLessFunc( m_Map );
+}
+
+
+//-----------------------------------------------------------------------------
+
+CAI_Enemies::~CAI_Enemies()
+{
+ for ( CMemMap::IndexType_t i = m_Map.FirstInorder(); i != m_Map.InvalidIndex(); i = m_Map.NextInorder( i ) )
+ {
+ delete m_Map[i];
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Purges any dead enemies from memory
+//-----------------------------------------------------------------------------
+
+AI_EnemyInfo_t *CAI_Enemies::GetFirst( AIEnemiesIter_t *pIter )
+{
+ CMemMap::IndexType_t i = m_Map.FirstInorder();
+ *pIter = (AIEnemiesIter_t)(unsigned)i;
+
+ if ( i == m_Map.InvalidIndex() )
+ return NULL;
+
+ if ( m_Map[i]->hEnemy == NULL )
+ return GetNext( pIter );
+
+ return m_Map[i];
+}
+
+//-----------------------------------------------------------------------------
+
+AI_EnemyInfo_t *CAI_Enemies::GetNext( AIEnemiesIter_t *pIter )
+{
+ CMemMap::IndexType_t i = (CMemMap::IndexType_t)((unsigned)(*pIter));
+
+ if ( i == m_Map.InvalidIndex() )
+ return NULL;
+
+ i = m_Map.NextInorder( i );
+ *pIter = (AIEnemiesIter_t)(unsigned)i;
+ if ( i == m_Map.InvalidIndex() )
+ return NULL;
+
+ if ( m_Map[i]->hEnemy == NULL )
+ return GetNext( pIter );
+
+ return m_Map[i];
+}
+
+//-----------------------------------------------------------------------------
+
+AI_EnemyInfo_t *CAI_Enemies::Find( CBaseEntity *pEntity, bool bTryDangerMemory )
+{
+ if ( pEntity == AI_UNKNOWN_ENEMY )
+ pEntity = NULL;
+
+ CMemMap::IndexType_t i = m_Map.Find( pEntity );
+ if ( i == m_Map.InvalidIndex() )
+ {
+ if ( !bTryDangerMemory || ( i = m_Map.Find( NULL ) ) == m_Map.InvalidIndex() )
+ return NULL;
+ Assert(m_Map[i]->bDangerMemory == true);
+ }
+ return m_Map[i];
+}
+
+
+//-----------------------------------------------------------------------------
+
+AI_EnemyInfo_t *CAI_Enemies::GetDangerMemory()
+{
+ CMemMap::IndexType_t i = m_Map.Find( NULL );
+ if ( i == m_Map.InvalidIndex() )
+ return NULL;
+ Assert(m_Map[i]->bDangerMemory == true);
+ return m_Map[i];
+}
+
+//-----------------------------------------------------------------------------
+
+bool CAI_Enemies::ShouldDiscardMemory( AI_EnemyInfo_t *pMemory )
+{
+ CBaseEntity *pEnemy = pMemory->hEnemy;
+
+ if ( pEnemy )
+ {
+ CAI_BaseNPC *pEnemyNPC = pEnemy->MyNPCPointer();
+ if ( pEnemyNPC && pEnemyNPC->GetState() == NPC_STATE_DEAD )
+ return true;
+ }
+ else
+ {
+ if ( !pMemory->bDangerMemory )
+ return true;
+ }
+
+ if ( !pMemory->bUnforgettable &&
+ gpGlobals->curtime > pMemory->timeLastSeen + m_flEnemyDiscardTime )
+ {
+ return true;
+ }
+
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+
+void CAI_Enemies::RefreshMemories(void)
+{
+ AI_PROFILE_SCOPE(CAI_Enemies_RefreshMemories);
+
+ if ( m_flFreeKnowledgeDuration >= m_flEnemyDiscardTime )
+ {
+ m_flFreeKnowledgeDuration = m_flEnemyDiscardTime - .1;
+ }
+
+ // -------------------
+ // Check each record
+ // -------------------
+
+ CMemMap::IndexType_t i = m_Map.FirstInorder();
+ while ( i != m_Map.InvalidIndex() )
+ {
+ AI_EnemyInfo_t *pMemory = m_Map[i];
+
+ CMemMap::IndexType_t iNext = m_Map.NextInorder( i ); // save so can remove
+ if ( ShouldDiscardMemory( pMemory ) )
+ {
+ delete pMemory;
+ m_Map.RemoveAt(i);
+ }
+ else if ( pMemory->hEnemy )
+ {
+ if ( gpGlobals->curtime <= pMemory->timeLastSeen + m_flFreeKnowledgeDuration )
+ {
+ // Free knowledge is ignored if the target has notarget on
+ if ( !(pMemory->hEnemy->GetFlags() & FL_NOTARGET) )
+ {
+ pMemory->vLastKnownLocation = pMemory->hEnemy->GetAbsOrigin();
+ }
+ }
+
+ if ( gpGlobals->curtime <= pMemory->timeLastSeen )
+ {
+ pMemory->vLastSeenLocation = pMemory->hEnemy->GetAbsOrigin();
+ }
+ }
+ i = iNext;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Updates information about our enemies
+// Output : Returns true if new enemy, false if already know of enemy
+//-----------------------------------------------------------------------------
+
+bool CAI_Enemies::UpdateMemory(CAI_Network* pAINet, CBaseEntity *pEnemy, const Vector &vPosition, float reactionDelay, bool firstHand )
+{
+ if ( pEnemy == AI_UNKNOWN_ENEMY )
+ pEnemy = NULL;
+
+ const float DIST_TRIGGER_REACQUIRE_SQ = Square(20.0 * 12.0);
+ const float TIME_TRIGGER_REACQUIRE = 4.0;
+ const float MIN_DIST_TIME_TRIGGER_REACQUIRE_SQ = Square(4.0 * 12.0);
+
+ AI_EnemyInfo_t *pMemory = Find( pEnemy );
+ // -------------------------------------------
+ // Otherwise just update my own
+ // -------------------------------------------
+ // Update enemy information
+ if ( pMemory )
+ {
+ Assert(pEnemy || pMemory->bDangerMemory == true);
+
+ if ( firstHand )
+ pMemory->timeLastSeen = gpGlobals->curtime;
+ pMemory->bEludedMe = false;
+
+ float deltaDist = (pMemory->vLastKnownLocation - vPosition).LengthSqr();
+
+ if (deltaDist>DIST_TRIGGER_REACQUIRE_SQ || ( deltaDist>MIN_DIST_TIME_TRIGGER_REACQUIRE_SQ && ( gpGlobals->curtime - pMemory->timeLastSeen ) > TIME_TRIGGER_REACQUIRE ) )
+ {
+ pMemory->timeLastReacquired = gpGlobals->curtime;
+ }
+
+ // Only update if the enemy has moved
+ if (deltaDist>Square(12.0))
+ {
+ pMemory->vLastKnownLocation = vPosition;
+
+ }
+
+ // Update the time at which we first saw him firsthand
+ if ( firstHand && pMemory->timeAtFirstHand == AI_INVALID_TIME )
+ {
+ pMemory->timeAtFirstHand = gpGlobals->curtime;
+ }
+
+ return false;
+ }
+
+ // If not on my list of enemies add it
+ AI_EnemyInfo_t *pAddMemory = new AI_EnemyInfo_t;
+ pAddMemory->vLastKnownLocation = vPosition;
+
+ if ( firstHand )
+ {
+ pAddMemory->timeLastReacquired = pAddMemory->timeFirstSeen = pAddMemory->timeLastSeen = pAddMemory->timeAtFirstHand = gpGlobals->curtime;
+ }
+ else
+ {
+ // Block free knowledge
+ pAddMemory->timeLastReacquired = pAddMemory->timeFirstSeen = pAddMemory->timeLastSeen = ( gpGlobals->curtime - (m_flFreeKnowledgeDuration + 0.01) );
+ pAddMemory->timeAtFirstHand = AI_INVALID_TIME;
+ }
+
+ if ( reactionDelay > 0.0 )
+ pAddMemory->timeValidEnemy = gpGlobals->curtime + reactionDelay;
+
+ pAddMemory->bEludedMe = false;
+
+ // I'm either remembering a postion of an enmey of just a danger position
+ pAddMemory->hEnemy = pEnemy;
+ pAddMemory->bDangerMemory = ( pEnemy == NULL );
+
+ // add to the list
+ m_Map.Insert( pEnemy, pAddMemory );
+ m_serial++;
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+// Purpose : Returns true if this enemy is part of my memory
+//------------------------------------------------------------------------------
+void CAI_Enemies::OnTookDamageFrom( CBaseEntity *pEnemy )
+{
+ AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
+ if ( pMemory )
+ pMemory->timeLastReceivedDamageFrom = gpGlobals->curtime;
+}
+
+//------------------------------------------------------------------------------
+// Purpose : Returns true if this enemy is part of my memory
+//------------------------------------------------------------------------------
+bool CAI_Enemies::HasMemory( CBaseEntity *pEnemy )
+{
+ return ( Find( pEnemy ) != NULL );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Clear information about our enemy
+//-----------------------------------------------------------------------------
+void CAI_Enemies::ClearMemory(CBaseEntity *pEnemy)
+{
+ CMemMap::IndexType_t i = m_Map.Find( pEnemy );
+ if ( i != m_Map.InvalidIndex() )
+ {
+ delete m_Map[i];
+ m_Map.RemoveAt( i );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Notes that the given enemy has eluded me
+//-----------------------------------------------------------------------------
+void CAI_Enemies::MarkAsEluded( CBaseEntity *pEnemy )
+{
+ AI_EnemyInfo_t *pMemory = Find( pEnemy );
+ if ( pMemory )
+ {
+ pMemory->bEludedMe = true;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns last known posiiton of given enemy
+//-----------------------------------------------------------------------------
+const Vector &CAI_Enemies::LastKnownPosition( CBaseEntity *pEnemy )
+{
+ AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
+ if ( pMemory )
+ {
+ m_vecDefaultLKP = pMemory->vLastKnownLocation;
+ }
+ else
+ {
+ DevWarning( 2,"Asking LastKnownPosition for enemy that's not in my memory!!\n");
+ }
+ return m_vecDefaultLKP;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the last position the enemy was SEEN at. This will always be
+// different than LastKnownPosition() when the enemy is out of sight, because
+// the last KNOWN position will be updated for a number of seconds after the
+// player disappears.
+//-----------------------------------------------------------------------------
+const Vector &CAI_Enemies::LastSeenPosition( CBaseEntity *pEnemy )
+{
+ AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
+ if ( pMemory )
+ {
+ m_vecDefaultLSP = pMemory->vLastSeenLocation;
+ }
+ else
+ {
+ DevWarning( 2,"Asking LastSeenPosition for enemy that's not in my memory!!\n");
+ }
+ return m_vecDefaultLSP;
+}
+
+float CAI_Enemies::TimeLastReacquired( CBaseEntity *pEnemy )
+{
+ // I've never seen something that doesn't exist
+ if (!pEnemy)
+ return 0;
+
+ AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
+ if ( pMemory )
+ return pMemory->timeLastReacquired;
+
+ if ( pEnemy != AI_UNKNOWN_ENEMY )
+ DevWarning( 2,"Asking TimeLastReacquired for enemy that's not in my memory!!\n");
+ return AI_INVALID_TIME;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets position to the last known position of an enemy. If enemy
+// was not found returns last memory of danger position if it exists
+// Output : Returns false is no position is known
+//-----------------------------------------------------------------------------
+float CAI_Enemies::LastTimeSeen( CBaseEntity *pEnemy, bool bCheckDangerMemory /*= true*/ )
+{
+ // I've never seen something that doesn't exist
+ if (!pEnemy)
+ return 0;
+
+ AI_EnemyInfo_t *pMemory = Find( pEnemy, bCheckDangerMemory );
+ if ( pMemory )
+ return pMemory->timeLastSeen;
+
+ if ( pEnemy != AI_UNKNOWN_ENEMY )
+ DevWarning( 2,"Asking LastTimeSeen for enemy that's not in my memory!!\n");
+ return AI_INVALID_TIME;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get the time at which the enemy was first seen.
+// Output : Returns false is no position is known
+//-----------------------------------------------------------------------------
+float CAI_Enemies::FirstTimeSeen( CBaseEntity *pEnemy)
+{
+ // I've never seen something that doesn't exist
+ if (!pEnemy)
+ return 0;
+
+ AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
+ if ( pMemory )
+ return pMemory->timeFirstSeen;
+
+ if ( pEnemy != AI_UNKNOWN_ENEMY )
+ DevWarning( 2,"Asking FirstTimeSeen for enemy that's not in my memory!!\n");
+ return AI_INVALID_TIME;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pEnemy -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool CAI_Enemies::HasFreeKnowledgeOf( CBaseEntity *pEnemy )
+{
+ // I've never seen something that doesn't exist
+ if (!pEnemy)
+ return 0;
+
+ AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
+ if ( pMemory )
+ {
+ float flFreeKnowledgeTime = pMemory->timeLastSeen + m_flFreeKnowledgeDuration;
+ return ( gpGlobals->curtime < flFreeKnowledgeTime );
+ }
+
+ if ( pEnemy != AI_UNKNOWN_ENEMY )
+ DevWarning( 2,"Asking HasFreeKnowledgeOf for enemy that's not in my memory!!\n");
+ return AI_INVALID_TIME;
+}
+
+//-----------------------------------------------------------------------------
+float CAI_Enemies::LastTimeTookDamageFrom( CBaseEntity *pEnemy)
+{
+ // I've never seen something that doesn't exist
+ if (!pEnemy)
+ return 0;
+
+ AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
+ if ( pMemory )
+ return pMemory->timeLastReceivedDamageFrom;
+
+ if ( pEnemy != AI_UNKNOWN_ENEMY )
+ DevWarning( 2,"Asking LastTimeTookDamageFrom for enemy that's not in my memory!!\n");
+ return AI_INVALID_TIME;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the time at which the enemy was first seen firsthand
+// Input : *pEnemy -
+// Output : float
+//-----------------------------------------------------------------------------
+float CAI_Enemies::TimeAtFirstHand( CBaseEntity *pEnemy )
+{
+ // I've never seen something that doesn't exist
+ if (!pEnemy)
+ return 0;
+
+ AI_EnemyInfo_t *pMemory = Find( pEnemy, true );
+ if ( pMemory )
+ return pMemory->timeAtFirstHand;
+
+ if ( pEnemy != AI_UNKNOWN_ENEMY )
+ DevWarning( 2,"Asking TimeAtFirstHand for enemy that's not in my memory!!\n");
+ return AI_INVALID_TIME;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets position to the last known position of an enemy. If enemy
+// was not found returns last memory of danger position if it exists
+// Output : Returns false is no position is known
+//-----------------------------------------------------------------------------
+bool CAI_Enemies::HasEludedMe( CBaseEntity *pEnemy )
+{
+ AI_EnemyInfo_t *pMemory = Find( pEnemy );
+ if ( pMemory )
+ return pMemory->bEludedMe;
+ return false;
+}
+
+void CAI_Enemies::SetTimeValidEnemy( CBaseEntity *pEnemy, float flTime )
+{
+ AI_EnemyInfo_t *pMemory = Find( pEnemy );
+ if ( pMemory )
+ pMemory->timeValidEnemy = flTime;
+}
+
+//-----------------------------------------------------------------------------
+void CAI_Enemies::SetUnforgettable( CBaseEntity *pEnemy, bool bUnforgettable )
+{
+ AI_EnemyInfo_t *pMemory = Find( pEnemy );
+ if ( pMemory )
+ pMemory->bUnforgettable = bUnforgettable;
+}
+
+//-----------------------------------------------------------------------------
+void CAI_Enemies::SetMobbedMe( CBaseEntity *pEnemy, bool bMobbedMe )
+{
+ AI_EnemyInfo_t *pMemory = Find( pEnemy );
+ if ( pMemory )
+ pMemory->bMobbedMe = bMobbedMe;
+}
+
+//-----------------------------------------------------------------------------
+
+void CAI_Enemies::SetFreeKnowledgeDuration( float flDuration )
+{
+ m_flFreeKnowledgeDuration = flDuration;
+
+ if ( m_flFreeKnowledgeDuration >= m_flEnemyDiscardTime )
+ {
+ // If your free knowledge time is greater than your discard time,
+ // you'll forget about secondhand enemies passed to you by squadmates
+ // as soon as you're given them.
+ Assert( m_flFreeKnowledgeDuration < m_flEnemyDiscardTime );
+
+ m_flFreeKnowledgeDuration = m_flEnemyDiscardTime - .1;
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+void CAI_Enemies::SetEnemyDiscardTime( float flTime )
+{
+ m_flEnemyDiscardTime = flTime;
+
+ if ( m_flFreeKnowledgeDuration >= m_flEnemyDiscardTime )
+ {
+ // If your free knowledge time is greater than your discard time,
+ // you'll forget about secondhand enemies passed to you by squadmates
+ // as soon as you're given them.
+ Assert( m_flFreeKnowledgeDuration < m_flEnemyDiscardTime );
+
+ m_flFreeKnowledgeDuration = m_flEnemyDiscardTime - .1;
+ }
+}
|