extends "res://ui/menus/ModalMenu.gd" signal crew_requested(vessel_type: String) signal store_requested(vessel_type: String) const VESSEL_DEFINITIONS = preload("res://vessels/VesselDefinitions.gd") const RULE_COLOR := Color(0.45, 0.9, 0.55) const COLUMNS := 3 const LABEL_GAP := 2.0 const DIVIDER_GAP := 10.0 const CAPTION_LINES := 3.0 const CAPTION_MIN := 13 const CAPTION_MAX := 22 const LINE_RATIO := 1.25 @onready var status: Label = $StatusLabel @onready var available_title: Label = $AvailableTitle @onready var fleet_title: Label = $FleetTitle @onready var available_slots: Array = [$AvailableInterceptor, $AvailableShield, $AvailableGasBomber, $AvailableCarrier, $AvailableLaser, $AvailableDistorder] @onready var available_labels: Array = [$AvailableInterceptorLabel, $AvailableShieldLabel, $AvailableGasBomberLabel, $AvailableCarrierLabel, $AvailableLaserLabel, $AvailableDistorderLabel] @onready var fleet_slots: Array = [$FleetInterceptor, $FleetShield, $FleetGasBomber, $FleetCarrier, $FleetLaser, $FleetDistorder] @onready var fleet_labels: Array = [$FleetInterceptorLabel, $FleetShieldLabel, $FleetGasBomberLabel, $FleetCarrierLabel, $FleetLaserLabel, $FleetDistorderLabel] var divider_y: float = 0.0 func _ready() -> void: super._ready() for i in range(available_slots.size()): available_slots[i].pressed.connect( func(): crew_requested.emit(_vessel_types()[i])) fleet_slots[i].pressed.connect( func(): store_requested.emit(_vessel_types()[i])) _layout_sections() func open_for(fleet: Node) -> void: status.text = "" open_menu() refresh(fleet) func set_status(message: String) -> void: status.text = message func refresh(fleet: Node) -> void: var types: Array = _vessel_types() for i in range(mini(types.size(), available_slots.size())): var vessel_type: String = types[i] var definition: Resource = VESSEL_DEFINITIONS.get_definition(vessel_type) var available: int = GameState.stored_vessels.count(vessel_type) var deployed: int = 0 for ship in fleet.ships: if is_instance_valid(ship) and String(ship.vessel_type) == vessel_type: deployed += 1 available_labels[i].text = "%s\n%d available" % [definition.display_name, available] fleet_labels[i].text = "%s\n%d in fleet" % [definition.display_name, deployed] for slot in [available_slots[i], fleet_slots[i]]: slot.icon = definition.icon slot.glow_color = definition.glow_color available_slots[i].enabled = available > 0 \ and fleet.ships.size() < GameState.max_fleet_size() fleet_slots[i].enabled = deployed > 0 and fleet.ships.size() > 1 available_slots[i].queue_redraw() fleet_slots[i].queue_redraw() func _vessel_types() -> Array: var types: Array = [] for definition in VESSEL_DEFINITIONS.fleet(): types.append(String(definition.definition_id)) return types func _layout_sections() -> void: var count: int = available_slots.size() if count == 0: return var columns: int = mini(COLUMNS, count) var rows: int = int(ceil(float(count) / float(columns))) var top: float = available_title.position.y + available_title.size.y + 8.0 var bottom: float = status.position.y - 12.0 var title_height: float = fleet_title.size.y var section_height: float = (bottom - top - title_height - 16.0) * 0.5 if section_height <= 0.0: return var cell_width: float = size.x / float(columns) var cell_height: float = section_height / float(rows) var slot_size: float = minf(cell_height * 0.46, cell_width * 0.40) var label_height: float = maxf(cell_height - slot_size - LABEL_GAP * 2.0, 1.0) _layout_section(available_slots, available_labels, top, columns, cell_width, cell_height, slot_size, label_height) var available_bottom: float = top + section_height divider_y = available_bottom + DIVIDER_GAP fleet_title.position.y = divider_y + DIVIDER_GAP var fleet_top: float = fleet_title.position.y + title_height + 8.0 _layout_section(fleet_slots, fleet_labels, fleet_top, columns, cell_width, cell_height, slot_size, label_height) queue_redraw() func _layout_section(slots: Array, labels: Array, top: float, columns: int, cell_width: float, cell_height: float, slot_size: float, label_height: float) -> void: if columns <= 0: return for i in range(slots.size()): var column: int = i % columns var row: int = i / columns var cell_x: float = float(column) * cell_width var cell_y: float = top + float(row) * cell_height slots[i].position = Vector2(cell_x + (cell_width - slot_size) * 0.5, cell_y) slots[i].size = Vector2(slot_size, slot_size) labels[i].position = Vector2(cell_x, cell_y + slot_size + LABEL_GAP) labels[i].size = Vector2(cell_width, label_height) labels[i].horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER labels[i].vertical_alignment = VERTICAL_ALIGNMENT_TOP labels[i].autowrap_mode = TextServer.AUTOWRAP_WORD_SMART labels[i].add_theme_font_size_override("font_size", caption_size(label_height)) labels[i].clip_text = true func caption_size(label_height: float) -> int: return clampi(int(label_height / (CAPTION_LINES * LINE_RATIO)), CAPTION_MIN, CAPTION_MAX) func _draw() -> void: if divider_y <= 0.0: return NeonDraw.draw_glowing_line(self, Vector2(24.0, divider_y), Vector2(size.x - 24.0, divider_y), RULE_COLOR, 0.5, 0.4)