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.

975 lines
30 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef AI_BEHAVIOR_H
  8. #define AI_BEHAVIOR_H
  9. #include "ai_component.h"
  10. #include "ai_basenpc.h"
  11. #include "ai_default.h"
  12. #include "ai_criteria.h"
  13. #include "networkvar.h"
  14. #include "delegates.h"
  15. #include "tier1/utlvector.h"
  16. #include "generic_classmap.h"
  17. #ifdef DEBUG
  18. #pragma warning(push)
  19. #include <typeinfo>
  20. #pragma warning(pop)
  21. #pragma warning(disable:4290)
  22. #endif
  23. #if defined( _WIN32 )
  24. #pragma once
  25. #endif
  26. //-----------------------------------------------------------------------------
  27. // CAI_Behavior...
  28. //
  29. // Purpose: The core component that defines a behavior in an NPC by selecting
  30. // schedules and running tasks
  31. //
  32. // Intended to be used as an organizational tool as well as a way
  33. // for various NPCs to share behaviors without sharing an inheritance
  34. // relationship, and without cramming those behaviors into the base
  35. // NPC class.
  36. //-----------------------------------------------------------------------------
  37. struct AIChannelScheduleState_t
  38. {
  39. AIChannelScheduleState_t() { memset( this, 0, sizeof( *this ) ); }
  40. bool bActive;
  41. CAI_Schedule * pSchedule;
  42. int idealSchedule;
  43. int failSchedule;
  44. int iCurTask;
  45. TaskStatus_e fTaskStatus;
  46. float timeStarted;
  47. float timeCurTaskStarted;
  48. AI_TaskFailureCode_t taskFailureCode;
  49. bool bScheduleWasInterrupted;
  50. DECLARE_SIMPLE_DATADESC();
  51. };
  52. //-----------------------------------------------------------------------------
  53. // Purpose: Base class defines interface to behaviors and provides bridging
  54. // methods
  55. //-----------------------------------------------------------------------------
  56. class CAI_BehaviorBase : public CAI_Component, public IAI_BehaviorBridge
  57. {
  58. DECLARE_CLASS( CAI_BehaviorBase, CAI_Component )
  59. public:
  60. CAI_BehaviorBase(CAI_BaseNPC *pOuter = NULL)
  61. : CAI_Component(pOuter),
  62. m_pBackBridge(NULL)
  63. {
  64. m_bAllocated = false;
  65. }
  66. void SetAllocated( ) { m_bAllocated = true; }
  67. bool IsAllocated( ) { return m_bAllocated; }
  68. #define AI_GENERATE_BEHAVIOR_BRIDGES
  69. #include "ai_behavior_template.h"
  70. #define AI_GENERATE_BASE_METHODS
  71. #include "ai_behavior_template.h"
  72. virtual const char *GetClassNameV() { return ""; }
  73. virtual const char *GetName() = 0;
  74. virtual bool DeleteOnHostDestroy() { return m_bAllocated; } // @QUESTION: should switch to reference count?
  75. virtual bool KeyValue( const char *szKeyName, const char *szValue )
  76. {
  77. return false;
  78. }
  79. bool IsRunning() { Assert( GetOuter() ); return ( GetOuter()->GetPrimaryBehavior() == this ); }
  80. virtual bool CanSelectSchedule() { return true; }
  81. virtual void BeginScheduleSelection() {}
  82. virtual void EndScheduleSelection() {}
  83. void SetBackBridge( IAI_BehaviorBridge *pBackBridge )
  84. {
  85. Assert( m_pBackBridge == NULL || pBackBridge == NULL );
  86. m_pBackBridge = pBackBridge;
  87. }
  88. virtual void Precache() {}
  89. virtual void Spawn() {}
  90. virtual void UpdateOnRemove() {}
  91. virtual void Event_Killed( const CTakeDamageInfo &info ) {}
  92. virtual void CleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput ) {}
  93. virtual void OnChangeHintGroup( string_t oldGroup, string_t newGroup ) {}
  94. void BridgeOnStartSchedule( int scheduleType );
  95. int BridgeSelectSchedule();
  96. bool BridgeSelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode, int *pResult );
  97. bool BridgeStartTask( const Task_t *pTask );
  98. bool BridgeRunTask( const Task_t *pTask);
  99. int BridgeTranslateSchedule( int scheduleType );
  100. bool BridgeGetSchedule( int localScheduleID, CAI_Schedule **ppResult );
  101. bool BridgeTaskName(int taskID, const char **);
  102. virtual void BuildScheduleTestBits() {}
  103. virtual void BuildScheduleTestBitsNotActive() {}
  104. virtual void GatherConditions();
  105. virtual void GatherConditionsNotActive() { return; } // Override this and your behavior will call this in place of GatherConditions() when your behavior is NOT the active one.
  106. virtual void OnUpdateShotRegulator() {}
  107. virtual float GetJumpGravity() const;
  108. virtual bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos, float maxUp, float maxDown, float maxDist ) const;
  109. virtual bool MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost );
  110. virtual void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) {};
  111. virtual CAI_ClassScheduleIdSpace *GetClassScheduleIdSpace();
  112. virtual int DrawDebugTextOverlays( int text_offset );
  113. virtual bool ShouldNPCSave() { return true; }
  114. virtual int Save( ISave &save );
  115. virtual int Restore( IRestore &restore );
  116. virtual void OnRestore() {}
  117. static void SaveBehaviors(ISave &save, CAI_BehaviorBase *pCurrentBehavior, CAI_BehaviorBase **ppBehavior, int nBehaviors, bool bTestIfNPCSave = true );
  118. static int RestoreBehaviors(IRestore &restore, CAI_BehaviorBase **ppBehavior, int nBehaviors, bool bTestIfNPCSave = true ); // returns index of "current" behavior, or -1
  119. public:
  120. //
  121. // Secondary schedule channel support
  122. //
  123. void StartChannel( int channel );
  124. void StopChannel( int channel );
  125. void MaintainChannelSchedules();
  126. void MaintainSchedule( int channel );
  127. void SetSchedule( int channel, CAI_Schedule *pNewSchedule );
  128. bool SetSchedule( int channel, int localScheduleID );
  129. void ClearSchedule( int channel, const char *szReason );
  130. CAI_Schedule *GetCurSchedule( int channel );
  131. bool IsCurSchedule( int channel, int schedId, bool fIdeal = true );
  132. virtual void OnScheduleChange( int channel );
  133. virtual void OnStartSchedule( int channel, int scheduleType );
  134. virtual int SelectSchedule( int channel );
  135. virtual int SelectFailSchedule( int channel, int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
  136. virtual int TranslateSchedule( int channel, int scheduleType ) { return scheduleType; }
  137. virtual void StartTask( int channel, const Task_t *pTask );
  138. virtual void RunTask( int channel, const Task_t *pTask );
  139. const Task_t *GetCurTask( void ) { return BaseClass::GetCurTask(); }
  140. const Task_t *GetCurTask( int channel );
  141. bool TaskIsComplete( int channel ) { return ( m_ScheduleChannels[channel].fTaskStatus == TASKSTATUS_COMPLETE ); }
  142. int TaskIsComplete() { return BaseClass::TaskIsComplete(); }
  143. virtual void TaskFail( AI_TaskFailureCode_t code ) { BaseClass::TaskFail( code ) ; }
  144. void TaskFail( const char *pszGeneralFailText ) { BaseClass::TaskFail( pszGeneralFailText ); }
  145. void TaskComplete( bool fIgnoreSetFailedCondition = false ) { BaseClass::TaskComplete( fIgnoreSetFailedCondition ); }
  146. virtual void TaskFail( int channel, AI_TaskFailureCode_t code );
  147. void TaskFail( int channel, const char *pszGeneralFailText ) { TaskFail( channel, MakeFailCode( pszGeneralFailText ) ); }
  148. void TaskComplete( int channel, bool fIgnoreSetFailedCondition = false );
  149. private:
  150. bool IsScheduleValid( AIChannelScheduleState_t *pScheduleState );
  151. CAI_Schedule *GetNewSchedule( int channel );
  152. CAI_Schedule *GetFailSchedule( AIChannelScheduleState_t *pScheduleState );
  153. const Task_t *GetTask( AIChannelScheduleState_t *pScheduleState );
  154. void SaveChannels( ISave &save );
  155. void RestoreChannels( IRestore &restore );
  156. CUtlVector<AIChannelScheduleState_t> m_ScheduleChannels;
  157. protected:
  158. int GetNpcState() { return GetOuter()->m_NPCState; }
  159. virtual void OnStartSchedule( int scheduleType );
  160. virtual int SelectSchedule();
  161. virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
  162. virtual void StartTask( const Task_t *pTask );
  163. virtual void RunTask( const Task_t *pTask );
  164. virtual int TranslateSchedule( int scheduleType );
  165. virtual CAI_Schedule *GetSchedule(int schedule);
  166. virtual const char *GetSchedulingErrorName();
  167. bool IsCurSchedule( int schedId, bool fIdeal = true );
  168. CAI_Hint * GetHintNode() { return GetOuter()->GetHintNode(); }
  169. const CAI_Hint *GetHintNode() const { return GetOuter()->GetHintNode(); }
  170. void SetHintNode( CAI_Hint *pHintNode ) { GetOuter()->SetHintNode( pHintNode ); }
  171. void ClearHintNode( float reuseDelay = 0.0 ) { GetOuter()->ClearHintNode( reuseDelay ); }
  172. string_t GetHintGroup() { return GetOuter()->GetHintGroup(); }
  173. void ClearHintGroup() { GetOuter()->ClearHintGroup(); }
  174. void SetHintGroup( string_t name ) { GetOuter()->SetHintGroup( name ); }
  175. // For now, only support simple behavior stack:
  176. DELEGATE_TO_OBJECT_0V( BehaviorBridge_GatherConditions, m_pBackBridge );
  177. DELEGATE_TO_OBJECT_0( int, BehaviorBridge_SelectSchedule, m_pBackBridge );
  178. DELEGATE_TO_OBJECT_1( int, BehaviorBridge_TranslateSchedule, int, m_pBackBridge );
  179. protected:
  180. // Used by derived classes to chain a task to a task that might not be the
  181. // one they are currently handling:
  182. void ChainStartTask( int task, float taskData = 0 );
  183. void ChainRunTask( int task, float taskData = 0 );
  184. protected:
  185. bool NotifyChangeBehaviorStatus( bool fCanFinishSchedule = false );
  186. bool HaveSequenceForActivity( Activity activity ) { return GetOuter()->HaveSequenceForActivity( activity ); }
  187. //---------------------------------
  188. //
  189. // These allow derived classes to implement custom schedules
  190. //
  191. static CAI_GlobalScheduleNamespace *GetSchedulingSymbols() { return CAI_BaseNPC::GetSchedulingSymbols(); }
  192. static bool LoadSchedules() { return true; }
  193. virtual bool IsBehaviorSchedule( int scheduleType ) { return false; }
  194. CAI_Navigator * GetNavigator() { return GetOuter()->GetNavigator(); }
  195. CAI_Motor * GetMotor() { return GetOuter()->GetMotor(); }
  196. CAI_TacticalServices * GetTacticalServices() { return GetOuter()->GetTacticalServices(); }
  197. bool m_fOverrode;
  198. IAI_BehaviorBridge *m_pBackBridge;
  199. bool m_bAllocated;
  200. public:
  201. static CGenericClassmap< CAI_BehaviorBase > *GetBehaviorClasses();
  202. private:
  203. static CGenericClassmap< CAI_BehaviorBase > *GetBehaviorClassesInternal();
  204. private:
  205. DECLARE_DATADESC();
  206. };
  207. #define LINK_BEHAVIOR_TO_CLASS( localName, className ) \
  208. static CAI_BehaviorBase *C##className##Factory( void ) \
  209. { \
  210. return static_cast< CAI_BehaviorBase * >( new className ); \
  211. }; \
  212. class C##localName##Foo \
  213. { \
  214. public: \
  215. C##localName##Foo( void ) \
  216. { \
  217. CAI_BehaviorBase::GetBehaviorClasses()->Add( #localName, #className, \
  218. sizeof( className ),&C##className##Factory ); \
  219. } \
  220. }; \
  221. static C##localName##Foo g_C##localName##Foo;
  222. #define LINK_BEHAVIOR_TO_CLASSNAME( className ) \
  223. static CAI_BehaviorBase *C##className##Factory( void ) \
  224. { \
  225. return static_cast< CAI_BehaviorBase * >( new className ); \
  226. }; \
  227. class C##className##Foo \
  228. { \
  229. public: \
  230. C##className##Foo( void ) \
  231. { \
  232. CAI_BehaviorBase::GetBehaviorClasses()->Add( className::GetClassName(), #className, \
  233. sizeof( className ),&C##className##Factory ); \
  234. } \
  235. }; \
  236. static C##className##Foo g_C##className##Foo;
  237. //-----------------------------------------------------------------------------
  238. // Purpose: Template provides provides back bridge to owning class and
  239. // establishes namespace settings
  240. //-----------------------------------------------------------------------------
  241. template <class NPC_CLASS = CAI_BaseNPC, const int ID_SPACE_OFFSET = 100000>
  242. class CAI_Behavior : public CAI_ComponentWithOuter<NPC_CLASS, CAI_BehaviorBase>
  243. {
  244. public:
  245. DECLARE_CLASS_NOFRIEND( CAI_Behavior, NPC_CLASS );
  246. enum
  247. {
  248. NEXT_TASK = ID_SPACE_OFFSET,
  249. NEXT_SCHEDULE = ID_SPACE_OFFSET,
  250. NEXT_CONDITION = ID_SPACE_OFFSET,
  251. NEXT_CHANNEL = ID_SPACE_OFFSET,
  252. };
  253. void SetCondition( int condition )
  254. {
  255. if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us
  256. condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition );
  257. this->GetOuter()->SetCondition( condition );
  258. }
  259. bool HasCondition( int condition )
  260. {
  261. if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us
  262. condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition );
  263. return this->GetOuter()->HasCondition( condition );
  264. }
  265. bool HasInterruptCondition( int condition )
  266. {
  267. if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us
  268. condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition );
  269. return this->GetOuter()->HasInterruptCondition( condition );
  270. }
  271. void ClearCondition( int condition )
  272. {
  273. if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us
  274. condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition );
  275. this->GetOuter()->ClearCondition( condition );
  276. }
  277. protected:
  278. CAI_Behavior(NPC_CLASS *pOuter = NULL)
  279. : CAI_ComponentWithOuter<NPC_CLASS, CAI_BehaviorBase>(pOuter)
  280. {
  281. }
  282. static CAI_GlobalScheduleNamespace *GetSchedulingSymbols()
  283. {
  284. return NPC_CLASS::GetSchedulingSymbols();
  285. }
  286. virtual CAI_ClassScheduleIdSpace *GetClassScheduleIdSpace()
  287. {
  288. return this->GetOuter()->GetClassScheduleIdSpace();
  289. }
  290. static CAI_ClassScheduleIdSpace &AccessClassScheduleIdSpaceDirect()
  291. {
  292. return NPC_CLASS::AccessClassScheduleIdSpaceDirect();
  293. }
  294. private:
  295. virtual bool IsBehaviorSchedule( int scheduleType ) { return ( scheduleType >= ID_SPACE_OFFSET && scheduleType < ID_SPACE_OFFSET + 10000 ); }
  296. };
  297. //-----------------------------------------------------------------------------
  298. // Purpose: The common instantiation of the above template
  299. //-----------------------------------------------------------------------------
  300. typedef CAI_Behavior<> CAI_SimpleBehavior;
  301. //-----------------------------------------------------------------------------
  302. // Purpose: Base class for AIs that want to act as a host for CAI_Behaviors
  303. // NPCs aren't required to use this, but probably want to.
  304. //-----------------------------------------------------------------------------
  305. template <class BASE_NPC>
  306. class CAI_BehaviorHostBase : public BASE_NPC
  307. {
  308. DECLARE_CLASS( CAI_BehaviorHostBase, BASE_NPC );
  309. protected:
  310. CAI_BehaviorHostBase()
  311. {
  312. }
  313. };
  314. template <class BASE_NPC>
  315. class CAI_BehaviorHost : public CAI_BehaviorHostBase<BASE_NPC>
  316. {
  317. DECLARE_CLASS( CAI_BehaviorHost, CAI_BehaviorHostBase<BASE_NPC> );
  318. public:
  319. CAI_BehaviorHost()
  320. {
  321. }
  322. #define AI_GENERATE_BRIDGES
  323. #include "ai_behavior_template.h"
  324. #define AI_GENERATE_HOST_METHODS
  325. #include "ai_behavior_template.h"
  326. void CleanupOnDeath( CBaseEntity *pCulprit = NULL, bool bFireDeathOutput = true );
  327. virtual int Save( ISave &save );
  328. virtual int Restore( IRestore &restore );
  329. // Bridges
  330. void Precache();
  331. void UpdateOnRemove();
  332. void Event_Killed( const CTakeDamageInfo &info );
  333. void GatherConditions();
  334. int SelectSchedule();
  335. void KeepRunningBehavior();
  336. int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
  337. void OnStartSchedule( int scheduleType );
  338. int TranslateSchedule( int scheduleType );
  339. void StartTask( const Task_t *pTask );
  340. void RunTask( const Task_t *pTask );
  341. CAI_Schedule * GetSchedule(int localScheduleID);
  342. const char * TaskName(int taskID);
  343. void BuildScheduleTestBits();
  344. void BuildScheduleTestBitsNotActive();
  345. void OnChangeHintGroup( string_t oldGroup, string_t newGroup );
  346. void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon );
  347. void OnRestore();
  348. float GetJumpGravity() const;
  349. bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos, float maxUp, float maxDown, float maxDist ) const;
  350. bool MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost );
  351. //---------------------------------
  352. protected:
  353. CAI_Schedule * GetNewSchedule();
  354. CAI_Schedule * GetFailSchedule();
  355. private:
  356. void BehaviorBridge_GatherConditions();
  357. int BehaviorBridge_SelectSchedule();
  358. int BehaviorBridge_TranslateSchedule( int scheduleType );
  359. float BehaviorBridge_GetJumpGravity() const;
  360. bool BehaviorBridge_IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos, float maxUp, float maxDown, float maxDist ) const;
  361. bool BehaviorBridge_MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost );
  362. bool m_bCalledBehaviorSelectSchedule;
  363. };
  364. //-----------------------------------------------------------------------------
  365. // The first frame a behavior begins schedule selection, it won't have had it's GatherConditions()
  366. // called. To fix this, BeginScheduleSelection() manually calls the new behavior's GatherConditions(),
  367. // but sets this global so that the baseclass GatherConditions() isn't called as well.
  368. extern bool g_bBehaviorHost_PreventBaseClassGatherConditions;
  369. //-----------------------------------------------------------------------------
  370. inline void CAI_BehaviorBase::BridgeOnStartSchedule( int scheduleType )
  371. {
  372. int localId = AI_IdIsGlobal( scheduleType ) ? GetClassScheduleIdSpace()->ScheduleGlobalToLocal( scheduleType ) : scheduleType;
  373. OnStartSchedule( localId );
  374. }
  375. //-------------------------------------
  376. inline int CAI_BehaviorBase::BridgeSelectSchedule()
  377. {
  378. int result = SelectSchedule();
  379. if ( IsBehaviorSchedule( result ) )
  380. return GetClassScheduleIdSpace()->ScheduleLocalToGlobal( result );
  381. return result;
  382. }
  383. //-------------------------------------
  384. inline bool CAI_BehaviorBase::BridgeSelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode, int *pResult )
  385. {
  386. m_fOverrode = true;
  387. int result = SelectFailSchedule( failedSchedule, failedTask, taskFailCode );
  388. if ( m_fOverrode )
  389. {
  390. if ( result != SCHED_NONE )
  391. {
  392. if ( IsBehaviorSchedule( result ) )
  393. *pResult = GetClassScheduleIdSpace()->ScheduleLocalToGlobal( result );
  394. else
  395. *pResult = result;
  396. return true;
  397. }
  398. Warning( "An AI behavior is in control but has no recommended schedule\n" );
  399. }
  400. return false;
  401. }
  402. //-------------------------------------
  403. inline bool CAI_BehaviorBase::BridgeStartTask( const Task_t *pTask )
  404. {
  405. m_fOverrode = true;
  406. StartTask( pTask );
  407. return m_fOverrode;
  408. }
  409. //-------------------------------------
  410. inline bool CAI_BehaviorBase::BridgeRunTask( const Task_t *pTask)
  411. {
  412. m_fOverrode = true;
  413. RunTask( pTask );
  414. return m_fOverrode;
  415. }
  416. //-------------------------------------
  417. inline void CAI_BehaviorBase::ChainStartTask( int task, float taskData )
  418. {
  419. Task_t tempTask = { task, taskData };
  420. bool fPrevOverride = m_fOverrode;
  421. this->GetOuter()->StartTask( (const Task_t *)&tempTask );
  422. m_fOverrode = fPrevOverride;;
  423. }
  424. //-------------------------------------
  425. inline void CAI_BehaviorBase::ChainRunTask( int task, float taskData )
  426. {
  427. Task_t tempTask = { task, taskData };
  428. bool fPrevOverride = m_fOverrode;
  429. this->GetOuter()->RunTask( (const Task_t *) &tempTask );
  430. m_fOverrode = fPrevOverride;;
  431. }
  432. //-------------------------------------
  433. inline int CAI_BehaviorBase::BridgeTranslateSchedule( int scheduleType )
  434. {
  435. int localId = AI_IdIsGlobal( scheduleType ) ? GetClassScheduleIdSpace()->ScheduleGlobalToLocal( scheduleType ) : scheduleType;
  436. int result = TranslateSchedule( localId );
  437. return result;
  438. }
  439. //-------------------------------------
  440. inline bool CAI_BehaviorBase::BridgeGetSchedule( int localScheduleID, CAI_Schedule **ppResult )
  441. {
  442. *ppResult = GetSchedule( localScheduleID );
  443. return (*ppResult != NULL );
  444. }
  445. //-------------------------------------
  446. inline bool CAI_BehaviorBase::BridgeTaskName( int taskID, const char **ppResult )
  447. {
  448. if ( AI_IdIsLocal( taskID ) )
  449. {
  450. *ppResult = GetSchedulingSymbols()->TaskIdToSymbol( GetClassScheduleIdSpace()->TaskLocalToGlobal( taskID ) );
  451. return (*ppResult != NULL );
  452. }
  453. return false;
  454. }
  455. //-----------------------------------------------------------------------------
  456. template <class BASE_NPC>
  457. inline void CAI_BehaviorHost<BASE_NPC>::CleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput )
  458. {
  459. this->DeferSchedulingToBehavior( NULL );
  460. for( int i = 0; i < this->m_Behaviors.Count(); i++ )
  461. {
  462. this->m_Behaviors[i]->CleanupOnDeath( pCulprit, bFireDeathOutput );
  463. }
  464. BaseClass::CleanupOnDeath( pCulprit, bFireDeathOutput );
  465. }
  466. //-------------------------------------
  467. template <class BASE_NPC>
  468. inline void CAI_BehaviorHost<BASE_NPC>::GatherConditions()
  469. {
  470. // Iterate over behaviors and call GatherConditionsNotActive() on each behavior
  471. // not currently active.
  472. for( int i = 0; i < this->m_Behaviors.Count(); i++ )
  473. {
  474. if( this->m_Behaviors[i] != this->m_pPrimaryBehavior )
  475. {
  476. this->m_Behaviors[i]->GatherConditionsNotActive();
  477. }
  478. }
  479. if ( this->m_pPrimaryBehavior )
  480. this->m_pPrimaryBehavior->GatherConditions();
  481. else
  482. BaseClass::GatherConditions();
  483. }
  484. //-------------------------------------
  485. template <class BASE_NPC>
  486. inline void CAI_BehaviorHost<BASE_NPC>::BehaviorBridge_GatherConditions()
  487. {
  488. if ( g_bBehaviorHost_PreventBaseClassGatherConditions )
  489. return;
  490. BaseClass::GatherConditions();
  491. }
  492. //-------------------------------------
  493. template <class BASE_NPC>
  494. inline void CAI_BehaviorHost<BASE_NPC>::OnStartSchedule( int scheduleType )
  495. {
  496. if ( this->m_pPrimaryBehavior )
  497. this->m_pPrimaryBehavior->BridgeOnStartSchedule( scheduleType );
  498. BaseClass::OnStartSchedule( scheduleType );
  499. }
  500. //-------------------------------------
  501. template <class BASE_NPC>
  502. inline int CAI_BehaviorHost<BASE_NPC>::BehaviorBridge_SelectSchedule()
  503. {
  504. return BaseClass::SelectSchedule();
  505. }
  506. //-------------------------------------
  507. template <class BASE_NPC>
  508. inline CAI_Schedule *CAI_BehaviorHost<BASE_NPC>::GetNewSchedule()
  509. {
  510. m_bCalledBehaviorSelectSchedule = false;
  511. CAI_Schedule *pResult = BaseClass::GetNewSchedule();
  512. if ( !m_bCalledBehaviorSelectSchedule && this->m_pPrimaryBehavior )
  513. this->DeferSchedulingToBehavior( NULL );
  514. return pResult;
  515. }
  516. //-------------------------------------
  517. template <class BASE_NPC>
  518. inline CAI_Schedule *CAI_BehaviorHost<BASE_NPC>::GetFailSchedule()
  519. {
  520. m_bCalledBehaviorSelectSchedule = false;
  521. CAI_Schedule *pResult = BaseClass::GetFailSchedule();
  522. if ( !m_bCalledBehaviorSelectSchedule && this->m_pPrimaryBehavior )
  523. this->DeferSchedulingToBehavior( NULL );
  524. return pResult;
  525. }
  526. //-------------------------------------
  527. template <class BASE_NPC>
  528. inline int CAI_BehaviorHost<BASE_NPC>::BehaviorBridge_TranslateSchedule( int scheduleType )
  529. {
  530. return BaseClass::TranslateSchedule( scheduleType );
  531. }
  532. //-------------------------------------
  533. template <class BASE_NPC>
  534. inline int CAI_BehaviorHost<BASE_NPC>::TranslateSchedule( int scheduleType )
  535. {
  536. if ( this->m_pPrimaryBehavior )
  537. {
  538. return this->m_pPrimaryBehavior->BridgeTranslateSchedule( scheduleType );
  539. }
  540. return BaseClass::TranslateSchedule( scheduleType );
  541. }
  542. //-------------------------------------
  543. template <class BASE_NPC>
  544. inline int CAI_BehaviorHost<BASE_NPC>::SelectSchedule()
  545. {
  546. m_bCalledBehaviorSelectSchedule = true;
  547. if ( this->m_pPrimaryBehavior )
  548. {
  549. return this->m_pPrimaryBehavior->BridgeSelectSchedule();
  550. }
  551. return BaseClass::SelectSchedule();
  552. }
  553. //-------------------------------------
  554. template <class BASE_NPC>
  555. inline void CAI_BehaviorHost<BASE_NPC>::KeepRunningBehavior()
  556. {
  557. if ( this->m_pPrimaryBehavior )
  558. m_bCalledBehaviorSelectSchedule = true;
  559. }
  560. //-------------------------------------
  561. template <class BASE_NPC>
  562. inline int CAI_BehaviorHost<BASE_NPC>::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode )
  563. {
  564. m_bCalledBehaviorSelectSchedule = true;
  565. int result = 0;
  566. if ( this->m_pPrimaryBehavior && this->m_pPrimaryBehavior->BridgeSelectFailSchedule( failedSchedule, failedTask, taskFailCode, &result ) )
  567. return result;
  568. return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode );
  569. }
  570. //-------------------------------------
  571. template <class BASE_NPC>
  572. inline void CAI_BehaviorHost<BASE_NPC>::StartTask( const Task_t *pTask )
  573. {
  574. if ( this->m_pPrimaryBehavior && this->m_pPrimaryBehavior->BridgeStartTask( pTask ) )
  575. return;
  576. BaseClass::StartTask( pTask );
  577. }
  578. //-------------------------------------
  579. template <class BASE_NPC>
  580. inline void CAI_BehaviorHost<BASE_NPC>::RunTask( const Task_t *pTask )
  581. {
  582. if ( this->m_pPrimaryBehavior && this->m_pPrimaryBehavior->BridgeRunTask( pTask ) )
  583. return;
  584. BaseClass::RunTask( pTask );
  585. }
  586. //-------------------------------------
  587. template <class BASE_NPC>
  588. inline CAI_Schedule *CAI_BehaviorHost<BASE_NPC>::GetSchedule(int localScheduleID)
  589. {
  590. CAI_Schedule *pResult;
  591. if ( this->m_pPrimaryBehavior && this->m_pPrimaryBehavior->BridgeGetSchedule( localScheduleID, &pResult ) )
  592. return pResult;
  593. return BaseClass::GetSchedule( localScheduleID );
  594. }
  595. //-------------------------------------
  596. template <class BASE_NPC>
  597. inline const char *CAI_BehaviorHost<BASE_NPC>::TaskName(int taskID)
  598. {
  599. const char *pszResult = NULL;
  600. if ( this->m_pPrimaryBehavior && this->m_pPrimaryBehavior->BridgeTaskName( taskID, &pszResult ) )
  601. return pszResult;
  602. return BaseClass::TaskName( taskID );
  603. }
  604. //-------------------------------------
  605. template <class BASE_NPC>
  606. inline void CAI_BehaviorHost<BASE_NPC>::BuildScheduleTestBits()
  607. {
  608. // Iterate over behaviors and call BuildScheduleTestBitsNotActive() on each behavior
  609. // not currently active.
  610. for( int i = 0; i < this->m_Behaviors.Count(); i++ )
  611. {
  612. if( this->m_Behaviors[i] != this->m_pPrimaryBehavior )
  613. {
  614. this->m_Behaviors[i]->BuildScheduleTestBitsNotActive();
  615. }
  616. }
  617. if ( this->m_pPrimaryBehavior )
  618. this->m_pPrimaryBehavior->BuildScheduleTestBits();
  619. BaseClass::BuildScheduleTestBits();
  620. }
  621. //-------------------------------------
  622. template <class BASE_NPC>
  623. inline void CAI_BehaviorHost<BASE_NPC>::OnChangeHintGroup( string_t oldGroup, string_t newGroup )
  624. {
  625. for( int i = 0; i < this->m_Behaviors.Count(); i++ )
  626. {
  627. this->m_Behaviors[i]->OnChangeHintGroup( oldGroup, newGroup );
  628. }
  629. BaseClass::OnChangeHintGroup( oldGroup, newGroup );
  630. }
  631. //-------------------------------------
  632. template <class BASE_NPC>
  633. inline float CAI_BehaviorHost<BASE_NPC>::BehaviorBridge_GetJumpGravity() const
  634. {
  635. return BaseClass::GetJumpGravity();
  636. }
  637. //-------------------------------------
  638. template <class BASE_NPC>
  639. inline bool CAI_BehaviorHost<BASE_NPC>::BehaviorBridge_IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos, float maxUp, float maxDown, float maxDist ) const
  640. {
  641. return BaseClass::IsJumpLegal( startPos, apex, endPos, maxUp, maxDown, maxDist );
  642. }
  643. //-------------------------------------
  644. template <class BASE_NPC>
  645. inline bool CAI_BehaviorHost<BASE_NPC>::BehaviorBridge_MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost )
  646. {
  647. return BaseClass::MovementCost( moveType, vecStart, vecEnd, pCost );
  648. }
  649. //-------------------------------------
  650. template <class BASE_NPC>
  651. inline void CAI_BehaviorHost<BASE_NPC>::OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon )
  652. {
  653. for( int i = 0; i < this->m_Behaviors.Count(); i++ )
  654. {
  655. this->m_Behaviors[i]->OnChangeActiveWeapon( pOldWeapon, pNewWeapon );
  656. }
  657. BaseClass::OnChangeActiveWeapon( pOldWeapon, pNewWeapon );
  658. }
  659. //-------------------------------------
  660. template <class BASE_NPC>
  661. inline void CAI_BehaviorHost<BASE_NPC>::OnRestore()
  662. {
  663. for( int i = 0; i < this->m_Behaviors.Count(); i++ )
  664. {
  665. this->m_Behaviors[i]->OnRestore();
  666. }
  667. BaseClass::OnRestore();
  668. }
  669. //-------------------------------------
  670. template <class BASE_NPC>
  671. inline void CAI_BehaviorHost<BASE_NPC>::Precache()
  672. {
  673. BaseClass::Precache();
  674. for( int i = 0; i < this->m_Behaviors.Count(); i++ )
  675. {
  676. this->m_Behaviors[i]->Precache();
  677. }
  678. }
  679. //-------------------------------------
  680. template <class BASE_NPC>
  681. inline void CAI_BehaviorHost<BASE_NPC>::UpdateOnRemove()
  682. {
  683. for( int i = 0; i < this->m_Behaviors.Count(); i++ )
  684. {
  685. this->m_Behaviors[i]->UpdateOnRemove();
  686. }
  687. BaseClass::UpdateOnRemove();
  688. }
  689. //-------------------------------------
  690. template <class BASE_NPC>
  691. inline void CAI_BehaviorHost<BASE_NPC>::Event_Killed( const CTakeDamageInfo &info )
  692. {
  693. for( int i = 0; i < this->m_Behaviors.Count(); i++ )
  694. {
  695. this->m_Behaviors[i]->Event_Killed( info );
  696. }
  697. BaseClass::Event_Killed( info );
  698. }
  699. //-----------------------------------------------------------------------------
  700. template <class BASE_NPC>
  701. inline float CAI_BehaviorHost<BASE_NPC>::GetJumpGravity() const
  702. {
  703. // @HACKHACK
  704. float base = BaseClass::GetJumpGravity();
  705. for( int i = 0; i < this->m_Behaviors.Count(); i++ )
  706. {
  707. float current = this->m_Behaviors[i]->GetJumpGravity();
  708. if ( current != base )
  709. {
  710. return current;
  711. }
  712. }
  713. return BaseClass::GetJumpGravity();
  714. }
  715. //-------------------------------------
  716. template <class BASE_NPC>
  717. inline bool CAI_BehaviorHost<BASE_NPC>::IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos, float maxUp, float maxDown, float maxDist ) const
  718. {
  719. // @HACKHACK
  720. bool base = BaseClass::IsJumpLegal( startPos, apex, endPos, maxUp, maxDown, maxDist );
  721. for( int i = 0; i < this->m_Behaviors.Count(); i++ )
  722. {
  723. bool current = this->m_Behaviors[i]->IsJumpLegal( startPos, apex, endPos, maxUp, maxDown, maxDist );
  724. if ( current != base )
  725. {
  726. return current;
  727. }
  728. }
  729. return base;
  730. }
  731. template <class BASE_NPC>
  732. inline bool CAI_BehaviorHost<BASE_NPC>::MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost )
  733. {
  734. // @HACKHACK
  735. bool base = BaseClass::MovementCost( moveType, vecStart, vecEnd, pCost );
  736. for( int i = 0; i < this->m_Behaviors.Count(); i++ )
  737. {
  738. bool current = this->m_Behaviors[i]->MovementCost( moveType, vecStart, vecEnd, pCost );
  739. if ( current != base )
  740. {
  741. return current;
  742. }
  743. }
  744. return base;
  745. }
  746. //-------------------------------------
  747. template <class BASE_NPC>
  748. inline int CAI_BehaviorHost<BASE_NPC>::Save( ISave &save )
  749. {
  750. int result = BaseClass::Save( save );
  751. if ( result )
  752. CAI_BehaviorBase::SaveBehaviors( save, this->m_pPrimaryBehavior, this->AccessBehaviors(), this->NumBehaviors() );
  753. return result;
  754. }
  755. //-------------------------------------
  756. template <class BASE_NPC>
  757. inline int CAI_BehaviorHost<BASE_NPC>::Restore( IRestore &restore )
  758. {
  759. int result = BaseClass::Restore( restore );
  760. if ( result )
  761. {
  762. int iCurrent = CAI_BehaviorBase::RestoreBehaviors( restore, this->AccessBehaviors(), this->NumBehaviors() );
  763. if ( iCurrent != -1 )
  764. this->m_pPrimaryBehavior = this->AccessBehaviors()[iCurrent];
  765. else
  766. this->m_pPrimaryBehavior = NULL;
  767. }
  768. return result;
  769. }
  770. //-----------------------------------------------------------------------------
  771. #endif // AI_BEHAVIOR_H