Improve ship lab upgrade selection

This commit is contained in:
Loïc Wisniewski 2026-08-13 16:45:08 +02:00
commit 8219893cda
3 changed files with 208 additions and 29 deletions

View file

@ -35,12 +35,18 @@ extends Node2D
get_node("../UI/LabMenu/VesselC"),
]
@onready var lab_vessel_label: Label = get_node("../UI/LabMenu/VesselLabel")
@onready var lab_list: Label = get_node("../UI/LabMenu/UpgradeList")
@onready var lab_detail: Label = get_node("../UI/LabMenu/DetailLabel")
@onready var lab_status: Label = get_node("../UI/LabMenu/StatusLabel")
@onready var lab_next_button: IconButton = get_node("../UI/LabMenu/NextButton")
@onready var lab_buy_button: IconButton = get_node("../UI/LabMenu/BuyButton")
@onready var lab_close_button: IconButton = get_node("../UI/LabMenu/CloseButton")
@onready var lab_upgrade_buttons: Array = [
get_node("../UI/LabMenu/Upgrade0"), get_node("../UI/LabMenu/Upgrade1"),
get_node("../UI/LabMenu/Upgrade2"), get_node("../UI/LabMenu/Upgrade3"),
]
@onready var lab_upgrade_labels: Array = [
get_node("../UI/LabMenu/Upgrade0Label"), get_node("../UI/LabMenu/Upgrade1Label"),
get_node("../UI/LabMenu/Upgrade2Label"), get_node("../UI/LabMenu/Upgrade3Label"),
]
@onready var craft_shield_button: IconButton = get_node("../UI/CraftMenu/ShieldButton")
@onready var queue_slots: Array = [
get_node("../UI/CraftMenu/QueueSlot0"), get_node("../UI/CraftMenu/QueueSlot1"),
@ -86,10 +92,9 @@ extends Node2D
get_node("../UI/BuildMenu/ShipLabLabel"), get_node("../UI/BuildMenu/ShipLabCost")],
]
# Which vessel the lab screen is showing, and which of its upgrades is
# selected. The screen steps through one upgrade at a time rather than
# listing tappable rows: on a phone a row of small hit targets is worse than
# one big Buy button and a Next.
# Which vessel the lab screen is showing, and which visible upgrade card is
# selected. Each vessel gets its own small set of direct cards; the detail and
# Buy controls below them only describe the one the player tapped.
var lab_vessel: String = GameState.VESSEL_INTERCEPTOR
var lab_choice: int = 0
@onready var planet_field: Node2D = get_node("../PlanetField")
@ -217,10 +222,11 @@ func _ready() -> void:
build_lab_button.pressed.connect(_on_place_ship_lab)
craft_shield_button.pressed.connect(_on_craft_shield)
lab_close_button.pressed.connect(func(): lab_menu.visible = false)
lab_next_button.pressed.connect(_on_lab_next)
lab_buy_button.pressed.connect(_on_lab_buy)
for i in range(lab_vessel_buttons.size()):
lab_vessel_buttons[i].pressed.connect(_on_lab_vessel.bind(i))
for i in range(lab_upgrade_buttons.size()):
lab_upgrade_buttons[i].pressed.connect(_on_lab_upgrade.bind(i))
info_close_button.pressed.connect(_close_info)
info_build_button.pressed.connect(_confirm_build)
@ -787,6 +793,7 @@ func _lab_options() -> Array:
options.append({"unlock": true, "name": "Unlock Shield Vessel",
"desc": "Lets the ship crafter build shield vessels. Its shield absorbs one lethal hit, then cycles back up.",
"cost": GameState.UNLOCK_SHIELD_COST})
return options
for u in GameState.upgrades_for(lab_vessel):
options.append({"unlock": false, "id": u.id, "name": u.name, "desc": u.desc})
return options
@ -799,11 +806,11 @@ func _on_lab_vessel(index: int) -> void:
_refresh_lab()
func _on_lab_next() -> void:
var options: Array = _lab_options()
if options.is_empty():
func _on_lab_upgrade(index: int) -> void:
if index < 0 or index >= _lab_options().size():
return
lab_choice = (lab_choice + 1) % options.size()
lab_choice = index
lab_status.text = ""
_refresh_lab()
@ -838,33 +845,37 @@ func _refresh_lab() -> void:
for i in range(lab_vessel_buttons.size()):
var this_vessel: String = [GameState.VESSEL_INTERCEPTOR, GameState.VESSEL_SHIELD,
GameState.VESSEL_TRANSPORTER][i]
lab_vessel_buttons[i].enabled = this_vessel != lab_vessel
lab_vessel_buttons[i].enabled = true
lab_vessel_buttons[i].glow_color = Color(0.45, 0.9, 0.55) if this_vessel == lab_vessel \
else _vessel_colour(this_vessel)
lab_vessel_buttons[i].queue_redraw()
lab_vessel_label.text = GameState.VESSEL_NAMES.get(lab_vessel, lab_vessel)
lab_vessel_label.text = "%s research" % GameState.VESSEL_NAMES.get(lab_vessel, lab_vessel)
var options: Array = _lab_options()
for i in range(lab_upgrade_buttons.size()):
var visible: bool = i < options.size()
lab_upgrade_buttons[i].visible = visible
lab_upgrade_labels[i].visible = visible
if not visible:
continue
var option: Dictionary = options[i]
var price_text: String = "%d ore" % (GameState.UNLOCK_SHIELD_COST if bool(option.unlock) else GameState.upgrade_cost(option.id))
if not bool(option.unlock) and GameState.upgrade_maxed(option.id):
price_text = "MAX"
var level_note: String = "" if bool(option.unlock) else " %d/%d" % [
GameState.upgrade_level(option.id), int(GameState.upgrade_def(option.id).max_level)]
lab_upgrade_labels[i].text = "%s%s\n%s" % [option.name, level_note, price_text]
lab_upgrade_buttons[i].icon = IconButton.Icon.SHIP_LAB
lab_upgrade_buttons[i].glow_color = Color(1.0, 0.85, 0.4) if i == lab_choice else _vessel_colour(lab_vessel)
lab_upgrade_buttons[i].enabled = true
lab_upgrade_buttons[i].queue_redraw()
if options.is_empty():
lab_list.text = ""
lab_detail.text = ""
lab_buy_button.enabled = false
lab_buy_button.queue_redraw()
return
lab_choice = clampi(lab_choice, 0, options.size() - 1)
# The whole page at a glance, with the selected line marked - so the
# player can see what else is there without stepping through it.
var lines: Array = []
for i in range(options.size()):
var o: Dictionary = options[i]
var marker: String = ">" if i == lab_choice else " "
if o.unlock:
lines.append("%s %s %d ore" % [marker, o.name, GameState.UNLOCK_SHIELD_COST])
else:
var lvl: int = GameState.upgrade_level(o.id)
var max_lvl: int = int(GameState.upgrade_def(o.id).max_level)
var price: String = "MAX" if GameState.upgrade_maxed(o.id) else "%d ore" % GameState.upgrade_cost(o.id)
lines.append("%s %s %d/%d %s" % [marker, o.name, lvl, max_lvl, price])
lab_list.text = "\n".join(lines)
var choice: Dictionary = options[lab_choice]
lab_detail.text = "%s\n%s" % [choice.name, choice.desc]
if choice.unlock: