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.

232 lines
6.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. //=========================================================
  9. // GMan - misunderstood servant of the people
  10. //=========================================================
  11. #include "cbase.h"
  12. #include "ai_default.h"
  13. #include "ai_task.h"
  14. #include "ai_schedule.h"
  15. #include "ai_node.h"
  16. #include "ai_hull.h"
  17. #include "ai_hint.h"
  18. #include "ai_memory.h"
  19. #include "ai_route.h"
  20. #include "ai_motor.h"
  21. #include "soundent.h"
  22. #include "game.h"
  23. #include "npcevent.h"
  24. #include "entitylist.h"
  25. #include "activitylist.h"
  26. #include "animation.h"
  27. #include "IEffects.h"
  28. #include "vstdlib/random.h"
  29. #include "ai_baseactor.h"
  30. //=========================================================
  31. // Monster's Anim Events Go Here
  32. //=========================================================
  33. class CNPC_GMan : public CAI_BaseActor
  34. {
  35. DECLARE_CLASS( CNPC_GMan, CAI_BaseActor );
  36. public:
  37. void Spawn( void );
  38. void Precache( void );
  39. float MaxYawSpeed( void ){ return 90.0f; }
  40. Class_T Classify ( void );
  41. void HandleAnimEvent( animevent_t *pEvent );
  42. int GetSoundInterests ( void );
  43. bool IsInC5A1();
  44. void StartTask( const Task_t *pTask );
  45. void RunTask( const Task_t *pTask );
  46. int OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo );
  47. void TraceAttack( CBaseEntity *pAttacker, float flDamage, const Vector &vecDir, trace_t *ptr, int bitsDamageType);
  48. virtual int PlayScriptedSentence( const char *pszSentence, float duration, float volume, soundlevel_t soundlevel, bool bConcurrent, CBaseEntity *pListener );
  49. EHANDLE m_hPlayer;
  50. EHANDLE m_hTalkTarget;
  51. float m_flTalkTime;
  52. };
  53. LINK_ENTITY_TO_CLASS( monster_gman, CNPC_GMan );
  54. //=========================================================
  55. // Hack that tells us whether the GMan is in the final map
  56. //=========================================================
  57. bool CNPC_GMan::IsInC5A1()
  58. {
  59. const char *pMapName = STRING(gpGlobals->mapname);
  60. if( pMapName )
  61. {
  62. return !Q_strnicmp( pMapName, "c5a1", 4 );
  63. }
  64. return false;
  65. }
  66. //=========================================================
  67. // Classify - indicates this monster's place in the
  68. // relationship table.
  69. //=========================================================
  70. Class_T CNPC_GMan::Classify ( void )
  71. {
  72. return CLASS_NONE;
  73. }
  74. //=========================================================
  75. // HandleAnimEvent - catches the monster-specific messages
  76. // that occur when tagged animation frames are played.
  77. //=========================================================
  78. void CNPC_GMan::HandleAnimEvent( animevent_t *pEvent )
  79. {
  80. switch( pEvent->event )
  81. {
  82. case 1:
  83. default:
  84. BaseClass::HandleAnimEvent( pEvent );
  85. break;
  86. }
  87. }
  88. //=========================================================
  89. // GetSoundInterests - generic monster can't hear.
  90. //=========================================================
  91. int CNPC_GMan::GetSoundInterests ( void )
  92. {
  93. return NULL;
  94. }
  95. //=========================================================
  96. // Spawn
  97. //=========================================================
  98. void CNPC_GMan::Spawn()
  99. {
  100. Precache();
  101. BaseClass::Spawn();
  102. SetModel( "models/gman.mdl" );
  103. SetHullType(HULL_HUMAN);
  104. SetHullSizeNormal();
  105. SetSolid( SOLID_BBOX );
  106. AddSolidFlags( FSOLID_NOT_STANDABLE );
  107. SetMoveType( MOVETYPE_STEP );
  108. SetBloodColor( BLOOD_COLOR_MECH );
  109. m_iHealth = 8;
  110. m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result )
  111. m_NPCState = NPC_STATE_NONE;
  112. CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS | bits_CAP_USE_WEAPONS | bits_CAP_ANIMATEDFACE | bits_CAP_TURN_HEAD);
  113. NPCInit();
  114. }
  115. //=========================================================
  116. // Precache - precaches all resources this monster needs
  117. //=========================================================
  118. void CNPC_GMan::Precache()
  119. {
  120. PrecacheModel( "models/gman.mdl" );
  121. }
  122. //=========================================================
  123. // AI Schedules Specific to this monster
  124. //=========================================================
  125. void CNPC_GMan::StartTask( const Task_t *pTask )
  126. {
  127. switch( pTask->iTask )
  128. {
  129. case TASK_WAIT:
  130. if (m_hPlayer == NULL)
  131. {
  132. m_hPlayer = gEntList.FindEntityByClassname( NULL, "player" );
  133. }
  134. break;
  135. }
  136. BaseClass::StartTask( pTask );
  137. }
  138. void CNPC_GMan::RunTask( const Task_t *pTask )
  139. {
  140. switch( pTask->iTask )
  141. {
  142. case TASK_WAIT:
  143. // look at who I'm talking to
  144. if (m_flTalkTime > gpGlobals->curtime && m_hTalkTarget != NULL)
  145. {
  146. AddLookTarget( m_hTalkTarget->GetAbsOrigin(), 1.0, 2.0 );
  147. }
  148. // look at player, but only if playing a "safe" idle animation
  149. else if (m_hPlayer != NULL && (GetSequence() == 0 || IsInC5A1()) )
  150. {
  151. AddLookTarget( m_hPlayer->EyePosition(), 1.0, 3.0 );
  152. }
  153. else
  154. {
  155. // Just center the head forward.
  156. Vector forward;
  157. GetVectors( &forward, NULL, NULL );
  158. AddLookTarget( GetAbsOrigin() + forward * 12.0f, 1.0, 1.0 );
  159. SetBoneController( 0, 0 );
  160. }
  161. BaseClass::RunTask( pTask );
  162. break;
  163. }
  164. SetBoneController( 0, 0 );
  165. BaseClass::RunTask( pTask );
  166. }
  167. //=========================================================
  168. // Override all damage
  169. //=========================================================
  170. int CNPC_GMan::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo )
  171. {
  172. m_iHealth = m_iMaxHealth / 2; // always trigger the 50% damage aitrigger
  173. if ( inputInfo.GetDamage() > 0 )
  174. SetCondition( COND_LIGHT_DAMAGE );
  175. if ( inputInfo.GetDamage() >= 20 )
  176. SetCondition( COND_HEAVY_DAMAGE );
  177. return TRUE;
  178. }
  179. void CNPC_GMan::TraceAttack( CBaseEntity *pAttacker, float flDamage, const Vector &vecDir, trace_t *ptr, int bitsDamageType)
  180. {
  181. g_pEffects->Ricochet( ptr->endpos, ptr->plane.normal );
  182. // AddMultiDamage( pevAttacker, this, flDamage, bitsDamageType );
  183. }
  184. int CNPC_GMan::PlayScriptedSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, bool bConcurrent, CBaseEntity *pListener )
  185. {
  186. BaseClass::PlayScriptedSentence( pszSentence, delay, volume, soundlevel, bConcurrent, pListener );
  187. m_flTalkTime = gpGlobals->curtime + delay;
  188. m_hTalkTarget = pListener;
  189. return 1;
  190. }