Files
MaidEngine/docs/superpowers/plans/2026-04-01-combat-ui-unit-panel.md
2026-04-01 17:16:58 -04:00

6.5 KiB

Combat UI Unit Panel Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Replace the exit-button CombatUI with a bottom-left panel that shows the selected unit's name and HP.

Architecture: CombatUI listens to the unit_selected_changed signal from units in the "units" group. On selection, it populates a name label and HP progress bar and shows the panel. On deselection, it hides the panel.

Tech Stack: Godot 4.6, GDScript, .tscn scene files


File Structure

File Action Responsibility
prefabs/unit.tscn Modify Add Unit node to "units" group
scripts/combat_ui.gd Create Script that connects to unit signals, shows/hides panel, populates data
prefabs/combat_ui.tscn Modify Remove exit button, add UnitPanel with NameLabel and HPBar, attach new script

Task 1: Add Unit to the "units" group

Files:

  • Modify: prefabs/unit.tscn

  • Step 1: Add the group to the Unit scene

In prefabs/unit.tscn, add a groups property to the root Unit node so every instantiated unit is automatically in the "units" group. Add this line to the root [node name="Unit" ...] block:

groups=["units"]

The full node line becomes:

[node name="Unit" type="Node2D" unique_id=1893234933 groups=["units"]]
  • Step 2: Verify in editor

Open scenes/combat_test.tscn in Godot, run the scene (F5), and use the Remote scene tree to confirm the spawned unit node appears under the "units" group.

  • Step 3: Commit
git add prefabs/unit.tscn
git commit -m "feat: add Unit to 'units' group for discovery"

Task 2: Create combat_ui.gd script

Files:

  • Create: scripts/combat_ui.gd

  • Step 1: Write the script

Create scripts/combat_ui.gd with the following content:

class_name CombatUI extends CanvasLayer

@onready var unit_panel: PanelContainer = %UnitPanel
@onready var name_label: Label = %NameLabel
@onready var hp_bar: ProgressBar = %HPBar

func _ready() -> void:
	unit_panel.visible = false
	for unit: Unit in get_tree().get_nodes_in_group("units"):
		unit.unit_selected_changed.connect(_on_unit_selected_changed)

func _on_unit_selected_changed(unit: Unit, selected: bool) -> void:
	if selected:
		name_label.text = unit.current_info.name
		hp_bar.max_value = unit.current_stats.max_hp
		hp_bar.value = unit.current_stats.current_hp
		unit_panel.visible = true
	else:
		unit_panel.visible = false
  • Step 2: Commit
git add scripts/combat_ui.gd
git commit -m "feat: add CombatUI script for unit info panel"

Task 3: Rebuild combat_ui.tscn

Files:

  • Modify: prefabs/combat_ui.tscn

  • Step 1: Replace the scene file contents

Replace the entire contents of prefabs/combat_ui.tscn with:

[gd_scene format=3 uid="uid://cy7r0udfcsqbn"]

[ext_resource type="Theme" uid="uid://dx26d6py3n8xi" path="res://resources/main_ui_theme.tres" id="1_2ro41"]
[ext_resource type="Script" path="res://scripts/combat_ui.gd" id="2_ui_script"]

[node name="CombatUI" type="CanvasLayer" unique_id=1093388037]
script = ExtResource("2_ui_script")

[node name="UnitPanel" type="PanelContainer" parent="." unique_id=2000000001]
unique_name_in_owner = true
visible = false
anchors_preset = 2
anchor_top = 1.0
anchor_bottom = 1.0
offset_left = 8.0
offset_top = -78.0
offset_right = 208.0
offset_bottom = -8.0
grow_vertical = 0
theme = ExtResource("1_2ro41")

[node name="MarginContainer" type="MarginContainer" parent="UnitPanel"]
layout_mode = 2
theme_override_constants/margin_left = 8
theme_override_constants/margin_top = 8
theme_override_constants/margin_right = 8
theme_override_constants/margin_bottom = 8

[node name="VBoxContainer" type="VBoxContainer" parent="UnitPanel/MarginContainer"]
layout_mode = 2

[node name="NameLabel" type="Label" parent="UnitPanel/MarginContainer/VBoxContainer" unique_id=2000000002]
unique_name_in_owner = true
layout_mode = 2
text = "Unit"

[node name="HPBar" type="ProgressBar" parent="UnitPanel/MarginContainer/VBoxContainer" unique_id=2000000003]
unique_name_in_owner = true
layout_mode = 2
max_value = 100.0
value = 100.0
show_percentage = false

Key changes from the old file:

  • Removed the exit button, its inline GDScript, the VBoxContainer, and the [connection] block.

  • Added the combat_ui.gd script as an ext_resource and attached it to the root node.

  • Added UnitPanel (PanelContainer) anchored to bottom-left with 8px margin from edges, 200px wide, ~70px tall.

  • NameLabel and HPBar are marked with unique_name_in_owner = true so the script can reference them via %NameLabel and %HPBar.

  • UnitPanel is also unique-named for %UnitPanel access.

  • show_percentage = false on HPBar since we just want the bar visual.

  • Step 2: Open in Godot and verify scene tree

Open prefabs/combat_ui.tscn in the Godot editor. Confirm:

  1. No errors in the Scene dock.
  2. The node tree shows: CombatUI > UnitPanel > MarginContainer > VBoxContainer > NameLabel + HPBar.
  3. The UnitPanel is positioned at the bottom-left of the viewport.
  • Step 3: Commit
git add prefabs/combat_ui.tscn
git commit -m "feat: replace exit button with unit info panel in CombatUI"

Task 4: Integration test — verify end-to-end behavior

Files:

  • None (manual verification)

  • Step 1: Run the combat test scene

Run scenes/combat_test.tscn (F5 or F6 from the scene). The test map generator spawns a unit named "Putit" with 50 HP.

  • Step 2: Verify panel is hidden on start

Confirm the bottom-left corner is empty — no panel visible.

  • Step 3: Click the unit to select it

Click the "Putit" unit on the map. Confirm:

  1. The panel appears in the bottom-left corner.
  2. The name label shows "Putit".
  3. The HP bar is full (50/50).
  • Step 4: Click an empty tile to deselect

Click an empty floor tile (this moves the unit, but the unit stays selected). Currently, clicking a different unit would deselect the first — since there's only one test unit, verify that selecting the same unit again keeps the panel visible and data correct.

  • Step 5: Verify exit button is gone

Confirm there is no "Exit" button anywhere in the UI.

  • Step 6: Commit (if any tweaks were needed)
git add -A
git commit -m "fix: adjustments from integration testing"