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
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;
|
|
}
|