diff --git a/scenes/game/slot_ui.gd b/scenes/game/slot_ui.gd new file mode 100644 index 0000000..078ae83 --- /dev/null +++ b/scenes/game/slot_ui.gd @@ -0,0 +1,72 @@ +class_name SlotUI extends Control + +## Nível máximo exibido (quantidade máxima de levels preenchidos). +@export var max_levels: int = 5 + +## Container que contém os pontos de nível. +@onready var weapon_levels: HBoxContainer = $Root/WeaponLevels +## Ícone exibido dentro do quadrado (arma/passivo). +@onready var weapon_icon: TextureRect = $Root/Border/WeaponIcon + +## Se o slot está ocupado/selecionado (ícone e níveis visíveis). +var is_selected: bool = false +## Nível atual, usado para preencher os levels. +var current_level: int = 0 + + +## Estado inicial: slot vazio (sem ícone e sem níveis). +func _ready() -> void: + weapon_icon.visible = false + _set_levels_visible(false) + _set_level(0) + + +## Marca o slot como selecionado: +## - define a textura do ícone +## - torna ícone e níveis visíveis +## - aplica o nível (preenche quadrados) +func set_selected(texture: Texture2D, level: int) -> void: + is_selected = true + weapon_icon.texture = texture + weapon_icon.visible = true + _set_levels_visible(true) + _set_level(level) + + +## Limpa o slot: +## - remove o ícone +## - esconde níveis +## - reseta nível para 0 +func clear_slot() -> void: + is_selected = false + weapon_icon.texture = null + weapon_icon.visible = false + _set_levels_visible(false) + _set_level(0) + + +## Mostra/oculta o container de levels. +func _set_levels_visible(visible_value: bool) -> void: + weapon_levels.visible = visible_value + + +## Atualiza o nível atual e preenche os levels: +## - clamp em 0..max_levels +## - para cada ColorRect em `weapon_levels`, liga (branco) até o nível e desliga (alpha 0) os demais +func _set_level(level: int) -> void: + current_level = level + if current_level < 0: + current_level = 0 + if current_level > max_levels: + current_level = max_levels + var level_index: int = 0 + for child in weapon_levels.get_children(): + level_index += 1 + if child is ColorRect: + var level_indicator := child as ColorRect + if level_index <= current_level: + # ligado (branco) + level_indicator.color = Color(1, 1, 1, 1) + else: + # desligado (invisível) + level_indicator.color = Color(1, 1, 1, 0) diff --git a/scenes/game/slot_ui.gd.uid b/scenes/game/slot_ui.gd.uid new file mode 100644 index 0000000..3510001 --- /dev/null +++ b/scenes/game/slot_ui.gd.uid @@ -0,0 +1 @@ +uid://we4r4e1yduly diff --git a/scenes/game/slot_ui.tscn b/scenes/game/slot_ui.tscn new file mode 100644 index 0000000..ab6d760 --- /dev/null +++ b/scenes/game/slot_ui.tscn @@ -0,0 +1,77 @@ +[gd_scene load_steps=4 format=3 uid="uid://bp82ohb46iqkd"] + +[ext_resource type="Texture2D" uid="uid://c1godu1moy8li" path="res://assets/sprites/icons/drone-image.png" id="1_32iq7"] +[ext_resource type="Script" uid="uid://we4r4e1yduly" path="res://scenes/game/slot_ui.gd" id="1_67fst"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_32iq7"] +bg_color = Color(0.6, 0.6, 0.6, 0) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.74641997, 0.74641997, 0.7464196, 1) +corner_radius_top_left = 2 +corner_radius_top_right = 2 +corner_radius_bottom_right = 2 +corner_radius_bottom_left = 2 + +[node name="SlotUi" type="Control"] +custom_minimum_size = Vector2(42, 58) +layout_mode = 3 +anchors_preset = 0 +offset_right = 42.0 +offset_bottom = 58.0 +script = ExtResource("1_67fst") + +[node name="Root" type="VBoxContainer" parent="."] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 +alignment = 1 + +[node name="Border" type="Panel" parent="Root"] +custom_minimum_size = Vector2(42, 42) +layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_32iq7") + +[node name="WeaponIcon" type="TextureRect" parent="Root/Border"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("1_32iq7") +expand_mode = 1 +stretch_mode = 5 + +[node name="WeaponLevels" type="HBoxContainer" parent="Root"] +custom_minimum_size = Vector2(0, 12) +layout_mode = 2 +theme_override_constants/separation = 5 +alignment = 1 + +[node name="Level1" type="ColorRect" parent="Root/WeaponLevels"] +custom_minimum_size = Vector2(4, 6) +layout_mode = 2 +color = Color(0.63049096, 0.6304908, 0.6304908, 1) + +[node name="Level2" type="ColorRect" parent="Root/WeaponLevels"] +custom_minimum_size = Vector2(4, 6) +layout_mode = 2 +color = Color(0.63049096, 0.6304908, 0.6304908, 1) + +[node name="Level3" type="ColorRect" parent="Root/WeaponLevels"] +custom_minimum_size = Vector2(4, 6) +layout_mode = 2 +color = Color(0.63049096, 0.6304908, 0.6304908, 1) + +[node name="Level4" type="ColorRect" parent="Root/WeaponLevels"] +custom_minimum_size = Vector2(4, 6) +layout_mode = 2 +color = Color(0.63049096, 0.6304908, 0.6304908, 1) + +[node name="Level5" type="ColorRect" parent="Root/WeaponLevels"] +custom_minimum_size = Vector2(4, 6) +layout_mode = 2 +color = Color(0.63049096, 0.6304908, 0.6304908, 1) diff --git a/scenes/globals/gui_manager.tscn b/scenes/globals/gui_manager.tscn index e7f9c52..83158d8 100644 --- a/scenes/globals/gui_manager.tscn +++ b/scenes/globals/gui_manager.tscn @@ -1,14 +1,22 @@ -[gd_scene load_steps=42 format=3 uid="uid://kqrwytbvwyno"] +[gd_scene load_steps=50 format=3 uid="uid://kqrwytbvwyno"] [ext_resource type="Script" uid="uid://63ocy5a6gohw" path="res://scripts/globals/gui_manager.gd" id="1_01qsd"] [ext_resource type="FontFile" uid="uid://du5x3bmkjrs0k" path="res://assets/fonts/Jersey25-Regular.ttf" id="2_3da3r"] [ext_resource type="FontFile" uid="uid://d3qxk71omhsy" path="res://assets/fonts/PixelifySans-VariableFont_wght.ttf" id="2_8d174"] +[ext_resource type="Script" uid="uid://dwjobttdvs4aq" path="res://scripts/game/weapons_layer_ui.gd" id="3_3300y"] [ext_resource type="Texture2D" uid="uid://jvmip0bjonjh" path="res://assets/sprites/menus_and_misc/bg menu.jpg" id="3_mrw3c"] +[ext_resource type="PackedScene" uid="uid://bp82ohb46iqkd" path="res://scenes/game/slot_ui.tscn" id="3_v2ivh"] +[ext_resource type="Texture2D" uid="uid://b3m52u6qpfgij" path="res://assets/sprites/levels_sprites/projectile.png" id="4_k83f3"] [ext_resource type="Texture2D" uid="uid://dkjp51g1sjh21" path="res://assets/sprites/menus_and_misc/logo animado.png" id="4_rbxbw"] +[ext_resource type="Texture2D" uid="uid://drlku570m4xp1" path="res://assets/sprites/levels_sprites/turret.png" id="5_ewkre"] [ext_resource type="Theme" uid="uid://765j1dxaivoe" path="res://assets/themes/buttons/buttons_theme.tres" id="5_w8ru2"] [ext_resource type="PackedScene" uid="uid://b35fe5wdtb77i" path="res://scenes/globals/sound_icon.tscn" id="6_haemp"] +[ext_resource type="Texture2D" uid="uid://cp5wefpif1pbb" path="res://assets/sprites/icons/mine-image.png" id="6_tun2a"] +[ext_resource type="Texture2D" uid="uid://c1godu1moy8li" path="res://assets/sprites/icons/drone-image.png" id="7_d2a71"] [ext_resource type="Texture2D" uid="uid://krnpsv5q7w60" path="res://assets/sprites/menus_and_misc/creditos2.png" id="7_dc7dl"] [ext_resource type="Script" uid="uid://c8nh1wpwg1qo2" path="res://scripts/menus/input_settings.gd" id="8_aae78"] +[ext_resource type="Texture2D" uid="uid://ripgyitk8gr0" path="res://assets/sprites/icons/shield-minimalistic-svgrepo-com (1).svg" id="8_qd1n1"] +[ext_resource type="Texture2D" uid="uid://bc6h5ffy64jvv" path="res://assets/sprites/icons/speed-skiing-svgrepo-com.svg" id="9_urw70"] [ext_resource type="PackedScene" uid="uid://duqt0xpu2vl7s" path="res://scenes/menus/input_button.tscn" id="9_yixji"] [ext_resource type="PackedScene" uid="uid://bm6d5h4uxvq7x" path="res://scenes/game/select_upgrades_scene.tscn" id="10_3da3r"] [ext_resource type="AudioStream" uid="uid://ttsymx30w523" path="res://assets/sounds/menus/MENU SOUND - DOWN.wav" id="10_271i3"] @@ -243,10 +251,10 @@ anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 anchor_bottom = 0.5 -offset_left = -20.0 -offset_top = -220.0 -offset_right = 20.0 -offset_bottom = -197.0 +offset_left = -185.5 +offset_top = -262.0 +offset_right = 185.5 +offset_bottom = -222.0 grow_horizontal = 2 grow_vertical = 2 theme_override_font_sizes/font_size = 24 @@ -255,6 +263,59 @@ text = "WARNING: BLACK HOLE NEAR!!!" horizontal_alignment = 1 vertical_alignment = 1 +[node name="WeaponsLayer2" type="Control" parent="GameHud"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +script = ExtResource("3_3300y") +weapon_1_texture = ExtResource("4_k83f3") +weapon_2_texture = ExtResource("5_ewkre") +weapon_3_texture = ExtResource("6_tun2a") +weapon_4_texture = ExtResource("7_d2a71") +shield_texture = ExtResource("8_qd1n1") +speed_texture = ExtResource("9_urw70") + +[node name="MarginContainer" type="MarginContainer" parent="GameHud/WeaponsLayer2"] +layout_mode = 1 +offset_right = 250.0 +offset_bottom = 86.0 +scale = Vector2(0.798965, 0.7948529) +theme_override_constants/margin_left = 24 +theme_override_constants/margin_top = 58 + +[node name="VBoxContainer" type="VBoxContainer" parent="GameHud/WeaponsLayer2/MarginContainer"] +layout_mode = 2 + +[node name="WeaponsRow" type="HBoxContainer" parent="GameHud/WeaponsLayer2/MarginContainer/VBoxContainer"] +layout_mode = 2 +theme_override_constants/separation = 8 + +[node name="SlotUi" parent="GameHud/WeaponsLayer2/MarginContainer/VBoxContainer/WeaponsRow" instance=ExtResource("3_v2ivh")] +layout_mode = 2 + +[node name="SlotUi2" parent="GameHud/WeaponsLayer2/MarginContainer/VBoxContainer/WeaponsRow" instance=ExtResource("3_v2ivh")] +layout_mode = 2 + +[node name="SlotUi3" parent="GameHud/WeaponsLayer2/MarginContainer/VBoxContainer/WeaponsRow" instance=ExtResource("3_v2ivh")] +layout_mode = 2 + +[node name="SlotUi4" parent="GameHud/WeaponsLayer2/MarginContainer/VBoxContainer/WeaponsRow" instance=ExtResource("3_v2ivh")] +layout_mode = 2 + +[node name="PassivesRow" type="HBoxContainer" parent="GameHud/WeaponsLayer2/MarginContainer/VBoxContainer"] +layout_mode = 2 +theme_override_constants/separation = 8 + +[node name="SlotPassive1" parent="GameHud/WeaponsLayer2/MarginContainer/VBoxContainer/PassivesRow" instance=ExtResource("3_v2ivh")] +layout_mode = 2 + +[node name="SlotPassive2" parent="GameHud/WeaponsLayer2/MarginContainer/VBoxContainer/PassivesRow" instance=ExtResource("3_v2ivh")] +layout_mode = 2 + [node name="MainMenu" type="CanvasLayer" parent="."] visible = false diff --git a/scripts/game/weapons_layer_ui.gd b/scripts/game/weapons_layer_ui.gd new file mode 100644 index 0000000..6f63188 --- /dev/null +++ b/scripts/game/weapons_layer_ui.gd @@ -0,0 +1,111 @@ +class_name WeaponsLayerUI extends Control + +# Texturas dos ícones exibidos em cada slot. +@export var weapon_1_texture: Texture2D +@export var weapon_2_texture: Texture2D +@export var weapon_3_texture: Texture2D +@export var weapon_4_texture: Texture2D +@export var shield_texture: Texture2D +@export var speed_texture: Texture2D + +# Containers na cena que possuem os SlotUI. +@onready var weapons_row: HBoxContainer = $MarginContainer/VBoxContainer/WeaponsRow +@onready var passives_row: HBoxContainer = $MarginContainer/VBoxContainer/PassivesRow + +# Cache dos SlotUI para acesso por índice. +var weapon_slots: Array[SlotUI] = [] +var passive_slots: Array[SlotUI] = [] + + +func _ready() -> void: + # Monta cache, conecta sinal do PlayerUpgrades e faz o primeiro refresh da UI. + _cache_slots() + _bind_signals() + _refresh_weapons() + _refresh_passives() + + +## Coleta apenas filhos do tipo SlotUI (ignora outros nós decorativos). +func _cache_slots() -> void: + weapon_slots.clear() + for child in weapons_row.get_children(): + if child is SlotUI: + weapon_slots.append(child) + passive_slots.clear() + for child in passives_row.get_children(): + if child is SlotUI: + passive_slots.append(child) + + +## Conecta ao sinal global para atualizar a UI sempre que um upgrade mudar. +func _bind_signals() -> void: + if get_tree().root.has_node("PlayerUpgrades"): + if not PlayerUpgrades.stats_updated.is_connected(_on_upgrades_changed): + PlayerUpgrades.stats_updated.connect(_on_upgrades_changed) + + +## Recria o estado visual de armas e passivos com base nos níveis atuais. +func _on_upgrades_changed() -> void: + _refresh_weapons() + _refresh_passives() + + +## Lê níveis das armas ativas no PlayerUpgrades e aplica no slot equivalente. +func _refresh_weapons() -> void: + var weapon1 := _get_upgrade_level("active_weapon_1_level", 0) + var weapon2 := _get_upgrade_level("active_weapon_2_level", 0) + var weapon3 := _get_upgrade_level("active_weapon_3_level", 0) + var weapon4 := _get_upgrade_level("active_weapon_4_level", 0) + _set_slot_from_level(0, weapon_1_texture, weapon1) + _set_slot_from_level(1, weapon_2_texture, weapon2) + _set_slot_from_level(2, weapon_3_texture, weapon3) + _set_slot_from_level(3, weapon_4_texture, weapon4) + + +## Lê níveis dos passivos no PlayerUpgrades e aplica no slot equivalente. +func _refresh_passives() -> void: + var shield_level := _get_upgrade_level("passive_shield_level", 0) + var speed_level := _get_upgrade_level("passive_speed_level", 0) + _set_passive_slot_from_level(0, shield_texture, shield_level) + _set_passive_slot_from_level(1, speed_texture, speed_level) + + +## Atualiza um slot de arma: + # - Se level > 0: exibe ícone e preenche níveis + # - Caso contrário: limpa o slot +func _set_slot_from_level(index: int, texture: Texture2D, level: int) -> void: + if index < 0: + return + if index >= weapon_slots.size(): + return + if level > 0 and texture != null: + weapon_slots[index].set_selected(texture, level) + else: + weapon_slots[index].clear_slot() + + +## Atualiza um slot de passivos: + # - Se level > 0: exibe ícone e preenche níveis + # - Caso contrário: limpa o slot +func _set_passive_slot_from_level(index: int, texture: Texture2D, level: int) -> void: + if index < 0: + return + if index >= passive_slots.size(): + return + if level > 0 and texture != null: + passive_slots[index].set_selected(texture, level) + else: + passive_slots[index].clear_slot() + + +## Lê dinamicamente os campos de upgrades do PlayerUpgrades (ex.: "active_weapon_1_level"). +# Retorna int (aceita int/float) ou default_level caso não exista/esteja inválido, por segurança. +func _get_upgrade_level(upgrade_field_name: String, default_level: int) -> int: + if not get_tree().root.has_node("PlayerUpgrades"): + return default_level + var upgrade_default_level = PlayerUpgrades.get(upgrade_field_name) + if typeof(upgrade_default_level) == TYPE_INT: + return int(upgrade_default_level) + if typeof(upgrade_default_level) == TYPE_FLOAT: + return int(upgrade_default_level) + return default_level diff --git a/scripts/game/weapons_layer_ui.gd.uid b/scripts/game/weapons_layer_ui.gd.uid new file mode 100644 index 0000000..23a9ed4 --- /dev/null +++ b/scripts/game/weapons_layer_ui.gd.uid @@ -0,0 +1 @@ +uid://dwjobttdvs4aq diff --git a/scripts/player/player_upgrades.gd b/scripts/player/player_upgrades.gd index 84b6e8f..2a4803b 100644 --- a/scripts/player/player_upgrades.gd +++ b/scripts/player/player_upgrades.gd @@ -25,7 +25,7 @@ var base_damage_rate: float = 500.0 var base_max_acceleration: float = 1000.0 # Nível atual da Arma Ativa -var active_weapon_1_level: int = 0 +var active_weapon_1_level: int = 1 var active_weapon_2_level: int = 0 var active_weapon_3_level: int = 0 var active_weapon_4_level: int = 0 @@ -99,7 +99,7 @@ func get_effective_max_acceleration() -> float: ## Reseta todos os níveis de upgrades (ativos e passivos) para 0 e emite o sinal ## stats_updated. func reset() -> void: - active_weapon_1_level = 0 + active_weapon_1_level = 1 active_weapon_2_level = 0 active_weapon_3_level = 0 active_weapon_4_level = 0