1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
//========= 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<CSimpleEmitter> 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<CSimpleEmitter> 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 );
|