//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
# include "cbase.h"
# include "c_smoke_trail.h"
# include "fx.h"
# include "engine/ivdebugoverlay.h"
# include "engine/IEngineSound.h"
# include "c_te_effect_dispatch.h"
# include "glow_overlay.h"
# include "fx_explosion.h"
# include "tier1/KeyValues.h"
# include "toolframework_client.h"
# include "view.h"
# include "clienteffectprecachesystem.h"
// memdbgon must be the last include file in a .cpp file!!!
# include "tier0/memdbgon.h"
//
// CRocketTrailParticle
//
class CRocketTrailParticle : public CSimpleEmitter
{
public :
CRocketTrailParticle ( const char * pDebugName ) : CSimpleEmitter ( pDebugName ) { }
//Create
static CRocketTrailParticle * Create ( const char * pDebugName )
{
return new CRocketTrailParticle ( pDebugName ) ;
}
//Roll
virtual float UpdateRoll ( SimpleParticle * pParticle , float timeDelta )
{
pParticle - > m_flRoll + = pParticle - > m_flRollDelta * timeDelta ;
pParticle - > m_flRollDelta + = pParticle - > m_flRollDelta * ( timeDelta * - 8.0f ) ;
//Cap the minimum roll
if ( fabs ( pParticle - > m_flRollDelta ) < 0.5f )
{
pParticle - > m_flRollDelta = ( pParticle - > m_flRollDelta > 0.0f ) ? 0.5f : - 0.5f ;
}
return pParticle - > m_flRoll ;
}
//Alpha
virtual float UpdateAlpha ( const SimpleParticle * pParticle )
{
return ( ( ( float ) pParticle - > m_uchStartAlpha / 255.0f ) * sin ( M_PI * ( pParticle - > m_flLifetime / pParticle - > m_flDieTime ) ) ) ;
}
private :
CRocketTrailParticle ( const CRocketTrailParticle & ) ;
} ;
//
// CSmokeParticle
//
class CSmokeParticle : public CSimpleEmitter
{
public :
CSmokeParticle ( const char * pDebugName ) : CSimpleEmitter ( pDebugName ) { }
//Create
static CSmokeParticle * Create ( const char * pDebugName )
{
return new CSmokeParticle ( pDebugName ) ;
}
//Alpha
virtual float UpdateAlpha ( const SimpleParticle * pParticle )
{
return ( ( ( float ) pParticle - > m_uchStartAlpha / 255.0f ) * sin ( M_PI * ( pParticle - > m_flLifetime / pParticle - > m_flDieTime ) ) ) ;
}
//Color
virtual Vector UpdateColor ( const SimpleParticle * pParticle )
{
Vector color ;
float tLifetime = pParticle - > m_flLifetime / pParticle - > m_flDieTime ;
float ramp = 1.0f - tLifetime ;
color [ 0 ] = ( ( float ) pParticle - > m_uchColor [ 0 ] * ramp ) / 255.0f ;
color [ 1 ] = ( ( float ) pParticle - > m_uchColor [ 1 ] * ramp ) / 255.0f ;
color [ 2 ] = ( ( float ) pParticle - > m_uchColor [ 2 ] * ramp ) / 255.0f ;
return color ;
}
//Roll
virtual float UpdateRoll ( SimpleParticle * pParticle , float timeDelta )
{
pParticle - > m_flRoll + = pParticle - > m_flRollDelta * timeDelta ;
pParticle - > m_flRollDelta + = pParticle - > m_flRollDelta * ( timeDelta * - 8.0f ) ;
//Cap the minimum roll
if ( fabs ( pParticle - > m_flRollDelta ) < 0.5f )
{
pParticle - > m_flRollDelta = ( pParticle - > m_flRollDelta > 0.0f ) ? 0.5f : - 0.5f ;
}
return pParticle - > m_flRoll ;
}
private :
CSmokeParticle ( const CSmokeParticle & ) ;
} ;
// Datatable.. this can have all the smoketrail parameters when we need it to.
IMPLEMENT_CLIENTCLASS_DT ( C_SmokeTrail , DT_SmokeTrail , SmokeTrail )
RecvPropFloat ( RECVINFO ( m_SpawnRate ) ) ,
RecvPropVector ( RECVINFO ( m_StartColor ) ) ,
RecvPropVector ( RECVINFO ( m_EndColor ) ) ,
RecvPropFloat ( RECVINFO ( m_ParticleLifetime ) ) ,
RecvPropFloat ( RECVINFO ( m_StopEmitTime ) ) ,
RecvPropFloat ( RECVINFO ( m_MinSpeed ) ) ,
RecvPropFloat ( RECVINFO ( m_MaxSpeed ) ) ,
RecvPropFloat ( RECVINFO ( m_MinDirectedSpeed ) ) ,
RecvPropFloat ( RECVINFO ( m_MaxDirectedSpeed ) ) ,
RecvPropFloat ( RECVINFO ( m_StartSize ) ) ,
RecvPropFloat ( RECVINFO ( m_EndSize ) ) ,
RecvPropFloat ( RECVINFO ( m_SpawnRadius ) ) ,
RecvPropInt ( RECVINFO ( m_bEmit ) ) ,
RecvPropInt ( RECVINFO ( m_nAttachment ) ) ,
RecvPropFloat ( RECVINFO ( m_Opacity ) ) ,
END_RECV_TABLE ( )
// ------------------------------------------------------------------------- //
// ParticleMovieExplosion
// ------------------------------------------------------------------------- //
C_SmokeTrail : : C_SmokeTrail ( )
{
m_MaterialHandle [ 0 ] = NULL ;
m_MaterialHandle [ 1 ] = NULL ;
m_SpawnRate = 10 ;
m_ParticleSpawn . Init ( 10 ) ;
m_StartColor . Init ( 0.5 , 0.5 , 0.5 ) ;
m_EndColor . Init ( 0 , 0 , 0 ) ;
m_ParticleLifetime = 5 ;
m_StopEmitTime = 0 ; // No end time
m_MinSpeed = 2 ;
m_MaxSpeed = 4 ;
m_MinDirectedSpeed = m_MaxDirectedSpeed = 0 ;
m_StartSize = 35 ;
m_EndSize = 55 ;
m_SpawnRadius = 2 ;
m_VelocityOffset . Init ( ) ;
m_Opacity = 0.5f ;
m_bEmit = true ;
m_nAttachment = - 1 ;
m_pSmokeEmitter = NULL ;
m_pParticleMgr = NULL ;
}
C_SmokeTrail : : ~ C_SmokeTrail ( )
{
if ( ToolsEnabled ( ) & & clienttools - > IsInRecordingMode ( ) & & m_pSmokeEmitter . IsValid ( ) & & m_pSmokeEmitter - > GetToolParticleEffectId ( ) ! = TOOLPARTICLESYSTEMID_INVALID )
{
KeyValues * msg = new KeyValues ( " OldParticleSystem_ActivateEmitter " ) ;
msg - > SetInt ( " id " , m_pSmokeEmitter - > GetToolParticleEffectId ( ) ) ;
msg - > SetInt ( " emitter " , 0 ) ;
msg - > SetInt ( " active " , false ) ;
msg - > SetFloat ( " time " , gpGlobals - > curtime ) ;
ToolFramework_PostToolMessage ( HTOOLHANDLE_INVALID , msg ) ;
msg - > deleteThis ( ) ;
}
if ( m_pParticleMgr )
{
m_pParticleMgr - > RemoveEffect ( & m_ParticleEffect ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_SmokeTrail : : GetAimEntOrigin ( IClientEntity * pAttachedTo , Vector * pAbsOrigin , QAngle * pAbsAngles )
{
C_BaseEntity * pEnt = pAttachedTo - > GetBaseEntity ( ) ;
if ( pEnt & & ( m_nAttachment > 0 ) )
{
pEnt - > GetAttachment ( m_nAttachment , * pAbsOrigin , * pAbsAngles ) ;
}
else
{
BaseClass : : GetAimEntOrigin ( pAttachedTo , pAbsOrigin , pAbsAngles ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bEmit -
//-----------------------------------------------------------------------------
void C_SmokeTrail : : SetEmit ( bool bEmit )
{
m_bEmit = bEmit ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : rate -
//-----------------------------------------------------------------------------
void C_SmokeTrail : : SetSpawnRate ( float rate )
{
m_SpawnRate = rate ;
m_ParticleSpawn . Init ( rate ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bnewentity -
//-----------------------------------------------------------------------------
void C_SmokeTrail : : OnDataChanged ( DataUpdateType_t updateType )
{
C_BaseEntity : : OnDataChanged ( updateType ) ;
if ( updateType = = DATA_UPDATE_CREATED )
{
Start ( ParticleMgr ( ) , NULL ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pParticleMgr -
// *pArgs -
//-----------------------------------------------------------------------------
void C_SmokeTrail : : Start ( CParticleMgr * pParticleMgr , IPrototypeArgAccess * pArgs )
{
if ( ! pParticleMgr - > AddEffect ( & m_ParticleEffect , this ) )
return ;
m_pParticleMgr = pParticleMgr ;
m_pSmokeEmitter = CSmokeParticle : : Create ( " smokeTrail " ) ;
if ( ! m_pSmokeEmitter )
{
Assert ( false ) ;
return ;
}
m_pSmokeEmitter - > SetSortOrigin ( GetAbsOrigin ( ) ) ;
m_pSmokeEmitter - > SetNearClip ( 64.0f , 128.0f ) ;
m_MaterialHandle [ 0 ] = g_Mat_DustPuff [ 0 ] ;
m_MaterialHandle [ 1 ] = g_Mat_DustPuff [ 1 ] ;
m_ParticleSpawn . Init ( m_SpawnRate ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : fTimeDelta -
//-----------------------------------------------------------------------------
void C_SmokeTrail : : Update ( float fTimeDelta )
{
if ( ! m_pSmokeEmitter )
return ;
Vector offsetColor ;
// Add new particles
if ( ! m_bEmit )
return ;
if ( ( m_StopEmitTime ! = 0 ) & & ( m_StopEmitTime < = gpGlobals - > curtime ) )
return ;
float tempDelta = fTimeDelta ;
SimpleParticle * pParticle ;
Vector offset ;
Vector vecOrigin ;
VectorMA ( GetAbsOrigin ( ) , - fTimeDelta , GetAbsVelocity ( ) , vecOrigin ) ;
Vector vecForward ;
GetVectors ( & vecForward , NULL , NULL ) ;
while ( m_ParticleSpawn . NextEvent ( tempDelta ) )
{
float fldt = fTimeDelta - tempDelta ;
offset . Random ( - m_SpawnRadius , m_SpawnRadius ) ;
offset + = vecOrigin ;
VectorMA ( offset , fldt , GetAbsVelocity ( ) , offset ) ;
pParticle = ( SimpleParticle * ) m_pSmokeEmitter - > AddParticle ( sizeof ( SimpleParticle ) , m_MaterialHandle [ random - > RandomInt ( 0 , 1 ) ] , offset ) ;
if ( pParticle = = NULL )
continue ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = m_ParticleLifetime ;
pParticle - > m_vecVelocity . Random ( - 1.0f , 1.0f ) ;
pParticle - > m_vecVelocity * = random - > RandomFloat ( m_MinSpeed , m_MaxSpeed ) ;
pParticle - > m_vecVelocity = pParticle - > m_vecVelocity + GetAbsVelocity ( ) ;
float flDirectedVel = random - > RandomFloat ( m_MinDirectedSpeed , m_MaxDirectedSpeed ) ;
VectorMA ( pParticle - > m_vecVelocity , flDirectedVel , vecForward , pParticle - > m_vecVelocity ) ;
offsetColor = m_StartColor ;
float flMaxVal = MAX ( m_StartColor [ 0 ] , m_StartColor [ 1 ] ) ;
if ( flMaxVal < m_StartColor [ 2 ] )
{
flMaxVal = m_StartColor [ 2 ] ;
}
offsetColor / = flMaxVal ;
offsetColor * = random - > RandomFloat ( - 0.2f , 0.2f ) ;
offsetColor + = m_StartColor ;
offsetColor [ 0 ] = clamp ( offsetColor [ 0 ] , 0.0f , 1.0f ) ;
offsetColor [ 1 ] = clamp ( offsetColor [ 1 ] , 0.0f , 1.0f ) ;
offsetColor [ 2 ] = clamp ( offsetColor [ 2 ] , 0.0f , 1.0f ) ;
pParticle - > m_uchColor [ 0 ] = offsetColor [ 0 ] * 255.0f ;
pParticle - > m_uchColor [ 1 ] = offsetColor [ 1 ] * 255.0f ;
pParticle - > m_uchColor [ 2 ] = offsetColor [ 2 ] * 255.0f ;
pParticle - > m_uchStartSize = m_StartSize ;
pParticle - > m_uchEndSize = m_EndSize ;
float alpha = random - > RandomFloat ( m_Opacity * 0.75f , m_Opacity * 1.25f ) ;
alpha = clamp ( alpha , 0.0f , 1.0f ) ;
pParticle - > m_uchStartAlpha = alpha * 255 ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = random - > RandomFloat ( - 1.0f , 1.0f ) ;
}
}
void C_SmokeTrail : : RenderParticles ( CParticleRenderIterator * pIterator )
{
}
void C_SmokeTrail : : SimulateParticles ( CParticleSimulateIterator * pIterator )
{
}
//-----------------------------------------------------------------------------
// This is called after sending this entity's recording state
//-----------------------------------------------------------------------------
void C_SmokeTrail : : CleanupToolRecordingState ( KeyValues * msg )
{
if ( ! ToolsEnabled ( ) )
return ;
BaseClass : : CleanupToolRecordingState ( msg ) ;
// Generally, this is used to allow the entity to clean up
// allocated state it put into the message, but here we're going
// to use it to send particle system messages because we
// know the grenade has been recorded at this point
if ( ! clienttools - > IsInRecordingMode ( ) | | ! m_pSmokeEmitter . IsValid ( ) )
return ;
// For now, we can't record smoketrails that don't have a moveparent
C_BaseEntity * pEnt = GetMoveParent ( ) ;
if ( ! pEnt )
return ;
bool bEmitterActive = m_bEmit & & ( ( m_StopEmitTime = = 0 ) | | ( m_StopEmitTime > gpGlobals - > curtime ) ) ;
// NOTE: Particle system destruction message will be sent by the particle effect itself.
if ( m_pSmokeEmitter - > GetToolParticleEffectId ( ) = = TOOLPARTICLESYSTEMID_INVALID )
{
int nId = m_pSmokeEmitter - > AllocateToolParticleEffectId ( ) ;
KeyValues * msg = new KeyValues ( " OldParticleSystem_Create " ) ;
msg - > SetString ( " name " , " C_SmokeTrail " ) ;
msg - > SetInt ( " id " , nId ) ;
msg - > SetFloat ( " time " , gpGlobals - > curtime ) ;
KeyValues * pRandomEmitter = msg - > FindKey ( " DmeRandomEmitter " , true ) ;
pRandomEmitter - > SetInt ( " count " , m_SpawnRate ) ; // particles per second, when duration is < 0
pRandomEmitter - > SetFloat ( " duration " , - 1 ) ;
pRandomEmitter - > SetInt ( " active " , bEmitterActive ) ;
KeyValues * pEmitterParent1 = pRandomEmitter - > FindKey ( " emitter1 " , true ) ;
pEmitterParent1 - > SetFloat ( " randomamount " , 0.5f ) ;
KeyValues * pEmitterParent2 = pRandomEmitter - > FindKey ( " emitter2 " , true ) ;
pEmitterParent2 - > SetFloat ( " randomamount " , 0.5f ) ;
KeyValues * pEmitter = pEmitterParent1 - > FindKey ( " DmeSpriteEmitter " , true ) ;
pEmitter - > SetString ( " material " , " particle/particle_smokegrenade " ) ;
KeyValues * pInitializers = pEmitter - > FindKey ( " initializers " , true ) ;
// FIXME: Until we can interpolate ent logs during emission, this can't work
KeyValues * pPosition = pInitializers - > FindKey ( " DmePositionPointToEntityInitializer " , true ) ;
pPosition - > SetPtr ( " entindex " , ( void * ) pEnt - > entindex ( ) ) ;
pPosition - > SetInt ( " attachmentIndex " , m_nAttachment ) ;
pPosition - > SetFloat ( " randomDist " , m_SpawnRadius ) ;
pPosition - > SetFloat ( " startx " , pEnt - > GetAbsOrigin ( ) . x ) ;
pPosition - > SetFloat ( " starty " , pEnt - > GetAbsOrigin ( ) . y ) ;
pPosition - > SetFloat ( " startz " , pEnt - > GetAbsOrigin ( ) . z ) ;
KeyValues * pLifetime = pInitializers - > FindKey ( " DmeRandomLifetimeInitializer " , true ) ;
pLifetime - > SetFloat ( " minLifetime " , m_ParticleLifetime ) ;
pLifetime - > SetFloat ( " maxLifetime " , m_ParticleLifetime ) ;
KeyValues * pVelocity = pInitializers - > FindKey ( " DmeAttachmentVelocityInitializer " , true ) ;
pVelocity - > SetPtr ( " entindex " , ( void * ) entindex ( ) ) ;
pVelocity - > SetFloat ( " minAttachmentSpeed " , m_MinDirectedSpeed ) ;
pVelocity - > SetFloat ( " maxAttachmentSpeed " , m_MaxDirectedSpeed ) ;
pVelocity - > SetFloat ( " minRandomSpeed " , m_MinSpeed ) ;
pVelocity - > SetFloat ( " maxRandomSpeed " , m_MaxSpeed ) ;
KeyValues * pRoll = pInitializers - > FindKey ( " DmeRandomRollInitializer " , true ) ;
pRoll - > SetFloat ( " minRoll " , 0.0f ) ;
pRoll - > SetFloat ( " maxRoll " , 360.0f ) ;
KeyValues * pRollSpeed = pInitializers - > FindKey ( " DmeRandomRollSpeedInitializer " , true ) ;
pRollSpeed - > SetFloat ( " minRollSpeed " , - 1.0f ) ;
pRollSpeed - > SetFloat ( " maxRollSpeed " , 1.0f ) ;
KeyValues * pColor = pInitializers - > FindKey ( " DmeRandomValueColorInitializer " , true ) ;
Color c (
FastFToC ( clamp ( m_StartColor . x , 0.f , 1.f ) ) ,
FastFToC ( clamp ( m_StartColor . y , 0.f , 1.f ) ) ,
FastFToC ( clamp ( m_StartColor . z , 0.f , 1.f ) ) ,
255 ) ;
pColor - > SetColor ( " startColor " , c ) ;
pColor - > SetFloat ( " minStartValueDelta " , - 0.2f ) ;
pColor - > SetFloat ( " maxStartValueDelta " , 0.2f ) ;
pColor - > SetColor ( " endColor " , Color ( 0 , 0 , 0 , 255 ) ) ;
KeyValues * pAlpha = pInitializers - > FindKey ( " DmeRandomAlphaInitializer " , true ) ;
int nMinAlpha = 255 * m_Opacity * 0.75f ;
int nMaxAlpha = 255 * m_Opacity * 1.25f ;
pAlpha - > SetInt ( " minStartAlpha " , 0 ) ;
pAlpha - > SetInt ( " maxStartAlpha " , 0 ) ;
pAlpha - > SetInt ( " minEndAlpha " , clamp ( nMinAlpha , 0 , 255 ) ) ;
pAlpha - > SetInt ( " maxEndAlpha " , clamp ( nMaxAlpha , 0 , 255 ) ) ;
KeyValues * pSize = pInitializers - > FindKey ( " DmeRandomSizeInitializer " , true ) ;
pSize - > SetFloat ( " minStartSize " , m_StartSize ) ;
pSize - > SetFloat ( " maxStartSize " , m_StartSize ) ;
pSize - > SetFloat ( " minEndSize " , m_EndSize ) ;
pSize - > SetFloat ( " maxEndSize " , m_EndSize ) ;
KeyValues * pUpdaters = pEmitter - > FindKey ( " updaters " , true ) ;
pUpdaters - > FindKey ( " DmePositionVelocityUpdater " , true ) ;
pUpdaters - > FindKey ( " DmeRollUpdater " , true ) ;
KeyValues * pRollSpeedUpdater = pUpdaters - > FindKey ( " DmeRollSpeedAttenuateUpdater " , true ) ;
pRollSpeedUpdater - > SetFloat ( " attenuation " , 1.0f - 8.0f / 30.0f ) ;
pRollSpeedUpdater - > SetFloat ( " attenuationTme " , 1.0f / 30.0f ) ;
pRollSpeedUpdater - > SetFloat ( " minRollSpeed " , 0.5f ) ;
pUpdaters - > FindKey ( " DmeAlphaSineUpdater " , true ) ;
pUpdaters - > FindKey ( " DmeColorUpdater " , true ) ;
pUpdaters - > FindKey ( " DmeSizeUpdater " , true ) ;
KeyValues * pEmitter2 = pEmitter - > MakeCopy ( ) ;
pEmitter2 - > SetString ( " material " , " particle/particle_noisesphere " ) ;
pEmitterParent2 - > AddSubKey ( pEmitter2 ) ;
ToolFramework_PostToolMessage ( HTOOLHANDLE_INVALID , msg ) ;
msg - > deleteThis ( ) ;
}
else
{
KeyValues * msg = new KeyValues ( " OldParticleSystem_ActivateEmitter " ) ;
msg - > SetInt ( " id " , m_pSmokeEmitter - > GetToolParticleEffectId ( ) ) ;
msg - > SetInt ( " emitter " , 0 ) ;
msg - > SetInt ( " active " , bEmitterActive ) ;
msg - > SetFloat ( " time " , gpGlobals - > curtime ) ;
ToolFramework_PostToolMessage ( HTOOLHANDLE_INVALID , msg ) ;
msg - > deleteThis ( ) ;
}
}
//==================================================
// RocketTrail
//==================================================
// Expose to the particle app.
EXPOSE_PROTOTYPE_EFFECT ( RocketTrail , C_RocketTrail ) ;
// Datatable.. this can have all the smoketrail parameters when we need it to.
IMPLEMENT_CLIENTCLASS_DT ( C_RocketTrail , DT_RocketTrail , RocketTrail )
RecvPropFloat ( RECVINFO ( m_SpawnRate ) ) ,
RecvPropVector ( RECVINFO ( m_StartColor ) ) ,
RecvPropVector ( RECVINFO ( m_EndColor ) ) ,
RecvPropFloat ( RECVINFO ( m_ParticleLifetime ) ) ,
RecvPropFloat ( RECVINFO ( m_StopEmitTime ) ) ,
RecvPropFloat ( RECVINFO ( m_MinSpeed ) ) ,
RecvPropFloat ( RECVINFO ( m_MaxSpeed ) ) ,
RecvPropFloat ( RECVINFO ( m_StartSize ) ) ,
RecvPropFloat ( RECVINFO ( m_EndSize ) ) ,
RecvPropFloat ( RECVINFO ( m_SpawnRadius ) ) ,
RecvPropInt ( RECVINFO ( m_bEmit ) ) ,
RecvPropInt ( RECVINFO ( m_nAttachment ) ) ,
RecvPropFloat ( RECVINFO ( m_Opacity ) ) ,
RecvPropInt ( RECVINFO ( m_bDamaged ) ) ,
RecvPropFloat ( RECVINFO ( m_flFlareScale ) ) ,
END_RECV_TABLE ( )
// ------------------------------------------------------------------------- //
// ParticleMovieExplosion
// ------------------------------------------------------------------------- //
C_RocketTrail : : C_RocketTrail ( )
{
m_MaterialHandle [ 0 ] = NULL ;
m_MaterialHandle [ 1 ] = NULL ;
m_SpawnRate = 10 ;
m_ParticleSpawn . Init ( 10 ) ;
m_StartColor . Init ( 0.5 , 0.5 , 0.5 ) ;
m_EndColor . Init ( 0 , 0 , 0 ) ;
m_ParticleLifetime = 5 ;
m_StopEmitTime = 0 ; // No end time
m_MinSpeed = 2 ;
m_MaxSpeed = 4 ;
m_StartSize = 35 ;
m_EndSize = 55 ;
m_SpawnRadius = 2 ;
m_VelocityOffset . Init ( ) ;
m_Opacity = 0.5f ;
m_bEmit = true ;
m_bDamaged = false ;
m_nAttachment = - 1 ;
m_pRocketEmitter = NULL ;
m_pParticleMgr = NULL ;
}
C_RocketTrail : : ~ C_RocketTrail ( )
{
if ( m_pParticleMgr )
{
m_pParticleMgr - > RemoveEffect ( & m_ParticleEffect ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_RocketTrail : : GetAimEntOrigin ( IClientEntity * pAttachedTo , Vector * pAbsOrigin , QAngle * pAbsAngles )
{
C_BaseEntity * pEnt = pAttachedTo - > GetBaseEntity ( ) ;
if ( pEnt & & ( m_nAttachment > 0 ) )
{
pEnt - > GetAttachment ( m_nAttachment , * pAbsOrigin , * pAbsAngles ) ;
}
else
{
BaseClass : : GetAimEntOrigin ( pAttachedTo , pAbsOrigin , pAbsAngles ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bEmit -
//-----------------------------------------------------------------------------
void C_RocketTrail : : SetEmit ( bool bEmit )
{
m_bEmit = bEmit ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : rate -
//-----------------------------------------------------------------------------
void C_RocketTrail : : SetSpawnRate ( float rate )
{
m_SpawnRate = rate ;
m_ParticleSpawn . Init ( rate ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bnewentity -
//-----------------------------------------------------------------------------
void C_RocketTrail : : OnDataChanged ( DataUpdateType_t updateType )
{
C_BaseEntity : : OnDataChanged ( updateType ) ;
if ( updateType = = DATA_UPDATE_CREATED )
{
Start ( ParticleMgr ( ) , NULL ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pParticleMgr -
// *pArgs -
//-----------------------------------------------------------------------------
void C_RocketTrail : : Start ( CParticleMgr * pParticleMgr , IPrototypeArgAccess * pArgs )
{
if ( ! pParticleMgr - > AddEffect ( & m_ParticleEffect , this ) )
return ;
m_pParticleMgr = pParticleMgr ;
m_pRocketEmitter = CRocketTrailParticle : : Create ( " smokeTrail " ) ;
if ( ! m_pRocketEmitter )
{
Assert ( false ) ;
return ;
}
m_pRocketEmitter - > SetSortOrigin ( GetAbsOrigin ( ) ) ;
m_pRocketEmitter - > SetNearClip ( 64.0f , 128.0f ) ;
m_MaterialHandle [ 0 ] = g_Mat_DustPuff [ 0 ] ;
m_MaterialHandle [ 1 ] = g_Mat_DustPuff [ 1 ] ;
m_ParticleSpawn . Init ( m_SpawnRate ) ;
m_vecLastPosition = GetAbsOrigin ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : fTimeDelta -
//-----------------------------------------------------------------------------
void C_RocketTrail : : Update ( float fTimeDelta )
{
if ( ! m_pRocketEmitter )
return ;
if ( gpGlobals - > frametime = = 0.0f )
return ;
CSmartPtr < CSimpleEmitter > pSimple = CSimpleEmitter : : Create ( " MuzzleFlash " ) ;
pSimple - > SetSortOrigin ( GetAbsOrigin ( ) ) ;
SimpleParticle * pParticle ;
Vector forward , offset ;
AngleVectors ( GetAbsAngles ( ) , & forward ) ;
forward . Negate ( ) ;
float flScale = random - > RandomFloat ( m_flFlareScale - 0.5f , m_flFlareScale + 0.5f ) ;
//
// Flash
//
int i ;
for ( i = 1 ; i < 9 ; i + + )
{
offset = GetAbsOrigin ( ) + ( forward * ( i * 2.0f * m_flFlareScale ) ) ;
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , pSimple - > GetPMaterial ( VarArgs ( " effects/muzzleflash%d " , random - > RandomInt ( 1 , 4 ) ) ) , offset ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = 0.01f ;
pParticle - > m_vecVelocity . Init ( ) ;
pParticle - > m_uchColor [ 0 ] = 255 ;
pParticle - > m_uchColor [ 1 ] = 255 ;
pParticle - > m_uchColor [ 2 ] = 255 ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 128 ;
pParticle - > m_uchStartSize = ( random - > RandomFloat ( 5.0f , 6.0f ) * ( 12 - ( i ) ) / 9 ) * flScale ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = 0.0f ;
}
// Add new particles (undamaged version)
if ( m_bEmit )
{
Vector moveDiff = GetAbsOrigin ( ) - m_vecLastPosition ;
float moveLength = VectorNormalize ( moveDiff ) ;
int numPuffs = moveLength / ( m_StartSize / 2.0f ) ;
//debugoverlay->AddLineOverlay( m_vecLastPosition, GetAbsOrigin(), 255, 0, 0, true, 2.0f );
//FIXME: More rational cap here, perhaps
if ( numPuffs > 50 )
numPuffs = 50 ;
Vector offsetColor ;
float step = moveLength / numPuffs ;
//Fill in the gaps
for ( i = 1 ; i < numPuffs + 1 ; i + + )
{
offset = m_vecLastPosition + ( moveDiff * step * i ) ;
//debugoverlay->AddBoxOverlay( offset, -Vector(2,2,2), Vector(2,2,2), vec3_angle, i*4, i*4, i*4, true, 4.0f );
pParticle = ( SimpleParticle * ) m_pRocketEmitter - > AddParticle ( sizeof ( SimpleParticle ) , m_MaterialHandle [ random - > RandomInt ( 0 , 1 ) ] , offset ) ;
if ( pParticle ! = NULL )
{
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = m_ParticleLifetime + random - > RandomFloat ( m_ParticleLifetime * 0.9f , m_ParticleLifetime * 1.1f ) ;
pParticle - > m_vecVelocity . Random ( - 1.0f , 1.0f ) ;
pParticle - > m_vecVelocity * = random - > RandomFloat ( m_MinSpeed , m_MaxSpeed ) ;
offsetColor = m_StartColor * random - > RandomFloat ( 0.75f , 1.25f ) ;
offsetColor [ 0 ] = clamp ( offsetColor [ 0 ] , 0.0f , 1.0f ) ;
offsetColor [ 1 ] = clamp ( offsetColor [ 1 ] , 0.0f , 1.0f ) ;
offsetColor [ 2 ] = clamp ( offsetColor [ 2 ] , 0.0f , 1.0f ) ;
pParticle - > m_uchColor [ 0 ] = offsetColor [ 0 ] * 255.0f ;
pParticle - > m_uchColor [ 1 ] = offsetColor [ 1 ] * 255.0f ;
pParticle - > m_uchColor [ 2 ] = offsetColor [ 2 ] * 255.0f ;
pParticle - > m_uchStartSize = m_StartSize * random - > RandomFloat ( 0.75f , 1.25f ) ;
pParticle - > m_uchEndSize = m_EndSize * random - > RandomFloat ( 1.0f , 1.25f ) ;
float alpha = random - > RandomFloat ( m_Opacity * 0.75f , m_Opacity * 1.25f ) ;
if ( alpha > 1.0f )
alpha = 1.0f ;
if ( alpha < 0.0f )
alpha = 0.0f ;
pParticle - > m_uchStartAlpha = alpha * 255 ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = random - > RandomFloat ( - 8.0f , 8.0f ) ;
}
}
}
if ( m_bDamaged )
{
SimpleParticle * pParticle ;
Vector offset ;
Vector offsetColor ;
CSmartPtr < CEmberEffect > pEmitter = CEmberEffect : : Create ( " C_RocketTrail::damaged " ) ;
pEmitter - > SetSortOrigin ( GetAbsOrigin ( ) ) ;
PMaterialHandle flameMaterial = m_pRocketEmitter - > GetPMaterial ( VarArgs ( " sprites/flamelet%d " , random - > RandomInt ( 1 , 4 ) ) ) ;
// Flames from the rocket
for ( i = 0 ; i < 8 ; i + + )
{
offset = RandomVector ( - 8 , 8 ) + GetAbsOrigin ( ) ;
pParticle = ( SimpleParticle * ) pEmitter - > AddParticle ( sizeof ( SimpleParticle ) , flameMaterial , offset ) ;
if ( pParticle ! = NULL )
{
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = 0.25f ;
pParticle - > m_vecVelocity . Random ( - 1.0f , 1.0f ) ;
pParticle - > m_vecVelocity * = random - > RandomFloat ( 32 , 128 ) ;
offsetColor = m_StartColor * random - > RandomFloat ( 0.75f , 1.25f ) ;
offsetColor [ 0 ] = clamp ( offsetColor [ 0 ] , 0.0f , 1.0f ) ;
offsetColor [ 1 ] = clamp ( offsetColor [ 1 ] , 0.0f , 1.0f ) ;
offsetColor [ 2 ] = clamp ( offsetColor [ 2 ] , 0.0f , 1.0f ) ;
pParticle - > m_uchColor [ 0 ] = offsetColor [ 0 ] * 255.0f ;
pParticle - > m_uchColor [ 1 ] = offsetColor [ 1 ] * 255.0f ;
pParticle - > m_uchColor [ 2 ] = offsetColor [ 2 ] * 255.0f ;
pParticle - > m_uchStartSize = 8.0f ;
pParticle - > m_uchEndSize = 32.0f ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = random - > RandomFloat ( - 8.0f , 8.0f ) ;
}
}
}
m_vecLastPosition = GetAbsOrigin ( ) ;
}
void C_RocketTrail : : RenderParticles ( CParticleRenderIterator * pIterator )
{
}
void C_RocketTrail : : SimulateParticles ( CParticleSimulateIterator * pIterator )
{
}
SporeEffect : : SporeEffect ( const char * pDebugName ) : CSimpleEmitter ( pDebugName )
{
}
SporeEffect * SporeEffect : : Create ( const char * pDebugName )
{
return new SporeEffect ( pDebugName ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : fTimeDelta -
// Output : Vector
//-----------------------------------------------------------------------------
void SporeEffect : : UpdateVelocity ( SimpleParticle * pParticle , float timeDelta )
{
float speed = VectorNormalize ( pParticle - > m_vecVelocity ) ;
Vector offset ;
speed - = ( 64.0f * timeDelta ) ;
offset . Random ( - 0.5f , 0.5f ) ;
pParticle - > m_vecVelocity + = offset ;
VectorNormalize ( pParticle - > m_vecVelocity ) ;
pParticle - > m_vecVelocity * = speed ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pParticle -
// timeDelta -
//-----------------------------------------------------------------------------
Vector SporeEffect : : UpdateColor ( const SimpleParticle * pParticle )
{
Vector color ;
float ramp = ( ( float ) pParticle - > m_uchStartAlpha / 255.0f ) * sin ( M_PI * ( pParticle - > m_flLifetime / pParticle - > m_flDieTime ) ) ; //1.0f - ( pParticle->m_flLifetime / pParticle->m_flDieTime );
color [ 0 ] = ( ( float ) pParticle - > m_uchColor [ 0 ] * ramp ) / 255.0f ;
color [ 1 ] = ( ( float ) pParticle - > m_uchColor [ 1 ] * ramp ) / 255.0f ;
color [ 2 ] = ( ( float ) pParticle - > m_uchColor [ 2 ] * ramp ) / 255.0f ;
return color ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pParticle -
// timeDelta -
// Output : float
//-----------------------------------------------------------------------------
float SporeEffect : : UpdateAlpha ( const SimpleParticle * pParticle )
{
return ( ( ( float ) pParticle - > m_uchStartAlpha / 255.0f ) * sin ( M_PI * ( pParticle - > m_flLifetime / pParticle - > m_flDieTime ) ) ) ;
}
//==================================================
// C_SporeExplosion
//==================================================
EXPOSE_PROTOTYPE_EFFECT ( SporeExplosion , C_SporeExplosion ) ;
IMPLEMENT_CLIENTCLASS_DT ( C_SporeExplosion , DT_SporeExplosion , SporeExplosion )
RecvPropFloat ( RECVINFO ( m_flSpawnRate ) ) ,
RecvPropFloat ( RECVINFO ( m_flParticleLifetime ) ) ,
RecvPropFloat ( RECVINFO ( m_flStartSize ) ) ,
RecvPropFloat ( RECVINFO ( m_flEndSize ) ) ,
RecvPropFloat ( RECVINFO ( m_flSpawnRadius ) ) ,
RecvPropBool ( RECVINFO ( m_bEmit ) ) ,
RecvPropBool ( RECVINFO ( m_bDontRemove ) ) ,
END_RECV_TABLE ( )
C_SporeExplosion : : C_SporeExplosion ( void )
{
m_pParticleMgr = NULL ;
m_flSpawnRate = 32 ;
m_flParticleLifetime = 5 ;
m_flStartSize = 32 ;
m_flEndSize = 64 ;
m_flSpawnRadius = 32 ;
m_pSporeEffect = NULL ;
m_teParticleSpawn . Init ( 32 ) ;
m_bEmit = true ;
m_bDontRemove = false ;
}
C_SporeExplosion : : ~ C_SporeExplosion ( )
{
if ( m_pParticleMgr ! = NULL )
{
m_pParticleMgr - > RemoveEffect ( & m_ParticleEffect ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bnewentity -
//-----------------------------------------------------------------------------
void C_SporeExplosion : : OnDataChanged ( DataUpdateType_t updateType )
{
C_BaseEntity : : OnDataChanged ( updateType ) ;
if ( updateType = = DATA_UPDATE_CREATED )
{
m_flPreviousSpawnRate = m_flSpawnRate ;
m_teParticleSpawn . Init ( m_flSpawnRate ) ;
Start ( ParticleMgr ( ) , NULL ) ;
}
else if ( m_bEmit )
{
// Just been turned on by the server.
m_flPreviousSpawnRate = m_flSpawnRate ;
m_teParticleSpawn . Init ( m_flSpawnRate ) ;
}
m_pSporeEffect - > SetDontRemove ( m_bDontRemove ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pParticleMgr -
// *pArgs -
//-----------------------------------------------------------------------------
void C_SporeExplosion : : Start ( CParticleMgr * pParticleMgr , IPrototypeArgAccess * pArgs )
{
//Add us into the effect manager
if ( pParticleMgr - > AddEffect ( & m_ParticleEffect , this ) = = false )
return ;
//Create our main effect
m_pSporeEffect = SporeEffect : : Create ( " C_SporeExplosion " ) ;
if ( m_pSporeEffect = = NULL )
return ;
m_hMaterial = m_pSporeEffect - > GetPMaterial ( " particle/fire " ) ;
m_pSporeEffect - > SetSortOrigin ( GetAbsOrigin ( ) ) ;
m_pSporeEffect - > SetNearClip ( 64 , 128 ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_SporeExplosion : : AddParticles ( void )
{
//Spores
Vector offset ;
Vector dir ;
//Get our direction
AngleVectors ( GetAbsAngles ( ) , & dir ) ;
SimpleParticle * sParticle ;
for ( int i = 0 ; i < 4 ; i + + )
{
//Add small particle to the effect's origin
offset . Random ( - m_flSpawnRadius , m_flSpawnRadius ) ;
sParticle = ( SimpleParticle * ) m_pSporeEffect - > AddParticle ( sizeof ( SimpleParticle ) , m_hMaterial , GetAbsOrigin ( ) + offset ) ;
if ( sParticle = = NULL )
return ;
sParticle - > m_flLifetime = 0.0f ;
sParticle - > m_flDieTime = 2.0f ;
sParticle - > m_flRoll = 0 ;
sParticle - > m_flRollDelta = 0 ;
sParticle - > m_uchColor [ 0 ] = 225 ;
sParticle - > m_uchColor [ 1 ] = 140 ;
sParticle - > m_uchColor [ 2 ] = 64 ;
sParticle - > m_uchStartAlpha = Helper_RandomInt ( 128 , 255 ) ;
sParticle - > m_uchEndAlpha = 0 ;
sParticle - > m_uchStartSize = Helper_RandomInt ( 1 , 2 ) ;
sParticle - > m_uchEndSize = 1 ;
sParticle - > m_vecVelocity = dir * Helper_RandomFloat ( 128.0f , 256.0f ) ;
}
//Add smokey bits
offset . Random ( - ( m_flSpawnRadius * 0.5 ) , ( m_flSpawnRadius * 0.5 ) ) ;
sParticle = ( SimpleParticle * ) m_pSporeEffect - > AddParticle ( sizeof ( SimpleParticle ) , g_Mat_DustPuff [ 1 ] , GetAbsOrigin ( ) + offset ) ;
if ( sParticle = = NULL )
return ;
sParticle - > m_flLifetime = 0.0f ;
sParticle - > m_flDieTime = 1.0f ;
sParticle - > m_flRoll = Helper_RandomFloat ( 0 , 360 ) ;
sParticle - > m_flRollDelta = Helper_RandomFloat ( - 2.0f , 2.0f ) ;
sParticle - > m_uchColor [ 0 ] = 225 ;
sParticle - > m_uchColor [ 1 ] = 140 ;
sParticle - > m_uchColor [ 2 ] = 64 ;
sParticle - > m_uchStartAlpha = Helper_RandomInt ( 32 , 64 ) ;
sParticle - > m_uchEndAlpha = 0 ;
sParticle - > m_uchStartSize = m_flStartSize ;
sParticle - > m_uchEndSize = m_flEndSize ;
sParticle - > m_vecVelocity = dir * Helper_RandomFloat ( 64.0f , 128.0f ) ;
}
ConVar cl_sporeclipdistance ( " cl_sporeclipdistance " , " 512 " , FCVAR_CHEAT | FCVAR_CLIENTDLL ) ;
//-----------------------------------------------------------------------------
// Purpose:
// Input : fTimeDelta -
//-----------------------------------------------------------------------------
void C_SporeExplosion : : Update ( float fTimeDelta )
{
if ( m_bEmit )
{
float tempDelta = fTimeDelta ;
float flDist = ( MainViewOrigin ( ) - GetAbsOrigin ( ) ) . Length ( ) ;
//Lower the spawnrate by half if we're far away from it.
if ( cl_sporeclipdistance . GetFloat ( ) < = flDist )
{
if ( m_flSpawnRate = = m_flPreviousSpawnRate )
{
m_flPreviousSpawnRate = m_flSpawnRate * 0.5f ;
m_teParticleSpawn . ResetRate ( m_flPreviousSpawnRate ) ;
}
}
else
{
if ( m_flSpawnRate ! = m_flPreviousSpawnRate )
{
m_flPreviousSpawnRate = m_flSpawnRate ;
m_teParticleSpawn . ResetRate ( m_flPreviousSpawnRate ) ;
}
}
while ( m_teParticleSpawn . NextEvent ( tempDelta ) )
{
AddParticles ( ) ;
}
}
}
void C_SporeExplosion : : SimulateParticles ( CParticleSimulateIterator * pIterator )
{
StandardParticle_t * pParticle = ( StandardParticle_t * ) pIterator - > GetFirst ( ) ;
while ( pParticle )
{
pParticle - > m_Lifetime + = pIterator - > GetTimeDelta ( ) ;
if ( pParticle - > m_Lifetime > m_flParticleLifetime )
{
pIterator - > RemoveParticle ( pParticle ) ;
}
pParticle = ( StandardParticle_t * ) pIterator - > GetNext ( ) ;
}
}
void C_SporeExplosion : : RenderParticles ( CParticleRenderIterator * pIterator )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void RPGShotDownCallback ( const CEffectData & data )
{
CLocalPlayerFilter filter ;
C_BaseEntity : : EmitSound ( filter , SOUND_FROM_WORLD , " Missile.ShotDown " , & data . m_vOrigin ) ;
if ( CExplosionOverlay * pOverlay = new CExplosionOverlay )
{
pOverlay - > m_flLifetime = 0 ;
pOverlay - > m_vPos = data . m_vOrigin ;
pOverlay - > m_nSprites = 1 ;
pOverlay - > m_vBaseColors [ 0 ] . Init ( 1.0f , 0.9f , 0.7f ) ;
pOverlay - > m_Sprites [ 0 ] . m_flHorzSize = 0.01f ;
pOverlay - > m_Sprites [ 0 ] . m_flVertSize = pOverlay - > m_Sprites [ 0 ] . m_flHorzSize * 0.5f ;
pOverlay - > Activate ( ) ;
}
}
DECLARE_CLIENT_EFFECT ( " RPGShotDown " , RPGShotDownCallback ) ;
//==================================================
// C_SporeTrail
//==================================================
class C_SporeTrail : public C_BaseParticleEntity
{
public :
DECLARE_CLASS ( C_SporeTrail , C_BaseParticleEntity ) ;
DECLARE_CLIENTCLASS ( ) ;
C_SporeTrail ( void ) ;
virtual ~ C_SporeTrail ( void ) ;
public :
void SetEmit ( bool bEmit ) ;
// C_BaseEntity
public :
virtual void OnDataChanged ( DataUpdateType_t updateType ) ;
virtual void GetAimEntOrigin ( IClientEntity * pAttachedTo , Vector * pAbsOrigin , QAngle * pAbsAngles ) ;
// IPrototypeAppEffect
public :
virtual void Start ( CParticleMgr * pParticleMgr , IPrototypeArgAccess * pArgs ) ;
// IParticleEffect
public :
virtual void Update ( float fTimeDelta ) ;
virtual void RenderParticles ( CParticleRenderIterator * pIterator ) ;
virtual void SimulateParticles ( CParticleSimulateIterator * pIterator ) ;
virtual void StartRender ( VMatrix & effectMatrix ) ;
public :
Vector m_vecEndColor ;
float m_flSpawnRate ;
float m_flParticleLifetime ;
float m_flStartSize ;
float m_flEndSize ;
float m_flSpawnRadius ;
Vector m_vecVelocityOffset ;
bool m_bEmit ;
private :
C_SporeTrail ( const C_SporeTrail & ) ;
void AddParticles ( void ) ;
PMaterialHandle m_hMaterial ;
TimedEvent m_teParticleSpawn ;
//CSmartPtr<SporeSmokeEffect> m_pSmokeEffect;
Vector m_vecPos ;
Vector m_vecLastPos ; // This is stored so we can spawn particles in between the previous and new position
// to eliminate holes in the trail.
VMatrix m_mAttachmentMatrix ;
CParticleMgr * m_pParticleMgr ;
} ;
//==================================================
// C_SporeTrail
//==================================================
IMPLEMENT_CLIENTCLASS_DT ( C_SporeTrail , DT_SporeTrail , SporeTrail )
RecvPropFloat ( RECVINFO ( m_flSpawnRate ) ) ,
RecvPropVector ( RECVINFO ( m_vecEndColor ) ) ,
RecvPropFloat ( RECVINFO ( m_flParticleLifetime ) ) ,
RecvPropFloat ( RECVINFO ( m_flStartSize ) ) ,
RecvPropFloat ( RECVINFO ( m_flEndSize ) ) ,
RecvPropFloat ( RECVINFO ( m_flSpawnRadius ) ) ,
RecvPropInt ( RECVINFO ( m_bEmit ) ) ,
END_RECV_TABLE ( )
C_SporeTrail : : C_SporeTrail ( void )
{
m_pParticleMgr = NULL ;
//m_pSmokeEffect = SporeSmokeEffect::Create( "C_SporeTrail" );
m_flSpawnRate = 10 ;
m_flParticleLifetime = 5 ;
m_flStartSize = 35 ;
m_flEndSize = 55 ;
m_flSpawnRadius = 2 ;
m_teParticleSpawn . Init ( 5 ) ;
m_vecEndColor . Init ( ) ;
m_vecPos . Init ( ) ;
m_vecLastPos . Init ( ) ;
m_vecVelocityOffset . Init ( ) ;
m_bEmit = true ;
}
C_SporeTrail : : ~ C_SporeTrail ( )
{
if ( m_pParticleMgr )
{
m_pParticleMgr - > RemoveEffect ( & m_ParticleEffect ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bEmit -
//-----------------------------------------------------------------------------
void C_SporeTrail : : SetEmit ( bool bEmit )
{
m_bEmit = bEmit ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bnewentity -
//-----------------------------------------------------------------------------
void C_SporeTrail : : OnDataChanged ( DataUpdateType_t updateType )
{
C_BaseEntity : : OnDataChanged ( updateType ) ;
if ( updateType = = DATA_UPDATE_CREATED )
{
Start ( ParticleMgr ( ) , NULL ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pParticleMgr -
// *pArgs -
//-----------------------------------------------------------------------------
void C_SporeTrail : : Start ( CParticleMgr * pParticleMgr , IPrototypeArgAccess * pArgs )
{
if ( pParticleMgr - > AddEffect ( & m_ParticleEffect , this ) = = false )
return ;
m_hMaterial = g_Mat_DustPuff [ 1 ] ;
m_pParticleMgr = pParticleMgr ;
m_teParticleSpawn . Init ( 64 ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_SporeTrail : : AddParticles ( void )
{
Vector offset = RandomVector ( - 4.0f , 4.0f ) ;
//Make a new particle
SimpleParticle * sParticle = ( SimpleParticle * ) m_ParticleEffect . AddParticle ( sizeof ( SimpleParticle ) , m_hMaterial ) ; //m_pSmokeEffect->AddParticle( sizeof(SimpleParticle), m_hMaterial, GetAbsOrigin()+offset );
if ( sParticle = = NULL )
return ;
sParticle - > m_Pos = offset ;
sParticle - > m_flRoll = Helper_RandomInt ( 0 , 360 ) ;
sParticle - > m_flRollDelta = Helper_RandomFloat ( - 2.0f , 2.0f ) ;
sParticle - > m_flLifetime = 0.0f ;
sParticle - > m_flDieTime = 0.5f ;
sParticle - > m_uchColor [ 0 ] = 225 ;
sParticle - > m_uchColor [ 1 ] = 140 ;
sParticle - > m_uchColor [ 2 ] = 64 ;
sParticle - > m_uchStartAlpha = Helper_RandomInt ( 64 , 128 ) ;
sParticle - > m_uchEndAlpha = 0 ;
sParticle - > m_uchStartSize = 1.0f ;
sParticle - > m_uchEndSize = 1.0f ;
sParticle - > m_vecVelocity = RandomVector ( - 8.0f , 8.0f ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : fTimeDelta -
//-----------------------------------------------------------------------------
void C_SporeTrail : : Update ( float fTimeDelta )
{
if ( m_pParticleMgr = = NULL )
return ;
//Add new particles
if ( m_bEmit )
{
float tempDelta = fTimeDelta ;
while ( m_teParticleSpawn . NextEvent ( tempDelta ) )
{
AddParticles ( ) ;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : &effectMatrix -
//-----------------------------------------------------------------------------
void C_SporeTrail : : StartRender ( VMatrix & effectMatrix )
{
effectMatrix = effectMatrix * m_mAttachmentMatrix ;
}
void C_SporeTrail : : RenderParticles ( CParticleRenderIterator * pIterator )
{
if ( m_bEmit = = false )
return ;
const SimpleParticle * pParticle = ( const SimpleParticle * ) pIterator - > GetFirst ( ) ;
while ( pParticle )
{
//Render
Vector tPos ;
TransformParticle ( m_pParticleMgr - > GetModelView ( ) , pParticle - > m_Pos , tPos ) ;
float sortKey = tPos . z ;
Vector color = Vector ( 1.0f , 1.0f , 1.0f ) ;
//Render it
RenderParticle_ColorSize (
pIterator - > GetParticleDraw ( ) ,
tPos ,
color ,
1.0f ,
4 ) ;
pParticle = ( const SimpleParticle * ) pIterator - > GetNext ( sortKey ) ;
}
}
void C_SporeTrail : : SimulateParticles ( CParticleSimulateIterator * pIterator )
{
if ( m_bEmit = = false )
return ;
SimpleParticle * pParticle = ( SimpleParticle * ) pIterator - > GetFirst ( ) ;
while ( pParticle )
{
//UpdateVelocity( pParticle, timeDelta );
pParticle - > m_Pos + = pParticle - > m_vecVelocity * pIterator - > GetTimeDelta ( ) ;
//Should this particle die?
pParticle - > m_flLifetime + = pIterator - > GetTimeDelta ( ) ;
if ( pParticle - > m_flLifetime > = pParticle - > m_flDieTime )
{
pIterator - > RemoveParticle ( pParticle ) ;
}
pParticle = ( SimpleParticle * ) pIterator - > GetNext ( ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_SporeTrail : : GetAimEntOrigin ( IClientEntity * pAttachedTo , Vector * pAbsOrigin , QAngle * pAbsAngles )
{
C_BaseEntity * pEnt = pAttachedTo - > GetBaseEntity ( ) ;
pEnt - > GetAttachment ( 1 , * pAbsOrigin , * pAbsAngles ) ;
matrix3x4_t matrix ;
AngleMatrix ( * pAbsAngles , * pAbsOrigin , matrix ) ;
m_mAttachmentMatrix = matrix ;
}
//==================================================
// FireTrailhou
//==================================================
// Datatable.. this can have all the smoketrail parameters when we need it to.
IMPLEMENT_CLIENTCLASS_DT ( C_FireTrail , DT_FireTrail , CFireTrail )
RecvPropInt ( RECVINFO ( m_nAttachment ) ) ,
RecvPropFloat ( RECVINFO ( m_flLifetime ) ) ,
END_RECV_TABLE ( )
// ------------------------------------------------------------------------- //
// ParticleMovieExplosion
// ------------------------------------------------------------------------- //
C_FireTrail : : C_FireTrail ( )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_FireTrail : : ~ C_FireTrail ( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pParticleMgr -
// *pArgs -
//-----------------------------------------------------------------------------
void C_FireTrail : : Start ( CParticleMgr * pParticleMgr , IPrototypeArgAccess * pArgs )
{
BaseClass : : Start ( pParticleMgr , pArgs ) ;
m_pTrailEmitter = CSimpleEmitter : : Create ( " FireTrail " ) ;
if ( ! m_pTrailEmitter )
{
Assert ( false ) ;
return ;
}
m_pTrailEmitter - > SetSortOrigin ( GetAbsOrigin ( ) ) ;
// Setup our materials
m_hMaterial [ FTRAIL_SMOKE1 ] = g_Mat_DustPuff [ 0 ] ;
m_hMaterial [ FTRAIL_SMOKE2 ] = g_Mat_DustPuff [ 1 ] ;
m_hMaterial [ FTRAIL_FLAME1 ] = m_pTrailEmitter - > GetPMaterial ( " sprites/flamelet1 " ) ;
m_hMaterial [ FTRAIL_FLAME2 ] = m_pTrailEmitter - > GetPMaterial ( " sprites/flamelet2 " ) ;
m_hMaterial [ FTRAIL_FLAME3 ] = m_pTrailEmitter - > GetPMaterial ( " sprites/flamelet3 " ) ;
m_hMaterial [ FTRAIL_FLAME4 ] = m_pTrailEmitter - > GetPMaterial ( " sprites/flamelet4 " ) ;
m_hMaterial [ FTRAIL_FLAME5 ] = m_pTrailEmitter - > GetPMaterial ( " sprites/flamelet5 " ) ;
// Setup our smoke emitter
m_pSmokeEmitter = CSmokeParticle : : Create ( " FireTrail_Smoke " ) ;
m_pSmokeEmitter - > SetSortOrigin ( GetAbsOrigin ( ) ) ;
m_pSmokeEmitter - > SetNearClip ( 64.0f , 128.0f ) ;
if ( ! m_pSmokeEmitter )
{
Assert ( false ) ;
return ;
}
// Seed our first position as the last known one
m_vecLastPosition = GetAbsOrigin ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : fTimeDelta -
//-----------------------------------------------------------------------------
void C_FireTrail : : Update ( float fTimeDelta )
{
if ( ! m_pTrailEmitter )
return ;
if ( ( m_flLifetime ! = 0 ) & & ( m_flLifetime < = gpGlobals - > curtime ) )
return ;
CSmartPtr < CSimpleEmitter > pSimple = CSimpleEmitter : : Create ( " FireTrail " ) ;
pSimple - > SetSortOrigin ( GetAbsOrigin ( ) ) ;
Vector offset ;
# define STARTSIZE 8
# define ENDSIZE 16
# define PARTICLE_LIFETIME 0.075f
# define MIN_SPEED 32
# define MAX_SPEED 64
// Add new particles
//if ( ShouldEmit() )
{
Vector moveDiff = GetAbsOrigin ( ) - m_vecLastPosition ;
float moveLength = VectorNormalize ( moveDiff ) ;
int numPuffs = moveLength / ( STARTSIZE / 2.0f ) ;
//FIXME: More rational cap here, perhaps
numPuffs = clamp ( numPuffs , 1 , 32 ) ;
SimpleParticle * pParticle ;
Vector offset ;
Vector offsetColor ;
float step = moveLength / numPuffs ;
//Fill in the gaps
for ( int i = 1 ; i < numPuffs + 1 ; i + + )
{
offset = m_vecLastPosition + ( moveDiff * step * i ) + RandomVector ( - 4.0f , 4.0f ) ;
//debugoverlay->AddBoxOverlay( offset, -Vector(2,2,2), Vector(2,2,2), vec3_angle, i*4, i*4, i*4, true, 1.0f );
pParticle = ( SimpleParticle * ) m_pSmokeEmitter - > AddParticle ( sizeof ( SimpleParticle ) , m_hMaterial [ random - > RandomInt ( FTRAIL_FLAME1 , FTRAIL_FLAME5 ) ] , offset ) ;
if ( pParticle ! = NULL )
{
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = /*PARTICLE_LIFETIME*/ 0.5f ; // + random->RandomFloat(PARTICLE_LIFETIME*0.75f, PARTICLE_LIFETIME*1.25f);
pParticle - > m_vecVelocity . Random ( 0.0f , 1.0f ) ;
pParticle - > m_vecVelocity * = random - > RandomFloat ( MIN_SPEED , MAX_SPEED ) ;
pParticle - > m_vecVelocity [ 2 ] + = 50 ; //random->RandomFloat( 32, 64 );
pParticle - > m_uchColor [ 0 ] = 255.0f ;
pParticle - > m_uchColor [ 1 ] = 255.0f ;
pParticle - > m_uchColor [ 2 ] = 255.0f ;
pParticle - > m_uchStartSize = STARTSIZE * 2.0f ;
pParticle - > m_uchEndSize = STARTSIZE * 0.5f ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_flRoll = 0.0f ; //random->RandomInt( 0, 360 );
pParticle - > m_flRollDelta = random - > RandomFloat ( - 16.0f , 16.0f ) ;
}
}
//
// Smoke
//
offset = RandomVector ( - STARTSIZE * 0.5f , STARTSIZE * 0.5f ) + GetAbsOrigin ( ) ;
pParticle = ( SimpleParticle * ) m_pSmokeEmitter - > AddParticle ( sizeof ( SimpleParticle ) , m_hMaterial [ random - > RandomInt ( FTRAIL_SMOKE1 , FTRAIL_SMOKE2 ) ] , offset ) ;
if ( pParticle ! = NULL )
{
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = ( PARTICLE_LIFETIME * 10.0f ) + random - > RandomFloat ( PARTICLE_LIFETIME * 0.75f , PARTICLE_LIFETIME * 1.25f ) ;
pParticle - > m_vecVelocity . Random ( 0.0f , 1.0f ) ;
pParticle - > m_vecVelocity * = random - > RandomFloat ( MIN_SPEED , MAX_SPEED ) ;
pParticle - > m_vecVelocity [ 2 ] + = random - > RandomFloat ( 50 , 100 ) ;
pParticle - > m_uchColor [ 0 ] = 255.0f * 0.5f ;
pParticle - > m_uchColor [ 1 ] = 245.0f * 0.5f ;
pParticle - > m_uchColor [ 2 ] = 205.0f * 0.5f ;
pParticle - > m_uchStartSize = 16 * random - > RandomFloat ( 0.75f , 1.25f ) ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize * 2.5f ;
pParticle - > m_uchStartAlpha = 64 ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = random - > RandomFloat ( - 16.0f , 16.0f ) ;
}
}
// Save off this position
m_vecLastPosition = GetAbsOrigin ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose: High drag, non color changing particle
//-----------------------------------------------------------------------------
class CDustFollower : public CSimpleEmitter
{
public :
CDustFollower ( const char * pDebugName ) : CSimpleEmitter ( pDebugName ) { }
//Create
static CDustFollower * Create ( const char * pDebugName )
{
return new CDustFollower ( pDebugName ) ;
}
//Alpha
virtual float UpdateAlpha ( const SimpleParticle * pParticle )
{
return ( ( ( float ) pParticle - > m_uchStartAlpha / 255.0f ) * sin ( M_PI * ( pParticle - > m_flLifetime / pParticle - > m_flDieTime ) ) ) ;
}
virtual void UpdateVelocity ( SimpleParticle * pParticle , float timeDelta )
{
pParticle - > m_vecVelocity = pParticle - > m_vecVelocity * ExponentialDecay ( 0.3 , timeDelta ) ;
}
//Roll
virtual float UpdateRoll ( SimpleParticle * pParticle , float timeDelta )
{
pParticle - > m_flRoll + = pParticle - > m_flRollDelta * timeDelta ;
pParticle - > m_flRollDelta * = ExponentialDecay ( 0.5 , timeDelta ) ;
return pParticle - > m_flRoll ;
}
private :
CDustFollower ( const CDustFollower & ) ;
} ;
// Datatable.. this can have all the smoketrail parameters when we need it to.
IMPLEMENT_CLIENTCLASS_DT ( C_DustTrail , DT_DustTrail , DustTrail )
RecvPropFloat ( RECVINFO ( m_SpawnRate ) ) ,
RecvPropVector ( RECVINFO ( m_Color ) ) ,
RecvPropFloat ( RECVINFO ( m_ParticleLifetime ) ) ,
RecvPropFloat ( RECVINFO ( m_StopEmitTime ) ) ,
RecvPropFloat ( RECVINFO ( m_MinSpeed ) ) ,
RecvPropFloat ( RECVINFO ( m_MaxSpeed ) ) ,
RecvPropFloat ( RECVINFO ( m_MinDirectedSpeed ) ) ,
RecvPropFloat ( RECVINFO ( m_MaxDirectedSpeed ) ) ,
RecvPropFloat ( RECVINFO ( m_StartSize ) ) ,
RecvPropFloat ( RECVINFO ( m_EndSize ) ) ,
RecvPropFloat ( RECVINFO ( m_SpawnRadius ) ) ,
RecvPropInt ( RECVINFO ( m_bEmit ) ) ,
RecvPropFloat ( RECVINFO ( m_Opacity ) ) ,
END_RECV_TABLE ( )
// ------------------------------------------------------------------------- //
// ParticleMovieExplosion
// ------------------------------------------------------------------------- //
C_DustTrail : : C_DustTrail ( )
{
for ( int i = 0 ; i < DUSTTRAIL_MATERIALS ; i + + )
{
m_MaterialHandle [ i ] = NULL ;
}
m_SpawnRate = 10 ;
m_ParticleSpawn . Init ( 10 ) ;
m_Color . Init ( 0.5 , 0.5 , 0.5 ) ;
m_ParticleLifetime = 5 ;
m_StartEmitTime = gpGlobals - > curtime ;
m_StopEmitTime = 0 ; // No end time
m_MinSpeed = 2 ;
m_MaxSpeed = 4 ;
m_MinDirectedSpeed = m_MaxDirectedSpeed = 0 ;
m_StartSize = 35 ;
m_EndSize = 55 ;
m_SpawnRadius = 2 ;
m_VelocityOffset . Init ( ) ;
m_Opacity = 0.5f ;
m_bEmit = true ;
m_pDustEmitter = NULL ;
m_pParticleMgr = NULL ;
}
C_DustTrail : : ~ C_DustTrail ( )
{
if ( ToolsEnabled ( ) & & clienttools - > IsInRecordingMode ( ) & & m_pDustEmitter . IsValid ( ) & & m_pDustEmitter - > GetToolParticleEffectId ( ) ! = TOOLPARTICLESYSTEMID_INVALID )
{
KeyValues * msg = new KeyValues ( " OldParticleSystem_ActivateEmitter " ) ;
msg - > SetInt ( " id " , m_pDustEmitter - > GetToolParticleEffectId ( ) ) ;
msg - > SetInt ( " emitter " , 0 ) ;
msg - > SetInt ( " active " , false ) ;
msg - > SetFloat ( " time " , gpGlobals - > curtime ) ;
ToolFramework_PostToolMessage ( HTOOLHANDLE_INVALID , msg ) ;
msg - > deleteThis ( ) ;
}
if ( m_pParticleMgr )
{
m_pParticleMgr - > RemoveEffect ( & m_ParticleEffect ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bEmit -
//-----------------------------------------------------------------------------
void C_DustTrail : : SetEmit ( bool bEmit )
{
m_bEmit = bEmit ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : rate -
//-----------------------------------------------------------------------------
void C_DustTrail : : SetSpawnRate ( float rate )
{
m_SpawnRate = rate ;
m_ParticleSpawn . Init ( rate ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bnewentity -
//-----------------------------------------------------------------------------
void C_DustTrail : : OnDataChanged ( DataUpdateType_t updateType )
{
C_BaseEntity : : OnDataChanged ( updateType ) ;
if ( updateType = = DATA_UPDATE_CREATED )
{
Start ( ParticleMgr ( ) , NULL ) ;
}
}
// FIXME: These all have to be moved out of this old system and into the new to leverage art assets!
CLIENTEFFECT_REGISTER_BEGIN ( PrecacheEffectDusttrail )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0001 " )
/*
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0002 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0003 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0004 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0005 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0006 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0007 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0008 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0009 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0010 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0011 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0012 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0013 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0014 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0015 " )
CLIENTEFFECT_MATERIAL ( " particle/smokesprites_0016 " )
*/
CLIENTEFFECT_REGISTER_END ( )
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pParticleMgr -
// *pArgs -
//-----------------------------------------------------------------------------
void C_DustTrail : : Start ( CParticleMgr * pParticleMgr , IPrototypeArgAccess * pArgs )
{
if ( ! pParticleMgr - > AddEffect ( & m_ParticleEffect , this ) )
return ;
m_pParticleMgr = pParticleMgr ;
m_pDustEmitter = CDustFollower : : Create ( " DustTrail " ) ;
if ( ! m_pDustEmitter )
{
Assert ( false ) ;
return ;
}
m_pDustEmitter - > SetSortOrigin ( GetAbsOrigin ( ) ) ;
m_pDustEmitter - > SetNearClip ( 64.0f , 128.0f ) ;
for ( int i = 0 ; i < DUSTTRAIL_MATERIALS ; i + + )
{
//char name[256];
//Q_snprintf( name, sizeof( name ), "particle/smokesprites_%04d", i + 1 );
m_MaterialHandle [ i ] = m_pDustEmitter - > GetPMaterial ( " particle/smokesprites_0001 " ) ;
}
m_ParticleSpawn . Init ( m_SpawnRate ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : fTimeDelta -
//-----------------------------------------------------------------------------
void C_DustTrail : : Update ( float fTimeDelta )
{
if ( ! m_pDustEmitter )
return ;
Vector offsetColor ;
// Add new particles
if ( ! m_bEmit )
return ;
if ( ( m_StopEmitTime ! = 0 ) & & ( m_StopEmitTime < = gpGlobals - > curtime ) )
return ;
float tempDelta = fTimeDelta ;
SimpleParticle * pParticle ;
Vector offset ;
Vector vecOrigin ;
VectorMA ( GetAbsOrigin ( ) , - fTimeDelta , GetAbsVelocity ( ) , vecOrigin ) ;
Vector vecForward ;
GetVectors ( & vecForward , NULL , NULL ) ;
while ( m_ParticleSpawn . NextEvent ( tempDelta ) )
{
float fldt = fTimeDelta - tempDelta ;
offset . Random ( - m_SpawnRadius , m_SpawnRadius ) ;
offset + = vecOrigin ;
VectorMA ( offset , fldt , GetAbsVelocity ( ) , offset ) ;
//if ( random->RandomFloat( 0.f, 5.0f ) > GetAbsVelocity().Length())
// continue;
pParticle = ( SimpleParticle * ) m_pDustEmitter - > AddParticle ( sizeof ( SimpleParticle ) , m_MaterialHandle [ random - > RandomInt ( 0 , 0 ) ] , offset ) ; // FIXME: the other sprites look bad
if ( pParticle = = NULL )
continue ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = m_ParticleLifetime ;
pParticle - > m_vecVelocity . Random ( - 1.0f , 1.0f ) ;
pParticle - > m_vecVelocity * = random - > RandomFloat ( m_MinSpeed , m_MaxSpeed ) ;
pParticle - > m_vecVelocity = pParticle - > m_vecVelocity + GetAbsVelocity ( ) ;
float flDirectedVel = random - > RandomFloat ( m_MinDirectedSpeed , m_MaxDirectedSpeed ) ;
VectorMA ( pParticle - > m_vecVelocity , flDirectedVel , vecForward , pParticle - > m_vecVelocity ) ;
offsetColor = m_Color ;
float flMaxVal = MAX ( m_Color [ 0 ] , m_Color [ 1 ] ) ;
if ( flMaxVal < m_Color [ 2 ] )
{
flMaxVal = m_Color [ 2 ] ;
}
offsetColor / = flMaxVal ;
offsetColor * = random - > RandomFloat ( - 0.2f , 0.2f ) ;
offsetColor + = m_Color ;
offsetColor [ 0 ] = clamp ( offsetColor [ 0 ] , 0.0f , 1.0f ) ;
offsetColor [ 1 ] = clamp ( offsetColor [ 1 ] , 0.0f , 1.0f ) ;
offsetColor [ 2 ] = clamp ( offsetColor [ 2 ] , 0.0f , 1.0f ) ;
pParticle - > m_uchColor [ 0 ] = offsetColor [ 0 ] * 255.0f ;
pParticle - > m_uchColor [ 1 ] = offsetColor [ 1 ] * 255.0f ;
pParticle - > m_uchColor [ 2 ] = offsetColor [ 2 ] * 255.0f ;
pParticle - > m_uchStartSize = m_StartSize ;
pParticle - > m_uchEndSize = m_EndSize ;
float alpha = random - > RandomFloat ( m_Opacity * 0.75f , m_Opacity * 1.25f ) ;
alpha = clamp ( alpha , 0.0f , 1.0f ) ;
if ( m_StopEmitTime ! = 0 & & m_StopEmitTime > m_StartEmitTime )
{
alpha * = sqrt ( ( m_StopEmitTime - gpGlobals - > curtime ) / ( m_StopEmitTime - m_StartEmitTime ) ) ;
}
pParticle - > m_uchStartAlpha = alpha * 255 ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = random - > RandomFloat ( - 1.0f , 1.0f ) ;
}
}
void C_DustTrail : : RenderParticles ( CParticleRenderIterator * pIterator )
{
}
void C_DustTrail : : SimulateParticles ( CParticleSimulateIterator * pIterator )
{
}
//-----------------------------------------------------------------------------
// This is called after sending this entity's recording state
//-----------------------------------------------------------------------------
void C_DustTrail : : CleanupToolRecordingState ( KeyValues * msg )
{
if ( ! ToolsEnabled ( ) )
return ;
BaseClass : : CleanupToolRecordingState ( msg ) ;
// Generally, this is used to allow the entity to clean up
// allocated state it put into the message, but here we're going
// to use it to send particle system messages because we
// know the grenade has been recorded at this point
if ( ! clienttools - > IsInRecordingMode ( ) | | ! m_pDustEmitter . IsValid ( ) )
return ;
// For now, we can't record Dusttrails that don't have a moveparent
C_BaseEntity * pEnt = GetMoveParent ( ) ;
if ( ! pEnt )
return ;
bool bEmitterActive = m_bEmit & & ( ( m_StopEmitTime = = 0 ) | | ( m_StopEmitTime > gpGlobals - > curtime ) ) ;
// NOTE: Particle system destruction message will be sent by the particle effect itself.
if ( m_pDustEmitter - > GetToolParticleEffectId ( ) = = TOOLPARTICLESYSTEMID_INVALID )
{
int nId = m_pDustEmitter - > AllocateToolParticleEffectId ( ) ;
KeyValues * msg = new KeyValues ( " OldParticleSystem_Create " ) ;
msg - > SetString ( " name " , " C_DustTrail " ) ;
msg - > SetInt ( " id " , nId ) ;
msg - > SetFloat ( " time " , gpGlobals - > curtime ) ;
KeyValues * pEmitter = msg - > FindKey ( " DmeSpriteEmitter " , true ) ;
pEmitter - > SetString ( " material " , " particle/smokesprites_0001 " ) ;
pEmitter - > SetInt ( " count " , m_SpawnRate ) ; // particles per second, when duration is < 0
pEmitter - > SetFloat ( " duration " , - 1 ) ; // FIXME
pEmitter - > SetInt ( " active " , bEmitterActive ) ;
KeyValues * pInitializers = pEmitter - > FindKey ( " initializers " , true ) ;
// FIXME: Until we can interpolate ent logs during emission, this can't work
KeyValues * pPosition = pInitializers - > FindKey ( " DmePositionPointToEntityInitializer " , true ) ;
pPosition - > SetPtr ( " entindex " , ( void * ) pEnt - > entindex ( ) ) ;
pPosition - > SetInt ( " attachmentIndex " , GetParentAttachment ( ) ) ;
pPosition - > SetFloat ( " randomDist " , m_SpawnRadius ) ;
pPosition - > SetFloat ( " startx " , pEnt - > GetAbsOrigin ( ) . x ) ;
pPosition - > SetFloat ( " starty " , pEnt - > GetAbsOrigin ( ) . y ) ;
pPosition - > SetFloat ( " startz " , pEnt - > GetAbsOrigin ( ) . z ) ;
KeyValues * pVelocity = pInitializers - > FindKey ( " DmeDecayVelocityInitializer " , true ) ;
pVelocity - > SetFloat ( " velocityX " , pEnt - > GetAbsVelocity ( ) . x ) ;
pVelocity - > SetFloat ( " velocityY " , pEnt - > GetAbsVelocity ( ) . y ) ;
pVelocity - > SetFloat ( " velocityZ " , pEnt - > GetAbsVelocity ( ) . z ) ;
pVelocity - > SetFloat ( " decayto " , 0.5 ) ;
pVelocity - > SetFloat ( " decaytime " , 0.3 ) ;
KeyValues * pLifetime = pInitializers - > FindKey ( " DmeRandomLifetimeInitializer " , true ) ;
pLifetime - > SetFloat ( " minLifetime " , m_ParticleLifetime ) ;
pLifetime - > SetFloat ( " maxLifetime " , m_ParticleLifetime ) ;
KeyValues * pRoll = pInitializers - > FindKey ( " DmeRandomRollInitializer " , true ) ;
pRoll - > SetFloat ( " minRoll " , 0.0f ) ;
pRoll - > SetFloat ( " maxRoll " , 360.0f ) ;
KeyValues * pRollSpeed = pInitializers - > FindKey ( " DmeRandomRollSpeedInitializer " , true ) ;
pRollSpeed - > SetFloat ( " minRollSpeed " , - 1.0f ) ;
pRollSpeed - > SetFloat ( " maxRollSpeed " , 1.0f ) ;
KeyValues * pColor = pInitializers - > FindKey ( " DmeRandomValueColorInitializer " , true ) ;
Color c (
FastFToC ( clamp ( m_Color . x , 0.f , 1.f ) ) ,
FastFToC ( clamp ( m_Color . y , 0.f , 1.f ) ) ,
FastFToC ( clamp ( m_Color . z , 0.f , 1.f ) ) ,
255 ) ;
pColor - > SetColor ( " startColor " , c ) ;
pColor - > SetFloat ( " minStartValueDelta " , 0.0f ) ;
pColor - > SetFloat ( " maxStartValueDelta " , 0.0f ) ;
pColor - > SetColor ( " endColor " , c ) ;
KeyValues * pAlpha = pInitializers - > FindKey ( " DmeRandomAlphaInitializer " , true ) ;
int nMinAlpha = 255 * m_Opacity * 0.75f ;
int nMaxAlpha = 255 * m_Opacity * 1.25f ;
pAlpha - > SetInt ( " minStartAlpha " , clamp ( nMinAlpha , 0 , 255 ) ) ;
pAlpha - > SetInt ( " maxStartAlpha " , clamp ( nMaxAlpha , 0 , 255 ) ) ;
pAlpha - > SetInt ( " minEndAlpha " , clamp ( nMinAlpha , 0 , 255 ) ) ;
pAlpha - > SetInt ( " maxEndAlpha " , clamp ( nMaxAlpha , 0 , 255 ) ) ;
KeyValues * pSize = pInitializers - > FindKey ( " DmeRandomSizeInitializer " , true ) ;
pSize - > SetFloat ( " minStartSize " , m_StartSize ) ;
pSize - > SetFloat ( " maxStartSize " , m_StartSize ) ;
pSize - > SetFloat ( " minEndSize " , m_EndSize ) ;
pSize - > SetFloat ( " maxEndSize " , m_EndSize ) ;
KeyValues * pUpdaters = pEmitter - > FindKey ( " updaters " , true ) ;
pUpdaters - > FindKey ( " DmePositionVelocityDecayUpdater " , true ) ;
pUpdaters - > FindKey ( " DmeRollUpdater " , true ) ;
KeyValues * pRollSpeedUpdater = pUpdaters - > FindKey ( " DmeRollSpeedAttenuateUpdater " , true ) ;
pRollSpeedUpdater - > SetFloat ( " attenuation " , 1.0f - 8.0f / 30.0f ) ;
pRollSpeedUpdater - > SetFloat ( " attenuationTme " , 1.0f / 30.0f ) ;
pRollSpeedUpdater - > SetFloat ( " minRollSpeed " , 0.5f ) ;
pUpdaters - > FindKey ( " DmeAlphaSineRampUpdater " , true ) ;
pUpdaters - > FindKey ( " DmeColorUpdater " , true ) ;
pUpdaters - > FindKey ( " DmeSizeUpdater " , true ) ;
ToolFramework_PostToolMessage ( HTOOLHANDLE_INVALID , msg ) ;
msg - > deleteThis ( ) ;
}
else
{
KeyValues * msg = new KeyValues ( " OldParticleSystem_ActivateEmitter " ) ;
msg - > SetInt ( " id " , m_pDustEmitter - > GetToolParticleEffectId ( ) ) ;
msg - > SetInt ( " emitter " , 0 ) ;
msg - > SetInt ( " active " , bEmitterActive ) ;
msg - > SetFloat ( " time " , gpGlobals - > curtime ) ;
ToolFramework_PostToolMessage ( HTOOLHANDLE_INVALID , msg ) ;
msg - > deleteThis ( ) ;
}
}