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.

201 lines
6.2 KiB

  1. //========= Copyright � 1996-2009, Valve Corporation, All rights reserved. ============//
  2. //
  3. //=============================================================================//
  4. #include "cbase.h"
  5. #include "shot_manipulator.h"
  6. #include "paint_sprayer_shared.h"
  7. #include "debugoverlay_shared.h"
  8. #include "paint_stream_manager.h"
  9. #ifdef CLIENT_DLL
  10. #include "c_paint_sprayer.h"
  11. #else
  12. #include "paint_sprayer.h"
  13. #endif
  14. ConVar debug_paint_sprayer_cone("debug_paint_sprayer_cone", "0", FCVAR_REPLICATED | FCVAR_CHEAT);
  15. ConVar max_noisy_blobs_per_second("max_noisy_blobs_per_second", "5.0f", FCVAR_REPLICATED | FCVAR_CHEAT);
  16. float const MAX_SPRAYER_SPREAD_ANGLE = 89.f;
  17. void CPaintSprayer::SprayPaint( float flDeltaTime )
  18. {
  19. CPaintStream *pPaintStream = m_hPaintStream;
  20. if ( !pPaintStream )
  21. return;
  22. //Don't spray silent blobs on the clients
  23. if( m_bSilent && gpGlobals->IsClient() )
  24. {
  25. return;
  26. }
  27. if( flDeltaTime <= 0.0f )
  28. {
  29. return;
  30. }
  31. Vector vecSprayDir;
  32. AngleVectors( GetAbsAngles(), &vecSprayDir );
  33. m_flAccumulatedTime += flDeltaTime;
  34. const float fireDeltaTime = 1.0f / m_flBlobsPerSecond;
  35. int blobsFired = 0;
  36. while ( m_flAccumulatedTime > fireDeltaTime )
  37. {
  38. m_flAccumulatedTime -= fireDeltaTime;
  39. if ( pPaintStream->GetBlobsCount() >= m_nMaxBlobCount )
  40. continue;
  41. CPaintBlob *pBlob = FirePaintBlob( GetAbsOrigin(),
  42. GetAbsOrigin(),
  43. GetAbsVelocity(),
  44. vecSprayDir,
  45. m_PaintPowerType,
  46. m_flBlobSpreadRadius,
  47. m_flBlobSpreadAngle,
  48. m_flMinSpeed,
  49. m_flMaxSpeed,
  50. m_flStreakPercentage,
  51. m_flMinStreakTime,
  52. m_flMaxStreakTime,
  53. m_flMinStreakSpeedDampen,
  54. m_flMaxStreakSpeedDampen,
  55. m_bSilent,
  56. m_bDrawOnly,
  57. pPaintStream,
  58. m_nBlobRandomSeed );
  59. if( pBlob )
  60. {
  61. m_flPercentageSinceLastNoisyBlob += m_flNoisyBlobPercentage;
  62. if( m_flPercentageSinceLastNoisyBlob >= 1.0f )
  63. {
  64. m_flPercentageSinceLastNoisyBlob = 0.0f;
  65. pBlob->SetShouldPlaySound( !m_bSilent );
  66. }
  67. }
  68. pPaintStream->AddPaintBlob( pBlob );
  69. ++m_nBlobRandomSeed;
  70. ++blobsFired;
  71. }
  72. // Note: Assume that if the sprayer is dripping, it's not spawning more than
  73. // one blob per frame and also that, if it did, we wouldn't want more
  74. // than one drip sound playing from the same position in a frame or within
  75. // a fraction of a second in general. That takes this conditional out of
  76. // the loop above.
  77. #ifdef GAME_DLL
  78. if( !m_bSilent && blobsFired > 0 &&
  79. m_nAmbientSound == PAINT_SPRAYER_SOUND_DRIP )
  80. {
  81. CBroadcastRecipientFilter filter;
  82. CBaseEntity::EmitSound( filter, entindex(), "Paint.Drip", &GetAbsOrigin() );
  83. }
  84. #endif
  85. }
  86. CPaintBlob* FirePaintBlob( const Vector& vecSourcePosition,
  87. const Vector& vecOldSourcePosition,
  88. const Vector& vecSourceVelocity,
  89. const Vector& vecSprayDir,
  90. int paintType,
  91. float flBlobSpreadRadius,
  92. float flBlobSpreadAngle,
  93. float flMinSpeed,
  94. float flMaxSpeed,
  95. float flBlobStreakPercent,
  96. float flMinStreakTime,
  97. float flMaxStreakTime,
  98. float flMinStreakSpeedDampen,
  99. float flMaxStreakSpeedDampen,
  100. bool bSilent,
  101. bool bDrawOnly,
  102. CBaseEntity *pOwner,
  103. int nRandomSeed /*= 0*/ )
  104. {
  105. #ifdef CLIENT_DLL
  106. // if the client is listen server, don't create blobs twice, we don't want to double the work
  107. if ( engine->IsClientLocalToActiveServer() )
  108. return NULL;
  109. #endif
  110. // set random seed
  111. RandomSeed( nRandomSeed );
  112. // clamp spread angle
  113. flBlobSpreadAngle = clamp( flBlobSpreadAngle, 0.f, MAX_SPRAYER_SPREAD_ANGLE );
  114. // random position inside the circle area
  115. Vector vecCircleRight, vecCircleUp;
  116. VectorVectors( vecSprayDir, vecCircleRight, vecCircleUp );
  117. vecCircleUp.NormalizeInPlace();
  118. VMatrix matRotate;
  119. MatrixBuildRotationAboutAxis( matRotate, vecSprayDir, RandomFloat( 0.f, 360.f ) );
  120. Vector vecBlobFirePos = vecSourcePosition + RandomFloat( 0.f, flBlobSpreadRadius ) * ( matRotate * vecCircleUp );
  121. // compute cone origin
  122. float flDistanceToConeOrigin = 1.f;
  123. Vector vecConeOrigin;
  124. if ( AlmostEqual( flBlobSpreadAngle, 0.f ) )
  125. {
  126. vecConeOrigin = vecBlobFirePos - flDistanceToConeOrigin * vecSprayDir.Normalized();
  127. }
  128. else
  129. {
  130. flDistanceToConeOrigin = flBlobSpreadRadius / tanf( DEG2RAD( flBlobSpreadAngle ) );
  131. vecConeOrigin = vecSourcePosition - flDistanceToConeOrigin * vecSprayDir.Normalized();
  132. }
  133. // compute direction from random position
  134. Vector vecBlobFireDir = vecBlobFirePos - vecConeOrigin;
  135. if ( AlmostEqual( flBlobSpreadRadius, 0.f ) )
  136. {
  137. float flSpread = sin( DEG2RAD( flBlobSpreadAngle )/2.0f );
  138. Vector vecSpraySpread( flSpread, flSpread, flSpread );
  139. CShotManipulator shotManipulator( vecSprayDir );
  140. vecBlobFireDir = shotManipulator.ApplySpread( vecSpraySpread );
  141. }
  142. vecBlobFireDir.NormalizeInPlace();
  143. if ( debug_paint_sprayer_cone.GetBool() )
  144. {
  145. QAngle debugAngle;
  146. VectorAngles( vecSprayDir, debugAngle );
  147. #ifdef CLIENT_DLL
  148. NDebugOverlay::Circle( vecSourcePosition, debugAngle, flBlobSpreadRadius, 255, 0, 0, 128, true, 0.1f );
  149. NDebugOverlay::Line( vecBlobFirePos, vecBlobFirePos + 20 * vecBlobFireDir, 255, 255, 0, true, 1.f );
  150. #else
  151. NDebugOverlay::Circle( vecSourcePosition, debugAngle, flBlobSpreadRadius, 0, 255, 0, 128, true, 0.1f );
  152. NDebugOverlay::Line( vecBlobFirePos, vecBlobFirePos + 20 * vecBlobFireDir, 0, 255, 255, true, 1.f );
  153. #endif
  154. }
  155. Vector vecBlobVelocity = vecBlobFireDir * RandomFloat( flMinSpeed, flMaxSpeed ) + vecSourceVelocity;
  156. //The streaking values of the blob
  157. float flStreakTime = 0.0f;
  158. float flStreakSpeedDampen = 0.0f;
  159. bool bShouldStreak = ( RandomFloat( 0.0f, 1.0f ) * 100.0f ) <= flBlobStreakPercent;
  160. if( bShouldStreak )
  161. {
  162. flStreakTime = RandomFloat( flMinStreakTime, flMaxStreakTime );
  163. flStreakSpeedDampen = RandomFloat( flMinStreakSpeedDampen, flMaxStreakSpeedDampen );
  164. }
  165. CPaintBlob *pBlob = PaintStreamManager.AllocatePaintBlob( bSilent );
  166. if ( pBlob )
  167. {
  168. pBlob->Init( vecBlobFirePos, vecBlobVelocity, paintType, flStreakTime, flStreakSpeedDampen, pOwner, bSilent, bDrawOnly );
  169. }
  170. return pBlob;
  171. }