Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.

279 lines
5.6 KiB

5 years ago
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "utlrbtree.h"
#include "saverestore_utlvector.h"
#include "ai_goalentity.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
//
// CAI_GoalEntity implementation
//
BEGIN_DATADESC( CAI_GoalEntity )
DEFINE_KEYFIELD( m_iszActor, FIELD_STRING, "Actor" ),
DEFINE_KEYFIELD( m_iszGoal, FIELD_STRING, "Goal" ),
DEFINE_KEYFIELD( m_fStartActive, FIELD_BOOLEAN, "StartActive" ),
DEFINE_KEYFIELD( m_iszConceptModifiers, FIELD_STRING, "BaseConceptModifiers" ),
DEFINE_KEYFIELD( m_SearchType, FIELD_INTEGER, "SearchType" ),
DEFINE_UTLVECTOR( m_actors, FIELD_EHANDLE ),
DEFINE_FIELD( m_hGoalEntity, FIELD_EHANDLE ),
DEFINE_FIELD( m_flags, FIELD_INTEGER ),
DEFINE_THINKFUNC( DelayedRefresh ),
// Inputs
DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ),
DEFINE_INPUTFUNC( FIELD_VOID, "UpdateActors", InputUpdateActors ),
DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ),
END_DATADESC()
//-------------------------------------
void CAI_GoalEntity::Spawn()
{
SetThink( &CAI_GoalEntity::DelayedRefresh );
SetNextThink( gpGlobals->curtime + 0.1f );
}
//-------------------------------------
void CAI_GoalEntity::OnRestore()
{
BaseClass::OnRestore();
ExitDormant();
if ( ( m_flags & ACTIVE ) )
gEntList.AddListenerEntity( this );
}
//-------------------------------------
void CAI_GoalEntity::DelayedRefresh()
{
inputdata_t ignored;
if ( m_fStartActive )
{
Assert( !(m_flags & ACTIVE) );
InputActivate( ignored );
m_fStartActive = false;
}
else
InputUpdateActors( ignored );
SetThink( NULL );
}
//-------------------------------------
void CAI_GoalEntity::PruneActors()
{
for ( int i = m_actors.Count() - 1; i >= 0; i-- )
{
if ( m_actors[i] == NULL || m_actors[i]->IsMarkedForDeletion() || m_actors[i]->GetState() == NPC_STATE_DEAD )
m_actors.FastRemove( i );
}
}
//-------------------------------------
void CAI_GoalEntity::ResolveNames()
{
m_actors.SetCount( 0 );
CBaseEntity *pEntity = NULL;
for (;;)
{
switch ( m_SearchType )
{
case ST_ENTNAME:
{
pEntity = gEntList.FindEntityByName( pEntity, m_iszActor );
break;
}
case ST_CLASSNAME:
{
pEntity = gEntList.FindEntityByClassname( pEntity, STRING( m_iszActor ) );
break;
}
}
if ( !pEntity )
break;
CAI_BaseNPC *pActor = pEntity->MyNPCPointer();
if ( pActor && pActor->GetState() != NPC_STATE_DEAD )
{
AIHANDLE temp;
temp = pActor;
m_actors.AddToTail( temp );
}
}
m_hGoalEntity = gEntList.FindEntityByName( NULL, m_iszGoal );
}
//-------------------------------------
void CAI_GoalEntity::InputActivate( inputdata_t &inputdata )
{
if ( !( m_flags & ACTIVE ) )
{
gEntList.AddListenerEntity( this );
UpdateActors();
m_flags |= ACTIVE;
for ( int i = 0; i < m_actors.Count(); i++ )
{
EnableGoal( m_actors[i] );
}
}
}
//-------------------------------------
void CAI_GoalEntity::InputUpdateActors( inputdata_t &inputdata )
{
int i;
CUtlRBTree<CAI_BaseNPC *> prevActors;
CUtlRBTree<CAI_BaseNPC *>::IndexType_t index;
SetDefLessFunc( prevActors );
PruneActors();
for ( i = 0; i < m_actors.Count(); i++ )
{
prevActors.Insert( m_actors[i] );
}
ResolveNames();
for ( i = 0; i < m_actors.Count(); i++ )
{
index = prevActors.Find( m_actors[i] );
if ( index == prevActors.InvalidIndex() )
{
if ( m_flags & ACTIVE )
EnableGoal( m_actors[i] );
}
else
prevActors.Remove( m_actors[i] );
}
for ( index = prevActors.FirstInorder(); index != prevActors.InvalidIndex(); index = prevActors.NextInorder( index ) )
{
if ( m_flags & ACTIVE )
DisableGoal( prevActors[ index ] );
}
}
//-------------------------------------
void CAI_GoalEntity::InputDeactivate( inputdata_t &inputdata )
{
if ( m_flags & ACTIVE )
{
gEntList.RemoveListenerEntity( this );
UpdateActors();
m_flags &= ~ACTIVE;
for ( int i = 0; i < m_actors.Count(); i++ )
{
DisableGoal( m_actors[i] );
}
}
}
//-------------------------------------
void CAI_GoalEntity::EnterDormant( void )
{
if ( m_flags & ACTIVE )
{
m_flags |= DORMANT;
for ( int i = 0; i < m_actors.Count(); i++ )
{
DisableGoal( m_actors[i] );
}
}
}
//-------------------------------------
void CAI_GoalEntity::ExitDormant( void )
{
if ( m_flags & DORMANT )
{
m_flags &= ~DORMANT;
inputdata_t ignored;
InputUpdateActors( ignored );
}
}
//-------------------------------------
void CAI_GoalEntity::UpdateOnRemove()
{
if ( m_flags & ACTIVE )
{
inputdata_t inputdata;
InputDeactivate( inputdata );
}
BaseClass::UpdateOnRemove();
}
//-------------------------------------
void CAI_GoalEntity::OnEntityCreated( CBaseEntity *pEntity )
{
Assert( m_flags & ACTIVE );
if ( pEntity->MyNPCPointer() )
{
SetThink( &CAI_GoalEntity::DelayedRefresh );
SetNextThink( gpGlobals->curtime + 0.1f );
}
}
//-------------------------------------
void CAI_GoalEntity::OnEntityDeleted( CBaseEntity *pEntity )
{
Assert( pEntity != this );
}
//-----------------------------------------------------------------------------
int CAI_GoalEntity::DrawDebugTextOverlays()
{
char tempstr[512];
int offset = BaseClass::DrawDebugTextOverlays();
Q_snprintf( tempstr, sizeof(tempstr), "Active: %s", IsActive() ? "yes" : "no" );
EntityText( offset, tempstr, 0 );
offset++;
return offset;
}