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.

365 lines
8.9 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "grenade_satchel.h"
  10. #include "player.h"
  11. #include "soundenvelope.h"
  12. #include "engine/IEngineSound.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. ConVar sk_plr_dmg_satchel ( "sk_plr_dmg_satchel","0");
  16. ConVar sk_npc_dmg_satchel ( "sk_npc_dmg_satchel","0");
  17. ConVar sk_satchel_radius ( "sk_satchel_radius","0");
  18. BEGIN_DATADESC( CSatchelCharge )
  19. DEFINE_SOUNDPATCH( m_soundSlide ),
  20. DEFINE_FIELD( m_flSlideVolume, FIELD_FLOAT ),
  21. DEFINE_FIELD( m_flNextBounceSoundTime, FIELD_TIME ),
  22. DEFINE_FIELD( m_bInAir, FIELD_BOOLEAN ),
  23. DEFINE_FIELD( m_vLastPosition, FIELD_POSITION_VECTOR ),
  24. DEFINE_FIELD( m_pMyWeaponSLAM, FIELD_CLASSPTR ),
  25. DEFINE_FIELD( m_bIsAttached, FIELD_BOOLEAN ),
  26. // Function Pointers
  27. DEFINE_FUNCTION( SatchelTouch ),
  28. DEFINE_FUNCTION( SatchelThink ),
  29. DEFINE_FUNCTION( SatchelUse ),
  30. END_DATADESC()
  31. LINK_ENTITY_TO_CLASS( npc_satchel, CSatchelCharge );
  32. //=========================================================
  33. // Deactivate - do whatever it is we do to an orphaned
  34. // satchel when we don't want it in the world anymore.
  35. //=========================================================
  36. void CSatchelCharge::Deactivate( void )
  37. {
  38. AddSolidFlags( FSOLID_NOT_SOLID );
  39. UTIL_Remove( this );
  40. }
  41. void CSatchelCharge::Spawn( void )
  42. {
  43. Precache( );
  44. // motor
  45. SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
  46. SetSolid( SOLID_BBOX );
  47. SetCollisionGroup( COLLISION_GROUP_PROJECTILE );
  48. SetModel( "models/Weapons/w_slam.mdl" );
  49. UTIL_SetSize(this, Vector( -6, -6, -2), Vector(6, 6, 2));
  50. SetTouch( SatchelTouch );
  51. SetUse( SatchelUse );
  52. SetThink( SatchelThink );
  53. SetNextThink( gpGlobals->curtime + 0.1f );
  54. m_flDamage = sk_plr_dmg_satchel.GetFloat();
  55. m_DmgRadius = sk_satchel_radius.GetFloat();
  56. m_takedamage = DAMAGE_YES;
  57. m_iHealth = 1;
  58. SetGravity( UTIL_ScaleForGravity( 560 ) ); // slightly lower gravity
  59. SetFriction( 1.0 );
  60. SetSequence( 1 );
  61. m_bIsAttached = false;
  62. m_bInAir = true;
  63. m_flSlideVolume = -1.0;
  64. m_flNextBounceSoundTime = 0;
  65. m_vLastPosition = vec3_origin;
  66. InitSlideSound();
  67. }
  68. //-----------------------------------------------------------------------------
  69. void CSatchelCharge::InitSlideSound(void)
  70. {
  71. CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
  72. CPASAttenuationFilter filter( this );
  73. m_soundSlide = controller.SoundCreate( filter, entindex(), CHAN_STATIC, "SatchelCharge.Slide", ATTN_NORM );
  74. }
  75. //-----------------------------------------------------------------------------
  76. // Purpose:
  77. // Input :
  78. // Output :
  79. //-----------------------------------------------------------------------------
  80. void CSatchelCharge::KillSlideSound(void)
  81. {
  82. CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
  83. controller.CommandClear( m_soundSlide );
  84. controller.SoundFadeOut( m_soundSlide, 0.0 );
  85. }
  86. //-----------------------------------------------------------------------------
  87. // Purpose:
  88. // Input :
  89. // Output :
  90. //-----------------------------------------------------------------------------
  91. void CSatchelCharge::SatchelUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  92. {
  93. KillSlideSound();
  94. SetThink( Detonate );
  95. SetNextThink( gpGlobals->curtime );
  96. }
  97. //-----------------------------------------------------------------------------
  98. // Purpose:
  99. // Input :
  100. // Output :
  101. //-----------------------------------------------------------------------------
  102. void CSatchelCharge::SatchelTouch( CBaseEntity *pOther )
  103. {
  104. Assert( pOther );
  105. if ( !pOther->IsSolid() )
  106. return;
  107. // If successfully thrown and touching the
  108. // NPC that released this grenade, pick it up
  109. if ( pOther == GetThrower() && GetOwnerEntity() == NULL )
  110. {
  111. CBasePlayer *pPlayer = ToBasePlayer( m_pMyWeaponSLAM->GetOwner() );
  112. if (pPlayer)
  113. {
  114. // Give the player ammo
  115. pPlayer->GiveAmmo(1, m_pMyWeaponSLAM->m_iSecondaryAmmoType);
  116. CPASAttenuationFilter filter( pPlayer, "SatchelCharge.Pickup" );
  117. EmitSound( filter, pPlayer->entindex(), "SatchelCharge.Pickup" );
  118. m_bIsLive = false;
  119. // Take weapon out of detonate mode if necessary
  120. if (!m_pMyWeaponSLAM->AnyUndetonatedCharges())
  121. {
  122. m_pMyWeaponSLAM->m_bDetonatorArmed = false;
  123. m_pMyWeaponSLAM->m_bNeedDetonatorHolster = true;
  124. // Put detonator away right away
  125. m_pMyWeaponSLAM->SetWeaponIdleTime( gpGlobals->curtime );
  126. }
  127. // Kill any sliding sound
  128. KillSlideSound();
  129. // Remove satchel charge from world
  130. UTIL_Remove( this );
  131. return;
  132. }
  133. }
  134. StudioFrameAdvance( );
  135. // Is it attached to a wall?
  136. if (m_bIsAttached)
  137. {
  138. return;
  139. }
  140. SetGravity( 1 );// normal gravity now
  141. // HACKHACK - On ground isn't always set, so look for ground underneath
  142. trace_t tr;
  143. UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,10), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
  144. if ( tr.fraction < 1.0 )
  145. {
  146. // add a bit of static friction
  147. SetAbsVelocity( GetAbsVelocity() * 0.85 );
  148. SetLocalAngularVelocity( GetLocalAngularVelocity() * 0.8 );
  149. }
  150. UpdateSlideSound();
  151. if (m_bInAir)
  152. {
  153. BounceSound();
  154. m_bInAir = false;
  155. }
  156. }
  157. void CSatchelCharge::UpdateSlideSound( void )
  158. {
  159. if (!m_soundSlide)
  160. {
  161. return;
  162. }
  163. float volume = GetAbsVelocity().Length2D()/1000;
  164. if (volume < 0.01 && m_soundSlide)
  165. {
  166. KillSlideSound();
  167. return;
  168. }
  169. // HACKHACK - On ground isn't always set, so look for ground underneath
  170. trace_t tr;
  171. UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,10), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
  172. CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
  173. if ( tr.fraction < 1.0 )
  174. {
  175. if (m_flSlideVolume == -1.0)
  176. {
  177. controller.CommandClear( m_soundSlide );
  178. controller.Play( m_soundSlide, 1.0, 100 );
  179. m_flSlideVolume = 1.0;
  180. }
  181. else
  182. {
  183. float volume = GetAbsVelocity().Length()/1000;
  184. if ( volume < m_flSlideVolume )
  185. {
  186. m_flSlideVolume = volume;
  187. controller.CommandClear( m_soundSlide );
  188. controller.SoundChangeVolume( m_soundSlide, volume, 0.1 );
  189. }
  190. }
  191. }
  192. else
  193. {
  194. controller.CommandClear( m_soundSlide );
  195. controller.SoundChangeVolume( m_soundSlide, 0.0, 0.01 );
  196. m_flSlideVolume = -1.0;
  197. m_bInAir = true;
  198. return;
  199. }
  200. }
  201. void CSatchelCharge::SatchelThink( void )
  202. {
  203. // If attached resize so player can pick up off wall
  204. if (m_bIsAttached)
  205. {
  206. UTIL_SetSize(this, Vector( -2, -2, -6), Vector(2, 2, 6));
  207. }
  208. UpdateSlideSound();
  209. // See if I can lose my owner (has dropper moved out of way?)
  210. // Want do this so owner can shoot the satchel charge
  211. if (GetOwnerEntity())
  212. {
  213. trace_t tr;
  214. Vector vUpABit = GetAbsOrigin();
  215. vUpABit.z += 5.0;
  216. CBaseEntity* saveOwner = GetOwnerEntity();
  217. SetOwnerEntity( NULL );
  218. UTIL_TraceEntity( this, GetAbsOrigin(), vUpABit, MASK_SOLID, &tr );
  219. if ( tr.startsolid || tr.fraction != 1.0 )
  220. {
  221. SetOwnerEntity( saveOwner );
  222. }
  223. }
  224. // Bounce movement code gets this think stuck occasionally so check if I've
  225. // succeeded in moving, otherwise kill my motions.
  226. else if ((GetAbsOrigin() - m_vLastPosition).LengthSqr()<1)
  227. {
  228. SetAbsVelocity( vec3_origin );
  229. QAngle angVel = GetLocalAngularVelocity();
  230. angVel.y = 0;
  231. SetLocalAngularVelocity( angVel );
  232. // Kill any remaining sound
  233. KillSlideSound();
  234. // Clear think function
  235. SetThink(NULL);
  236. return;
  237. }
  238. m_vLastPosition= GetAbsOrigin();
  239. StudioFrameAdvance( );
  240. SetNextThink( gpGlobals->curtime + 0.1f );
  241. if (!IsInWorld())
  242. {
  243. // Kill any remaining sound
  244. KillSlideSound();
  245. UTIL_Remove( this );
  246. return;
  247. }
  248. // Is it attached to a wall?
  249. if (m_bIsAttached)
  250. {
  251. return;
  252. }
  253. Vector vecNewVel = GetAbsVelocity();
  254. if (GetWaterLevel() == 3)
  255. {
  256. SetMoveType( MOVETYPE_FLY );
  257. vecNewVel *= 0.8;
  258. vecNewVel.z += 8;
  259. SetLocalAngularVelocity( GetLocalAngularVelocity() * 0.9 );
  260. }
  261. else if (GetWaterLevel() == 0)
  262. {
  263. SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
  264. }
  265. else
  266. {
  267. vecNewVel.z -= 8;
  268. }
  269. SetAbsVelocity( vecNewVel );
  270. }
  271. void CSatchelCharge::Precache( void )
  272. {
  273. PrecacheModel("models/Weapons/w_slam.mdl");
  274. PrecacheScriptSound( "SatchelCharge.Pickup" );
  275. PrecacheScriptSound( "SatchelCharge.Bounce" );
  276. PrecacheScriptSound( "SatchelCharge.Slide" );
  277. }
  278. void CSatchelCharge::BounceSound( void )
  279. {
  280. if (gpGlobals->curtime > m_flNextBounceSoundTime)
  281. {
  282. EmitSound( "SatchelCharge.Bounce" );
  283. m_flNextBounceSoundTime = gpGlobals->curtime + 0.1;
  284. }
  285. }
  286. //-----------------------------------------------------------------------------
  287. // Purpose: Constructor
  288. // Input :
  289. // Output :
  290. //-----------------------------------------------------------------------------
  291. CSatchelCharge::CSatchelCharge(void)
  292. {
  293. m_vLastPosition.Init();
  294. m_pMyWeaponSLAM = NULL;
  295. }
  296. CSatchelCharge::~CSatchelCharge(void)
  297. {
  298. CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
  299. controller.SoundDestroy( m_soundSlide );
  300. }