An Fx autoload + one_shot_effect base so every effect is an inspector-editable .tscn (the systems/fx/ authoring dir): blood/slam/spark/flash primitives and the bull's kick/dash/slam/roll + movement effects (bull_*.tscn), fired via Fx.spawn() / Fx.attach(). Plus a preview gallery + smoke test, and bull_impact_fx.gd for the coded, non-particle slam rings + kick flash-pop. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CCyaJPTHCH9EDthpf4A5Sj
5.0 KiB
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) # one-shot: fire and forget (self-frees)
Fx.spawn(&"slam_dust", Transform3D(Basis(), point)) # at a world point
var trail := Fx.attach(&"bull_charge_trail", node) # continuous: caller keeps it + toggles .emitting
Siim's workflow
- 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. - Pick an effect
.tscninfx/(blood_burst,slam_dust,spark,hit_flash) and open it. - Tune it in the inspector. Everything lives on the
CPUParticles3Dnode 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.
- 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.
Bull ability effects
The bull's moves are wired to effect scenes here, so you can retune every one in the inspector —
open the .tscn, drag its colour ramp / curves / emission, save. No code.
| Ability | Effect scene(s) | Kind |
|---|---|---|
| Ground slam | bull_slam.tscn (dust) |
one-shot burst |
| Back-kick | bull_kick.tscn — dust + its stones and sparks child emitters |
one-shot burst |
| Dash / roll launch | bull_dash.tscn |
one-shot burst |
| Hoof dust (walking / sprinting) | bull_hoof_dust.tscn |
continuous |
| Charge trail (the blue streak) | bull_charge_trail.tscn |
continuous |
| Roll sparks | bull_roll_sparks.tscn |
continuous |
Two kinds, edited the same way. One-shot effects fire once and clean themselves up — they show
up in the gallery, so preview and tune them there. Continuous effects follow the bull and switch on
and off with what it's doing (dust while moving, the trail during a roll); the gallery can't show
those, so preview one by opening its .tscn and ticking Emitting on in the inspector's viewport.
Two things stay in code and aren't yours to tune here: the slam's expanding shockwave rings and the
kick's white flash-pop — those are stretched flat meshes, not particles (actors/player/bull_impact_fx.gd).
The dust's walk-vs-sprint size is also code (a fixed multiplier); its colour and shape are the .tscn.
Composite effect (like the kick): one scene, several CPUParticles3D — a root plus child emitters.
one_shot_effect.gd fires every emitter in the scene together, so you can build a layered hit
(dust + debris + sparks) as one file and tune each layer separately.
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() (one-shot) / attach() (continuous); name→path registry |
one_shot_effect.gd |
Root helper: fires every emitter in the scene once, frees it when done |
blood_burst.tscn etc. |
The effects themselves — edit these |
bull_*.tscn |
The bull's ability effects (see the table above) — 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 |