diff options
Diffstat (limited to 'mp/src/game/client/c_env_particlescript.cpp')
| -rw-r--r-- | mp/src/game/client/c_env_particlescript.cpp | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/mp/src/game/client/c_env_particlescript.cpp b/mp/src/game/client/c_env_particlescript.cpp new file mode 100644 index 00000000..cfbaa84d --- /dev/null +++ b/mp/src/game/client/c_env_particlescript.cpp @@ -0,0 +1,304 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//===========================================================================//
+
+#include "cbase.h"
+#include "c_baseanimating.h"
+#include "particlemgr.h"
+#include "materialsystem/imaterialvar.h"
+#include "cl_animevent.h"
+#include "particle_util.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//-----------------------------------------------------------------------------
+// An entity which emits other entities at points
+//-----------------------------------------------------------------------------
+class C_EnvParticleScript : public C_BaseAnimating, public IParticleEffect
+{
+public:
+ DECLARE_CLASS( C_EnvParticleScript, C_BaseAnimating );
+ DECLARE_CLIENTCLASS();
+
+ C_EnvParticleScript();
+
+// IParticleEffect overrides.
+public:
+ virtual bool ShouldSimulate() const { return m_bSimulate; }
+ virtual void SetShouldSimulate( bool bSim ) { m_bSimulate = bSim; }
+
+ virtual void RenderParticles( CParticleRenderIterator *pIterator );
+ virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
+
+ virtual const Vector &GetSortOrigin();
+
+// C_BaseAnimating overrides
+public:
+ // NOTE: Ths enclosed particle effect binding will do all the drawing
+ // But we have to return true, unlike other particle systems, for the animation events to work
+ virtual bool ShouldDraw() { return true; }
+ virtual int DrawModel( int flags ) { return 0; }
+ virtual int GetFxBlend( void ) { return 0; }
+
+ virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
+ virtual void OnPreDataChanged( DataUpdateType_t updateType );
+ virtual void OnDataChanged( DataUpdateType_t updateType );
+
+private:
+
+ // Creates, destroys particles attached to an attachment
+ void CreateParticle( const char *pAttachmentName, const char *pSpriteName );
+ void DestroyAllParticles( const char *pAttachmentName );
+ void DestroyAllParticles( );
+
+private:
+ struct ParticleScriptParticle_t : public Particle
+ {
+ int m_nAttachment;
+ float m_flSize;
+ };
+
+ CParticleEffectBinding m_ParticleEffect;
+ float m_flMaxParticleSize;
+ int m_nOldSequence;
+ float m_flSequenceScale;
+ bool m_bSimulate;
+};
+
+REGISTER_EFFECT( C_EnvParticleScript );
+
+//-----------------------------------------------------------------------------
+// Datatable
+//-----------------------------------------------------------------------------
+IMPLEMENT_CLIENTCLASS_DT( C_EnvParticleScript, DT_EnvParticleScript, CEnvParticleScript )
+ RecvPropFloat( RECVINFO(m_flSequenceScale) ),
+END_RECV_TABLE()
+
+
+//-----------------------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------------------
+C_EnvParticleScript::C_EnvParticleScript()
+{
+ m_flMaxParticleSize = 0.0f;
+ m_bSimulate = true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Check for changed sequence numbers
+//-----------------------------------------------------------------------------
+void C_EnvParticleScript::OnPreDataChanged( DataUpdateType_t updateType )
+{
+ BaseClass::OnPreDataChanged( updateType );
+
+ m_nOldSequence = GetSequence();
+}
+
+
+//-----------------------------------------------------------------------------
+// Starts up the particle system
+//-----------------------------------------------------------------------------
+void C_EnvParticleScript::OnDataChanged( DataUpdateType_t updateType )
+{
+ BaseClass::OnDataChanged( updateType );
+
+ if(updateType == DATA_UPDATE_CREATED)
+ {
+ ParticleMgr()->AddEffect( &m_ParticleEffect, this );
+ }
+
+ if ( m_nOldSequence != GetSequence() )
+ {
+ DestroyAllParticles();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Creates, destroys particles attached to an attachment
+//-----------------------------------------------------------------------------
+void C_EnvParticleScript::CreateParticle( const char *pAttachmentName, const char *pSpriteName )
+{
+ // Find the attachment
+ int nAttachment = LookupAttachment( pAttachmentName );
+ if ( nAttachment <= 0 )
+ return;
+
+ // Get the sprite materials
+ PMaterialHandle hMat = m_ParticleEffect.FindOrAddMaterial( pSpriteName );
+ ParticleScriptParticle_t *pParticle =
+ (ParticleScriptParticle_t*)m_ParticleEffect.AddParticle(sizeof(ParticleScriptParticle_t), hMat);
+
+ if ( pParticle == NULL )
+ return;
+
+ // Get the sprite size from the material's materialvars
+ bool bFound = false;
+ IMaterialVar *pMaterialVar = NULL;
+ IMaterial *pMaterial = ParticleMgr()->PMaterialToIMaterial( hMat );
+ if ( pMaterial )
+ {
+ pMaterialVar = pMaterial->FindVar( "$spritesize", &bFound, false );
+ }
+
+ if ( bFound )
+ {
+ pParticle->m_flSize = pMaterialVar->GetFloatValue();
+ }
+ else
+ {
+ pParticle->m_flSize = 100.0f;
+ }
+
+ // Make sure the particle cull size reflects our particles
+ if ( pParticle->m_flSize > m_flMaxParticleSize )
+ {
+ m_flMaxParticleSize = pParticle->m_flSize;
+ m_ParticleEffect.SetParticleCullRadius( m_flMaxParticleSize );
+ }
+
+ // Place the particle on the attachment specified
+ pParticle->m_nAttachment = nAttachment;
+ QAngle vecAngles;
+ GetAttachment( nAttachment, pParticle->m_Pos, vecAngles );
+
+ if ( m_flSequenceScale != 1.0f )
+ {
+ pParticle->m_Pos -= GetAbsOrigin();
+ pParticle->m_Pos *= m_flSequenceScale;
+ pParticle->m_Pos += GetAbsOrigin();
+ }
+}
+
+void C_EnvParticleScript::DestroyAllParticles( const char *pAttachmentName )
+{
+ int nAttachment = LookupAttachment( pAttachmentName );
+ if ( nAttachment <= 0 )
+ return;
+
+ int nCount = m_ParticleEffect.GetNumActiveParticles();
+ Particle** ppParticles = (Particle**)stackalloc( nCount * sizeof(Particle*) );
+ int nActualCount = m_ParticleEffect.GetActiveParticleList( nCount, ppParticles );
+ Assert( nActualCount == nCount );
+
+ for ( int i = 0; i < nActualCount; ++i )
+ {
+ ParticleScriptParticle_t *pParticle = (ParticleScriptParticle_t*)ppParticles[i];
+ if ( pParticle->m_nAttachment == nAttachment )
+ {
+ // Mark for deletion
+ pParticle->m_nAttachment = -1;
+ }
+ }
+}
+
+void C_EnvParticleScript::DestroyAllParticles( )
+{
+ int nCount = m_ParticleEffect.GetNumActiveParticles();
+ Particle** ppParticles = (Particle**)stackalloc( nCount * sizeof(Particle*) );
+ int nActualCount = m_ParticleEffect.GetActiveParticleList( nCount, ppParticles );
+ Assert( nActualCount == nCount );
+
+ for ( int i = 0; i < nActualCount; ++i )
+ {
+ ParticleScriptParticle_t *pParticle = (ParticleScriptParticle_t*)ppParticles[i];
+
+ // Mark for deletion
+ pParticle->m_nAttachment = -1;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// The animation events will create particles on the attachment points
+//-----------------------------------------------------------------------------
+void C_EnvParticleScript::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
+{
+ // Handle events to create + destroy particles
+ switch( event )
+ {
+ case CL_EVENT_SPRITEGROUP_CREATE:
+ {
+ char pAttachmentName[256];
+ char pSpriteName[256];
+ int nArgs = sscanf( options, "%255s %255s", pAttachmentName, pSpriteName );
+ if ( nArgs == 2 )
+ {
+ CreateParticle( pAttachmentName, pSpriteName );
+ }
+ }
+ return;
+
+ case CL_EVENT_SPRITEGROUP_DESTROY:
+ {
+ char pAttachmentName[256];
+ int nArgs = sscanf( options, "%255s", pAttachmentName );
+ if ( nArgs == 1 )
+ {
+ DestroyAllParticles( pAttachmentName );
+ }
+ }
+ return;
+ }
+
+ // Fall back
+ BaseClass::FireEvent( origin, angles, event, options );
+}
+
+
+//-----------------------------------------------------------------------------
+// Simulate the particles
+//-----------------------------------------------------------------------------
+void C_EnvParticleScript::RenderParticles( CParticleRenderIterator *pIterator )
+{
+ const ParticleScriptParticle_t* pParticle = (const ParticleScriptParticle_t*)pIterator->GetFirst();
+ while ( pParticle )
+ {
+ Vector vecRenderPos;
+ TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, vecRenderPos );
+ float sortKey = vecRenderPos.z;
+
+ Vector color( 1, 1, 1 );
+ RenderParticle_ColorSize( pIterator->GetParticleDraw(), vecRenderPos, color, 1.0f, pParticle->m_flSize );
+
+ pParticle = (const ParticleScriptParticle_t*)pIterator->GetNext( sortKey );
+ }
+}
+
+void C_EnvParticleScript::SimulateParticles( CParticleSimulateIterator *pIterator )
+{
+ ParticleScriptParticle_t* pParticle = (ParticleScriptParticle_t*)pIterator->GetFirst();
+ while ( pParticle )
+ {
+ // Here's how we retire particles
+ if ( pParticle->m_nAttachment == -1 )
+ {
+ pIterator->RemoveParticle( pParticle );
+ }
+ else
+ {
+ // Move the particle to the attachment point
+ QAngle vecAngles;
+ GetAttachment( pParticle->m_nAttachment, pParticle->m_Pos, vecAngles );
+
+ if ( m_flSequenceScale != 1.0f )
+ {
+ pParticle->m_Pos -= GetAbsOrigin();
+ pParticle->m_Pos *= m_flSequenceScale;
+ pParticle->m_Pos += GetAbsOrigin();
+ }
+ }
+
+ pParticle = (ParticleScriptParticle_t*)pIterator->GetNext();
+ }
+}
+
+const Vector &C_EnvParticleScript::GetSortOrigin()
+{
+ return GetAbsOrigin();
+}
|