From 09fd671e70daf5504d689a64ccb0aad2ed758a34 Mon Sep 17 00:00:00 2001 From: Kellan KOZUME Date: Sat, 18 Apr 2026 18:23:02 -0400 Subject: [PATCH] feat(minigame): implement wire puzzle, player lock, and HUD integration --- assets/tilesets/entrepot-tilesets.png | Bin 0 -> 6274 bytes assets/tilesets/entrepot-tilesets.png.import | 40 +++ autoloads/game_state.gd | 23 +- entities/npcs/vrac7/vrac7.gd | 130 +++++++++- entities/player/player.gd | 7 + entities/player/player.tscn | 18 +- levels/entrepot/entrepot.gd | 14 + levels/entrepot/entrepot.gd.uid | 1 + levels/entrepot/entrepot.tscn | 203 ++++++++++++++- levels/repair_zone.gd | 16 +- project.godot | 3 +- ui/dialogue_box.tscn | 1 + ui/hud.gd | 20 ++ ui/hud.tscn | 52 ++-- ui/minigame/minigame.gd | 0 ui/minigame/repair_minigame.gd | 243 ++++++++++++++++++ ...minigame.gd.uid => repair_minigame.gd.uid} | 0 ui/minigame/repair_minigame.tscn | 45 ++++ 18 files changed, 764 insertions(+), 52 deletions(-) create mode 100755 assets/tilesets/entrepot-tilesets.png create mode 100644 assets/tilesets/entrepot-tilesets.png.import create mode 100644 levels/entrepot/entrepot.gd create mode 100644 levels/entrepot/entrepot.gd.uid delete mode 100644 ui/minigame/minigame.gd create mode 100644 ui/minigame/repair_minigame.gd rename ui/minigame/{minigame.gd.uid => repair_minigame.gd.uid} (100%) create mode 100644 ui/minigame/repair_minigame.tscn diff --git a/assets/tilesets/entrepot-tilesets.png b/assets/tilesets/entrepot-tilesets.png new file mode 100755 index 0000000000000000000000000000000000000000..45e1ad41f90867ec398b4e87cca299bbbf151377 GIT binary patch literal 6274 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 Ay8r+H literal 0 HcmV?d00001 diff --git a/assets/tilesets/entrepot-tilesets.png.import b/assets/tilesets/entrepot-tilesets.png.import new file mode 100644 index 0000000..d3da245 --- /dev/null +++ b/assets/tilesets/entrepot-tilesets.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bbr6t3088svah" +path="res://.godot/imported/entrepot-tilesets.png-e3f6686008bed17574a462f3ad7205e0.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/tilesets/entrepot-tilesets.png" +dest_files=["res://.godot/imported/entrepot-tilesets.png-e3f6686008bed17574a462f3ad7205e0.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/autoloads/game_state.gd b/autoloads/game_state.gd index 5b8709a..9800e08 100644 --- a/autoloads/game_state.gd +++ b/autoloads/game_state.gd @@ -13,11 +13,18 @@ var repaired := { "iris3": false, } var inventory := {} +var flags := {} + +func get_flag(key: String) -> bool: + return flags.get(key, false) + +func set_flag(key: String, value: bool) -> void: + flags[key] = value # Items -func add_item(id: String) -> void: +func add_item(id: String, amount: int = 1) -> void: if inventory.has(id): - inventory[id] += 1 + inventory[id] += amount inventory_changed.emit() else: inventory[id] = 1 @@ -27,11 +34,11 @@ func add_item(id: String) -> void: func has_item(id: String) -> bool: return inventory.get(id, 0) > 0 -func remove_item(id: String) -> void: - if has_item(id): - inventory[id] -= 1 - if inventory[id] <= 0: - inventory.erase(id) +func remove_item(item_id: String, amount: int) -> void: + if inventory.has(item_id): + inventory[item_id] -= amount + if inventory[item_id] <= 0: + inventory.erase(item_id) inventory_changed.emit() # Robots repairs @@ -50,6 +57,6 @@ func complete_repair(npc_id: String) -> void: # Consomme les pièces var required = REPAIR_REQUIREMENTS[npc_id] for item_id in required: - remove_item(item_id) + remove_item(item_id, required[item_id]) repaired[npc_id] = true print("Réparation terminée : ", npc_id) diff --git a/entities/npcs/vrac7/vrac7.gd b/entities/npcs/vrac7/vrac7.gd index afc6495..025c0da 100644 --- a/entities/npcs/vrac7/vrac7.gd +++ b/entities/npcs/vrac7/vrac7.gd @@ -1,31 +1,135 @@ extends Area2D - class_name Vrac7 -@export var prompt_text : String = "[E] Parler" +@export var prompt_text: String = "[E] Parler" + +# ── Dialogues ──────────────────────────────────────────────────────────────── -# Dialogue initial — avant réparation const DIALOGUE_INTRO := [ { "name": "VRAC-7", "text": "Toi... tu es nouveau ? Non, attends — SCRAP-09 ? Tu as dormi longtemps. Très longtemps." }, { "name": "VRAC-7", "text": "Je suis coincé sous cette étagère depuis... je ne sais plus. Tu peux m'aider ?" }, { "name": "VRAC-7", "text": "Il me faut 1 engrenage et 1 câble. J'en ai vu par là dans l'entrepôt." }, ] -# Dialogue après réparation -const DIALOGUE_REPAIRED := [ - { "name": "VRAC-7", "text": "Je me souviens du dernier jour. Ils ont éteint les lumières en partant." }, - { "name": "VRAC-7", "text": "Mais ils ont laissé les générateurs allumés. Je crois que c'était intentionnel." }, - { "name": "VRAC-7", "text": "L'atelier est par là. Prends la clé — tu en auras besoin." }, +const DIALOGUE_MISSING_ITEMS := [ + { "name": "VRAC-7", "text": "Pas encore les pièces ? L'entrepôt est grand." }, + { "name": "VRAC-7", "text": "Les engrenages sont tombés derrière les étagères du fond. Les câbles, je les ai vus rouler vers la sortie ouest le jour où tout s'est effondré." }, ] +const DIALOGUE_HAS_ITEMS := [ + { "name": "VRAC-7", "text": "Tu les as. Bien. Connecte les circuits — mon système moteur est encore là, quelque part." }, +] + +const DIALOGUE_POST_REPAIR := [ + { "name": "VRAC-7", "text": "Ah. Voilà. Je n'avais pas oublié ce que c'était de bouger, mais... c'est différent de s'en souvenir." }, + { "name": "VRAC-7", "text": "Je me souviens du dernier jour. Ils ont éteint les lumières en partant. Mais ils ont laissé les générateurs allumés. Je crois que c'était intentionnel." }, + { "name": "VRAC-7", "text": "L'atelier est par là. La clé magnétique — tiens. Elle était dans ma pince depuis le début. Je la gardais pour quelqu'un." }, +] + +const DIALOGUE_AFTER_ATELIER := [ + { "name": "VRAC-7", "text": "Tu as trouvé ce que tu cherchais ? Moi je reste ici." }, + { "name": "VRAC-7", "text": "Pas par obligation. C'est juste que... cet endroit est à nous maintenant. Quelqu'un doit s'en occuper." }, +] + +# ── Items requis ────────────────────────────────────────────────────────────── + +const REQUIRED_ITEMS := { + "engrenage": 1, +} + +# ── Lifecycle ───────────────────────────────────────────────────────────────── + +func _ready() -> void: + body_entered.connect(_on_body_entered) + body_exited.connect(_on_body_exited) + +func _on_body_entered(body: Node) -> void: + if body.is_in_group("player"): + var hud: HUD = get_tree().get_first_node_in_group("hud") + if hud: + hud.show_prompt(prompt_text) + +func _on_body_exited(body: Node) -> void: + if body.is_in_group("player"): + var hud: HUD = get_tree().get_first_node_in_group("hud") + if hud: + hud.hide_prompt() + +# ── Interaction principale ──────────────────────────────────────────────────── + func interact() -> void: - var hud : HUD = get_tree().get_first_node_in_group("hud") + var hud: HUD = get_tree().get_first_node_in_group("hud") if hud: hud.hide_prompt() - var dialogue_box : DialogueBox = get_tree().get_first_node_in_group("dialogue_box") + + var dialogue_box: DialogueBox = get_tree().get_first_node_in_group("dialogue_box") if not dialogue_box: return - if GameState.repaired.get("vrac7", false): - dialogue_box.start(DIALOGUE_REPAIRED) - else: + + # État 1 — Déjà réparé, joueur revient après avoir visité l'atelier + if GameState.get_flag("vrac7_repaired") and GameState.get_flag("visited_atelier"): + dialogue_box.start(DIALOGUE_AFTER_ATELIER) + return + + # État 2 — Déjà réparé, dialogue post-réparation standard + if GameState.get_flag("vrac7_repaired"): + dialogue_box.start(DIALOGUE_POST_REPAIR) + return + + # État 3 — Possède les items → lancer le mini-jeu + if _has_required_items(): + dialogue_box.start(DIALOGUE_HAS_ITEMS) + dialogue_box.dialogue_finished.connect(_start_minigame, CONNECT_ONE_SHOT) + return + + # État 4 — Premier contact (jamais parlé) + if not GameState.get_flag("vrac7_met"): + GameState.set_flag("vrac7_met", true) dialogue_box.start(DIALOGUE_INTRO) + return + + # État 5 — Revient sans les items + dialogue_box.start(DIALOGUE_MISSING_ITEMS) + +# ── Mini-jeu ────────────────────────────────────────────────────────────────── + +func _start_minigame() -> void: + var dialogue_box: DialogueBox = get_tree().get_first_node_in_group("dialogue_box") + if dialogue_box: + dialogue_box.hide() + var minigame_node := preload("res://ui/minigame/repair_minigame.tscn").instantiate() + get_tree().root.add_child(minigame_node) + var minigame := minigame_node as RepairMinigame + if minigame == null: + return + minigame.repair_complete.connect(_on_repair_done, CONNECT_ONE_SHOT) + minigame.open("vrac7") + +func _on_repair_done() -> void: + # Consomme les items + GameState.remove_item("engrenage", 1) + GameState.remove_item("cable", 1) + + # Donne la clé de l'atelier + GameState.add_item("cle_atelier", 1) + GameState.set_flag("vrac7_repaired", true) + + # LOG système + var hud: HUD = get_tree().get_first_node_in_group("hud") + if hud: + hud.show_log("Unité VRAC-7 : réparation complète. Statut : opérationnel.") + await get_tree().create_timer(0.5).timeout + hud.show_log("Clé magnétique obtenue. Accès atelier déverrouillé.") + + # Dialogue post-réparation + var dialogue_box: DialogueBox = get_tree().get_first_node_in_group("dialogue_box") + if dialogue_box: + dialogue_box.start(DIALOGUE_POST_REPAIR) + +# ── Helpers ─────────────────────────────────────────────────────────────────── + +func _has_required_items() -> bool: + for item_id in REQUIRED_ITEMS: + if GameState.inventory.get(item_id, 0) < REQUIRED_ITEMS[item_id]: + return false + return true diff --git a/entities/player/player.gd b/entities/player/player.gd index 2eaf4eb..d5fe6e0 100644 --- a/entities/player/player.gd +++ b/entities/player/player.gd @@ -9,8 +9,15 @@ const SPEED := 120 var last_direction := Vector2.DOWN var interactable : Node = null +var is_locked := false : + set(value): + is_locked = value + if value: + velocity = Vector2.ZERO + sprite.play("idle_" + _dir_name(last_direction)) func _ready() -> void: + add_to_group("player") interaction_area.area_entered.connect(_on_interaction_area_area_entered) interaction_area.area_exited.connect(_on_interaction_area_area_exited) diff --git a/entities/player/player.tscn b/entities/player/player.tscn index 3c9bd68..6dd9a42 100644 --- a/entities/player/player.tscn +++ b/entities/player/player.tscn @@ -508,31 +508,29 @@ animations = [{ [sub_resource type="RectangleShape2D" id="RectangleShape2D_bectd"] size = Vector2(45.375, 42.84375) -[node name="Player" type="Node2D" unique_id=628518902] - -[node name="CharacterBody2D" type="CharacterBody2D" parent="." unique_id=92363508] +[node name="CharacterBody2D" type="CharacterBody2D" unique_id=1424887591] collision_layer = 3 script = ExtResource("1_fkugw") -[node name="CollisionShape2D" type="CollisionShape2D" parent="CharacterBody2D" unique_id=865652003] +[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=2097287881] shape = SubResource("CapsuleShape2D_26q78") -[node name="Camera2D" type="Camera2D" parent="CharacterBody2D" unique_id=1653637445] +[node name="Camera2D" type="Camera2D" parent="." unique_id=1266755049] zoom = Vector2(0.75, 0.75) position_smoothing_enabled = true -[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="CharacterBody2D" unique_id=1859344504] -position = Vector2(-1, -12) +[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." unique_id=1926532622] +position = Vector2(-1, -8) sprite_frames = SubResource("SpriteFrames_ix1gt") animation = &"walk_right" autoplay = "idle_down" -[node name="InteractionArea" type="Area2D" parent="CharacterBody2D" unique_id=22124935] +[node name="InteractionArea" type="Area2D" parent="." unique_id=1623204784] position = Vector2(-1, -12) collision_layer = 16 collision_mask = 12 -[node name="CollisionShape2D" type="CollisionShape2D" parent="CharacterBody2D/InteractionArea" unique_id=51125783] -position = Vector2(2, 7) +[node name="CollisionShape2D" type="CollisionShape2D" parent="InteractionArea" unique_id=446150610] +position = Vector2(1, 9) shape = SubResource("RectangleShape2D_bectd") debug_color = Color(0.9411765, 0, 0.29411766, 0.19607843) diff --git a/levels/entrepot/entrepot.gd b/levels/entrepot/entrepot.gd new file mode 100644 index 0000000..07413d3 --- /dev/null +++ b/levels/entrepot/entrepot.gd @@ -0,0 +1,14 @@ +extends Node2D + +func _ready() -> void: + print(get_tree().get_nodes_in_group("dialogue_box")) + await get_tree().process_frame + for zone in get_tree().get_nodes_in_group("repair_zones"): + if zone is RepairZone: + zone.repair_requested.connect(_on_repair_requested) + + +func _on_repair_requested(npc_id: String) -> void: + # Test de trigger + GameState.complete_repair(npc_id) + print("Flux réparation OK pour : ", npc_id) diff --git a/levels/entrepot/entrepot.gd.uid b/levels/entrepot/entrepot.gd.uid new file mode 100644 index 0000000..ec3e600 --- /dev/null +++ b/levels/entrepot/entrepot.gd.uid @@ -0,0 +1 @@ +uid://e22s84h1jwke diff --git a/levels/entrepot/entrepot.tscn b/levels/entrepot/entrepot.tscn index 8563968..0e7c310 100644 --- a/levels/entrepot/entrepot.tscn +++ b/levels/entrepot/entrepot.tscn @@ -1,3 +1,204 @@ -[gd_scene format=3 uid="uid://kmybl0c637as"] +[gd_scene format=4 uid="uid://kmybl0c637as"] + +[ext_resource type="Script" uid="uid://e22s84h1jwke" path="res://levels/entrepot/entrepot.gd" id="1_ptc2q"] +[ext_resource type="Texture2D" uid="uid://bbr6t3088svah" path="res://assets/tilesets/entrepot-tilesets.png" id="1_qvgxo"] +[ext_resource type="PackedScene" uid="uid://mh3msmluve7p" path="res://entities/player/player.tscn" id="2_n70cd"] +[ext_resource type="PackedScene" uid="uid://bb3olg2rlygdc" path="res://entities/npcs/vrac7/vrac7.tscn" id="3_jr8qv"] +[ext_resource type="PackedScene" uid="uid://jrjxu1xfx0ud" path="res://ui/dialogue_box.tscn" id="5_s155k"] +[ext_resource type="PackedScene" uid="uid://o7qrmpywwhu8" path="res://ui/hud.tscn" id="6_kejd5"] +[ext_resource type="PackedScene" uid="uid://grs5ypwkxv3x" path="res://entities/items/item.tscn" id="6_srx2q"] + +[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_n70cd"] +texture = ExtResource("1_qvgxo") +texture_region_size = Vector2i(32, 32) +0:5/size_in_atlas = Vector2i(2, 1) +0:5/0 = 0 +0:6/0 = 0 +1:6/0 = 0 +4:5/0 = 0 +4:6/0 = 0 +0:3/0 = 0 +0:3/0/terrain_set = 0 +0:3/0/terrain = 0 +0:3/0/terrains_peering_bit/right_side = 0 +0:3/0/terrains_peering_bit/bottom_right_corner = 0 +0:3/0/terrains_peering_bit/bottom_side = 0 +0:3/0/terrains_peering_bit/bottom_left_corner = 0 +0:3/0/terrains_peering_bit/left_side = 0 +0:3/0/terrains_peering_bit/top_left_corner = 0 +0:3/0/terrains_peering_bit/top_side = 0 +0:3/0/terrains_peering_bit/top_right_corner = 0 +0:4/size_in_atlas = Vector2i(2, 1) +0:4/0 = 0 +1:3/0 = 0 +1:3/0/terrain_set = 0 +1:3/0/terrain = 0 +1:3/0/terrains_peering_bit/right_side = 0 +1:3/0/terrains_peering_bit/bottom_right_corner = 0 +1:3/0/terrains_peering_bit/bottom_side = 0 +1:3/0/terrains_peering_bit/bottom_left_corner = 0 +1:3/0/terrains_peering_bit/left_side = 0 +1:3/0/terrains_peering_bit/top_left_corner = 0 +1:3/0/terrains_peering_bit/top_side = 0 +1:3/0/terrains_peering_bit/top_right_corner = 0 +2:3/0 = 0 +2:3/0/terrain_set = 0 +2:3/0/terrain = 0 +2:3/0/terrains_peering_bit/right_side = 0 +2:3/0/terrains_peering_bit/bottom_right_corner = 0 +2:3/0/terrains_peering_bit/bottom_side = 0 +2:3/0/terrains_peering_bit/bottom_left_corner = 0 +2:3/0/terrains_peering_bit/left_side = 0 +2:3/0/terrains_peering_bit/top_left_corner = 0 +2:3/0/terrains_peering_bit/top_side = 0 +2:3/0/terrains_peering_bit/top_right_corner = 0 +0:1/0 = 0 +0:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(8, -16, 16, -16, 16, 16, 8, 16) +0:2/0 = 0 +0:2/0/terrain_set = 0 +0:2/0/terrain = 0 +0:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) +0:2/0/terrains_peering_bit/right_side = 0 +0:2/0/terrains_peering_bit/bottom_right_corner = 0 +0:2/0/terrains_peering_bit/bottom_side = 0 +0:2/0/terrains_peering_bit/bottom_left_corner = 0 +0:2/0/terrains_peering_bit/left_side = 0 +0:2/0/terrains_peering_bit/top_left_corner = 0 +0:2/0/terrains_peering_bit/top_side = 0 +0:2/0/terrains_peering_bit/top_right_corner = 0 +1:1/0 = 0 +1:1/0/terrain_set = 0 +1:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 8, 16, 8, 16, 16, -16, 16) +1:1/0/terrains_peering_bit/top_left_corner = 0 +1:1/0/terrains_peering_bit/top_side = 0 +1:1/0/terrains_peering_bit/top_right_corner = 0 +1:2/0 = 0 +1:2/0/terrain_set = 0 +1:2/0/terrain = 0 +1:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) +1:2/0/terrains_peering_bit/right_side = 0 +1:2/0/terrains_peering_bit/bottom_right_corner = 0 +1:2/0/terrains_peering_bit/bottom_side = 0 +1:2/0/terrains_peering_bit/bottom_left_corner = 0 +1:2/0/terrains_peering_bit/left_side = 0 +1:2/0/terrains_peering_bit/top_left_corner = 0 +1:2/0/terrains_peering_bit/top_side = 0 +1:2/0/terrains_peering_bit/top_right_corner = 0 +2:1/0 = 0 +2:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -16, -16, -16, -16, 16, -8, 16) +2:2/0 = 0 +2:2/0/terrain_set = 0 +2:2/0/terrain = 0 +2:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) +2:2/0/terrains_peering_bit/right_side = 0 +2:2/0/terrains_peering_bit/bottom_right_corner = 0 +2:2/0/terrains_peering_bit/bottom_side = 0 +2:2/0/terrains_peering_bit/bottom_left_corner = 0 +2:2/0/terrains_peering_bit/left_side = 0 +2:2/0/terrains_peering_bit/top_left_corner = 0 +2:2/0/terrains_peering_bit/top_side = 0 +2:2/0/terrains_peering_bit/top_right_corner = 0 +3:1/0 = 0 +3:1/0/terrain_set = 0 +3:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(8, -16, 16, -16, 16, 16, 8, 16) +3:1/0/terrains_peering_bit/top_right_corner = 0 +3:2/size_in_atlas = Vector2i(1, 2) +3:2/0 = 0 +3:2/0/terrain_set = 0 +3:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 20, 16, 20, 16, 32, -16, 32) +4:1/0 = 0 +4:1/0/terrain_set = 0 +4:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -16, -16, -16, -16, 16, -8, 16) +4:1/0/terrains_peering_bit/top_left_corner = 0 +4:2/0 = 0 +4:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-12, -4, 12, -4, 12, 12, -12, 12) +2:0/0 = 0 +2:0/0/terrain_set = 0 +2:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) +2:0/0/terrains_peering_bit/bottom_left_corner = 0 +2:0/0/terrains_peering_bit/left_side = 0 +2:0/0/terrains_peering_bit/top_left_corner = 0 +2:0/0/terrains_peering_bit/top_side = 0 +2:0/0/terrains_peering_bit/top_right_corner = 0 +3:0/0 = 0 +3:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(8, -16, 16, -16, 16, 16, 8, 16) +4:0/0 = 0 +4:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -16, -16, -16, -16, 16, -8, 16) +0:0/0 = 0 +0:0/0/terrain_set = 0 +0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) +0:0/0/terrains_peering_bit/right_side = 0 +0:0/0/terrains_peering_bit/bottom_right_corner = 0 +0:0/0/terrains_peering_bit/top_left_corner = 0 +0:0/0/terrains_peering_bit/top_side = 0 +0:0/0/terrains_peering_bit/top_right_corner = 0 +2:5/size_in_atlas = Vector2i(2, 1) +2:5/0 = 0 +2:6/size_in_atlas = Vector2i(2, 1) +2:6/0 = 0 + +[sub_resource type="TileSet" id="TileSet_jr8qv"] +physics_layer_0/collision_layer = 1 +physics_layer_0/collision_mask = 0 +terrain_set_0/mode = 0 +terrain_set_0/terrain_0/name = "Entrepot" +terrain_set_0/terrain_0/color = Color(0.5, 0.34375, 0.25, 1) +sources/0 = SubResource("TileSetAtlasSource_n70cd") [node name="Entrepot" type="Node2D" unique_id=981054710] +script = ExtResource("1_ptc2q") + +[node name="Hud" parent="." unique_id=1774402684 instance=ExtResource("6_kejd5")] +position = Vector2(199, 301) + +[node name="DialogueBox" parent="." unique_id=1374394268 instance=ExtResource("5_s155k")] +position = Vector2(-118, 137) + +[node name="Vrac7" parent="." unique_id=829712169 instance=ExtResource("3_jr8qv")] +z_index = 500 +position = Vector2(56, 379) + +[node name="Map" type="Node" parent="." unique_id=306161900] + +[node name="Fix" type="TileMapLayer" parent="Map" unique_id=451440612] +z_index = 2 +tile_map_data = PackedByteArray("AAAAACYAAAABAAEAAAAeACYAAAABAAEAAAAeACgAAAAAAAIAAAAAACgAAAAAAAIAAAA=") +tile_set = SubResource("TileSet_jr8qv") + +[node name="Ground" type="TileMapLayer" parent="Map" unique_id=1677946938] +tile_map_data = PackedByteArray("AAAeAAIAAAAAAAIAAAAAAAIAAAAAAAIAAAAeACYAAAABAAEAAAAAAAYAAAACAAMAAAAAAAgAAAACAAMAAAAAAAoAAAACAAMAAAAAAAwAAAACAAMAAAAcAAYAAAACAAMAAAAcAAgAAAACAAMAAAAcAAoAAAACAAMAAAAcAAwAAAACAAMAAAAcAA4AAAACAAMAAAAaAA4AAAACAAMAAAAYAA4AAAACAAMAAAAWAA4AAAACAAMAAAAUAA4AAAACAAMAAAASAA4AAAACAAMAAAAOAA4AAAACAAMAAAAMAA4AAAACAAMAAAAKAA4AAAACAAMAAAAIAA4AAAACAAMAAAAGAA4AAAACAAMAAAAEAA4AAAACAAMAAAACAA4AAAACAAMAAAAAAA4AAAACAAMAAAACAAYAAAACAAMAAAAEAAYAAAACAAMAAAAGAAYAAAACAAMAAAAIAAYAAAACAAMAAAAKAAYAAAACAAMAAAAMAAYAAAACAAMAAAAOAAYAAAACAAMAAAAQAAYAAAACAAMAAAASAAYAAAACAAMAAAAUAAYAAAACAAMAAAAWAAYAAAACAAMAAAAYAAYAAAACAAMAAAAaAAYAAAACAAMAAAACAAgAAAACAAMAAAAEAAgAAAACAAMAAAAGAAgAAAACAAMAAAAIAAgAAAACAAMAAAAKAAgAAAACAAMAAAAMAAgAAAACAAMAAAAOAAgAAAACAAMAAAAQAAgAAAACAAMAAAASAAgAAAACAAMAAAAUAAgAAAACAAMAAAAWAAgAAAACAAMAAAAYAAgAAAACAAMAAAAaAAgAAAACAAMAAAAaAAoAAAACAAMAAAAYAAoAAAACAAMAAAAWAAoAAAACAAMAAAAUAAoAAAACAAMAAAASAAoAAAACAAMAAAAQAAoAAAACAAMAAAAOAAoAAAACAAMAAAAMAAoAAAACAAMAAAAKAAoAAAACAAMAAAAIAAoAAAACAAMAAAAGAAoAAAACAAMAAAAEAAoAAAACAAMAAAACAAoAAAACAAMAAAACAAwAAAACAAMAAAAEAAwAAAACAAMAAAAGAAwAAAACAAMAAAAIAAwAAAACAAMAAAAKAAwAAAACAAMAAAAMAAwAAAACAAMAAAAOAAwAAAACAAMAAAASAAwAAAACAAMAAAAUAAwAAAACAAMAAAAWAAwAAAACAAMAAAAYAAwAAAACAAMAAAAaAAwAAAACAAMAAAAcABAAAAACAAMAAAAaABAAAAACAAMAAAAYABAAAAACAAMAAAAWABAAAAACAAMAAAAUABAAAAACAAMAAAASABAAAAACAAMAAAAOABAAAAACAAMAAAAMABAAAAACAAMAAAAKABAAAAACAAMAAAAIABAAAAACAAMAAAAGABAAAAACAAMAAAAEABAAAAACAAMAAAACABAAAAACAAMAAAAAABAAAAACAAMAAAAeAAYAAAACAAMAAAAeAAgAAAACAAMAAAAeAAoAAAACAAMAAAAeAAwAAAACAAMAAAAeAA4AAAACAAMAAAAeABAAAAACAAMAAAAQABAAAAACAAMAAAAQAA4AAAACAAMAAAAQAAwAAAACAAMAAAAAABIAAAACAAMAAAACABIAAAACAAMAAAAEABIAAAACAAMAAAAGABIAAAACAAMAAAAIABIAAAACAAMAAAAKABIAAAACAAMAAAAMABIAAAACAAMAAAAOABIAAAACAAMAAAAQABIAAAACAAMAAAASABIAAAACAAMAAAAUABIAAAACAAMAAAAWABIAAAACAAMAAAAYABIAAAACAAMAAAAaABIAAAACAAMAAAAcABIAAAACAAMAAAAeABIAAAACAAMAAAAeABQAAAACAAMAAAAcABQAAAACAAMAAAAaABQAAAACAAMAAAAYABQAAAACAAMAAAAWABQAAAACAAMAAAAUABQAAAACAAMAAAASABQAAAACAAMAAAAQABQAAAACAAMAAAAOABQAAAACAAMAAAAMABQAAAACAAMAAAAKABQAAAACAAMAAAAIABQAAAACAAMAAAAGABQAAAACAAMAAAAEABQAAAACAAMAAAACABQAAAACAAMAAAAAABQAAAACAAMAAAAAABYAAAACAAMAAAACABYAAAACAAMAAAAEABYAAAACAAMAAAAGABYAAAACAAMAAAAIABYAAAACAAMAAAAKABYAAAACAAMAAAAMABYAAAACAAMAAAAOABYAAAACAAMAAAAQABYAAAACAAMAAAASABYAAAACAAMAAAAUABYAAAACAAMAAAAWABYAAAACAAMAAAAYABYAAAACAAMAAAAaABYAAAACAAMAAAAcABYAAAACAAMAAAAeABYAAAACAAMAAAAeABgAAAACAAMAAAAcABgAAAACAAMAAAAaABgAAAACAAMAAAAYABgAAAACAAMAAAAWABgAAAACAAMAAAAUABgAAAACAAMAAAASABgAAAACAAMAAAAQABgAAAACAAMAAAAOABgAAAACAAMAAAAMABgAAAACAAMAAAAKABgAAAACAAMAAAAIABgAAAACAAMAAAAEABgAAAACAAMAAAAGABgAAAACAAMAAAACABgAAAACAAMAAAAAABgAAAACAAMAAAAAABoAAAACAAMAAAACABoAAAACAAMAAAAEABoAAAACAAMAAAAGABoAAAACAAMAAAAIABoAAAACAAMAAAAKABoAAAACAAMAAAAMABoAAAACAAMAAAAOABoAAAACAAMAAAAQABoAAAACAAMAAAASABoAAAACAAMAAAAUABoAAAACAAMAAAAWABoAAAACAAMAAAAYABoAAAACAAMAAAAaABoAAAACAAMAAAAcABoAAAACAAMAAAAeABoAAAACAAMAAAAeABwAAAACAAMAAAAcABwAAAACAAMAAAAaABwAAAACAAMAAAAYABwAAAACAAMAAAAWABwAAAACAAMAAAAUABwAAAACAAMAAAASABwAAAACAAMAAAAQABwAAAACAAMAAAAOABwAAAACAAMAAAAMABwAAAACAAMAAAAKABwAAAACAAMAAAAIABwAAAACAAMAAAAGABwAAAACAAMAAAAEABwAAAACAAMAAAACABwAAAACAAMAAAAAABwAAAACAAMAAAAAAB4AAAACAAMAAAACAB4AAAACAAMAAAAEAB4AAAACAAMAAAAGAB4AAAACAAMAAAAIAB4AAAACAAMAAAAKAB4AAAACAAMAAAAMAB4AAAACAAMAAAAOAB4AAAACAAMAAAAQAB4AAAACAAMAAAASAB4AAAACAAMAAAAUAB4AAAACAAMAAAAWAB4AAAACAAMAAAAYAB4AAAACAAMAAAAaAB4AAAACAAMAAAAcAB4AAAACAAMAAAAeAB4AAAACAAMAAAAeACAAAAACAAMAAAAcACAAAAACAAMAAAAaACAAAAACAAMAAAAYACAAAAACAAMAAAAWACAAAAACAAMAAAAUACAAAAACAAMAAAASACAAAAACAAMAAAAQACAAAAACAAMAAAAOACAAAAACAAMAAAAMACAAAAACAAMAAAAKACAAAAACAAMAAAAIACAAAAACAAMAAAAGACAAAAACAAMAAAAEACAAAAACAAMAAAACACAAAAACAAMAAAAAACAAAAACAAMAAAAAACIAAAACAAMAAAACACIAAAACAAMAAAAEACIAAAACAAMAAAAGACIAAAACAAMAAAAIACIAAAACAAMAAAAKACIAAAACAAMAAAAMACIAAAACAAMAAAAOACIAAAACAAMAAAAQACIAAAACAAMAAAASACIAAAACAAMAAAAUACIAAAACAAMAAAAWACIAAAACAAMAAAAYACIAAAACAAMAAAAaACIAAAACAAMAAAAcACIAAAACAAMAAAAeACIAAAACAAMAAAAeACQAAAACAAMAAAAcACQAAAACAAMAAAAaACQAAAACAAMAAAAYACQAAAACAAMAAAAWACQAAAACAAMAAAAUACQAAAACAAMAAAASACQAAAACAAMAAAAQACQAAAACAAMAAAAOACQAAAACAAMAAAAMACQAAAACAAMAAAAKACQAAAACAAMAAAAIACQAAAACAAMAAAAGACQAAAACAAMAAAAEACQAAAACAAMAAAACACQAAAACAAMAAAAAACQAAAACAAMAAAAAACYAAAABAAEAAAAeACgAAAADAAEAAAAAACgAAAAEAAEAAAAAAAQAAAAAAAIAAAAeAAQAAAAAAAIAAAACAAQAAAAAAAIAAAAEAAQAAAAAAAIAAAAGAAQAAAAAAAIAAAACAAIAAAAAAAIAAAAEAAIAAAAAAAIAAAAGAAIAAAAAAAIAAAAIAAQAAAAAAAIAAAAIAAIAAAAAAAIAAAAKAAIAAAAAAAIAAAAKAAQAAAAAAAIAAAAMAAQAAAAAAAIAAAAMAAIAAAAAAAIAAAAOAAIAAAAAAAIAAAAOAAQAAAAAAAIAAAAQAAQAAAAAAAIAAAAQAAIAAAAAAAIAAAASAAIAAAAAAAIAAAASAAQAAAAAAAIAAAAUAAQAAAAAAAIAAAAUAAIAAAAAAAIAAAAWAAIAAAAAAAIAAAAWAAQAAAAAAAIAAAAYAAQAAAAAAAIAAAAYAAIAAAAAAAIAAAAaAAIAAAAAAAIAAAAaAAQAAAAAAAIAAAAcAAIAAAAAAAIAAAAcAAQAAAAAAAIAAAA=") +tile_set = SubResource("TileSet_jr8qv") + +[node name="Walls" type="TileMapLayer" parent="Map" unique_id=142135081] +z_index = 2 +tile_map_data = PackedByteArray("AAAAAAAAAAACAAAAAAACAAAAAAABAAEAAAAEAAAAAAABAAEAAAAGAAAAAAABAAEAAAAIAAAAAAABAAEAAAAKAAAAAAABAAEAAAAMAAAAAAABAAEAAAAOAAAAAAABAAEAAAAQAAAAAAABAAEAAAASAAAAAAABAAEAAAAUAAAAAAABAAEAAAAWAAAAAAABAAEAAAAYAAAAAAABAAEAAAAaAAAAAAABAAEAAAAcAAAAAAABAAEAAAAeAAAAAAAAAAAAAAAAAAIAAAAEAAAAAAAeAAIAAAADAAAAAAAeAAQAAAADAAAAAAAeAAYAAAADAAAAAAAeAAgAAAADAAAAAAAeAAoAAAADAAAAAAAeAAwAAAADAAAAAAAeAA4AAAADAAAAAAAeABAAAAADAAAAAAAeABIAAAADAAAAAAAeABQAAAADAAAAAAAeABYAAAADAAAAAAAeABgAAAADAAAAAAAeABoAAAADAAAAAAAeABwAAAADAAAAAAAeAB4AAAADAAAAAAAeACAAAAADAAAAAAAeACIAAAADAAAAAAAeACQAAAADAAAAAAAcACYAAAABAAEAAAAaACYAAAABAAEAAAAYACYAAAABAAEAAAAWACYAAAABAAEAAAAUACYAAAABAAEAAAAMACYAAAABAAEAAAAKACYAAAABAAEAAAAAAAQAAAAEAAAAAAAAAAYAAAAEAAAAAAAAAAgAAAAEAAAAAAAAAAoAAAAEAAAAAAAAAAwAAAAEAAAAAAAAAA4AAAAEAAAAAAAAABAAAAAEAAAAAAAAABIAAAAEAAAAAAAAABQAAAAEAAAAAAAAABYAAAAEAAAAAAAAABgAAAAEAAAAAAAAABoAAAAEAAAAAAAAABwAAAAEAAAAAAAAAB4AAAAEAAAAAAAAACAAAAAEAAAAAAAAACIAAAAEAAAAAAAAACQAAAAEAAAAAAAIACYAAAABAAEAAAAGACYAAAABAAEAAAAEACYAAAABAAEAAAACACYAAAABAAEAAAAAACYAAAACAAEAAAAeACcAAAADAAEAAAAeACYAAAADAAEAAAAOACYAAAABAAEAAAASACYAAAABAAEAAAAAACcAAAAEAAEAAAASACgAAAAAAAIAAAAUACgAAAAAAAIAAAAWACgAAAAAAAIAAAAYACgAAAAAAAIAAAAaACgAAAAAAAIAAAAcACgAAAAAAAIAAAAOACgAAAAAAAIAAAAMACgAAAAAAAIAAAAKACgAAAAAAAIAAAAIACgAAAAAAAIAAAAGACgAAAAAAAIAAAAEACgAAAAAAAIAAAACACgAAAAAAAIAAAA=") +tile_set = SubResource("TileSet_jr8qv") + +[node name="Door" type="TileMapLayer" parent="Map" unique_id=382416981] +z_index = 2 +tile_map_data = PackedByteArray("AAAQACcAAAADAAIAAAAAACYAAAAEAAEAAAAeACYAAAADAAEAAAA=") +tile_set = SubResource("TileSet_jr8qv") + +[node name="Windows" type="TileMapLayer" parent="Map" unique_id=836194583] +z_index = 5 +tile_map_data = PackedByteArray("AAADAAEAAAAAAAQAAAAbAAEAAAAAAAQAAAAHAAEAAAAAAAYAAAAXAAEAAAAAAAYAAAAXAAMAAAAEAAUAAAAXAAUAAAAEAAUAAAAXAAcAAAAEAAUAAAAHAAMAAAAEAAUAAAAHAAUAAAAEAAUAAAAHAAcAAAAEAAUAAAAHAAkAAAAEAAYAAAAXAAkAAAAEAAYAAAADAAMAAAACAAUAAAADAAUAAAACAAUAAAADAAcAAAACAAUAAAAbAAMAAAACAAUAAAAbAAUAAAACAAUAAAAbAAcAAAACAAUAAAAbAAkAAAACAAYAAAADAAkAAAACAAYAAAAPAAEAAAAAAAQAAAAPAAMAAAACAAUAAAAPAAUAAAACAAUAAAAPAAcAAAACAAUAAAAPAAkAAAACAAYAAAA=") +tile_set = SubResource("TileSet_jr8qv") + +[node name="Objects" type="TileMapLayer" parent="Map" unique_id=2001863559] +tile_map_data = PackedByteArray("AAAYAAUAAAAEAAIAAAAaAAUAAAAEAAIAAAAcAAUAAAAEAAIAAAAeAAUAAAAEAAIAAAAaAAcAAAAEAAIAAAAcAAcAAAAEAAIAAAAeAAcAAAAEAAIAAAAYAAcAAAAEAAIAAAAaAAkAAAAEAAIAAAAcAAkAAAAEAAIAAAAeAAkAAAAEAAIAAAAEAAUAAAAEAAIAAAAGAAUAAAAEAAIAAAAAAAUAAAAEAAIAAAA=") +tile_set = SubResource("TileSet_jr8qv") + +[node name="ObjectsLayer2" type="TileMapLayer" parent="Map" unique_id=1892511212] +z_index = 3 +tile_map_data = PackedByteArray("AAAFAAQAAAAEAAIAAAAZAAQAAAAEAAIAAAAbAAQAAAAEAAIAAAAdAAQAAAAEAAIAAAAdAAYAAAAEAAIAAAAbAAYAAAAEAAIAAAAZAAYAAAAEAAIAAAAbAAgAAAAEAAIAAAAdAAgAAAAEAAIAAAA=") +tile_set = SubResource("TileSet_jr8qv") + +[node name="Other" type="TileMapLayer" parent="Map" unique_id=985720640] +tile_set = SubResource("TileSet_jr8qv") + +[node name="Item" parent="Map" unique_id=1691516870 instance=ExtResource("6_srx2q")] +position = Vector2(136, 263) + +[node name="Player" parent="." unique_id=628518902 instance=ExtResource("2_n70cd")] +z_index = 1 +position = Vector2(262, 239) diff --git a/levels/repair_zone.gd b/levels/repair_zone.gd index 06d9183..9cf484b 100644 --- a/levels/repair_zone.gd +++ b/levels/repair_zone.gd @@ -7,11 +7,21 @@ extends Area2D signal repair_requested(npc_id: String) func interact() -> void: - print("interact() appelé sur RepairZone") - print("can_repair : ", GameState.can_repair(npc_id)) - print("inventaire : ", GameState.inventory) if GameState.can_repair(npc_id): repair_requested.emit(npc_id) print("Lancement mini-jeu pour : ", npc_id) + _start_repair() else: print("Pièces manquantes pour réparer ", npc_id) + +# Dans le script du PNJ, quand les items sont validés +func _start_repair() -> void: + var minigame = preload("res://ui/minigame/repair_minigame.tscn").instantiate() + get_tree().root.add_child(minigame) + minigame.repair_complete.connect(_on_repair_done) + minigame.open("vrac7") + +func _on_repair_done() -> void: + GameState.set_flag("vrac7_repaired", true) + # dialogue_system.start("vrac7_post_repair") + # → [LOG] "Unité VRAC-7 : réparation complète. Statut : opérationnel." diff --git a/project.godot b/project.godot index 71fa27f..781f91c 100644 --- a/project.godot +++ b/project.godot @@ -11,9 +11,10 @@ config_version=5 [application] config/name="Scrap Signal" -run/main_scene="uid://c5lskgqkorw6v" +run/main_scene="uid://kmybl0c637as" config/features=PackedStringArray("4.6", "GL Compatibility") run/max_fps=60 +boot_splash/bg_color=Color(0, 0, 0, 1) config/icon="res://icon.svg" [autoload] diff --git a/ui/dialogue_box.tscn b/ui/dialogue_box.tscn index b157c12..4967334 100644 --- a/ui/dialogue_box.tscn +++ b/ui/dialogue_box.tscn @@ -11,6 +11,7 @@ border_width_bottom = 1 border_color = Color(0.53333336, 0.53333336, 0.53333336, 1) [node name="DialogueBox" type="Node2D" unique_id=1374394268] +z_index = 500 [node name="DialogueBox" type="CanvasLayer" parent="." unique_id=1732454601 groups=["dialogue_box"]] script = ExtResource("1_2ix3t") diff --git a/ui/hud.gd b/ui/hud.gd index 05a0757..f3be8cb 100644 --- a/ui/hud.gd +++ b/ui/hud.gd @@ -9,6 +9,11 @@ extends CanvasLayer @onready var interact_prompt := $InteractPrompt @onready var prompt_label := $InteractPrompt/PromptLabel +@onready var log_container := $LogContainer +@onready var log_label := $LogContainer/LogLabel + +var _log_tween : Tween + func _ready() -> void: GameState.inventory_changed.connect(_refresh) _refresh() @@ -25,3 +30,18 @@ func _refresh() -> void: var count : int = GameState.inventory.get(item_id, 0) slots[item_id].text = "x%d" % count slots[item_id].get_parent().modulate.a = 0.4 if count == 0 else 1.0 + +func show_log(message: String) -> void: + log_label.text = "> " + message + log_container.modulate.a = 1.0 + log_container.show() + + # Annule le tween précédent si un log était encore visible + if _log_tween: + _log_tween.kill() + + # Disparaît après 3 secondes avec un fade out + _log_tween = create_tween() + _log_tween.tween_interval(2.5) + _log_tween.tween_property(log_container, "modulate:a", 0.0, 0.5) + _log_tween.tween_callback(log_container.hide) diff --git a/ui/hud.tscn b/ui/hud.tscn index 0ada65d..be12a01 100644 --- a/ui/hud.tscn +++ b/ui/hud.tscn @@ -8,15 +8,16 @@ border_width_top = 1 border_color = Color(0.33333334, 0.33333334, 0.33333334, 1) border_blend = true +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_546lt"] +bg_color = Color(0, 0, 0, 0.6) + [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_276te"] bg_color = Color(0, 0, 0, 0.003921569) -[node name="Hud" type="Node2D" unique_id=1774402684] - -[node name="HUD" type="CanvasLayer" parent="." unique_id=1046780358 groups=["hud"]] +[node name="HUD" type="CanvasLayer" unique_id=1746360319 groups=["hud"]] script = ExtResource("1_rbyyf") -[node name="InventoryBar" type="PanelContainer" parent="HUD" unique_id=255970268] +[node name="InventoryBar" type="PanelContainer" parent="." unique_id=1523829052] anchors_preset = 12 anchor_top = 1.0 anchor_right = 1.0 @@ -26,42 +27,61 @@ grow_horizontal = 2 grow_vertical = 0 theme_override_styles/panel = SubResource("StyleBoxFlat_rbyyf") -[node name="ItemRow" type="HBoxContainer" parent="HUD/InventoryBar" unique_id=616700836] +[node name="ItemRow" type="HBoxContainer" parent="InventoryBar" unique_id=279840989] layout_mode = 2 theme_override_constants/separation = 8 alignment = 1 -[node name="EngrenageSlot" type="HBoxContainer" parent="HUD/InventoryBar/ItemRow" unique_id=615738426] +[node name="EngrenageSlot" type="HBoxContainer" parent="InventoryBar/ItemRow" unique_id=237860192] layout_mode = 2 -[node name="Icon" type="TextureRect" parent="HUD/InventoryBar/ItemRow/EngrenageSlot" unique_id=1435745466] +[node name="Icon" type="TextureRect" parent="InventoryBar/ItemRow/EngrenageSlot" unique_id=1231030010] layout_mode = 2 -[node name="Count" type="Label" parent="HUD/InventoryBar/ItemRow/EngrenageSlot" unique_id=1082443403] +[node name="Count" type="Label" parent="InventoryBar/ItemRow/EngrenageSlot" unique_id=1232241990] layout_mode = 2 theme_override_font_sizes/font_size = 6 -[node name="CableSlot" type="HBoxContainer" parent="HUD/InventoryBar/ItemRow" unique_id=1777823230] +[node name="CableSlot" type="HBoxContainer" parent="InventoryBar/ItemRow" unique_id=1605493752] layout_mode = 2 -[node name="Icon" type="TextureRect" parent="HUD/InventoryBar/ItemRow/CableSlot" unique_id=1512420928] +[node name="Icon" type="TextureRect" parent="InventoryBar/ItemRow/CableSlot" unique_id=1278175009] layout_mode = 2 -[node name="Count" type="Label" parent="HUD/InventoryBar/ItemRow/CableSlot" unique_id=241891402] +[node name="Count" type="Label" parent="InventoryBar/ItemRow/CableSlot" unique_id=1479768730] layout_mode = 2 theme_override_font_sizes/font_size = 6 -[node name="CircuitSlot" type="HBoxContainer" parent="HUD/InventoryBar/ItemRow" unique_id=707078098] +[node name="CircuitSlot" type="HBoxContainer" parent="InventoryBar/ItemRow" unique_id=2106106895] layout_mode = 2 -[node name="Icon" type="TextureRect" parent="HUD/InventoryBar/ItemRow/CircuitSlot" unique_id=273462465] +[node name="Icon" type="TextureRect" parent="InventoryBar/ItemRow/CircuitSlot" unique_id=1469623782] layout_mode = 2 -[node name="Count" type="Label" parent="HUD/InventoryBar/ItemRow/CircuitSlot" unique_id=766125092] +[node name="Count" type="Label" parent="InventoryBar/ItemRow/CircuitSlot" unique_id=2121401937] layout_mode = 2 theme_override_font_sizes/font_size = 6 -[node name="InteractPrompt" type="PanelContainer" parent="HUD" unique_id=1666962404] +[node name="LogContainer" type="PanelContainer" parent="." unique_id=2020517372] +visible = false +anchors_preset = 10 +anchor_right = 1.0 +grow_horizontal = 2 +mouse_filter = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_546lt") + +[node name="LogLabel" type="RichTextLabel" parent="LogContainer" unique_id=957446787] +layout_mode = 2 +mouse_filter = 2 +theme_override_font_sizes/normal_font_size = 8 +theme_override_font_sizes/bold_font_size = 8 +theme_override_font_sizes/bold_italics_font_size = 8 +theme_override_font_sizes/italics_font_size = 8 +theme_override_font_sizes/mono_font_size = 8 +bbcode_enabled = true +fit_content = true + +[node name="InteractPrompt" type="PanelContainer" parent="." unique_id=1303778847] visible = false anchors_preset = 8 anchor_left = 0.5 @@ -75,7 +95,7 @@ grow_horizontal = 2 grow_vertical = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_276te") -[node name="PromptLabel" type="Label" parent="HUD/InteractPrompt" unique_id=1518438846] +[node name="PromptLabel" type="Label" parent="InteractPrompt" unique_id=924240162] layout_mode = 2 theme_override_colors/font_shadow_color = Color(0, 0, 0, 0.39215687) theme_override_constants/shadow_offset_x = 0 diff --git a/ui/minigame/minigame.gd b/ui/minigame/minigame.gd deleted file mode 100644 index e69de29..0000000 diff --git a/ui/minigame/repair_minigame.gd b/ui/minigame/repair_minigame.gd new file mode 100644 index 0000000..2d66da6 --- /dev/null +++ b/ui/minigame/repair_minigame.gd @@ -0,0 +1,243 @@ +class_name RepairMinigame +extends CanvasLayer + +signal repair_complete + +const PUZZLES := { + "vrac7": { + "title": "RECONNEXION — SYSTÈME MOTEUR", + "connections": [[0, 0], [1, 2], [3, 3]] + }, + "iris3": { + "title": "RECALIBRATION — CAPTEUR OPTIQUE", + "connections": [[0, 1], [2, 3]] + } +} + +const GRID_SIZE := 4 + +var current_puzzle: Dictionary +var paths: Array = [] +var active_path: int = -1 +var solved_paths: Array = [] + +@onready var grid := $Background/Panel/VBoxContainer/Grid +@onready var title_lbl := $Background/Panel/VBoxContainer/Title +@onready var status := $Background/Panel/VBoxContainer/StatusLabel + +# ── Lifecycle ───────────────────────────────────────────────────────────────── + +func _ready() -> void: + layer = 1000 + + var panel := $Background/Panel + panel.set_anchors_preset(Control.PRESET_CENTER) + + var vbox := $Background/Panel/VBoxContainer + vbox.alignment = BoxContainer.ALIGNMENT_CENTER + vbox.add_theme_constant_override("separation", 12) + + # Centre la grid horizontalement dans le VBox + grid.size_flags_horizontal = Control.SIZE_SHRINK_CENTER + grid.size_flags_vertical = Control.SIZE_SHRINK_CENTER + +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed("ui_cancel"): + _cancel() + +# ── API publique ────────────────────────────────────────────────────────────── + +func open(robot_id: String) -> void: + current_puzzle = PUZZLES[robot_id] + title_lbl.text = current_puzzle["title"] + paths.clear() + solved_paths.clear() + for _c in current_puzzle["connections"]: + paths.append([]) + solved_paths.append(false) + _set_hud_visible(false) + _set_player_enabled(false) + _build_grid() + _update_status() + show() + +# ── Grille ──────────────────────────────────────────────────────────────────── + +func _build_grid() -> void: + for child in grid.get_children(): + child.queue_free() + + # Taille fixe de la grille : GRID_SIZE * taille bouton + séparation + var cell_size := 25 + var separation := 4 + var grid_px := GRID_SIZE * cell_size + (GRID_SIZE - 1) * separation + grid.custom_minimum_size = Vector2(grid_px, grid_px) + grid.columns = GRID_SIZE + + for row in GRID_SIZE: + for col in GRID_SIZE: + var btn := Button.new() + btn.custom_minimum_size = Vector2(cell_size, cell_size) + btn.name = "Cell_%d_%d" % [row, col] + btn.add_theme_stylebox_override("normal", _make_stylebox(Color(0.15, 0.15, 0.15), 1.0)) + btn.add_theme_stylebox_override("hover", _make_stylebox(Color(0.25, 0.25, 0.25), 1.0)) + + if col == 0: + var path_idx = _entry_for_row(row) + if path_idx >= 0: + btn.text = "●" + btn.modulate = _color_for_path(path_idx) + elif col == 3: + var path_idx = _exit_for_row(row) + if path_idx >= 0: + btn.text = "●" + btn.modulate = _color_for_path(path_idx) + + btn.pressed.connect(_on_cell_pressed.bind(row, col)) + grid.add_child(btn) + +func _on_cell_pressed(row: int, col: int) -> void: + var entry_idx = _entry_for_row(row) + if col == 0 and entry_idx >= 0: + active_path = entry_idx + paths[active_path] = [Vector2i(row, col)] + _refresh_grid() + return + + if active_path < 0: + return + + var last: Vector2i = paths[active_path].back() if paths[active_path].size() > 0 else Vector2i(-1, -1) + var cell := Vector2i(row, col) + + if not _is_adjacent(last, cell): + return + + for i in paths.size(): + if i == active_path: + continue + if cell in paths[i]: + return + + paths[active_path].append(cell) + + var exit_row = current_puzzle["connections"][active_path][1] + if col == 3 and row == exit_row: + solved_paths[active_path] = true + active_path = -1 + _refresh_grid() + _update_status() + _check_win() + return + + _refresh_grid() + _update_status() + +# ── Victoire / Annulation ───────────────────────────────────────────────────── + +func _check_win() -> void: + if solved_paths.all(func(s): return s == true): + await get_tree().create_timer(0.6).timeout + repair_complete.emit() + _close() + +func _cancel() -> void: + active_path = -1 + _close() + +func _close() -> void: + _set_hud_visible(true) + _set_player_enabled(true) + hide() + +# ── Affichage ───────────────────────────────────────────────────────────────── + +func _refresh_grid() -> void: + for row in GRID_SIZE: + for col in GRID_SIZE: + var btn: Button = grid.get_node_or_null("Cell_%d_%d" % [row, col]) + if btn == null: + continue + var cell := Vector2i(row, col) + var found := false + + for i in paths.size(): + if cell in paths[i]: + var c := _color_for_path(i) + var is_endpoint := (col == 0 or col == 3) + btn.text = "●" if is_endpoint else "■" + btn.modulate = Color.WHITE + btn.add_theme_stylebox_override("normal", _make_stylebox(c, 0.5)) + btn.add_theme_color_override("font_color", c) + found = true + break + + if not found: + btn.modulate = Color.WHITE + btn.text = "" + btn.add_theme_stylebox_override("normal", _make_stylebox(Color(0.15, 0.15, 0.15), 1.0)) + btn.remove_theme_color_override("font_color") + var ei = _entry_for_row(row) + var xi = _exit_for_row(row) + if col == 0 and ei >= 0: + btn.text = "●" + btn.add_theme_color_override("font_color", _color_for_path(ei)) + elif col == 3 and xi >= 0: + btn.text = "●" + btn.add_theme_color_override("font_color", _color_for_path(xi)) + +func _update_status() -> void: + var count := solved_paths.count(true) + var total := solved_paths.size() + if count == total: + status.text = "✓ RÉPARATION COMPLÈTE" + status.add_theme_color_override("font_color", Color("#6daa45")) + else: + status.text = "%d / %d connexions établies" % [count, total] + status.remove_theme_color_override("font_color") + +# ── Helpers ─────────────────────────────────────────────────────────────────── + +func _set_hud_visible(visible: bool) -> void: + var hud = get_tree().get_first_node_in_group("hud") + if hud: + hud.visible = visible + +func _make_stylebox(color: Color, alpha: float) -> StyleBoxFlat: + var sb := StyleBoxFlat.new() + sb.bg_color = Color(color.r, color.g, color.b, alpha) + sb.corner_radius_top_left = 4 + sb.corner_radius_top_right = 4 + sb.corner_radius_bottom_left = 4 + sb.corner_radius_bottom_right = 4 + return sb + +func _entry_for_row(row: int) -> int: + for i in current_puzzle["connections"].size(): + if current_puzzle["connections"][i][0] == row: + return i + return -1 + +func _exit_for_row(row: int) -> int: + for i in current_puzzle["connections"].size(): + if current_puzzle["connections"][i][1] == row: + return i + return -1 + +func _is_adjacent(a: Vector2i, b: Vector2i) -> bool: + return abs(a.x - b.x) + abs(a.y - b.y) == 1 + +func _color_for_path(idx: int) -> Color: + var colors := [Color("#f4c430"), Color("#5bc8f5"), Color("#f47c3c")] + return colors[idx % colors.size()] + +func _set_player_enabled(enabled: bool) -> void: + var player = get_tree().get_first_node_in_group("player") + print("_set_player_enabled: ", enabled, " | player trouvé: ", player) + if player: + player.set_process(enabled) + player.set_physics_process(enabled) + player.set_process_unhandled_input(enabled) + player.is_locked = false + if not enabled and player is CharacterBody2D: + player.velocity = Vector2.ZERO diff --git a/ui/minigame/minigame.gd.uid b/ui/minigame/repair_minigame.gd.uid similarity index 100% rename from ui/minigame/minigame.gd.uid rename to ui/minigame/repair_minigame.gd.uid diff --git a/ui/minigame/repair_minigame.tscn b/ui/minigame/repair_minigame.tscn new file mode 100644 index 0000000..eb811fe --- /dev/null +++ b/ui/minigame/repair_minigame.tscn @@ -0,0 +1,45 @@ +[gd_scene format=3 uid="uid://djtxltf8mtuv6"] + +[ext_resource type="Script" uid="uid://b5237vkobhji0" path="res://ui/minigame/repair_minigame.gd" id="1_151ia"] + +[node name="RepairMinigame" type="CanvasLayer" unique_id=189116174] +script = ExtResource("1_151ia") + +[node name="Background" type="ColorRect" parent="." unique_id=1916489054] +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -70.0 +offset_top = -70.0 +offset_right = -70.0 +offset_bottom = -70.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="Panel" type="PanelContainer" parent="Background" unique_id=1782143434] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="Background/Panel" unique_id=937959925] +layout_mode = 2 +alignment = 1 + +[node name="Title" type="Label" parent="Background/Panel/VBoxContainer" unique_id=1457760472] +layout_mode = 2 +theme_override_font_sizes/font_size = 8 +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="Grid" type="GridContainer" parent="Background/Panel/VBoxContainer" unique_id=123587798] +layout_mode = 2 +columns = 4 + +[node name="StatusLabel" type="Label" parent="Background/Panel/VBoxContainer" unique_id=1700512059] +layout_mode = 2 +theme_override_font_sizes/font_size = 8 +horizontal_alignment = 1 +vertical_alignment = 1