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.

266 lines
6.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Implements the tripmine grenade.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "beam_shared.h"
  9. #include "shake.h"
  10. #include "grenade_tripmine.h"
  11. #include "vstdlib/random.h"
  12. #include "engine/IEngineSound.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. extern const char* g_pModelNameLaser;
  16. ConVar sk_plr_dmg_tripmine ( "sk_plr_dmg_tripmine","0");
  17. ConVar sk_npc_dmg_tripmine ( "sk_npc_dmg_tripmine","0");
  18. ConVar sk_tripmine_radius ( "sk_tripmine_radius","0");
  19. LINK_ENTITY_TO_CLASS( npc_tripmine, CTripmineGrenade );
  20. BEGIN_DATADESC( CTripmineGrenade )
  21. DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ),
  22. DEFINE_FIELD( m_flPowerUp, FIELD_TIME ),
  23. DEFINE_FIELD( m_vecDir, FIELD_VECTOR ),
  24. DEFINE_FIELD( m_vecEnd, FIELD_POSITION_VECTOR ),
  25. DEFINE_FIELD( m_flBeamLength, FIELD_FLOAT ),
  26. DEFINE_FIELD( m_pBeam, FIELD_CLASSPTR ),
  27. DEFINE_FIELD( m_posOwner, FIELD_POSITION_VECTOR ),
  28. DEFINE_FIELD( m_angleOwner, FIELD_VECTOR ),
  29. // Function Pointers
  30. DEFINE_FUNCTION( WarningThink ),
  31. DEFINE_FUNCTION( PowerupThink ),
  32. DEFINE_FUNCTION( BeamBreakThink ),
  33. DEFINE_FUNCTION( DelayDeathThink ),
  34. END_DATADESC()
  35. CTripmineGrenade::CTripmineGrenade()
  36. {
  37. m_vecDir.Init();
  38. m_vecEnd.Init();
  39. m_posOwner.Init();
  40. m_angleOwner.Init();
  41. }
  42. void CTripmineGrenade::Spawn( void )
  43. {
  44. Precache( );
  45. // motor
  46. SetMoveType( MOVETYPE_FLY );
  47. SetSolid( SOLID_BBOX );
  48. AddSolidFlags( FSOLID_NOT_SOLID );
  49. SetModel( "models/Weapons/w_slam.mdl" );
  50. m_flCycle = 0;
  51. m_nBody = 3;
  52. m_flDamage = sk_plr_dmg_tripmine.GetFloat();
  53. m_DmgRadius = sk_tripmine_radius.GetFloat();
  54. ResetSequenceInfo( );
  55. m_flPlaybackRate = 0;
  56. UTIL_SetSize(this, Vector( -4, -4, -2), Vector(4, 4, 2));
  57. m_flPowerUp = gpGlobals->curtime + 2.0;
  58. SetThink( PowerupThink );
  59. SetNextThink( gpGlobals->curtime + 0.2 );
  60. m_takedamage = DAMAGE_YES;
  61. m_iHealth = 1;
  62. EmitSound( "TripmineGrenade.Charge" );
  63. // Tripmine sits at 90 on wall so rotate back to get m_vecDir
  64. QAngle angles = GetLocalAngles();
  65. angles.x -= 90;
  66. AngleVectors( angles, &m_vecDir );
  67. m_vecEnd = GetLocalOrigin() + m_vecDir * 2048;
  68. }
  69. void CTripmineGrenade::Precache( void )
  70. {
  71. PrecacheModel("models/Weapons/w_slam.mdl");
  72. PrecacheScriptSound( "TripmineGrenade.Charge" );
  73. PrecacheScriptSound( "TripmineGrenade.PowerUp" );
  74. PrecacheScriptSound( "TripmineGrenade.StopSound" );
  75. PrecacheScriptSound( "TripmineGrenade.Activate" );
  76. PrecacheScriptSound( "TripmineGrenade.ShootRope" );
  77. PrecacheScriptSound( "TripmineGrenade.Hook" );
  78. }
  79. void CTripmineGrenade::WarningThink( void )
  80. {
  81. // set to power up
  82. SetThink( PowerupThink );
  83. SetNextThink( gpGlobals->curtime + 1.0f );
  84. }
  85. void CTripmineGrenade::PowerupThink( void )
  86. {
  87. if (gpGlobals->curtime > m_flPowerUp)
  88. {
  89. MakeBeam( );
  90. RemoveSolidFlags( FSOLID_NOT_SOLID );
  91. m_bIsLive = true;
  92. // play enabled sound
  93. EmitSound( "TripmineGrenade.PowerUp" );;
  94. }
  95. SetNextThink( gpGlobals->curtime + 0.1f );
  96. }
  97. void CTripmineGrenade::KillBeam( void )
  98. {
  99. if ( m_pBeam )
  100. {
  101. UTIL_Remove( m_pBeam );
  102. m_pBeam = NULL;
  103. }
  104. }
  105. void CTripmineGrenade::MakeBeam( void )
  106. {
  107. trace_t tr;
  108. UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
  109. m_flBeamLength = tr.fraction;
  110. // If I hit a living thing, send the beam through me so it turns on briefly
  111. // and then blows the living thing up
  112. CBaseEntity *pEntity = tr.m_pEnt;
  113. CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity );
  114. // Draw length is not the beam length if entity is in the way
  115. float drawLength = tr.fraction;
  116. if (pBCC)
  117. {
  118. SetOwnerEntity( pBCC );
  119. UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
  120. m_flBeamLength = tr.fraction;
  121. SetOwnerEntity( NULL );
  122. }
  123. // set to follow laser spot
  124. SetThink( BeamBreakThink );
  125. // Delay first think slightly so beam has time
  126. // to appear if person right in front of it
  127. SetNextThink( gpGlobals->curtime + 1.0f );
  128. Vector vecTmpEnd = GetLocalOrigin() + m_vecDir * 2048 * drawLength;
  129. m_pBeam = CBeam::BeamCreate( g_pModelNameLaser, 1.0 );
  130. m_pBeam->PointEntInit( vecTmpEnd, this );
  131. m_pBeam->SetColor( 0, 214, 198 );
  132. m_pBeam->SetScrollRate( 25.6 );
  133. m_pBeam->SetBrightness( 64 );
  134. }
  135. void CTripmineGrenade::BeamBreakThink( void )
  136. {
  137. // See if I can go solid yet (has dropper moved out of way?)
  138. if (IsSolidFlagSet( FSOLID_NOT_SOLID ))
  139. {
  140. trace_t tr;
  141. Vector vUpBit = GetAbsOrigin();
  142. vUpBit.z += 5.0;
  143. UTIL_TraceEntity( this, GetAbsOrigin(), vUpBit, MASK_SHOT, &tr );
  144. if ( !tr.startsolid && (tr.fraction == 1.0) )
  145. {
  146. RemoveSolidFlags( FSOLID_NOT_SOLID );
  147. }
  148. }
  149. trace_t tr;
  150. // NOT MASK_SHOT because we want only simple hit boxes
  151. UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
  152. // ALERT( at_console, "%f : %f\n", tr.flFraction, m_flBeamLength );
  153. // respawn detect.
  154. if ( !m_pBeam )
  155. {
  156. MakeBeam( );
  157. if ( tr.m_pEnt )
  158. m_hOwner = tr.m_pEnt; // reset owner too
  159. }
  160. CBaseEntity *pEntity = tr.m_pEnt;
  161. CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity );
  162. if (pBCC || fabs( m_flBeamLength - tr.fraction ) > 0.001)
  163. {
  164. m_iHealth = 0;
  165. Event_Killed( CTakeDamageInfo( (CBaseEntity*)m_hOwner, this, 100, GIB_NORMAL ) );
  166. return;
  167. }
  168. SetNextThink( gpGlobals->curtime + 0.1f );
  169. }
  170. int CTripmineGrenade::OnTakeDamage_Alive( const CTakeDamageInfo &info )
  171. {
  172. if (gpGlobals->curtime < m_flPowerUp && info.GetDamage() < m_iHealth)
  173. {
  174. // disable
  175. // Create( "weapon_tripmine", GetLocalOrigin() + m_vecDir * 24, GetAngles() );
  176. SetThink( SUB_Remove );
  177. SetNextThink( gpGlobals->curtime + 0.1f );
  178. KillBeam();
  179. return FALSE;
  180. }
  181. return BaseClass::OnTakeDamage_Alive( info );
  182. }
  183. //-----------------------------------------------------------------------------
  184. // Purpose:
  185. // Input :
  186. // Output :
  187. //-----------------------------------------------------------------------------
  188. void CTripmineGrenade::Event_Killed( const CTakeDamageInfo &info )
  189. {
  190. m_takedamage = DAMAGE_NO;
  191. SetThink( DelayDeathThink );
  192. SetNextThink( gpGlobals->curtime + 0.5 );
  193. EmitSound( "TripmineGrenade.StopSound" );
  194. }
  195. void CTripmineGrenade::DelayDeathThink( void )
  196. {
  197. KillBeam();
  198. trace_t tr;
  199. UTIL_TraceLine ( GetAbsOrigin() + m_vecDir * 8, GetAbsOrigin() - m_vecDir * 64, MASK_SOLID, this, COLLISION_GROUP_NONE, & tr);
  200. UTIL_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START );
  201. Explode( &tr, DMG_BLAST );
  202. }