extends PanelContainer const BALANCE := preload("res://scripts/captain/captain_balance.gd") @onready var player: CharacterBody2D = get_node("../../../PlayerShip") @onready var level_label: Label = $Contents/Header/Level @onready var xp_label: Label = $Contents/XPLabel @onready var xp_bar: ProgressBar = $Contents/XPBar @onready var credits_label: Label = $Contents/Wallet/Credits @onready var points_label: Label = $Contents/Wallet/Points var _collapsed := false var _collapse_button: Button var _captain: CaptainProgress var _rank_labels: Dictionary = {} var _effect_labels: Dictionary = {} var _buttons: Dictionary = {} func _ready() -> void: _build_portrait() _captain = GameState.captain _captain.normalize_skill_ranks() for skill in BALANCE.SKILL_NAMES: var row := HBoxContainer.new() row.name = skill row.add_theme_constant_override("separation", 5) var title := Label.new() title.text = BALANCE.SKILL_NAMES[skill] title.tooltip_text = BALANCE.SKILL_HELP[skill] title.size_flags_horizontal = Control.SIZE_EXPAND_FILL title.add_theme_font_size_override("font_size", 11) row.add_child(title) var rank := Label.new() rank.custom_minimum_size.x = 40 rank.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT rank.add_theme_font_size_override("font_size", 11) row.add_child(rank) _rank_labels[skill] = rank var effect := Label.new() effect.custom_minimum_size.x = 74 effect.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT effect.add_theme_font_size_override("font_size", 10) row.add_child(effect) _effect_labels[skill] = effect var button := Button.new() button.name = "Train_" + skill button.text = "+" button.custom_minimum_size = Vector2(24, 22) button.add_theme_font_size_override("font_size", 13) button.tooltip_text = "Rozwiń umiejętność za 1 punkt nauki.\n" + BALANCE.SKILL_HELP[skill] button.pressed.connect(_train.bind(skill)) row.add_child(button) _buttons[skill] = button $Contents/Skills.add_child(row) _captain.changed.connect(_refresh) player.get_node("ShipInventory").connect("inventory_changed", _refresh) _refresh() if bool(GameState.hud_panel_state.get("captain_collapsed", true)): _toggle_collapsed() func _train(skill: String) -> void: _captain.train_skill(skill) func _refresh() -> void: level_label.text = "POZ. %d" % _captain.level xp_label.text = "XP %d / %d" % [_captain.experience, _captain.get_xp_required()] xp_bar.max_value = _captain.get_xp_required() xp_bar.value = _captain.experience credits_label.text = "Kredyty: %d" % _captain.credits points_label.text = "Punkty: %d" % _captain.learning_points for skill in _buttons: var rank := _captain.get_skill_rank(skill) _rank_labels[skill].text = "%d/%d" % [rank, BALANCE.MAX_SKILL_RANK] var suffix: String = {"piloting": "unik", "gunner": "DMG", "mechanic": "red.", "sharp_eye": "kryt"}[skill] var bonus := _captain.get_skill_bonus(skill) _effect_labels[skill].text = "%.1f%% %s" % [bonus * 100.0, suffix] var next_bonus := BALANCE.skill_bonus(skill, rank + 1) _buttons[skill].tooltip_text = BALANCE.SKILL_HELP[skill] + ("\nOsiągnięto limit 20 punktów." if rank >= BALANCE.MAX_SKILL_RANK else "\nNastępny punkt: %.1f%% → %.1f%%" % [bonus * 100.0, next_bonus * 100.0]) _buttons[skill].disabled = not _captain.can_train(skill) func _build_portrait() -> void: custom_minimum_size = Vector2(320, 0) var style := StyleBoxFlat.new() style.bg_color = Color(0.025, 0.042, 0.064, 0.96) style.border_color = Color("376779") style.set_border_width_all(1) style.set_corner_radius_all(8) style.set_content_margin_all(10) add_theme_stylebox_override("panel", style) _collapse_button = Button.new() _collapse_button.name = "CollapseCaptain" _collapse_button.text = "−" _collapse_button.flat = true _collapse_button.focus_mode = Control.FOCUS_NONE _collapse_button.custom_minimum_size = Vector2(24, 24) _collapse_button.pressed.connect(_toggle_collapsed) $Contents/Header.add_child(_collapse_button) var row := HBoxContainer.new() row.name = "PortraitRow" row.add_theme_constant_override("separation", 10) $Contents.add_child(row) $Contents.move_child(row, 1) var frame := PanelContainer.new() frame.name = "AvatarFrame" var portrait_style := style.duplicate() as StyleBoxFlat portrait_style.set_content_margin_all(2) portrait_style.border_color = Color("daa85d") frame.add_theme_stylebox_override("panel", portrait_style) row.add_child(frame) var portrait := TextureRect.new() portrait.name = "CaptainAvatar" portrait.custom_minimum_size = Vector2(76, 76) portrait.expand_mode = TextureRect.EXPAND_IGNORE_SIZE portrait.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_COVERED portrait.mouse_filter = Control.MOUSE_FILTER_IGNORE if ResourceLoader.exists("res://assets/avatars/captain.png"): portrait.texture = load("res://assets/avatars/captain.png") frame.add_child(portrait) var info := VBoxContainer.new() info.size_flags_horizontal = Control.SIZE_EXPAND_FILL info.alignment = BoxContainer.ALIGNMENT_CENTER row.add_child(info) var designation := Label.new() designation.text = "DOWÓDCA STATKU" designation.add_theme_font_size_override("font_size", 11) designation.add_theme_color_override("font_color", Color("91dbea")) info.add_child(designation) xp_label.reparent(info, false) xp_bar.reparent(info, false) xp_bar.custom_minimum_size.y = 5 func _toggle_collapsed() -> void: _collapsed = not _collapsed GameState.hud_panel_state["captain_collapsed"] = _collapsed for child in $Contents.get_children(): if child.name not in ["Header", "PortraitRow"]: child.visible = not _collapsed _collapse_button.text = "+" if _collapsed else "−" size.y = get_combined_minimum_size().y