dialog and intro state
							parent
							
								
									89f2e375cf
								
							
						
					
					
						commit
						5fab0c8ff0
					
				|  | @ -0,0 +1,26 @@ | |||
| Join Doc | ||||
| Doc: The name... | ||||
| Doc: is... | ||||
| Doc: I'm the Two Time, back-to-back, consecutive years... | ||||
| Doc: You were still in your little diapers... | ||||
| Doc: Still in your little onesies, pajamas, little footsy pajamas. He-man pajamas. Spiderman pajamas. | ||||
| Doc: You are still sleeping on the top of your bunk bed, underneath your blankets, scared to death of the boogieman underneath your bed! | ||||
| Doc: You were still there. | ||||
| Doc: While I was out. | ||||
| Doc: At Marine World. | ||||
| Doc: Winning. | ||||
| Doc: Two years in a row. | ||||
| Doc: The 1993-1994 Blockbuster video game championship. | ||||
| Doc: Right in front of the killer whale exhibit. 200+ TVs. NBA Jam. | ||||
| Doc: I AM THE... | ||||
| Doc: I'm an international video game superstar. | ||||
| Doc: I'm 6'8", 37" vertical leap. A jawline that will cut, slice, deliver anything that you will ever dream of right to your front door. | ||||
| Doc: Nothing but success. Nothing but success. | ||||
| Doc: That's what my life's about. Period. | ||||
| Doc: And the arena today, ladies and gentlemen... | ||||
| Doc: is wide open, and the crowds are flooding in. VIP seating. Skybox section. Reserved for the Slick Daddy Club. | ||||
| Doc: The Slick Daddy Club looking so damn good today. I'm feeling so damn good, it's OBVIOUS. | ||||
| Doc: The V of success. | ||||
| Challenge Doc, The Two Time? | ||||
| - Yes | ||||
| - No | ||||
|  | @ -0,0 +1,28 @@ | |||
| ~ duel | ||||
| 
 | ||||
| Doc, The Two Time: The name... | ||||
| Doc, The Two Time: is Doctor... | ||||
| Doc, The Two Time: Disrespect. | ||||
| Doc, The Two Time: I'm the two-time, back to back, consecutive years... | ||||
| Doc, The Two Time: A lot of you were still in your little diapers. | ||||
| Doc, The Two Time: Still in your little onesies, pajamas. Little footsy pajamas. He-Man pajamas. Spiderman pajamas. | ||||
| Doc, The Two Time: A lot of you were still sleeping on the top of your bunk bed, underneath your blankets, scared to death of the boogieman underneath your bed. | ||||
| Doc, The Two Time: A lot of you were still there. | ||||
| Doc, The Two Time: While I was out... | ||||
| Doc, The Two Time: at Marine World. | ||||
| Doc, The Two Time: Winning. | ||||
| Doc, The Two Time: Two years in a row. The 1993-1994 Blockbuster video game championship right in front of the killer whale exhibit. 200+ TVs. NBA Jam. | ||||
| Doc, The Two Time: I AM THE... | ||||
| Doc, The Two Time: I'm an international videogame superstar. I'm 6'8", 37" vertical leap. A jawline that will cut, slice, deliver anything that you will ever dream of right to your front door. | ||||
| Doc, The Two Time: Nothing but success. | ||||
| Doc, The Two Time: That's what my life's about. Period. | ||||
| Doc, The Two Time: And the arena today, ladies and gentlemen... | ||||
| Doc, The Two Time: is wide open, and the crowds are flooding in. VIP seating. Skybox section. Reserved for the Slick Daddy Club. | ||||
| Doc, The Two Time: The Slick Daddy Club looking so damn good today. I'm feeling so damn good. It's obvious. | ||||
| Doc, The Two Time: The V of success. | ||||
| Challenge [b]Doc, The Two Time[/b]? | ||||
| - Yes | ||||
| 	do emit("SummonBoss", "Doc") | ||||
| - No => END | ||||
| 
 | ||||
| => END | ||||
|  | @ -0,0 +1,15 @@ | |||
| [remap] | ||||
| 
 | ||||
| importer="dialogue_manager_compiler_8" | ||||
| type="Resource" | ||||
| uid="uid://dntkvjjr8mrgf" | ||||
| path="res://.godot/imported/doc.dialogue-9af7b89bed22cfead99a33235819bbdf.tres" | ||||
| 
 | ||||
| [deps] | ||||
| 
 | ||||
| source_file="res://Assets/Dialog/doc.dialogue" | ||||
| dest_files=["res://.godot/imported/doc.dialogue-9af7b89bed22cfead99a33235819bbdf.tres"] | ||||
| 
 | ||||
| [params] | ||||
| 
 | ||||
| defaults=true | ||||
											
												Binary file not shown.
											
										
									
								|  | @ -0,0 +1,19 @@ | |||
| [remap] | ||||
| 
 | ||||
| importer="mp3" | ||||
| type="AudioStreamMP3" | ||||
| uid="uid://dy4qjflo1k28b" | ||||
| path="res://.godot/imported/calm-storm-ambient.mp3-0433d7efeb05231869c7e6e6134f0645.mp3str" | ||||
| 
 | ||||
| [deps] | ||||
| 
 | ||||
| source_file="res://Assets/Sounds/calm-storm-ambient.mp3" | ||||
| dest_files=["res://.godot/imported/calm-storm-ambient.mp3-0433d7efeb05231869c7e6e6134f0645.mp3str"] | ||||
| 
 | ||||
| [params] | ||||
| 
 | ||||
| loop=false | ||||
| loop_offset=0 | ||||
| bpm=0 | ||||
| beat_count=0 | ||||
| bar_beats=4 | ||||
											
												Binary file not shown.
											
										
									
								
											
												Binary file not shown.
											
										
									
								| Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB | 
|  | @ -1,13 +1,14 @@ | |||
| [gd_resource type="ParticleProcessMaterial" load_steps=3 format=3 uid="uid://rcjujd5dv7lm"] | ||||
| 
 | ||||
| [sub_resource type="Gradient" id="Gradient_v7xci"] | ||||
| offsets = PackedFloat32Array(0.525926, 0.6) | ||||
| offsets = PackedFloat32Array(0.525926, 0.585185) | ||||
| colors = PackedColorArray(0, 0, 0, 1, 1, 0, 0, 1) | ||||
| 
 | ||||
| [sub_resource type="GradientTexture1D" id="GradientTexture1D_pntll"] | ||||
| gradient = SubResource("Gradient_v7xci") | ||||
| 
 | ||||
| [resource] | ||||
| particle_flag_rotate_y = true | ||||
| particle_flag_disable_z = true | ||||
| spread = 180.0 | ||||
| gravity = Vector3(0, 0, 0) | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ public abstract partial class Boss : Enemy | |||
|     private bool _isActive; | ||||
| 
 | ||||
