1976149ce5
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.
51 lines
1.5 KiB
GDScript
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)
|