From 142a24a8957b7a2379918f214532875399fe882b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Mart=C3=ADnez=20Palacio?= Date: Mon, 7 Oct 2024 13:08:29 +0200 Subject: [PATCH] Add cutscene system --- Cutscenes/prototype_defeated.tres | 14 ++ Cutscenes/prototype_start.tres | 37 +++ Hiro/hiro_ai.gdshader | 15 ++ Hiro/hiro_ai_shader.tres | 51 +++++ Scripts/Cutscenes/Commands/base.gd | 5 + Scripts/Cutscenes/Commands/emit_message.gd | 3 + Scripts/Cutscenes/Commands/set_flag.gd | 5 + Scripts/Cutscenes/Commands/show_dialogue.gd | 11 + Scripts/Cutscenes/Commands/turn_character.gd | 15 ++ Scripts/Cutscenes/cutscene.gd | 4 + Scripts/Cutscenes/manager.gd | 33 +++ Scripts/Levels/arena_level.gd | 24 ++ Scripts/UI/textbox.gd | 99 ++++++++ Scripts/hiro_ai.gd | 6 + Scripts/util.gd | 15 ++ UI/textbox_ui.tscn | 229 +++++++++++++++++-- world/world.tscn | 57 +++-- 17 files changed, 585 insertions(+), 38 deletions(-) create mode 100644 Cutscenes/prototype_defeated.tres create mode 100644 Cutscenes/prototype_start.tres create mode 100644 Hiro/hiro_ai.gdshader create mode 100644 Hiro/hiro_ai_shader.tres create mode 100644 Scripts/Cutscenes/Commands/base.gd create mode 100644 Scripts/Cutscenes/Commands/emit_message.gd create mode 100644 Scripts/Cutscenes/Commands/set_flag.gd create mode 100644 Scripts/Cutscenes/Commands/show_dialogue.gd create mode 100644 Scripts/Cutscenes/Commands/turn_character.gd create mode 100644 Scripts/Cutscenes/cutscene.gd create mode 100644 Scripts/Cutscenes/manager.gd create mode 100644 Scripts/UI/textbox.gd create mode 100644 Scripts/util.gd diff --git a/Cutscenes/prototype_defeated.tres b/Cutscenes/prototype_defeated.tres new file mode 100644 index 0000000..abf7f52 --- /dev/null +++ b/Cutscenes/prototype_defeated.tres @@ -0,0 +1,14 @@ +[gd_resource type="Resource" script_class="Cutscene" load_steps=4 format=3 uid="uid://cwfayxsvfvfp3"] + +[ext_resource type="Script" path="res://Scripts/Cutscenes/cutscene.gd" id="1_5oimi"] +[ext_resource type="Script" path="res://Scripts/Cutscenes/Commands/show_dialogue.gd" id="1_m28bn"] + +[sub_resource type="Resource" id="Resource_eeatu"] +script = ExtResource("1_m28bn") +character = 0 +messages = Array[String](["Ha! I won! Told you I kill you!"]) +textbox_direction = 0 + +[resource] +script = ExtResource("1_5oimi") +commands = Array[Resource("res://Scripts/Cutscenes/Commands/base.gd")]([SubResource("Resource_eeatu")]) diff --git a/Cutscenes/prototype_start.tres b/Cutscenes/prototype_start.tres new file mode 100644 index 0000000..90e8860 --- /dev/null +++ b/Cutscenes/prototype_start.tres @@ -0,0 +1,37 @@ +[gd_resource type="Resource" script_class="Cutscene" load_steps=9 format=3 uid="uid://bj3rm1r1ouq0r"] + +[ext_resource type="Script" path="res://Scripts/Cutscenes/cutscene.gd" id="1_ejncn"] +[ext_resource type="Script" path="res://Scripts/Cutscenes/Commands/show_dialogue.gd" id="1_r5tuj"] +[ext_resource type="Script" path="res://Scripts/Cutscenes/Commands/turn_character.gd" id="2_eqfp1"] + +[sub_resource type="Resource" id="Resource_o72ak"] +script = ExtResource("2_eqfp1") +character = NodePath("../HiroPlayer") +facing_direction = 3 + +[sub_resource type="Resource" id="Resource_vdtv6"] +script = ExtResource("2_eqfp1") +character = NodePath("../HiroAI") +facing_direction = 0 + +[sub_resource type="Resource" id="Resource_r2p8t"] +script = ExtResource("1_r5tuj") +character = 0 +messages = Array[String](["This is a test for the cutscene!", "Now I'm going to kill you!"]) +textbox_direction = 1 + +[sub_resource type="Resource" id="Resource_fuu2y"] +script = ExtResource("2_eqfp1") +character = NodePath("../HiroPlayer") +facing_direction = 2 + +[sub_resource type="Resource" id="Resource_x3xc6"] +script = ExtResource("1_r5tuj") +character = 0 +messages = Array[String](["Whaaat? Who are you!?", "You have no chance against me!!"]) +textbox_direction = 0 + +[resource] +resource_name = "prototype_start" +script = ExtResource("1_ejncn") +commands = Array[Resource("res://Scripts/Cutscenes/Commands/base.gd")]([SubResource("Resource_o72ak"), SubResource("Resource_vdtv6"), SubResource("Resource_r2p8t"), SubResource("Resource_fuu2y"), SubResource("Resource_x3xc6")]) diff --git a/Hiro/hiro_ai.gdshader b/Hiro/hiro_ai.gdshader new file mode 100644 index 0000000..10a8247 --- /dev/null +++ b/Hiro/hiro_ai.gdshader @@ -0,0 +1,15 @@ +shader_type canvas_item; +render_mode blend_mix; + +uniform vec3 tint_color : source_color = vec3(1.0, 0.0, 0.0); +uniform float intensity : hint_range(0, 1) = 1.0; + +void fragment() { + COLOR = vec4(mix(COLOR.rgb, tint_color, intensity), COLOR.a); +} + +// bleh, we prolly don't need this +//void light() { + //vec4 color = COLOR; + //LIGHT = vec4(color.rgb * LIGHT_COLOR.rgb * LIGHT_ENERGY, LIGHT_COLOR.a * (1.0 - intensity)); +//} diff --git a/Hiro/hiro_ai_shader.tres b/Hiro/hiro_ai_shader.tres new file mode 100644 index 0000000..62954b2 --- /dev/null +++ b/Hiro/hiro_ai_shader.tres @@ -0,0 +1,51 @@ +[gd_resource type="VisualShader" load_steps=4 format=3 uid="uid://dmoh1f7aoriyv"] + +[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_jknad"] +expanded_output_ports = [0] +input_name = "color" + +[sub_resource type="VisualShaderNodeColorParameter" id="VisualShaderNodeColorParameter_bpbi7"] +expanded_output_ports = [0] +parameter_name = "Tint_Color" + +[sub_resource type="VisualShaderNodeMix" id="VisualShaderNodeMix_rbqa7"] +default_input_values = [0, Vector3(0, 0, 0), 1, Vector3(1, 1, 1), 2, Vector3(0.5, 0.5, 0.5)] +op_type = 3 + +[resource] +code = "shader_type canvas_item; +render_mode blend_mix; + +uniform vec4 Tint_Color : source_color; + + + +void fragment() { +// Input:2 + vec4 n_out2p0 = COLOR; + + +// ColorParameter:3 + vec4 n_out3p0 = Tint_Color; + float n_out3p4 = n_out3p0.a; + + +// Mix:4 + vec3 n_out4p0 = mix(vec3(n_out2p0.xyz), vec3(n_out3p0.xyz), vec3(n_out3p4)); + + +// Output:0 + COLOR.rgb = n_out4p0; + + +} +" +mode = 1 +flags/light_only = false +nodes/fragment/2/node = SubResource("VisualShaderNodeInput_jknad") +nodes/fragment/2/position = Vector2(-340, 60) +nodes/fragment/3/node = SubResource("VisualShaderNodeColorParameter_bpbi7") +nodes/fragment/3/position = Vector2(-280, 260) +nodes/fragment/4/node = SubResource("VisualShaderNodeMix_rbqa7") +nodes/fragment/4/position = Vector2(140, 100) +nodes/fragment/connections = PackedInt32Array(2, 0, 4, 0, 3, 0, 4, 1, 3, 4, 4, 2, 4, 0, 0, 0) diff --git a/Scripts/Cutscenes/Commands/base.gd b/Scripts/Cutscenes/Commands/base.gd new file mode 100644 index 0000000..d92228a --- /dev/null +++ b/Scripts/Cutscenes/Commands/base.gd @@ -0,0 +1,5 @@ +extends Resource +class_name CutsceneCommand + +func validate() -> bool: + return true diff --git a/Scripts/Cutscenes/Commands/emit_message.gd b/Scripts/Cutscenes/Commands/emit_message.gd new file mode 100644 index 0000000..9056d55 --- /dev/null +++ b/Scripts/Cutscenes/Commands/emit_message.gd @@ -0,0 +1,3 @@ +class_name EmitMessageCommand extends CutsceneCommand + +@export var message: StringName = "" diff --git a/Scripts/Cutscenes/Commands/set_flag.gd b/Scripts/Cutscenes/Commands/set_flag.gd new file mode 100644 index 0000000..3f4574b --- /dev/null +++ b/Scripts/Cutscenes/Commands/set_flag.gd @@ -0,0 +1,5 @@ +class_name SetFlagCommand extends CutsceneCommand + +@export var target: NodePath +@export var property: String +@export var value = false diff --git a/Scripts/Cutscenes/Commands/show_dialogue.gd b/Scripts/Cutscenes/Commands/show_dialogue.gd new file mode 100644 index 0000000..f214559 --- /dev/null +++ b/Scripts/Cutscenes/Commands/show_dialogue.gd @@ -0,0 +1,11 @@ +extends CutsceneCommand +class_name ShowDialogueCommand + +enum TextboxDirection { + LEFT, + RIGHT +} + +@export var character: Util.CastCharacter +@export var messages: Array[String] = [] +@export var textbox_direction = TextboxDirection.LEFT diff --git a/Scripts/Cutscenes/Commands/turn_character.gd b/Scripts/Cutscenes/Commands/turn_character.gd new file mode 100644 index 0000000..e801233 --- /dev/null +++ b/Scripts/Cutscenes/Commands/turn_character.gd @@ -0,0 +1,15 @@ +extends CutsceneCommand +class_name TurnCharacterCommand + +@export_node_path("CharacterBody2D") var character: NodePath +@export var facing_direction: Util.CardinalDirection + +var _directions = [ + Vector2.UP, + Vector2.LEFT, + Vector2.DOWN, + Vector2.RIGHT +] + +func get_direction() -> Vector2: + return _directions[facing_direction] diff --git a/Scripts/Cutscenes/cutscene.gd b/Scripts/Cutscenes/cutscene.gd new file mode 100644 index 0000000..be7b768 --- /dev/null +++ b/Scripts/Cutscenes/cutscene.gd @@ -0,0 +1,4 @@ +extends Resource +class_name Cutscene + +@export var commands: Array[CutsceneCommand] = [] diff --git a/Scripts/Cutscenes/manager.gd b/Scripts/Cutscenes/manager.gd new file mode 100644 index 0000000..3629f11 --- /dev/null +++ b/Scripts/Cutscenes/manager.gd @@ -0,0 +1,33 @@ +extends Node +class_name CutsceneManager + +signal loaded(cutscene_name: String) +signal started(cutscene_name: String) +signal issued_command(command: CutsceneCommand, manager: CutsceneManager) +signal finished(cutscene_name: String) + +@export var cutscene: Cutscene + +@onready var _step = -1 +var _current_command: CutsceneCommand: get = get_current_command + +func get_current_command() -> CutsceneCommand: + return _current_command + +func step() -> void: + _step += 1 + if(_step == 0): + started.emit(cutscene.resource_name) + if(_step >= cutscene.commands.size()): + finished.emit(cutscene.resource_name) + else: + _current_command = cutscene.commands[_step] + issued_command.emit(_current_command, self) + +func load_cutscene(new_cutscene: Cutscene) -> void: + cutscene = new_cutscene + _step = -1 + loaded.emit(cutscene.resource_name) + +func _on_ui_dialogue_completed(): + step() diff --git a/Scripts/Levels/arena_level.gd b/Scripts/Levels/arena_level.gd index 59a6282..bb44b77 100644 --- a/Scripts/Levels/arena_level.gd +++ b/Scripts/Levels/arena_level.gd @@ -9,11 +9,35 @@ func _ready(): battle_ui.initialize(player.health, ai.health) battle_ui.set_player_health(player.health) battle_ui.set_enemy_health(ai.health) + $CutsceneManager.step() func _on_player_defeated(): if Globals.nsfw == true: explosion_generator.spawn(player.position) + var cutscene = load("res://Cutscenes/prototype_defeated.tres") + $CutsceneManager.load_cutscene(cutscene) + $CutsceneManager.step() func _on_ai_defeated(): if Globals.nsfw == true: explosion_generator.spawn(ai.position) + +func _on_cutscene_started(cutscene_name): + $HiroPlayer.can_move = false + if cutscene_name == "prototype_start": + $HiroAI.set_ai_enabled(false) + +func _on_cutscene_finished(cutscene_name: String): + print("Cutscene " + cutscene_name + " finished") + $HiroPlayer.can_move = true + if cutscene_name == "prototype_start": + $HiroAI.set_ai_enabled(true) + + +func _on_cutscene_manager_issued_command(command: CutsceneCommand, manager: CutsceneManager): + if command is TurnCharacterCommand: + var character = manager.get_node(command.character) + # TODO: We need to set a common class for character nodes. + assert(character is CharacterBody2D and character.has_method("set_animation_direction")) + character.set_animation_direction(command.get_direction()) + manager.step() diff --git a/Scripts/UI/textbox.gd b/Scripts/UI/textbox.gd new file mode 100644 index 0000000..c822262 --- /dev/null +++ b/Scripts/UI/textbox.gd @@ -0,0 +1,99 @@ +extends CanvasLayer + +enum TextboxDirection { + LEFT, + RIGHT +} + +# CPS = Characters per second +@export var cps = 3.0 + +@onready var animation_player = $AnimationPlayer +@onready var _textboxes = [ + $LeftTextbox/ChatboxContainer/Chatbox/PlacementContainer/MarginContainer/Text, + $RightTextbox/ChatboxContainer/Chatbox/PlacementContainer/MarginContainer/Text +] +@onready var _portraits = [ + $LeftTextbox/ChatboxContainer/Portrait, + $RightTextbox/ChatboxContainer/Portrait +] +@onready var _indicators = [ + $LeftTextbox/ChatboxContainer/Chatbox/PlacementContainer/NextIndicator, + $RightTextbox/ChatboxContainer/Chatbox/PlacementContainer/NextIndicator +] + +signal display_completed +signal dialogue_continued +signal dialogue_completed + +var _direction = TextboxDirection.LEFT +var _directions = ["left", "right"] +var _dialogue: Array[String] = [] +var _next = 0 +var _text = "" +var _display_text = "" +var _displaying = false +var frames = 0.0 + +func _ready(): + for textbox in _textboxes: + textbox.size = Vector2(720, 480) + +func _process(delta): + if _displaying: + if _display_text == _text: + _displaying = false + display_completed.emit() + else: + frames += delta + if frames >= 1/cps: + frames = 0.0 + _display_text = _display_text + _text.substr(_display_text.length(), 1) + _textboxes[_direction].text = _display_text + for i in _indicators.size(): + var indicator = _indicators[i] + indicator.visible = i == _direction && !_displaying && !animation_player.is_playing() + +func _input(event): + if event.is_action_pressed("ui_accept"): + if _displaying: + _display_text = _text + _displaying = false + get_viewport().set_input_as_handled() + elif _display_text == _text: + dialogue_continued.emit() + _dialogue_continue() + get_viewport().set_input_as_handled() + +func _dialogue_start(_who: Util.CastCharacter, dialogue: Array[String], direction: TextboxDirection): + _next = 0 + _direction = direction + _dialogue = dialogue + _text = _dialogue[_next] + _display_text = "" + animation_player.play("show_" + _directions[_direction]) + +func _dialogue_continue(): + _next += 1 + if _next >= _dialogue.size(): + _end_dialogue() + else: + _text = _dialogue[_next] + _display_text = "" + _displaying = true + +func _end_dialogue(): + _text = "" + _display_text = "" + _displaying = false # just in case + animation_player.play("hide_" + _directions[_direction]) + +func _on_animation_finished(anim_name: StringName): + if anim_name.contains("show"): + _displaying = true + elif anim_name.contains("hide"): + dialogue_completed.emit() + +func _on_cutscene_command_issued(command: CutsceneCommand, _manager: CutsceneManager): + if command is ShowDialogueCommand: + _dialogue_start(command.character, command.messages, command.textbox_direction) diff --git a/Scripts/hiro_ai.gd b/Scripts/hiro_ai.gd index 89d5a7a..ac30ec7 100644 --- a/Scripts/hiro_ai.gd +++ b/Scripts/hiro_ai.gd @@ -54,6 +54,12 @@ func _physics_process(_delta): func _on_player_attack_did_hit(other, attack_power: int, attack_direction: Vector2): if other.get_parent().get_instance_id() == get_instance_id() : _on_ai_got_hurt(attack_power, attack_direction) + +func set_ai_process_mode(mode: ProcessMode): + $StateMachine.process_mode = mode + +func set_ai_enabled(enabled: bool): + set_ai_process_mode(Node.PROCESS_MODE_INHERIT if enabled else Node.PROCESS_MODE_DISABLED) func _on_ai_got_hurt(attack_power: int, attack_direction: Vector2): attacked_from = attack_direction diff --git a/Scripts/util.gd b/Scripts/util.gd new file mode 100644 index 0000000..e77f8e2 --- /dev/null +++ b/Scripts/util.gd @@ -0,0 +1,15 @@ +extends Object +class_name Util + +enum CastCharacter { + hiro, + reed, + nem +} + +enum CardinalDirection { + North, + West, + South, + East +} diff --git a/UI/textbox_ui.tscn b/UI/textbox_ui.tscn index 0ca1b01..fba752d 100644 --- a/UI/textbox_ui.tscn +++ b/UI/textbox_ui.tscn @@ -1,5 +1,6 @@ -[gd_scene load_steps=4 format=3 uid="uid://7oi3hcf5q4o7"] +[gd_scene load_steps=11 format=3 uid="uid://7oi3hcf5q4o7"] +[ext_resource type="Script" path="res://Scripts/UI/textbox.gd" id="1_nbji8"] [ext_resource type="FontFile" uid="uid://bgqotudi6bifk" path="res://UI/Gundam 00 font gaufont.ttf" id="1_p6ypw"] [ext_resource type="Texture2D" uid="uid://b7opep16uyb5r" path="res://Hiro/testportrait.png" id="2_6wmjm"] @@ -7,15 +8,120 @@ font = ExtResource("1_p6ypw") font_size = 18 -[node name="TextboxUI" type="Control"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 +[sub_resource type="Animation" id="Animation_pk8my"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("LeftTextbox:position") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(-720, 0)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("RightTextbox:position") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(720, 0)] +} -[node name="ChatboxContainer" type="Control" parent="."] +[sub_resource type="Animation" id="Animation_eq77b"] +resource_name = "hide" +length = 0.266668 +step = 0.0166667 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("LeftTextbox:position") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.266667), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector2(0, 0), Vector2(-720, 0)] +} + +[sub_resource type="Animation" id="Animation_o6mf0"] +resource_name = "hide_right" +length = 0.250002 +step = 0.0166667 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("RightTextbox:position") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.25), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector2(0, 0), Vector2(720, 0)] +} + +[sub_resource type="Animation" id="Animation_cb4qc"] +resource_name = "show" +length = 0.266668 +step = 0.0166667 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("LeftTextbox:position") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.266667), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector2(-720, 0), Vector2(0, 0)] +} + +[sub_resource type="Animation" id="Animation_ucf3h"] +resource_name = "show_right" +length = 0.250002 +step = 0.0166667 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("RightTextbox:position") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.25), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector2(720, 0), Vector2(0, 0)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_c2uka"] +_data = { +"RESET": SubResource("Animation_pk8my"), +"hide_left": SubResource("Animation_eq77b"), +"hide_right": SubResource("Animation_o6mf0"), +"show_left": SubResource("Animation_cb4qc"), +"show_right": SubResource("Animation_ucf3h") +} + +[node name="TextboxUI" type="CanvasLayer"] +script = ExtResource("1_nbji8") + +[node name="LeftTextbox" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 0 +offset_left = -720.0 +offset_bottom = 480.0 + +[node name="ChatboxContainer" type="Control" parent="LeftTextbox"] layout_mode = 1 anchor_top = 0.55 anchor_right = 1.0 @@ -23,7 +129,7 @@ anchor_bottom = 0.95 grow_horizontal = 2 grow_vertical = 0 -[node name="Chatbox" type="PanelContainer" parent="ChatboxContainer"] +[node name="Chatbox" type="PanelContainer" parent="LeftTextbox/ChatboxContainer"] layout_mode = 1 anchors_preset = -1 anchor_top = 0.358 @@ -33,10 +139,11 @@ grow_horizontal = 2 grow_vertical = 2 size_flags_horizontal = 3 -[node name="PlacementContainer" type="Control" parent="ChatboxContainer/Chatbox"] +[node name="PlacementContainer" type="Control" parent="LeftTextbox/ChatboxContainer/Chatbox"] layout_mode = 2 -[node name="NextIndicator" type="Label" parent="ChatboxContainer/Chatbox/PlacementContainer"] +[node name="NextIndicator" type="Label" parent="LeftTextbox/ChatboxContainer/Chatbox/PlacementContainer"] +visible = false layout_mode = 1 anchors_preset = -1 anchor_left = 1.0 @@ -50,7 +157,7 @@ grow_vertical = 0 text = ">" label_settings = SubResource("LabelSettings_ydgvr") -[node name="MarginContainer" type="MarginContainer" parent="ChatboxContainer/Chatbox/PlacementContainer"] +[node name="MarginContainer" type="MarginContainer" parent="LeftTextbox/ChatboxContainer/Chatbox/PlacementContainer"] layout_mode = 1 anchors_preset = -1 anchor_left = 0.269 @@ -63,16 +170,15 @@ theme_override_constants/margin_top = 16 theme_override_constants/margin_right = 16 theme_override_constants/margin_bottom = 16 -[node name="Text" type="Label" parent="ChatboxContainer/Chatbox/PlacementContainer/MarginContainer"] +[node name="Text" type="Label" parent="LeftTextbox/ChatboxContainer/Chatbox/PlacementContainer/MarginContainer"] custom_minimum_size = Vector2(100, 0) layout_mode = 2 size_flags_vertical = 1 -text = "Hello my name is Hiro Toyama, you destroyed my gunpla. Now I'm going to kill you." label_settings = SubResource("LabelSettings_ydgvr") autowrap_mode = 2 text_overrun_behavior = 3 -[node name="Portrait" type="TextureRect" parent="ChatboxContainer"] +[node name="Portrait" type="TextureRect" parent="LeftTextbox/ChatboxContainer"] layout_mode = 1 anchors_preset = -1 anchor_right = 0.286 @@ -81,3 +187,94 @@ grow_vertical = 0 texture = ExtResource("2_6wmjm") expand_mode = 1 stretch_mode = 5 + +[node name="RightTextbox" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 1 +anchor_left = 1.0 +anchor_right = 1.0 +offset_left = 720.0 +offset_right = 1440.0 +offset_bottom = 480.0 +grow_horizontal = 0 + +[node name="ChatboxContainer" type="Control" parent="RightTextbox"] +layout_mode = 1 +anchor_top = 0.55 +anchor_right = 1.0 +anchor_bottom = 0.95 +grow_horizontal = 2 +grow_vertical = 0 + +[node name="Chatbox" type="PanelContainer" parent="RightTextbox/ChatboxContainer"] +layout_mode = 1 +anchors_preset = -1 +anchor_top = 0.358 +anchor_right = 0.9 +anchor_bottom = 1.0 +offset_left = 72.0 +offset_right = 72.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 + +[node name="PlacementContainer" type="Control" parent="RightTextbox/ChatboxContainer/Chatbox"] +layout_mode = 2 + +[node name="NextIndicator" type="Label" parent="RightTextbox/ChatboxContainer/Chatbox/PlacementContainer"] +layout_mode = 1 +anchors_preset = -1 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_right = -16.0 +offset_bottom = -16.0 +grow_horizontal = 0 +grow_vertical = 0 +text = ">" +label_settings = SubResource("LabelSettings_ydgvr") + +[node name="MarginContainer" type="MarginContainer" parent="RightTextbox/ChatboxContainer/Chatbox/PlacementContainer"] +layout_mode = 1 +anchors_preset = -1 +anchor_left = 0.269 +anchor_right = 0.919 +anchor_bottom = 1.0 +offset_left = -137.312 +offset_right = -137.312 +grow_vertical = 2 +size_flags_horizontal = 0 +theme_override_constants/margin_left = 16 +theme_override_constants/margin_top = 16 +theme_override_constants/margin_right = 16 +theme_override_constants/margin_bottom = 16 + +[node name="Text" type="Label" parent="RightTextbox/ChatboxContainer/Chatbox/PlacementContainer/MarginContainer"] +custom_minimum_size = Vector2(100, 0) +layout_mode = 2 +size_flags_vertical = 1 +text = "Lorem ipsum dolor sit amet +Quantiscat et sigmus dolmen romani ite domus +......." +label_settings = SubResource("LabelSettings_ydgvr") +autowrap_mode = 2 +text_overrun_behavior = 3 + +[node name="Portrait" type="TextureRect" parent="RightTextbox/ChatboxContainer"] +layout_mode = 1 +anchors_preset = -1 +anchor_left = 0.65 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_vertical = 0 +texture = ExtResource("2_6wmjm") +expand_mode = 1 +stretch_mode = 5 + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +libraries = { +"": SubResource("AnimationLibrary_c2uka") +} + +[connection signal="animation_finished" from="AnimationPlayer" to="." method="_on_animation_finished"] diff --git a/world/world.tscn b/world/world.tscn index ba3593e..e3cefab 100644 --- a/world/world.tscn +++ b/world/world.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=21 format=3 uid="uid://bxuxjqxxqy7ce"] +[gd_scene load_steps=23 format=3 uid="uid://bxuxjqxxqy7ce"] [ext_resource type="PackedScene" uid="uid://di21xheryhp0k" path="res://Hiro/hiro_player.tscn" id="1_c1gpq"] [ext_resource type="PackedScene" uid="uid://b8sfype1vx5ad" path="res://Nem/nem_npc.tscn" id="1_sqt7d"] @@ -18,6 +18,8 @@ [ext_resource type="Texture2D" uid="uid://jnub86bpiebw" path="res://NPCs/npc4.png" id="14_46hs3"] [ext_resource type="Texture2D" uid="uid://baw6gijyxv1fv" path="res://NPCs/npc5.png" id="15_ppm1i"] [ext_resource type="Texture2D" uid="uid://bcvxfjlg8mmjr" path="res://NPCs/npc6.png" id="16_cgyrp"] +[ext_resource type="Script" path="res://Scripts/Cutscenes/manager.gd" id="19_5yvrq"] +[ext_resource type="Resource" uid="uid://bj3rm1r1ouq0r" path="res://Cutscenes/prototype_start.tres" id="20_elypl"] [sub_resource type="Gradient" id="Gradient_3ox2i"] colors = PackedColorArray(0, 0, 0, 1, 0, 0, 0, 1) @@ -29,6 +31,29 @@ gradient = SubResource("Gradient_3ox2i") y_sort_enabled = true script = ExtResource("1_y634h") +[node name="TextboxUI" parent="." instance=ExtResource("12_8pgvx")] +layer = 2 +cps = 100.0 + +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="BattleUI" parent="CanvasLayer" instance=ExtResource("10_hxn8m")] + +[node name="Debug" type="Control" parent="CanvasLayer"] +visible = false +layout_mode = 3 +anchor_left = 0.667 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 0 +grow_vertical = 2 + +[node name="StateChartDebugger" parent="CanvasLayer/Debug" instance=ExtResource("2_o5str")] +layout_mode = 1 +size_flags_horizontal = 0 +enabled = false +initial_node_to_watch = NodePath("../../../HiroAI") + [node name="MapElements" type="Node2D" parent="."] y_sort_enabled = true position = Vector2(-136, -190) @@ -123,27 +148,6 @@ MELEE_RADIUS = 300 [node name="ExplosionGenerator" type="Node" parent="."] script = ExtResource("9_df2wo") -[node name="CanvasLayer" type="CanvasLayer" parent="."] - -[node name="BattleUI" parent="CanvasLayer" instance=ExtResource("10_hxn8m")] - -[node name="Debug" type="Control" parent="CanvasLayer"] -visible = false -layout_mode = 3 -anchor_left = 0.667 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 0 -grow_vertical = 2 - -[node name="StateChartDebugger" parent="CanvasLayer/Debug" instance=ExtResource("2_o5str")] -layout_mode = 1 -size_flags_horizontal = 0 -enabled = false -initial_node_to_watch = NodePath("../../../HiroAI") - -[node name="TextboxUI" parent="CanvasLayer" instance=ExtResource("12_8pgvx")] - [node name="NPCs" type="Node2D" parent="."] visible = false @@ -177,6 +181,11 @@ texture_filter = 1 position = Vector2(285, -102) texture = ExtResource("16_cgyrp") +[node name="CutsceneManager" type="Node" parent="."] +script = ExtResource("19_5yvrq") +cutscene = ExtResource("20_elypl") + +[connection signal="dialogue_completed" from="TextboxUI" to="CutsceneManager" method="_on_ui_dialogue_completed"] [connection signal="attack_did_hit" from="HiroPlayer" to="HiroAI" method="_on_player_attack_did_hit"] [connection signal="defeated" from="HiroPlayer" to="." method="_on_player_defeated"] [connection signal="defeated" from="HiroPlayer" to="HiroAI" method="_on_player_been_defeated"] @@ -184,3 +193,7 @@ texture = ExtResource("16_cgyrp") [connection signal="attack_did_hit" from="HiroAI" to="HiroPlayer" method="_on_enemy_attack_did_hit"] [connection signal="defeated" from="HiroAI" to="." method="_on_ai_defeated"] [connection signal="got_hurt" from="HiroAI" to="CanvasLayer/BattleUI" method="_on_enemy_got_hurt"] +[connection signal="finished" from="CutsceneManager" to="." method="_on_cutscene_finished"] +[connection signal="issued_command" from="CutsceneManager" to="." method="_on_cutscene_manager_issued_command"] +[connection signal="issued_command" from="CutsceneManager" to="TextboxUI" method="_on_cutscene_command_issued"] +[connection signal="started" from="CutsceneManager" to="." method="_on_cutscene_started"]