Counter Strike : Global Offensive Source Code
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.

280 lines
5.7 KiB

  1. //========= Copyright � 1996-2005, 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. SetContextThink( &CAI_GoalEntity::DelayedRefresh, gpGlobals->curtime + 0.1f, "Refresh" );
  35. }
  36. //-------------------------------------
  37. void CAI_GoalEntity::OnRestore()
  38. {
  39. BaseClass::OnRestore();
  40. ExitDormant();
  41. if ( ( m_flags & ACTIVE ) )
  42. gEntList.AddListenerEntity( this );
  43. }
  44. //-------------------------------------
  45. void CAI_GoalEntity::DelayedRefresh()
  46. {
  47. inputdata_t ignored;
  48. if ( m_fStartActive )
  49. {
  50. Assert( !(m_flags & ACTIVE) );
  51. InputActivate( ignored );
  52. m_fStartActive = false;
  53. }
  54. else
  55. InputUpdateActors( ignored );
  56. SetContextThink( NULL, 0, "Refresh" );
  57. }
  58. //-------------------------------------
  59. void CAI_GoalEntity::PruneActors()
  60. {
  61. for ( int i = m_actors.Count() - 1; i >= 0; i-- )
  62. {
  63. if ( m_actors[i] == NULL || m_actors[i]->IsMarkedForDeletion() || m_actors[i]->GetState() == NPC_STATE_DEAD )
  64. m_actors.FastRemove( i );
  65. }
  66. }
  67. //-------------------------------------
  68. void CAI_GoalEntity::ResolveNames()
  69. {
  70. m_actors.SetCount( 0 );
  71. CBaseEntity *pEntity = NULL;
  72. for (;;)
  73. {
  74. switch ( m_SearchType )
  75. {
  76. case ST_ENTNAME:
  77. {
  78. pEntity = gEntList.FindEntityByName( pEntity, m_iszActor );
  79. break;
  80. }
  81. case ST_CLASSNAME:
  82. {
  83. pEntity = gEntList.FindEntityByClassname( pEntity, STRING( m_iszActor ) );
  84. break;
  85. }
  86. }
  87. if ( !pEntity )
  88. break;
  89. CAI_BaseNPC *pActor = pEntity->MyNPCPointer();
  90. if ( pActor && pActor->GetState() != NPC_STATE_DEAD )
  91. {
  92. AIHANDLE temp;
  93. temp = pActor;
  94. m_actors.AddToTail( temp );
  95. }
  96. }
  97. m_hGoalEntity = gEntList.FindEntityByName( NULL, m_iszGoal );
  98. }
  99. //-------------------------------------
  100. void CAI_GoalEntity::InputActivate( inputdata_t &inputdata )
  101. {
  102. if ( !( m_flags & ACTIVE ) )
  103. {
  104. OnActivate();
  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. OnDeactivate();
  150. gEntList.RemoveListenerEntity( this );
  151. UpdateActors();
  152. m_flags &= ~ACTIVE;
  153. for ( int i = 0; i < m_actors.Count(); i++ )
  154. {
  155. DisableGoal( m_actors[i] );
  156. }
  157. }
  158. }
  159. //-------------------------------------
  160. void CAI_GoalEntity::EnterDormant( void )
  161. {
  162. if ( m_flags & ACTIVE )
  163. {
  164. m_flags |= DORMANT;
  165. for ( int i = 0; i < m_actors.Count(); i++ )
  166. {
  167. DisableGoal( m_actors[i] );
  168. }
  169. }
  170. }
  171. //-------------------------------------
  172. void CAI_GoalEntity::ExitDormant( void )
  173. {
  174. if ( m_flags & DORMANT )
  175. {
  176. m_flags &= ~DORMANT;
  177. inputdata_t ignored;
  178. InputUpdateActors( ignored );
  179. }
  180. }
  181. //-------------------------------------
  182. void CAI_GoalEntity::UpdateOnRemove()
  183. {
  184. if ( m_flags & ACTIVE )
  185. {
  186. inputdata_t inputdata;
  187. InputDeactivate( inputdata );
  188. }
  189. BaseClass::UpdateOnRemove();
  190. }
  191. //-------------------------------------
  192. void CAI_GoalEntity::OnEntityCreated( CBaseEntity *pEntity )
  193. {
  194. Assert( m_flags & ACTIVE );
  195. if ( pEntity->MyNPCPointer() )
  196. {
  197. SetContextThink( &CAI_GoalEntity::DelayedRefresh, gpGlobals->curtime + 0.1f, "Refresh" );
  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. }