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.

185 lines
5.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Game-specific impact effect hooks
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "fx_impact.h"
  8. #include "engine/IEngineSound.h"
  9. #include "decals.h"
  10. #include "IEffects.h"
  11. #include "fx.h"
  12. #include "c_impact_effects.h"
  13. #include "fx_fleck.h"
  14. //-----------------------------------------------------------------------------
  15. // This does the actual debris flecks
  16. //-----------------------------------------------------------------------------
  17. #define FLECK_MIN_SPEED 64.0f
  18. #define FLECK_MAX_SPEED 128.0f
  19. #define FLECK_GRAVITY 800.0f
  20. #define FLECK_DAMPEN 0.3f
  21. #define FLECK_ANGULAR_SPRAY 0.6f
  22. static void FX_Flecks( const Vector& origin, trace_t *trace, char materialType, int iScale )
  23. {
  24. Vector color;
  25. GetColorForSurface( trace, &color );
  26. Vector spawnOffset = trace->endpos + ( trace->plane.normal * 1.0f );
  27. CSmartPtr<CFleckParticles> fleckEmitter = CFleckParticles::Create( "FX_DebrisFlecks", spawnOffset, Vector(5,5,5) );
  28. if ( !fleckEmitter )
  29. return;
  30. // Handle increased scale
  31. float flMaxSpeed = FLECK_MAX_SPEED * iScale;
  32. float flAngularSpray = MAX( 0.2, FLECK_ANGULAR_SPRAY - ( (float)iScale * 0.2f) ); // More power makes the spray more controlled
  33. // Setup our collision information
  34. fleckEmitter->m_ParticleCollision.Setup( spawnOffset, &trace->plane.normal, flAngularSpray, FLECK_MIN_SPEED, flMaxSpeed, FLECK_GRAVITY, FLECK_DAMPEN );
  35. PMaterialHandle *hMaterial;
  36. switch ( materialType )
  37. {
  38. case CHAR_TEX_WOOD:
  39. hMaterial = g_Mat_Fleck_Wood;
  40. break;
  41. case CHAR_TEX_CONCRETE:
  42. case CHAR_TEX_TILE:
  43. default:
  44. hMaterial = g_Mat_Fleck_Cement;
  45. break;
  46. }
  47. Vector dir, end;
  48. float colorRamp;
  49. int numFlecks = random->RandomInt( 4, 16 ) * iScale;
  50. FleckParticle *pFleckParticle;
  51. //Dump out flecks
  52. int i;
  53. for ( i = 0; i < numFlecks; i++ )
  54. {
  55. pFleckParticle = (FleckParticle *) fleckEmitter->AddParticle( sizeof(FleckParticle), hMaterial[random->RandomInt(0,1)], spawnOffset );
  56. if ( pFleckParticle == NULL )
  57. break;
  58. pFleckParticle->m_flLifetime = 0.0f;
  59. pFleckParticle->m_flDieTime = 3.0f;
  60. dir[0] = trace->plane.normal[0] + random->RandomFloat( -flAngularSpray, flAngularSpray );
  61. dir[1] = trace->plane.normal[1] + random->RandomFloat( -flAngularSpray, flAngularSpray );
  62. dir[2] = trace->plane.normal[2] + random->RandomFloat( -flAngularSpray, flAngularSpray );
  63. pFleckParticle->m_uchSize = random->RandomInt( 1, 2 );
  64. pFleckParticle->m_vecVelocity = dir * ( random->RandomFloat( FLECK_MIN_SPEED, flMaxSpeed) * ( 3 - pFleckParticle->m_uchSize ) );
  65. pFleckParticle->m_flRoll = random->RandomFloat( 0, 360 );
  66. pFleckParticle->m_flRollDelta = random->RandomFloat( 0, 360 );
  67. colorRamp = random->RandomFloat( 0.75f, 1.25f );
  68. pFleckParticle->m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
  69. pFleckParticle->m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
  70. pFleckParticle->m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
  71. }
  72. }
  73. //-----------------------------------------------------------------------------
  74. // Purpose: Perform custom effects based on the Decal index
  75. //-----------------------------------------------------------------------------
  76. void DOD_PerformCustomEffects( const Vector &vecOrigin, trace_t &tr, const Vector &shotDir, int iMaterial, float flScale )
  77. {
  78. // Throw out the effect if any of these are true
  79. if ( tr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) )
  80. return;
  81. int iScale = (int)flScale;
  82. if ( iScale < 1 )
  83. iScale = 1;
  84. // Cement and wood have dust and flecks
  85. if ( ( iMaterial == CHAR_TEX_CONCRETE ) ||
  86. ( iMaterial == CHAR_TEX_TILE ) ||
  87. ( iMaterial == CHAR_TEX_WOOD ) )
  88. {
  89. FX_Flecks( vecOrigin, &tr, iMaterial, iScale );
  90. FX_DustImpact( vecOrigin, &tr, flScale );
  91. }
  92. else if ( ( iMaterial == CHAR_TEX_DIRT ) || ( iMaterial == CHAR_TEX_SAND ) )
  93. {
  94. FX_DustImpact( vecOrigin, &tr, flScale );
  95. }
  96. else if ( ( iMaterial == CHAR_TEX_METAL ) || ( iMaterial == CHAR_TEX_VENT ) )
  97. {
  98. Vector reflect;
  99. float dot = shotDir.Dot( tr.plane.normal );
  100. reflect = shotDir + ( tr.plane.normal * ( dot*-2.0f ) );
  101. reflect[0] += random->RandomFloat( -0.2f, 0.2f );
  102. reflect[1] += random->RandomFloat( -0.2f, 0.2f );
  103. reflect[2] += random->RandomFloat( -0.2f, 0.2f );
  104. FX_MetalSpark( vecOrigin, reflect, tr.plane.normal, iScale );
  105. }
  106. else if ( iMaterial == CHAR_TEX_COMPUTER )
  107. {
  108. Vector offset = vecOrigin + ( tr.plane.normal * 1.0f );
  109. g_pEffects->Sparks( offset );
  110. }
  111. }
  112. //-----------------------------------------------------------------------------
  113. // Purpose: Handle weapon impacts
  114. //-----------------------------------------------------------------------------
  115. void ImpactCallback( const CEffectData &data )
  116. {
  117. trace_t tr;
  118. Vector vecOrigin, vecStart, vecShotDir;
  119. int iMaterial, iDamageType, iHitbox;
  120. short nSurfaceProp;
  121. C_BaseEntity *pEntity = ParseImpactData( data, &vecOrigin, &vecStart, &vecShotDir, nSurfaceProp, iMaterial, iDamageType, iHitbox );
  122. if ( !pEntity )
  123. return;
  124. // If we hit, perform our custom effects and play the sound
  125. if ( Impact( vecOrigin, vecStart, iMaterial, iDamageType, iHitbox, pEntity, tr ) )
  126. {
  127. float flScale = 0.75f;
  128. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  129. if ( pPlayer )
  130. {
  131. float flDistSqr = (vecOrigin - pPlayer->GetAbsOrigin()).LengthSqr();
  132. flScale = RemapValClamped( flDistSqr, (400*400), (1000*1000), 0.8, 1.2 );
  133. }
  134. // Check for custom effects based on the Decal index
  135. DOD_PerformCustomEffects( vecOrigin, tr, vecShotDir, iMaterial, flScale );
  136. PlayImpactSound( pEntity, tr, vecOrigin, nSurfaceProp );
  137. //Play a ricochet sound some of the time
  138. if( random->RandomInt(1,10) <= 3 && (iDamageType == DMG_BULLET) )
  139. {
  140. CLocalPlayerFilter filter;
  141. C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, "Bounce.Shrapnel", &vecOrigin );
  142. }
  143. }
  144. }
  145. DECLARE_CLIENT_EFFECT( "Impact", ImpactCallback );