Files
urm03/scripts/arena.gd
T
vh 1976149ce5 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.
2026-08-07 11:47:21 -07:00

51 lines
1.5 KiB
GDScript

extends Node2D
## One greybox arena, one screen (640x360), fixed camera. Draws its own
## floor and wall slabs; tracks kills and chemistry procs; conducts the
## authorship-loud chemistry feedback stack (canon: brief hitstop + the
## two tag hues meeting at the point of contact + a per-pair sting —
## no proc text, the light and the sting are the noun).
const CHEM_FX := preload("res://scripts/chemistry_fx.gd")
var kills: int = 0
var chem_procs: int = 0
func _ready() -> void:
add_to_group("arena")
$Spawner.grunt_spawned.connect(_on_grunt_spawned)
$Mech.hull_changed.connect(_on_hull_changed)
func chemistry_proc(at: Vector2, axis: Vector2) -> void:
chem_procs += 1
var hand := get_tree().get_first_node_in_group("hand")
if hand != null:
hand.hitstop()
var fx: Node2D = CHEM_FX.new()
fx.position = at
fx.axis = axis
add_child(fx)
$Sting.play()
func _on_grunt_spawned(grunt: Node) -> void:
grunt.died.connect(func() -> void: kills += 1)
func _on_hull_changed(hull: float, hull_max: float) -> void:
$HUD/HullFill.size.x = 118.0 * (hull / hull_max)
func _draw() -> void:
draw_rect(Rect2(0, 0, 640, 360), Color(0.1, 0.11, 0.13))
for x in range(0, 641, 32):
draw_line(Vector2(x, 0), Vector2(x, 360), Color(0.13, 0.145, 0.17))
for y in range(0, 361, 32):
draw_line(Vector2(0, y), Vector2(640, y), Color(0.13, 0.145, 0.17))
var wall := Color(0.3, 0.32, 0.36)
draw_rect(Rect2(0, 0, 640, 16), wall)
draw_rect(Rect2(0, 344, 640, 16), wall)
draw_rect(Rect2(0, 0, 16, 360), wall)
draw_rect(Rect2(624, 0, 16, 360), wall)