251 lines
9.8 KiB
GDScript
251 lines
9.8 KiB
GDScript
extends CanvasLayer
|
||
|
||
@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 _debug_expanded := true
|
||
var _ability_buttons: Dictionary = {}
|
||
var _ability_bar: HBoxContainer
|
||
var _ability_ready_style: StyleBoxFlat
|
||
var _ability_blocked_style: StyleBoxFlat
|
||
var _inventory_clip: Control
|
||
var _sidebar: PanelContainer
|
||
var _sidebar_toggle: Button
|
||
var _sidebar_open := false
|
||
var _sidebar_tween: Tween
|
||
const SIDEBAR_WIDTH := 344.0
|
||
|
||
func _ready() -> void:
|
||
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", 9)
|
||
_create_sidebar()
|
||
_inventory_clip = Control.new()
|
||
_inventory_clip.name = "InventoryDrawer"
|
||
_inventory_clip.clip_contents = true
|
||
_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(780, inventory_panel.get_combined_minimum_size().y)
|
||
$HUDRoot.resized.connect(func() -> void: _layout_sidebar.call_deferred())
|
||
_create_ability_bar()
|
||
debug_toggle.pressed.connect(_toggle_debug)
|
||
inventory_button.pressed.connect(_toggle_inventory)
|
||
_update_debug_toggle()
|
||
_layout_sidebar.call_deferred()
|
||
|
||
func _create_sidebar() -> void:
|
||
_sidebar = PanelContainer.new()
|
||
_sidebar.name = "CaptainShipDrawer"
|
||
var style := StyleBoxFlat.new()
|
||
style.bg_color = Color(0.018, 0.028, 0.043, 0.97)
|
||
style.border_color = Color("52677e")
|
||
style.set_border_width_all(1)
|
||
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
|
||
contents.add_theme_constant_override("separation", 8)
|
||
scroll.add_child(contents)
|
||
var captain := $HUDRoot/CaptainPanel as PanelContainer
|
||
var equipment := $HUDRoot/ShipEquipmentPanel as PanelContainer
|
||
for panel in [captain, equipment]:
|
||
panel.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
|
||
panel.reparent(contents, false)
|
||
panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||
panel.add_theme_stylebox_override("panel", StyleBoxEmpty.new())
|
||
if panel == captain:
|
||
contents.add_child(HSeparator.new())
|
||
_sidebar_toggle = Button.new()
|
||
_sidebar_toggle.name = "CaptainShipToggle"
|
||
_sidebar_toggle.text = "KAPITAN / STATEK ◀"
|
||
_sidebar_toggle.add_theme_font_size_override("font_size", 12)
|
||
_sidebar_toggle.focus_mode = Control.FOCUS_NONE
|
||
$HUDRoot.add_child(_sidebar_toggle)
|
||
_sidebar_toggle.set_anchors_and_offsets_preset(Control.PRESET_TOP_RIGHT)
|
||
_sidebar_toggle.offset_left = -210
|
||
_sidebar_toggle.offset_right = -8
|
||
_sidebar_toggle.offset_top = 8
|
||
_sidebar_toggle.offset_bottom = 38
|
||
_sidebar_toggle.pressed.connect(_toggle_sidebar)
|
||
_sidebar.hide()
|
||
|
||
func _toggle_sidebar() -> void:
|
||
_sidebar_open = not _sidebar_open
|
||
if _sidebar_tween != null and _sidebar_tween.is_running():
|
||
_sidebar_tween.kill()
|
||
_sidebar_toggle.text = "ZAMKNIJ ▶" if _sidebar_open else "KAPITAN / STATEK ◀"
|
||
if _sidebar_open:
|
||
_sidebar.show()
|
||
else:
|
||
close_inventory()
|
||
_sidebar_tween = create_tween()
|
||
_sidebar_tween.tween_property(_sidebar, "position:x", $HUDRoot.size.x - SIDEBAR_WIDTH - 8 if _sidebar_open else $HUDRoot.size.x, 0.25).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT if _sidebar_open else Tween.EASE_IN)
|
||
if not _sidebar_open:
|
||
_sidebar_tween.tween_callback(_sidebar.hide)
|
||
|
||
func _layout_sidebar() -> void:
|
||
if _sidebar_tween != null and _sidebar_tween.is_running():
|
||
_sidebar_tween.kill()
|
||
_sidebar.size = Vector2(SIDEBAR_WIDTH, maxf(100.0, $HUDRoot.size.y - 52.0))
|
||
_sidebar.position = Vector2($HUDRoot.size.x - SIDEBAR_WIDTH - 8 if _sidebar_open else $HUDRoot.size.x, 44)
|
||
_sidebar.visible = _sidebar_open
|
||
_inventory_clip.size = inventory_panel.size
|
||
_layout_inventory()
|
||
|
||
func _layout_inventory() -> void:
|
||
if _inventory_clip == null:
|
||
return
|
||
var equipment := _sidebar.get_node("Scroll/Contents/ShipEquipmentPanel") as Control
|
||
_inventory_clip.position = Vector2(_sidebar.position.x - _inventory_clip.size.x - 8, minf(equipment.global_position.y, maxf(8.0, $HUDRoot.size.y - inventory_panel.size.y - 8)))
|
||
|
||
func _process(_delta: float) -> void:
|
||
_layout_inventory()
|
||
_update_ability_bar()
|
||
if not _debug_expanded:
|
||
return
|
||
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""" % [
|
||
GameState.system_level,
|
||
int(game.call("get_remaining_enemies")),
|
||
player.velocity.length(),
|
||
float(player.get("energy_regeneration")) + float(player.call("get_solar_regeneration")),
|
||
float(player.get("shield_regeneration")),
|
||
_get_bonus_summary(),
|
||
]
|
||
|
||
func _toggle_debug() -> void:
|
||
_debug_expanded = not _debug_expanded
|
||
debug_info.visible = _debug_expanded
|
||
_update_debug_toggle()
|
||
|
||
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%%""" % [
|
||
(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,
|
||
]
|
||
|
||
func _create_ability_bar() -> void:
|
||
_ability_ready_style = _make_ability_style(true)
|
||
_ability_blocked_style = _make_ability_style(false)
|
||
var panel := PanelContainer.new()
|
||
panel.name = "ActiveAbilities"
|
||
$HUDRoot.add_child(panel)
|
||
panel.set_anchors_and_offsets_preset(Control.PRESET_BOTTOM_LEFT)
|
||
panel.offset_left = 12.0
|
||
panel.offset_right = 12.0
|
||
panel.offset_top = -54.0
|
||
panel.offset_bottom = -12.0
|
||
_ability_bar = HBoxContainer.new()
|
||
_ability_bar.add_theme_constant_override("separation", 4)
|
||
panel.add_child(_ability_bar)
|
||
for index in 6:
|
||
var button := Button.new()
|
||
button.name = "Ability%d" % (index + 1)
|
||
button.custom_minimum_size = Vector2(120, 40)
|
||
button.add_theme_font_size_override("font_size", 11)
|
||
button.pressed.connect(func() -> void: player.call("activate_ability", index))
|
||
_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()
|
||
button.text = "[%d] %s\n%s" % [index + 1, ability.display_name, "GOTOWE" if reason.is_empty() else reason]
|
||
var style := _ability_ready_style if reason.is_empty() else _ability_blocked_style
|
||
button.add_theme_stylebox_override("normal", style)
|
||
button.add_theme_stylebox_override("disabled", style)
|
||
button.add_theme_stylebox_override("hover", style)
|
||
button.add_theme_color_override("font_color", Color("a5ffda"))
|
||
button.add_theme_color_override("font_disabled_color", Color("a3aebb"))
|
||
button.tooltip_text = ability.description + ("\n" + reason if not reason.is_empty() else "\nGotowe")
|
||
_ability_bar.get_parent().visible = any_equipped
|
||
|
||
func _make_ability_style(ready: bool) -> StyleBoxFlat:
|
||
var style := StyleBoxFlat.new()
|
||
style.bg_color = Color("174237") if ready else Color("202731")
|
||
style.border_color = Color("77e8bc") if ready else Color("526071")
|
||
style.set_border_width_all(2 if ready else 1)
|
||
style.set_content_margin_all(6)
|
||
return style
|