|     [Export] | ||||
|     public bool IsActive | ||||
|     public virtual bool IsActive | ||||
|     { | ||||
|         get => _isActive; | ||||
|         set | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ using Godot; | |||
| using GodotUtilities; | ||||
| using SupaLidlGame.Extensions; | ||||
| using SupaLidlGame.State.Character; | ||||
| using DialogueManagerRuntime; | ||||
| 
 | ||||
| namespace SupaLidlGame.Characters; | ||||
| 
 | ||||
|  | @ -9,6 +10,8 @@ public partial class Doc : Boss | |||
| { | ||||
|     public AnimationPlayer TelegraphAnimation { get; set; } | ||||
| 
 | ||||
|     public AnimationPlayer MiscAnimation { get; set; } | ||||
| 
 | ||||
|     [Export] | ||||
|     public Items.Weapons.Sword Lance { get; set; } | ||||
| 
 | ||||
|  | @ -16,6 +19,19 @@ public partial class Doc : Boss | |||
|     protected CharacterDashState _dashState; | ||||
|     protected float _originalDashModifier; | ||||
| 
 | ||||
|     [Export] | ||||
|     public override bool IsActive | ||||
|     { | ||||
|         get => base.IsActive; | ||||
|         set | ||||
|         { | ||||
|             base.IsActive = value; | ||||
|             var introState = BossStateMachine | ||||
|                 .GetNode<State.NPC.Doc.DocIntroState>("Intro"); | ||||
|             BossStateMachine.ChangeState(introState); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public override float Health | ||||
|     { | ||||
|         get => base.Health; | ||||
|  | @ -58,11 +74,34 @@ public partial class Doc : Boss | |||
|     public override void _Ready() | ||||
|     { | ||||
|         TelegraphAnimation = GetNode<AnimationPlayer>("Animations/Telegraph"); | ||||
|         MiscAnimation = GetNode<AnimationPlayer>("Animations/Misc"); | ||||
| 
 | ||||
|         base._Ready(); | ||||
| 
 | ||||
|         _dashState = StateMachine.FindChildOfType<CharacterDashState>(); | ||||
|         _originalDashModifier = _dashState.VelocityModifier; | ||||
| 
 | ||||
|         var dialog = GD.Load<Resource>("res://Assets/Dialog/doc.dialogue"); | ||||
| 
 | ||||
|         GetNode<BoundingBoxes.InteractionTrigger>("InteractionTrigger") | ||||
|             .Interaction += () => | ||||
|         { | ||||
|             //DialogueManager.ShowExampleDialogueBalloon(dialog, "duel"); | ||||
|             this.GetAncestor<Utils.World>().DialogueBalloon | ||||
|                 .Start(dialog, "duel"); | ||||
|                 //.Call("start", dialog, "duel"); | ||||
|         }; | ||||
| 
 | ||||
|         GetNode<State.Global.GlobalState>("/root/GlobalState") | ||||
|             .SummonBoss += (string name) => | ||||
|         { | ||||
|             if (name == "Doc") | ||||
|             { | ||||
|                 IsActive = true; | ||||
|                 Inventory.SelectedItem = Lance; | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
| 
 | ||||
|         // when we are hurt, start the boss fight | ||||
|         Hurt += (Events.HealthChangedArgs args) => | ||||
|  | @ -71,6 +110,7 @@ public partial class Doc : Boss | |||
|             { | ||||
|                 IsActive = true; | ||||
|                 Inventory.SelectedItem = Lance; | ||||
|                 //DialogueManager.ShowExampleDialogueBalloon(); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| [gd_scene load_steps=62 format=3 uid="uid://d2skjvvx6fal0"] | ||||
| [gd_scene load_steps=66 format=3 uid="uid://d2skjvvx6fal0"] | ||||
| 
 | ||||
| [ext_resource type="Script" path="res://Characters/Doc.cs" id="2_3elet"] | ||||
| [ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_5jxom"] | ||||
|  | @ -19,6 +19,7 @@ | |||
| [ext_resource type="AudioStream" uid="uid://k6kpdj1kv0jg" path="res://Assets/Sounds/splat.ogg" id="9_stm0e"] | ||||
| [ext_resource type="Script" path="res://State/NPC/Doc/DocShungiteSpikeState.cs" id="10_bgs6o"] | ||||
| [ext_resource type="PackedScene" uid="uid://cqx56u46g2c16" path="res://Entities/CompactDisc.tscn" id="11_23p3o"] | ||||
| [ext_resource type="Script" path="res://State/NPC/Doc/DocIntroState.cs" id="11_lt771"] | ||||
| [ext_resource type="Script" path="res://State/NPC/Doc/DocChooseAttackState.cs" id="12_45x13"] | ||||
| [ext_resource type="Script" path="res://State/NPC/Doc/DocUnwantedFrequencyState.cs" id="12_d51jv"] | ||||
| [ext_resource type="PackedScene" uid="uid://1y5r6sklwgrp" path="res://Entities/UnwantedFrequency.tscn" id="13_lpj21"] | ||||
|  | @ -32,6 +33,7 @@ | |||
| [ext_resource type="PackedScene" uid="uid://p7oijq6dbvvk" path="res://Items/Weapons/DocLance.tscn" id="24_2es2r"] | ||||
| [ext_resource type="PackedScene" uid="uid://bauucuqvjwbxp" path="res://Items/Weapons/DocLanceHold.tscn" id="26_0tntj"] | ||||
| [ext_resource type="AudioStream" uid="uid://cqj44je3mvk60" path="res://Assets/Sounds/rauuul.wav" id="26_js7p2"] | ||||
| [ext_resource type="PackedScene" uid="uid://dldnp8eunxj3q" path="res://BoundingBoxes/InteractionTrigger.tscn" id="33_08dyq"] | ||||
| 
 | ||||
| [sub_resource type="ShaderMaterial" id="ShaderMaterial_7n7iy"] | ||||
| resource_local_to_scene = true | ||||
|  | @ -397,11 +399,102 @@ _data = { | |||
| "stun": ExtResource("21_ixn4k") | ||||
| } | ||||
| 
 | ||||
| [sub_resource type="Animation" id="Animation_ucpsk"] | ||||
| length = 0.001 | ||||
| tracks/0/type = "value" | ||||
| tracks/0/imported = false | ||||
| tracks/0/enabled = true | ||||
| tracks/0/path = NodePath("../Sprite:frame") | ||||
| tracks/0/interp = 1 | ||||
| tracks/0/loop_wrap = true | ||||
| tracks/0/keys = { | ||||
| "times": PackedFloat32Array(0), | ||||
| "transitions": PackedFloat32Array(1), | ||||
| "update": 1, | ||||
| "values": [0] | ||||
| } | ||||
| tracks/1/type = "value" | ||||
| tracks/1/imported = false | ||||
| tracks/1/enabled = true | ||||
| tracks/1/path = NodePath("../Effects/IntroParticles:emitting") | ||||
| tracks/1/interp = 1 | ||||
| tracks/1/loop_wrap = true | ||||
| tracks/1/keys = { | ||||
| "times": PackedFloat32Array(0), | ||||
| "transitions": PackedFloat32Array(1), | ||||
| "update": 1, | ||||
| "values": [false] | ||||
| } | ||||
| tracks/2/type = "value" | ||||
| tracks/2/imported = false | ||||
| tracks/2/enabled = true | ||||
| tracks/2/path = NodePath("../Sprite:scale") | ||||
| tracks/2/interp = 1 | ||||
| tracks/2/loop_wrap = true | ||||
| tracks/2/keys = { | ||||
| "times": PackedFloat32Array(0), | ||||
| "transitions": PackedFloat32Array(1), | ||||
| "update": 0, | ||||
| "values": [Vector2(1, 1)] | ||||
| } | ||||
| 
 | ||||
| [sub_resource type="Animation" id="Animation_uemm6"] | ||||
| resource_name = "intro" | ||||
| length = 3.0 | ||||
| tracks/0/type = "method" | ||||
| tracks/0/imported = false | ||||
| tracks/0/enabled = true | ||||
| tracks/0/path = NodePath("../Effects/BattleCry") | ||||
| tracks/0/interp = 1 | ||||
| tracks/0/loop_wrap = true | ||||
| tracks/0/keys = { | ||||
| "times": PackedFloat32Array(0), | ||||
| "transitions": PackedFloat32Array(1), | ||||
| "values": [{ | ||||
| "args": [0.0], | ||||
| "method": &"play" | ||||
| }] | ||||
| } | ||||
| tracks/1/type = "value" | ||||
| tracks/1/imported = false | ||||
| tracks/1/enabled = true | ||||
| tracks/1/path = NodePath("../Sprite:frame") | ||||
| tracks/1/interp = 1 | ||||
| tracks/1/loop_wrap = true | ||||
| tracks/1/keys = { | ||||
| "times": PackedFloat32Array(0), | ||||
| "transitions": PackedFloat32Array(1), | ||||
| "update": 1, | ||||
| "values": [16] | ||||
| } | ||||
| tracks/2/type = "value" | ||||
| tracks/2/imported = false | ||||
| tracks/2/enabled = true | ||||
| tracks/2/path = NodePath("../Effects/IntroParticles:emitting") | ||||
| tracks/2/interp = 1 | ||||
| tracks/2/loop_wrap = true | ||||
| tracks/2/keys = { | ||||
| "times": PackedFloat32Array(0, 3), | ||||
| "transitions": PackedFloat32Array(1, 1), | ||||
| "update": 1, | ||||
| "values": [true, false] | ||||
| } | ||||
| tracks/3/type = "value" | ||||
| tracks/3/imported = false | ||||
| tracks/3/enabled = true | ||||
| tracks/3/path = NodePath("../Sprite:scale") | ||||
| tracks/3/interp = 1 | ||||
| tracks/3/loop_wrap = true | ||||
| tracks/3/keys = { | ||||
| "times": PackedFloat32Array(0, 0.1), | ||||
| "transitions": PackedFloat32Array(1, 1), | ||||
| "update": 0, | ||||
| "values": [Vector2(2, 0.5), Vector2(1, 1)] | ||||
| } | ||||
| 
 | ||||
| [sub_resource type="AnimationLibrary" id="AnimationLibrary_kjxam"] | ||||
| _data = { | ||||
| "RESET": SubResource("Animation_ucpsk"), | ||||
| "intro": SubResource("Animation_uemm6") | ||||
| } | ||||
| 
 | ||||
|  | @ -456,6 +549,9 @@ size = Vector2(11, 5) | |||
| [sub_resource type="RectangleShape2D" id="RectangleShape2D_8lxmf"] | ||||
| size = Vector2(16, 19) | ||||
| 
 | ||||
| [sub_resource type="CircleShape2D" id="CircleShape2D_8hwat"] | ||||
| radius = 16.0 | ||||
| 
 | ||||
| [node name="Doc" type="CharacterBody2D" node_paths=PackedStringArray("Lance", "BossStateMachine", "Sprite", "Inventory", "StateMachine", "Hurtbox")] | ||||
| y_sort_enabled = true | ||||
| texture_filter = 3 | ||||
|  | @ -500,6 +596,11 @@ Character = NodePath("../..") | |||
| script = ExtResource("6_kjpug") | ||||
| InitialState = NodePath("Telegraph") | ||||
| 
 | ||||
| [node name="Intro" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("NextState", "NPC")] | ||||
| script = ExtResource("11_lt771") | ||||
| NextState = NodePath("../Telegraph") | ||||
| NPC = NodePath("../..") | ||||
| 
 | ||||
| [node name="Telegraph" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("TelegraphAnimationPlayer", "AttackState", "NPC")] | ||||
| script = ExtResource("7_tfwbh") | ||||
| TelegraphAnimationPlayer = NodePath("../../Animations/Telegraph") | ||||
|  | @ -533,17 +634,22 @@ ChooseAttackState = NodePath("../ChooseAttack") | |||
| Doc = NodePath("../..") | ||||
| NPC = NodePath("../..") | ||||
| 
 | ||||
| [node name="LanceIntro" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("NextState", "NPC")] | ||||
| script = ExtResource("11_lt771") | ||||
| NextState = NodePath("../Lance") | ||||
| NPC = NodePath("../..") | ||||
| 
 | ||||
| [node name="Lance" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("ExitState", "NPC")] | ||||
| script = ExtResource("15_dmd05") | ||||
| ExitState = NodePath("../Exit") | ||||
| NPC = NodePath("../..") | ||||
| 
 | ||||
| [node name="ChooseAttack" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("DartState", "SpikeState", "UnwantedFrequencyState", "LanceState", "ExitState", "NPC")] | ||||
| [node name="ChooseAttack" type="Node" parent="BossStateMachine" node_paths=PackedStringArray("DartState", "SpikeState", "UnwantedFrequencyState", "LanceIntroState", "ExitState", "NPC")] | ||||
| script = ExtResource("12_45x13") | ||||
| DartState = NodePath("../Dart") | ||||
| SpikeState = NodePath("../Spike") | ||||
| UnwantedFrequencyState = NodePath("../UnwantedFrequency") | ||||
| LanceState = NodePath("../Lance") | ||||
| LanceIntroState = NodePath("../LanceIntro") | ||||
| ExitState = NodePath("../Exit") | ||||
| NPC = NodePath("../..") | ||||
| 
 | ||||
|  | @ -607,6 +713,7 @@ emitting = false | |||
| amount = 32 | ||||
| process_material = ExtResource("19_q4rt1") | ||||
| texture = ExtResource("19_p0p6c") | ||||
| lifetime = 0.5 | ||||
| 
 | ||||
| [node name="Dash" type="GPUParticles2D" parent="Effects"] | ||||
| position = Vector2(0, -8) | ||||
|  | @ -626,7 +733,7 @@ use_parent_material = true | |||
| position = Vector2(-0.5, 0) | ||||
| texture = ExtResource("3_rs44f") | ||||
| offset = Vector2(0, -8) | ||||
| hframes = 16 | ||||
| hframes = 17 | ||||
| 
 | ||||
| [node name="CollisionShape2D" type="CollisionShape2D" parent="."] | ||||
| position = Vector2(-0.5, -1.5) | ||||
|  | @ -652,4 +759,11 @@ Items = Array[Node2D]([]) | |||
| [node name="HurtSound" type="AudioStreamPlayer2D" parent="."] | ||||
| stream = ExtResource("9_stm0e") | ||||
| 
 | ||||
| [node name="InteractionTrigger" parent="." instance=ExtResource("33_08dyq")] | ||||
| 
 | ||||
| [node name="CollisionShape2D" parent="InteractionTrigger" index="0"] | ||||
| position = Vector2(0, -8) | ||||
| shape = SubResource("CircleShape2D_8hwat") | ||||
| 
 | ||||
| [editable path="Hurtbox"] | ||||
| [editable path="InteractionTrigger"] | ||||
|  |  | |||
|  | @ -0,0 +1,271 @@ | |||
| using Godot; | ||||
| using Godot.Collections; | ||||
| using DialogueManagerRuntime; | ||||
| 
 | ||||
| namespace SupaLidlGame.Dialogue; | ||||
| 
 | ||||
| // https://github.com/nathanhoad/godot_dialogue_manager/blob/main/examples/csharp_balloon/Balloon.cs | ||||
| // TODO: rewrite this | ||||
| 
 | ||||
| public partial class Balloon : CanvasLayer | ||||
| { | ||||
|   Color VISIBLE = new Color(1f, 1f, 1f, 1f); | ||||
|   Color INVISIBLE = new Color(1f, 1f, 1f, 0f); | ||||
| 
 | ||||
|   ColorRect balloon; | ||||
|   MarginContainer margin; | ||||
|   RichTextLabel characterLabel; | ||||
|   RichTextLabel dialogueLabel; | ||||
|   VBoxContainer responsesMenu; | ||||
|   RichTextLabel responseTemplate; | ||||
| 
 | ||||
|   Resource resource; | ||||
|   Array<Variant> temporaryGameStates = new Array<Variant>(); | ||||
|   bool isWaitingForInput = false; | ||||
| 
 | ||||
|   DialogueLine dialogueLine; | ||||
|   DialogueLine DialogueLine | ||||
|   { | ||||
|     get => dialogueLine; | ||||
|     set | ||||
|     { | ||||
|       isWaitingForInput = false; | ||||
| 
 | ||||
|       if (value == null) | ||||
|       { | ||||
|         QueueFree(); | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       dialogueLine = value; | ||||
| 
 | ||||
|       UpdateDialogueLine(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   public override void _Ready() | ||||
|   { | ||||
|     balloon = GetNode<ColorRect>("Balloon"); | ||||
|     margin = GetNode<MarginContainer>("Balloon/Margin"); | ||||
|     characterLabel = GetNode<RichTextLabel>("Balloon/Margin/VBox/CharacterLabel"); | ||||
|     dialogueLabel = GetNode<RichTextLabel>("Balloon/Margin/VBox/DialogueLabel"); | ||||
|     responsesMenu = GetNode<VBoxContainer>("Balloon/Margin/VBox/Responses"); | ||||
|     responseTemplate = GetNode<RichTextLabel>("Balloon/Margin/VBox/ResponseTemplate"); | ||||
|     GD.Print("responses menu is " + responsesMenu); | ||||
|     GD.Print("lulw"); | ||||
| 
 | ||||
|     responseTemplate.Hide(); | ||||
|     balloon.Hide(); | ||||
|     balloon.CustomMinimumSize = new Vector2(balloon.GetViewportRect().Size.X, balloon.CustomMinimumSize.Y); | ||||
| 
 | ||||
|     balloon.GuiInput += (inputEvent) => | ||||
|     { | ||||
| 
 | ||||
|       if (!isWaitingForInput) return; | ||||
|       if (GetResponses().Count > 0) return; | ||||
| 
 | ||||
|       GetViewport().SetInputAsHandled(); | ||||
| 
 | ||||
|       if (inputEvent is InputEventMouseButton && inputEvent.IsPressed() && (inputEvent as InputEventMouseButton).ButtonIndex == MouseButton.Left) | ||||
|       { | ||||
|         Next(dialogueLine.NextId); | ||||
|       } | ||||
|       else if (inputEvent.IsActionPressed("ui_accept") && GetViewport().GuiGetFocusOwner() == balloon) | ||||
|       { | ||||
|         Next(dialogueLine.NextId); | ||||
|       } | ||||
| 
 | ||||
|     }; | ||||
| 
 | ||||
|     margin.Resized += () => HandleResize(); | ||||
| 
 | ||||
|     Engine.GetSingleton("DialogueManager").Connect("mutated", Callable.From((Dictionary mutation) => | ||||
|     { | ||||
|       isWaitingForInput = false; | ||||
|       balloon.Hide(); | ||||
|     })); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   public override void _UnhandledInput(InputEvent inputEvent) | ||||
|   { | ||||
|     // Only the balloon is allowed to handle input while it's showing | ||||
|     GetViewport().SetInputAsHandled(); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   public async void Start(Resource dialogueResource, string title, Array<Variant> extraGameStates = null) | ||||
|   { | ||||
|     temporaryGameStates = extraGameStates; | ||||
|     isWaitingForInput = false; | ||||
|     resource = dialogueResource; | ||||
| 
 | ||||
|     DialogueLine = await DialogueManager.GetNextDialogueLine(resource, title, temporaryGameStates ?? new Array<Variant>()); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   private async void Next(string nextId) | ||||
|   { | ||||
|     DialogueLine = await DialogueManager.GetNextDialogueLine(resource, nextId, temporaryGameStates ?? new Array<Variant>()); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /// Helpers | ||||
| 
 | ||||
| 
 | ||||
|   private void ConfigureMenu() | ||||
|   { | ||||
|     balloon.FocusMode = Control.FocusModeEnum.None; | ||||
| 
 | ||||
|     var items = GetResponses(); | ||||
|     for (int i = 0; i < items.Count; i++) | ||||
|     { | ||||
|       var item = items[i]; | ||||
| 
 | ||||
|       item.FocusMode = Control.FocusModeEnum.All; | ||||
| 
 | ||||
|       item.FocusNeighborLeft = item.GetPath(); | ||||
|       item.FocusNeighborRight = item.GetPath(); | ||||
| 
 | ||||
|       if (i == 0) | ||||
|       { | ||||
|         item.FocusNeighborTop = item.GetPath(); | ||||
|         item.FocusPrevious = item.GetPath(); | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         item.FocusNeighborTop = items[i - 1].GetPath(); | ||||
|         item.FocusPrevious = items[i - 1].GetPath(); | ||||
|       } | ||||
| 
 | ||||
|       if (i == items.Count - 1) | ||||
|       { | ||||
|         item.FocusNeighborBottom = item.GetPath(); | ||||
|         item.FocusNext = item.GetPath(); | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         item.FocusNeighborBottom = items[i + 1].GetPath(); | ||||
|         item.FocusNext = items[i + 1].GetPath(); | ||||
|       } | ||||
| 
 | ||||
|       item.MouseEntered += () => | ||||
|       { | ||||
|         if (item.Name.ToString().Contains("Disallowed")) return; | ||||
| 
 | ||||
|         item.GrabFocus(); | ||||
|       }; | ||||
|       item.GuiInput += (inputEvent) => | ||||
|       { | ||||
|         if (item.Name.ToString().Contains("Disallowed")) return; | ||||
| 
 | ||||
|         if (inputEvent is InputEventMouseButton && inputEvent.IsPressed() && (inputEvent as InputEventMouseButton).ButtonIndex == MouseButton.Left) | ||||
|         { | ||||
|           Next(dialogueLine.Responses[item.GetIndex()].NextId); | ||||
|         } | ||||
|         else if (inputEvent.IsActionPressed("ui_accept") && GetResponses().Contains(item)) | ||||
|         { | ||||
|           Next(dialogueLine.Responses[item.GetIndex()].NextId); | ||||
|         } | ||||
|       }; | ||||
|     } | ||||
| 
 | ||||
|     items[0].GrabFocus(); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   private Array<Control> GetResponses() | ||||
|   { | ||||
|     Array<Control> items = new Array<Control>(); | ||||
|     foreach (Control child in responsesMenu.GetChildren()) | ||||
|     { | ||||
|       if (child.Name.ToString().Contains("Disallowed")) continue; | ||||
| 
 | ||||
|       items.Add(child); | ||||
|     } | ||||
| 
 | ||||
|     return items; | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   private void HandleResize() | ||||
|   { | ||||
|     if (!IsInstanceValid(margin)) | ||||
|     { | ||||
|       CallDeferred("HandleResize"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     balloon.CustomMinimumSize = new Vector2(balloon.CustomMinimumSize.X, margin.Size.Y); | ||||
|     balloon.Size = new Vector2(balloon.Size.X, 0); | ||||
|     Vector2 viewportSize = balloon.GetViewportRect().Size; | ||||
|     balloon.GlobalPosition = new Vector2((viewportSize.X - balloon.Size.X) * 0.5f, viewportSize.Y - balloon.Size.Y); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   private async void UpdateDialogueLine() | ||||
|   { | ||||
|     foreach (Control child in responsesMenu.GetChildren()) | ||||
|     { | ||||
|       child.Free(); | ||||
|     } | ||||
| 
 | ||||
|     characterLabel.Visible = !string.IsNullOrEmpty(dialogueLine.Character); | ||||
|     characterLabel.Text = dialogueLine.Character; | ||||
| 
 | ||||
|     dialogueLabel.Modulate = INVISIBLE; | ||||
|     dialogueLabel.CustomMinimumSize = new Vector2(dialogueLabel.GetParent<Control>().Size.X - 1, dialogueLabel.CustomMinimumSize.Y); | ||||
|     dialogueLabel.Set("dialogue_line", dialogueLine); | ||||
| 
 | ||||
|     // Show any responses we have | ||||
|     responsesMenu.Modulate = INVISIBLE; | ||||
|     foreach (var response in dialogueLine.Responses) | ||||
|     { | ||||
|       RichTextLabel item = (RichTextLabel)responseTemplate.Duplicate(); | ||||
|       item.Name = $"Response{responsesMenu.GetChildCount()}"; | ||||
|       if (!response.IsAllowed) | ||||
|       { | ||||
|         item.Name = item.Name + "Disallowed"; | ||||
|         item.Modulate = new Color(item.Modulate, 0.4f); | ||||
|       } | ||||
|       item.Text = response.Text; | ||||
|       item.Show(); | ||||
|       responsesMenu.AddChild(item); | ||||
|     } | ||||
| 
 | ||||
|     // Show the balloon | ||||
|     balloon.Show(); | ||||
| 
 | ||||
|     dialogueLabel.Modulate = VISIBLE; | ||||
|     if (!string.IsNullOrEmpty(dialogueLine.Text)) | ||||
|     { | ||||
|       dialogueLabel.Call("type_out"); | ||||
|       await ToSignal(dialogueLabel, "finished_typing"); | ||||
|     } | ||||
| 
 | ||||
|     // Wait for input | ||||
|     if (dialogueLine.Responses.Count > 0) | ||||
|     { | ||||
|       responsesMenu.Modulate = VISIBLE; | ||||
|       ConfigureMenu(); | ||||
|     } | ||||
|     else if (!string.IsNullOrEmpty(dialogueLine.Time)) | ||||
|     { | ||||
|       float time = 0f; | ||||
|       if (!float.TryParse(dialogueLine.Time, out time)) | ||||
|       { | ||||
|         time = dialogueLine.Text.Length * 0.02f; | ||||
|       } | ||||
|       await ToSignal(GetTree().CreateTimer(time), "timeout"); | ||||
|       Next(dialogueLine.NextId); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|       isWaitingForInput = true; | ||||
|       balloon.FocusMode = Control.FocusModeEnum.All; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -0,0 +1,212 @@ | |||
| extends CanvasLayer | ||||
| 
 | ||||
| 
 | ||||
| @onready var balloon: ColorRect = $Balloon | ||||
| @onready var margin: MarginContainer = $Balloon/Margin | ||||
| @onready var character_label: RichTextLabel = $Balloon/Margin/VBox/CharacterLabel | ||||
| @onready var dialogue_label := $Balloon/Margin/VBox/DialogueLabel | ||||
| @onready var responses_menu: VBoxContainer = $Balloon/Margin/VBox/Responses | ||||
| @onready var response_template: RichTextLabel = %ResponseTemplate | ||||
| 
 | ||||
| ## The dialogue resource | ||||
| var resource: DialogueResource | ||||
| 
 | ||||
| ## Temporary game states | ||||
| var temporary_game_states: Array = [] | ||||
| 
 | ||||
| ## See if we are waiting for the player | ||||
| var is_waiting_for_input: bool = false | ||||
| 
 | ||||
| ## See if we are running a long mutation and should hide the balloon | ||||
| var will_hide_balloon: bool = false | ||||
| 
 | ||||
| ## The current line | ||||
| var dialogue_line: DialogueLine: | ||||
|     set(next_dialogue_line): | ||||
|         is_waiting_for_input = false | ||||
| 
 | ||||
|         if not next_dialogue_line: | ||||
|             queue_free() | ||||
|             return | ||||
| 
 | ||||
|         # Remove any previous responses | ||||
|         for child in responses_menu.get_children(): | ||||
|             responses_menu.remove_child(child) | ||||
|             child.queue_free() | ||||
| 
 | ||||
|         dialogue_line = next_dialogue_line | ||||
| 
 | ||||
|         character_label.visible = not dialogue_line.character.is_empty() | ||||
|         character_label.text = tr(dialogue_line.character, "dialogue") | ||||
| 
 | ||||
|         dialogue_label.modulate.a = 0 | ||||
|         dialogue_label.custom_minimum_size.x = dialogue_label.get_parent().size.x - 1 | ||||
|         dialogue_label.dialogue_line = dialogue_line | ||||
| 
 | ||||
|         # Show any responses we have | ||||
|         responses_menu.modulate.a = 0 | ||||
|         if dialogue_line.responses.size() > 0: | ||||
|             for response in dialogue_line.responses: | ||||
|                 # Duplicate the template so we can grab the fonts, sizing, etc | ||||
|                 var item: RichTextLabel = response_template.duplicate(0) | ||||
|                 item.name = "Response%d" % responses_menu.get_child_count() | ||||
|                 if not response.is_allowed: | ||||
|                     item.name = String(item.name) + "Disallowed" | ||||
|                     item.modulate.a = 0.4 | ||||
|                 item.text = response.text | ||||
|                 item.show() | ||||
|                 responses_menu.add_child(item) | ||||
| 
 | ||||
|         # Show our balloon | ||||
|         balloon.show() | ||||
|         will_hide_balloon = false | ||||
| 
 | ||||
|         dialogue_label.modulate.a = 1 | ||||
|         if not dialogue_line.text.is_empty(): | ||||
|             dialogue_label.type_out() | ||||
|             await dialogue_label.finished_typing | ||||
| 
 | ||||
|         # Wait for input | ||||
|         if dialogue_line.responses.size() > 0: | ||||
|             responses_menu.modulate.a = 1 | ||||
|             configure_menu() | ||||
|         elif dialogue_line.time != null: | ||||
|             var time = dialogue_line.text.length() * 0.02 if dialogue_line.time == "auto" else dialogue_line.time.to_float() | ||||
|             await get_tree().create_timer(time).timeout | ||||
|             next(dialogue_line.next_id) | ||||
|         else: | ||||
|             is_waiting_for_input = true | ||||
|             balloon.focus_mode = Control.FOCUS_ALL | ||||
|             balloon.grab_focus() | ||||
|     get: | ||||
|         return dialogue_line | ||||
| 
 | ||||
| 
 | ||||
| func _ready() -> void: | ||||
|     response_template.hide() | ||||
|     balloon.hide() | ||||
|     balloon.custom_minimum_size.x = balloon.get_viewport_rect().size.x | ||||
| 
 | ||||
|     Engine.get_singleton("DialogueManager").mutated.connect(_on_mutated) | ||||
| 
 | ||||
| 
 | ||||
| func _unhandled_input(_event: InputEvent) -> void: | ||||
|     # Only the balloon is allowed to handle input while it's showing | ||||
|     get_viewport().set_input_as_handled() | ||||
| 
 | ||||
| 
 | ||||
| ## Start some dialogue | ||||
| func start(dialogue_resource: DialogueResource, title: String, extra_game_states: Array = []) -> void: | ||||
|     temporary_game_states = extra_game_states | ||||
|     is_waiting_for_input = false | ||||
|     resource = dialogue_resource | ||||
| 
 | ||||
|     self.dialogue_line = await resource.get_next_dialogue_line(title, temporary_game_states) | ||||
| 
 | ||||
| 
 | ||||
| ## Go to the next line | ||||
| func next(next_id: String) -> void: | ||||
|     self.dialogue_line = await resource.get_next_dialogue_line(next_id, temporary_game_states) | ||||
| 
 | ||||
| 
 | ||||
| ### Helpers | ||||
| 
 | ||||
| 
 | ||||
| # Set up keyboard movement and signals for the response menu | ||||
| func configure_menu() -> void: | ||||
|     balloon.focus_mode = Control.FOCUS_NONE | ||||
| 
 | ||||
|     var items = get_responses() | ||||
|     for i in items.size(): | ||||
|         var item: Control = items[i] | ||||
| 
 | ||||
|         item.focus_mode = Control.FOCUS_ALL | ||||
| 
 | ||||
|         item.focus_neighbor_left = item.get_path() | ||||
|         item.focus_neighbor_right = item.get_path() | ||||
| 
 | ||||
|         if i == 0: | ||||
|             item.focus_neighbor_top = item.get_path() | ||||
|             item.focus_previous = item.get_path() | ||||
|         else: | ||||
|             item.focus_neighbor_top = items[i - 1].get_path() | ||||
|             item.focus_previous = items[i - 1].get_path() | ||||
| 
 | ||||
|         if i == items.size() - 1: | ||||
|             item.focus_neighbor_bottom = item.get_path() | ||||
|             item.focus_next = item.get_path() | ||||
|         else: | ||||
|             item.focus_neighbor_bottom = items[i + 1].get_path() | ||||
|             item.focus_next = items[i + 1].get_path() | ||||
| 
 | ||||
|         item.mouse_entered.connect(_on_response_mouse_entered.bind(item)) | ||||
|         item.gui_input.connect(_on_response_gui_input.bind(item)) | ||||
| 
 | ||||
|     items[0].grab_focus() | ||||
| 
 | ||||
| 
 | ||||
| # Get a list of enabled items | ||||
| func get_responses() -> Array: | ||||
|     var items: Array = [] | ||||
|     for child in responses_menu.get_children(): | ||||
|         if "Disallowed" in child.name: continue | ||||
|         items.append(child) | ||||
| 
 | ||||
|     return items | ||||
| 
 | ||||
| 
 | ||||
| func handle_resize() -> void: | ||||
|     if not is_instance_valid(margin): | ||||
|         call_deferred("handle_resize") | ||||
|         return | ||||
| 
 | ||||
|     balloon.custom_minimum_size.y = margin.size.y | ||||
|     # Force a resize on only the height | ||||
|     balloon.size.y = 0 | ||||
|     var viewport_size = balloon.get_viewport_rect().size | ||||
|     balloon.global_position = Vector2((viewport_size.x - balloon.size.x) * 0.5, viewport_size.y - balloon.size.y) | ||||
| 
 | ||||
| 
 | ||||
| ### Signals | ||||
| 
 | ||||
| 
 | ||||
| func _on_mutated(_mutation: Dictionary) -> void: | ||||
|     is_waiting_for_input = false | ||||
|     will_hide_balloon = true | ||||
|     get_tree().create_timer(0.1).timeout.connect(func(): | ||||
|         if will_hide_balloon: | ||||
|             will_hide_balloon = false | ||||
|             balloon.hide() | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| func _on_response_mouse_entered(item: Control) -> void: | ||||
|     if "Disallowed" in item.name: return | ||||
| 
 | ||||
|     item.grab_focus() | ||||
| 
 | ||||
| 
 | ||||
| func _on_response_gui_input(event: InputEvent, item: Control) -> void: | ||||
|     if "Disallowed" in item.name: return | ||||
| 
 | ||||
|     if event is InputEventMouseButton and event.is_pressed() and event.button_index == 1: | ||||
|         next(dialogue_line.responses[item.get_index()].next_id) | ||||
|     elif event.is_action_pressed("ui_accept") and item in get_responses(): | ||||
|         next(dialogue_line.responses[item.get_index()].next_id) | ||||
| 
 | ||||
| 
 | ||||
| func _on_balloon_gui_input(event: InputEvent) -> void: | ||||
|     if not is_waiting_for_input: return | ||||
|     if dialogue_line.responses.size() > 0: return | ||||
| 
 | ||||
|     # When there are no response options the balloon itself is the clickable thing | ||||
|     get_viewport().set_input_as_handled() | ||||
| 
 | ||||
|     if event is InputEventMouseButton and event.is_pressed() and event.button_index == 1: | ||||
|         next(dialogue_line.next_id) | ||||
|     elif event.is_action_pressed("ui_accept") and get_viewport().gui_get_focus_owner() == balloon: | ||||
|         next(dialogue_line.next_id) | ||||
| 
 | ||||
| 
 | ||||
| func _on_margin_resized() -> void: | ||||
|     handle_resize() | ||||
|  | @ -0,0 +1,85 @@ | |||
| [gd_scene load_steps=7 format=3 uid="uid://73jm5qjy52vq"] | ||||
| 
 | ||||
| [ext_resource type="Script" path="res://Dialogue/Balloon.cs" id="1_obwi7"] | ||||
| [ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_a8ve6"] | ||||
| [ext_resource type="Theme" uid="uid://cksjbu3vrup5" path="res://UI/Themes/supalidl.tres" id="2_kowbc"] | ||||
| [ext_resource type="FontFile" uid="uid://bo3obq6sos7lu" path="res://Assets/Fonts/compass-pro.ttf" id="4_8e5aq"] | ||||
| 
 | ||||
| [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5d24i"] | ||||
| content_margin_left = 40.0 | ||||
| content_margin_top = 5.0 | ||||
| content_margin_right = 5.0 | ||||
| content_margin_bottom = 5.0 | ||||
| bg_color = Color(1, 1, 1, 0.25098) | ||||
| 
 | ||||
| [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_oj3c8"] | ||||
| content_margin_left = 40.0 | ||||
| content_margin_top = 5.0 | ||||
| content_margin_right = 5.0 | ||||
| content_margin_bottom = 5.0 | ||||
| draw_center = false | ||||
| 
 | ||||
| [node name="DialogBalloon" type="CanvasLayer"] | ||||
| layer = 100 | ||||
| script = ExtResource("1_obwi7") | ||||
| 
 | ||||
| [node name="Balloon" type="ColorRect" parent="."] | ||||
| color = Color(0.117647, 0.113725, 0.223529, 0.313726) | ||||
| 
 | ||||
| [node name="Margin" type="MarginContainer" parent="Balloon"] | ||||
| layout_mode = 0 | ||||
| anchor_right = 1.0 | ||||
| offset_bottom = 119.0 | ||||
| grow_horizontal = 2 | ||||
| theme_override_constants/margin_left = 20 | ||||
| theme_override_constants/margin_top = 10 | ||||
| theme_override_constants/margin_right = 20 | ||||
| theme_override_constants/margin_bottom = 10 | ||||
| metadata/_edit_layout_mode = 1 | ||||
| 
 | ||||
| [node name="VBox" type="VBoxContainer" parent="Balloon/Margin"] | ||||
| layout_mode = 2 | ||||
| theme = ExtResource("2_kowbc") | ||||
| theme_override_constants/separation = 10 | ||||
| 
 | ||||
| [node name="CharacterLabel" type="RichTextLabel" parent="Balloon/Margin/VBox"] | ||||
| layout_mode = 2 | ||||
| mouse_filter = 1 | ||||
| theme_override_colors/font_shadow_color = Color(0.0352941, 0.0392157, 0.0784314, 1) | ||||
| theme_override_colors/font_outline_color = Color(0.117647, 0.113725, 0.223529, 1) | ||||
| theme_override_constants/shadow_offset_x = 2 | ||||
| theme_override_constants/shadow_offset_y = 3 | ||||
| theme_override_constants/outline_size = 8 | ||||
| bbcode_enabled = true | ||||
| text = "Character" | ||||
| fit_content = true | ||||
| scroll_active = false | ||||
| 
 | ||||
| [node name="DialogueLabel" parent="Balloon/Margin/VBox" instance=ExtResource("2_a8ve6")] | ||||
| layout_mode = 2 | ||||
| theme_override_colors/font_outline_color = Color(0.117647, 0.113725, 0.223529, 1) | ||||
| theme_override_constants/outline_size = 4 | ||||
| theme_override_fonts/normal_font = ExtResource("4_8e5aq") | ||||
| text = "I bought a whole bunch of shungite." | ||||
| 
 | ||||
| [node name="Responses" type="VBoxContainer" parent="Balloon/Margin/VBox"] | ||||
| layout_mode = 2 | ||||
| theme_override_constants/separation = 2 | ||||
| 
 | ||||
| [node name="ResponseTemplate" type="RichTextLabel" parent="Balloon/Margin/VBox"] | ||||
| unique_name_in_owner = true | ||||
| layout_mode = 2 | ||||
| theme_override_colors/font_outline_color = Color(0.117647, 0.113725, 0.223529, 1) | ||||
| theme_override_constants/outline_size = 4 | ||||
| theme_override_styles/focus = SubResource("StyleBoxFlat_5d24i") | ||||
| theme_override_styles/normal = SubResource("StyleBoxFlat_oj3c8") | ||||
| bbcode_enabled = true | ||||
| text = "Response" | ||||
| fit_content = true | ||||
| scroll_active = false | ||||
| shortcut_keys_enabled = false | ||||
| meta_underlined = false | ||||
| hint_underlined = false | ||||
| 
 | ||||
| [connection signal="gui_input" from="Balloon" to="." method="_on_balloon_gui_input"] | ||||
| [connection signal="resized" from="Balloon/Margin" to="." method="_on_margin_resized"] | ||||
|  | @ -0,0 +1,87 @@ | |||
| [gd_scene load_steps=8 format=3 uid="uid://b361p61jmf257"] | ||||
| 
 | ||||
| [ext_resource type="Script" path="res://Dialogue/balloon.gd" id="1_4u26j"] | ||||
| [ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/dialogue_label.tscn" id="2_a8ve6"] | ||||
| 
 | ||||
| [sub_resource type="Theme" id="Theme_isg48"] | ||||
| default_font_size = 9 | ||||
| 
 | ||||
| [sub_resource type="Theme" id="Theme_owda0"] | ||||
| default_font_size = 9 | ||||
| 
 | ||||
| [sub_resource type="Theme" id="Theme_fakos"] | ||||
| default_font_size = 9 | ||||
| 
 | ||||
| [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5d24i"] | ||||
| content_margin_left = 20.0 | ||||
| content_margin_top = 2.0 | ||||
| content_margin_right = 2.0 | ||||
| content_margin_bottom = 2.0 | ||||
| bg_color = Color(1, 1, 1, 0.25098) | ||||
| 
 | ||||
| [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_oj3c8"] | ||||
| content_margin_left = 20.0 | ||||
| content_margin_top = 2.0 | ||||
| content_margin_right = 2.0 | ||||
| content_margin_bottom = 2.0 | ||||
| draw_center = false | ||||
| 
 | ||||
| [node name="ExampleBalloon" type="CanvasLayer"] | ||||
| layer = 100 | ||||
| script = ExtResource("1_4u26j") | ||||
| 
 | ||||
| [node name="Balloon" type="ColorRect" parent="."] | ||||
| color = Color(0, 0, 0, 1) | ||||
| 
 | ||||
| [node name="Margin" type="MarginContainer" parent="Balloon"] | ||||
| layout_mode = 1 | ||||
| anchors_preset = 10 | ||||
| anchor_right = 1.0 | ||||
| offset_bottom = 75.0 | ||||
| grow_horizontal = 2 | ||||
| theme_override_constants/margin_left = 20 | ||||
| theme_override_constants/margin_top = 10 | ||||
| theme_override_constants/margin_right = 20 | ||||
| theme_override_constants/margin_bottom = 10 | ||||
| metadata/_edit_layout_mode = 1 | ||||
| 
 | ||||
| [node name="VBox" type="VBoxContainer" parent="Balloon/Margin"] | ||||
| layout_mode = 2 | ||||
| theme_override_constants/separation = 4 | ||||
| 
 | ||||
| [node name="CharacterLabel" type="RichTextLabel" parent="Balloon/Margin/VBox"] | ||||
| modulate = Color(1, 1, 1, 0.501961) | ||||
| layout_mode = 2 | ||||
| mouse_filter = 1 | ||||
| theme = SubResource("Theme_isg48") | ||||
| bbcode_enabled = true | ||||
| text = "Character" | ||||
| fit_content = true | ||||
| scroll_active = false | ||||
| 
 | ||||
| [node name="DialogueLabel" parent="Balloon/Margin/VBox" instance=ExtResource("2_a8ve6")] | ||||
| layout_mode = 2 | ||||
| theme = SubResource("Theme_owda0") | ||||
| text = "Dialogue" | ||||
| 
 | ||||
| [node name="Responses" type="VBoxContainer" parent="Balloon/Margin/VBox"] | ||||
| layout_mode = 2 | ||||
| theme_override_constants/separation = 1 | ||||
| 
 | ||||
| [node name="ResponseTemplate" type="RichTextLabel" parent="Balloon/Margin/VBox"] | ||||
| unique_name_in_owner = true | ||||
| layout_mode = 2 | ||||
| focus_mode = 2 | ||||
| theme = SubResource("Theme_fakos") | ||||
| theme_override_styles/focus = SubResource("StyleBoxFlat_5d24i") | ||||
| theme_override_styles/normal = SubResource("StyleBoxFlat_oj3c8") | ||||
| bbcode_enabled = true | ||||
| text = "Response" | ||||
| fit_content = true | ||||
| scroll_active = false | ||||
| shortcut_keys_enabled = false | ||||
| meta_underlined = false | ||||
| hint_underlined = false | ||||
| 
 | ||||
| [connection signal="gui_input" from="Balloon" to="." method="_on_balloon_gui_input"] | ||||
| [connection signal="resized" from="Balloon/Margin" to="." method="_on_margin_resized"] | ||||
|  | @ -1,16 +1,18 @@ | |||
| [gd_scene load_steps=6 format=3 uid="uid://1pb3mpmrl7lc"] | ||||
| [gd_scene load_steps=7 format=3 uid="uid://1pb3mpmrl7lc"] | ||||
| 
 | ||||
| [ext_resource type="Script" path="res://Utils/World.cs" id="1_1k6ew"] | ||||
| [ext_resource type="PackedScene" uid="uid://b2x17su05ou5w" path="res://Scenes/Maps/Arena.tscn" id="2_avsrq"] | ||||
| [ext_resource type="PackedScene" uid="uid://bxo553hblp6nf" path="res://UI/HealthBar.tscn" id="3_5rhge"] | ||||
| [ext_resource type="Script" path="res://UI/UIController.cs" id="3_fe62s"] | ||||
| [ext_resource type="PackedScene" uid="uid://01d24ij5av1y" path="res://UI/BossBar.tscn" id="5_8njq4"] | ||||
| [ext_resource type="PackedScene" uid="uid://73jm5qjy52vq" path="res://Dialogue/balloon.tscn" id="6_2bdwl"] | ||||
| 
 | ||||
| [node name="World" type="Node2D" node_paths=PackedStringArray("UIController", "MusicPlayer")] | ||||
| [node name="World" type="Node2D" node_paths=PackedStringArray("UIController", "MusicPlayer", "DialogueBalloon")] | ||||
| script = ExtResource("1_1k6ew") | ||||
| StartingArea = ExtResource("2_avsrq") | ||||
| UIController = NodePath("CanvasLayer/UI") | ||||
| MusicPlayer = NodePath("MusicPlayer") | ||||
| DialogueBalloon = NodePath("DialogBalloon") | ||||
| 
 | ||||
| [node name="CanvasLayer" type="CanvasLayer" parent="."] | ||||
| 
 | ||||
|  | @ -70,3 +72,5 @@ grow_horizontal = 2 | |||
| grow_vertical = 2 | ||||
| 
 | ||||
| [node name="MusicPlayer" type="AudioStreamPlayer" parent="."] | ||||
| 
 | ||||
| [node name="DialogBalloon" parent="." instance=ExtResource("6_2bdwl")] | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| [gd_scene load_steps=15 format=3 uid="uid://b2x17su05ou5w"] | ||||
| [gd_scene load_steps=16 format=3 uid="uid://b2x17su05ou5w"] | ||||
| 
 | ||||
| [ext_resource type="PackedScene" uid="uid://clwv2owvk6abe" path="res://Scenes/BaseMap.tscn" id="1_ifiic"] | ||||
| [ext_resource type="Texture2D" uid="uid://b0yiy7w8nxmas" path="res://Assets/Sprites/arena-tileset.png" id="2_wnjm0"] | ||||
|  | @ -7,6 +7,7 @@ | |||
| [ext_resource type="PackedScene" uid="uid://c1w7t6irnohfx" path="res://Entities/Torch.tscn" id="6_1wwor"] | ||||
| [ext_resource type="PackedScene" uid="uid://ceadk7pam7vab" path="res://Entities/TorchLamp.tscn" id="6_jy3pc"] | ||||
| [ext_resource type="Texture2D" uid="uid://d1ukste16yq6v" path="res://Assets/Sprites/Particles/player-light.png" id="7_y7j0e"] | ||||
| [ext_resource type="AudioStream" uid="uid://dy4qjflo1k28b" path="res://Assets/Sounds/calm-storm-ambient.mp3" id="8_wox7d"] | ||||
| 
 | ||||
| [sub_resource type="CanvasTexture" id="CanvasTexture_3n6aa"] | ||||
| diffuse_texture = ExtResource("2_wnjm0") | ||||
|  | @ -251,7 +252,7 @@ physics_layer_0/collision_layer = 1 | |||
| sources/2 = SubResource("TileSetAtlasSource_5yxvt") | ||||
| sources/0 = SubResource("TileSetAtlasSource_fcd6d") | ||||
| 
 | ||||
| [sub_resource type="ShaderMaterial" id="ShaderMaterial_q3ile"] | ||||
| [sub_resource type="ShaderMaterial" id="ShaderMaterial_i75i0"] | ||||
| resource_local_to_scene = true | ||||
| shader = ExtResource("5_h8k5p") | ||||
| shader_parameter/color = Quaternion(1, 1, 1, 1) | ||||
|  | @ -343,7 +344,7 @@ visible = false | |||
| position = Vector2(120, -112) | ||||
| 
 | ||||
| [node name="Doc" parent="Entities" index="18" instance=ExtResource("4_ej0f3")] | ||||
| material = SubResource("ShaderMaterial_q3ile") | ||||
| material = SubResource("ShaderMaterial_i75i0") | ||||
| 
 | ||||
| [node name="PointLight2D" type="PointLight2D" parent="Entities" index="19"] | ||||
| position = Vector2(168, -42) | ||||
|  | @ -357,6 +358,12 @@ height = 16.0 | |||
| 
 | ||||
| [node name="CanvasGroup" type="CanvasGroup" parent="Entities" index="20"] | ||||
| 
 | ||||
| [node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="Entities" index="21"] | ||||
| position = Vector2(19, 23) | ||||
| stream = ExtResource("8_wox7d") | ||||
| volume_db = -5.0 | ||||
| autoplay = true | ||||
| 
 | ||||
| [node name="Areas" parent="." index="2"] | ||||
| visible = false | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,4 +7,7 @@ public partial class GlobalState : Node | |||
|     public Utils.World World { get; set; } | ||||
| 
 | ||||
|     public Progression Progression { get; set; } | ||||
| 
 | ||||
|     [Signal] | ||||
|     public delegate void SummonBossEventHandler(string bossName); | ||||
| } | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ public partial class DocChooseAttackState : NPCState | |||
|     public DocUnwantedFrequencyState UnwantedFrequencyState { get; set; } | ||||
| 
 | ||||
|     [Export] | ||||
|     public DocLanceState LanceState { get; set; } | ||||
|     public DocIntroState LanceIntroState { get; set; } | ||||
| 
 | ||||
|     [Export] | ||||
|     public DocExitState ExitState { get; set; } | ||||
|  | @ -44,7 +44,7 @@ public partial class DocChooseAttackState : NPCState | |||
|     { | ||||
|         if (Doc.Intensity == 3) | ||||
|         { | ||||
|             return LanceState; | ||||
|             return LanceIntroState; | ||||
|         } | ||||
| 
 | ||||
|         if (previous is not DocTelegraphState) | ||||
|  |  | |||
|  | @ -0,0 +1,38 @@ | |||
| using Godot; | ||||
| 
 | ||||
| namespace SupaLidlGame.State.NPC.Doc; | ||||
| 
 | ||||
| public partial class DocIntroState : NPCState | ||||
| { | ||||
|     [Export] | ||||
|     public NPCState NextState { get; set; } | ||||
| 
 | ||||
|     [Export] | ||||
|     public double Duration { get; set; } | ||||
| 
 | ||||
|     private double _currentDuration; | ||||
|     private Characters.Doc _doc; | ||||
| 
 | ||||
|     public override void _Ready() | ||||
|     { | ||||
|         base._Ready(); | ||||
|         _doc = NPC as Characters.Doc; | ||||
|     } | ||||
| 
 | ||||
|     public override NPCState Enter(IState<NPCState> previousState) | ||||
|     { | ||||
|         _currentDuration = Duration; | ||||
|         _doc.MiscAnimation.Play("intro"); | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     public override NPCState Process(double delta) | ||||
|     { | ||||
|         if ((_currentDuration -= delta) <= 0) | ||||
|         { | ||||
|             return NextState; | ||||
|         } | ||||
| 
 | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
|  | @ -36,52 +36,13 @@ public partial class DocLanceState : DocAttackState | |||
|     { | ||||
|         var state = base.Enter(previousState); | ||||
|         _doc.ShouldMove = true; | ||||
|         _doc.GetNode<AudioStreamPlayer2D>("Effects/BattleCry").Play(); | ||||
| 
 | ||||
|         //if (_doc.Intensity > 2) | ||||
|         //{ | ||||
|         //    if (_doc.Inventory.SelectedItem != _doc.LanceHold) | ||||
|         //    { | ||||
|         //        _doc.Inventory.SelectedItem = _doc.LanceHold; | ||||
|         //        _doc.UseCurrentItem(); | ||||
|         //        _doc.CanAttack = false; | ||||
|         //    } | ||||
|         //} | ||||
|         //else | ||||
|         //{ | ||||
|         //    // wtf are we doing here? | ||||
|         //    throw new System.InvalidOperationException(); | ||||
|         //} | ||||
| 
 | ||||
|         //_oldFriction = _doc.Friction; | ||||
|         //_doc.Friction = 0; | ||||
| 
 | ||||
|         //Attack(); | ||||
| 
 | ||||
|         return state; | ||||
|     } | ||||
| 
 | ||||
|     public override void Exit(IState<NPCState> nextState) | ||||
|     { | ||||
|         //_doc.Friction = _oldFriction; | ||||
|         //_doc.ApplyImpulse(Vector2.Zero, true); | ||||
|         //_doc.DeuseCurrentItem(); | ||||
|         //_doc.CanAttack = true; | ||||
|         base.Exit(nextState); | ||||
|     } | ||||
| 
 | ||||
|     protected override void Attack() | ||||
|     { | ||||
|         //var pos = _doc.GlobalPosition; | ||||
|         //var player = _world.CurrentPlayer; | ||||
|         //var playerPos = player.GlobalPosition; | ||||
|         //var predictedPos = Utils.Physics.PredictNewPosition( | ||||
|         //    pos, DashSpeed, playerPos, player.Velocity, out float time); | ||||
|         //var dir = _doc.GlobalPosition.DirectionTo(predictedPos); | ||||
| 
 | ||||
|         //_currentAttackDuration = AttackDuration = time; | ||||
| 
 | ||||
|         //_doc.ApplyImpulse(dir * DashSpeed, true); | ||||
|     } | ||||
| 
 | ||||
|     public override NPCState Process(double delta) | ||||
|  |  | |||
|  | @ -35,9 +35,9 @@ horizontal_alignment = 1 | |||
| [node name="BarMargin" type="MarginContainer" parent="."] | ||||
| layout_mode = 2 | ||||
| size_flags_vertical = 3 | ||||
| theme_override_constants/margin_left = 64 | ||||
| theme_override_constants/margin_right = 64 | ||||
| theme_override_constants/margin_bottom = 8 | ||||
| theme_override_constants/margin_left = 128 | ||||
| theme_override_constants/margin_right = 128 | ||||
| theme_override_constants/margin_bottom = 32 | ||||
| 
 | ||||
| [node name="BossBar" type="TextureProgressBar" parent="BarMargin"] | ||||
| texture_filter = 1 | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| using Godot; | ||||
| using SupaLidlGame.Characters; | ||||
| using SupaLidlGame.Extensions; | ||||
| using SupaLidlGame.Scenes; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
|  | @ -26,6 +27,9 @@ public partial class World : Node2D | |||
|     [Export] | ||||
|     public AudioStreamPlayer MusicPlayer { get; set; } | ||||
| 
 | ||||
|     [Export] | ||||
|     public Dialogue.Balloon DialogueBalloon { get; set; } | ||||
| 
 | ||||
|     private Dictionary<string, Map> _maps; | ||||
| 
 | ||||
|     private string _currentConnector; | ||||
|  | @ -255,4 +259,6 @@ public partial class World : Node2D | |||
|         CurrentPlayer.GlobalPosition = SaveLocation; | ||||
|         CurrentPlayer.Spawn(); | ||||
|     } | ||||
| 
 | ||||
|     public Node FindEntity(string name) => CurrentMap.Entities.GetNode(name); | ||||
| } | ||||
|  |  | |||
|  | @ -18,6 +18,12 @@ config/icon="res://icon.svg" | |||
| [autoload] | ||||
| 
 | ||||
| DebugConsole="*res://Debug/DebugConsole.cs" | ||||
| DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd" | ||||
| GlobalState="*res://State/Global/GlobalState.cs" | ||||
| 
 | ||||
| [dialogue_manager] | ||||
| 
 | ||||
| general/states=["GlobalState"] | ||||
| 
 | ||||
| [display] | ||||
| 
 | ||||
|  | @ -30,6 +36,10 @@ window/stretch/aspect="expand" | |||
| 
 | ||||
| project/assembly_name="SupaLidlGame" | ||||
| 
 | ||||
| [editor_plugins] | ||||
| 
 | ||||
| enabled=PackedStringArray("res://addons/dialogue_manager/plugin.cfg") | ||||
| 
 | ||||
| [input] | ||||
| 
 | ||||
| ui_left={ | ||||
|  | @ -93,6 +103,10 @@ equip_3={ | |||
| ] | ||||
| } | ||||
| 
 | ||||
| [internationalization] | ||||
| 
 | ||||
| locale/translations_pot_files=PackedStringArray("res://Assets/Dialog/doc.dialogue") | ||||
| 
 | ||||
| [layer_names] | ||||
| 
 | ||||
| 2d_physics/layer_1="World" | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue