feat: KINETIC+HEAT chemistry row + self-heating burster — greybox build complete

Chemistry row *Spread* (canon CONCEPT.md § tag grammar): a heated
enemy slammed into another (knockback impact >= threshold, not a
walking bump) spreads its heat on contact and passes momentum, so
chains cascade with decaying force — chemistry feeding chemistry.
Authorship-loud feedback stack per canon: ~80ms hitstop (owned by the
hand, capped so chain procs can't lock the world; rides on top of
freeze/thaw states), the two tag hues meeting at the point of impact
(oriented fx, no proc text), and a per-pair audio sting (procedural
placeholder, _ph-marked per asset policy).

Burster: second enemy type, HEAT-tagged walking bomb (orange base,
literal tag mirror) — self-heats ~0.5/s toward threshold, big
detonation. Every 4th spawn. Detonations are now symmetric: they
damage enemies AND the mech in radius (one grammar on both sides;
heat play prices standing close). Grunt scene exports drive both
enemy types — no subclass.

Smoke gate extended: burster self-heat observed (retry-tolerant),
deterministic staged chemistry proc (heated striker slammed into cold
neighbor outside weapon range -> proc counter, heat spread). 3/3
green on nh3-dev headless 4.7.1. Known cosmetic: 2 ObjectDB instances
reported leaked at exit (constant, exit-order artifact — audio stream
alive at quit), not a runtime leak.
This commit is contained in:
vh
2026-08-07 11:47:21 -07:00
parent 3d2410c8fd
commit 1976149ce5
14 changed files with 233 additions and 17 deletions
Binary file not shown.
@@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://c6t7uwmnlqaup"
path="res://.godot/imported/chem_sting_kinetic_heat_ph.wav-8ea5181b52abc6efbaead61e1d2c7753.sample"
[deps]
source_file="res://assets/audio/chem_sting_kinetic_heat_ph.wav"
dest_files=["res://.godot/imported/chem_sting_kinetic_heat_ph.wav-8ea5181b52abc6efbaead61e1d2c7753.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=2