Fx Groups
Testing FxGroups
[edit | edit source]Open up fx_group_texter.tscn and Run Current Scene (Ctrl+R).

The two panels on the left are:
- Attack FXGs. These are fxgs that have a corresponding target fxg. The base one runs at the originating tile and the target one runs at the target tile(s).
- Other FXGs. Abilities or events, at the originating tile only.
FXGs are added to each list by their file names; when the system finds a pair of fxgs with one ending in "_target", it will add the two to the top list and otherwise in the bottom.
This scene hot-reloads! If you modify an FXG scene in the editor, save it, and then switch back to the running tester, re-running the FXG should use the updated values! This should work for tweaking resources, but you may have to re-run the scene in order to obtain new graphic files or sounds.
Anatomy of an FxGroup
[edit | edit source]
Fx Group scenes are composed of a FxGroup node with some number of children nodes that play sprite animations, FMOD sound effect events, particle emitters, and movements of the originating mech token.
They can also have sub-FxGroup nodes as children to coordinate the ordering and timing of such effects. These children FxGroups can have their own basic effects and FxGroup children of their own, etc. The timing of when children FxGroups play their effects is detailed below.
In order to allow the game to show results of an action mid-completion of the effect, the Preamble signal can be emitted at some point during the effect.
FxGroup scene files should live in the content/fx_groups/ directory. Subfolders can be created at the developer's discretion.
Timing of an FxGroup
[edit | edit source]
Start
[edit | edit source]The root FxGroup is kicked off by code. It may or may not be awaited; attacks wait for the effect to finish, while terrain destruction just kind of happens in the background.
Start delay & jitter
[edit | edit source]It can wait some amount of time before kicking off its children effects. Jitter will randomly add up to its amount of time in seconds to this delay.
Basic children
[edit | edit source]AnimatedSprite3D, MuzzleFlash, GPUParticle3D, and BumpNodes all count as "basic children". They all kick off at the same time here.
Children FxGroups
[edit | edit source]These have three possible start points:
- Immediate — start at the same time as the rest of the basic children
- Parent Preamble — start whenever the parent fires its Preamble signal.
- Basic Siblings Finished — start when the basic children of its parent finish
Preamble
[edit | edit source]This has four possible points it could be emitted:
- Immediate — effectively no preamble; emits as soon as all the rest of the effects start
- Basic Children Finished — emits when all non-FXG children complete (animations
- Duration — emit after a set time (looks at the "Preamble Duration" value, which no other preamble mode uses)
- At finish — effectively the entire thing is preamble; emits when all children have completed.
When the Preamble is emitted:
- Any children FXGs set to "Parent Preamble" are kicked off.
- Any awaiting game code is resumed so we don't have to wait for the entire FXG to complete before showing results.
For example, the attack event sequence uses the preamble point like this:

- The result of the attack is calculated.
- Attack FXG is started, and the event code halts. (e.g. for the "wind up" to the attack)
- Event code awaits the Preamble to be emitted.
- The result of the attack is shown: miss/hit text, damage popcorn, etc.
- The Target FXG also begins playing, even though the post-preamble of the attack FXG is still playing at the same time.
- The event code waits for the Target FXG to emit its preamble.
- Game proceeds apace, allowing for the dice rolls and stuff to happen while the Target FXG is still finishing up.
Other abilities may also await for/respond to a Preamble signal separately from the completion of the entire FxGroup, but since they're less standardized it's case-by-case. Only the root FxGroup's preamble affects outside code like this; children FxGroup preambles are only used for internal timings.
Complete
[edit | edit source]An FxGroup marks itself as complete when both all basic effects children (including sounds) and all FxGroup children have marked themselves as complete.
Useful FXG sub-nodes
[edit | edit source]SfxEmitter
[edit | edit source]Plays a sound effect event set up in FMOD. Variations and timing are set up there. You shouldn't need to set any values on these nodes besides which event to play. This does not count as a "basic child", so the FXG will not await this sound completing for the animations.
GPUParticles3D
[edit | edit source]Particle emitters! This is a whole thing that might be a bit much to make a written guide on. The important values to set for these are:
- the Time dropdown (lifetime, explosiveness)
- creating a new Process Material (emission position and particle movement) with Animation Speed = 1 if you want a spritesheet.
- Draw Passes > New Quadmesh for Pass 1 > New StandardMaterial3D with the static sprite/horizontal single-strip spritesheet in question.
Since particle emitters don't have a reliable "run for this long" mechanism, the length of time particle emitters run for is set by Emitter Duration on the parent FxGroup node. The emitter will run for that duration then hang out for an extra particle's lifetime before declaring itself finished.
There is also a custom node called GpuParticles3DPointing that is identical to the basic particles node but it gets angled towards the target of the fx (or the origin, if on the target). Basically a muzzle flare but for particles.
BumpNodes / BumpCores
[edit | edit source]
BumpNodes directly move or flash mech sprites. BumpCores exist so they can be passed around as resources via code; just create a new one for each BumpNode when creating these via the editor.
You should set up the FXG so only one of these are active at a time; chaining them together is fine, but they'll likely conflict if you have two running at once on the same mech.
The direction of the bump will be provided by the code that calls this. For attacks, this will be the angle from the attacker to the target; to get the attacker to recoil backwards, for example, you'd want to set Angle Offset to 180.
There's currently a default Hit Bump that plays when a mech gets damaged, so don't worry about adding that to each target. I think that default will eventually be superseded by FXGs specific to each damage type in the future.
- angle_random — Check to ignore Angle Offset and pick a random direction each time get_angle_offset() is called
- angle offset — direction of the bump in DEGREES (offsets the base_angle given to the BumpNode)
- repeats — 1 is one-shot
- distance — how far in world coords to bump them (1.0 = one entire tile)
- duration out — time to the extent of the bump to the extent
- duration in — time from the extent of the bump to return to baseline
- hold — delay at max before returning to baseline
- pause — delay at baseline before starting the next round
- smooth — do we pop them to the end point or tween them there
- flash color — when bumping back, tweens albedo to this color. (1,1,1) is normal, (4,4,4) is a reasonable flash to white.
Muzzle Flash
[edit | edit source]
Extends AnimatedSprite3D for some extra common functionality. This will position itself to:
- be on a plane parallel to the ground
- be on a ring centered on the mech of the given diameter, pointing outwards
It will also run the given animation for the given repeats before automatically stopping & marking itself as finished.
If you give it additional sprite frames in its alternate_sprite_frames property, it will randomly shuffle sprite frames after finishing each animation loop (you could have it weigh certain possibilities more heavily by adding them to the array multiple times). The total pool of possible spriteframes is this array + its original sprite_frames.
You can give a muzzle flash a GPUParticles3D as a child and it will run those particles as one-shots, re-enabling the emitter at the end of each animation loop. You probably want high explosiveness for the emitter to emit a bunch, but be careful to not toggle it back on again before those original particles are gone or no new ones will spawn.
AnimatedSprite3D / SpriteFrames
[edit | edit source]Note: the stock game has moved away from using AnimatedSprite3D nodes, generally opting instead to use a genuine particle system. However, the machinery for these are still in place.
AnimatedSprite3D is one-shot an out-of-the-box Godot node that will animate a SpriteFrames resource. When the FXG starts, it will cause the AnimatedSprite3D to:
- run its SpriteFrames from the start of the animation
- run the animation a single time before stopping & marking itself as finished.
- fade in from transparency at start and fade out on finish if the parent FXGroup has Animated Sprite Fade Time set.
FXGs will automatically set the following values on animated sprites, in order to keep things consistent:
- billboard: enabled
- double_sided: disabled
- texture_filter: nearest w/ mipmaps
- render_priority: 1
SpriteFrames
[edit | edit source]SpriteFrame resources are created from the FileSystem panel and live next to the spritesheet image asset. They define how a spritesheet should be sliced up into an animation, and are shared across all FXGs that might want to use an AnimatedSprite3D with this animation.
To make a new one, right-click near the spritesheet > Create new > Resource > SpriteFrames, and name it the same thing as the spritesheet png. Double-click the new SpriteFrames file to open up the SpriteFrames editor from the bottom of the screen.
There's a little grid icon underneath the Animation Frames label that you can press to go and open up the spritesheet and set the size an ordering of the of the frames. You may also want to set the FPS of the animations here.
After that, you can use this SpriteFrames resource in any AnimatedSprite3D node!
Launched Projectile
[edit | edit source]todo: write docs
Arcing Projectile
[edit | edit source]todo: write docs
Arcing Sprite
[edit | edit source]todo: write docs
Rotating Mesh
[edit | edit source]It spins by some speed and direction endlessly.
Controlled Light & Controlled Decal
[edit | edit source]todo: touch grass