fc4fc59a2b
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.
89 lines
1.9 KiB
GDScript
89 lines
1.9 KiB
GDScript
extends CanvasLayer
|
|
## Between-rooms layer: node fork (CARD vs SCRAP), card draft (3
|
|
## options + scrap decline — canon pick anatomy, compressed), and the
|
|
## run tally. Pauses the world while active; runs ALWAYS so it can
|
|
## read input. Number keys 1-4 select. Greybox dev UI — draw calls
|
|
## and letters, no art.
|
|
|
|
signal fork_chosen(kind: String)
|
|
signal draft_chosen(card_id: int)
|
|
signal restart_requested
|
|
|
|
const MODE_NONE := ""
|
|
const MODE_FORK := "fork"
|
|
const MODE_DRAFT := "draft"
|
|
const MODE_TALLY := "tally"
|
|
|
|
@export var fork_scrap_reward := 8
|
|
@export var draft_decline_scrap := 4
|
|
|
|
var mode := MODE_NONE
|
|
var active := false
|
|
var draft_options: Array[int] = []
|
|
var tally_stats := {}
|
|
var tally_failed := false
|
|
|
|
|
|
func _ready() -> void:
|
|
add_to_group("interstitial")
|
|
process_mode = Node.PROCESS_MODE_ALWAYS
|
|
layer = 3
|
|
visible = false
|
|
|
|
|
|
func open_fork() -> void:
|
|
_open(MODE_FORK)
|
|
|
|
|
|
func open_draft(options: Array[int]) -> void:
|
|
draft_options = options
|
|
_open(MODE_DRAFT)
|
|
|
|
|
|
func open_tally(stats: Dictionary, failed: bool) -> void:
|
|
tally_stats = stats
|
|
tally_failed = failed
|
|
_open(MODE_TALLY)
|
|
|
|
|
|
func close() -> void:
|
|
mode = MODE_NONE
|
|
active = false
|
|
visible = false
|
|
get_tree().paused = false
|
|
|
|
|
|
func _open(m: String) -> void:
|
|
mode = m
|
|
active = true
|
|
visible = true
|
|
get_tree().paused = true
|
|
$HUD.queue_redraw()
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
if not active:
|
|
return
|
|
$HUD.queue_redraw()
|
|
match mode:
|
|
MODE_FORK:
|
|
if Input.is_action_just_pressed("opt_1"):
|
|
close()
|
|
fork_chosen.emit("card")
|
|
elif Input.is_action_just_pressed("opt_2"):
|
|
close()
|
|
fork_chosen.emit("scrap")
|
|
MODE_DRAFT:
|
|
for i in draft_options.size():
|
|
if Input.is_action_just_pressed("opt_%d" % (i + 1)):
|
|
close()
|
|
draft_chosen.emit(draft_options[i])
|
|
return
|
|
if Input.is_action_just_pressed("opt_4"):
|
|
close()
|
|
draft_chosen.emit(-1)
|
|
MODE_TALLY:
|
|
if Input.is_action_just_pressed("opt_1"):
|
|
close()
|
|
restart_requested.emit()
|