Particles and ParticleSystems
Work in Progress | ||
---|---|---|
This page is the result of a currently running discussion. The information on it is subject to change. If you wish to follow the discussion or want to know more about the history of this page, please follow this chat link. |
"Particles" are ingame objects designed to represent things like smoke, gas, sparks, fire and Railgun effects. They're usually contained within a "ParticleSystem" that's attached to a weapon or an object, such as the IFV Repair spark or Ghost Stalker's Railgun. ParticleSystems are basically commanders of single Particles - they spawn their own Particles when needed, tell them where to go, how to act and when to die. There are no unmanaged Particles in the game, even the seemingly independent Poison Gas Particles spawned by the Virus are in fact controlled by the global particle system the game creates especially for "uncontrolled" particles.
BehavesLike
Flag: | BehavesLike |
File(s): | rules(md).ini |
Values: | Smoke, Gas, Fire, Spark, Railgun |
Applicable to: | Particles, ParticleSystems |
The pivotal flag for Particles and ParticleSystems is Template:TTL. As the flag name implies, BehavesLike defines how the Particle or ParticleSystem in question behaves like. There are five possible values for this flag, but unfortunately, Westwood decided to use the exact same flag with the exact same values for both Particles as well as ParticleSystems, making their effects on one of them independent from the other one, but having Particle be influenced by what behavior its ParticleSystem is set to.
This means: Whenever you set this flag, look closely on what kind of object you are setting it - Particle or ParticleSystem. It makes a difference.
BehavesLike=Smoke
This behaviour is normally used to depict smoke caused by damage the object has sustained, or smoke produced by normal functionality of the object (Slave Miner's smoke stacks). The system follows its owner object around.
On Particles
Makes the particles hover at least 5 leptons above ground. This particle can only be rendered as a SHP image. See the section on DC/EC for details on animating the image. Applies WindEffect to the particles as follows:
Every (10 / Template:TTL) frames, the coordinates of the particle are modified by a constant amount depending on [General]→WindDirection=: counting from straight up (North) clockwise, the offsets are: {0,-2}, {2,-2}, {2, 0}, {1, 2}, {0, 2}, {-2,2}, {-2,0}, {-2,-2}. Note that only the fourth offset differs from the offsets used for Gas particles.
On ParticleSystems
These particles, like Gas, float around, but they are also influenced by [AudioVisual]→Gravity= to an extent. In addition to that, they emit Damage, however that Damage doesn't follow the natural damage delivery system and instead just is applied to each object standing in the same cell as the particle itself (except the particle's owner object), ignoring the assigned Warhead's CellSpread entirely. When a particle in this system expires, if it has Template:TTL set, this particle will be spawned, and it has a 5/6 chance of being more translucent than its predecessor, which means you should not chain up more than five particles this way.
Attention: Each successor is spawned twice, so five particles pointing to the same NextParticle will spawn ten particles when they expire.
BehavesLike=Gas
This behaviour is naturally used to depict gases floating around, such as Tiberium Gas emitted by the Veinhole Monster in Tiberian Sun or Poison Gas created by the Virus-induced deaths in Yuri's Revenge. The system usually has no owner object and floats around in accordance to the wind.
On Particles
This particle can only be rendered as a SHP image. Initial Velocity might get a minor random boost. See the section on DC/EC for details on animating the image. Applies WindEffect to the particles as follows:
Every frame, the coordinates of the particle are modified by a constant amount depending on [General]→WindDirection=: counting from straight up (North) clockwise, the constant offsets are: {0,-2}, {2,-2}, {2, 0}, {2, 2}, {0, 2}, {-2,2}, {-2,0}, {-2,-2} , and these are multiplied by Template:TTL before being added to the coordinates. This is applied independently from any movement the particle system is performing.
On ParticleSystems
Doesn't do much except make the particles move around somewhat randomly.
BehavesLike=Fire
This behaviour is used by flamethrower-type weapons like the Devil's Tongue subterranean flame tank in Tiberian Sun. The system obeys the source object's turret facing and will not fire until the turret is correctly facing the target. This behaviour generates lots of particles in a sine wave formation.
On Particles
Kills the particle as it lands to the ground. This particle can only be rendered as a SHP image, with 4 directional variations. the section on DC/EC for more details.
On ParticleSystems
Makes the particle more translucent as it "matures", and, much like Smoke, can damage each object in the same cell except its owner object.
BehavesLike=Spark
This behaviour is used (predictably) to depict sparks caused by damaged electrical systems or welding sparks (IFV Repair weapon). In addition to spawning particles, this behaviour also creates flashes of light programmatically, although other behaviours can also create these flashes in a different way.
On Particles
This particle cannot have any Image set and is always drawn as a single pixel. It is not drawn if the player has selected low Detail Level in Game Options.
On ParticleSystems
Makes the particles affected by [AudioVisual]→Gravity= as they move.
BehavesLike=Railgun
This behaviour is used for the Railgun particles. It is the most complex one, calculating the particles' trajectories along the path as a spiral. There are multiple INI controls to adjust this spiral's behaviour. It also can draw a narrow laser beam along the center of the spiral, this laser is visually quite different from ordinary ones generated by laser-type weapons.
On Particles
This particle cannot have any Image set and is always drawn as a single pixel. Gets a smaller ExistenceCounter bonus than other types.
On ParticleSystems
Doesn't do much except move the particles in a predefined direction.
Spawning
Particles
Aside from particles created when their controlling Particle System behaviour decides to do so, there are some special case particles spawned as part of the global ParticleSystem:
- Template:TTL Once the animation SpawnsParticle is on expires, the specified particle is spawned Template:TTL times.
- GasCloudM1 In TS, the Veinhole Monster spouted a cloud of poisonous gas every once in a while.
- Template:TTL In YR, when a Virus kills a soldier, the animation set under [CombatDamage]→InfantryVirus= is triggered, spawning a particle set through SpawnsParticle once.
ParticleSystems
Particle Systems are spawned by the game under the following circumstances:
- Template:TTL Voxel animations can have ParticleSystems attached.
- [CombatDamage]→DefaultSparkSystem= In YR, if Robot Tanks go offline, this ParticleSystem will be spawned every once in a while.
- Template:TTL When a tank, ship or aircraft (or anything else with Template:TTL) is damaged into yellow condition, a smoke system (BehavesLike=Smoke) is chosen at random from the DamageParticleSystems list is spawned on it. Once the unit has been healed (or killed), the system is destroyed. Should the unit be healed, and then immediately damaged again, a new smoke system will not be spawned while the old one still exists.
- Cyborgs with Template:TTL In TS, when Cyborgs (Template:TTL) had yellow ([AudioVisual]→ConditionYellow=) or less health, sparks would spawn from their bodies (DamageSparks). Similar to Organic units, a system is chosen at random from DamageParticleSystems, only this time, it will be one of the spark systems (BehavesLike=Spark). Again, there can only ever be one system per unit in existence. The odds of this system being created (assuming the previous condition allows it) are set in [General]→ConditionRedSparkingProbability= or [General]→ConditionYellowSparkingProbability=, depending on whether the cyborg's health is below [AudioVisual]→ConditionRed= or not.
- Template:TTL A unit fires a weapon with an AttachedParticleSystem. The weapon should have Template:TTL, Template:TTL or Template:TTL set (depending on the type of ParticleSystem attached), and will not be able to fire any more weapons with that flag until the ParticleSystem expired. (e.g. a unit which fires an IsRailgun=yes weapon has to wait until the railgun system it spawned has vanished before it will be able to fire any other weapon with IsRailgun=yes.)
- Map Actions can call for the creation of a ParticleSystem.
- Scenario start All subjectively "unmanaged" Particles (i.e. those not spawned by a ParticleSystem) are actually part of a hidden global ParticleSystem named "GasCloudSys".
- A Parasite is "firing its weapon" inside its host - the [CombatDamage]→DefaultSparkSystem= will be created. This system is ownerless, will be recreated with each "shot" and will expire on its own.
- A weapon with Template:TTL is fired - the [CombatDamage]→DefaultSparkSystem= will be created. Like the parasite one, this system is ownerless.
- A warhead with Template:TTL set is detonated - an ownerless system declared in this flag will be created. Note that despite the flag being named Particle, you're supposed to specify a ParticleSystem as its value.
- A warhead is detonated in a cell that contains an OverlayType with Template:TTL set - the [CombatDamage]→BarrelParticle= system will be created. Note the Particle/ParticleSystem naming again.
- A Mind Controlling object that's subject to MasterMindOverload logic is overloaded - 5 instances of the [CombatDamage]→DefaultSparkSystem= will be created.
- A BuildingType is placed - the System specified as Template:TTL , if any, is created. This system is recreated whenever the building decloaks, however, this part is done if the BuildingType has the Template:TTL set to non-zero coordinates, without checking that it actually has a NaturalParticleSystem set.
- A BuildingType is destroyed - a random System from those listed in Template:TTL (only systems with Template:TTL are eligible) will be created.
- A Harvester or a Slave unloads ore at a Refinery - up to four instances of the System specified as Template:TTL will be created, depending on how many of Template:TTL, Template:TTL, Template:TTL, Template:TTL are set to non-zero. These systems will auto expire after Template:TTL frames.
Automated Lag Countermeasures
To reduce lag, particles that do not have a non-zero Template:TTL set are not drawn if the frame rate drops below a certain threshold. This is independent from whether or not the particle actually deals damage (only Particles belonging to ParticleSystems with BehavesLike=Fire or BehavesLike=Smoke do).
- Particles with BehavesLike=Spark or BehavesLike=Gas are not drawn at low Visual Detail Level.
- Particles with BehavesLike=Spark or BehavesLike=Railgun cannot have an SHP image and are always drawn as a single pixel.
- Particles with BehavesLike=Smoke, BehavesLike=Gas or BehavesLike=Fire need to have an SHP image (not a voxel!). If Visual Detail Level is set to high, they can be translucent: Setting [Particle]→Translucency= to 25, 50, or any number larger than 74 will respectively make this particle 25%, 50% or 75% translucent. Fire particles become more translucent as they "mature", according to the Template:TTL and Template:TTL controls (see the section on DC/EC for more details). Chained particles in a system that has BehavesLike=Smoke can become more translucent than their predecessors with random luck.
Advanced Controls
The rules(md).ini precedes the [Particles] section with these comments:
; MaxDC = How many frames go by before this particle damages the things near it? (def = 0) ; MaxEC = How many frames does this object last (def = 0) ; Damage = How much damage does it do (def = 0) ; Warhead = What warhead to use for damage purposes (def = WARHEAD_NONE) ; StartFrame = what frame of image to start on? (def = 0) ; NumLoopFrames = how many frames form a single loop? (def = 1) ; WindEffect = to what degree does the wind affect his particle, 0 = not at all, 5 = a lot (def = 0) ; Velocity = speed at which particle travels (def = 0.0) ; Radius = how big is this particle? (used for attract/repel) ; ; BehavesLike, DeleteOnStateLimit, EndStateAI, StateAIAdvance are things that ; shouldn't be messed with
For once, it's not completely unreasonable - those things shouldn't be messed with unless you do know what you're doing.
Most of these flags only apply to particles in ParticleSystems with certain behaviours. Namely, "AIState" advances are only done for ParticleSystems with BehavesLike=Smoke or BehavesLike=Gas. Other behaviours only increment the ExpirationCounter and expire particles if it reaches the limit.
- MaxDC (most likely Damage Counter)
- This flag controls the delay, in frames, before this particle will be able to inflict damage, limited to 65535 frames (wraparound, not saturation).
- MaxEC (most likely Existence Counter)
- This flag controls the delay, in frames, before this particle will expire. In reality, particles get a random lifetime bonus when they're created - particles with BehavesLike=Railgun get a random bonus of [1..10] frames, other particles get a random bonus of [1..MaxEC] frames. Total lifetime is limited to 65535 frames (wraparound, not saturation).
- StateAIAdvance
- Each time this many frames pass in this particle's lifetime, its internal "AIState" is incremented.
- Translucent25State
- Translucent50State
- If a particle's internal "AIState" is equal to these values, the particle becomes 25% or 50% translucent, respectively.
- EndStateAI
- This is the maximum "AIState" for this particle.
- DeleteOnStateLimit
- If set, this particle will be forcibly removed from the game once its AIState matches EndStateAI.
- FinalDamageStage
- The particle will stop emitting damage after this many frames have elapsed since MaxDC expired and it started dealing damage.
- StartFrame
- NumLoopFrames
- Have no effect in Yuri's Revenge. The animation sequences are hardcoded:
- Particles with BehavesLike=Smoke or BehavesLike=Gas use the "AIState" as the frame index.
- Particles with BehavesLike=Fire use the "AIState" + ((direction of the trajectory % 4) * Template:TTL) as the frame index. Basically, the frames [0..EndStateAI - 1] are used for directions 0 and 4 (straight north/south), frames [EndStateAI..2 * EndStateAI - 1] are used for directions 1 and 5 (NE/SW), and so on. Check the TS flameall.shp for details.
"SHP Railgun hack"
The original, pixel-based railgun has one significant drawback: Universally, whenever a railgun is fired, there will be a noticeable slowdown of the game. This made the usage of railguns by modders a double-edged sword - on one hand, especially in Red Alert 2 and Yuri's Revenge, it was a cool, unused effect for weapons; on the other hand, using it, especially on "common" units, would make the game crawl to a halt.
In 2004, gamemate discovered and published a hack that allowed putting SHP images in place of the generated pixels of a railgun. This technique made railguns both more customizable, allowing their usage for a wide array of weapons, as well as, magically, lag free. gamemate's advice was subsequently copied to PPM's tutorial section and has since been the go-to solution for lag-free railguns.
On the technical side, gamemate's statement "both must be present for this to work" is incorrect; the later BehavesLike=Smoke simply overrides BehavesLike=Railgun anyway. What does the magic is a simple fact: The code does not check whether BehavesLike on a Particle is set to the same behavior as BehavesLike on the ParticleSystem controlling it. Knowing this, one can craft constructs in which the two flags mismatch and create new, interesting combinations. The key to this particular hack is having a ParticleSystem that BehavesLike=Railgun and controls Particles which BehavesLike=Smoke, and thus accept (require) SHPs for their imagery.
Example Code
As originally posted by gamemate, cleaned up.
; Particle system [XXXXSys] BehavesLike=Railgun HoldsWhat=XXXXPart Spawns=yes SpawnFrames=1 SpawnRadius=1 Slowdown= ; Can be any number, .002 is a good value ParticleCap=7 SpawnCutoff=10 SpawnTranslucencyCutoff=11
; Particle [XXXXPart] BehavesLike=Smoke MaxEC=30 Image=XXXX ; Short small anims are the best ones Translucency=25 Velocity=5.0 Deacc=.05 WindEffect=0 DeleteOnStateLimit=yes EndStateAI=20 StateAIAdvance=3
See also
- Needs particle flag box here