extends "res://ui/menus/ModalMenu.gd" signal fleet_add_requested(vessel_type: String) signal fleet_remove_requested(vessel_type: String) signal unlock_skills_requested signal unlimited_resources_requested(enabled: bool) signal wave_requested const ICON_BUTTON = preload("res://ui/IconButton.gd") const VESSEL_DEFINITIONS = preload("res://vessels/VesselDefinitions.gd") const ROW_HEIGHT: float = 86.0 const DESIGN_SIZE := Vector2(720.0, 1280.0) @onready var content: Control = $Content @onready var fleet_summary: Label = $Content/FleetSummary @onready var fleet_rows: VBoxContainer = $Content/FleetRows @onready var unlock_button: IconButton = $Content/ToolButtons/UnlockSkills @onready var unlimited_button: IconButton = $Content/ToolButtons/UnlimitedResources @onready var wave_button: IconButton = $Content/ToolButtons/StartWave @onready var unlimited_label: Label = $Content/ToolLabels/UnlimitedLabel @onready var status: Label = $Content/StatusLabel var fleet: Node = null var row_controls: Dictionary = {} func _ready() -> void: super._ready() $Content/CloseButton.pressed.connect(close_menu) _build_fleet_rows() unlock_button.pressed.connect(func(): unlock_skills_requested.emit()) unlimited_button.pressed.connect(func(): unlimited_resources_requested.emit(not GameState.dev_unlimited_resources)) wave_button.pressed.connect(func(): wave_requested.emit()) _layout_content() func _notification(what: int) -> void: if what == NOTIFICATION_RESIZED and is_node_ready(): _layout_content() func _layout_content() -> void: # The project has a landscape reference viewport but is played in portrait # too. A fixed design canvas keeps touch targets at their authored size and # scales the complete composition uniformly into either shape. var factor: float = minf(size.x / DESIGN_SIZE.x, size.y / DESIGN_SIZE.y) content.scale = Vector2(factor, factor) content.position = (size - DESIGN_SIZE * factor) * 0.5 func open_for(fleet_node: Node) -> void: fleet = fleet_node status.text = "" open_menu() refresh() func set_status(message: String) -> void: status.text = message refresh() func refresh() -> void: if fleet == null or not is_instance_valid(fleet): return var total: int = fleet.ships.size() fleet_summary.text = "CURRENT FLEET %d / %d" % [total, GameState.max_fleet_size()] for definition in VESSEL_DEFINITIONS.fleet(): var vessel_type: String = String(definition.definition_id) var count: int = 0 for ship in fleet.ships: if is_instance_valid(ship) and String(ship.vessel_type) == vessel_type: count += 1 var controls: Dictionary = row_controls.get(vessel_type, {}) if controls.is_empty(): continue (controls.count as Label).text = str(count) (controls.add as IconButton).enabled = total < GameState.max_fleet_size() (controls.remove as IconButton).enabled = count > 0 and total > 1 unlock_button.highlighted = _all_skills_unlocked() unlimited_button.highlighted = GameState.dev_unlimited_resources unlimited_label.text = "UNLIMITED RESOURCES\n%s" \ % ("ON" if GameState.dev_unlimited_resources else "OFF") func _all_skills_unlocked() -> bool: for node in GameState.SKILL_TREE: if not GameState.is_unlocked(String(node.id)): return false return true func _build_fleet_rows() -> void: for definition in VESSEL_DEFINITIONS.fleet(): var vessel_type: String = String(definition.definition_id) var row := HBoxContainer.new() row.custom_minimum_size = Vector2(0.0, ROW_HEIGHT) row.add_theme_constant_override("separation", 12) fleet_rows.add_child(row) var vessel_icon := ICON_BUTTON.new() vessel_icon.custom_minimum_size = Vector2(76.0, 76.0) vessel_icon.mouse_filter = Control.MOUSE_FILTER_IGNORE vessel_icon.icon = int(definition.icon) vessel_icon.glow_color = definition.glow_color row.add_child(vessel_icon) var name_label := Label.new() name_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL name_label.text = String(definition.display_name) name_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER name_label.add_theme_font_size_override("font_size", 25) row.add_child(name_label) var remove_button := ICON_BUTTON.new() remove_button.custom_minimum_size = Vector2(70.0, 70.0) remove_button.icon = IconButton.Icon.MINUS remove_button.glow_color = definition.glow_color remove_button.pressed.connect(_request_remove.bind(vessel_type)) row.add_child(remove_button) var count_label := Label.new() count_label.custom_minimum_size = Vector2(48.0, 0.0) count_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER count_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER count_label.add_theme_font_size_override("font_size", 31) row.add_child(count_label) var add_button := ICON_BUTTON.new() add_button.custom_minimum_size = Vector2(70.0, 70.0) add_button.icon = IconButton.Icon.PLUS add_button.glow_color = definition.glow_color add_button.pressed.connect(_request_add.bind(vessel_type)) row.add_child(add_button) row_controls[vessel_type] = { "count": count_label, "add": add_button, "remove": remove_button, } func _request_add(vessel_type: String) -> void: fleet_add_requested.emit(vessel_type) func _request_remove(vessel_type: String) -> void: fleet_remove_requested.emit(vessel_type)