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.

238 lines
7.2 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // TF Pumpkin Bomb
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "particle_parse.h"
  8. #include "tf_player.h"
  9. #include "tf_gamerules.h"
  10. #include "tf_target_dummy.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. #include "tf_ammo_pack.h"
  14. #define DUMMY_MODEL "models/props_training/target_engineer.mdl"
  15. #define DUMMY_DEMO_MODEL "models/props_training/target_demoman.mdl"
  16. //#define TEAM_PUMPKIN "models/props_halloween/pumpkin_explode_teamcolor.mdl"
  17. LINK_ENTITY_TO_CLASS( tf_target_dummy, CTFTargetDummy);
  18. IMPLEMENT_AUTO_LIST( ITFTargetDummy );
  19. ConVar tf_target_dummy_health( "tf_target_dummy_health", "200", FCVAR_GAMEDLL | FCVAR_DEVELOPMENTONLY ); // DEV ONLY
  20. ConVar tf_target_dummy_melee_mult( "tf_target_dummy_melee_mult", "3.0f", FCVAR_GAMEDLL | FCVAR_DEVELOPMENTONLY ); // DEV ONLY
  21. ConVar tf_target_dummy_bullet_mult( "tf_target_dummy_bullet_mult", "0.1f", FCVAR_GAMEDLL | FCVAR_DEVELOPMENTONLY ); // DEV ONLY
  22. ConVar tf_target_dummy_other_mult( "tf_target_dummy_other_mult", "0.2f", FCVAR_GAMEDLL | FCVAR_DEVELOPMENTONLY ); // DEV ONLY
  23. ConVar tf_target_dummy_lifetime( "tf_target_dummy_lifetime", "30.0f", FCVAR_GAMEDLL | FCVAR_DEVELOPMENTONLY ); // DEV ONLY
  24. #ifdef GAME_DLL
  25. extern ConVar tf_obj_gib_velocity_min;
  26. extern ConVar tf_obj_gib_velocity_max;
  27. extern ConVar tf_obj_gib_maxspeed;
  28. #endif
  29. //-----------------------------------------------------------------------------
  30. // Static
  31. CTFTargetDummy* CTFTargetDummy::Create( const Vector& vPosition, const QAngle& qAngles, CTFPlayer *pOwner )
  32. {
  33. QAngle qProper = qAngles;
  34. qProper.z = 0;
  35. qProper.x = 0;
  36. CTFTargetDummy *pDummy = assert_cast<CTFTargetDummy*>( CBaseEntity::Create( "tf_target_dummy", vPosition, qProper, pOwner ) );
  37. if ( pDummy && pOwner )
  38. {
  39. pDummy->ChangeTeam( pOwner->GetTeamNumber() );
  40. pDummy->m_nSkin = pOwner->GetTeamNumber() == TF_TEAM_BLUE ? 1 : 2;
  41. }
  42. return pDummy;
  43. }
  44. //-----------------------------------------------------------------------------
  45. CTFTargetDummy::CTFTargetDummy()
  46. {
  47. }
  48. //-----------------------------------------------------------------------------
  49. // Purpose:
  50. //-----------------------------------------------------------------------------
  51. void CTFTargetDummy::Precache( void )
  52. {
  53. PrecacheModel( DUMMY_MODEL );
  54. int iModel = PrecacheModel( DUMMY_DEMO_MODEL );
  55. PrecacheGibsForModel( iModel );
  56. PrecacheParticleSystem( "target_break" );
  57. PrecacheParticleSystem( "lowV_debrischunks" );
  58. BaseClass::Precache();
  59. }
  60. //-----------------------------------------------------------------------------
  61. void CTFTargetDummy::Spawn()
  62. {
  63. Precache();
  64. m_aGibs.Purge();
  65. // TODO: Model Selection
  66. if ( RandomInt( 0, 1 ) == 1 )
  67. {
  68. SetModel( DUMMY_DEMO_MODEL );
  69. BuildGibList( m_aGibs, GetModelIndex(), 1.0f, COLLISION_GROUP_NONE );
  70. }
  71. else
  72. {
  73. SetModel( DUMMY_MODEL );
  74. }
  75. // Set Team
  76. BaseClass::Spawn();
  77. SetMoveType( MOVETYPE_NONE );
  78. SetSolid( SOLID_VPHYSICS );
  79. SetCollisionGroup( TFCOLLISION_GROUP_OBJECT );
  80. //SetSolidFlags( FSOLID_TRIGGER );
  81. m_takedamage = DAMAGE_YES;
  82. SetHealth( tf_target_dummy_health.GetInt() );
  83. //DispatchParticleEffect( "merasmus_object_spawn", WorldSpaceCenter(), GetAbsAngles() );
  84. SetContextThink( &CTFTargetDummy::DestroyThink, gpGlobals->curtime + tf_target_dummy_lifetime.GetFloat(), "DestroyThink" );
  85. }
  86. //-----------------------------------------------------------------------------
  87. void CTFTargetDummy::Event_Killed( const CTakeDamageInfo &info )
  88. {
  89. EmitSound( "Halloween.Merasmus_Hiding_Explode" );
  90. BaseClass::Event_Killed( info );
  91. }
  92. //-----------------------------------------------------------------------------
  93. int CTFTargetDummy::OnTakeDamage( const CTakeDamageInfo &info )
  94. {
  95. DispatchParticleEffect( "lowV_debrischunks", info.GetDamagePosition(), GetAbsAngles() );
  96. CTakeDamageInfo newinfo = info;
  97. if ( InSameTeam( info.GetAttacker() ))
  98. {
  99. return 0;
  100. }
  101. // melee and fire is normal
  102. // bullet is heavily reduced
  103. // everything else (blast/ energy etc..) reduced
  104. //CTFPlayer *pTFPlayer = ToTFPlayer( newinfo.GetAttacker() );
  105. if ( ( newinfo.GetDamageType() & DMG_BUCKSHOT ) || ( newinfo.GetDamageType() & DMG_BULLET ) )
  106. {
  107. newinfo.SetDamage( newinfo.GetDamage() * tf_target_dummy_bullet_mult.GetFloat() );
  108. }
  109. else if ( ( newinfo.GetDamageType() & DMG_CLUB ) || ( newinfo.GetDamageType() & DMG_BURN ) )
  110. {
  111. newinfo.SetDamage( newinfo.GetDamage() * tf_target_dummy_melee_mult.GetFloat() );
  112. }
  113. else
  114. {
  115. newinfo.SetDamage( newinfo.GetDamage() * tf_target_dummy_other_mult.GetFloat() );
  116. }
  117. int iDamage = BaseClass::OnTakeDamage( newinfo );
  118. if ( m_iHealth <= 0 )
  119. {
  120. Destroy();
  121. }
  122. return iDamage;
  123. }
  124. //-----------------------------------------------------------------------------
  125. void CTFTargetDummy::DestroyThink()
  126. {
  127. // Blow us up.
  128. //CTakeDamageInfo info( this, this, vec3_origin, GetAbsOrigin(), 0, DMG_GENERIC );
  129. //Killed( info );
  130. Destroy();
  131. UTIL_Remove( this );
  132. }
  133. //-----------------------------------------------------------------------------
  134. void CTFTargetDummy::Destroy()
  135. {
  136. SpewGibs();
  137. DispatchParticleEffect( "target_break", WorldSpaceCenter(), GetAbsAngles() );
  138. }
  139. //-----------------------------------------------------------------------------
  140. void CTFTargetDummy::SpewGibs()
  141. {
  142. for ( int i = 0; i < m_aGibs.Count(); i++ )
  143. {
  144. CTFAmmoPack *pAmmoPack = CTFAmmoPack::Create( GetAbsOrigin() + m_aGibs[i].offset, GetAbsAngles(), this, m_aGibs[i].modelName );
  145. Assert( pAmmoPack );
  146. if ( pAmmoPack )
  147. {
  148. pAmmoPack->ActivateWhenAtRest();
  149. // Calculate the initial impulse on the weapon.
  150. Vector vecImpulse( random->RandomFloat( -0.5f, 0.5f ), random->RandomFloat( -0.5f, 0.5f ), random->RandomFloat( 0.75f, 1.25f ) );
  151. VectorNormalize( vecImpulse );
  152. vecImpulse *= random->RandomFloat( tf_obj_gib_velocity_min.GetFloat(), tf_obj_gib_velocity_max.GetFloat() );
  153. // Cap the impulse.
  154. float flSpeed = vecImpulse.Length();
  155. if ( flSpeed > tf_obj_gib_maxspeed.GetFloat() )
  156. {
  157. VectorScale( vecImpulse, tf_obj_gib_maxspeed.GetFloat() / flSpeed, vecImpulse );
  158. }
  159. if ( pAmmoPack->VPhysicsGetObject() )
  160. {
  161. AngularImpulse angImpulse( 0.f, random->RandomFloat( 0.f, 100.f ), 0.f );
  162. pAmmoPack->VPhysicsGetObject()->SetVelocityInstantaneous( &vecImpulse, &angImpulse );
  163. }
  164. pAmmoPack->SetInitialVelocity( vecImpulse );
  165. pAmmoPack->m_nSkin = ( GetTeamNumber() == TF_TEAM_RED ) ? 0 : 1;
  166. // Give the ammo pack some health, so that trains can destroy it.
  167. pAmmoPack->SetCollisionGroup( COLLISION_GROUP_DEBRIS );
  168. pAmmoPack->m_takedamage = DAMAGE_YES;
  169. pAmmoPack->SetHealth( 900 );
  170. pAmmoPack->m_bObjGib = true;
  171. pAmmoPack->GiveAmmo( 0, TF_AMMO_METAL );
  172. }
  173. }
  174. }
  175. //-----------------------------------------------------------------------------
  176. bool CTFTargetDummy::ShouldCollide( int collisionGroup, int contentsMask ) const
  177. {
  178. if ( collisionGroup == COLLISION_GROUP_PLAYER_MOVEMENT )
  179. {
  180. if ( GetCollisionGroup() == TFCOLLISION_GROUP_OBJECT_SOLIDTOPLAYERMOVEMENT )
  181. {
  182. return true;
  183. }
  184. switch ( GetTeamNumber() )
  185. {
  186. case TF_TEAM_RED:
  187. if ( !( contentsMask & CONTENTS_REDTEAM ) )
  188. return false;
  189. break;
  190. case TF_TEAM_BLUE:
  191. if ( !( contentsMask & CONTENTS_BLUETEAM ) )
  192. return false;
  193. break;
  194. }
  195. }
  196. return BaseClass::ShouldCollide( collisionGroup, contentsMask );
  197. }