//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: A simple test entity for creating special effects // //============================================================================= #include "cbase.h" #include "c_te_effect_dispatch.h" #include "particles_simple.h" // Declare the sparkler entity for the client-side class C_Sparkler : public C_BaseEntity { public: DECLARE_CLIENTCLASS(); DECLARE_CLASS( C_Sparkler, C_BaseEntity ); virtual void OnDataChanged( DataUpdateType_t updateType ); // Called when data changes on the server virtual void ClientThink( void ); // Client-side think function for the entity private: bool m_bEmit; // Determines whether or not we should emit particles float m_flScale; // Size of the effect CSmartPtr m_hEmitter; // Particle emitter for this entity PMaterialHandle m_hMaterial; // Material handle used for this entity's particles TimedEvent m_tParticleTimer; // Timer used to control particle emission rate }; // Declare the data-table for server/client communication IMPLEMENT_CLIENTCLASS_DT( C_Sparkler, DT_Sparkler, CSparkler ) RecvPropInt( RECVINFO( m_bEmit ) ), // Boolean state from the server RecvPropFloat( RECVINFO( m_flScale ) ), END_RECV_TABLE() //----------------------------------------------------------------------------- // Purpose: Called when data changes on the server //----------------------------------------------------------------------------- void C_Sparkler::OnDataChanged( DataUpdateType_t updateType ) { // NOTE: We MUST call the base classes' implementation of this function BaseClass::OnDataChanged( updateType ); // Setup our entity's particle system on creation if ( updateType == DATA_UPDATE_CREATED ) { // Creat the emitter m_hEmitter = CSimpleEmitter::Create( "env_sparkler" ); // Obtain a reference handle to our particle's desired material if ( m_hEmitter.IsValid() ) { m_hMaterial = m_hEmitter->GetPMaterial( "effects/yellowflare" ); } // Spawn 128 particles per second m_tParticleTimer.Init( 128 ); // Call our ClientThink() function once every client frame SetNextClientThink( CLIENT_THINK_ALWAYS ); } } //----------------------------------------------------------------------------- // Purpose: Client-side think function for the entity //----------------------------------------------------------------------------- void C_Sparkler::ClientThink( void ) { // We must have a valid emitter if ( m_hEmitter == NULL ) return; // We must be allowed to emit particles by the server if ( m_bEmit == false ) return; SimpleParticle *pParticle; float curTime = gpGlobals->frametime; // Add as many particles as required this frame while ( m_tParticleTimer.NextEvent( curTime ) ) { // Create the particle pParticle = m_hEmitter->AddSimpleParticle( m_hMaterial, GetAbsOrigin() ); if ( pParticle == NULL ) return; // Setup our size pParticle->m_uchStartSize = (unsigned char) m_flScale; pParticle->m_uchEndSize = 0; // Setup our roll pParticle->m_flRoll = random->RandomFloat( 0, 2*M_PI ); pParticle->m_flRollDelta = random->RandomFloat( -DEG2RAD( 180 ), DEG2RAD( 180 ) ); // Set our color pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; // Setup our alpha values pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 255; // Obtain a random direction Vector velocity = RandomVector( -1.0f, 1.0f ); VectorNormalize( velocity ); // Obtain a random speed float speed = random->RandomFloat( 4.0f, 8.0f ) * m_flScale; // Set our velocity pParticle->m_vecVelocity = velocity * speed; // Die in a short range of time pParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f ); } } // ============================================================================ // // Dispatch Effect version // // ============================================================================ //----------------------------------------------------------------------------- // Purpose: Callback to create a sparkle effect on the client // Input : &data - information about the effect //----------------------------------------------------------------------------- void SparkleCallback( const CEffectData &data ) { // Create a simple particle emitter CSmartPtr pSparkleEmitter = CSimpleEmitter::Create( "Sparkle" ); if ( pSparkleEmitter == NULL ) return; // Make local versions of our passed in data Vector origin = data.m_vOrigin; float scale = data.m_flScale; // Set our sort origin to make the system cull properly pSparkleEmitter->SetSortOrigin( origin ); // Find the material handle we wish to use for these particles PMaterialHandle hMaterial = pSparkleEmitter->GetPMaterial( "effects/yellowflare" ); SimpleParticle *pParticle; // Make a group of particles in the world for ( int i = 0; i < 64; i++ ) { // Create a particle pParticle = pSparkleEmitter->AddSimpleParticle( hMaterial, origin ); if ( pParticle == NULL ) return; // Set our sizes pParticle->m_uchStartSize = (unsigned char) scale; pParticle->m_uchEndSize = 0; // Set our roll pParticle->m_flRoll = random->RandomFloat( 0, 2*M_PI ); pParticle->m_flRollDelta = random->RandomFloat( -DEG2RAD( 180 ), DEG2RAD( 180 ) ); // Set our color pParticle->m_uchColor[0] = 255; // Red pParticle->m_uchColor[1] = 255; // Green pParticle->m_uchColor[2] = 255; // Blue // Set our alpha pParticle->m_uchStartAlpha = 0; pParticle->m_uchEndAlpha = 255; // Create a random vector Vector velocity = RandomVector( -1.0f, 1.0f ); VectorNormalize( velocity ); // Find a random speed for the particle float speed = random->RandomFloat( 4.0f, 8.0f ) * scale; // Build and set the velocity of the particle pParticle->m_vecVelocity = velocity * speed; // Declare our lifetime pParticle->m_flDieTime = 1.0f; } } // This links our server-side call to a client-side function DECLARE_CLIENT_EFFECT( "Sparkle", SparkleCallback );