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.

291 lines
7.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // TF Pumpkin Bomb
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "tf_pumpkin_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. #define PUMPKIN_MODEL "models/props_halloween/pumpkin_explode.mdl"
  22. #define TEAM_PUMPKIN "models/props_halloween/pumpkin_explode_teamcolor.mdl"
  23. LINK_ENTITY_TO_CLASS( tf_pumpkin_bomb, CTFPumpkinBomb );
  24. IMPLEMENT_NETWORKCLASS_ALIASED( TFPumpkinBomb, DT_TFPumpkinBomb )
  25. BEGIN_NETWORK_TABLE( CTFPumpkinBomb, DT_TFPumpkinBomb )
  26. END_NETWORK_TABLE()
  27. IMPLEMENT_AUTO_LIST( ITFPumpkinBomb );
  28. //-----------------------------------------------------------------------------
  29. // Purpose:
  30. //-----------------------------------------------------------------------------
  31. CTFPumpkinBomb::CTFPumpkinBomb()
  32. {
  33. #ifdef GAME_DLL
  34. m_bIsSpell = false;
  35. #endif
  36. m_bDead = false;
  37. m_bPrecached = false;
  38. m_iTeam = TF_TEAM_HALLOWEEN;
  39. m_flDamage = 150.0f;
  40. m_flScale = 1.0f;
  41. m_flRadius = 300.0f;
  42. m_flLifeTime = -1.0f;
  43. }
  44. //-----------------------------------------------------------------------------
  45. // Purpose:
  46. //-----------------------------------------------------------------------------
  47. void CTFPumpkinBomb::Precache()
  48. {
  49. BaseClass::Precache();
  50. // always allow late precaching, so we don't pay the cost of the
  51. // Halloween pumpkin bomb for the entire year
  52. bool bAllowPrecache = CBaseEntity::IsPrecacheAllowed();
  53. CBaseEntity::SetAllowPrecache( true );
  54. int iModel = PrecacheModel( PUMPKIN_MODEL );
  55. PrecacheGibsForModel( iModel );
  56. PrecacheModel( TEAM_PUMPKIN );
  57. PrecacheScriptSound( "Halloween.PumpkinExplode" );
  58. CBaseEntity::SetAllowPrecache( bAllowPrecache );
  59. m_bPrecached = true;
  60. }
  61. //-----------------------------------------------------------------------------
  62. void CTFPumpkinBomb::SetInitParams( float scale, float damage, float radius, int iTeam, float flLifeTime )
  63. {
  64. m_iTeam = iTeam;
  65. m_flDamage = damage;
  66. m_flScale = scale;
  67. m_flRadius = radius;
  68. if ( flLifeTime > 0 )
  69. {
  70. m_flLifeTime = flLifeTime;
  71. }
  72. }
  73. //-----------------------------------------------------------------------------
  74. void CTFPumpkinBomb::Spawn()
  75. {
  76. if ( !m_bPrecached )
  77. {
  78. Precache();
  79. }
  80. if ( m_iTeam != TF_TEAM_HALLOWEEN )
  81. {
  82. SetModel( TEAM_PUMPKIN );
  83. m_nSkin = m_iTeam == TF_TEAM_BLUE ? 2 : 1; // This is actually opposite of what you'd think so Blue team can Hurt Blue Pumpkins
  84. SetCollisionGroup( TFCOLLISION_GROUP_TANK );
  85. SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
  86. SetSolid( SOLID_BBOX );
  87. SetHealth( 1 );
  88. }
  89. else
  90. {
  91. SetModel( PUMPKIN_MODEL );
  92. SetMoveType( MOVETYPE_VPHYSICS );
  93. SetSolid( SOLID_VPHYSICS );
  94. SetHealth( 1 );
  95. }
  96. BaseClass::Spawn();
  97. SetModelScale( m_flScale );
  98. m_takedamage = DAMAGE_YES;
  99. m_bDead = false;
  100. SetTouch( &CTFPumpkinBombShim::Touch );
  101. #ifdef GAME_DLL
  102. if ( m_flLifeTime > 0 )
  103. {
  104. SetContextThink( &CTFPumpkinBomb::RemovePumpkin, gpGlobals->curtime + m_flLifeTime, "RemovePumpkin" );
  105. }
  106. #endif
  107. }
  108. //-----------------------------------------------------------------------------
  109. void CTFPumpkinBomb::RemovePumpkin()
  110. {
  111. #ifdef GAME_DLL
  112. CPVSFilter filter( GetAbsOrigin() );
  113. TE_TFParticleEffect( filter, 0.0, m_iTeam == TF_TEAM_RED ? "spell_pumpkin_mirv_goop_red" : "spell_pumpkin_mirv_goop_blue", GetAbsOrigin(), vec3_angle );
  114. UTIL_Remove( this );
  115. #endif // GAME_DLL
  116. }
  117. //-----------------------------------------------------------------------------
  118. // Purpose:
  119. //-----------------------------------------------------------------------------
  120. void CTFPumpkinBomb::PumpkinTouch( CBaseEntity *pOther )
  121. {
  122. if ( !pOther )
  123. return;
  124. #ifdef GAME_DLL
  125. if ( pOther->GetFlags() & FL_GRENADE )
  126. {
  127. // Only let my team destroy
  128. CBaseEntity *pAttacker = NULL;
  129. CBaseGrenade *pGrenade = dynamic_cast<CBaseGrenade*>(pOther);
  130. if ( pGrenade )
  131. {
  132. pAttacker = pGrenade->GetThrower();
  133. // Do a proper explosion
  134. Vector velDir = pGrenade->GetAbsVelocity();
  135. VectorNormalize( velDir );
  136. Vector vecSpot = pGrenade->GetAbsOrigin() - velDir * 32;
  137. trace_t tr;
  138. UTIL_TraceLine( vecSpot, vecSpot + velDir * 64, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
  139. // Boom
  140. pGrenade->Explode( &tr, DMG_BLAST );
  141. }
  142. else
  143. {
  144. CTFBaseRocket *pRocket = dynamic_cast<CTFBaseRocket*>(pOther);
  145. if ( pRocket )
  146. {
  147. Vector velDir = pRocket->GetAbsVelocity();
  148. VectorNormalize( velDir );
  149. Vector vecSpot = pRocket->GetAbsOrigin() - velDir * 32;
  150. trace_t tr;
  151. UTIL_TraceLine( vecSpot, vecSpot + velDir * 64, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
  152. pRocket->Explode( &tr, this );
  153. }
  154. }
  155. if ( !pAttacker )
  156. {
  157. CTFBaseProjectile *pProj = dynamic_cast<CTFBaseProjectile*>(pOther);
  158. if ( pProj )
  159. {
  160. pAttacker = pProj->GetScorer();
  161. }
  162. }
  163. if ( m_iTeam != TF_TEAM_HALLOWEEN && pOther->GetTeamNumber() != m_iTeam )
  164. {
  165. RemovePumpkin();
  166. }
  167. else
  168. {
  169. TakeDamage( CTakeDamageInfo( pOther, pAttacker, 10.f, DMG_CRUSH ) );
  170. }
  171. }
  172. else if ( FStrEq( STRING(pOther->m_iClassname), "trigger_hurt" ) )
  173. {
  174. RemovePumpkin();
  175. }
  176. #endif
  177. }
  178. //-----------------------------------------------------------------------------
  179. #ifdef GAME_DLL
  180. int CTFPumpkinBomb::OnTakeDamage( const CTakeDamageInfo &info )
  181. {
  182. CPVSFilter filter( GetAbsOrigin() );
  183. if ( m_iTeam != TF_TEAM_HALLOWEEN )
  184. {
  185. TE_TFParticleEffect( filter, 0.0, m_iTeam == TF_TEAM_RED ? "spell_pumpkin_mirv_goop_red" : "spell_pumpkin_mirv_goop_blue", GetAbsOrigin(), vec3_angle );
  186. }
  187. // if damage is from same team, Setlife to one and pass to base class
  188. if ( info.GetAttacker()->GetTeamNumber() == m_iTeam )
  189. {
  190. SetHealth( 1 );
  191. }
  192. else if ( m_iTeam != TF_TEAM_HALLOWEEN )
  193. {
  194. RemovePumpkin();
  195. return 0;
  196. }
  197. return BaseClass::OnTakeDamage( info );
  198. }
  199. //-----------------------------------------------------------------------------
  200. void CTFPumpkinBomb::Event_Killed( const CTakeDamageInfo &info )
  201. {
  202. if ( m_bDead )
  203. return;
  204. m_bDead = true;
  205. if ( m_iTeam != TF_TEAM_HALLOWEEN && info.GetAttacker()->GetTeamNumber() != m_iTeam )
  206. {
  207. RemovePumpkin();
  208. return;
  209. }
  210. trace_t tr;
  211. Vector vecSpot = GetAbsOrigin() + Vector ( 0 , 0 , 8 );
  212. UTIL_TraceLine( vecSpot, vecSpot + Vector ( 0, 0, -32 ), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr );
  213. // Explosion effect and gibs.
  214. Vector vecOrigin = GetAbsOrigin();
  215. QAngle vecAngles = GetAbsAngles();
  216. CPVSFilter filter( vecOrigin );
  217. TE_TFExplosion( filter, 0.0f, vecOrigin, tr.plane.normal, TF_WEAPON_PUMPKIN_BOMB, -1 );
  218. TE_TFParticleEffect( filter, 0.0f, "pumpkin_explode", vecOrigin, vecAngles );
  219. // Deal damage.
  220. SetSolid( SOLID_NONE );
  221. if ( info.GetAttacker() )
  222. {
  223. ChangeTeam( info.GetAttacker()->GetTeamNumber() );
  224. }
  225. CTakeDamageInfo damage_info( this, info.GetAttacker(), NULL, m_flDamage, DMG_BLAST | DMG_HALF_FALLOFF | DMG_NOCLOSEDISTANCEMOD );
  226. damage_info.SetDamageCustom( m_bIsSpell ? TF_DMG_CUSTOM_SPELL_MIRV : TF_DMG_CUSTOM_PUMPKIN_BOMB );
  227. if ( TFGameRules() )
  228. {
  229. CTFRadiusDamageInfo radiusinfo( &damage_info, vecOrigin, m_flRadius, this );
  230. TFGameRules()->RadiusDamage( radiusinfo );
  231. }
  232. // Don't decal players with scorch.
  233. if ( tr.m_pEnt && !tr.m_pEnt->IsPlayer() )
  234. {
  235. UTIL_DecalTrace( &tr, "Scorch" );
  236. }
  237. Break();
  238. BaseClass::Event_Killed( info );
  239. }
  240. void CTFPumpkinBomb::Break( void )
  241. {
  242. CPVSFilter filter( GetAbsOrigin() );
  243. UserMessageBegin( filter, "BreakModel" );
  244. WRITE_SHORT( GetModelIndex() );
  245. WRITE_VEC3COORD( GetAbsOrigin() );
  246. WRITE_ANGLES( GetAbsAngles() );
  247. WRITE_SHORT( m_nSkin );
  248. MessageEnd();
  249. }
  250. #endif