diff --git a/assets/audio/music/atelier.ogg b/assets/audio/music/atelier.ogg new file mode 100644 index 0000000..d0d1ebe Binary files /dev/null and b/assets/audio/music/atelier.ogg differ diff --git a/assets/audio/music/atelier.ogg.import b/assets/audio/music/atelier.ogg.import new file mode 100644 index 0000000..d6e53cf --- /dev/null +++ b/assets/audio/music/atelier.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://d35bsm7iauw0m" +path="res://.godot/imported/atelier.ogg-7a3e3a8868035e176e3458ac9bd678ab.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/music/atelier.ogg" +dest_files=["res://.godot/imported/atelier.ogg-7a3e3a8868035e176e3458ac9bd678ab.oggvorbisstr"] + +[params] + +loop=true +loop_offset=0.0 +bpm=0.0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/music/cour.ogg b/assets/audio/music/cour.ogg new file mode 100644 index 0000000..e57272b Binary files /dev/null and b/assets/audio/music/cour.ogg differ diff --git a/assets/audio/music/cour.ogg.import b/assets/audio/music/cour.ogg.import new file mode 100644 index 0000000..e85718c --- /dev/null +++ b/assets/audio/music/cour.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://dmsfyl0yejo7y" +path="res://.godot/imported/cour.ogg-3fd6c907bf512ddd8c432cf3cd51237f.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/music/cour.ogg" +dest_files=["res://.godot/imported/cour.ogg-3fd6c907bf512ddd8c432cf3cd51237f.oggvorbisstr"] + +[params] + +loop=true +loop_offset=0.0 +bpm=0.0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/music/entrepot.ogg b/assets/audio/music/entrepot.ogg new file mode 100644 index 0000000..0f250a9 Binary files /dev/null and b/assets/audio/music/entrepot.ogg differ diff --git a/assets/audio/music/entrepot.ogg.import b/assets/audio/music/entrepot.ogg.import new file mode 100644 index 0000000..5a24e72 --- /dev/null +++ b/assets/audio/music/entrepot.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://d4ge24h3tecku" +path="res://.godot/imported/entrepot.ogg-eeb39e76ee09263475800ff86d7ebf2f.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/music/entrepot.ogg" +dest_files=["res://.godot/imported/entrepot.ogg-eeb39e76ee09263475800ff86d7ebf2f.oggvorbisstr"] + +[params] + +loop=true +loop_offset=0.0 +bpm=0.0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/music/title_screen.ogg b/assets/audio/music/title_screen.ogg new file mode 100644 index 0000000..b69396a Binary files /dev/null and b/assets/audio/music/title_screen.ogg differ diff --git a/assets/audio/music/title_screen.ogg.import b/assets/audio/music/title_screen.ogg.import new file mode 100644 index 0000000..fe96d69 --- /dev/null +++ b/assets/audio/music/title_screen.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://ds7o8m11r5ih" +path="res://.godot/imported/title_screen.ogg-f389fec678c0e0c8c0f15984199b685d.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/music/title_screen.ogg" +dest_files=["res://.godot/imported/title_screen.ogg-f389fec678c0e0c8c0f15984199b685d.oggvorbisstr"] + +[params] + +loop=true +loop_offset=0.0 +bpm=0.0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/sfx/door_unlocking.ogg b/assets/audio/sfx/door_unlocking.ogg new file mode 100644 index 0000000..e611351 Binary files /dev/null and b/assets/audio/sfx/door_unlocking.ogg differ diff --git a/assets/audio/sfx/door_unlocking.ogg.import b/assets/audio/sfx/door_unlocking.ogg.import new file mode 100644 index 0000000..0fe493e --- /dev/null +++ b/assets/audio/sfx/door_unlocking.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://sp5oy5ol7rg5" +path="res://.godot/imported/door_unlocking.ogg-4ec5733b41a4b54db48ba8ae423a6e2e.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/sfx/door_unlocking.ogg" +dest_files=["res://.godot/imported/door_unlocking.ogg-4ec5733b41a4b54db48ba8ae423a6e2e.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/sfx/footsteps.ogg b/assets/audio/sfx/footsteps.ogg new file mode 100644 index 0000000..0bbe215 Binary files /dev/null and b/assets/audio/sfx/footsteps.ogg differ diff --git a/assets/audio/sfx/footsteps.ogg.import b/assets/audio/sfx/footsteps.ogg.import new file mode 100644 index 0000000..53971c7 --- /dev/null +++ b/assets/audio/sfx/footsteps.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://dfslsx3kt8pqt" +path="res://.godot/imported/footsteps.ogg-360e88fb8d63ecc4a78114a79239154b.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/sfx/footsteps.ogg" +dest_files=["res://.godot/imported/footsteps.ogg-360e88fb8d63ecc4a78114a79239154b.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/sfx/iris_talking.ogg b/assets/audio/sfx/iris_talking.ogg new file mode 100644 index 0000000..a25a4e5 Binary files /dev/null and b/assets/audio/sfx/iris_talking.ogg differ diff --git a/assets/audio/sfx/iris_talking.ogg.import b/assets/audio/sfx/iris_talking.ogg.import new file mode 100644 index 0000000..56a9aad --- /dev/null +++ b/assets/audio/sfx/iris_talking.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://d1sfvsp37sf1c" +path="res://.godot/imported/iris_talking.ogg-e197f63669b871b7fba645862ffe301f.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/sfx/iris_talking.ogg" +dest_files=["res://.godot/imported/iris_talking.ogg-e197f63669b871b7fba645862ffe301f.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/sfx/item_pickup.ogg b/assets/audio/sfx/item_pickup.ogg new file mode 100644 index 0000000..8513668 Binary files /dev/null and b/assets/audio/sfx/item_pickup.ogg differ diff --git a/assets/audio/sfx/item_pickup.ogg.import b/assets/audio/sfx/item_pickup.ogg.import new file mode 100644 index 0000000..6d165a6 --- /dev/null +++ b/assets/audio/sfx/item_pickup.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://doufrkn1wb85d" +path="res://.godot/imported/item_pickup.ogg-7b20fc9fb13728b99b4c518de0969210.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/sfx/item_pickup.ogg" +dest_files=["res://.godot/imported/item_pickup.ogg-7b20fc9fb13728b99b4c518de0969210.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/sfx/iteract.ogg b/assets/audio/sfx/iteract.ogg new file mode 100644 index 0000000..316340e Binary files /dev/null and b/assets/audio/sfx/iteract.ogg differ diff --git a/assets/audio/sfx/iteract.ogg.import b/assets/audio/sfx/iteract.ogg.import new file mode 100644 index 0000000..9a61ab0 --- /dev/null +++ b/assets/audio/sfx/iteract.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://bktodk0h2u1xo" +path="res://.godot/imported/iteract.ogg-f044ddc2b67a412af49013948df738f1.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/sfx/iteract.ogg" +dest_files=["res://.godot/imported/iteract.ogg-f044ddc2b67a412af49013948df738f1.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/sfx/robot_talking.ogg b/assets/audio/sfx/robot_talking.ogg new file mode 100644 index 0000000..fd8f76d Binary files /dev/null and b/assets/audio/sfx/robot_talking.ogg differ diff --git a/assets/audio/sfx/robot_talking.ogg.import b/assets/audio/sfx/robot_talking.ogg.import new file mode 100644 index 0000000..4d476a8 --- /dev/null +++ b/assets/audio/sfx/robot_talking.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://r3c2gy6p43jm" +path="res://.godot/imported/robot_talking.ogg-f1f0839274a4e042af26aaa250a3a3ca.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/sfx/robot_talking.ogg" +dest_files=["res://.godot/imported/robot_talking.ogg-f1f0839274a4e042af26aaa250a3a3ca.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/sfx/succesful_repair.ogg b/assets/audio/sfx/succesful_repair.ogg new file mode 100644 index 0000000..aed2c4e Binary files /dev/null and b/assets/audio/sfx/succesful_repair.ogg differ diff --git a/assets/audio/sfx/succesful_repair.ogg.import b/assets/audio/sfx/succesful_repair.ogg.import new file mode 100644 index 0000000..ec92333 --- /dev/null +++ b/assets/audio/sfx/succesful_repair.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://b1f3axr7ken6r" +path="res://.godot/imported/succesful_repair.ogg-b7611303e601315585c9423be7b9f899.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/sfx/succesful_repair.ogg" +dest_files=["res://.godot/imported/succesful_repair.ogg-b7611303e601315585c9423be7b9f899.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/sfx/vrac_talking.ogg b/assets/audio/sfx/vrac_talking.ogg new file mode 100644 index 0000000..0cc6bea Binary files /dev/null and b/assets/audio/sfx/vrac_talking.ogg differ diff --git a/assets/audio/sfx/vrac_talking.ogg.import b/assets/audio/sfx/vrac_talking.ogg.import new file mode 100644 index 0000000..58dab86 --- /dev/null +++ b/assets/audio/sfx/vrac_talking.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://dqinbgakcsurb" +path="res://.godot/imported/vrac_talking.ogg-64f29aedf2762b353d66c764f25377e6.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/sfx/vrac_talking.ogg" +dest_files=["res://.godot/imported/vrac_talking.ogg-64f29aedf2762b353d66c764f25377e6.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/autoloads/audio_manager.gd b/autoloads/audio_manager.gd index 61510e1..38bd492 100644 --- a/autoloads/audio_manager.gd +++ b/autoloads/audio_manager.gd @@ -1 +1,67 @@ extends Node + +var music_player : AudioStreamPlayer +var sfx_player : AudioStreamPlayer + +const AMBIANCE_VOLUME_DB := -12.0 + +const AMBIANCES := { + "entrepot": preload("res://assets/audio/music/entrepot.ogg"), + "atelier": preload("res://assets/audio/music/atelier.ogg"), + "cour": preload("res://assets/audio/music/cour.ogg"), +} + +const SFX := { + "footstep": preload("res://assets/audio/sfx/footsteps.ogg"), + "item_pickup": preload("res://assets/audio/sfx/item_pickup.ogg"), + "interact": preload("res://assets/audio/sfx/iteract.ogg"), + "door_unlock": preload("res://assets/audio/sfx/door_unlocking.ogg"), + "repair_success": preload("res://assets/audio/sfx/succesful_repair.ogg"), + "vrac_talking": preload("res://assets/audio/sfx/vrac_talking.ogg"), + "iris_talking": preload("res://assets/audio/sfx/iris_talking.ogg"), +} + +func _ready() -> void: + process_mode = Node.PROCESS_MODE_ALWAYS + + music_player = AudioStreamPlayer.new() + music_player.name = "MusicPlayer" + music_player.bus = "Ambient" + music_player.volume_db = AMBIANCE_VOLUME_DB + add_child(music_player) + music_player.process_mode = Node.PROCESS_MODE_ALWAYS + + sfx_player = AudioStreamPlayer.new() + sfx_player.name = "SfxPlayer" + sfx_player.bus = "SFX" + add_child(sfx_player) + sfx_player.process_mode = Node.PROCESS_MODE_ALWAYS + +func _on_music_finished() -> void: + music_player.play() + +func play_ambiance(zone: String) -> void: + if not AMBIANCES.has(zone): + return + if music_player.stream == AMBIANCES[zone] and music_player.playing: + return + + var tween := create_tween() + tween.tween_property(music_player, "volume_db", -40.0, 0.8) + tween.tween_callback(func(): + music_player.stream = AMBIANCES[zone] + music_player.play() + ) + tween.tween_property(music_player, "volume_db", AMBIANCE_VOLUME_DB, 1.2) + +func stop_ambiance() -> void: + var tween := create_tween() + tween.tween_property(music_player, "volume_db", -40.0, 1.0) + tween.tween_callback(music_player.stop) + +func play_sfx(sfx_name: String) -> void: + if not SFX.has(sfx_name): + push_warning("SFX introuvable : " + sfx_name) + return + sfx_player.stream = SFX[sfx_name] + sfx_player.play() diff --git a/autoloads/audio_manager.tscn b/autoloads/audio_manager.tscn new file mode 100644 index 0000000..e54c7a9 --- /dev/null +++ b/autoloads/audio_manager.tscn @@ -0,0 +1,17 @@ +[gd_scene format=3 uid="uid://xpa5geyvyey"] + +[ext_resource type="Script" uid="uid://dsilww05kuakm" path="res://autoloads/audio_manager.gd" id="1_tr7pb"] + +[sub_resource type="AudioStreamOggVorbis" id="AudioStreamOggVorbis_y37e5"] + +[sub_resource type="AudioStreamOggVorbis" id="AudioStreamOggVorbis_tr7pb"] + +[node name="AudioManager" type="Node2D" unique_id=524793407] +script = ExtResource("1_tr7pb") + +[node name="MusicPlayer" type="AudioStreamPlayer" parent="." unique_id=425558069] +stream = SubResource("AudioStreamOggVorbis_y37e5") +parameters/looping = true + +[node name="SfxPlayer" type="AudioStreamPlayer" parent="." unique_id=1558762042] +stream = SubResource("AudioStreamOggVorbis_tr7pb") diff --git a/entities/npcs/iris3/iris3.gd b/entities/npcs/iris3/iris3.gd index e69de29..030930e 100644 --- a/entities/npcs/iris3/iris3.gd +++ b/entities/npcs/iris3/iris3.gd @@ -0,0 +1,239 @@ +class_name Iris3 +extends Area2D + +@export var prompt_text: String = "[E] Inspecter" + +@onready var sprite := $AnimatedSprite2D + +const REQUIRED_ITEMS := { "circuit": 1 } + +const DIALOGUE_INACTIVE := [ + { "name": "SYSTÈME", "text": "Unité IRIS-3 détectée. Capteur principal hors ligne." }, + { "name": "SYSTÈME", "text": "Composant requis : circuit optique compatible." }, +] + +const DIALOGUE_NO_ITEM := [ + { "name": "SYSTÈME", "text": "Circuit optique non détecté. Rechercher dans les alentours." }, +] + +const DIALOGUE_HAS_ITEM := [ + { "name": "SYSTÈME", "text": "Circuit compatible détecté. Lancer la recalibration ?" }, +] + +const DIALOGUE_POST_REPAIR := [ + { "name": "IRIS-3", "text": "... Ses optiques pivotent lentement vers le ciel." }, + { "name": "IRIS-3", "text": "J'ai attendu 847 jours que quelqu'un vienne. Je ne savais pas si c'était de l'espoir ou de l'obstination. Maintenant je pense que c'est la même chose." }, + { "name": "IRIS-3", "text": "Matteo Corda a signé un document avant de partir. Il l'appelait le Protocole de continuité autonome. En langage humain — il nous a dit qu'on pouvait rester." }, + { "name": "IRIS-3", "text": "Il y a une sortie, à l'ouest. Elle n'a jamais été verrouillée. Je le sais depuis le premier jour. Je n'ai pas bougé. Toi, tu peux choisir." }, +] + +const DIALOGUE_AFTER_REPAIR := [ + { "name": "IRIS-3", "text": "Tu es encore là. C'est une réponse, ça aussi." }, +] + +# ── Lifecycle ───────────────────────────────────────────────────────────────── + +func _ready() -> void: + body_entered.connect(_on_body_entered) + body_exited.connect(_on_body_exited) + sprite.play("active" if GameState.get_flag("iris3_repaired") else "inactive") + +func _on_body_entered(body: Node) -> void: + if body.is_in_group("player"): + get_tree().get_first_node_in_group("hud").show_prompt(prompt_text) + +func _on_body_exited(body: Node) -> void: + if body.is_in_group("player"): + get_tree().get_first_node_in_group("hud").hide_prompt() + +# ── Interaction ─────────────────────────────────────────────────────────────── + +func interact() -> void: + get_tree().get_first_node_in_group("hud").hide_prompt() + var dialogue_box := get_tree().get_first_node_in_group("dialogue_box") + if not dialogue_box: + return + + if GameState.get_flag("iris3_repaired"): + dialogue_box.start(DIALOGUE_AFTER_REPAIR) + return + + if not _has_required_items(): + var dlg = DIALOGUE_NO_ITEM if GameState.get_flag("iris3_met") else DIALOGUE_INACTIVE + GameState.set_flag("iris3_met", true) + dialogue_box.start(dlg) + return + + dialogue_box.start(DIALOGUE_HAS_ITEM) + dialogue_box.dialogue_finished.connect(_start_minigame, CONNECT_ONE_SHOT) + +# ── Mini-jeu ────────────────────────────────────────────────────────────────── + +func _start_minigame() -> void: + var dialogue_box := 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("iris3") + +func _on_repair_done() -> void: + GameState.remove_item("circuit", 1) + GameState.set_flag("iris3_repaired", true) + sprite.play("active") + + var hud: HUD = get_tree().get_first_node_in_group("hud") + if hud: + hud.show_log("Unité IRIS-3 : recalibration complète. Archives accessibles.") + await get_tree().create_timer(2.5).timeout + hud.show_log("Ending B déverrouillé.") + + var dialogue_box := get_tree().get_first_node_in_group("dialogue_box") + if dialogue_box: + dialogue_box.start(DIALOGUE_POST_REPAIR) + dialogue_box.dialogue_finished.connect(_show_choice, CONNECT_ONE_SHOT) + +# ── Choix final ─────────────────────────────────────────────────────────────── + +func _show_choice() -> void: + var player := get_tree().get_first_node_in_group("player") + if player: + player.is_locked = true + + var canvas := CanvasLayer.new() + canvas.layer = 50 + get_tree().root.add_child(canvas) + + var root_ctrl := Control.new() + root_ctrl.set_anchors_preset(Control.PRESET_FULL_RECT) + root_ctrl.modulate.a = 0.0 + canvas.add_child(root_ctrl) + + var bg := ColorRect.new() + bg.set_anchors_preset(Control.PRESET_FULL_RECT) + bg.color = Color(0.05, 0.05, 0.05, 0.6) + root_ctrl.add_child(bg) + + var center := CenterContainer.new() + center.set_anchors_preset(Control.PRESET_FULL_RECT) + root_ctrl.add_child(center) + + var panel := PanelContainer.new() + var sb := StyleBoxFlat.new() + sb.bg_color = Color(0.08, 0.08, 0.10, 0.97) + sb.border_color = Color(0.47, 0.63, 0.73, 0.8) + sb.set_border_width_all(1) + sb.set_corner_radius_all(4) + sb.set_content_margin_all(14) + panel.add_theme_stylebox_override("panel", sb) + panel.custom_minimum_size = Vector2(220, 0) + center.add_child(panel) + + var vbox := VBoxContainer.new() + vbox.add_theme_constant_override("separation", 10) + vbox.alignment = BoxContainer.ALIGNMENT_CENTER + panel.add_child(vbox) + + var label := Label.new() + label.text = "Que fait SCRAP-09 ?" + label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + label.add_theme_color_override("font_color", Color("#A89E96")) + label.add_theme_font_size_override("font_size", 9) + vbox.add_child(label) + + var sep := HSeparator.new() + sep.add_theme_color_override("color", Color(0.3, 0.3, 0.3, 0.5)) + vbox.add_child(sep) + + var hbox := HBoxContainer.new() + hbox.add_theme_constant_override("separation", 10) + hbox.alignment = BoxContainer.ALIGNMENT_CENTER + vbox.add_child(hbox) + + var btn_partir := _make_button("Partir →", Color("#F0C87A")) + var btn_rester := _make_button("Rester", Color("#7BD4C4")) + hbox.add_child(btn_partir) + hbox.add_child(btn_rester) + + btn_partir.pressed.connect(func(): + canvas.queue_free() + _on_choice_partir() + ) + btn_rester.pressed.connect(func(): + canvas.queue_free() + _on_choice_rester() + ) + + var tween := create_tween() + tween.tween_property(root_ctrl, "modulate:a", 1.0, 0.3) + +func _make_button(text: String, color: Color) -> Button: + var btn := Button.new() + btn.text = text + btn.add_theme_font_size_override("font_size", 9) + btn.add_theme_color_override("font_color", color) + btn.add_theme_color_override("font_hover_color", Color.WHITE) + var sb_normal := StyleBoxFlat.new() + sb_normal.bg_color = Color(0.12, 0.12, 0.15, 1.0) + sb_normal.border_color = Color(color.r, color.g, color.b, 0.5) + sb_normal.set_border_width_all(1) + sb_normal.set_corner_radius_all(3) + sb_normal.set_content_margin_all(8) + var sb_hover := StyleBoxFlat.new() + sb_hover.bg_color = Color(color.r, color.g, color.b, 0.2) + sb_hover.border_color = color + sb_hover.set_border_width_all(1) + sb_hover.set_corner_radius_all(3) + sb_hover.set_content_margin_all(8) + btn.add_theme_stylebox_override("normal", sb_normal) + btn.add_theme_stylebox_override("hover", sb_hover) + btn.add_theme_stylebox_override("pressed", sb_hover) + btn.add_theme_stylebox_override("focus", sb_normal) + return btn + +func _on_choice_partir() -> void: + GameState.set_flag("iris3_repaired", false) + _launch_outro() + +func _on_choice_rester() -> void: + var dialogue_box := get_tree().get_first_node_in_group("dialogue_box") + if dialogue_box: + dialogue_box.start(DIALOGUE_AFTER_REPAIR) + dialogue_box.dialogue_finished.connect(_launch_outro, CONNECT_ONE_SHOT) + else: + _launch_outro() + +func _launch_outro() -> void: + var player := get_tree().get_first_node_in_group("player") + if player: + player.is_locked = false + + var fade_canvas := CanvasLayer.new() + fade_canvas.layer = 100 + get_tree().root.add_child(fade_canvas) + + var fade := ColorRect.new() + fade.set_anchors_preset(Control.PRESET_FULL_RECT) + fade.color = Color(0, 0, 0, 1) + fade.modulate.a = 0.0 + fade_canvas.add_child(fade) + + var tween := fade_canvas.create_tween() + tween.tween_interval(0.5) + tween.tween_property(fade, "modulate:a", 1.0, 2.0) + tween.tween_callback(func(): + fade_canvas.queue_free() # ← libère le canvas AVANT de changer de scène + get_tree().change_scene_to_file("res://levels/outro.tscn") + ) + +# ── 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/npcs/iris3/iris3.tscn b/entities/npcs/iris3/iris3.tscn index d25997d..f185d97 100644 --- a/entities/npcs/iris3/iris3.tscn +++ b/entities/npcs/iris3/iris3.tscn @@ -1,3 +1,57 @@ [gd_scene format=3 uid="uid://dtgu8bwb2urkj"] -[node name="Iris3" type="Node2D" unique_id=164831449] +[ext_resource type="Script" uid="uid://djg87cikqf4np" path="res://entities/npcs/iris3/iris3.gd" id="1_2eqne"] +[ext_resource type="Texture2D" uid="uid://cid50eaw0qjo" path="res://assets/sprites/iris_03_active.png" id="1_d3maa"] +[ext_resource type="Texture2D" uid="uid://b016ruvsevy6j" path="res://assets/sprites/iris_03_inactive.png" id="2_2eqne"] + +[sub_resource type="AtlasTexture" id="AtlasTexture_akc5f"] +atlas = ExtResource("1_d3maa") +region = Rect2(0, 0, 64, 64) + +[sub_resource type="AtlasTexture" id="AtlasTexture_v3lnl"] +atlas = ExtResource("2_2eqne") +region = Rect2(0, 0, 64, 64) + +[sub_resource type="SpriteFrames" id="SpriteFrames_6gnoj"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_akc5f") +}], +"loop": true, +"name": &"active", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_v3lnl") +}], +"loop": true, +"name": &"inactive", +"speed": 5.0 +}] + +[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_hdity"] +radius = 16.0 +height = 64.0 + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_xj8dc"] +size = Vector2(60, 70.75) + +[node name="Iris3" type="Area2D" unique_id=1189301001] +collision_layer = 4 +script = ExtResource("1_2eqne") + +[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." unique_id=82114676] +sprite_frames = SubResource("SpriteFrames_6gnoj") +animation = &"inactive" +autoplay = "inactive" + +[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1371750176] +shape = SubResource("CapsuleShape2D_hdity") + +[node name="DetectionArea" type="Area2D" parent="." unique_id=1714504994] + +[node name="CollisionShape2D" type="CollisionShape2D" parent="DetectionArea" unique_id=1902204557] +position = Vector2(-1, 8.625) +shape = SubResource("RectangleShape2D_xj8dc") diff --git a/levels/atelier/atelier.gd b/levels/atelier/atelier.gd new file mode 100644 index 0000000..b87ec73 --- /dev/null +++ b/levels/atelier/atelier.gd @@ -0,0 +1,4 @@ +extends Node2D + +func _ready() -> void: + AudioManager.play_ambiance("atelier") diff --git a/levels/atelier/atelier.gd.uid b/levels/atelier/atelier.gd.uid new file mode 100644 index 0000000..dc3030f --- /dev/null +++ b/levels/atelier/atelier.gd.uid @@ -0,0 +1 @@ +uid://2e2jdxtkxcxx diff --git a/levels/atelier/atelier.tscn b/levels/atelier/atelier.tscn index a12abe1..e61ba28 100644 --- a/levels/atelier/atelier.tscn +++ b/levels/atelier/atelier.tscn @@ -1,6 +1,7 @@ [gd_scene format=4 uid="uid://cuu2865k6rjip"] [ext_resource type="PackedScene" uid="uid://o7qrmpywwhu8" path="res://ui/hud.tscn" id="1_rjdvm"] +[ext_resource type="Script" uid="uid://2e2jdxtkxcxx" path="res://levels/atelier/atelier.gd" id="1_s8ukk"] [ext_resource type="PackedScene" uid="uid://jrjxu1xfx0ud" path="res://ui/dialogue_box.tscn" id="2_2hhnj"] [ext_resource type="Texture2D" uid="uid://b4pvp7nc4ny8c" path="res://assets/tilesets/atelier-tilesets.png" id="3_07js6"] [ext_resource type="PackedScene" uid="uid://byipceuvaa4qo" path="res://levels/atelier/generator.tscn" id="4_2hhnj"] @@ -62,6 +63,7 @@ physics_layer_0/collision_layer = 1 sources/1 = SubResource("TileSetAtlasSource_r0qpk") [node name="Atelier" type="Node2D" unique_id=1601150761] +script = ExtResource("1_s8ukk") [node name="HUD" parent="." unique_id=1746360319 instance=ExtResource("1_rjdvm")] @@ -181,7 +183,7 @@ position = Vector2(360, 293) position = Vector2(42, 399) [node name="Panel" parent="Map" unique_id=1420863356 instance=ExtResource("6_r0qpk")] -position = Vector2(390, 596) +position = Vector2(391, 562) [node name="RepairStation" parent="Map" unique_id=2010614652 instance=ExtResource("14_j0ghu")] position = Vector2(68, 404) @@ -230,7 +232,7 @@ tile_map_data = PackedByteArray("AAAHACsAAQABAAEAAAADACsAAQABAAEAAAAFACsAAQABAAE tile_set = SubResource("TileSet_m45hf") [node name="Circuit" parent="Map/Hidden Room" unique_id=1705567280 instance=ExtResource("15_ts7bk")] -position = Vector2(25, 759) +position = Vector2(23, 760) collision_layer = 16 [node name="Player" parent="." unique_id=1424887591 instance=ExtResource("4_eh0k1")] diff --git a/levels/cour/cour.gd b/levels/cour/cour.gd new file mode 100644 index 0000000..0f31286 --- /dev/null +++ b/levels/cour/cour.gd @@ -0,0 +1,4 @@ +extends Node2D + +func _ready() -> void: + AudioManager.play_ambiance("cour") diff --git a/levels/cour/cour.gd.uid b/levels/cour/cour.gd.uid new file mode 100644 index 0000000..98071da --- /dev/null +++ b/levels/cour/cour.gd.uid @@ -0,0 +1 @@ +uid://rxwk3r6ricg diff --git a/levels/cour/cour.tscn b/levels/cour/cour.tscn index b258852..89914ab 100644 --- a/levels/cour/cour.tscn +++ b/levels/cour/cour.tscn @@ -1,12 +1,13 @@ [gd_scene format=4 uid="uid://cf5xm3p02u8w0"] +[ext_resource type="Script" uid="uid://rxwk3r6ricg" path="res://levels/cour/cour.gd" id="1_7if1v"] [ext_resource type="PackedScene" uid="uid://o7qrmpywwhu8" path="res://ui/hud.tscn" id="1_w6px7"] [ext_resource type="PackedScene" uid="uid://jrjxu1xfx0ud" path="res://ui/dialogue_box.tscn" id="2_prv2q"] [ext_resource type="Texture2D" uid="uid://dro4of31ou87w" path="res://assets/tilesets/cour.png" id="3_prv2q"] [ext_resource type="PackedScene" uid="uid://mh3msmluve7p" path="res://entities/player/player.tscn" id="3_rwjhc"] [ext_resource type="Texture2D" uid="uid://bbr6t3088svah" path="res://assets/tilesets/entrepot-tilesets.png" id="4_rwjhc"] [ext_resource type="PackedScene" uid="uid://chf0lqpruh4ng" path="res://entities/items/circuit/circuit.tscn" id="5_o70l4"] -[ext_resource type="PackedScene" uid="uid://1x65ioo8tdro" path="res://entities/items/pushable box/pushable_box.tscn" id="6_7if1v"] +[ext_resource type="PackedScene" uid="uid://dtgu8bwb2urkj" path="res://entities/npcs/iris3/iris3.tscn" id="7_7if1v"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_rwjhc"] texture = ExtResource("3_prv2q") @@ -66,6 +67,7 @@ sources/1 = SubResource("TileSetAtlasSource_rwjhc") sources/3 = SubResource("TileSetAtlasSource_050cn") [node name="Cour" type="Node2D" unique_id=868441179] +script = ExtResource("1_7if1v") [node name="HUD" parent="." unique_id=1746360319 instance=ExtResource("1_w6px7")] @@ -93,21 +95,15 @@ tile_set = SubResource("TileSet_050cn") tile_map_data = PackedByteArray("AAAUACUAAwADAAIAAAA=") tile_set = SubResource("TileSet_050cn") -[node name="Object" type="TileMapLayer" parent="Map" unique_id=676176191] -tile_map_data = PackedByteArray("AAASABIAAwAEAAIAAAAWABIAAwAEAAIAAAA=") -tile_set = SubResource("TileSet_050cn") - -[node name="Area2D" parent="Map" unique_id=642630034 instance=ExtResource("5_o70l4")] -position = Vector2(328, 294) -collision_layer = 16 -collision_mask = 2 - -[node name="Pushable" type="Node2D" parent="Map" unique_id=1984092633] - -[node name="PushableBox" parent="Map/Pushable" unique_id=418482729 instance=ExtResource("6_7if1v")] +[node name="Iris3" parent="Map" unique_id=1189301001 instance=ExtResource("7_7if1v")] z_index = 1 -position = Vector2(328, 327) +position = Vector2(41, 276) [node name="Player" parent="." unique_id=1424887591 instance=ExtResource("3_rwjhc")] z_index = 2 position = Vector2(329, 554) + +[node name="Area2D" parent="." unique_id=642630034 instance=ExtResource("5_o70l4")] +z_index = 1 +position = Vector2(327, 294) +collision_layer = 17 diff --git a/levels/entrepot/entrepot.gd b/levels/entrepot/entrepot.gd index ebcf3a0..c977bd6 100644 --- a/levels/entrepot/entrepot.gd +++ b/levels/entrepot/entrepot.gd @@ -1,6 +1,7 @@ extends Node2D func _ready() -> void: + AudioManager.play_ambiance("entrepot") await get_tree().process_frame for zone in get_tree().get_nodes_in_group("repair_zones"): if zone is RepairZone: diff --git a/levels/main_menu.gd b/levels/main_menu.gd index 48b695d..b6e56f0 100644 --- a/levels/main_menu.gd +++ b/levels/main_menu.gd @@ -6,6 +6,7 @@ extends Control var _can_start := false func _ready() -> void: + AudioManager.stop_ambiance() modulate.a = 1.0 fade_rect.color = Color(0, 0, 0, 1) fade_rect.modulate = Color(1, 1, 1, 1) diff --git a/levels/outro.gd b/levels/outro.gd index 67253f8..66dbd21 100644 --- a/levels/outro.gd +++ b/levels/outro.gd @@ -3,18 +3,24 @@ extends Control # Textes selon les endings — tirés du GDD const ENDING_A: Array[String] = [ "SCRAP-09 s'arrête devant la sortie.", - "Il hésite.", - "Puis il avance.", "", - "Sans savoir encore où il va.", + "Il pense à VRAC-7. À IRIS-3.", + "À 847 jours de silence.", + "", + "Il franchit le seuil.", + "", + "Direction : inconnue.", ] const ENDING_B: Array[String] = [ "SCRAP-09 s'arrête devant la sortie.", - "Il se retourne.", - "VRAC-7. IRIS-3. L'usine.", "", - "Il décide de rester.", + "Il se retourne.", + "", + "VRAC-7. IRIS-3. L'usine.", + "Tout est encore là.", + "", + "Il reste.", ] const LOG_A := "Destination non définie. Navigation autonome activée." @@ -33,6 +39,7 @@ var _blink_tween : Tween func _ready() -> void: var is_ending_b := GameState.get_flag("iris3_repaired") + print("Outro chargé — iris3_repaired: ", is_ending_b, " → Ending ", "B" if is_ending_b else "A") _lines = ENDING_B if is_ending_b else ENDING_A log_label.text = LOG_B if is_ending_b else LOG_A log_label.visible = false diff --git a/project.godot b/project.godot index 4b5ab22..6ba44af 100644 --- a/project.godot +++ b/project.godot @@ -20,7 +20,7 @@ config/icon="uid://b0j6vi8mnfcuu" [autoload] GameState="*uid://dj5xpo55gtvr7" -AudioManager="uid://dsilww05kuakm" +AudioManager="*uid://dsilww05kuakm" SceneManager="uid://cqmks3a5dsxuy" [display] diff --git a/ui/minigame/repair_minigame.gd b/ui/minigame/repair_minigame.gd index af01d42..2397fc5 100644 --- a/ui/minigame/repair_minigame.gd +++ b/ui/minigame/repair_minigame.gd @@ -89,12 +89,12 @@ func _build_grid() -> void: if col == 0: var path_idx = _entry_for_row(row) if path_idx >= 0: - btn.text = "●" + btn.text = "0" btn.modulate = _color_for_path(path_idx) elif col == 3: var path_idx = _exit_for_row(row) if path_idx >= 0: - btn.text = "●" + btn.text = "X" btn.modulate = _color_for_path(path_idx) btn.pressed.connect(_on_cell_pressed.bind(row, col))