Files
urm03/scripts/interstitial_hud.gd
vh fc4fc59a2b feat: M2 run skeleton — belt, card draft, node fork, room sequencing, run tally
Belt (canon: charges are the cost, the belt is the ammo): cards are
CARD_TYPES indices consumed on play, next slides into the 2-slot hand;
belt cap 8; HUD shows hand glyphs + upcoming-card ticks. Card pool
grows to 4: SHOCKWAVE, HEATWAVE, DASH (impulse along held movement
direction — aimable while frozen, no aim input), IGNITE (nearest-enemy
heat spike past threshold). Rooms: spawn-budget waves (base 8 +4/room,
4 rooms/run); clear -> interstitial fork (CARD vs SCRAP +8) -> CARD
opens a 3-option draft + scrap decline (+4) -> next room; final clear
or mech destruction -> tally overlay (rooms/kills/scrap/chem) with
relaunch on 1. Interstitial owns the pause while active; the hand
yields input and time authority to it. Mech death now signals the run
manager instead of hard-reloading.

Chain semantics (same-tag surge / cross-tag chemistry trigger)
deliberately deferred to M3.

Smoke gate: belt consumption white-boxed in the card phase, _until
moved to process_frame (physics awaits deadlock under pause), run
phase covers clear->fork->draft->belt growth->room advance->tally.
3/3 green on nh3-dev headless 4.7.1.
2026-08-07 20:30:43 -07:00

54 lines
2.5 KiB
GDScript

extends Control
## Draw layer for the interstitial (fork / draft / tally). Reads the
## parent CanvasLayer's state. Greybox dev UI.
@onready var _layer: CanvasLayer = get_parent()
const KINETIC_HUE := Color(0.75, 0.85, 0.95)
const HEAT_HUE := Color(0.95, 0.55, 0.2)
const SCRAP_HUE := Color(0.95, 0.8, 0.35)
func _draw() -> void:
if not _layer.active:
return
var font := ThemeDB.fallback_font
draw_rect(Rect2(0, 0, 640, 360), Color(0, 0, 0, 0.55))
match _layer.mode:
"fork":
_tile(Rect2(230, 140, 60, 56), Color(0.35, 0.4, 0.45), "1")
draw_rect(Rect2(248, 152, 24, 32), KINETIC_HUE.lerp(HEAT_HUE, 0.5))
_tile(Rect2(350, 140, 60, 56), Color(0.35, 0.4, 0.45), "2")
_diamond(Vector2(380, 166))
draw_string(font, Vector2(372, 186), "+%d" % _layer.fork_scrap_reward, HORIZONTAL_ALIGNMENT_LEFT, -1, 9, Color(0.9, 0.9, 0.9))
"draft":
var hand := get_tree().get_first_node_in_group("hand")
for i in _layer.draft_options.size():
var card: Dictionary = hand.CARD_TYPES[_layer.draft_options[i]]
var r := Rect2(200 + i * 76, 140, 56, 64)
_tile(r, Color(0.3, 0.33, 0.38), str(i + 1))
draw_rect(Rect2(r.position.x + 16, r.position.y + 10, 24, 32), card.hue)
draw_string(font, Vector2(r.position.x + 22, r.position.y + 30), card.glyph, HORIZONTAL_ALIGNMENT_LEFT, -1, 12, Color(0.1, 0.1, 0.12))
_tile(Rect2(200 + 3 * 76, 148, 56, 48), Color(0.3, 0.33, 0.38), "4")
_diamond(Vector2(200 + 3 * 76 + 24, 168))
draw_string(font, Vector2(200 + 3 * 76 + 12, 186), "+%d" % _layer.draft_decline_scrap, HORIZONTAL_ALIGNMENT_LEFT, -1, 9, Color(0.9, 0.9, 0.9))
"tally":
var col := Color(0.75, 0.3, 0.25) if _layer.tally_failed else Color(0.45, 0.7, 0.45)
draw_rect(Rect2(200, 110, 240, 8), col)
var y := 150.0
for key in _layer.tally_stats:
draw_string(font, Vector2(250, y), "%s %s" % [key, str(_layer.tally_stats[key])], HORIZONTAL_ALIGNMENT_LEFT, -1, 11, Color(0.9, 0.9, 0.92))
y += 20.0
draw_string(font, Vector2(250, y + 12), "1 = relaunch", HORIZONTAL_ALIGNMENT_LEFT, -1, 9, Color(0.6, 0.65, 0.7))
func _tile(r: Rect2, c: Color, key_hint: String) -> void:
draw_rect(r, c)
draw_rect(r.grow(1.0), Color(0.9, 0.9, 0.95, 0.5), false, 1.0)
draw_string(ThemeDB.fallback_font, Vector2(r.position.x + 3, r.end.y - 4), key_hint, HORIZONTAL_ALIGNMENT_LEFT, -1, 8, Color(0.95, 0.95, 0.95, 0.8))
func _diamond(at: Vector2) -> void:
var pts := PackedVector2Array([at + Vector2(0, -6), at + Vector2(5, 0), at + Vector2(0, 6), at + Vector2(-5, 0)])
draw_colored_polygon(pts, SCRAP_HUE)