extends Control signal closed const UI := preload("res://scripts/planets/expedition_ui.gd") const MENU := preload("res://scripts/planets/freighter_menu.gd") const GEAR := preload("res://scripts/planets/captain_equipment.gd") const RECIPES := preload("res://scripts/items/crafting_recipes.gd") const CATALOG := preload("res://scripts/game/ship_catalog.gd") var captain: Resource var inventory: Node var _content: VBoxContainer var _tab := "overview" var _drawer: PanelContainer var _drawer_title: Label var _wallet: Label var _hint: Label var _owned_open := false var _storage_columns: GridContainer var _storage_notice := "" @onready var deck: Control = $Deck @onready var _audio: Node = $FreighterAudio func _ready() -> void: if captain == null: captain = GameState.captain deck.sync_rooms(captain.expedition.freighter_rooms) deck.section_selected.connect(_select_section) deck.section_hovered.connect(_hover_section) var chassis := CATALOG.for_path(GameState.selected_ship_path) deck.ship_name = str(chassis.name) var sprite: Sprite2D if is_instance_valid(inventory): var ship: Node = inventory.get_parent() sprite = ship.get_node_or_null("Sprite2D") as Sprite2D deck.ship_texture = sprite.texture if sprite != null else load(CATALOG.texture_path(chassis)) if sprite != null: deck.ship_name = str(CATALOG.for_path(sprite.texture.resource_path).name) _build_header() _build_footer() _build_drawer() resized.connect(_layout) captain.changed.connect(_sync_header) _sync_header() _layout() _refresh() func _build_header() -> void: var header := HBoxContainer.new() header.name = "Header" header.set_anchors_and_offsets_preset(Control.PRESET_TOP_WIDE) header.offset_left = 26 header.offset_right = -26 header.offset_top = 20 header.add_theme_constant_override("separation",22) add_child(header) var heading := VBoxContainer.new() heading.size_flags_horizontal = Control.SIZE_EXPAND_FILL header.add_child(heading) MENU.label(heading,"FREGATA / POKŁAD OPERACYJNY",24,Color("e3e9e8")) MENU.label(heading,"01 / POKŁAD GŁÓWNY · POŁĄCZENIE ZABEZPIECZONE",11,Color("77969f")) _wallet = MENU.label(header,"",13,Color("c9aa7c")) _wallet.custom_minimum_size.x = 150 _wallet.vertical_alignment = VERTICAL_ALIGNMENT_CENTER var storage_button := MENU.button(header,"MAGAZYN",func(): _select_section("storage")) storage_button.custom_minimum_size.x = 100 storage_button.size_flags_vertical = Control.SIZE_SHRINK_CENTER var leave := MENU.button(header,"ODLOT [L]",func(): closed.emit()) leave.custom_minimum_size.x = 110 leave.size_flags_vertical = Control.SIZE_SHRINK_CENTER func _build_footer() -> void: var footer := HBoxContainer.new() footer.name = "Footer" footer.set_anchors_and_offsets_preset(Control.PRESET_BOTTOM_WIDE) footer.offset_left = 26 footer.offset_right = -26 footer.offset_top = -43 footer.offset_bottom = -12 add_child(footer) _hint = MENU.label(footer,"Wybierz pomieszczenie na pokładzie. · Warsztat i hangar są dostępne.",12,Color("91a9ae")) _hint.size_flags_horizontal = Control.SIZE_EXPAND_FILL footer.add_theme_constant_override("separation",18) MENU.label(footer,"● OPERACYJNE",11,Color("79d9d8")).custom_minimum_size.x = 110 MENU.label(footer,"● W REMONCIE",11,Color("bca078")).custom_minimum_size.x = 110 func _build_drawer() -> void: _drawer = UI.panel(self) _drawer.name = "SectionPanel" MENU.style(_drawer) var stack := VBoxContainer.new() stack.add_theme_constant_override("separation",8) _drawer.add_child(stack) var row := HBoxContainer.new() stack.add_child(row) _drawer_title = MENU.label(row,"",18,MENU.GOLD) _drawer_title.size_flags_horizontal = Control.SIZE_EXPAND_FILL MENU.button(row,"×",_close_section).custom_minimum_size.x = 32 var scroll := ScrollContainer.new() scroll.name = "SectionScroll" scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL stack.add_child(scroll) _content = VBoxContainer.new() _content.size_flags_horizontal = Control.SIZE_EXPAND_FILL _content.add_theme_constant_override("separation",8) scroll.add_child(_content) func _layout() -> void: if not is_instance_valid(_drawer): return var viewport_size := size var storage: bool = _tab == "storage" or (_tab == "expansion_3" and deck.is_built(_tab)) var width := minf(700 if storage else (440 if _tab == "hangar" else 490),viewport_size.x-32) var target_height := 420 if _tab == "hangar" else (520 if _tab == "workshop" else (600 if storage else (300 if _tab == "command" else 260))) var height := minf(target_height,maxf(240,viewport_size.y-140)) _drawer.position = Vector2(16 if _tab == "hangar" else viewport_size.x-width-16,maxf(90,(viewport_size.y-height)*0.5)) _drawer.size = Vector2(width,height) if is_instance_valid(_storage_columns): _storage_columns.columns = 2 if width >= 640 else 1 func _sync_header() -> void: if is_instance_valid(_wallet): _wallet.text = "%d KREDYTÓW\n%d CZĘŚCI" % [captain.credits,floori(captain.parts)] func _hover_section(section: String) -> void: var data: Dictionary = deck.room(section) _hint.text = "%s / %s" % [data.title,data.status] if not data.is_empty() else "Wybierz pomieszczenie na pokładzie. · Warsztat i hangar są dostępne." func _select_section(section: String) -> void: var room: Dictionary = deck.room("expansion_3" if section == "storage" else section) var pan: float = 0.0 if room.is_empty() else ((room.rect as Rect2).get_center().x / deck.DESIGN_SIZE.x - 0.5)*1.4 _audio.enter_section(section,pan) _storage_notice = "" _tab = section deck.selected = section _refresh() func _close_section() -> void: _audio.close_section() _tab = "overview" deck.selected = "" _drawer.hide() deck.queue_redraw() func _input(event: InputEvent) -> void: if not event is InputEventKey or not event.pressed or event.echo: return if event.keycode not in [KEY_L,KEY_ESCAPE]: return # Docking removes this scene immediately, so consume input before emitting closed. get_viewport().set_input_as_handled() if event.keycode == KEY_L: closed.emit() elif _drawer.visible: _close_section() else: closed.emit() func _label(text: String, size_value := 14, color := Color("c5d3d7")) -> Label: var node := MENU.label(_content,text,size_value,color) node.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART return node func _refresh() -> void: _storage_columns = null _audio.set_maintenance_needed(captain.expedition.lander_hp < 30) for child in _content.get_children(): _content.remove_child(child) child.queue_free() _sync_header() if _tab == "overview": _drawer.hide() return _drawer.show() _layout() _content.get_parent().set("scroll_vertical",0) if _tab == "workshop": _drawer_title.text = "WARSZTAT" _build_workshop() elif _tab == "hangar": _drawer_title.text = "HANGAR / OBSŁUGA" _build_hangar() elif _tab == "command": _drawer_title.text = "CENTRUM DOWODZENIA" _build_command() elif _tab == "storage" or (_tab == "expansion_3" and deck.is_built(_tab)): _drawer_title.text = "MAGAZYN FRACHTOWCA" _build_storage() else: _build_room() func _build_room() -> void: var section: Dictionary = deck.room(_tab) _drawer_title.text = str(section.get("title","SEKCJA ROZWOJOWA")) if not deck.is_buildable(_tab): _label("Wybierz pomieszczenie na pokładzie.") return var plan: Dictionary = deck.plan(_tab) _label("ZBUDOWANO" if deck.is_built(_tab) else "W REMONCIE",21,UI.CYAN if deck.is_built(_tab) else Color("e0b16a")) _label(str(plan.description)) if str(plan.kind) == "alien_research": _label("Próbki oczekujące na analizę: %d" % captain.expedition.analysis_samples,16,UI.CYAN) _label("Próbki z jaskiń są przechowywane po powrocie. Analiza będzie dostępna później.",13) if deck.is_built(_tab): _label("Pomieszczenie jest wyposażone. Jego mechanika zostanie dodana w kolejnym etapie.",14,Color("849da5")) else: _label("Budowa jest teraz bezpłatna. Wyposażenie pojawi się od razu na pokładzie.",14,Color("849da5")) MENU.button(_content,"ZBUDUJ · BEZ KOSZTÓW",_construct_room.bind(_tab)) MENU.button(_content,"Wróć na pokład",_close_section) func _construct_room(id: String) -> void: if not deck.is_buildable(id) or deck.is_built(id): return captain.expedition.freighter_rooms[id] = str(deck.plan(id).kind) captain.expedition.emit_changed() deck.sync_rooms(captain.expedition.freighter_rooms) _audio.service_completed() _hover_section(id) _refresh() func _build_hangar() -> void: var progress: Resource = captain.expedition MENU.hero(_content,"hangar","") var ship_row := MENU.row(_content) MENU.icon(ship_row,deck.ship_texture,32) var ship_text := VBoxContainer.new() ship_text.size_flags_horizontal = Control.SIZE_EXPAND_FILL ship_row.add_child(ship_text) MENU.label(ship_text,deck.ship_name,15,MENU.GOLD) MENU.label(ship_text,"Żelazo %d · Części %d" % [int(captain.minerals.get("iron",0)),int(captain.parts)],12,MENU.MUTED) var service := MENU.card(_content) MENU.style(service.get_parent(),8,0.70) var row := MENU.row(service) MENU.icon(row,preload("res://assets/planets/lander.png"),34) var info := VBoxContainer.new() info.size_flags_horizontal = Control.SIZE_EXPAND_FILL row.add_child(info) MENU.label(info,"Lądownik · %d%%" % ceili(progress.lander_hp),13,MENU.GOLD) var bar := ProgressBar.new() bar.value = progress.lander_hp bar.show_percentage = false bar.custom_minimum_size.y = 5 var fill := StyleBoxFlat.new() fill.bg_color = Color("85b7a0") fill.set_corner_radius_all(3) bar.add_theme_stylebox_override("fill",fill) info.add_child(bar) var cost: int = progress.repair_cost() var cost_row := MENU.row(info) MENU.icon(cost_row,RECIPES.icon("parts"),14) var repair_cost := MENU.label(cost_row,str(cost),11,MENU.MUTED) repair_cost.name = "RepairCost" repair_cost.autowrap_mode = TextServer.AUTOWRAP_OFF var repair := MENU.button(row,"Napraw",func(): if progress.repair(captain): _audio.service_completed(0.65) _refresh(),true) repair.name = "RepairLander" repair.custom_minimum_size = Vector2(58,26) repair.size_flags_vertical = Control.SIZE_SHRINK_CENTER repair.tooltip_text = "Napraw do 100%% · koszt %d części. Pełny kadłub wymagany do lądowania." % cost repair.disabled = cost == 0 or captain.parts < cost _build_slot_upgrades() var delivery := MENU.card(_content) MENU.style(delivery.get_parent(),8,0.70) var delivery_row := MENU.row(delivery) MENU.icon(delivery_row,preload("res://assets/icons/shield.png"),24) var label := MENU.label(delivery_row,"Odzyskane moduły · %d" % progress.delivered_modules.size(),12,MENU.MUTED) label.size_flags_horizontal = Control.SIZE_EXPAND_FILL var take := MENU.button(delivery_row,"Odbierz",func(): if is_instance_valid(inventory): progress.deliver_modules(inventory) _refresh()) take.name = "CollectRecovered" take.custom_minimum_size = Vector2(58,26) take.tooltip_text = "Odbierz do ładowni statku. Przedmioty bez miejsca pozostają na fregacie." take.disabled = progress.delivered_modules.is_empty() or not is_instance_valid(inventory) func _build_slot_upgrades() -> void: if not is_instance_valid(inventory): _label("Zadokuj statkiem, aby rozbudować sloty.",12,MENU.MUTED) return _label("ROZBUDOWA STATKU",13,MENU.GOLD) var grid := GridContainer.new() grid.columns = 3 grid.add_theme_constant_override("h_separation",6) _content.add_child(grid) for kind in ["cargo","weapon","extension"]: var count: int = inventory.unlocked_cargo_rows if kind == "cargo" else (inventory.unlocked_weapon_slots if kind == "weapon" else inventory.unlocked_extension_slots) var limit: int = inventory.CARGO_ROW_COUNT if kind == "cargo" else (inventory.WEAPON_SLOT_COUNT if kind == "weapon" else inventory.EXTENSION_SLOT_COUNT) var card := MENU.card(grid) MENU.style(card.get_parent(),6,0.70) card.add_theme_constant_override("separation",4) var row := MENU.row(card) row.add_theme_constant_override("separation",5) var icons := {"cargo":"res://assets/icons/cargo_crate.svg","weapon":"res://assets/icons/machine_gun.png","extension":"res://assets/icons/computer.png"} MENU.icon(row,load(icons[kind]),26) var title := VBoxContainer.new() title.size_flags_horizontal = Control.SIZE_EXPAND_FILL row.add_child(title) MENU.label(title,{"cargo":"Ładownia","weapon":"Broń","extension":"Rozszerzenia"}[kind],11,MENU.TEXT) MENU.label(title,"%d / %d" % [count,limit],11,MENU.MUTED) var action := MENU.row(card) action.add_theme_constant_override("separation",4) MENU.icon(action,RECIPES.icon("iron"),14) var price := MENU.label(action,"10",11,MENU.MUTED) price.size_flags_horizontal = Control.SIZE_EXPAND_FILL var unlock := MENU.button(action,"+1" if count < limit else "✓",_unlock_ship_slot.bind(kind),true) unlock.name = "Unlock"+kind.capitalize() unlock.custom_minimum_size = Vector2(30,24) unlock.tooltip_text = "Osiągnięto limit." if count >= limit else "Odblokuj %s · koszt 10 żelaza." % ("rząd ładowni (+5 miejsc)" if kind == "cargo" else "kolejny slot") unlock.disabled = not (inventory.can_unlock_cargo_row(captain) if kind == "cargo" else inventory.can_unlock_slot(kind,captain)) func _unlock_ship_slot(kind: String) -> void: if is_instance_valid(inventory): if kind == "cargo": inventory.unlock_cargo_row(captain) else: inventory.unlock_slot(kind,captain) _refresh() func _build_storage() -> void: MENU.hero(_content,"storage","MAGAZYN / ZASOBY I WYPOSAŻENIE") if not deck.is_built("expansion_3"): _build_resource_overview() var construction := MENU.card(_content) MENU.label(construction,"SKŁAD MODUŁÓW W REMONCIE",15,MENU.GOLD) MENU.button(construction,"ZBUDUJ SKŁAD · BEZ KOSZTÓW",_construct_room.bind("expansion_3"),true) return if not is_instance_valid(inventory): return _label("MODUŁY / Kliknij ikonę, aby przenieść przedmiot",14,MENU.GOLD) if not _storage_notice.is_empty(): _label(_storage_notice,12,MENU.GOLD) _storage_columns = GridContainer.new() _storage_columns.columns = 2 if _drawer.size.x >= 640 else 1 _storage_columns.add_theme_constant_override("h_separation",12) _storage_columns.add_theme_constant_override("v_separation",12) _content.add_child(_storage_columns) for retrieve in [false,true]: var column := VBoxContainer.new() column.size_flags_horizontal = Control.SIZE_EXPAND_FILL column.add_theme_constant_override("separation",6) _storage_columns.add_child(column) var storage: Array = captain.expedition.freighter_storage MENU.label(column,"FREGATA · %d" % storage.size() if retrieve else "STATEK · %d / %d" % [inventory.get_cargo_used(),inventory.get_cargo_capacity()],14,MENU.GOLD) var bulk := MENU.button(column,"← Odbierz wszystko" if retrieve else "Odłóż wszystko →",_transfer_all.bind(retrieve)) bulk.disabled = storage.is_empty() or inventory.get_cargo_used() >= inventory.get_cargo_capacity() if retrieve else inventory.get_cargo_used() == 0 var grid := GridContainer.new() grid.name = "FreighterSlots" if retrieve else "ShipSlots" grid.columns = 5 grid.add_theme_constant_override("h_separation",4) grid.add_theme_constant_override("v_separation",4) column.add_child(grid) var count: int = maxi(20,ceili(storage.size()/5.0)*5) if retrieve else inventory.CARGO_SIZE for index in count: var item: ItemInstance = storage[index] if retrieve and index < storage.size() else (inventory.get_item("cargo",index) if not retrieve else null) var slot := Button.new() slot.set_script(preload("res://scripts/planets/freighter_storage_slot.gd")) slot.item = item slot.retrieve = retrieve slot.locked = not retrieve and index >= inventory.get_cargo_capacity() if item != null: slot.transfer = _transfer_storage.bind(retrieve,index,item) grid.add_child(slot) if retrieve and item != null: slot.disabled = inventory.get_cargo_used() >= inventory.get_cargo_capacity() _label("ZAMONTOWANE NA STATKU",12,MENU.MUTED) var mounted := HFlowContainer.new() _content.add_child(mounted) for group in [inventory.weapon_slots,inventory.module_slots,inventory.extension_slots]: for item in group: if item == null: continue var picture := MENU.icon(mounted,item.definition.icon,32) picture.mouse_filter = Control.MOUSE_FILTER_STOP picture.tooltip_text = item.get_tooltip_text()+"\nZamontowane — najpierw zdejmij do ładowni." _label("SPRZĘT KAPITANA · %d szt. ODZYSKANE MODUŁY · %d" % [captain.gear_items.size(),captain.expedition.delivered_modules.size()],12,MENU.MUTED) var owned := HFlowContainer.new() _content.add_child(owned) for gear in captain.gear_items: var picture := MENU.icon(owned,GEAR.icon(str(gear.kind)),28) picture.mouse_filter = Control.MOUSE_FILTER_STOP picture.tooltip_text = "%s · poziom %d" % [GEAR.NAMES[gear.kind],gear.level] for item in captain.expedition.delivered_modules: var picture := MENU.icon(owned,item.definition.icon,28) picture.mouse_filter = Control.MOUSE_FILTER_STOP picture.tooltip_text = item.get_tooltip_text()+"\nOdbierz w Hangarze." _content.add_child(HSeparator.new()) _build_resource_overview() func _build_resource_overview() -> void: _label("ZAPASY GRACZA",14,MENU.GOLD) var grid := GridContainer.new() grid.name = "ResourceOverview" grid.columns = 4 if _drawer.size.x >= 600 else 3 grid.add_theme_constant_override("h_separation",6) grid.add_theme_constant_override("v_separation",5) _content.add_child(grid) var values: Dictionary = {"credits":captain.credits,"parts":int(captain.parts)} for key in RECIPES.MINERALS+preload("res://scripts/planets/planet_profiles.gd").MATERIALS: values[key] = int(captain.minerals.get(key,0)) for key in captain.minerals: values[key] = int(captain.minerals[key]) if is_instance_valid(inventory): for key in ["ammunition","missile","irradiated_ammunition","energy_bank"]: values[key] = inventory.get_crafted_stock(key) values.samples = captain.expedition.analysis_samples var names: Dictionary = RECIPES.NAMES.duplicate() names.merge(GEAR.MATERIAL_NAMES) names.merge({"credits":"Kredyty","parts":"Części","ammunition":"Amunicja","missile":"Rakiety","irradiated_ammunition":"Radiacyjna","energy_bank":"Powerbanki","samples":"Próbki"}) for key in values: var tile := MENU.card(grid) tile.get_parent().name = "Stock_"+key var row := MENU.row(tile) var path := "res://assets/icons/resources/%s.%s" % [key,"svg" if key in ["credits","energy_bank"] else "png"] if ResourceLoader.exists(path): MENU.icon(row,load(path),22) var labels := VBoxContainer.new() labels.size_flags_horizontal = Control.SIZE_EXPAND_FILL row.add_child(labels) MENU.label(labels,str(names.get(key,key)),11,MENU.MUTED) MENU.label(labels,str(values[key]),13,MENU.GOLD) tile.get_parent().tooltip_text = "%s: %d" % [names.get(key,key),values[key]] func _transfer_all(retrieve: bool) -> void: if not is_instance_valid(inventory): return var count := 0 if retrieve: for index in range(captain.expedition.freighter_storage.size()-1,-1,-1): if inventory.retrieve_from_freighter(index,captain.expedition.freighter_storage[index],captain): count += 1 else: for index in range(inventory.get_cargo_capacity()-1,-1,-1): var item: ItemInstance = inventory.get_item("cargo",index) if item != null and inventory.store_on_freighter(index,item,captain): count += 1 _storage_notice = "Przeniesiono %d przedmiotów." % count _refresh() func _transfer_storage(retrieve: bool, index: int, expected: ItemInstance) -> void: if not is_instance_valid(inventory): return if retrieve: inventory.retrieve_from_freighter(index,expected,captain) else: inventory.store_on_freighter(index,expected,captain) _refresh() func _build_supply_production() -> void: for group in [["AMUNICJA I RAKIETY",["ammunition","missile","irradiated_ammunition"]],["ZAOPATRZENIE",["parts","energy_bank"]]]: _label(group[0],13,MENU.GOLD) var grid := GridContainer.new() grid.columns = 3 grid.add_theme_constant_override("h_separation",6) _content.add_child(grid) for id in group[1]: var recipe: Dictionary = RECIPES.DATA[id] var card := MENU.card(grid) MENU.style(card.get_parent(),6) card.add_theme_constant_override("separation",4) card.get_parent().tooltip_text = recipe.name+" · partia: %d szt." % recipe.amount var row := MENU.row(card) MENU.icon(row,RECIPES.icon(id),28) var stock := MENU.label(row,str(inventory.get_crafted_stock(id) if is_instance_valid(inventory) else 0),13,MENU.GOLD) stock.size_flags_horizontal = Control.SIZE_EXPAND_FILL var actions := MENU.row(card) actions.add_theme_constant_override("separation",4) for batches in [1,10]: var button := MENU.button(actions,"+%d" % batches,_craft_supply.bind(id,batches),true) button.name = ("Craft_" if batches == 1 else "Craft10_")+id button.custom_minimum_size = Vector2(36,24) button.size_flags_horizontal = Control.SIZE_EXPAND_FILL var cost: Dictionary = recipe.cost.duplicate() for key in cost: cost[key] = int(cost[key])*batches button.tooltip_text = "%s: %d partii = %d szt.\nKoszt: %s" % [recipe.name,batches,int(recipe.amount)*batches,UI.material_text(cost)] button.disabled = not _can_craft_supply(id,batches) func _can_craft_supply(id: String, batches: int) -> bool: if not is_instance_valid(inventory) or not RECIPES.DATA.has(id) or batches not in [1,10]: return false for key in RECIPES.DATA[id].cost: if int(captain.minerals.get(key,0)) < int(RECIPES.DATA[id].cost[key])*batches: return false return true func _craft_supply(id: String, batches := 1) -> void: if _tab != "workshop" or not _can_craft_supply(id,batches): return for index in batches: inventory.craft(id) _audio.service_completed(-0.48) _refresh() func _build_workshop() -> void: MENU.hero(_content,"workshop","") _build_supply_production() _label("EKWIPUNEK KAPITANA",13,MENU.GOLD) var grid := GridContainer.new() grid.columns = 3 grid.add_theme_constant_override("h_separation",6) _content.add_child(grid) for kind in GEAR.KINDS: var card := MENU.card(grid) MENU.style(card.get_parent(),6) card.add_theme_constant_override("separation",4) var row := MENU.row(card) MENU.icon(row,GEAR.icon(kind),32) var levels := MENU.label(row,"L%d → L%d" % [GEAR.level(captain,kind),GEAR.next_level(captain,kind)],12,GEAR.COLORS[kind]) levels.size_flags_horizontal = Control.SIZE_EXPAND_FILL var build := MENU.button(row,"+1",_craft.bind(kind),true) build.name = "CraftGear_"+kind build.custom_minimum_size = Vector2(36,24) build.size_flags_vertical = Control.SIZE_SHRINK_CENTER build.tooltip_text = "%s · poziom %d\nKoszt: %s\nWytwarza i zakłada nowy przedmiot." % [GEAR.NAMES[kind],GEAR.next_level(captain,kind),GEAR.recipe_text(captain,kind)] card.get_parent().tooltip_text = build.tooltip_text build.disabled = not GEAR.can_craft(captain,kind) MENU.button(_content,"Posiadane "+("−" if _owned_open else "+"),func(): _owned_open = not _owned_open _refresh()) if _owned_open: for gear in captain.gear_items: var equipped: bool = captain.gear_slots.get(gear.kind,-1) == gear.uid var label_text := "%s · L%d%s" % [GEAR.NAMES[gear.kind],gear.level," [ZAŁOŻONE]" if equipped else ""] var button := MENU.button(_content,label_text,_equip.bind(gear.kind,gear.uid)) button.disabled = equipped func _build_command() -> void: var progress: Resource = captain.expedition _label("MOSTEK / SYSTEMY NAWIGACYJNE",13,Color("8bd9d0")) _label("Łączność z twoim statkiem jest stabilna. Fregata pozostaje gotowa do przejścia do kolejnego układu.") _label("Zeskanowane planety: %d" % progress.scans.size(),16) _label("Próbki do analizy w dziale badań obcych: %d" % progress.analysis_samples,15,UI.CYAN) _label("ODZYSKANE ARCHIWA",15,UI.CYAN) if progress.research_records.is_empty(): _label("Brak odzyskanych zapisów.",13,Color("819ca5")) for key in progress.research_records: _label("%s ×%d" % [key,progress.research_records[key]],13) _label("Rozbudowa centrum dowodzenia oraz pozostałych sekcji będzie dostępna później.",13,Color("bc9e72")) func _craft(kind: String) -> void: if _tab != "workshop": return var gear: Dictionary = GEAR.craft(captain,kind) if not gear.is_empty(): GEAR.equip(captain,kind,int(gear.uid)) _audio.service_completed(-0.48) _refresh() func _equip(kind: String, uid: int) -> void: GEAR.equip(captain,kind,uid) _refresh()