Counter Strike : Global Offensive Source Code
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
7.2 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "fx.h"
  8. #include "c_te_effect_dispatch.h"
  9. #include "basecombatweapon_shared.h"
  10. #include "baseviewmodel_shared.h"
  11. #include "particles_new.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. ConVar r_drawtracers( "r_drawtracers", "1", FCVAR_CHEAT );
  15. ConVar r_drawtracers_firstperson( "r_drawtracers_firstperson", "1", FCVAR_ARCHIVE | FCVAR_RELEASE, "Toggle visibility of first person weapon tracers" );
  16. ConVar r_drawtracers_movetonotintersect( "r_drawtracers_movetonotintersect", "1", FCVAR_CHEAT, "" );
  17. extern ConVar cl_righthand;
  18. void FormatViewModelAttachment( C_BasePlayer *pPlayer, Vector &vOrigin, bool bInverse );
  19. #define TRACER_SPEED 5000
  20. //-----------------------------------------------------------------------------
  21. // Purpose:
  22. //-----------------------------------------------------------------------------
  23. Vector GetTracerOrigin( const CEffectData &data )
  24. {
  25. Vector vecStart = data.m_vStart;
  26. QAngle vecAngles;
  27. int iAttachment = data.m_nAttachmentIndex;;
  28. // Attachment?
  29. if ( data.m_fFlags & TRACER_FLAG_USEATTACHMENT )
  30. {
  31. C_BaseViewModel *pViewModel = NULL;
  32. // If the entity specified is a weapon being carried by this player, use the viewmodel instead
  33. IClientRenderable *pRenderable = data.GetRenderable();
  34. if ( !pRenderable )
  35. return vecStart;
  36. C_BaseEntity *pEnt = data.GetEntity();
  37. // This check should probably be for all multiplayer games, investigate later
  38. #if defined( TF_CLIENT_DLL )
  39. if ( pEnt && pEnt->IsDormant() )
  40. return vecStart;
  41. #endif
  42. FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
  43. {
  44. ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
  45. C_BaseCombatWeapon *pWpn = ToBaseCombatWeapon( pEnt );
  46. if ( pWpn && pWpn->IsCarriedByLocalPlayer() )
  47. {
  48. C_BasePlayer *player = ToBasePlayer( pWpn->GetOwner() );
  49. pViewModel = player ? player->GetViewModel( 0 ) : NULL;
  50. if ( pViewModel )
  51. {
  52. // Get the viewmodel and use it instead
  53. pRenderable = pViewModel;
  54. break;
  55. }
  56. }
  57. }
  58. // Get the attachment origin
  59. if ( !pRenderable->GetAttachment( iAttachment, vecStart, vecAngles ) )
  60. {
  61. DevMsg( "GetTracerOrigin: Couldn't find attachment %d on model %s\n", iAttachment,
  62. modelinfo->GetModelName( pRenderable->GetModel() ) );
  63. }
  64. }
  65. return vecStart;
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Purpose:
  69. //-----------------------------------------------------------------------------
  70. void TracerCallback( const CEffectData &data )
  71. {
  72. if ( !C_BasePlayer::HasAnyLocalPlayer() )
  73. return;
  74. if ( !r_drawtracers.GetBool() )
  75. return;
  76. if ( !r_drawtracers_firstperson.GetBool() )
  77. {
  78. C_BaseViewModel *pViewModel = ToBaseViewModel(data.GetEntity());
  79. if ( pViewModel )
  80. return;
  81. }
  82. // Grab the data
  83. Vector vecStart = GetTracerOrigin( data );
  84. float flVelocity = data.m_flScale;
  85. bool bWhiz = (data.m_fFlags & TRACER_FLAG_WHIZ);
  86. int iEntIndex = data.entindex();
  87. if ( IsPlayerIndex( iEntIndex ) && C_BasePlayer::IsLocalPlayer( C_BaseEntity::Instance( iEntIndex ) ) )
  88. {
  89. ACTIVE_SPLITSCREEN_PLAYER_GUARD_ENT( C_BaseEntity::Instance( iEntIndex ) );
  90. Vector foo = data.m_vStart;
  91. QAngle vangles;
  92. Vector vforward, vright, vup;
  93. engine->GetViewAngles( vangles );
  94. AngleVectors( vangles, &vforward, &vright, &vup );
  95. VectorMA( data.m_vStart, 4, vright, foo );
  96. foo[2] -= 0.5f;
  97. FX_PlayerTracer( foo, (Vector&)data.m_vOrigin );
  98. return;
  99. }
  100. // Use default velocity if none specified
  101. if ( !flVelocity )
  102. {
  103. flVelocity = TRACER_SPEED;
  104. }
  105. // Do tracer effect
  106. FX_Tracer( (Vector&)vecStart, (Vector&)data.m_vOrigin, flVelocity, bWhiz );
  107. }
  108. DECLARE_CLIENT_EFFECT_BEGIN( Tracer, TracerCallback )
  109. PRECACHE( MATERIAL, "effects/spark" )
  110. PRECACHE( GAMESOUND, "Bullets.DefaultNearmiss" )
  111. DECLARE_CLIENT_EFFECT_END()
  112. //-----------------------------------------------------------------------------
  113. // Purpose:
  114. //-----------------------------------------------------------------------------
  115. static int s_nWeaponTracerIndex;
  116. void ParticleTracerCallback( const CEffectData &data )
  117. {
  118. if ( !C_BasePlayer::HasAnyLocalPlayer() )
  119. return;
  120. if ( !r_drawtracers.GetBool() )
  121. return;
  122. C_BaseEntity *pEntity = data.GetEntity();
  123. C_BasePlayer *pPlayer = NULL;
  124. C_BaseViewModel *pViewModel = ToBaseViewModel(pEntity);
  125. if ( pEntity )
  126. {
  127. pPlayer = dynamic_cast<C_BasePlayer*>( pEntity );
  128. if ( pPlayer && !pViewModel )
  129. pViewModel = pPlayer->GetViewModel( 0 );
  130. if ( !r_drawtracers_firstperson.GetBool() && pPlayer )
  131. {
  132. if ( pViewModel )
  133. return;
  134. }
  135. }
  136. int nParticleIndex = (data.m_nHitBox > 1) ? data.m_nHitBox : s_nWeaponTracerIndex;
  137. Vector vecEnd;
  138. // Grab the data
  139. C_BaseCombatWeapon *pWpn = (pEntity) ? pEntity->MyCombatWeaponPointer() : NULL;
  140. if ( (!pWpn && !pViewModel) || !(data.m_fFlags & TRACER_FLAG_USEATTACHMENT) )
  141. {
  142. Vector vecStart = GetTracerOrigin( data );
  143. vecEnd = data.m_vOrigin;
  144. // if the tracer visually hits anything that it should not, we move the tracer to almost match the bullet trace itself
  145. if ( r_drawtracers_movetonotintersect.GetBool() )
  146. {
  147. trace_t tr;
  148. UTIL_TraceLine( vecStart, vecEnd, MASK_SHOT, pEntity, COLLISION_GROUP_PROJECTILE, &tr );
  149. if ( tr.fraction != 1.0f && pPlayer )
  150. {
  151. vecStart = pPlayer->EyePosition();
  152. ACTIVE_SPLITSCREEN_PLAYER_GUARD( pPlayer );
  153. QAngle vangles;
  154. Vector vforward, vright, vup;
  155. engine->GetViewAngles( vangles );
  156. AngleVectors( vangles, &vforward, &vright, &vup );
  157. VectorMA( vecStart, cl_righthand.GetBool() ? 2.5 : -2.5, vright, vecStart );
  158. VectorMA( vecStart, 10, vforward, vecStart );
  159. vecStart[2] -= 2.5f;
  160. }
  161. }
  162. // Create the particle effect
  163. QAngle vecAngles;
  164. Vector vecToEnd = vecEnd - vecStart;
  165. VectorNormalize(vecToEnd);
  166. VectorAngles( vecToEnd, vecAngles );
  167. DispatchParticleEffect( nParticleIndex, vecStart, vecEnd, vecAngles );
  168. }
  169. else
  170. {
  171. Vector vecStart = GetTracerOrigin( data );
  172. vecEnd = data.m_vOrigin;
  173. QAngle dummy;
  174. if ( pViewModel )
  175. {
  176. C_BasePlayer *pPlayer = ToBasePlayer( ((C_BaseViewModel *)pViewModel)->GetOwner() );
  177. FormatViewModelAttachment( pPlayer, vecStart, true );
  178. }
  179. // if the tracer visually hits anything that it should not, just don't do the tracer
  180. trace_t tr;
  181. UTIL_TraceLine( vecStart, vecEnd, MASK_VISIBLE, pEntity, COLLISION_GROUP_DEBRIS, &tr );
  182. if ( tr.fraction == 1.0f )
  183. DispatchParticleEffect( nParticleIndex, vecStart, vecEnd, dummy );
  184. }
  185. if ( data.m_fFlags & TRACER_FLAG_WHIZ )
  186. {
  187. Vector vecStart = data.m_vStart;
  188. FX_TracerSound( vecStart, vecEnd, TRACER_TYPE_DEFAULT );
  189. }
  190. }
  191. DECLARE_CLIENT_EFFECT_BEGIN( ParticleTracer, ParticleTracerCallback );
  192. PRECACHE_INDEX( PARTICLE_SYSTEM, "weapon_tracers", s_nWeaponTracerIndex )
  193. DECLARE_CLIENT_EFFECT_END()
  194. //-----------------------------------------------------------------------------
  195. // Purpose:
  196. //-----------------------------------------------------------------------------
  197. void TracerSoundCallback( const CEffectData &data )
  198. {
  199. // Grab the data
  200. Vector vecStart = GetTracerOrigin( data );
  201. // Do tracer effect
  202. FX_TracerSound( vecStart, (Vector&)data.m_vOrigin, data.m_fFlags );
  203. }
  204. DECLARE_CLIENT_EFFECT( TracerSound, TracerSoundCallback );