Particles In Code: Difference between revisions
TomEdwards (talk | contribs) |
m (Setting bug notice hidetested=1 param on page where the bug might not need tested in param specified) |
||
(7 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
{{toc-right}} | {{toc-right}} | ||
This page details the management of [[:Category:Particle System|"Orange Box" particles]] in C++ code. It does not cover the old, hard-coded particle tech. | |||
== Precaching == | == Precaching == | ||
Particle systems must be [[ | Particle systems must be [[Precaching Assets|precached]] before they can be used. This can be achieved by listing the PCF file containing them in <code>[[particles_manifest.txt]]</code> and utilizing the [[function]] [[PrecacheParticleSystem|PrecacheParticleSystem()]] in code. As an alternative all particle effects within a PCF can be precached by adding a '!' character as a prefix to the path used in <code>particles_manifest.txt</code>. | ||
Precache via code: | |||
<source lang=cpp>PrecacheParticleSystem( "your_particle_effect_name" );</source> | <source lang=cpp>PrecacheParticleSystem( "your_particle_effect_name" );</source> | ||
== | |||
Precache via script: | |||
<source lang=cpp>particles_manifest | |||
{ | |||
"file" "!particles/blood_impact.pcf" // all effects will be precached on map spawn | |||
"file" "particles/fire_01.pcf" // effects contained in this file will have to be precached manually | |||
[...] | |||
}</source> | |||
== Shared == | |||
=== Dispatching === | === Dispatching === | ||
When dispatched from the server, the particle systems will be networked as [[Temporary Entity|temporary entities]]. | |||
<source lang=cpp> | <source lang=cpp> | ||
Line 20: | Line 34: | ||
// Create at model attachment | // Create at model attachment | ||
DispatchParticleEffect( "my_particle", ParticleAttachment_t, pOwner, iAttachment, bResetAllParticlesOnEntity | DispatchParticleEffect( "my_particle", ParticleAttachment_t, pOwner, iAttachment, bResetAllParticlesOnEntity )</source> | ||
See also <code>[[#ParticleAttachment_t|ParticleAttachment_t]]</code>, below. | * See also <code>[[#ParticleAttachment_t|ParticleAttachment_t]]</code>, below. | ||
* <code>vecStart</code>, taken by some overloads of <code>DispatchParticleEffect()</code>, defines the location of [[Control Point (particles)|control point]] 1. If you don't specify <code>vecStart</code>, the value of <code>vecOrigin</code> is used instead. | |||
{{bug|Valve's code for dispatching a particle on a model [[attachment]] is broken. [[SDK Known Issues List Fixed#Server Dispatching an Attached Particle Effect|Get the fix here.]]}} | {{bug|hidetested=1|Valve's code for dispatching a particle on a model [[attachment]] is broken. [[SDK Known Issues List Fixed#Server Dispatching an Attached Particle Effect|Get the fix here.]]}} | ||
=== Destroying === | === Destroying === | ||
Line 35: | Line 50: | ||
=== Creating === | === Creating === | ||
For more control over the effect, a particle system can be created by a new <code>[[CNewParticleEffect]]</code> object and managed through the owning entity's <code>[[ParticleProp()]]</code> accessor: | |||
<source lang=cpp> | <source lang=cpp> | ||
#include "particles_new.h" | #include "particles_new.h" | ||
// Create a new system | C_MyEntity::MessWithParticles() | ||
CNewParticleEffect* pEffect = ParticleProp()->Create( "my_particles", PATTACH_ABSORIGIN ); | { | ||
// Create a new system | |||
CNewParticleEffect* pEffect = ParticleProp()->Create( "my_particles", PATTACH_ABSORIGIN ); | |||
// System already exists | |||
CNewParticleEffect* pEffect = ParticleProp()->FindEffect( "my_particles" ); | |||
} | |||
</source> | |||
'''Particles_new.h''' must also be #included here. | |||
Alternatively, you can hook into particle creation events: | Alternatively, you can hook into particle creation events: | ||
Line 51: | Line 71: | ||
<source lang=cpp>void C_MyEntity::OnNewParticleEffect( const char* pszParticleName, CNewParticleEffect* pNewParticleEffect ) | <source lang=cpp>void C_MyEntity::OnNewParticleEffect( const char* pszParticleName, CNewParticleEffect* pNewParticleEffect ) | ||
{ | { | ||
// | if ( V_strcmp(pszParticleName, "target_effect_name") == 0 ) | ||
{ | |||
// Do something | |||
} | |||
}</source> | }</source> | ||
{{warning|A [[#Dispatching|dispatch]] message from the server configures both [[Control Point (particles)|control point]] 0 '''AND''' 1. The values are applied after <code>OnNewParticleEffect()</code> is called, so don't bother trying to assign either of those CPs from it!}} | |||
=== Control points === | === Control points === | ||
When dispatching an effect from the server you can define the location of [[Control Point (particles)|control points]] 0 (with <code>vecOrigin</code>) and 1 (with <code>vecStart</code>). | |||
On the client, you can configure the location, rotation and parent entity of any CP with these <code>CNewParticleEffect</code> functions: | |||
; <code>SetControlPoint( [[Vector]] )</code> | ; <code>SetControlPoint( [[Vector]] )</code> | ||
Line 66: | Line 93: | ||
; <code>SetControlPointForwardVector()</code> | ; <code>SetControlPointForwardVector()</code> | ||
; <code>SetControlPointUpVector()</code> | ; <code>SetControlPointUpVector()</code> | ||
: Set orientation with a [[QAngle]] or series of Vectors. | : Set orientation with a [[QAngle]] or a series of Vectors. | ||
=== Destroying === | === Destroying === | ||
Line 92: | Line 119: | ||
: Spawn at a given origin. | : Spawn at a given origin. | ||
; <code>PATTACH_WORLDORIGIN</code> | ; <code>PATTACH_WORLDORIGIN</code> | ||
: Don't associate with an entity at all. Use with caution - could easily cause memory leaks. | : Don't associate with an entity at all. ''Use with caution - could easily cause memory leaks.'' | ||
[[Category: Particle System]] | [[Category:Particle System]] | ||
[[Category:Programming]] |
Latest revision as of 07:14, 20 May 2025
This page details the management of "Orange Box" particles in C++ code. It does not cover the old, hard-coded particle tech.
Precaching
Particle systems must be precached before they can be used. This can be achieved by listing the PCF file containing them in particles_manifest.txt
and utilizing the function PrecacheParticleSystem() in code. As an alternative all particle effects within a PCF can be precached by adding a '!' character as a prefix to the path used in particles_manifest.txt
.
Precache via code:
PrecacheParticleSystem( "your_particle_effect_name" );
Precache via script:
particles_manifest
{
"file" "!particles/blood_impact.pcf" // all effects will be precached on map spawn
"file" "particles/fire_01.pcf" // effects contained in this file will have to be precached manually
[...]
}
Dispatching
When dispatched from the server, the particle systems will be networked as temporary entities.
#include "particle_parse.h"
// Create at world co-ords
DispatchParticleEffect( "my_particle", vecOrigin, angAngles, pOwnerEntity )
// Create at model attachment
DispatchParticleEffect( "my_particle", ParticleAttachment_t, pOwner, iAttachment, bResetAllParticlesOnEntity )
- See also
ParticleAttachment_t
, below. vecStart
, taken by some overloads ofDispatchParticleEffect()
, defines the location of control point 1. If you don't specifyvecStart
, the value ofvecOrigin
is used instead.

Destroying
StopParticleEffects( CBaseEntity* )
- Stops all effects on the given entity.
Client
Creating
For more control over the effect, a particle system can be created by a new CNewParticleEffect
object and managed through the owning entity's ParticleProp()
accessor:
#include "particles_new.h"
C_MyEntity::MessWithParticles()
{
// Create a new system
CNewParticleEffect* pEffect = ParticleProp()->Create( "my_particles", PATTACH_ABSORIGIN );
// System already exists
CNewParticleEffect* pEffect = ParticleProp()->FindEffect( "my_particles" );
}
Particles_new.h must also be #included here.
Alternatively, you can hook into particle creation events:
void C_MyEntity::OnNewParticleEffect( const char* pszParticleName, CNewParticleEffect* pNewParticleEffect )
{
if ( V_strcmp(pszParticleName, "target_effect_name") == 0 )
{
// Do something
}
}

OnNewParticleEffect()
is called, so don't bother trying to assign either of those CPs from it!Control points
When dispatching an effect from the server you can define the location of control points 0 (with vecOrigin
) and 1 (with vecStart
).
On the client, you can configure the location, rotation and parent entity of any CP with these CNewParticleEffect
functions:
SetControlPoint( Vector )
- Arbitrary set the CP's value.
SetControlPointEntity( CBaseEntity* )
- Follow the given entity's origin.
Confirm:Set to NULL to disable following.
SetControlPointOrientation( QAngle )
SetControlPointRightVector()
SetControlPointForwardVector()
SetControlPointUpVector()
- Set orientation with a QAngle or a series of Vectors.
Destroying
StopParticleEffects( CBaseEntity* )
- Stops all effects on the given entity.
ParticleProp()->StopParticlesInvolving( CBaseEntity* )
- Stops all effects with a control point attached to the given entity. Todo: Global or only on current entity?
ParticleProp()->StopParticlesNamed( const char* )
- Stops all effects with the given system name. Todo: Global or only on current entity?
CNewParticleEffect::StopEmission( bool bInfiniteOnly, bool bRemoveAllParticles, bool bWakeOnStop)
- Stops the current particle system, without removing it. Todo: Meaning of first and third arguments.
ParticleAttachment_t
One of these values is passed when dispatching or creating an effect:
PATTACH_ABSORIGIN
PATTACH_ABSORIGIN_FOLLOW
- Spawn at (and optionally follow) the entity's origin.
PATTACH_POINT
PATTACH_POINT_FOLLOW
- Spawn at (and optionally follow) an attachment point on the entity's model.
PATTACH_CUSTOMORIGIN
- Spawn at a given origin.
PATTACH_WORLDORIGIN
- Don't associate with an entity at all. Use with caution - could easily cause memory leaks.