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.

274 lines
7.0 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Things thrown from the hand
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "player.h"
  8. #include "ammodef.h"
  9. #include "gamerules.h"
  10. #include "grenade_brickbat.h"
  11. #include "weapon_brickbat.h"
  12. #include "soundent.h"
  13. #include "decals.h"
  14. #include "IEffects.h"
  15. #include "engine/IEngineSound.h"
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. // Global Savedata for changelevel trigger
  19. BEGIN_DATADESC( CGrenade_Brickbat )
  20. DEFINE_FIELD( m_nType, FIELD_INTEGER ),
  21. DEFINE_FIELD( m_bExplodes, FIELD_BOOLEAN ),
  22. DEFINE_FIELD( m_bBounceToFlat, FIELD_BOOLEAN ),
  23. // Function Pointers
  24. DEFINE_FUNCTION( BrickbatTouch ),
  25. DEFINE_FUNCTION( BrickbatThink ),
  26. END_DATADESC()
  27. LINK_ENTITY_TO_CLASS( brickbat, CGrenade_Brickbat );
  28. void CGrenade_Brickbat::Spawn( void )
  29. {
  30. SetCollisionGroup( COLLISION_GROUP_PROJECTILE );
  31. SetTouch( BrickbatTouch );
  32. SetThink( BrickbatThink );
  33. SetNextThink( gpGlobals->curtime + 0.1f );
  34. m_takedamage = DAMAGE_YES;
  35. m_iHealth = 1;
  36. SetGravity( 1.0 );
  37. SetSequence( 1 );
  38. CreateVPhysics();
  39. }
  40. bool CGrenade_Brickbat::CreateVPhysics()
  41. {
  42. VPhysicsInitNormal( SOLID_VPHYSICS, 0, false );
  43. IPhysicsObject *pPhysics = VPhysicsGetObject();
  44. if ( pPhysics )
  45. {
  46. // we want world touches
  47. unsigned int flags = pPhysics->GetCallbackFlags();
  48. pPhysics->SetCallbackFlags( flags | CALLBACK_GLOBAL_TOUCH_STATIC );
  49. }
  50. return true;
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Purpose:
  54. // Input :
  55. // Output :
  56. //-----------------------------------------------------------------------------
  57. void CGrenade_Brickbat::BrickbatTouch( CBaseEntity *pOther )
  58. {
  59. // -----------------------------------------------------------
  60. // Might be physically simulated so get my velocity manually
  61. // -----------------------------------------------------------
  62. Vector vVelocity;
  63. GetVelocity(&vVelocity,NULL);
  64. // -----------------------------------
  65. // Do damage if we moving fairly fast
  66. // -----------------------------------
  67. if (vVelocity.Length() > 100)
  68. {
  69. if (GetThrower())
  70. {
  71. trace_t tr;
  72. tr = CBaseEntity::GetTouchTrace( );
  73. ClearMultiDamage( );
  74. Vector forward;
  75. AngleVectors( GetLocalAngles(), &forward );
  76. CTakeDamageInfo info( this, GetThrower(), m_flDamage, DMG_CRUSH );
  77. CalculateMeleeDamageForce( &info, forward, tr.endpos );
  78. pOther->DispatchTraceAttack( info, forward, &tr );
  79. ApplyMultiDamage();
  80. }
  81. // If this thrown item explodes, blow it up
  82. if (m_bExplodes)
  83. {
  84. Detonate();
  85. return;
  86. }
  87. }
  88. else if (pOther->GetFlags() & FL_CLIENT)
  89. {
  90. SpawnBrickbatWeapon();
  91. return;
  92. }
  93. }
  94. //------------------------------------------------------------------------------
  95. // Purpose : Brickbat grenade turns back into a brickbat weapon
  96. // Input :
  97. // Output :
  98. //------------------------------------------------------------------------------
  99. void CGrenade_Brickbat::SpawnBrickbatWeapon( void )
  100. {
  101. CWeaponBrickbat *pBrickbat = (CWeaponBrickbat*)CBaseEntity::CreateNoSpawn(
  102. "weapon_brickbat", GetLocalOrigin(), GetLocalAngles(), NULL );
  103. // Spawn after we set the ammo type so the correct model is used
  104. if (pBrickbat)
  105. {
  106. pBrickbat->m_iCurrentAmmoType = m_nType;
  107. pBrickbat->Spawn();
  108. VPhysicsDestroyObject();
  109. SetThink(NULL);
  110. UTIL_Remove(this);
  111. }
  112. }
  113. //------------------------------------------------------------------------------
  114. // Purpose :
  115. // Input :
  116. // Output :
  117. //------------------------------------------------------------------------------
  118. void CGrenade_Brickbat::BrickbatThink( void )
  119. {
  120. // -----------------------------------------------------------
  121. // Might be physically simulated so get my velocity manually
  122. // -----------------------------------------------------------
  123. Vector vVelocity;
  124. AngularImpulse vAngVel;
  125. GetVelocity(&vVelocity,&vAngVel);
  126. // See if I can lose my owner (has dropper moved out of way?)
  127. // Want do this so owner can throw the brickbat
  128. if (GetOwnerEntity())
  129. {
  130. trace_t tr;
  131. Vector vUpABit = GetAbsOrigin();
  132. vUpABit.z += 5.0;
  133. CBaseEntity* saveOwner = GetOwnerEntity();
  134. SetOwnerEntity( NULL );
  135. UTIL_TraceEntity( this, GetAbsOrigin(), vUpABit, MASK_SOLID, &tr );
  136. if ( tr.startsolid || tr.fraction != 1.0 )
  137. {
  138. SetOwnerEntity( saveOwner );
  139. }
  140. }
  141. // ---------------------------------------------------------------
  142. // Make sure we're not resting on a living thing's bounding box
  143. // ---------------------------------------------------------------
  144. if (vVelocity.Length() < 0.01)
  145. {
  146. trace_t tr;
  147. UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,10), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
  148. if ( tr.fraction < 1.0 && tr.m_pEnt)
  149. {
  150. CBaseEntity *pEntity = tr.m_pEnt;
  151. if (pEntity->GetFlags() & (FL_CLIENT | FL_NPC))
  152. {
  153. // --------------------
  154. // Bounce me off
  155. // --------------------
  156. Vector vNewVel;
  157. vNewVel.y = 100;
  158. vNewVel.x = random->RandomInt(-100,100);
  159. vNewVel.z = random->RandomInt(-100,100);
  160. // If physically simulated
  161. IPhysicsObject *pPhysicsObject = VPhysicsGetObject();
  162. if ( pPhysicsObject )
  163. {
  164. pPhysicsObject->AddVelocity( &vNewVel, &vAngVel );
  165. }
  166. // Otherwise
  167. else
  168. {
  169. SetAbsVelocity( vNewVel );
  170. }
  171. }
  172. }
  173. }
  174. if (vVelocity.Length() < 0.01)
  175. {
  176. SpawnBrickbatWeapon();
  177. }
  178. SetNextThink( gpGlobals->curtime + 0.1f );
  179. }
  180. //=====================================================================
  181. // > Rock
  182. //=====================================================================
  183. class CGrenadeRockBB : public CGrenade_Brickbat
  184. {
  185. public:
  186. DECLARE_CLASS( CGrenadeRockBB, CGrenade_Brickbat );
  187. void Spawn(void)
  188. {
  189. m_nType = BRICKBAT_ROCK;
  190. SetModel( "models/props_junk/Rock001a.mdl" );
  191. BaseClass::Spawn();
  192. }
  193. void Precache( void )
  194. {
  195. PrecacheModel("models/props_junk/Rock001a.mdl");
  196. BaseClass::Precache();
  197. }
  198. };
  199. LINK_ENTITY_TO_CLASS( grenade_rockbb, CGrenadeRockBB );
  200. PRECACHE_REGISTER(grenade_rockbb);
  201. //=====================================================================
  202. // > BeerBottle
  203. //=====================================================================
  204. class CGrenadeBottle : public CGrenade_Brickbat
  205. {
  206. public:
  207. DECLARE_CLASS( CGrenadeBottle, CGrenade_Brickbat );
  208. void Spawn(void)
  209. {
  210. m_nType = BRICKBAT_BOTTLE;
  211. m_bExplodes = true;
  212. SetModel( "models/weapons/w_bb_bottle.mdl" );
  213. BaseClass::Spawn();
  214. }
  215. void Precache( void );
  216. void Detonate( void );
  217. };
  218. void CGrenadeBottle::Precache( void )
  219. {
  220. PrecacheModel("models/weapons/w_bb_bottle.mdl");
  221. PrecacheScriptSound( "GrenadeBottle.Detonate" );
  222. BaseClass::Precache();
  223. }
  224. void CGrenadeBottle::Detonate( void )
  225. {
  226. trace_t trace;
  227. UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity(), MASK_SOLID, this, COLLISION_GROUP_NONE, &trace);
  228. UTIL_DecalTrace( &trace, "BeerSplash" );
  229. EmitSound( "GrenadeBottle.Detonate" );
  230. CSoundEnt::InsertSound(SOUND_COMBAT, GetAbsOrigin(), 400, 0.5);
  231. UTIL_Remove( this );
  232. }
  233. LINK_ENTITY_TO_CLASS( grenade_beerbottle, CGrenadeBottle );
  234. PRECACHE_REGISTER(grenade_beerbottle);