567 lines
25 KiB
GDScript
567 lines
25 KiB
GDScript
extends CanvasLayer
|
||
|
||
const RENDER_LAYERS := preload("res://scripts/ui/render_layers.gd")
|
||
|
||
@onready var debug_toggle: Button = $HUDRoot/DebugToggle
|
||
@onready var debug_info: Label = $HUDRoot/DebugInfo
|
||
@onready var player: CharacterBody2D = get_parent().get_node("PlayerShip")
|
||
@onready var inventory_button: Button = $HUDRoot/ShipEquipmentPanel/Contents/InventoryButton
|
||
@onready var inventory_panel: Control = $HUDRoot/ShipInventoryPanel
|
||
|
||
var _window_manager: Node
|
||
var _energy_bank_button: Button
|
||
var _debug_expanded := false
|
||
var _ability_buttons: Dictionary = {}
|
||
var _ability_bar: HBoxContainer
|
||
var _passive_skills: VBoxContainer
|
||
var _inventory_clip: Control
|
||
var _sidebar: PanelContainer
|
||
var _sidebar_toggle: Button
|
||
var _sidebar_open := false
|
||
var _sidebar_tween: Tween
|
||
const SIDEBAR_WIDTH := 306.0
|
||
const EQUIPMENT_UI_SCALE := 0.8
|
||
var _debug_scroll: ScrollContainer
|
||
var _debug_actions: VBoxContainer
|
||
var _debug_item_button: Button
|
||
var _debug_item_status: Label
|
||
var _captain_panel: PanelContainer
|
||
var _cockpit: Control
|
||
var _crafting_window: PanelContainer
|
||
var _captain_skills_ui: CanvasLayer
|
||
|
||
func _create_navigation() -> void:
|
||
var navigation := HBoxContainer.new()
|
||
navigation.name = "TopNavigation"
|
||
$HUDRoot.add_child(navigation)
|
||
navigation.set_anchors_and_offsets_preset(Control.PRESET_CENTER_TOP)
|
||
navigation.offset_left = -70
|
||
navigation.offset_right = 70
|
||
navigation.offset_top = 12
|
||
navigation.offset_bottom = 92
|
||
navigation.add_theme_constant_override("separation", 10)
|
||
_crafting_window = _create_window("CraftingWindow", "WARSZTAT", Vector2(704, 420))
|
||
var crafting := PanelContainer.new()
|
||
crafting.name = "CraftingPanel"
|
||
crafting.set_script(preload("res://scripts/ui/ship_crafting_panel.gd"))
|
||
crafting.set("standalone", true)
|
||
_crafting_window.get_node("Contents").add_child(crafting)
|
||
_captain_skills_ui = CanvasLayer.new()
|
||
_captain_skills_ui.set_script(preload("res://scripts/ui/captain_skills_ui.gd"))
|
||
_captain_skills_ui.set("player", player)
|
||
add_child(_captain_skills_ui)
|
||
for entry in [["Twórz", _crafting_window, "res://assets/icons/ui/crafting_art.png", Color("efb568")], ["Umiejętności kapitana", null, "res://assets/icons/ui/captain_skills_art.png", Color("b9a0ef")]]:
|
||
var button := Button.new()
|
||
button.tooltip_text = entry[0]
|
||
button.set_script(preload("res://scripts/ui/navigation_button.gd"))
|
||
button.call("configure_navigation", load(entry[2]) as Texture2D, entry[3], "TWÓRZ" if entry[1] != null else "KAPITAN")
|
||
navigation.add_child(button)
|
||
if entry[1] == null:
|
||
button.name = "OpenCaptainSkills"
|
||
button.pressed.connect(func() -> void:
|
||
_crafting_window.hide()
|
||
_captain_skills_ui.call("open_management")
|
||
)
|
||
else:
|
||
button.pressed.connect(_toggle_window.bind(entry[1]))
|
||
|
||
func _create_window(node_name: String, title: String, dimensions: Vector2) -> PanelContainer:
|
||
var window := PanelContainer.new()
|
||
window.name = node_name
|
||
window.z_index = RENDER_LAYERS.WINDOW_Z
|
||
var style := StyleBoxFlat.new()
|
||
style.bg_color = Color("0b1520")
|
||
style.border_color = Color("376779")
|
||
style.set_border_width_all(1)
|
||
style.set_corner_radius_all(8)
|
||
style.set_content_margin_all(16)
|
||
window.add_theme_stylebox_override("panel", style)
|
||
$HUDRoot.add_child(window)
|
||
window.set_anchors_and_offsets_preset(Control.PRESET_CENTER)
|
||
window.offset_left = -dimensions.x * 0.5
|
||
window.offset_right = dimensions.x * 0.5
|
||
window.offset_top = -dimensions.y * 0.5
|
||
window.offset_bottom = dimensions.y * 0.5
|
||
var contents := VBoxContainer.new()
|
||
contents.name = "Contents"
|
||
contents.add_theme_constant_override("separation", 12)
|
||
window.add_child(contents)
|
||
var header := HBoxContainer.new()
|
||
header.name = "Header"
|
||
contents.add_child(header)
|
||
var label := Label.new()
|
||
label.text = title
|
||
label.add_theme_font_size_override("font_size", 14)
|
||
label.add_theme_color_override("font_color", Color("91dbea"))
|
||
label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||
header.add_child(label)
|
||
var close := Button.new()
|
||
close.text = "×"
|
||
close.tooltip_text = "Zamknij"
|
||
close.custom_minimum_size = Vector2(32, 28)
|
||
close.pressed.connect(window.hide)
|
||
header.add_child(close)
|
||
window.hide()
|
||
_window_manager.call("register_window", window, window, header)
|
||
return window
|
||
|
||
func _toggle_window(window: PanelContainer) -> void:
|
||
var opening := not window.visible
|
||
_crafting_window.hide()
|
||
window.visible = opening
|
||
|
||
func _ready() -> void:
|
||
layer = RENDER_LAYERS.HUD
|
||
_sidebar_open = bool(GameState.hud_panel_state.get("ship_open", false))
|
||
_debug_expanded = bool(GameState.hud_panel_state.get("debug_expanded", false))
|
||
debug_info.visible = _debug_expanded
|
||
var energy_indicator := Node2D.new()
|
||
energy_indicator.name = "EnergyIndicator"
|
||
energy_indicator.set_script(preload("res://scripts/game/ship_energy_indicator.gd"))
|
||
energy_indicator.set("player", player)
|
||
player.add_child(energy_indicator)
|
||
var feedback := Control.new()
|
||
feedback.name = "CombatFeedback"
|
||
feedback.set_script(preload("res://scripts/ui/combat_feedback.gd"))
|
||
feedback.set("player", player)
|
||
$HUDRoot.add_child(feedback)
|
||
debug_info.add_theme_font_size_override("font_size", 10)
|
||
# The display font has unusually tall vertical metrics; keep debug rows compact.
|
||
debug_info.add_theme_constant_override("line_spacing", mini(0, 13 - ceili(debug_info.get_theme_font("font").get_height(10))))
|
||
_window_manager = Node.new()
|
||
_window_manager.name = "FloatingWindows"
|
||
_window_manager.set_script(preload("res://scripts/ui/floating_window_manager.gd"))
|
||
$HUDRoot.add_child(_window_manager)
|
||
_window_manager.connect("interaction_started", player.get_node("WeaponController").call.bind("block_ui_mouse_input"))
|
||
_create_sidebar()
|
||
_inventory_clip = Control.new()
|
||
_inventory_clip.name = "InventoryDrawer"
|
||
_inventory_clip.clip_contents = false
|
||
_inventory_clip.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
$HUDRoot.add_child(_inventory_clip)
|
||
inventory_panel.reparent(_inventory_clip, false)
|
||
inventory_panel.set("layout_mode", 0)
|
||
inventory_panel.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
|
||
inventory_panel.size = Vector2(560, inventory_panel.get_combined_minimum_size().y)
|
||
inventory_panel.scale = Vector2.ONE * EQUIPMENT_UI_SCALE
|
||
inventory_panel.set("drawer_width", inventory_panel.size.x * EQUIPMENT_UI_SCALE)
|
||
_window_manager.call("register_window", _inventory_clip, inventory_panel, inventory_panel.get_node("Contents/Header"))
|
||
$HUDRoot.resized.connect(func() -> void: _layout_sidebar.call_deferred())
|
||
_create_ability_bar()
|
||
var objectives := PanelContainer.new()
|
||
objectives.name = "MissionObjectives"
|
||
objectives.set_script(preload("res://scripts/ui/mission_objectives.gd"))
|
||
objectives.set("game", get_parent())
|
||
$HUDRoot.add_child(objectives)
|
||
debug_toggle.pressed.connect(_toggle_debug)
|
||
inventory_button.pressed.connect(_toggle_inventory)
|
||
_update_debug_toggle()
|
||
_layout_sidebar.call_deferred()
|
||
if _sidebar_open and bool(GameState.hud_panel_state.get("inventory_open", false)):
|
||
inventory_panel.call("_set_drawer_open", true)
|
||
|
||
func _create_sidebar() -> void:
|
||
_captain_panel = $HUDRoot/CaptainPanel
|
||
_captain_panel.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
|
||
_captain_panel.position = Vector2(12, 12)
|
||
_captain_panel.size = Vector2(244, _captain_panel.get_combined_minimum_size().y)
|
||
_captain_panel.resized.connect(_layout_debug)
|
||
_passive_skills = VBoxContainer.new()
|
||
_passive_skills.name = "PassiveCaptainSkills"
|
||
_passive_skills.add_theme_constant_override("separation", 6)
|
||
$HUDRoot.add_child(_passive_skills)
|
||
_passive_skills.minimum_size_changed.connect(func() -> void: _layout_debug.call_deferred())
|
||
GameState.captain.changed.connect(_refresh_passive_skills)
|
||
_refresh_passive_skills()
|
||
_debug_actions = VBoxContainer.new()
|
||
_debug_actions.name = "DebugActions"
|
||
_debug_actions.add_theme_constant_override("separation", 6)
|
||
$HUDRoot.add_child(_debug_actions)
|
||
_debug_item_button = Button.new()
|
||
_debug_item_button.name = "GenerateItem"
|
||
_debug_item_button.custom_minimum_size.y = 36
|
||
preload("res://scripts/ui/hud_button_style.gd").apply(_debug_item_button, Color("a9ef83"))
|
||
_debug_item_button.pressed.connect(_give_debug_item)
|
||
_debug_actions.add_child(_debug_item_button)
|
||
var ammunition_button := Button.new()
|
||
ammunition_button.name = "AddAmmunition"
|
||
ammunition_button.text = "Dodaj amunicję"
|
||
ammunition_button.tooltip_text = "+10 zwykłej amunicji, +10 radiacyjnej amunicji i +10 rakiet"
|
||
ammunition_button.custom_minimum_size.y = 36
|
||
preload("res://scripts/ui/hud_button_style.gd").apply(ammunition_button, Color("efb568"))
|
||
ammunition_button.pressed.connect(_give_debug_ammunition)
|
||
_debug_actions.add_child(ammunition_button)
|
||
_debug_item_status = Label.new()
|
||
_debug_item_status.add_theme_font_size_override("font_size", 10)
|
||
_debug_item_status.add_theme_color_override("font_color", Color("a9ef83"))
|
||
_debug_item_status.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||
_debug_item_status.hide()
|
||
_debug_actions.add_child(_debug_item_status)
|
||
_debug_actions.minimum_size_changed.connect(func() -> void: _layout_debug.call_deferred())
|
||
_debug_scroll = ScrollContainer.new()
|
||
_debug_scroll.name = "DebugScroll"
|
||
_debug_scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
|
||
$HUDRoot.add_child(_debug_scroll)
|
||
debug_info.reparent(_debug_scroll, false)
|
||
debug_info.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
|
||
debug_info.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||
debug_info.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
_sidebar = PanelContainer.new()
|
||
_sidebar.name = "ShipDrawer"
|
||
var style := StyleBoxFlat.new()
|
||
style.bg_color = Color(0.025, 0.042, 0.064, 1.0)
|
||
style.border_color = Color("376779")
|
||
style.set_border_width_all(1)
|
||
style.set_corner_radius_all(8)
|
||
style.set_content_margin_all(8)
|
||
_sidebar.add_theme_stylebox_override("panel", style)
|
||
$HUDRoot.add_child(_sidebar)
|
||
var scroll := ScrollContainer.new()
|
||
scroll.name = "Scroll"
|
||
scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
|
||
_sidebar.add_child(scroll)
|
||
var contents := VBoxContainer.new()
|
||
contents.name = "Contents"
|
||
contents.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||
scroll.add_child(contents)
|
||
var equipment := $HUDRoot/ShipEquipmentPanel as PanelContainer
|
||
equipment.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
|
||
equipment.reparent(contents, false)
|
||
equipment.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||
equipment.add_theme_stylebox_override("panel", StyleBoxEmpty.new())
|
||
contents.minimum_size_changed.connect(func() -> void: _layout_sidebar.call_deferred())
|
||
_sidebar_toggle = Button.new()
|
||
_sidebar_toggle.set_script(preload("res://scripts/ui/ship_profile.gd"))
|
||
_sidebar_toggle.set("player", player)
|
||
_sidebar_toggle.name = "ShipToggle"
|
||
_sidebar_toggle.tooltip_text = "Zamknij okno statku" if _sidebar_open else "Otwórz statek i sloty wyposażenia"
|
||
_sidebar_toggle.add_theme_font_size_override("font_size", 12)
|
||
preload("res://scripts/ui/hud_button_style.gd").apply(_sidebar_toggle)
|
||
preload("res://scripts/ui/hud_button_style.gd").apply(inventory_button, Color("b9a0ef"))
|
||
$HUDRoot.add_child(_sidebar_toggle)
|
||
_sidebar_toggle.set_anchors_and_offsets_preset(Control.PRESET_TOP_RIGHT)
|
||
_sidebar_toggle.offset_left = -352
|
||
_sidebar_toggle.offset_right = -12
|
||
_sidebar_toggle.offset_top = 12
|
||
_sidebar_toggle.offset_bottom = 122
|
||
_sidebar_toggle.pressed.connect(_toggle_sidebar)
|
||
_cockpit = Control.new()
|
||
_cockpit.name = "Cockpit"
|
||
_cockpit.set_script(preload("res://scripts/ui/flight_cockpit.gd"))
|
||
_cockpit.set("player", player)
|
||
_cockpit.set("game", get_parent())
|
||
$HUDRoot.add_child(_cockpit)
|
||
_window_manager.call("register_window", _sidebar, _sidebar, equipment.get_node("Contents/Title"))
|
||
_create_navigation()
|
||
_layout_debug()
|
||
|
||
func _layout_debug() -> void:
|
||
if not is_instance_valid(_debug_scroll) or not is_instance_valid(_captain_panel):
|
||
return
|
||
var top := _captain_panel.position.y + _captain_panel.size.y + 6.0
|
||
if is_instance_valid(_passive_skills):
|
||
_passive_skills.position = Vector2(_captain_panel.position.x, top)
|
||
_passive_skills.size = Vector2(36, _passive_skills.get_combined_minimum_size().y)
|
||
if _passive_skills.visible:
|
||
top += _passive_skills.size.y + 8.0
|
||
debug_toggle.position = Vector2(12, top)
|
||
_debug_actions.position = Vector2(18, top + 30)
|
||
_debug_actions.size = Vector2(310, _debug_actions.get_combined_minimum_size().y)
|
||
_debug_actions.visible = _debug_expanded
|
||
var scroll_top := _debug_actions.position.y + _debug_actions.size.y + 8.0
|
||
_debug_scroll.position = Vector2(18, scroll_top)
|
||
_debug_scroll.size = Vector2(310, maxf(40, $HUDRoot.size.y - scroll_top - 12))
|
||
_debug_scroll.visible = _debug_expanded
|
||
|
||
func _toggle_sidebar() -> void:
|
||
_sidebar_open = not _sidebar_open
|
||
GameState.hud_panel_state["ship_open"] = _sidebar_open
|
||
if _sidebar_tween != null and _sidebar_tween.is_running():
|
||
_sidebar_tween.kill()
|
||
_sidebar_toggle.tooltip_text = "Zamknij okno statku" if _sidebar_open else "Otwórz statek i sloty wyposażenia"
|
||
if _sidebar_open:
|
||
_sidebar.show()
|
||
else:
|
||
close_inventory()
|
||
_sidebar.visible = _sidebar_open
|
||
if _sidebar_open:
|
||
_window_manager.call("focus_window", _sidebar)
|
||
_layout_sidebar()
|
||
|
||
func _layout_sidebar() -> void:
|
||
if not is_instance_valid(_sidebar) or not is_instance_valid(_cockpit):
|
||
return
|
||
if _sidebar_tween != null and _sidebar_tween.is_running():
|
||
_sidebar_tween.kill()
|
||
_sidebar.scale = Vector2.ONE * EQUIPMENT_UI_SCALE
|
||
_sidebar.size = Vector2(maxf(SIDEBAR_WIDTH, _sidebar.get_combined_minimum_size().x), minf(_sidebar.get_node("Scroll/Contents").get_combined_minimum_size().y + 16.0, maxf(100.0, ($HUDRoot.size.y - 148.0) / EQUIPMENT_UI_SCALE)))
|
||
_cockpit.scale = Vector2.ONE * 0.85
|
||
_cockpit.size = Vector2(minf(850.0, ($HUDRoot.size.x - 24) / 0.85), 120)
|
||
_cockpit.position = Vector2(($HUDRoot.size.x - _cockpit.size.x * 0.85) * 0.5, $HUDRoot.size.y - _cockpit.size.y * 0.85 - 12)
|
||
if _ability_bar != null:
|
||
var abilities := _ability_bar.get_parent() as Control
|
||
abilities.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
|
||
abilities.position = Vector2(_cockpit.position.x + _cockpit.size.x * _cockpit.scale.x - 204.0, _cockpit.position.y - 40.0)
|
||
abilities.size = Vector2(204, 36)
|
||
if is_instance_valid(_captain_skills_ui):
|
||
_captain_skills_ui.call_deferred("_layout")
|
||
_layout_debug()
|
||
if not _sidebar.has_meta("floating_window_dragged"):
|
||
_sidebar.position = Vector2($HUDRoot.size.x - _sidebar.size.x * EQUIPMENT_UI_SCALE - 8, 136)
|
||
else:
|
||
_window_manager.call("clamp_window", _sidebar)
|
||
_sidebar.visible = _sidebar_open
|
||
_inventory_clip.size = inventory_panel.size * EQUIPMENT_UI_SCALE
|
||
_layout_inventory()
|
||
|
||
func _layout_inventory() -> void:
|
||
if not is_instance_valid(_inventory_clip) or not is_instance_valid(_sidebar):
|
||
return
|
||
if _inventory_clip.has_meta("floating_window_dragged"):
|
||
_window_manager.call("clamp_window", _inventory_clip)
|
||
return
|
||
var equipment := _sidebar.get_node("Scroll/Contents/ShipEquipmentPanel") as Control
|
||
_inventory_clip.position = Vector2(maxf(12.0, _sidebar.position.x - _inventory_clip.size.x - 8), minf(equipment.global_position.y, maxf(8.0, $HUDRoot.size.y - inventory_panel.size.y * EQUIPMENT_UI_SCALE - 8)))
|
||
|
||
func _update_energy_bank_button() -> void:
|
||
if _energy_bank_button == null:
|
||
_energy_bank_button = Button.new()
|
||
_energy_bank_button.name = "EnergyBankButton"
|
||
_energy_bank_button.set_script(preload("res://scripts/ui/captain_skill_button.gd"))
|
||
_energy_bank_button.call("configure", preload("res://assets/icons/resources/energy_bank.svg"), Color("70f5df"))
|
||
_energy_bank_button.custom_minimum_size = Vector2(48, 48)
|
||
_energy_bank_button.size = Vector2(48, 48)
|
||
$HUDRoot.add_child(_energy_bank_button)
|
||
var key := Label.new()
|
||
key.text = "R"
|
||
key.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
key.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
||
key.vertical_alignment = VERTICAL_ALIGNMENT_TOP
|
||
key.add_theme_font_size_override("font_size", 11)
|
||
key.add_theme_color_override("font_color", Color.WHITE)
|
||
key.add_theme_color_override("font_outline_color", Color("07141e"))
|
||
key.add_theme_constant_override("outline_size", 7)
|
||
_energy_bank_button.add_child(key)
|
||
key.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||
key.offset_right = -5
|
||
key.offset_top = 2
|
||
var amount := Label.new()
|
||
amount.name = "Amount"
|
||
amount.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
amount.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||
amount.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||
amount.add_theme_font_size_override("font_size", 22)
|
||
amount.add_theme_color_override("font_color", Color.WHITE)
|
||
amount.add_theme_color_override("font_outline_color", Color("07141e"))
|
||
amount.add_theme_constant_override("outline_size", 7)
|
||
_energy_bank_button.add_child(amount)
|
||
amount.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||
_energy_bank_button.pressed.connect(func() -> void: player.call("use_energy_bank"))
|
||
_energy_bank_button.position = Vector2(_cockpit.position.x + _cockpit.size.x * _cockpit.scale.x * 0.5 - 24.0, _cockpit.position.y - 56.0)
|
||
var inventory := player.get_node("ShipInventory") as ShipInventory
|
||
var count := inventory.get_energy_bank_count()
|
||
(_energy_bank_button.get_node("Amount") as Label).text = str(count)
|
||
_energy_bank_button.tooltip_text = "Bank energii: %d\nR • Przywraca %d%% maksymalnej energii" % [count, roundi(GameState.captain.get_energy_bank_fraction() * 100.0)]
|
||
_energy_bank_button.disabled = count == 0 or float(player.get("energy")) >= float(player.get("max_energy")) or bool(player.get("_is_destroyed")) or bool(player.get("is_docked"))
|
||
_energy_bank_button.call("set_visual_state", 0.0, false, _energy_bank_button.disabled)
|
||
|
||
func _process(_delta: float) -> void:
|
||
_update_energy_bank_button()
|
||
_layout_inventory()
|
||
_update_ability_bar()
|
||
if not _debug_expanded:
|
||
return
|
||
var inventory := player.get_node("ShipInventory") as ShipInventory
|
||
_debug_item_button.text = "LOSUJ PRZEDMIOT · POZ. %d" % GameState.system_level
|
||
_debug_item_button.disabled = inventory.get_cargo_used() >= ShipInventory.CARGO_SIZE
|
||
_debug_item_button.tooltip_text = "Magazyn jest pełny — zwolnij miejsce." if _debug_item_button.disabled else "Losuje przedmiot i addony dla poziomu aktualnego układu."
|
||
var game := get_parent()
|
||
debug_info.text = """POZIOM UKŁADU: %d
|
||
WROGOWIE: %d
|
||
PRĘDKOŚĆ: %.1f px/s
|
||
|
||
AKTUALNA REGENERACJA
|
||
Energia: %.1f pkt/s
|
||
Tarcze: %.1f pkt/s
|
||
|
||
%s""".replace("\r", "") % [
|
||
GameState.system_level,
|
||
int(game.call("get_remaining_enemies")),
|
||
player.velocity.length(),
|
||
float(player.call("get_energy_regeneration")),
|
||
float(player.get("shield_regeneration")),
|
||
_get_bonus_summary(),
|
||
]
|
||
|
||
func _toggle_debug() -> void:
|
||
_debug_expanded = not _debug_expanded
|
||
GameState.hud_panel_state["debug_expanded"] = _debug_expanded
|
||
debug_info.visible = _debug_expanded
|
||
_debug_scroll.visible = _debug_expanded
|
||
_debug_actions.visible = _debug_expanded
|
||
_update_debug_toggle()
|
||
_layout_debug()
|
||
|
||
func _give_debug_ammunition() -> void:
|
||
var inventory := player.get_node("ShipInventory") as ShipInventory
|
||
inventory.ammunition += 10
|
||
inventory.irradiated_ammunition += 10
|
||
inventory.missile_ammunition += 10
|
||
inventory.ammunition_changed.emit()
|
||
inventory.inventory_changed.emit()
|
||
|
||
func _give_debug_item() -> bool:
|
||
var inventory := player.get_node("ShipInventory") as ShipInventory
|
||
_debug_item_status.show()
|
||
if inventory.get_cargo_used() >= ShipInventory.CARGO_SIZE:
|
||
_debug_item_status.text = "Magazyn pełny — zwolnij miejsce."
|
||
_debug_item_status.add_theme_color_override("font_color", Color("ff8989"))
|
||
_layout_debug.call_deferred()
|
||
return false
|
||
var item := preload("res://scripts/items/item_generator.gd").generate(GameState.system_level)
|
||
if not inventory.add_item(item):
|
||
return false
|
||
_debug_item_status.text = "Dodano: %s · Poz. %d" % [item.definition.display_name, item.item_level]
|
||
_debug_item_status.add_theme_color_override("font_color", Color("a9ef83"))
|
||
_layout_debug.call_deferred()
|
||
return true
|
||
|
||
func _update_debug_toggle() -> void:
|
||
debug_toggle.text = "DEBUG [−]" if _debug_expanded else "DEBUG [+]"
|
||
|
||
func _toggle_inventory() -> void:
|
||
if not _sidebar_open:
|
||
_toggle_sidebar()
|
||
inventory_panel.call("toggle_drawer")
|
||
|
||
func close_inventory() -> void:
|
||
inventory_panel.call("close_drawer", true)
|
||
|
||
func _get_bonus_summary() -> String:
|
||
var cooldown_bonus := 0.0
|
||
var inventory := player.get_node("ShipInventory") as ShipInventory
|
||
for item in inventory.weapon_slots + inventory.module_slots:
|
||
if item != null:
|
||
cooldown_bonus += item.get_stat_total("missile_cooldown_reduction")
|
||
return """BONUSY (ADDONY + KAPITAN)
|
||
Obrażenia broni: %+.1f%%
|
||
Szansa na krytyk: %+.1f%%
|
||
Obrażenia krytyczne: %+.1f%%
|
||
Szansa na unik: %+.1f%%
|
||
Redukcja obrażeń: %+.1f%%
|
||
Odzysk tarcz z obrażeń: %.1f%%
|
||
Regeneracja energii: %+.1f pkt/s
|
||
Regeneracja tarcz: %+.1f pkt/s
|
||
Kadłub: %+.1f pkt
|
||
Tarcze: %+.1f pkt
|
||
Energia: %+.1f pkt
|
||
Prędkość maks.: %+.1f%%
|
||
Skrócenie cooldownu rakiet: %.2f s
|
||
Doświadczenie: %+.1f%%
|
||
Kredyty: %+.1f%%
|
||
Szczęście: %.1f%% / 60%%""".replace("\r", "") % [
|
||
(float(player.call("get_weapon_damage_multiplier")) - 1.0) * 100.0,
|
||
float(player.call("get_critical_chance")) * 100.0,
|
||
float(player.get("critical_damage_bonus")) * 100.0,
|
||
float(player.call("get_evasion_chance")) * 100.0,
|
||
float(player.call("get_damage_reduction")) * 100.0,
|
||
float(player.get("shield_on_damage_percent")),
|
||
float(player.get("energy_regeneration")) - float(player.get("base_energy_regeneration")),
|
||
float(player.get("shield_regeneration")) - float(player.get("base_shield_regeneration")),
|
||
float(player.get("max_hull")) - float(player.get("base_max_hull")),
|
||
float(player.get("max_shields")) - float(player.get("base_max_shields")),
|
||
float(player.get("max_energy")) - float(player.get("base_max_energy")),
|
||
(float(player.get("max_speed")) / float(player.get("base_max_speed")) - 1.0) * 100.0,
|
||
cooldown_bonus,
|
||
(float(player.get("experience_multiplier")) - 1.0) * 100.0,
|
||
(float(player.get("credits_multiplier")) - 1.0) * 100.0,
|
||
float(player.call("get_luck_chance")) * 100.0,
|
||
]
|
||
|
||
func _create_ability_bar() -> void:
|
||
var panel := PanelContainer.new()
|
||
panel.name = "ActiveAbilities"
|
||
$HUDRoot.add_child(panel)
|
||
panel.set_anchors_and_offsets_preset(Control.PRESET_CENTER_BOTTOM)
|
||
panel.offset_left = -120.0
|
||
panel.offset_right = 120.0
|
||
panel.offset_top = -220.0
|
||
panel.offset_bottom = -176.0
|
||
panel.add_theme_stylebox_override("panel", StyleBoxEmpty.new())
|
||
_ability_bar = HBoxContainer.new()
|
||
_ability_bar.name = "AbilityButtons"
|
||
_ability_bar.alignment = BoxContainer.ALIGNMENT_END
|
||
_ability_bar.add_theme_constant_override("separation", 6)
|
||
panel.add_child(_ability_bar)
|
||
for index in ShipInventory.EXTENSION_SLOT_COUNT:
|
||
var button := Button.new()
|
||
button.set_script(preload("res://scripts/ui/captain_skill_button.gd"))
|
||
button.name = "Ability%d" % (index + 1)
|
||
button.call("configure", null, Color("91dbea"))
|
||
var shortcut := Label.new()
|
||
shortcut.text = str(index + 1)
|
||
shortcut.position = Vector2(4, 2)
|
||
shortcut.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
shortcut.add_theme_font_size_override("font_size", 9)
|
||
shortcut.add_theme_font_override("font", ThemeDB.fallback_font)
|
||
shortcut.add_theme_color_override("font_outline_color", Color("030810"))
|
||
shortcut.add_theme_constant_override("outline_size", 4)
|
||
button.add_child(shortcut)
|
||
button.add_theme_font_size_override("font_size", 11)
|
||
button.pressed.connect(func() -> void: player.call("activate_ability", index))
|
||
var timer := Label.new()
|
||
timer.name = "Cooldown"
|
||
timer.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
timer.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||
timer.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||
timer.add_theme_font_size_override("font_size", 13)
|
||
timer.add_theme_font_override("font", ThemeDB.fallback_font)
|
||
timer.add_theme_color_override("font_outline_color", Color("030810"))
|
||
timer.add_theme_constant_override("outline_size", 4)
|
||
button.add_child(timer)
|
||
timer.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||
_ability_bar.add_child(button)
|
||
_ability_buttons[index] = button
|
||
_update_ability_bar()
|
||
|
||
func _update_ability_bar() -> void:
|
||
var any_equipped := false
|
||
for index in _ability_buttons:
|
||
var button: Button = _ability_buttons[index]
|
||
var ability: ActiveAbility = player.call("get_active_ability", index)
|
||
button.visible = ability != null
|
||
if ability == null:
|
||
continue
|
||
any_equipped = true
|
||
var reason: String = player.call("ability_unavailable_reason", index)
|
||
button.disabled = not reason.is_empty()
|
||
var item: ItemInstance = player.get_node("ShipInventory").get_item("extension", index)
|
||
button.call("configure", item.definition.icon, Color("91dbea"))
|
||
var cooldown := float(player.call("get_ability_cooldown", index))
|
||
button.call("set_visual_state", cooldown / maxf(0.01, ability.cooldown), false, not reason.is_empty())
|
||
(button.get_node("Cooldown") as Label).text = str(ceili(cooldown)) if cooldown > 0.0 else ""
|
||
button.tooltip_text = "[%d] %s\n" % [index + 1, ability.display_name] + ability.description + ("\n" + reason if not reason.is_empty() else "\nGotowe")
|
||
_ability_bar.get_parent().visible = any_equipped
|
||
|
||
func _refresh_passive_skills() -> void:
|
||
if not is_instance_valid(_passive_skills):
|
||
return
|
||
for child in _passive_skills.get_children():
|
||
_passive_skills.remove_child(child)
|
||
child.queue_free()
|
||
var catalog := preload("res://scripts/captain/captain_skills.gd")
|
||
for skill in catalog.IDS:
|
||
var rank := GameState.captain.get_skill_rank(skill)
|
||
if rank <= 0 or bool(catalog.DATA[skill]["active"]):
|
||
continue
|
||
var icon := Button.new()
|
||
icon.name = skill
|
||
icon.set_script(preload("res://scripts/ui/captain_skill_button.gd"))
|
||
icon.call("configure", catalog.icon(skill), Color(catalog.DATA[skill]["color"]))
|
||
icon.disabled = true
|
||
icon.mouse_default_cursor_shape = Control.CURSOR_HELP
|
||
icon.tooltip_text = "%s · poziom %d / 3\n%s" % [catalog.DATA[skill]["name"], rank, catalog.description(skill, rank)]
|
||
_passive_skills.add_child(icon)
|
||
_passive_skills.visible = _passive_skills.get_child_count() > 0
|
||
_layout_debug.call_deferred()
|