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.

533 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "isaverestore.h"
  9. #include "ai_behavior.h"
  10. #include "scripted.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. bool g_bBehaviorHost_PreventBaseClassGatherConditions;
  14. //-----------------------------------------------------------------------------
  15. // CAI_BehaviorBase
  16. //-----------------------------------------------------------------------------
  17. BEGIN_DATADESC_NO_BASE( CAI_BehaviorBase )
  18. END_DATADESC()
  19. //-------------------------------------
  20. CAI_ClassScheduleIdSpace *CAI_BehaviorBase::GetClassScheduleIdSpace()
  21. {
  22. return GetOuter()->GetClassScheduleIdSpace();
  23. }
  24. //-----------------------------------------------------------------------------
  25. // Purpose: Draw any text overlays (override in subclass to add additional text)
  26. // Input : Previous text offset from the top
  27. // Output : Current text offset from the top
  28. //-----------------------------------------------------------------------------
  29. int CAI_BehaviorBase::DrawDebugTextOverlays( int text_offset )
  30. {
  31. char tempstr[ 512 ];
  32. int offset = text_offset;
  33. if ( GetOuter()->m_debugOverlays & OVERLAY_TEXT_BIT )
  34. {
  35. Q_snprintf( tempstr, sizeof( tempstr ), "Behv: %s, ", GetName() );
  36. GetOuter()->EntityText( offset, tempstr, 0 );
  37. offset++;
  38. }
  39. return offset;
  40. }
  41. //-------------------------------------
  42. void CAI_BehaviorBase::GatherConditions()
  43. {
  44. Assert( m_pBackBridge != NULL );
  45. m_pBackBridge->BackBridge_GatherConditions();
  46. }
  47. //-------------------------------------
  48. void CAI_BehaviorBase::PrescheduleThink()
  49. {
  50. }
  51. //-------------------------------------
  52. void CAI_BehaviorBase::OnScheduleChange()
  53. {
  54. }
  55. //-------------------------------------
  56. void CAI_BehaviorBase::OnStartSchedule( int scheduleType )
  57. {
  58. }
  59. //-------------------------------------
  60. int CAI_BehaviorBase::SelectSchedule()
  61. {
  62. Assert( m_pBackBridge != NULL );
  63. return m_pBackBridge->BackBridge_SelectSchedule();
  64. }
  65. //-------------------------------------
  66. int CAI_BehaviorBase::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode )
  67. {
  68. m_fOverrode = false;
  69. return SCHED_NONE;
  70. }
  71. //-------------------------------------
  72. void CAI_BehaviorBase::StartTask( const Task_t *pTask )
  73. {
  74. m_fOverrode = false;
  75. }
  76. //-------------------------------------
  77. void CAI_BehaviorBase::RunTask( const Task_t *pTask )
  78. {
  79. m_fOverrode = false;
  80. }
  81. //-------------------------------------
  82. void CAI_BehaviorBase::AimGun( void )
  83. {
  84. m_fOverrode = false;
  85. }
  86. //-------------------------------------
  87. int CAI_BehaviorBase::TranslateSchedule( int scheduleType )
  88. {
  89. Assert( m_pBackBridge != NULL );
  90. return m_pBackBridge->BackBridge_TranslateSchedule( scheduleType );
  91. }
  92. //-------------------------------------
  93. CAI_Schedule *CAI_BehaviorBase::GetSchedule(int schedule)
  94. {
  95. if (!GetClassScheduleIdSpace()->IsGlobalBaseSet())
  96. {
  97. Warning("ERROR: %s missing schedule!\n", GetSchedulingErrorName());
  98. return g_AI_SchedulesManager.GetScheduleFromID(SCHED_IDLE_STAND);
  99. }
  100. if ( AI_IdIsLocal( schedule ) )
  101. {
  102. schedule = GetClassScheduleIdSpace()->ScheduleLocalToGlobal(schedule);
  103. }
  104. if ( schedule == -1 )
  105. return NULL;
  106. return g_AI_SchedulesManager.GetScheduleFromID( schedule );
  107. }
  108. //-------------------------------------
  109. bool CAI_BehaviorBase::IsCurSchedule( int schedule, bool fIdeal )
  110. {
  111. if ( AI_IdIsLocal( schedule ) )
  112. schedule = GetClassScheduleIdSpace()->ScheduleLocalToGlobal(schedule);
  113. return GetOuter()->IsCurSchedule( schedule, fIdeal );
  114. }
  115. //-------------------------------------
  116. const char *CAI_BehaviorBase::GetSchedulingErrorName()
  117. {
  118. return "CAI_Behavior";
  119. }
  120. //-------------------------------------
  121. Activity CAI_BehaviorBase::NPC_TranslateActivity( Activity activity )
  122. {
  123. Assert( m_pBackBridge != NULL );
  124. return m_pBackBridge->BackBridge_NPC_TranslateActivity( activity );
  125. }
  126. //-------------------------------------
  127. bool CAI_BehaviorBase::IsCurTaskContinuousMove()
  128. {
  129. m_fOverrode = false;
  130. return false;
  131. }
  132. //-------------------------------------
  133. float CAI_BehaviorBase::GetDefaultNavGoalTolerance()
  134. {
  135. Assert( m_pBackBridge != NULL );
  136. return m_pBackBridge->BackBridge_GetDefaultNavGoalTolerance();
  137. }
  138. //-------------------------------------
  139. bool CAI_BehaviorBase::FValidateHintType( CAI_Hint *pHint )
  140. {
  141. m_fOverrode = false;
  142. return false;
  143. }
  144. //-------------------------------------
  145. bool CAI_BehaviorBase::IsValidEnemy( CBaseEntity *pEnemy )
  146. {
  147. Assert( m_pBackBridge != NULL );
  148. return m_pBackBridge->BackBridge_IsValidEnemy( pEnemy );
  149. }
  150. //-------------------------------------
  151. CBaseEntity *CAI_BehaviorBase::BestEnemy( void )
  152. {
  153. Assert( m_pBackBridge != NULL );
  154. return m_pBackBridge->BackBridge_BestEnemy();
  155. }
  156. //-------------------------------------
  157. bool CAI_BehaviorBase::IsValidCover( const Vector &vLocation, CAI_Hint const *pHint )
  158. {
  159. Assert( m_pBackBridge != NULL );
  160. return m_pBackBridge->BackBridge_IsValidCover( vLocation, pHint );
  161. }
  162. //-------------------------------------
  163. bool CAI_BehaviorBase::IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint )
  164. {
  165. Assert( m_pBackBridge != NULL );
  166. return m_pBackBridge->BackBridge_IsValidShootPosition( vLocation, pNode, pHint );
  167. }
  168. //-------------------------------------
  169. float CAI_BehaviorBase::GetMaxTacticalLateralMovement( void )
  170. {
  171. Assert( m_pBackBridge != NULL );
  172. return m_pBackBridge->BackBridge_GetMaxTacticalLateralMovement();
  173. }
  174. //-------------------------------------
  175. bool CAI_BehaviorBase::ShouldIgnoreSound( CSound *pSound )
  176. {
  177. Assert( m_pBackBridge != NULL );
  178. return m_pBackBridge->BackBridge_ShouldIgnoreSound( pSound );
  179. }
  180. //-------------------------------------
  181. void CAI_BehaviorBase::OnSeeEntity( CBaseEntity *pEntity )
  182. {
  183. Assert( m_pBackBridge != NULL );
  184. m_pBackBridge->BackBridge_OnSeeEntity( pEntity );
  185. }
  186. //-------------------------------------
  187. void CAI_BehaviorBase::OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker )
  188. {
  189. Assert( m_pBackBridge != NULL );
  190. m_pBackBridge->BackBridge_OnFriendDamaged( pSquadmate, pAttacker );
  191. }
  192. //-------------------------------------
  193. bool CAI_BehaviorBase::IsInterruptable( void )
  194. {
  195. Assert( m_pBackBridge != NULL );
  196. return m_pBackBridge->BackBridge_IsInterruptable();
  197. }
  198. //-------------------------------------
  199. bool CAI_BehaviorBase::IsNavigationUrgent( void )
  200. {
  201. Assert( m_pBackBridge != NULL );
  202. return m_pBackBridge->BackBridge_IsNavigationUrgent();
  203. }
  204. //-------------------------------------
  205. bool CAI_BehaviorBase::CanFlinch( void )
  206. {
  207. Assert( m_pBackBridge != NULL );
  208. return m_pBackBridge->BackBridge_CanFlinch();
  209. }
  210. //-------------------------------------
  211. bool CAI_BehaviorBase::IsCrouching( void )
  212. {
  213. Assert( m_pBackBridge != NULL );
  214. return m_pBackBridge->BackBridge_IsCrouching();
  215. }
  216. //-------------------------------------
  217. bool CAI_BehaviorBase::IsCrouchedActivity( Activity activity )
  218. {
  219. Assert( m_pBackBridge != NULL );
  220. return m_pBackBridge->BackBridge_IsCrouchedActivity( activity );
  221. }
  222. //-------------------------------------
  223. bool CAI_BehaviorBase::QueryHearSound( CSound *pSound )
  224. {
  225. Assert( m_pBackBridge != NULL );
  226. return m_pBackBridge->BackBridge_QueryHearSound( pSound );
  227. }
  228. //-------------------------------------
  229. bool CAI_BehaviorBase::CanRunAScriptedNPCInteraction( bool bForced )
  230. {
  231. Assert( m_pBackBridge != NULL );
  232. return m_pBackBridge->BackBridge_CanRunAScriptedNPCInteraction( bForced );
  233. }
  234. //-------------------------------------
  235. bool CAI_BehaviorBase::ShouldPlayerAvoid( void )
  236. {
  237. Assert( m_pBackBridge != NULL );
  238. return m_pBackBridge->BackBridge_ShouldPlayerAvoid();
  239. }
  240. //-------------------------------------
  241. int CAI_BehaviorBase::OnTakeDamage_Alive( const CTakeDamageInfo &info )
  242. {
  243. Assert( m_pBackBridge != NULL );
  244. return m_pBackBridge->BackBridge_OnTakeDamage_Alive( info );
  245. }
  246. //-------------------------------------
  247. float CAI_BehaviorBase::GetReasonableFacingDist( void )
  248. {
  249. Assert( m_pBackBridge != NULL );
  250. return m_pBackBridge->BackBridge_GetReasonableFacingDist();
  251. }
  252. //-------------------------------------
  253. bool CAI_BehaviorBase::ShouldAlwaysThink()
  254. {
  255. m_fOverrode = false;
  256. return false;
  257. }
  258. //-------------------------------------
  259. Activity CAI_BehaviorBase::GetFlinchActivity( bool bHeavyDamage, bool bGesture )
  260. {
  261. Assert( m_pBackBridge != NULL );
  262. return m_pBackBridge->BackBridge_GetFlinchActivity( bHeavyDamage, bGesture );
  263. }
  264. //-------------------------------------
  265. bool CAI_BehaviorBase::OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult )
  266. {
  267. Assert( m_pBackBridge != NULL );
  268. return m_pBackBridge->BackBridge_OnCalcBaseMove( pMoveGoal, distClear, pResult );
  269. }
  270. //-------------------------------------
  271. void CAI_BehaviorBase::ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet )
  272. {
  273. Assert( m_pBackBridge != NULL );
  274. return m_pBackBridge->BackBridge_ModifyOrAppendCriteria( criteriaSet );
  275. }
  276. //-------------------------------------
  277. void CAI_BehaviorBase::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity )
  278. {
  279. Assert( m_pBackBridge != NULL );
  280. return m_pBackBridge->BackBridge_Teleport( newPosition, newAngles, newVelocity );
  281. }
  282. //-------------------------------------
  283. void CAI_BehaviorBase::HandleAnimEvent( animevent_t *pEvent )
  284. {
  285. Assert( m_pBackBridge != NULL );
  286. m_pBackBridge->BackBridge_HandleAnimEvent( pEvent );
  287. }
  288. //-------------------------------------
  289. bool CAI_BehaviorBase::NotifyChangeBehaviorStatus( bool fCanFinishSchedule )
  290. {
  291. bool fInterrupt = GetOuter()->OnBehaviorChangeStatus( this, fCanFinishSchedule );
  292. if ( !GetOuter()->IsInterruptable())
  293. return false;
  294. if ( fInterrupt )
  295. {
  296. if ( GetOuter()->m_hCine )
  297. {
  298. if( GetOuter()->m_hCine->PlayedSequence() )
  299. {
  300. DevWarning( "NPC: %s canceled running script %s due to behavior change\n", GetOuter()->GetDebugName(), GetOuter()->m_hCine->GetDebugName() );
  301. }
  302. else
  303. {
  304. DevWarning( "NPC: %s canceled script %s without playing, due to behavior change\n", GetOuter()->GetDebugName(), GetOuter()->m_hCine->GetDebugName() );
  305. }
  306. GetOuter()->m_hCine->CancelScript();
  307. }
  308. //!!!HACKHACK
  309. // this is dirty, but it forces NPC to pick a new schedule next time through.
  310. GetOuter()->ClearSchedule( "Changed behavior status" );
  311. }
  312. return fInterrupt;
  313. }
  314. //-------------------------------------
  315. int CAI_BehaviorBase::Save( ISave &save )
  316. {
  317. return save.WriteAll( this, GetDataDescMap() );
  318. }
  319. //-------------------------------------
  320. int CAI_BehaviorBase::Restore( IRestore &restore )
  321. {
  322. return restore.ReadAll( this, GetDataDescMap() );
  323. }
  324. //-------------------------------------
  325. #define BEHAVIOR_SAVE_BLOCKNAME "AI_Behaviors"
  326. #define BEHAVIOR_SAVE_VERSION 2
  327. void CAI_BehaviorBase::SaveBehaviors(ISave &save, CAI_BehaviorBase *pCurrentBehavior, CAI_BehaviorBase **ppBehavior, int nBehaviors )
  328. {
  329. save.StartBlock( BEHAVIOR_SAVE_BLOCKNAME );
  330. short temp = BEHAVIOR_SAVE_VERSION;
  331. save.WriteShort( &temp );
  332. temp = (short)nBehaviors;
  333. save.WriteShort( &temp );
  334. for ( int i = 0; i < nBehaviors; i++ )
  335. {
  336. if ( strcmp( ppBehavior[i]->GetDataDescMap()->dataClassName, CAI_BehaviorBase::m_DataMap.dataClassName ) != 0 )
  337. {
  338. save.StartBlock();
  339. save.WriteString( ppBehavior[i]->GetDataDescMap()->dataClassName );
  340. bool bIsCurrent = ( pCurrentBehavior == ppBehavior[i] );
  341. save.WriteBool( &bIsCurrent );
  342. ppBehavior[i]->Save( save );
  343. save.EndBlock();
  344. }
  345. }
  346. save.EndBlock();
  347. }
  348. //-------------------------------------
  349. int CAI_BehaviorBase::RestoreBehaviors(IRestore &restore, CAI_BehaviorBase **ppBehavior, int nBehaviors )
  350. {
  351. int iCurrent = -1;
  352. char szBlockName[SIZE_BLOCK_NAME_BUF];
  353. restore.StartBlock( szBlockName );
  354. if ( strcmp( szBlockName, BEHAVIOR_SAVE_BLOCKNAME ) == 0 )
  355. {
  356. short version;
  357. restore.ReadShort( &version );
  358. if ( version == BEHAVIOR_SAVE_VERSION )
  359. {
  360. short nToRestore;
  361. char szClassNameCurrent[256];
  362. restore.ReadShort( &nToRestore );
  363. for ( int i = 0; i < nToRestore; i++ )
  364. {
  365. restore.StartBlock();
  366. restore.ReadString( szClassNameCurrent, sizeof( szClassNameCurrent ), 0 );
  367. bool bIsCurrent;
  368. restore.ReadBool( &bIsCurrent );
  369. for ( int j = 0; j < nBehaviors; j++ )
  370. {
  371. if ( strcmp( ppBehavior[j]->GetDataDescMap()->dataClassName, szClassNameCurrent ) == 0 )
  372. {
  373. if ( bIsCurrent )
  374. iCurrent = j;
  375. ppBehavior[j]->Restore( restore );
  376. }
  377. }
  378. restore.EndBlock();
  379. }
  380. }
  381. }
  382. restore.EndBlock();
  383. return iCurrent;
  384. }
  385. //-----------------------------------------------------------------------------