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