diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/client/c_particle_system.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/client/c_particle_system.cpp')
| -rw-r--r-- | mp/src/game/client/c_particle_system.cpp | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/mp/src/game/client/c_particle_system.cpp b/mp/src/game/client/c_particle_system.cpp new file mode 100644 index 00000000..fc70c8aa --- /dev/null +++ b/mp/src/game/client/c_particle_system.cpp @@ -0,0 +1,274 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "cbase.h"
+#include "particles/particles.h"
+#include "c_te_effect_dispatch.h"
+#include "particles_new.h"
+#include "networkstringtable_clientdll.h"
+#include "tier0/vprof.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//-----------------------------------------------------------------------------
+// Purpose: An entity that spawns and controls a particle system
+//-----------------------------------------------------------------------------
+class C_ParticleSystem : public C_BaseEntity
+{
+ DECLARE_CLASS( C_ParticleSystem, C_BaseEntity );
+public:
+ DECLARE_CLIENTCLASS();
+
+ C_ParticleSystem();
+
+ void PreDataUpdate( DataUpdateType_t updateType );
+ void PostDataUpdate( DataUpdateType_t updateType );
+ void ClientThink( void );
+
+protected:
+ int m_iEffectIndex;
+ bool m_bActive;
+ bool m_bOldActive;
+ float m_flStartTime; // Time at which the effect started
+
+ enum { kMAXCONTROLPOINTS = 63 }; ///< actually one less than the total number of cpoints since 0 is assumed to be me
+
+
+ EHANDLE m_hControlPointEnts[kMAXCONTROLPOINTS];
+ // SendPropArray3( SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt( SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED ) ),
+ unsigned char m_iControlPointParents[kMAXCONTROLPOINTS];
+
+ bool m_bWeatherEffect;
+};
+
+IMPLEMENT_CLIENTCLASS(C_ParticleSystem, DT_ParticleSystem, CParticleSystem);
+
+BEGIN_RECV_TABLE_NOBASE( C_ParticleSystem, DT_ParticleSystem )
+ RecvPropVector( RECVINFO_NAME( m_vecNetworkOrigin, m_vecOrigin ) ),
+ RecvPropEHandle( RECVINFO(m_hOwnerEntity) ),
+ RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ),
+ RecvPropInt( RECVINFO( m_iParentAttachment ) ),
+ RecvPropQAngles( RECVINFO_NAME( m_angNetworkAngles, m_angRotation ) ),
+
+ RecvPropInt( RECVINFO( m_iEffectIndex ) ),
+ RecvPropBool( RECVINFO( m_bActive ) ),
+ RecvPropFloat( RECVINFO( m_flStartTime ) ),
+
+ RecvPropArray3( RECVINFO_ARRAY(m_hControlPointEnts), RecvPropEHandle( RECVINFO( m_hControlPointEnts[0] ) ) ),
+ RecvPropArray3( RECVINFO_ARRAY(m_iControlPointParents), RecvPropInt( RECVINFO(m_iControlPointParents[0]))),
+ RecvPropBool( RECVINFO( m_bWeatherEffect ) ),
+END_RECV_TABLE();
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+C_ParticleSystem::C_ParticleSystem()
+{
+ m_bWeatherEffect = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void C_ParticleSystem::PreDataUpdate( DataUpdateType_t updateType )
+{
+ m_bOldActive = m_bActive;
+
+ BaseClass::PreDataUpdate( updateType );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void C_ParticleSystem::PostDataUpdate( DataUpdateType_t updateType )
+{
+ BaseClass::PostDataUpdate( updateType );
+
+ // Always restart if just created and updated
+ // FIXME: Does this play fairly with PVS?
+ if ( updateType == DATA_UPDATE_CREATED )
+ {
+ if ( m_bActive )
+ {
+ // Delayed here so that we don't get invalid abs queries on level init with active particle systems
+ SetNextClientThink( gpGlobals->curtime );
+ }
+ }
+ else
+ {
+ if ( m_bOldActive != m_bActive )
+ {
+ if ( m_bActive )
+ {
+ // Delayed here so that we don't get invalid abs queries on level init with active particle systems
+ SetNextClientThink( gpGlobals->curtime );
+ }
+ else
+ {
+ ParticleProp()->StopEmission();
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void C_ParticleSystem::ClientThink( void )
+{
+ if ( m_bActive )
+ {
+ const char *pszName = GetParticleSystemNameFromIndex( m_iEffectIndex );
+ if ( pszName && pszName[0] )
+ {
+ if ( !GameRules()->AllowMapParticleEffect( pszName ) )
+ return;
+
+ if ( m_bWeatherEffect && !GameRules()->AllowWeatherParticles() )
+ return;
+
+ CNewParticleEffect *pEffect = ParticleProp()->Create( pszName, PATTACH_ABSORIGIN_FOLLOW );
+ AssertMsg1( pEffect, "Particle system couldn't make %s", pszName );
+ if (pEffect)
+ {
+ for ( int i = 0 ; i < kMAXCONTROLPOINTS ; ++i )
+ {
+ CBaseEntity *pOnEntity = m_hControlPointEnts[i].Get();
+ if ( pOnEntity )
+ {
+ ParticleProp()->AddControlPoint( pEffect, i + 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW );
+ }
+
+ AssertMsg2( m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS ,
+ "Particle system specified bogus control point parent (%d) for point %d.",
+ m_iControlPointParents[i], i );
+
+ if (m_iControlPointParents[i] != 0)
+ {
+ pEffect->SetControlPointParent(i+1, m_iControlPointParents[i]);
+ }
+ }
+
+ // NOTE: What we really want here is to compare our lifetime and that of our children and see if this delta is
+ // already past the end of it, denoting that we're finished. In that case, just destroy us and be done. -- jdw
+
+ // TODO: This can go when the SkipToTime code below goes
+ ParticleProp()->OnParticleSystemUpdated( pEffect, 0.0f );
+
+ // Skip the effect ahead if we're restarting it
+ float flTimeDelta = gpGlobals->curtime - m_flStartTime;
+ if ( flTimeDelta > 0.01f )
+ {
+ VPROF_BUDGET( "C_ParticleSystem::ClientThink SkipToTime", "Particle Simulation" );
+ pEffect->SkipToTime( flTimeDelta );
+ }
+ }
+ }
+ }
+}
+
+
+//======================================================================================================================
+// PARTICLE SYSTEM DISPATCH EFFECT
+//======================================================================================================================
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void ParticleEffectCallback( const CEffectData &data )
+{
+ if ( SuppressingParticleEffects() )
+ return; // this needs to be before using data.m_nHitBox, since that may be a serialized value that's past the end of the current particle system string table
+
+ const char *pszName = GetParticleSystemNameFromIndex( data.m_nHitBox );
+
+ CSmartPtr<CNewParticleEffect> pEffect = NULL;
+ if ( data.m_fFlags & PARTICLE_DISPATCH_FROM_ENTITY )
+ {
+ if ( data.m_hEntity.Get() )
+ {
+ C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity );
+ if ( pEnt && !pEnt->IsDormant() )
+ {
+ if ( data.m_fFlags & PARTICLE_DISPATCH_RESET_PARTICLES )
+ {
+ pEnt->ParticleProp()->StopEmission();
+ }
+
+ pEffect = pEnt->ParticleProp()->Create( pszName, (ParticleAttachment_t)data.m_nDamageType, data.m_nAttachmentIndex );
+ AssertMsg2( pEffect.IsValid() && pEffect->IsValid(), "%s could not create particle effect %s",
+ C_BaseEntity::Instance( data.m_hEntity )->GetDebugName(), pszName );
+ if ( pEffect.IsValid() && pEffect->IsValid() )
+ {
+ if ( (ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN )
+ {
+ pEffect->SetSortOrigin( data.m_vOrigin );
+ pEffect->SetControlPoint( 0, data.m_vOrigin );
+ pEffect->SetControlPoint( 1, data.m_vStart );
+ Vector vecForward, vecRight, vecUp;
+ AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp );
+ pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp );
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( GameRules() )
+ {
+ pszName = GameRules()->TranslateEffectForVisionFilter( "particles", pszName );
+ }
+
+ pEffect = CNewParticleEffect::Create( NULL, pszName );
+ if ( pEffect->IsValid() )
+ {
+ pEffect->SetSortOrigin( data.m_vOrigin );
+ pEffect->SetControlPoint( 0, data.m_vOrigin );
+ pEffect->SetControlPoint( 1, data.m_vStart );
+ Vector vecForward, vecRight, vecUp;
+ AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp );
+ pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp );
+ }
+ }
+
+ if ( pEffect.IsValid() && pEffect->IsValid() )
+ {
+ if ( data.m_bCustomColors )
+ {
+ pEffect->SetControlPoint( CUSTOM_COLOR_CP1, data.m_CustomColors.m_vecColor1 );
+ pEffect->SetControlPoint( CUSTOM_COLOR_CP2, data.m_CustomColors.m_vecColor2 );
+ }
+
+ if ( data.m_bControlPoint1 )
+ {
+ pEffect->SetControlPoint( 1, data.m_ControlPoint1.m_vecOffset );
+ }
+ }
+}
+
+DECLARE_CLIENT_EFFECT( "ParticleEffect", ParticleEffectCallback );
+
+
+//======================================================================================================================
+// PARTICLE SYSTEM STOP EFFECT
+//======================================================================================================================
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void ParticleEffectStopCallback( const CEffectData &data )
+{
+ if ( data.m_hEntity.Get() )
+ {
+ C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity );
+ if ( pEnt )
+ {
+ pEnt->ParticleProp()->StopEmission();
+ }
+ }
+ }
+
+DECLARE_CLIENT_EFFECT( "ParticleEffectStop", ParticleEffectStopCallback );
|