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.

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