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.

263 lines
6.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "sdk_basegrenade_projectile.h"
  8. float GetCurrentGravity( void );
  9. #ifdef CLIENT_DLL
  10. #include "c_sdk_player.h"
  11. #else
  12. #include "soundent.h"
  13. BEGIN_DATADESC( CBaseGrenadeProjectile )
  14. DEFINE_THINKFUNC( DangerSoundThink ),
  15. END_DATADESC()
  16. #endif
  17. IMPLEMENT_NETWORKCLASS_ALIASED( BaseGrenadeProjectile, DT_BaseGrenadeProjectile )
  18. BEGIN_NETWORK_TABLE( CBaseGrenadeProjectile, DT_BaseGrenadeProjectile )
  19. #ifdef CLIENT_DLL
  20. RecvPropVector( RECVINFO( m_vInitialVelocity ) )
  21. #else
  22. SendPropVector( SENDINFO( m_vInitialVelocity ),
  23. 20, // nbits
  24. 0, // flags
  25. -3000, // low value
  26. 3000 // high value
  27. )
  28. #endif
  29. END_NETWORK_TABLE()
  30. #ifdef CLIENT_DLL
  31. void CBaseGrenadeProjectile::PostDataUpdate( DataUpdateType_t type )
  32. {
  33. BaseClass::PostDataUpdate( type );
  34. if ( type == DATA_UPDATE_CREATED )
  35. {
  36. // Now stick our initial velocity into the interpolation history
  37. CInterpolatedVar< Vector > &interpolator = GetOriginInterpolator();
  38. interpolator.ClearHistory();
  39. float changeTime = GetLastChangeTime( LATCH_SIMULATION_VAR );
  40. // Add a sample 1 second back.
  41. Vector vCurOrigin = GetLocalOrigin() - m_vInitialVelocity;
  42. interpolator.AddToHead( changeTime - 1.0, &vCurOrigin, false );
  43. // Add the current sample.
  44. vCurOrigin = GetLocalOrigin();
  45. interpolator.AddToHead( changeTime, &vCurOrigin, false );
  46. }
  47. }
  48. int CBaseGrenadeProjectile::DrawModel( int flags )
  49. {
  50. // During the first half-second of our life, don't draw ourselves if he's
  51. // still playing his throw animation.
  52. // (better yet, we could draw ourselves in his hand).
  53. if ( GetThrower() != C_BasePlayer::GetLocalPlayer() )
  54. {
  55. if ( gpGlobals->curtime - m_flSpawnTime < 0.5 )
  56. {
  57. C_SDKPlayer *pPlayer = dynamic_cast<C_SDKPlayer*>( GetThrower() );
  58. if ( pPlayer && pPlayer->m_PlayerAnimState->IsThrowingGrenade() )
  59. {
  60. return 0;
  61. }
  62. }
  63. }
  64. return BaseClass::DrawModel( flags );
  65. }
  66. void CBaseGrenadeProjectile::Spawn()
  67. {
  68. m_flSpawnTime = gpGlobals->curtime;
  69. BaseClass::Spawn();
  70. }
  71. #else
  72. void CBaseGrenadeProjectile::Spawn( void )
  73. {
  74. BaseClass::Spawn();
  75. SetSolidFlags( FSOLID_NOT_STANDABLE );
  76. SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM );
  77. SetSolid( SOLID_BBOX ); // So it will collide with physics props!
  78. // smaller, cube bounding box so we rest on the ground
  79. SetSize( Vector ( -2, -2, -2 ), Vector ( 2, 2, 2 ) );
  80. }
  81. void CBaseGrenadeProjectile::DangerSoundThink( void )
  82. {
  83. if (!IsInWorld())
  84. {
  85. Remove( );
  86. return;
  87. }
  88. if( gpGlobals->curtime > m_flDetonateTime )
  89. {
  90. Detonate();
  91. return;
  92. }
  93. CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * 0.5, GetAbsVelocity().Length( ), 0.2 );
  94. SetNextThink( gpGlobals->curtime + 0.2 );
  95. if (GetWaterLevel() != 0)
  96. {
  97. SetAbsVelocity( GetAbsVelocity() * 0.5 );
  98. }
  99. }
  100. //Sets the time at which the grenade will explode
  101. void CBaseGrenadeProjectile::SetDetonateTimerLength( float timer )
  102. {
  103. m_flDetonateTime = gpGlobals->curtime + timer;
  104. }
  105. void CBaseGrenadeProjectile::ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity )
  106. {
  107. //Assume all surfaces have the same elasticity
  108. float flSurfaceElasticity = 1.0;
  109. //Don't bounce off of players with perfect elasticity
  110. if( trace.m_pEnt && trace.m_pEnt->IsPlayer() )
  111. {
  112. flSurfaceElasticity = 0.3;
  113. }
  114. // if its breakable glass and we kill it, don't bounce.
  115. // give some damage to the glass, and if it breaks, pass
  116. // through it.
  117. bool breakthrough = false;
  118. if( trace.m_pEnt && FClassnameIs( trace.m_pEnt, "func_breakable" ) )
  119. {
  120. breakthrough = true;
  121. }
  122. if( trace.m_pEnt && FClassnameIs( trace.m_pEnt, "func_breakable_surf" ) )
  123. {
  124. breakthrough = true;
  125. }
  126. if (breakthrough)
  127. {
  128. CTakeDamageInfo info( this, this, 10, DMG_CLUB );
  129. trace.m_pEnt->DispatchTraceAttack( info, GetAbsVelocity(), &trace );
  130. ApplyMultiDamage();
  131. if( trace.m_pEnt->m_iHealth <= 0 )
  132. {
  133. // slow our flight a little bit
  134. Vector vel = GetAbsVelocity();
  135. vel *= 0.4;
  136. SetAbsVelocity( vel );
  137. return;
  138. }
  139. }
  140. float flTotalElasticity = GetElasticity() * flSurfaceElasticity;
  141. flTotalElasticity = clamp( flTotalElasticity, 0.0f, 0.9f );
  142. // NOTE: A backoff of 2.0f is a reflection
  143. Vector vecAbsVelocity;
  144. PhysicsClipVelocity( GetAbsVelocity(), trace.plane.normal, vecAbsVelocity, 2.0f );
  145. vecAbsVelocity *= flTotalElasticity;
  146. // Get the total velocity (player + conveyors, etc.)
  147. VectorAdd( vecAbsVelocity, GetBaseVelocity(), vecVelocity );
  148. float flSpeedSqr = DotProduct( vecVelocity, vecVelocity );
  149. // Stop if on ground.
  150. if ( trace.plane.normal.z > 0.7f ) // Floor
  151. {
  152. // Verify that we have an entity.
  153. CBaseEntity *pEntity = trace.m_pEnt;
  154. Assert( pEntity );
  155. SetAbsVelocity( vecAbsVelocity );
  156. if ( flSpeedSqr < ( 30 * 30 ) )
  157. {
  158. if ( pEntity->IsStandable() )
  159. {
  160. SetGroundEntity( pEntity );
  161. }
  162. // Reset velocities.
  163. SetAbsVelocity( vec3_origin );
  164. SetLocalAngularVelocity( vec3_angle );
  165. //align to the ground so we're not standing on end
  166. QAngle angle;
  167. VectorAngles( trace.plane.normal, angle );
  168. // rotate randomly in yaw
  169. angle[1] = random->RandomFloat( 0, 360 );
  170. // TODO: rotate around trace.plane.normal
  171. SetAbsAngles( angle );
  172. }
  173. else
  174. {
  175. Vector vecDelta = GetBaseVelocity() - vecAbsVelocity;
  176. Vector vecBaseDir = GetBaseVelocity();
  177. VectorNormalize( vecBaseDir );
  178. float flScale = vecDelta.Dot( vecBaseDir );
  179. VectorScale( vecAbsVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, vecVelocity );
  180. VectorMA( vecVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, GetBaseVelocity() * flScale, vecVelocity );
  181. PhysicsPushEntity( vecVelocity, &trace );
  182. }
  183. }
  184. else
  185. {
  186. // If we get *too* slow, we'll stick without ever coming to rest because
  187. // we'll get pushed down by gravity faster than we can escape from the wall.
  188. if ( flSpeedSqr < ( 30 * 30 ) )
  189. {
  190. // Reset velocities.
  191. SetAbsVelocity( vec3_origin );
  192. SetLocalAngularVelocity( vec3_angle );
  193. }
  194. else
  195. {
  196. SetAbsVelocity( vecAbsVelocity );
  197. }
  198. }
  199. BounceSound();
  200. }
  201. void CBaseGrenadeProjectile::SetupInitialTransmittedGrenadeVelocity( const Vector &velocity )
  202. {
  203. m_vInitialVelocity = velocity;
  204. }
  205. #endif