Particles In Code: Difference between revisions
No edit summary  | 
				m (Setting bug notice hidetested=1 param on page where the bug might not need tested in param specified)  | 
				||
| (27 intermediate revisions by 9 users not shown) | |||
| Line 1: | Line 1: | ||
{{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 ==  | |||
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>  | |||
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 ===  | |||
When dispatched from the server, the particle systems will be networked as [[Temporary Entity|temporary entities]].  | |||
<source lang=cpp>  | |||
#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 )</source>  | |||
* 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|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 ===  | |||
; <code>StopParticleEffects( CBaseEntity* )</code>  | |||
: Stops all effects on the given entity.  | |||
== Client ==  | |||
=== 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>  | |||
#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" );  | |||
}  | |||
</source>  | |||
'''Particles_new.h''' must also be #included here.  | |||
Alternatively, you can hook into particle creation events:  | |||
<source lang=cpp>void C_MyEntity::OnNewParticleEffect( const char* pszParticleName, CNewParticleEffect* pNewParticleEffect )  | |||
{  | |||
	if ( V_strcmp(pszParticleName, "target_effect_name") == 0 )  | |||
	{  | |||
		// Do something  | |||
	}  | |||
}</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 ===  | |||
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>  | |||
: Arbitrary set the CP's value.  | |||
; <code>SetControlPointEntity( CBaseEntity* )</code>  | |||
: Follow the given entity's [[origin]]. {{confirm|Set to NULL to disable following.}}  | |||
; <code>SetControlPointOrientation( [[QAngle]] )</code>  | |||
; <code>SetControlPointRightVector()</code>  | |||
; <code>SetControlPointForwardVector()</code>  | |||
; <code>SetControlPointUpVector()</code>  | |||
: Set orientation with a [[QAngle]] or a series of Vectors.  | |||
=== Destroying ===  | |||
; <code>StopParticleEffects( CBaseEntity* )</code>  | |||
: Stops all effects on the given entity.  | |||
; <code>ParticleProp()->StopParticlesInvolving( CBaseEntity* )</code>  | |||
: Stops all effects with a control point attached to the given entity. {{todo|Global or only on current entity?}}  | |||
; <code>ParticleProp()->StopParticlesNamed( const char* )</code>  | |||
: Stops all effects with the given system name. {{todo|Global or only on current entity?}}  | |||
; <code>CNewParticleEffect<nowiki>::</nowiki>StopEmission( bool bInfiniteOnly, bool bRemoveAllParticles, bool bWakeOnStop)</code>  | |||
: 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:  | |||
; <code>PATTACH_ABSORIGIN</code>  | |||
; <code>PATTACH_ABSORIGIN_FOLLOW</code>  | |||
: Spawn at (and optionally follow) the entity's [[origin]].  | |||
; <code>PATTACH_POINT</code>  | |||
; <code>PATTACH_POINT_FOLLOW</code>  | |||
: Spawn at (and optionally follow) an [[attachment]] point on the entity's model.  | |||
; <code>PATTACH_CUSTOMORIGIN</code>  | |||
: Spawn at a given origin.  | |||
; <code>PATTACH_WORLDORIGIN</code>  | |||
: Don't associate with an entity at all. ''Use with caution - could easily cause memory leaks.''  | |||
[[Category:Particle System]]  | |||
[[Category:Programming]]  | |||
Latest revision as of 06: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 ofvecOriginis 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_ABSORIGINPATTACH_ABSORIGIN_FOLLOW- Spawn at (and optionally follow) the entity's origin.
 PATTACH_POINTPATTACH_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.