- Description of FX System
- The innerworkings
- Defining FX
- FX types
- FX property types
- Scheduling and timing effects
- Example 1: single-shot emission for 1 second
- Example 2: periodic emission switching on and off every 1 second during a period of 10 seconds
- Example 3: periodic emission, emitting for 100ms every 1 second during a period of 10 seconds
- Example 4: randomly occurring emission for 100ms during a period of 10 seconds
- Property modifiers
- Internal parameters
- Chaining effects
- Generic properties
Description of FX System
Red Eclipse comes with an extensible FX system, which allows for scripted audio/visual events, such as particles and sounds. Its creation has been motivated by removal of hardcoded parts in the game source code, allowing for further creative customization of various audio/visual aspects of the game.
Current support and usage
FX system is currently only used to script effects for weapons, projectiles and entities. It may be expanded for creation of map FX in the future.
An FX definition consists of a unique name (identifier), type and a set of properties. This information describes exactly the behavior of an effect. It may also contain references to other effects (by name), as to allow for automatic instantiation of child effects and so on. Definitions can be overwritten by simple re-definition. A single definition can only define a single kind of effect: one kind of a particle, one kind of a sound, etc. If multiple effects are desired to be emitted from the same source (by the same emitter), be it of the same or various other types, they can be chained together by parent-child relationship.
An FX emitter is a singular entity responsible for emission of effects. It holds a list of FX instances to emit, as well as all unique states and parameters that modulate the behavior of those instances.
There is a pool of pre-allocated emitters in the engine, which are reused as needed. This however means, that there is a limit to how many emitters can be used at once, at a given time (governed by the
An FX instance is responsible for emission of a single effect. Instances are managed by and bound to emitters. An emitter can have a chain of different instances, each instance emitting a unique effect.
There is a pool of pre-allocated instances in the engine, which are reused as needed. This however means, that there is a limit to how many instances can be used at once, at a given time (governed by the
Effects are defined by using
registerfx [name] [type] [body]
- name -
string- unique identifier
- type -
number- effect type, consult the FX type table. It is recommended handles are used instead, for readability.
- body -
code- block of properties defining the behavior of the effect
registerfx FX_P_AIRBLAST_LIFE $FX_TYPE_PARTICLE [ fxpropi parttype $FX_PARTTYPE_SINGLE fxpropi part $PART_HINT_SOFT fxpropf partsize 32 fxpropi colorized 1 fxpropi fade 1 fxpropf blend 0.1 ]
The list of supported FX types is as follows:
|FX type||Value||CubeScript handle||Description|
FX property types
FX properties have different types, in order to change/set them one must use appropriate functions:
|Colour||fxpropc||[red 0-255] [green 0-255] [blue 0-255]|
|Integer vector||fxpropiv||[integer x] [integer y] [integer z]|
|Float vector||fxpropfv||[float x] [float y] [float z]|
NOTE: On top of the aforementioned arguments, each function accepts optional modifier type and modifier parameter blocks. Those will be explained later.
Scheduling and timing effects
Effects can be scheduled in various ways. To change how timing functions on an effect, one must make use of the appropriate properties. All properties listed here (except for
activelen- time window in milliseconds in which an instance may be activated. After this period, the instance may no longer emit and will become invalidated. Used only when timed with an interval (see
emitlen- time in milliseconds how long a single emission lasts. Default:
emitinterval- interval in milliseconds at which a periodic emission will occur. Emission will only be attempted in a time window determined by
emittimelinessis enabled, an emission may be skipped if the time it takes to finish it (
emitlen) from the current point in time exceeds
activelen. Setting interval to a value of
1implies a standard, non-periodic emission. Default:
emittimeliness- when enabled, makes sure a periodic emission will be able to finish its full cycle (
emitlen) before trying to perform it. Generally, should only be used in cases when an emitter life is known. In other cases, emitters’ life may be prolonged/refreshed (e.g. for projectiles), negating the need to have
activelenpredetermined, unless desired otherwise. Default:
emitdelay- postpones the emission by a given time in milliseconds. Default:
emitparent- when enabled, automatically schedules emission to synchronize with a parent effect. Useful when a parent effect emits periodically (uses
emitsingle- when enabled, prevents an effect from being prolonged/refreshed. Default:
emitrestart- when enabled, resets time-driven parameters (such as interpolation or fade-in) on effect prolong/refresh. Default:
emitmove- as opposed to rest being
integertype, this one is
float, when set above
0, only allows emission when emitter moves at a given speed. Default:
emitparam- only allows emission when internal emitter parameter (see “Internal parameters”) of a given index (
integer) becomes larger than 0. Default:
Effect emissions can also be repeated by iterating an effect. It allows you to create repeated patterns using a single effect instance.
iter- how many times an effect should be emitted. Default:
iteroffset- position vector offset between each emission. Default:
0, 0, 0.
You can also modulate various properties by interpolating the values by the iteration. (see “Property modifiers”)
Example 1: single-shot emission for 1 second
registerfx FX_EXAMPLE1 $FX_TYPE_PARTICLE [ fxpropi emitlen 1000 ]
Example 2: periodic emission switching on and off every 1 second during a period of 10 seconds
registerfx FX_EXAMPLE2 $FX_TYPE_PARTICLE [ fxpropi activelen 10000 fxpropi emitlen 1000 fxpropi emitinterval 2000 fxpropi emittimeliness 1 ]
Example 3: periodic emission, emitting for 100ms every 1 second during a period of 10 seconds
registerfx FX_EXAMPLE3 $FX_TYPE_PARTICLE [ fxpropi activelen 10000 fxpropi emitlen 100 fxpropi emitinterval 1000 fxpropi emittimeliness 1 ]
Various properties can also have modifiers applied such as interpolation or randomness. Using such modifiers one can alter the scheduling parameters randomly or even interpolate them over time.
Example 4: randomly occurring emission for 100ms during a period of 10 seconds
registerfx FX_EXAMPLE4 $FX_TYPE_PARTICLE [ fxpropi activelen 10000 fxpropi emitlen 100 fxpropi emitinterval 2 fxpropi emitinterval 998 $FX_MOD_RAND fxpropi emittimeliness 1 ]
NOTE: In the supplied example a minimum interval of
2 is used, to ensure the emission is treated as periodic. Remember, value of
1 implies standard emission!
Emission will occur randomly from 2 to 1000 milliseconds (the random value is added to the base value).
By default effects will be emitted from the origin position the attached entity and in its direction. However, this can be overridden with the following properties:
The starting position of an effect is referred to as position, pos in short or from. The end position of an effect is referred to as end or to.
reloffset- enforces all position calculations to be done with regards to the entity’s direction. Default:
posoffset- offsets the starting position by a given vector. Default:
0, 0, 0.
endoffset- offsets the end position by a given vector. Default:
0, 0, 0.
endfrompos- sets the end position to be the same as the starting position, offset by a given vector. Disabled when vector is
0, 0, 0. Default:
0, 0, 0.
posfromend- sets the starting position to be the same as the end position, offset by a given vector. Disabled when vector is
0, 0, 0. Default:
0, 0, 0.
posflip- swaps the starting and end positions. Default:
endfromprev- sets the end position as the starting position from the previous frame. Default:
posfromenttag- sets the starting position to the position of an entity tag (see “Entity positions”). Default:
endfromenttag- sets the end position to the position of an entity tag (see “Entity positions”). Default:
posfroment- sets the starting position to one of the positions of an entity (see “Entity positions”). Default:
endfroment- sets the end position to one of the positions of an entity (see “Entity positions”). Default:
Player entities have a number of predefined positions, which can be used to position effects. In addition, they also have a number of tags, which are attached to the entity’s model bones, and follow the entity’s animation.
Entity position points
|Origin||0||$FX_ENT_POS_ORIGIN||Origin position of the entity.|
|Bottom||1||$FX_ENT_POS_BOTTOM||Bottom position of the entity.|
|Middle||2||$FX_ENT_POS_MIDDLE||Middle (by height) position of the entity.|
|Top||3||$FX_ENT_POS_TOP||Top position of the entity.|
|Dir||4||$FX_ENT_POS_DIR||Origin offset by the entity’s direction.|
|Muzzle||5||$FX_ENT_POS_MUZZLE||Gun muzzle position of the entity.|
Entity position tags
As previously mentioned, various properties can have modifiers applied. The availability of modifiers depends on the property. Modifiers can also have their own properties, further allowing for fine-tuning their behavior. Currently, there are two different modifiers available, the list may be expanded in the future:
|Modifier type||Value||CubeScript handle||Description||Has properties|
|Random||0||$FX_MOD_RAND||Adds a random value of
|Interpolation (lerp)||1||$FX_MOD_LERP||Interpolates from the base value to
NOTE: Random state is shared between all instances in an emitter’s chain. That way, the “randomness” can be synchronized between various effects within the same chain.
NOTE: Modifiers are applied in the following order:
Interpolation (lerp) modifier has the following properties (all are
lerptime- time in milliseconds it takes for the base value to reach the target value. Used only when
lerpmodeis not set to parameter mode. Default:
lerpmode- determines interpolation mode, (see “Interpolation modes”). Default:
lerpparam- changes which internal parameter (see “Internal parameters”) is used as the interpolator when
lerpmodein internal parameter mode. Default:
lerpshape- sets the interpolation shape (see “Interpolation shapes”). Default:
|Activation||0||$FX_MOD_LERP_ACTIVE||Interpolation begins with the activation of the emitter.|
|Emission||1||$FX_MOD_LERP_EMIT||Interpolation begins with the scheduled emission of the effect.|
|Internal parameter||2||$FX_MOD_LERP_PARAM||Interpolation by using parameter set by
|Iteration||3||$FX_MOD_LERP_ITER||Interpolation by using the iteration progress as the factor. (see “Iteration”)|
|Linear||0||$FX_MOD_LERP_SHAPE_LINEAR||y = x|
|Square in||1||$FX_MOD_LERP_SHAPE_SQUARE_IN||y = x^2|
|Square out||2||$FX_MOD_LERP_SHAPE_SQUARE_OUT||y = 1 - (1 - x)^2|
|Smooth||3||$FX_MOD_LERP_SHAPE_SMOOTH||y = x^2 * (3 - 2x)|
Example: Interpolating a particle’s size
registerfx FX_EXAMPLES_PARTICLE_SIZE_LERP $FX_TYPE_PARTICLE [ fxpropf partsize 0.5 fxpropf partsize 1.0 $FX_MOD_LERP [ fxpropi lerptime 1000 fxpropi lerpshape $FX_MOD_LERP_SHAPE_SMOOTH ] ]
Certain modifiers (such as interpolation) can use parameters, which are supplied from outside to modulate the behavior of an effect. The availability of parameters depends entirely on the context where an effect is used, therefore, parameters may share IDs if their usage context differs.
|Parameter||Context||Value (ID)||CubeScript handle||Description|
|Weapon power||Weapon FX||0||$W_FX_POWER_PARAM||Cooked weapon power,
|Projectile lifetime||Projectile life FX||0||$P_FX_LIFETIME_PARAM||Lifetime of a projectile,
|Projectile bounce velocity||Projectile bounce FX||0||$P_FX_BOUNCE_VEL_PARAM||Bounce velocity of a projectile,
|Impulse boost||Player impulse FX||0||<n/a>||Set to
There two ways to chain effects together: parenting and end-of-life emission.
When an effect is parented to other, it will be instantiated along with its parent. In order to parent an effect one must use the
fxparent function, passing the parent’s ID as the parameter.
Example 5: one effect parented to another
registerfx FX_EXAMPLE5_PARENT $FX_TYPE_PARTICLE [ ] registerfx FX_EXAMPLE5_CHILD $FX_TYPE_PARTICLE [ fxparent FX_EXAMPLE5_PARENT ]
As mentioned, besides parenting one could define an end-of-life emission, which causes an effect to create a new FX emitter with a desired effect on its end of life (e.g. past
activelen). In order to define such behavior, one must use
fxend command, passing desired effect ID as the parameter.
fxend is meant to be used on the caller, not the callee, which is the opposite of
Example 6: one effect occurring after the end of another
registerfx FX_EXAMPLE6_FIRST $FX_TYPE_PARTICLE [ fxend FX_EXAMPLE6_SECOND ] registerfx FX_EXAMPLE6_SECOND $FX_TYPE_PARTICLE [ ]
These properties are available regardless of the effect type.
|activelen||Integer||1||1||INT_MAX||Random||Instance active time (ms) (see “Scheduling and timing effects”)|
|emitlen||Integer||1||1||INT_MAX||Random, Lerp||Emission time (ms) (see “Scheduling and timing effects”)|
|emitinterval||Integer||1||1||INT_MAX||Random, Lerp||Emission interval (ms) (see “Scheduling and timing effects”)|
|emitdelay||Integer||0||0||INT_MAX||Random, Lerp||Emission delay (ms) (see “Scheduling and timing effects”)|
|emitparent||Integer||0||0||1||Parent scheduling (see “Scheduling and timing effects”)|
|emittimeliness||Integer||0||0||1||Emission timeliness (see “Scheduling and timing effects”)|
|emitsingle||Integer||0||0||1||Single emission (see “Scheduling and timing effects”)|
|emitrestart||Integer||0||0||1||Reset emit state on prolong (see “Scheduling and timing effects”)|
|emitmove||Float||0||0||FLT_MAX||Emission speed threshold (see “Scheduling and timing effects”)|
|emitparam||Integer||-1||-1||8||Emission internal param trigger (see “Scheduling and timing effects”)|
|fadein||Integer||0||0||INT_MAX||Fade in (ms)|
|fadeout||Integer||0||0||INT_MAX||Fade out (ms)|
|colorized||Integer||0||0||1||If enabled, colour is taken from the supplied state.|
|reloffset||Integer||0||1||1||Offset math in relation to direction (see “Positioning”)|
|posoffset||Float vector||-FLT_MAX||0||FLT_MAX||Random, Lerp||Start position offset (see “Positioning”)|
|endoffset||Float vector||-FLT_MAX||0||FLT_MAX||Random, Lerp||End position offset (see “Positioning”)|
|endfrompos||Float vector||-FLT_MAX||0||FLT_MAX||Random, Lerp||End position by offset from start (see “Positioning”)|
|posfromend||Float vector||-FLT_MAX||0||FLT_MAX||Random, Lerp||Start position by offset from end (see “Positioning”)|
|posflip||Integer||0||0||1||Flip start and end positions (see “Positioning”)|
|endfromprev||Integer||0||0||1||Previous start position as the end position (see “Positioning”)|
|posfromenttag||Integer||-1||-1||INT_MAX||Random, Lerp||Start position by entity tag (see “Positioning”)|
|endfromenttag||Integer||-1||-1||INT_MAX||Random, Lerp||End position by entity tag (see “Positioning”)|
|posfroment||Integer||-1||-1||INT_MAX||Random, Lerp||Start position by entity (see “Positioning”)|
|endfroment||Integer||-1||-1||INT_MAX||Random, Lerp||End position by entity (see “Positioning”)|