1
This commit is contained in:
278
game/server/ai_goalentity.cpp
Normal file
278
game/server/ai_goalentity.cpp
Normal file
@ -0,0 +1,278 @@
|
||||
//========= 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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user