Team Fortress 2 Source Code as on 22/4/2020
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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "utlrbtree.h"
  8. #include "saverestore_utlvector.h"
  9. #include "ai_goalentity.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include "tier0/memdbgon.h"
  12. //-----------------------------------------------------------------------------
  13. //
  14. // CAI_GoalEntity implementation
  15. //
  16. BEGIN_DATADESC( CAI_GoalEntity )
  17. DEFINE_KEYFIELD( m_iszActor, FIELD_STRING, "Actor" ),
  18. DEFINE_KEYFIELD( m_iszGoal, FIELD_STRING, "Goal" ),
  19. DEFINE_KEYFIELD( m_fStartActive, FIELD_BOOLEAN, "StartActive" ),
  20. DEFINE_KEYFIELD( m_iszConceptModifiers, FIELD_STRING, "BaseConceptModifiers" ),
  21. DEFINE_KEYFIELD( m_SearchType, FIELD_INTEGER, "SearchType" ),
  22. DEFINE_UTLVECTOR( m_actors, FIELD_EHANDLE ),
  23. DEFINE_FIELD( m_hGoalEntity, FIELD_EHANDLE ),
  24. DEFINE_FIELD( m_flags, FIELD_INTEGER ),
  25. DEFINE_THINKFUNC( DelayedRefresh ),
  26. // Inputs
  27. DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ),
  28. DEFINE_INPUTFUNC( FIELD_VOID, "UpdateActors", InputUpdateActors ),
  29. DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ),
  30. END_DATADESC()
  31. //-------------------------------------
  32. void CAI_GoalEntity::Spawn()
  33. {
  34. SetThink( &CAI_GoalEntity::DelayedRefresh );
  35. SetNextThink( gpGlobals->curtime + 0.1f );
  36. }
  37. //-------------------------------------
  38. void CAI_GoalEntity::OnRestore()
  39. {
  40. BaseClass::OnRestore();
  41. ExitDormant();
  42. if ( ( m_flags & ACTIVE ) )
  43. gEntList.AddListenerEntity( this );
  44. }
  45. //-------------------------------------
  46. void CAI_GoalEntity::DelayedRefresh()
  47. {
  48. inputdata_t ignored;
  49. if ( m_fStartActive )
  50. {
  51. Assert( !(m_flags & ACTIVE) );
  52. InputActivate( ignored );
  53. m_fStartActive = false;
  54. }
  55. else
  56. InputUpdateActors( ignored );
  57. SetThink( NULL );
  58. }
  59. //-------------------------------------
  60. void CAI_GoalEntity::PruneActors()
  61. {
  62. for ( int i = m_actors.Count() - 1; i >= 0; i-- )
  63. {
  64. if ( m_actors[i] == NULL || m_actors[i]->IsMarkedForDeletion() || m_actors[i]->GetState() == NPC_STATE_DEAD )
  65. m_actors.FastRemove( i );
  66. }
  67. }
  68. //-------------------------------------
  69. void CAI_GoalEntity::ResolveNames()
  70. {
  71. m_actors.SetCount( 0 );
  72. CBaseEntity *pEntity = NULL;
  73. for (;;)
  74. {
  75. switch ( m_SearchType )
  76. {
  77. case ST_ENTNAME:
  78. {
  79. pEntity = gEntList.FindEntityByName( pEntity, m_iszActor );
  80. break;
  81. }
  82. case ST_CLASSNAME:
  83. {
  84. pEntity = gEntList.FindEntityByClassname( pEntity, STRING( m_iszActor ) );
  85. break;
  86. }
  87. }
  88. if ( !pEntity )
  89. break;
  90. CAI_BaseNPC *pActor = pEntity->MyNPCPointer();
  91. if ( pActor && pActor->GetState() != NPC_STATE_DEAD )
  92. {
  93. AIHANDLE temp;
  94. temp = pActor;
  95. m_actors.AddToTail( temp );
  96. }
  97. }
  98. m_hGoalEntity = gEntList.FindEntityByName( NULL, m_iszGoal );
  99. }
  100. //-------------------------------------
  101. void CAI_GoalEntity::InputActivate( inputdata_t &inputdata )
  102. {
  103. if ( !( m_flags & ACTIVE ) )
  104. {
  105. gEntList.AddListenerEntity( this );
  106. UpdateActors();
  107. m_flags |= ACTIVE;
  108. for ( int i = 0; i < m_actors.Count(); i++ )
  109. {
  110. EnableGoal( m_actors[i] );
  111. }
  112. }
  113. }
  114. //-------------------------------------
  115. void CAI_GoalEntity::InputUpdateActors( inputdata_t &inputdata )
  116. {
  117. int i;
  118. CUtlRBTree<CAI_BaseNPC *> prevActors;
  119. CUtlRBTree<CAI_BaseNPC *>::IndexType_t index;
  120. SetDefLessFunc( prevActors );
  121. PruneActors();
  122. for ( i = 0; i < m_actors.Count(); i++ )
  123. {
  124. prevActors.Insert( m_actors[i] );
  125. }
  126. ResolveNames();
  127. for ( i = 0; i < m_actors.Count(); i++ )
  128. {
  129. index = prevActors.Find( m_actors[i] );
  130. if ( index == prevActors.InvalidIndex() )
  131. {
  132. if ( m_flags & ACTIVE )
  133. EnableGoal( m_actors[i] );
  134. }
  135. else
  136. prevActors.Remove( m_actors[i] );
  137. }
  138. for ( index = prevActors.FirstInorder(); index != prevActors.InvalidIndex(); index = prevActors.NextInorder( index ) )
  139. {
  140. if ( m_flags & ACTIVE )
  141. DisableGoal( prevActors[ index ] );
  142. }
  143. }
  144. //-------------------------------------
  145. void CAI_GoalEntity::InputDeactivate( inputdata_t &inputdata )
  146. {
  147. if ( m_flags & ACTIVE )
  148. {
  149. gEntList.RemoveListenerEntity( this );
  150. UpdateActors();
  151. m_flags &= ~ACTIVE;
  152. for ( int i = 0; i < m_actors.Count(); i++ )
  153. {
  154. DisableGoal( m_actors[i] );
  155. }
  156. }
  157. }
  158. //-------------------------------------
  159. void CAI_GoalEntity::EnterDormant( void )
  160. {
  161. if ( m_flags & ACTIVE )
  162. {
  163. m_flags |= DORMANT;
  164. for ( int i = 0; i < m_actors.Count(); i++ )
  165. {
  166. DisableGoal( m_actors[i] );
  167. }
  168. }
  169. }
  170. //-------------------------------------
  171. void CAI_GoalEntity::ExitDormant( void )
  172. {
  173. if ( m_flags & DORMANT )
  174. {
  175. m_flags &= ~DORMANT;
  176. inputdata_t ignored;
  177. InputUpdateActors( ignored );
  178. }
  179. }
  180. //-------------------------------------
  181. void CAI_GoalEntity::UpdateOnRemove()
  182. {
  183. if ( m_flags & ACTIVE )
  184. {
  185. inputdata_t inputdata;
  186. InputDeactivate( inputdata );
  187. }
  188. BaseClass::UpdateOnRemove();
  189. }
  190. //-------------------------------------
  191. void CAI_GoalEntity::OnEntityCreated( CBaseEntity *pEntity )
  192. {
  193. Assert( m_flags & ACTIVE );
  194. if ( pEntity->MyNPCPointer() )
  195. {
  196. SetThink( &CAI_GoalEntity::DelayedRefresh );
  197. SetNextThink( gpGlobals->curtime + 0.1f );
  198. }
  199. }
  200. //-------------------------------------
  201. void CAI_GoalEntity::OnEntityDeleted( CBaseEntity *pEntity )
  202. {
  203. Assert( pEntity != this );
  204. }
  205. //-----------------------------------------------------------------------------
  206. int CAI_GoalEntity::DrawDebugTextOverlays()
  207. {
  208. char tempstr[512];
  209. int offset = BaseClass::DrawDebugTextOverlays();
  210. Q_snprintf( tempstr, sizeof(tempstr), "Active: %s", IsActive() ? "yes" : "no" );
  211. EntityText( offset, tempstr, 0 );
  212. offset++;
  213. return offset;
  214. }