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.
278 lines
5.6 KiB
278 lines
5.6 KiB
//========= 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; |
|
} |
|
|
|
|
|
|