extends "res://scripts/ui/menu_modal.gd" signal load_requested(slot_id: String) signal saved const SHIPS := preload("res://scripts/game/ship_catalog.gd") var save_mode := false var _entries: Array[Dictionary] = [] var _selected_id := "" var _name: LineEdit var _list: VBoxContainer var _summary: Label var _status: Label var _action: Button var _group := ButtonGroup.new() func _ready() -> void: heading = "ZAPISZ WYPRAWĘ" if save_mode else "WCZYTAJ WYPRAWĘ" subtitle = "Nadaj nazwę nowemu zapisowi lub wybierz zapis do nadpisania." if save_mode else "Wybierz zapis i wróć do swojej wyprawy." marker = "ARCHIWUM / DZIENNIK POKŁADOWY" preferred_size = Vector2(900,660) super._ready() if save_mode: var row := HBoxContainer.new() row.add_theme_constant_override("separation",12) body.add_child(row) _name = LineEdit.new() _name.placeholder_text = tr("Nazwa zapisu") _name.max_length = 48 _name.size_flags_horizontal = Control.SIZE_EXPAND_FILL _name.custom_minimum_size.y = 44 input_style(_name) row.add_child(_name) button(row,tr("Nowy zapis"),_new_save) _name.text_changed.connect(func(_text: String) -> void: _update_action()) _name.text_submitted.connect(func(_text: String) -> void: _activate()) var content := HBoxContainer.new() content.add_theme_constant_override("separation",18) body.add_child(content) var left := VBoxContainer.new() left.size_flags_horizontal = Control.SIZE_EXPAND_FILL content.add_child(left) label(left,tr("ZAPISANE WYPRAWY"),11,CYAN) var scroll := ScrollContainer.new() scroll.custom_minimum_size = Vector2(440,270 if save_mode else 340) scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED left.add_child(scroll) _list = VBoxContainer.new() _list.size_flags_horizontal = Control.SIZE_EXPAND_FILL _list.add_theme_constant_override("separation",10) scroll.add_child(_list) var details := PanelContainer.new() details.custom_minimum_size.x = 220 details.add_theme_stylebox_override("panel",box(Color("0e202d"),Color("294653"),16)) content.add_child(details) var info := VBoxContainer.new() info.add_theme_constant_override("separation",16) details.add_child(info) label(info,tr("DANE WYPRAWY"),11,GOLD) _summary = label(info,"",14) _summary.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART var rule_note := label(info,tr("Wczytanie rozpoczyna poziom od początku. Postęp i wyposażenie zostają zachowane."),12,MUTED) rule_note.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART _status = label(body,"",12,GOLD) _status.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART _status.hide() button(footer,tr("Anuluj"),_close) _action = button(footer,tr("Zapisz grę") if save_mode else tr("Wczytaj"),_activate,true) _refresh_list() if save_mode: _new_save() elif not _entries.is_empty(): _select(_entries[0]) _update_action() func _refresh_list() -> void: for child in _list.get_children(): _list.remove_child(child) child.queue_free() _entries = GameState.SAVES.list_saves() for entry in _entries: if save_mode and entry.id == "auto": continue _add_entry(entry) if _list.get_child_count() == 0: var empty := label(_list,tr("Nie ma jeszcze zapisanych wypraw."),14,MUTED) empty.custom_minimum_size = Vector2(400,96) empty.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART func _add_entry(entry: Dictionary) -> void: var card := Button.new() card.toggle_mode = true card.button_group = _group card.custom_minimum_size.y = 88 card.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND style_button(card) card.name = entry.id _list.add_child(card) var row := HBoxContainer.new() row.mouse_filter = Control.MOUSE_FILTER_IGNORE row.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) row.offset_left = 14 row.offset_top = 12 row.offset_right = -14 row.offset_bottom = -12 row.add_theme_constant_override("separation",14) card.add_child(row) var icon := TextureRect.new() icon.texture = load(SHIPS.texture_path(SHIPS.for_path(entry.ship_path))) icon.custom_minimum_size = Vector2(54,54) icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED icon.mouse_filter = Control.MOUSE_FILTER_IGNORE row.add_child(icon) var column := VBoxContainer.new() column.size_flags_horizontal = Control.SIZE_EXPAND_FILL column.mouse_filter = Control.MOUSE_FILTER_IGNORE row.add_child(column) var name_label := label(column,tr(entry.name) if entry.id == "auto" else entry.name,16) name_label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS name_label.mouse_filter = Control.MOUSE_FILTER_IGNORE name_label.auto_translate_mode = Node.AUTO_TRANSLATE_MODE_DISABLED if entry.id != "auto" else Node.AUTO_TRANSLATE_MODE_INHERIT var metadata := label(column,tr("Układ %d · Kapitan %d") % [entry.level,entry.captain_level],12,CYAN) metadata.mouse_filter = Control.MOUSE_FILTER_IGNORE var date := label(column,str(entry.saved_at).replace("T"," "),11,MUTED) date.mouse_filter = Control.MOUSE_FILTER_IGNORE card.pressed.connect(_select.bind(entry)) func _select(entry: Dictionary) -> void: _selected_id = entry.id if save_mode: _name.text = entry.name _summary.text = tr("Układ %d\nKapitan · poziom %d\nKredyty: %d") % [entry.level,entry.captain_level,entry.credits] if entry.recovered: _summary.text += "\n\n"+tr("Odzyskano z kopii zapasowej") for card in _list.get_children(): if card is Button: card.set_pressed_no_signal(card.name == _selected_id) _update_action() func _new_save() -> void: _selected_id = "" _name.text = tr("Wyprawa %d") % GameState.system_level for card in _list.get_children(): if card is Button: card.set_pressed_no_signal(false) _summary.text = tr("Nowy zapis\nUkład %d\nKapitan · poziom %d") % [GameState.system_level,GameState.captain.level] _name.grab_focus() _name.select_all() _update_action() func _update_action() -> void: if _action == null: return _action.disabled = _name.text.strip_edges().is_empty() if save_mode else _selected_id.is_empty() _action.text = tr("Nadpisz zapis") if save_mode and not _selected_id.is_empty() else tr("Zapisz grę" if save_mode else "Wczytaj") func _activate() -> void: if _action.disabled: return if not save_mode: load_requested.emit(_selected_id) return var result := GameState.save_named_game(_name.text,_selected_id) if result != OK: _status.text = tr("Nie udało się zapisać gry.")+" "+error_string(result) _status.show() return saved.emit() _close()