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.

283 lines
6.9 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Implements the big scary boom-boom machine Antlions fear.
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "baseentity.h"
  8. #include "npcevent.h"
  9. #include "rotorwash.h"
  10. #include "soundenvelope.h"
  11. #include "engine/IEngineSound.h"
  12. #include "npc_antlion.h"
  13. #include "te_effect_dispatch.h"
  14. #if HL2_EPISODIC
  15. #define THUMPER_RADIUS m_iEffectRadius // this const is only used inside the thumper anyway
  16. #else
  17. #define THUMPER_RADIUS 1000
  18. #endif
  19. #define STATE_CHANGE_MODIFIER 0.02f
  20. #define THUMPER_SOUND_DURATION 1.5f
  21. #define THUMPER_MIN_SCALE 128
  22. #define THUMPER_MODEL_NAME "models/props_combine/CombineThumper002.mdl"
  23. ConVar thumper_show_radius("thumper_show_radius","0",FCVAR_CHEAT,"If true, advisor will use her custom impact damage table.");
  24. class CPropThumper : public CBaseAnimating
  25. {
  26. public:
  27. DECLARE_CLASS( CPropThumper, CBaseAnimating );
  28. DECLARE_DATADESC();
  29. virtual void Spawn( void );
  30. virtual void Precache( void );
  31. virtual void Think ( void );
  32. virtual void HandleAnimEvent( animevent_t *pEvent );
  33. virtual void StopLoopingSounds( void );
  34. void InputDisable( inputdata_t &inputdata );
  35. void InputEnable( inputdata_t &inputdata );
  36. void InitMotorSound( void );
  37. void HandleState( void );
  38. void Thump( void );
  39. private:
  40. bool m_bEnabled;
  41. int m_iHammerAttachment;
  42. CSoundPatch* m_sndMotor;
  43. EHANDLE m_hRepellantEnt;
  44. int m_iDustScale;
  45. COutputEvent m_OnThumped; // Fired when thumper goes off
  46. #if HL2_EPISODIC
  47. int m_iEffectRadius;
  48. #endif
  49. };
  50. LINK_ENTITY_TO_CLASS( prop_thumper, CPropThumper );
  51. //-----------------------------------------------------------------------------
  52. // Save/load
  53. //-----------------------------------------------------------------------------
  54. BEGIN_DATADESC( CPropThumper )
  55. DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ),
  56. DEFINE_FIELD( m_hRepellantEnt, FIELD_EHANDLE ),
  57. DEFINE_FIELD( m_iHammerAttachment, FIELD_INTEGER ),
  58. DEFINE_KEYFIELD( m_iDustScale, FIELD_INTEGER, "dustscale" ),
  59. #if HL2_EPISODIC
  60. DEFINE_KEYFIELD( m_iEffectRadius, FIELD_INTEGER, "EffectRadius" ),
  61. #endif
  62. DEFINE_SOUNDPATCH( m_sndMotor ),
  63. DEFINE_THINKFUNC( Think ),
  64. DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
  65. DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
  66. DEFINE_OUTPUT( m_OnThumped, "OnThumped" ),
  67. END_DATADESC()
  68. void CPropThumper::Spawn( void )
  69. {
  70. char *szModel = (char *)STRING( GetModelName() );
  71. if (!szModel || !*szModel)
  72. {
  73. szModel = THUMPER_MODEL_NAME;
  74. SetModelName( AllocPooledString(szModel) );
  75. }
  76. Precache();
  77. SetModel( szModel );
  78. SetSolid( SOLID_VPHYSICS );
  79. SetMoveType( MOVETYPE_NONE );
  80. VPhysicsInitStatic();
  81. BaseClass::Spawn();
  82. m_bEnabled = true;
  83. SetThink( &CPropThumper::Think );
  84. SetNextThink( gpGlobals->curtime + 1.0f );
  85. int iSequence = SelectHeaviestSequence ( ACT_IDLE );
  86. if ( iSequence != ACT_INVALID )
  87. {
  88. SetSequence( iSequence );
  89. ResetSequenceInfo();
  90. //Do this so we get the nice ramp-up effect.
  91. m_flPlaybackRate = random->RandomFloat( 0.0f, 1.0f);
  92. }
  93. m_iHammerAttachment = LookupAttachment( "hammer" );
  94. CAntlionRepellant *pRepellant = (CAntlionRepellant*)CreateEntityByName( "point_antlion_repellant" );
  95. if ( pRepellant )
  96. {
  97. pRepellant->Spawn();
  98. pRepellant->SetAbsOrigin( GetAbsOrigin() );
  99. pRepellant->SetRadius( THUMPER_RADIUS );
  100. m_hRepellantEnt = pRepellant;
  101. }
  102. if ( m_iDustScale == 0 )
  103. m_iDustScale = THUMPER_MIN_SCALE;
  104. #if HL2_EPISODIC
  105. if ( m_iEffectRadius == 0 )
  106. m_iEffectRadius = 1000;
  107. #endif
  108. }
  109. void CPropThumper::Precache( void )
  110. {
  111. BaseClass::Precache();
  112. PrecacheModel( STRING( GetModelName() ) );
  113. PrecacheScriptSound( "coast.thumper_hit" );
  114. PrecacheScriptSound( "coast.thumper_ambient" );
  115. PrecacheScriptSound( "coast.thumper_dust" );
  116. PrecacheScriptSound( "coast.thumper_startup" );
  117. PrecacheScriptSound( "coast.thumper_shutdown" );
  118. PrecacheScriptSound( "coast.thumper_large_hit" );
  119. }
  120. void CPropThumper::InitMotorSound( void )
  121. {
  122. CPASAttenuationFilter filter( this );
  123. m_sndMotor = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_STATIC, "coast.thumper_ambient" , ATTN_NORM );
  124. if ( m_sndMotor )
  125. {
  126. (CSoundEnvelopeController::GetController()).Play( m_sndMotor, 1.0f, 100 );
  127. }
  128. }
  129. void CPropThumper::HandleState( void )
  130. {
  131. if ( m_bEnabled == false )
  132. {
  133. m_flPlaybackRate = MAX( m_flPlaybackRate - STATE_CHANGE_MODIFIER, 0.0f );
  134. }
  135. else
  136. {
  137. m_flPlaybackRate = MIN( m_flPlaybackRate + STATE_CHANGE_MODIFIER, 1.0f );
  138. }
  139. (CSoundEnvelopeController::GetController()).Play( m_sndMotor, 1.0f, m_flPlaybackRate * 100 );
  140. }
  141. void CPropThumper::Think( void )
  142. {
  143. StudioFrameAdvance();
  144. DispatchAnimEvents( this );
  145. SetNextThink( gpGlobals->curtime + 0.1 );
  146. if ( m_sndMotor == NULL )
  147. InitMotorSound();
  148. else
  149. HandleState();
  150. }
  151. void CPropThumper::Thump ( void )
  152. {
  153. if ( m_iHammerAttachment != -1 )
  154. {
  155. Vector vOrigin;
  156. GetAttachment( m_iHammerAttachment, vOrigin );
  157. CEffectData data;
  158. data.m_nEntIndex = entindex();
  159. data.m_vOrigin = vOrigin;
  160. data.m_flScale = m_iDustScale * m_flPlaybackRate;
  161. DispatchEffect( "ThumperDust", data );
  162. UTIL_ScreenShake( vOrigin, 10.0 * m_flPlaybackRate, m_flPlaybackRate, m_flPlaybackRate / 2, THUMPER_RADIUS * m_flPlaybackRate, SHAKE_START, false );
  163. }
  164. EmitSound( "coast.thumper_dust" );
  165. CSoundEnt::InsertSound ( SOUND_THUMPER, GetAbsOrigin(), THUMPER_RADIUS * m_flPlaybackRate, THUMPER_SOUND_DURATION, this );
  166. if ( thumper_show_radius.GetBool() )
  167. {
  168. NDebugOverlay::Box( GetAbsOrigin(), Vector(-THUMPER_RADIUS, -THUMPER_RADIUS, -THUMPER_RADIUS), Vector(THUMPER_RADIUS, THUMPER_RADIUS, THUMPER_RADIUS),
  169. 255, 64, 64, 255, THUMPER_SOUND_DURATION );
  170. }
  171. if ( m_flPlaybackRate < 0.7f )
  172. return;
  173. if( m_iDustScale == THUMPER_MIN_SCALE )
  174. EmitSound( "coast.thumper_hit" );
  175. else
  176. EmitSound( "coast.thumper_large_hit" );
  177. // Signal that we've thumped
  178. m_OnThumped.FireOutput( this, this );
  179. }
  180. void CPropThumper::HandleAnimEvent( animevent_t *pEvent )
  181. {
  182. if ( pEvent->event == AE_THUMPER_THUMP )
  183. {
  184. Thump();
  185. return;
  186. }
  187. BaseClass::HandleAnimEvent( pEvent );
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Shuts down sounds
  191. //-----------------------------------------------------------------------------
  192. void CPropThumper::StopLoopingSounds( void )
  193. {
  194. if ( m_sndMotor != NULL )
  195. {
  196. (CSoundEnvelopeController::GetController()).SoundDestroy( m_sndMotor );
  197. m_sndMotor = NULL;
  198. }
  199. BaseClass::StopLoopingSounds();
  200. }
  201. void CPropThumper::InputDisable( inputdata_t &inputdata )
  202. {
  203. m_bEnabled = false;
  204. EmitSound( "coast.thumper_shutdown" );
  205. if ( m_hRepellantEnt )
  206. {
  207. variant_t emptyVariant;
  208. m_hRepellantEnt->AcceptInput( "Disable", this, this, emptyVariant, 0 );
  209. }
  210. }
  211. void CPropThumper::InputEnable( inputdata_t &inputdata )
  212. {
  213. m_bEnabled = true;
  214. EmitSound( "coast.thumper_startup" );
  215. if ( m_hRepellantEnt )
  216. {
  217. variant_t emptyVariant;
  218. m_hRepellantEnt->AcceptInput( "Enable", this, this, emptyVariant, 0 );
  219. }
  220. }