Files
Bullosseum/fx
richard c3f92d8758 Move the FX placeholder seeder into tools/
_seed_placeholders.gd is a one-off generator, not a shipped effect — it belongs
with the other headless tooling (bake_crowd_sheet, preview_*), not in the fx/
runtime dir Siim edits. Rename it to tools/seed_fx_placeholders.gd (matching the
dir's verb_noun convention) and repoint the two doc-comment references.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pq1VX2o1ZfiNRdCjD294wf
2026-09-05 10:52:23 +03:00
..

FX — the effect library

Gameplay code fires a named effect; the scene decides how it looks. That split is the whole point: a programmer writes Fx.spawn(&"blood_burst", hit_transform) once, and from then on every change to how a hit feels is a .tscn Siim edits in the inspector — no code, no recompile.

# anywhere in gameplay code
Fx.spawn(&"blood_burst", global_transform)          # at a node
Fx.spawn(&"slam_dust", Transform3D(Basis(), point)) # at a world point

Siim's workflow

  1. Open the gallery. Run fx/effect_gallery.tscn. It loops through every effect on a sand-lit stage with the effect's name on screen, so you see each one the way it reads in play.
  2. Pick an effect .tscn in fx/ (blood_burst, slam_dust, spark, hit_flash) and open it.
  3. Tune it in the inspector. Everything lives on the CPUParticles3D node and its material:
    • Colour → the node's Color Ramp (start colour → faded/transparent end).
    • Shape of the burst over time → Scale Amount Curve.
    • Amount / Lifetime / Explosiveness / Spread / Velocity / Gravity → the node's emission group.
    • The viewport previews particles live as you drag — no play needed.
  4. Save. That's the whole edit. Re-run the gallery to compare.

New effect? Add a fx/<name>.tscn (root = CPUParticles3D with one_shot_effect.gd attached — copy an existing one), then register its name → path in fx/fx.gd.

House style (keep effects reading as one game)

Palette — pull from these, don't invent per-effect colours:

Role Start End (fades to alpha 0)
Blood #FF0505 #400000
Dust #B89966 (tan) #8C7326
Ember #FFF299 → #FF8C1A transparent
Flash #FFFFFF transparent

Timing budgets — hits read best short: strike/flash effects ≤ 0.4 s, dust/settle ≤ 1.1 s. A one-shot effect frees itself lifetime + 0.5 s after spawn (one_shot_effect.gd), so keep lifetime honest.

PS1 look — materials are unshaded, alpha-blended, vertex-colour (colour comes from the ramp), cull disabled. Prefer few, chunky, low-poly billboarded quads over dense fine particles; the game runs the PS1 filter over everything, so subtlety is lost anyway.

Mobile — effects are CPUParticles3D, never GPUParticles3D. The web/GLES3/ANGLE target compiles particle shaders badly (see the notes in player.gd); CPU particles are just as tunable in the inspector and safe on-device. Keep this constraint when adding effects.

Files

File What it is
fx.gd The Fx autoload — spawn(name, xform, parent=null); name→path registry
one_shot_effect.gd Root helper: fires the emitter(s) once, frees the scene when done
blood_burst.tscn etc. The effects themselves — edit these
effect_gallery.tscn Preview stage (run it to review)
_seed_placeholders.gd One-off generator that wrote the first-draft defaults; not used at runtime