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.

251 lines
6.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // TF Generic Bomb
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "tf_generic_bomb.h"
  8. #include "takedamageinfo.h"
  9. #include "tf_shareddefs.h"
  10. #include "props_shared.h"
  11. #ifdef GAME_DLL
  12. #include "te_effect_dispatch.h"
  13. #include "tf_fx.h"
  14. #include "tf_projectile_base.h"
  15. #include "basegrenade_shared.h"
  16. #include "tf_gamerules.h"
  17. #include "tf_weaponbase_rocket.h"
  18. #endif
  19. // memdbgon must be the last include file in a .cpp file!!!
  20. #include "tier0/memdbgon.h"
  21. LINK_ENTITY_TO_CLASS( tf_generic_bomb, CTFGenericBomb );
  22. IMPLEMENT_NETWORKCLASS_ALIASED( TFGenericBomb, DT_TFGenericBomb )
  23. BEGIN_NETWORK_TABLE( CTFGenericBomb, DT_TFGenericBomb )
  24. END_NETWORK_TABLE()
  25. IMPLEMENT_AUTO_LIST( ITFGenericBomb );
  26. #ifdef GAME_DLL
  27. BEGIN_DATADESC( CTFGenericBomb )
  28. // Keyfields
  29. DEFINE_KEYFIELD( m_flDamage, FIELD_FLOAT, "damage" ),
  30. DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ),
  31. DEFINE_KEYFIELD( m_nHealth, FIELD_INTEGER, "health" ),
  32. DEFINE_KEYFIELD( m_strExplodeParticleName, FIELD_STRING, "explode_particle" ),
  33. DEFINE_KEYFIELD( m_strExplodeSoundName, FIELD_STRING, "sound" ),
  34. DEFINE_KEYFIELD( m_eWhoToDamage, FIELD_INTEGER, "friendlyfire" ),
  35. // Output
  36. DEFINE_OUTPUT( m_OnDetonate, "OnDetonate" ),
  37. // Input
  38. DEFINE_INPUTFUNC( FIELD_VOID, "Detonate", Detonate ),
  39. END_DATADESC()
  40. #endif
  41. //-----------------------------------------------------------------------------
  42. // Purpose:
  43. //-----------------------------------------------------------------------------
  44. CTFGenericBomb::CTFGenericBomb()
  45. {
  46. m_bDead = false;
  47. m_bPrecached = false;
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Purpose:
  51. //-----------------------------------------------------------------------------
  52. void CTFGenericBomb::Precache()
  53. {
  54. BaseClass::Precache();
  55. // always allow late precaching
  56. bool bAllowPrecache = CBaseEntity::IsPrecacheAllowed();
  57. CBaseEntity::SetAllowPrecache( true );
  58. int iModel = PrecacheModel( STRING( GetModelName() ) );
  59. PrecacheGibsForModel( iModel );
  60. PrecacheModel( STRING( GetModelName() ) );
  61. if ( STRING( m_strExplodeParticleName ) && STRING( m_strExplodeParticleName )[0] )
  62. {
  63. PrecacheParticleSystem( STRING( m_strExplodeParticleName ) );
  64. }
  65. if ( STRING( m_strExplodeSoundName ) && STRING( m_strExplodeSoundName )[0] )
  66. {
  67. PrecacheScriptSound( STRING( m_strExplodeSoundName ) );
  68. }
  69. CBaseEntity::SetAllowPrecache( bAllowPrecache );
  70. m_bPrecached = true;
  71. }
  72. //-----------------------------------------------------------------------------
  73. void CTFGenericBomb::Spawn()
  74. {
  75. if ( !m_bPrecached )
  76. {
  77. Precache();
  78. }
  79. #ifdef GAME_DLL
  80. SetModel( STRING( GetModelName() ) );
  81. #endif
  82. SetMoveType( MOVETYPE_VPHYSICS );
  83. SetSolid( SOLID_VPHYSICS );
  84. SetHealth( m_nHealth );
  85. BaseClass::Spawn();
  86. m_takedamage = DAMAGE_YES;
  87. m_bDead = false;
  88. SetTouch( &CTFGenericBombShim::Touch );
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Purpose:
  92. //-----------------------------------------------------------------------------
  93. void CTFGenericBomb::GenericTouch( CBaseEntity *pOther )
  94. {
  95. if ( !pOther )
  96. return;
  97. #ifdef GAME_DLL
  98. if ( pOther->GetFlags() & FL_GRENADE )
  99. {
  100. // Only let my team destroy
  101. CBaseEntity *pAttacker = NULL;
  102. CBaseGrenade *pGrenade = dynamic_cast<CBaseGrenade*>(pOther);
  103. if ( pGrenade )
  104. {
  105. pAttacker = pGrenade->GetThrower();
  106. // Do a proper explosion
  107. Vector velDir = pGrenade->GetAbsVelocity();
  108. VectorNormalize( velDir );
  109. Vector vecSpot = pGrenade->GetAbsOrigin() - velDir * 32;
  110. trace_t tr;
  111. UTIL_TraceLine( vecSpot, vecSpot + velDir * 64, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
  112. // Boom
  113. pGrenade->Explode( &tr, DMG_BLAST );
  114. }
  115. else
  116. {
  117. CTFBaseRocket *pRocket = dynamic_cast<CTFBaseRocket*>(pOther);
  118. if ( pRocket )
  119. {
  120. Vector velDir = pRocket->GetAbsVelocity();
  121. VectorNormalize( velDir );
  122. Vector vecSpot = pRocket->GetAbsOrigin() - velDir * 32;
  123. trace_t tr;
  124. UTIL_TraceLine( vecSpot, vecSpot + velDir * 64, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
  125. pRocket->Explode( &tr, this );
  126. }
  127. }
  128. if ( !pAttacker )
  129. {
  130. CTFBaseProjectile *pProj = dynamic_cast<CTFBaseProjectile*>(pOther);
  131. if ( pProj )
  132. {
  133. pAttacker = pProj->GetScorer();
  134. }
  135. }
  136. TakeDamage( CTakeDamageInfo( pOther, pAttacker, 10.f, DMG_CRUSH ) );
  137. }
  138. #endif
  139. }
  140. //-----------------------------------------------------------------------------
  141. #ifdef GAME_DLL
  142. void CTFGenericBomb::Detonate( inputdata_t& inputdata )
  143. {
  144. CTakeDamageInfo info;
  145. Event_Killed( info );
  146. }
  147. //-----------------------------------------------------------------------------
  148. void CTFGenericBomb::Event_Killed( const CTakeDamageInfo &info )
  149. {
  150. if ( m_bDead )
  151. return;
  152. m_bDead = true;
  153. trace_t tr;
  154. Vector vecSpot = GetAbsOrigin() + Vector ( 0 , 0 , 8 );
  155. UTIL_TraceLine( vecSpot, vecSpot + Vector ( 0, 0, -32 ), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr );
  156. // Explosion effect and gibs.
  157. Vector vecOrigin = GetAbsOrigin();
  158. QAngle vecAngles = GetAbsAngles();
  159. int iAttachment = LookupAttachment( "alt-origin" );
  160. if ( iAttachment > 0 )
  161. {
  162. GetAttachment( iAttachment, vecOrigin, vecAngles );
  163. }
  164. CPVSFilter pvsFilter( vecOrigin );
  165. if ( STRING( m_strExplodeParticleName ) && STRING( m_strExplodeParticleName )[0] )
  166. {
  167. TE_TFParticleEffect( pvsFilter, 0.0f, STRING( m_strExplodeParticleName ), vecOrigin, vecAngles );
  168. }
  169. if ( STRING( m_strExplodeSoundName ) && STRING( m_strExplodeSoundName )[0] )
  170. {
  171. EmitSound( STRING( m_strExplodeSoundName ) );
  172. }
  173. // Get the owner out of the attacker in case of arrows hitting the bomb.
  174. CBaseEntity* pAttacker = info.GetAttacker();
  175. if ( pAttacker && pAttacker->GetOwnerEntity() )
  176. {
  177. pAttacker = pAttacker->GetOwnerEntity();
  178. }
  179. // Deal damage.
  180. SetSolid( SOLID_NONE );
  181. if ( pAttacker )
  182. {
  183. ChangeTeam( pAttacker->GetTeamNumber() );
  184. }
  185. CTakeDamageInfo damage_info( this, pAttacker, NULL, m_flDamage, DMG_BLAST | DMG_HALF_FALLOFF | DMG_NOCLOSEDISTANCEMOD );
  186. damage_info.SetDamageCustom( TF_DMG_CUSTOM_NONE );
  187. damage_info.SetForceFriendlyFire( m_eWhoToDamage == DAMAGE_EVERYONE );
  188. if ( TFGameRules() )
  189. {
  190. CTFRadiusDamageInfo radiusinfo( &damage_info, vecOrigin, m_flRadius, this );
  191. TFGameRules()->RadiusDamage( radiusinfo );
  192. }
  193. // Don't decal players with scorch.
  194. if ( tr.m_pEnt && !tr.m_pEnt->IsPlayer() )
  195. {
  196. UTIL_DecalTrace( &tr, "Scorch" );
  197. }
  198. // Spawns gibs on the client
  199. UserMessageBegin( pvsFilter, "BreakModel" );
  200. WRITE_SHORT( GetModelIndex() );
  201. WRITE_VEC3COORD( vecOrigin );
  202. WRITE_ANGLES( vecAngles );
  203. WRITE_SHORT( m_nSkin );
  204. MessageEnd();
  205. m_OnDetonate.FireOutput( this, this );
  206. BaseClass::Event_Killed( info );
  207. }
  208. #endif