diff --git a/client/scripts/ui/shell/shell_state.gd b/client/scripts/ui/shell/shell_state.gd new file mode 100644 index 0000000..27caa65 --- /dev/null +++ b/client/scripts/ui/shell/shell_state.gd @@ -0,0 +1,36 @@ +class_name ShellState +extends RefCounted +## The HUD state the Main Window shell owns (§2: state). Seed values mirror mock +## 2a; later systems (combat vitals, inventory consumables) become the writers. +## No Luck/LCK value lives here — it is never surfaced (§7). + +var vitals: Dictionary = {"hp": 0, "hp_max": 0, "mp": 0, "mp_max": 0, "gold": 0} +var turn_order: Array[TurnEntry] = [] +var consumables: Array = [] +var round_label: String = "" +var location_label: String = "" +var dock_open: bool = true + + +func toggle_dock() -> bool: + dock_open = not dock_open + return dock_open + + +static func seed() -> ShellState: + var s := ShellState.new() + s.vitals = {"hp": 42, "hp_max": 60, "mp": 18, "mp_max": 30, "gold": 1240} + s.turn_order = [ + TurnEntry.new("EL", 17, &"you", true, false), + TurnEntry.new("DW", 12, &"ally"), + TurnEntry.new("HU", 9, &"ally"), + TurnEntry.new("GK", 0, &"enemy", false, true), + ] + var labels := ["Salve", "Draught", "Bomb", "Antidote", "Ration", "Torch", "", ""] + s.consumables = [] + for i in range(labels.size()): + s.consumables.append({"hotkey": i + 1, "label": labels[i]}) + s.round_label = "ROUND 4" + s.location_label = "THE LOWER WARD" + s.dock_open = true + return s diff --git a/client/scripts/ui/shell/shell_state.gd.uid b/client/scripts/ui/shell/shell_state.gd.uid new file mode 100644 index 0000000..e57742c --- /dev/null +++ b/client/scripts/ui/shell/shell_state.gd.uid @@ -0,0 +1 @@ +uid://f8vix48wmisv diff --git a/client/scripts/ui/shell/turn_entry.gd b/client/scripts/ui/shell/turn_entry.gd new file mode 100644 index 0000000..df28f45 --- /dev/null +++ b/client/scripts/ui/shell/turn_entry.gd @@ -0,0 +1,20 @@ +class_name TurnEntry +extends RefCounted +## One combatant in the turn-order rail (§2: state). Seed/placeholder now; the +## combat turn manager (M5) becomes its writer. `side` colours the rail: +## &"you" gold, &"ally" teal-muted, &"enemy" blood. + +var initials: String +var initiative: int +var side: StringName +var is_active: bool +var is_downed: bool + + +func _init(p_initials: String, p_initiative: int, p_side: StringName, + p_is_active := false, p_is_downed := false) -> void: + initials = p_initials + initiative = p_initiative + side = p_side + is_active = p_is_active + is_downed = p_is_downed diff --git a/client/scripts/ui/shell/turn_entry.gd.uid b/client/scripts/ui/shell/turn_entry.gd.uid new file mode 100644 index 0000000..311cb23 --- /dev/null +++ b/client/scripts/ui/shell/turn_entry.gd.uid @@ -0,0 +1 @@ +uid://toetic2iu7b8 diff --git a/client/tests/unit/test_shell_state.gd b/client/tests/unit/test_shell_state.gd new file mode 100644 index 0000000..cfea412 --- /dev/null +++ b/client/tests/unit/test_shell_state.gd @@ -0,0 +1,44 @@ +extends "res://addons/gut/test.gd" + + +func test_turn_entry_holds_fields(): + var e := TurnEntry.new("DW", 12, &"ally") + assert_eq(e.initials, "DW") + assert_eq(e.initiative, 12) + assert_eq(e.side, &"ally") + assert_false(e.is_active) + assert_false(e.is_downed) + + +func test_seed_vitals(): + var s := ShellState.seed() + assert_eq(s.vitals["hp"], 42) + assert_eq(s.vitals["hp_max"], 60) + assert_eq(s.vitals["mp"], 18) + assert_eq(s.vitals["mp_max"], 30) + assert_eq(s.vitals["gold"], 1240) + + +func test_seed_turn_order(): + var s := ShellState.seed() + assert_eq(s.turn_order.size(), 4) + assert_eq(s.turn_order[0].initials, "EL") + assert_true(s.turn_order[0].is_active, "first combatant is the active turn") + assert_true(s.turn_order[3].is_downed, "last combatant is downed") + + +func test_seed_consumables(): + var s := ShellState.seed() + assert_eq(s.consumables.size(), 8) + assert_eq(s.consumables[0]["label"], "Salve") + assert_eq(s.consumables[0]["hotkey"], 1) + assert_eq(s.consumables[6]["label"], "", "slot 7 is empty") + + +func test_toggle_dock_flips(): + var s := ShellState.seed() + assert_true(s.dock_open, "seed opens with the dock out") + assert_false(s.toggle_dock()) + assert_false(s.dock_open) + assert_true(s.toggle_dock()) + assert_true(s.dock_open) diff --git a/client/tests/unit/test_shell_state.gd.uid b/client/tests/unit/test_shell_state.gd.uid new file mode 100644 index 0000000..ae91db3 --- /dev/null +++ b/client/tests/unit/test_shell_state.gd.uid @@ -0,0 +1 @@ +uid://wkbpiulrv8rx