diff --git a/autoloads/save_system.gd b/autoloads/save_system.gd index 34eafeb..155b977 100644 --- a/autoloads/save_system.gd +++ b/autoloads/save_system.gd @@ -30,9 +30,9 @@ func load_game() -> bool: print("Game state loaded from: ", save_path) print("Player state: ", save_data["player_state"]) gm.player_state = save_data["player_state"] - var skills: Array[String] = [] - for skill_name in gm.player_state["unlocked_skills"]: - skills.append(skill_name) + var skills: Array[SkillData] = [] + for skill in gm.player_state["unlocked_skills"]: + skills.append(skill) gm.unlock_skills(skills) return true diff --git a/objects/ui/marketplace.tscn b/objects/ui/marketplace.tscn index 95e12e2..19e7f2d 100644 --- a/objects/ui/marketplace.tscn +++ b/objects/ui/marketplace.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=11 format=3 uid="uid://dlm2ri562fynd"] +[gd_scene load_steps=12 format=3 uid="uid://dlm2ri562fynd"] [ext_resource type="Script" uid="uid://duifmqjarjpuv" path="res://scripts/ui/marketplace.gd" id="1_ncpyg"] [ext_resource type="FontFile" uid="uid://xm0vbusjr7b7" path="res://fonts/PressStart2P-Regular.ttf" id="2_ho1tm"] @@ -9,11 +9,12 @@ [ext_resource type="Resource" uid="uid://cx5fsbexblp60" path="res://resources/skills/ice_brick.tres" id="6_6665y"] [ext_resource type="Resource" uid="uid://d3bjre2etov1n" path="res://resources/skills/magnetic.tres" id="7_ukny6"] [ext_resource type="PackedScene" uid="uid://dtl03rod7l2t0" path="res://objects/ui/marketplace_button.tscn" id="9_ode10"] +[ext_resource type="PackedScene" uid="uid://ceqjwmihj70lt" path="res://objects/ui/skill_button.tscn" id="10_c7w2b"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ode10"] bg_color = Color(0, 0, 0, 1) -[node name="Marketplace" type="Control" node_paths=PackedStringArray("root", "grid")] +[node name="Marketplace" type="Control" node_paths=PackedStringArray("root", "to_unlock_grid", "unlocked_grid")] layout_mode = 3 anchors_preset = 15 anchor_right = 1.0 @@ -23,9 +24,11 @@ grow_vertical = 2 script = ExtResource("1_ncpyg") root = NodePath(".") skill_data = Array[ExtResource("2_pg4mc")]([ExtResource("3_bk5yi"), ExtResource("4_tx0n3"), ExtResource("5_fqx8e"), ExtResource("6_6665y"), ExtResource("7_ukny6")]) -grid = NodePath("PanelContainer/MarginContainer/VBoxContainer/GridContainer") +to_unlock_grid = NodePath("PanelContainer/MarginContainer/VBoxContainer/ToUnlockGridContainer") +unlocked_grid = NodePath("PanelContainer/MarginContainer/VBoxContainer/UnlockedGridContainer") font = ExtResource("2_ho1tm") marketplace_button = ExtResource("9_ode10") +skill_button = ExtResource("10_c7w2b") [node name="PanelContainer" type="PanelContainer" parent="."] layout_mode = 1 @@ -55,7 +58,14 @@ vertical_alignment = 1 justification_flags = 162 uppercase = true -[node name="GridContainer" type="GridContainer" parent="PanelContainer/MarginContainer/VBoxContainer"] +[node name="ToUnlockGridContainer" type="GridContainer" parent="PanelContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 2 +theme_override_constants/h_separation = 4 +theme_override_constants/v_separation = 16 +columns = 3 + +[node name="UnlockedGridContainer" type="GridContainer" parent="PanelContainer/MarginContainer/VBoxContainer"] layout_mode = 2 size_flags_vertical = 2 theme_override_constants/h_separation = 4 diff --git a/objects/ui/skill_button.tscn b/objects/ui/skill_button.tscn new file mode 100644 index 0000000..503f860 --- /dev/null +++ b/objects/ui/skill_button.tscn @@ -0,0 +1,16 @@ +[gd_scene load_steps=3 format=3 uid="uid://ceqjwmihj70lt"] + +[ext_resource type="Texture2D" uid="uid://cvhoq7aubxlmq" path="res://sprites/ui/magnetic_skill_icon.png" id="1_wnfk3"] +[ext_resource type="Script" uid="uid://0obbehfd8fki" path="res://scripts/ui/skill_button.gd" id="2_m2732"] + +[node name="SkillButton" type="Button"] +offset_right = 8.0 +offset_bottom = 8.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_font_sizes/font_size = 8 +text = "Fire brick 100" +icon = ExtResource("1_wnfk3") +flat = true +autowrap_mode = 2 +script = ExtResource("2_m2732") diff --git a/scripts/components/skill_unlocker_component.gd b/scripts/components/skill_unlocker_component.gd index a4f4006..8ef3317 100644 --- a/scripts/components/skill_unlocker_component.gd +++ b/scripts/components/skill_unlocker_component.gd @@ -15,16 +15,20 @@ func try_unlock_skill(skill_data: SkillData) -> bool: if not game_manager: return false - if game_manager.is_skill_unlocked(skill_data.name): + if game_manager.is_skill_unlocked(skill_data): return false if not has_enough_coins(skill_data.cost): return false - game_manager.remove_coins(skill_data.cost) - game_manager.current_session_state["skills_unlocked"].append(skill_data.name) - skill_manager.add_skill(skill_data) - skill_unlocked.emit(skill_data) + var skill: SkillData = skill_data + skill.level = 1 + skill.is_active = true + + game_manager.remove_coins(skill.cost) + game_manager.current_session_state["skills_unlocked"].append(skill) + skill_manager.add_skill(skill) + skill_unlocked.emit(skill) return true @@ -36,5 +40,25 @@ func unlock_all_skills() -> void: skills.append(skill.name) skill_unlocked.emit(skill) - game_manager.unlock_skills(skills) + game_manager.unlock_skills(available_skills) skill_manager.apply_unlocked_skills() + + + +func try_upgrade_skill(skill_data: SkillData) -> bool: + if not game_manager: + return false + + if not game_manager.is_skill_unlocked(skill_data): + return false + + if skill_data.level >= skill_data.max_level: + return false + + if not has_enough_coins(skill_data.cost): + return false + + game_manager.remove_coins(skill_data.cost) + skill_data.level += 1 + skill_unlocked.emit(skill_data) + return true diff --git a/scripts/console_management.gd b/scripts/console_management.gd index 31bf95b..498360e 100644 --- a/scripts/console_management.gd +++ b/scripts/console_management.gd @@ -70,12 +70,16 @@ func console_unlock_skill(skill_name: Variant) -> void: Console.print_error("Invalid skill name: " + str(skill_name)) return - game_manager.unlock_skill(skill_name) var skill_data: SkillData = skill_manager.get_skill_by_name(skill_name) + skill_data.level = 1 + if not skill_data: Console.print_error("Skill not found: " + str(skill_name)) return - skill_manager.add_skill(skill_data) + + game_manager.unlock_skill(skill_data) + skill_manager.activate_skill(skill_data) + skill_unlocker.skill_unlocked.emit(skill_data) Console.print_info("Unlocked skill: " + str(skill_name)) diff --git a/scripts/game_manager.gd b/scripts/game_manager.gd index 06dc732..fe986d7 100644 --- a/scripts/game_manager.gd +++ b/scripts/game_manager.gd @@ -68,7 +68,6 @@ func get_kid_nodes() -> Array[CollectableComponent]: return kid_nodes - func get_player_node() -> Node: for node in nodes_in_scene: if node is PlayerController: @@ -118,23 +117,24 @@ func get_lives() -> int: return player_state["lives"] -func is_skill_unlocked(skill_name: String) -> bool: - return skill_name in player_state["unlocked_skills"] or skill_name in current_session_state["skills_unlocked"] + +func is_skill_unlocked(skill: SkillData) -> bool: + return skill in player_state["unlocked_skills"] or skill in current_session_state["skills_unlocked"] -func unlock_skill(skill_name: String) -> void: - if not is_skill_unlocked(skill_name): - player_state["unlocked_skills"].append(skill_name) +func unlock_skill(skill: SkillData) -> void: + if not is_skill_unlocked(skill): + player_state["unlocked_skills"].append(skill) -func remove_skill(skill_name: String) -> void: - if is_skill_unlocked(skill_name): - player_state["unlocked_skills"].erase(skill_name) +func remove_skill(skill: SkillData) -> void: + if is_skill_unlocked(skill): + player_state["unlocked_skills"].erase(skill) -func unlock_skills(skill_names: Array[String]) -> void: - for skill_name in skill_names: - unlock_skill(skill_name) +func unlock_skills(skills: Array[SkillData]) -> void: + for skill in skills: + unlock_skill(skill) func reset_player_state() -> void: @@ -213,8 +213,8 @@ func on_level_complete() -> void: var level_index = player_state["current_level"] mark_level_complete(level_index) add_coins(current_session_state["coins_collected"]) - for skill_name in current_session_state["skills_unlocked"]: - unlock_skill(skill_name) + for skill in current_session_state["skills_unlocked"]: + unlock_skill(skill) reset_current_session_state() try_to_go_to_next_level() @@ -228,5 +228,4 @@ func get_unlocked_skills() -> Array: return skills_unlocked if not skills_unlocked: return skills_current_session - return skills_unlocked + skills_current_session diff --git a/scripts/skill_manager.gd b/scripts/skill_manager.gd index 15b4970..3b28c3e 100644 --- a/scripts/skill_manager.gd +++ b/scripts/skill_manager.gd @@ -21,11 +21,10 @@ func add_skill(skill_data: SkillData) -> void: for skill in unlocked_skills: var data = null for s in available_skills: - if s.name == skill: + if s == skill: data = s break if data and data.type == SkillData.SkillType.THROW: - print("Removing previous throw skill: ", data.name) remove_skill(data.name) var skill_instance := skill_data.node.instantiate() @@ -46,7 +45,7 @@ func add_skill(skill_data: SkillData) -> void: owner.add_child(skill_instance) active_components[skill_data.name] = skill_instance - + func remove_skill(skill_name: String) -> void: if not active_components.has(skill_name): @@ -56,12 +55,17 @@ func remove_skill(skill_name: String) -> void: if is_instance_valid(skill_instance): skill_instance.queue_free() + var skills: Array = gm.get_unlocked_skills() + for s in skills: + if s.name == skill_name: + s.is_active = false + break active_components.erase(skill_name) func apply_unlocked_skills() -> void: for skill_data in available_skills: - if gm.is_skill_unlocked(skill_data.name): + if gm.is_skill_unlocked(skill_data): print("Applying skill: ", skill_data.name) call_deferred("add_skill", skill_data) else: @@ -73,3 +77,27 @@ func get_skill_by_name(skill_name: String) -> SkillData: if skill_data.name == skill_name: return skill_data return null + + +func activate_skill(skill: SkillData) -> void: + if not active_components.has(skill.name): + if skill: + add_skill(skill) + skill.is_active = true + + +func deactivate_skill(skill: SkillData) -> void: + if active_components.has(skill.name): + remove_skill(skill.name) + if skill: + skill.is_active = false + + +func toggle_skill_activation(skill: SkillData) -> void: + if not skill: + return + + if active_components.has(skill.name): + deactivate_skill(skill) + else: + activate_skill(skill) diff --git a/scripts/ui/marketplace.gd b/scripts/ui/marketplace.gd index 2729314..172aadb 100644 --- a/scripts/ui/marketplace.gd +++ b/scripts/ui/marketplace.gd @@ -3,15 +3,19 @@ extends Node @export var root: Control @export var skill_data: Array[SkillData] = [] -@export var grid: GridContainer +@export var to_unlock_grid: GridContainer +@export var unlocked_grid: GridContainer @export var font: Font @export var skill_unlocker: SkillUnlockerComponent @export var components_to_disable: Array[Node] = [] @export var marketplace_button: PackedScene +@export var skill_button: PackedScene @onready var game_manager: GM = $"/root/GameManager" -var buttons: Array[Button] = [] + +var unlock_buttons: Array[Button] = [] +var skill_buttons: Array[SkillButton] = [] func _ready() -> void: @@ -21,13 +25,17 @@ func _ready() -> void: var skills_to_unlock: Array[SkillData] = [] for skill in skill_data: - if skill.name in game_manager.player_state['unlocked_skills']: - continue skills_to_unlock.append(skill) for skill in skills_to_unlock: create_upgrade_button(skill) + var unlocked_skills := game_manager.get_unlocked_skills() + for skill in unlocked_skills: + create_skill_button(skill) + + skill_unlocker.skill_unlocked.connect(on_skill_unlocked) + func _input(event: InputEvent) -> void: if event.is_action_pressed("show_marketplace"): @@ -45,7 +53,8 @@ func get_button_text(skill: SkillData) -> String: return tr(skill.name) + " " + str(skill.cost) -func create_upgrade_button(skill: SkillData): + +func create_upgrade_button(skill: SkillData) -> void: var button := marketplace_button.instantiate() as MarketplaceButton button.text = get_button_text(skill) button.icon = skill.icon @@ -53,13 +62,25 @@ func create_upgrade_button(skill: SkillData): button.pressed.connect(func () -> void: _on_button_pressed(skill)) - buttons.append(button) - grid.add_child(button) - grid.queue_sort() + unlock_buttons.append(button) + to_unlock_grid.add_child(button) + to_unlock_grid.queue_sort() + + +func create_skill_button(skill: SkillData) -> void: + var button := skill_button.instantiate() as SkillButton + button.skill_data = skill + button.setup() + button.pressed.connect(func() -> void: on_skill_button_pressed(button)) + button.activate() + + skill_buttons.append(button) + unlocked_grid.add_child(button) + unlocked_grid.queue_sort() func remove_button(skill: SkillData): - for child in grid.get_children(): + for child in to_unlock_grid.get_children(): if child.text == get_button_text(skill): child.queue_free() break @@ -69,6 +90,38 @@ func _on_button_pressed(skill: SkillData) -> void: if not skill_unlocker: return - if skill_unlocker.try_unlock_skill(skill): - remove_button(skill) + if game_manager.is_skill_unlocked(skill): + if skill.level < skill.max_level: + skill_unlocker.try_upgrade_skill(skill) + if not skill.is_active: + skill_unlocker.skill_manager.toggle_skill_activation(skill) + else: + skill_unlocker.skill_manager.toggle_skill_activation(skill) + else: + skill_unlocker.try_unlock_skill(skill) + + +func on_skill_unlocked(skill: SkillData) -> void: + # need to fix this method + if not skill: + return + if skill_buttons.size() == 0: + create_skill_button(skill) + + for button in skill_buttons: + if button.skill_data.is_active: + button.activate() + else: + button.deactivate() + + +func on_skill_button_pressed(button: SkillButton) -> void: + if not skill_unlocker or not button.skill_data: + return + + skill_unlocker.skill_manager.toggle_skill_activation(button.skill_data) + button.activate() + for other_button in skill_buttons: + if other_button != button: + other_button.deactivate() diff --git a/scripts/ui/skill_button.gd b/scripts/ui/skill_button.gd new file mode 100644 index 0000000..10a2831 --- /dev/null +++ b/scripts/ui/skill_button.gd @@ -0,0 +1,22 @@ +class_name SkillButton +extends Button + +@export var skill_data: SkillData + + +func setup() -> void: + if not skill_data: + return + + icon = skill_data.icon + text = tr(skill_data.name) + + +func activate() -> void: + set("theme_override_colors/font_color", Color("#49aa10")) + + +func deactivate() -> void: + set("theme_override_colors/font_color", Color("#ffffff")) + + diff --git a/scripts/ui/skill_button.gd.uid b/scripts/ui/skill_button.gd.uid new file mode 100644 index 0000000..741a43d --- /dev/null +++ b/scripts/ui/skill_button.gd.uid @@ -0,0 +1 @@ +uid://0obbehfd8fki