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

//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
//=============================================================================//
#include "cbase.h"
#include "shot_manipulator.h"
#include "paint_sprayer_shared.h"
#include "debugoverlay_shared.h"
#include "paint_stream_manager.h"
#ifdef CLIENT_DLL
#include "c_paint_sprayer.h"
#else
#include "paint_sprayer.h"
#endif
ConVar debug_paint_sprayer_cone("debug_paint_sprayer_cone", "0", FCVAR_REPLICATED | FCVAR_CHEAT);
ConVar max_noisy_blobs_per_second("max_noisy_blobs_per_second", "5.0f", FCVAR_REPLICATED | FCVAR_CHEAT);
float const MAX_SPRAYER_SPREAD_ANGLE = 89.f;
void CPaintSprayer::SprayPaint( float flDeltaTime )
{
CPaintStream *pPaintStream = m_hPaintStream;
if ( !pPaintStream )
return;
//Don't spray silent blobs on the clients
if( m_bSilent && gpGlobals->IsClient() )
{
return;
}
if( flDeltaTime <= 0.0f )
{
return;
}
Vector vecSprayDir;
AngleVectors( GetAbsAngles(), &vecSprayDir );
m_flAccumulatedTime += flDeltaTime;
const float fireDeltaTime = 1.0f / m_flBlobsPerSecond;
int blobsFired = 0;
while ( m_flAccumulatedTime > fireDeltaTime )
{
m_flAccumulatedTime -= fireDeltaTime;
if ( pPaintStream->GetBlobsCount() >= m_nMaxBlobCount )
continue;
CPaintBlob *pBlob = FirePaintBlob( GetAbsOrigin(),
GetAbsOrigin(),
GetAbsVelocity(),
vecSprayDir,
m_PaintPowerType,
m_flBlobSpreadRadius,
m_flBlobSpreadAngle,
m_flMinSpeed,
m_flMaxSpeed,
m_flStreakPercentage,
m_flMinStreakTime,
m_flMaxStreakTime,
m_flMinStreakSpeedDampen,
m_flMaxStreakSpeedDampen,
m_bSilent,
m_bDrawOnly,
pPaintStream,
m_nBlobRandomSeed );
if( pBlob )
{
m_flPercentageSinceLastNoisyBlob += m_flNoisyBlobPercentage;
if( m_flPercentageSinceLastNoisyBlob >= 1.0f )
{
m_flPercentageSinceLastNoisyBlob = 0.0f;
pBlob->SetShouldPlaySound( !m_bSilent );
}
}
pPaintStream->AddPaintBlob( pBlob );
++m_nBlobRandomSeed;
++blobsFired;
}
// Note: Assume that if the sprayer is dripping, it's not spawning more than
// one blob per frame and also that, if it did, we wouldn't want more
// than one drip sound playing from the same position in a frame or within
// a fraction of a second in general. That takes this conditional out of
// the loop above.
#ifdef GAME_DLL
if( !m_bSilent && blobsFired > 0 &&
m_nAmbientSound == PAINT_SPRAYER_SOUND_DRIP )
{
CBroadcastRecipientFilter filter;
CBaseEntity::EmitSound( filter, entindex(), "Paint.Drip", &GetAbsOrigin() );
}
#endif
}
CPaintBlob* FirePaintBlob( const Vector& vecSourcePosition,
const Vector& vecOldSourcePosition,
const Vector& vecSourceVelocity,
const Vector& vecSprayDir,
int paintType,
float flBlobSpreadRadius,
float flBlobSpreadAngle,
float flMinSpeed,
float flMaxSpeed,
float flBlobStreakPercent,
float flMinStreakTime,
float flMaxStreakTime,
float flMinStreakSpeedDampen,
float flMaxStreakSpeedDampen,
bool bSilent,
bool bDrawOnly,
CBaseEntity *pOwner,
int nRandomSeed /*= 0*/ )
{
#ifdef CLIENT_DLL
// if the client is listen server, don't create blobs twice, we don't want to double the work
if ( engine->IsClientLocalToActiveServer() )
return NULL;
#endif
// set random seed
RandomSeed( nRandomSeed );
// clamp spread angle
flBlobSpreadAngle = clamp( flBlobSpreadAngle, 0.f, MAX_SPRAYER_SPREAD_ANGLE );
// random position inside the circle area
Vector vecCircleRight, vecCircleUp;
VectorVectors( vecSprayDir, vecCircleRight, vecCircleUp );
vecCircleUp.NormalizeInPlace();
VMatrix matRotate;
MatrixBuildRotationAboutAxis( matRotate, vecSprayDir, RandomFloat( 0.f, 360.f ) );
Vector vecBlobFirePos = vecSourcePosition + RandomFloat( 0.f, flBlobSpreadRadius ) * ( matRotate * vecCircleUp );
// compute cone origin
float flDistanceToConeOrigin = 1.f;
Vector vecConeOrigin;
if ( AlmostEqual( flBlobSpreadAngle, 0.f ) )
{
vecConeOrigin = vecBlobFirePos - flDistanceToConeOrigin * vecSprayDir.Normalized();
}
else
{
flDistanceToConeOrigin = flBlobSpreadRadius / tanf( DEG2RAD( flBlobSpreadAngle ) );
vecConeOrigin = vecSourcePosition - flDistanceToConeOrigin * vecSprayDir.Normalized();
}
// compute direction from random position
Vector vecBlobFireDir = vecBlobFirePos - vecConeOrigin;
if ( AlmostEqual( flBlobSpreadRadius, 0.f ) )
{
float flSpread = sin( DEG2RAD( flBlobSpreadAngle )/2.0f );
Vector vecSpraySpread( flSpread, flSpread, flSpread );
CShotManipulator shotManipulator( vecSprayDir );
vecBlobFireDir = shotManipulator.ApplySpread( vecSpraySpread );
}
vecBlobFireDir.NormalizeInPlace();
if ( debug_paint_sprayer_cone.GetBool() )
{
QAngle debugAngle;
VectorAngles( vecSprayDir, debugAngle );
#ifdef CLIENT_DLL
NDebugOverlay::Circle( vecSourcePosition, debugAngle, flBlobSpreadRadius, 255, 0, 0, 128, true, 0.1f );
NDebugOverlay::Line( vecBlobFirePos, vecBlobFirePos + 20 * vecBlobFireDir, 255, 255, 0, true, 1.f );
#else
NDebugOverlay::Circle( vecSourcePosition, debugAngle, flBlobSpreadRadius, 0, 255, 0, 128, true, 0.1f );
NDebugOverlay::Line( vecBlobFirePos, vecBlobFirePos + 20 * vecBlobFireDir, 0, 255, 255, true, 1.f );
#endif
}
Vector vecBlobVelocity = vecBlobFireDir * RandomFloat( flMinSpeed, flMaxSpeed ) + vecSourceVelocity;
//The streaking values of the blob
float flStreakTime = 0.0f;
float flStreakSpeedDampen = 0.0f;
bool bShouldStreak = ( RandomFloat( 0.0f, 1.0f ) * 100.0f ) <= flBlobStreakPercent;
if( bShouldStreak )
{
flStreakTime = RandomFloat( flMinStreakTime, flMaxStreakTime );
flStreakSpeedDampen = RandomFloat( flMinStreakSpeedDampen, flMaxStreakSpeedDampen );
}
CPaintBlob *pBlob = PaintStreamManager.AllocatePaintBlob( bSilent );
if ( pBlob )
{
pBlob->Init( vecBlobFirePos, vecBlobVelocity, paintType, flStreakTime, flStreakSpeedDampen, pOwner, bSilent, bDrawOnly );
}
return pBlob;
}