spaceship/ui/menus/StationMenu.gd

110 lines
4 KiB
GDScript3
Raw Normal View History

extends "res://ui/menus/ModalMenu.gd"
# Forgejo #216: transport hubs and spacial workshops used to conjure their own
# crews, free and permanent. The player orders them at a ship crafter now, and
# this is where they say how many they want standing HERE.
#
# The menu edits the ORDER, not the crew - the same split GarrisonPanel makes
# for outposts, and for the same reason: a hub that has asked for three and
# been sent one is waiting, not broken, and has to read that way.
#
# It also answers "how long will these last". Each vessel is spent by the work
# it does, so the bar row below shows what each of them has left, worst first,
# which is the number that decides whether another needs building.
const BAR_WIDTH: float = 54.0
const BAR_HEIGHT: float = 18.0
const BAR_GAP: float = 10.0
const BAR_TOP: float = 470.0
const WORN_COLOR: Color = Color(1.0, 0.35, 0.25)
const FRESH_COLOR: Color = Color(0.5, 1.0, 0.55)
const PLATE_COLOR: Color = Color(0.02, 0.02, 0.06, 0.9)
const FRAME_COLOR: Color = Color(0.85, 0.96, 1.0, 0.85)
@onready var title: Label = $TitleLabel
@onready var assigned_label: Label = $AssignedLabel
@onready var status: Label = $StatusLabel
@onready var condition_label: Label = $ConditionLabel
@onready var less_button: IconButton = $LessButton
@onready var more_button: IconButton = $MoreButton
var building_id: int = 0
func _ready() -> void:
super._ready()
# ModalMenu already owns $CloseButton and wires it.
less_button.pressed.connect(func(): _step(-1))
more_button.pressed.connect(func(): _step(1))
func open_for(next_building_id: int) -> void:
building_id = next_building_id
open_menu()
refresh()
func close_menu() -> void:
super.close_menu()
building_id = 0
func _step(delta: int) -> void:
if building_id == 0:
return
GameState.set_station_desired(building_id,
GameState.station_desired(building_id) + delta)
refresh()
func refresh() -> void:
if building_id == 0:
return
var building: Dictionary = GameState.find_building(building_id)
if building.is_empty():
close_menu()
return
var vessel_type: String = GameState.station_vessel_type(building)
var wanted: int = GameState.station_desired(building_id)
var here: int = GameState.station_crew(building_id)
var capacity: int = GameState.station_capacity(building)
title.text = String(building.get("type", "")).to_upper().replace("_", " ")
assigned_label.text = "%d / %d ASSIGNED (room for %d)" % [here, wanted, capacity]
less_button.enabled = wanted > 0
more_button.enabled = wanted < capacity
var name: String = GameState.vessel_name(vessel_type)
if wanted == 0:
status.text = "None assigned. Build %s at a ship crafter, then ask for them here." % name.to_lower()
elif here >= wanted:
status.text = "Fully crewed. Each one wears out with use and is not replaced by itself."
else:
status.text = "%d on order - sent from the mothership hangar as they are built." % (wanted - here)
var left: Array = GameState.station_condition(building_id)
condition_label.text = "CONDITION" if not left.is_empty() else ""
queue_redraw()
func _draw() -> void:
if building_id == 0:
return
# One bar per vessel standing here, worst first: what is left of the work
# it was built to do. Drawn rather than built from nodes because the count
# changes as vessels arrive and wear out, and a row of bars is cheaper to
# draw than to keep a pool of Controls in step with.
var left: Array = GameState.station_condition(building_id)
if left.is_empty():
return
var full: int = maxi(GameState.station_work_capacity(building_id), 1)
var total: float = float(left.size()) * BAR_WIDTH + float(left.size() - 1) * BAR_GAP
var x: float = (size.x - total) * 0.5
for remaining in left:
var fraction: float = clampf(float(remaining) / float(full), 0.0, 1.0)
draw_rect(Rect2(x - 2.0, BAR_TOP - 2.0, BAR_WIDTH + 4.0, BAR_HEIGHT + 4.0),
PLATE_COLOR)
draw_rect(Rect2(x, BAR_TOP, BAR_WIDTH * fraction, BAR_HEIGHT),
WORN_COLOR.lerp(FRESH_COLOR, fraction))
draw_rect(Rect2(x, BAR_TOP, BAR_WIDTH, BAR_HEIGHT), FRAME_COLOR, false, 1.5)
x += BAR_WIDTH + BAR_GAP