1350 lines
32 KiB
C#
1350 lines
32 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using Godot;
|
|
using Godot.Bridge;
|
|
using Godot.Collections;
|
|
using Godot.NativeInterop;
|
|
|
|
[ScriptPath("res://Scripts/Common/TextSystem.cs")]
|
|
public partial class TextSystem : NinePatchRect
|
|
{
|
|
public partial class MiniText
|
|
{
|
|
public RichTextLabel textObj;
|
|
|
|
public string text;
|
|
|
|
public string portraitSprite;
|
|
|
|
public AnimatedSprite2D portraitObj;
|
|
|
|
public Vector2 pos = miniDefault;
|
|
|
|
public Vector2 startP;
|
|
|
|
public float time;
|
|
|
|
public const float defaultTime = 10f;
|
|
}
|
|
|
|
[Signal]
|
|
public delegate void DiagEndEventHandler();
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
public AnimatedSprite2D portrait;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
public RichTextLabel text;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
public RichTextLabel[] promptText;
|
|
|
|
[Export(PropertyHint.None, "")]
|
|
public Sprite2D soul;
|
|
|
|
public static TextSystem instance;
|
|
|
|
public static Callable callable;
|
|
|
|
public static string[] replacers;
|
|
|
|
public static StringName[] redirects;
|
|
|
|
public static int lastPrompt;
|
|
|
|
public static Entity caller;
|
|
|
|
private static int currentPrompt;
|
|
|
|
private static int wait;
|
|
|
|
private static int currentIndex;
|
|
|
|
private static bool inPrompt;
|
|
|
|
public static bool overridePlayer = true;
|
|
|
|
public static bool slow;
|
|
|
|
public static bool firstFrame;
|
|
|
|
private static SavePrompt savePrompt;
|
|
|
|
private List<MiniText> miniTexts = new List<MiniText>();
|
|
|
|
private static readonly Vector2 promptOffset = new Vector2(-8f, 8f);
|
|
|
|
private static readonly Vector2 textDefaultPos = new Vector2(12f, 10f);
|
|
|
|
private static readonly Vector2 textDefaultSize = new Vector2(276f, 63f);
|
|
|
|
private static readonly Vector2 textDiagPos = new Vector2(73f, 10f);
|
|
|
|
private static readonly Vector2 textDiagSize = new Vector2(218f, 63f);
|
|
|
|
private static readonly Vector2 miniDefault = new Vector2(195f, 57f);
|
|
|
|
private static List<Texts.TextBlock> current;
|
|
|
|
private static readonly Texture2D dwTex = GD.Load<Texture2D>("res://Sprites/Menus/dwbox.png");
|
|
|
|
private static readonly Texture2D lwTex = GD.Load<Texture2D>("res://Sprites/Menus/utbox.png");
|
|
|
|
private const float topY = -115f;
|
|
|
|
private const float bottomY = 40f;
|
|
|
|
private const float promptDefaultY = 27f;
|
|
|
|
private const float promptBigY = 10f;
|
|
|
|
private static readonly System.Collections.Generic.Dictionary<string, object[]> bleeps = new System.Collections.Generic.Dictionary<string, object[]>
|
|
{
|
|
{
|
|
"Kanako",
|
|
new object[3]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/kanakoTalk.wav"),
|
|
0.85f,
|
|
0.5f
|
|
}
|
|
},
|
|
{
|
|
"KanaFB",
|
|
new object[4]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/kanakoTalk.wav"),
|
|
1f,
|
|
0.5f,
|
|
"Reverb"
|
|
}
|
|
},
|
|
{
|
|
"Warden",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/edTalk.wav"),
|
|
0.85f
|
|
}
|
|
},
|
|
{
|
|
"Bearing",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/aceTalk.wav"),
|
|
0.85f
|
|
}
|
|
},
|
|
{
|
|
"Ceroba",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/cerobaTalk.wav"),
|
|
1f
|
|
}
|
|
},
|
|
{
|
|
"Necklace",
|
|
new object[3]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/cerobaTalk.wav"),
|
|
0.85f,
|
|
0.75f
|
|
}
|
|
},
|
|
{
|
|
"Chujin",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/chujinTalk.wav"),
|
|
1f
|
|
}
|
|
},
|
|
{
|
|
"Dalv",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/dalvTalk.wav"),
|
|
1f
|
|
}
|
|
},
|
|
{
|
|
"Axis",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/axisTalk.wav"),
|
|
1f
|
|
}
|
|
},
|
|
{
|
|
"June",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/juneTalk.wav"),
|
|
1f
|
|
}
|
|
},
|
|
{
|
|
"Martlet",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/martletTalk.wav"),
|
|
1f
|
|
}
|
|
},
|
|
{
|
|
"Starlo",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/starloTalk.wav"),
|
|
1f
|
|
}
|
|
},
|
|
{
|
|
"Melody",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/melodyTalk.wav"),
|
|
1f
|
|
}
|
|
},
|
|
{
|
|
"Ace",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/aceTalk.wav"),
|
|
1f
|
|
}
|
|
},
|
|
{
|
|
"Mooch",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/moochTalk.wav"),
|
|
1f
|
|
}
|
|
},
|
|
{
|
|
"Moray",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/morayTalk.wav"),
|
|
1f
|
|
}
|
|
},
|
|
{
|
|
"Ed",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/edTalk.wav"),
|
|
1f
|
|
}
|
|
},
|
|
{
|
|
"System",
|
|
new object[2]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/SND_TXT2.wav"),
|
|
1f
|
|
}
|
|
},
|
|
{
|
|
"Toast",
|
|
new object[3]
|
|
{
|
|
GD.Load<AudioStream>("res://Audio/Bleeps/snd_mtt6.wav"),
|
|
1f,
|
|
1f
|
|
}
|
|
}
|
|
};
|
|
|
|
public static AudioStreamPlayer bleepPlayer;
|
|
|
|
public static AudioStreamPlayer extraSound;
|
|
|
|
private static readonly StringName dropShadowColor = "font_shadow_color";
|
|
|
|
private static readonly Color shadowColor = new Color(0f, 0f, 0.25f);
|
|
|
|
public static readonly AudioStream defaultBleep = GD.Load<AudioStream>("res://Audio/Bleeps/snd_text.wav");
|
|
|
|
public static readonly AudioStream defaultBleep2 = GD.Load<AudioStream>("res://Audio/Bleeps/SND_TXT2.wav");
|
|
|
|
private static char[] punctuation = new char[4] { '.', ',', '?', '!' };
|
|
|
|
private static readonly PackedScene miniTextObj = GD.Load<PackedScene>("res://Objects/UI/MiniText.tscn");
|
|
|
|
private static readonly System.Collections.Generic.Dictionary<StringName, string> regex = new System.Collections.Generic.Dictionary<StringName, string>
|
|
{
|
|
{ "money", "@(m)(\\d+)" },
|
|
{ "var", "@(v)(\\d+)" }
|
|
};
|
|
|
|
|
|
public static void LoadText(in string filename, ref System.Collections.Generic.Dictionary<string, Texts.TextBlock[]> dictionary)
|
|
{
|
|
dictionary.Clear();
|
|
using FileAccess fileAccess = FileAccess.Open(Texts.textFolder + "/" + filename, FileAccess.ModeFlags.Read);
|
|
string[] array = fileAccess.GetAsText(skipCr: true).Split('\n');
|
|
bool flag = false;
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
flag = false;
|
|
if (array[i].Length <= 0 || array[i][0] != '@')
|
|
{
|
|
continue;
|
|
}
|
|
List<Texts.TextBlock> list = new List<Texts.TextBlock>();
|
|
string text = array[i].Remove(0, 1);
|
|
Texts.TextBlock textBlock = new Texts.TextBlock();
|
|
if (flag)
|
|
{
|
|
textBlock.top = true;
|
|
}
|
|
for (int j = i + 1; j < array.Length; j++)
|
|
{
|
|
if (array[j] == "END")
|
|
{
|
|
list.Add(textBlock);
|
|
break;
|
|
}
|
|
if (array[j].Length <= 0)
|
|
{
|
|
continue;
|
|
}
|
|
if (array[j][0] == '.')
|
|
{
|
|
list.Add(textBlock);
|
|
textBlock = new Texts.TextBlock();
|
|
if (flag)
|
|
{
|
|
textBlock.top = true;
|
|
}
|
|
}
|
|
else if (array[j][0] == '>')
|
|
{
|
|
string[] array2 = array[j].Remove(0, 1).Split(':');
|
|
switch (array2[0].ToLower())
|
|
{
|
|
case "setflag":
|
|
case "flag":
|
|
{
|
|
textBlock.setFlags = new Array<SaveFile.Flags>();
|
|
for (int l = 1; l < array2.Length; l++)
|
|
{
|
|
textBlock.setFlags.Add((SaveFile.Flags)Enum.Parse(typeof(SaveFile.Flags), array2[l]));
|
|
}
|
|
break;
|
|
}
|
|
case "talkanim":
|
|
textBlock.talkAnim = array2[1];
|
|
break;
|
|
case "endanim":
|
|
textBlock.endAnim = array2[1];
|
|
break;
|
|
case "bleep":
|
|
textBlock.bleep = array2[1];
|
|
break;
|
|
case "portrait":
|
|
case "p":
|
|
textBlock.portrait = array2[1];
|
|
break;
|
|
case "setvalue":
|
|
case "value":
|
|
textBlock.setValue.Add(new int[3]
|
|
{
|
|
Convert.ToInt32(array2[1]),
|
|
Convert.ToInt32(array2[2]),
|
|
(array2.Length > 3) ? Convert.ToInt32(array2[3]) : 0
|
|
});
|
|
break;
|
|
case "anim":
|
|
textBlock.anims.Add(new StringName[2]
|
|
{
|
|
array2[1],
|
|
array2[2]
|
|
});
|
|
break;
|
|
case "save":
|
|
case "callsave":
|
|
textBlock.callSave = true;
|
|
break;
|
|
case "additem":
|
|
case "item":
|
|
textBlock.addItem.Add(new object[3]
|
|
{
|
|
(Items.Type)Enum.Parse(typeof(Items.Type), array2[1]),
|
|
(Items.IDs)Enum.Parse(typeof(Items.IDs), array2[2]),
|
|
(array2.Length <= 3) ? 1 : Convert.ToInt32(array2[3])
|
|
});
|
|
break;
|
|
case "heal":
|
|
textBlock.heal = true;
|
|
break;
|
|
case "mini":
|
|
textBlock.mini.Add(new MiniText
|
|
{
|
|
text = array2[2],
|
|
portraitSprite = array2[1]
|
|
});
|
|
if (array2.Length > 3)
|
|
{
|
|
List<MiniText> mini = textBlock.mini;
|
|
mini[mini.Count - 1].pos = new Vector2(Convert.ToSingle(array2[3]), Convert.ToSingle(array2[4]));
|
|
}
|
|
break;
|
|
case "changehp":
|
|
textBlock.changeHP = Convert.ToInt32(array2[1]);
|
|
break;
|
|
case "redirect":
|
|
if (array2.Length == 2)
|
|
{
|
|
textBlock.redirectOnFlag.Add(new object[2]
|
|
{
|
|
SaveFile.Flags.None,
|
|
array2[1]
|
|
});
|
|
}
|
|
else
|
|
{
|
|
textBlock.redirectOnFlag.Add(new object[2]
|
|
{
|
|
(SaveFile.Flags)Enum.Parse(typeof(SaveFile.Flags), array2[1]),
|
|
array2[2]
|
|
});
|
|
}
|
|
break;
|
|
case "prompts":
|
|
case "prompt":
|
|
{
|
|
textBlock.prompts = new string[array2.Length - 1];
|
|
for (int num2 = 0; num2 < array2.Length - 1; num2++)
|
|
{
|
|
textBlock.prompts[num2] = array2[num2 + 1].Replace("@", "\n");
|
|
}
|
|
break;
|
|
}
|
|
case "presult":
|
|
case "predirect":
|
|
case "promptredirect":
|
|
case "promptresult":
|
|
{
|
|
textBlock.redirects = new StringName[array2.Length - 1];
|
|
for (int num = 0; num < array2.Length - 1; num++)
|
|
{
|
|
textBlock.redirects[num] = array2[num + 1];
|
|
}
|
|
break;
|
|
}
|
|
case "promptneed":
|
|
{
|
|
textBlock.promptReq = new Array<SaveFile.Flags>();
|
|
for (int n = 0; n < array2.Length - 1; n++)
|
|
{
|
|
if (array2[n].Length > 2 && Enum.TryParse<SaveFile.Flags>(array2[n + 1], ignoreCase: true, out var result2))
|
|
{
|
|
textBlock.promptReq.Add(result2);
|
|
}
|
|
else
|
|
{
|
|
textBlock.promptReq.Add(SaveFile.Flags.None);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case "promptlimit":
|
|
{
|
|
textBlock.promptLimit = new Array<SaveFile.Flags>();
|
|
for (int m = 0; m < array2.Length - 1; m++)
|
|
{
|
|
if (array2[m].Length > 2 && Enum.TryParse<SaveFile.Flags>(array2[m + 1], ignoreCase: true, out var result))
|
|
{
|
|
textBlock.promptLimit.Add(result);
|
|
}
|
|
else
|
|
{
|
|
textBlock.promptLimit.Add(SaveFile.Flags.None);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case "hide":
|
|
textBlock.hide = true;
|
|
break;
|
|
case "hidebg":
|
|
textBlock.noBG = true;
|
|
break;
|
|
case "slow":
|
|
textBlock.delay = ((array2.Length == 1) ? 3 : Convert.ToInt32(array2[1]));
|
|
break;
|
|
case "event":
|
|
case "callevent":
|
|
textBlock.commonEvent = array2[1];
|
|
break;
|
|
case "instant":
|
|
textBlock.instant = true;
|
|
break;
|
|
case "instend":
|
|
textBlock.instEnd = true;
|
|
break;
|
|
case "sound":
|
|
case "soundstart":
|
|
textBlock.soundStart = array2[1];
|
|
if (array2.Length > 2 && array2[2] == "wait")
|
|
{
|
|
textBlock.waitSound = true;
|
|
}
|
|
break;
|
|
case "soundend":
|
|
textBlock.soundEnd = array2[1];
|
|
if (array2.Length > 2 && array2[2] == "wait")
|
|
{
|
|
textBlock.waitSound = true;
|
|
}
|
|
break;
|
|
case "tc":
|
|
textBlock.getTalker = "caller";
|
|
break;
|
|
case "talk":
|
|
textBlock.getTalker = array2[1];
|
|
break;
|
|
case "top":
|
|
textBlock.top = true;
|
|
if (array2.Length > 1 && array2[1] == "lock")
|
|
{
|
|
flag = true;
|
|
}
|
|
break;
|
|
case "mapflag":
|
|
case "setmapflag":
|
|
case "setmap":
|
|
{
|
|
for (int k = 1; k < array2.Length; k++)
|
|
{
|
|
textBlock.setMapFlag.Add(array2[k]);
|
|
}
|
|
break;
|
|
}
|
|
case "redirectmap":
|
|
textBlock.redirectOnMapFlag = new string[2]
|
|
{
|
|
array2[1],
|
|
array2[2]
|
|
};
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
string text2 = array[j].Replace("[shake]", "[shake level=6 rate=7]");
|
|
int num3 = 0;
|
|
for (int num4 = j + 1; num4 < array.Length && array[num4].Length > 0 && array[num4][0] != '.' && array[num4][0] != '>' && array[num4] != "END"; num4++)
|
|
{
|
|
text2 = text2 + "\n" + array[num4];
|
|
num3++;
|
|
}
|
|
textBlock.text = text2;
|
|
j += num3;
|
|
}
|
|
}
|
|
if (!dictionary.ContainsKey(text))
|
|
{
|
|
dictionary.Add(text, list.ToArray());
|
|
continue;
|
|
}
|
|
GD.Print("Text key " + text + " from file " + filename + " already registered before in Main.txt");
|
|
}
|
|
}
|
|
|
|
public override void _EnterTree()
|
|
{
|
|
instance = this;
|
|
if (!GodotObject.IsInstanceValid(bleepPlayer))
|
|
{
|
|
AudioStreamPlayer node = new AudioStreamPlayer
|
|
{
|
|
Bus = "Sound"
|
|
};
|
|
bleepPlayer = node;
|
|
AddChild(node, forceReadableName: false, InternalMode.Disabled);
|
|
}
|
|
}
|
|
|
|
public override void _Process(double delta)
|
|
{
|
|
if (savePrompt != null)
|
|
{
|
|
if (!GodotObject.IsInstanceValid(savePrompt))
|
|
{
|
|
savePrompt = null;
|
|
base.Modulate = Main.colorWhite;
|
|
End();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!base.Visible)
|
|
{
|
|
return;
|
|
}
|
|
soul.Visible = inPrompt;
|
|
if (inPrompt)
|
|
{
|
|
text.VisibleCharacters = int.MaxValue;
|
|
if (currentPrompt > -1)
|
|
{
|
|
soul.Position = promptText[currentPrompt].Position + promptOffset;
|
|
}
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if (i == currentPrompt)
|
|
{
|
|
promptText[i].Modulate = Main.colorYellow;
|
|
}
|
|
else
|
|
{
|
|
promptText[i].Modulate = Main.colorWhite;
|
|
}
|
|
}
|
|
if (Input.IsActionJustPressed(Main.keys[4]) && currentPrompt > -1)
|
|
{
|
|
Audio.PlaySound(Audio.commonSounds[2]);
|
|
inPrompt = false;
|
|
lastPrompt = currentPrompt;
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
promptText[j].Visible = false;
|
|
}
|
|
StringName[] array = redirects;
|
|
if (array != null && array.Length != 0)
|
|
{
|
|
GetText(current[0].redirects[lastPrompt]);
|
|
}
|
|
else
|
|
{
|
|
End();
|
|
}
|
|
return;
|
|
}
|
|
if (Input.IsActionJustPressed(Main.keys[0]) && current[0].prompts.Length >= 3)
|
|
{
|
|
string obj = current[0].prompts[2];
|
|
if (obj != null && obj.Length > 0 && promptText[2].Visible)
|
|
{
|
|
currentPrompt = 2;
|
|
Audio.PlaySound(Audio.commonSounds[0]);
|
|
return;
|
|
}
|
|
}
|
|
if (Input.IsActionJustPressed(Main.keys[1]) && current[0].prompts.Length >= 4)
|
|
{
|
|
string obj2 = current[0].prompts[3];
|
|
if (obj2 != null && obj2.Length > 0 && promptText[3].Visible)
|
|
{
|
|
currentPrompt = 3;
|
|
Audio.PlaySound(Audio.commonSounds[0]);
|
|
return;
|
|
}
|
|
}
|
|
if (Input.IsActionJustPressed(Main.keys[2]))
|
|
{
|
|
currentPrompt = 0;
|
|
Audio.PlaySound(Audio.commonSounds[0]);
|
|
}
|
|
else if (Input.IsActionJustPressed(Main.keys[3]))
|
|
{
|
|
currentPrompt = 1;
|
|
Audio.PlaySound(Audio.commonSounds[0]);
|
|
}
|
|
return;
|
|
}
|
|
if (text.VisibleRatio < 1f)
|
|
{
|
|
if (Input.IsActionPressed(Main.keys[7]))
|
|
{
|
|
text.VisibleRatio = 9999f;
|
|
return;
|
|
}
|
|
if (wait > 0)
|
|
{
|
|
wait--;
|
|
}
|
|
else
|
|
{
|
|
if (!bleepPlayer.Playing)
|
|
{
|
|
bleepPlayer.Play();
|
|
}
|
|
do
|
|
{
|
|
currentIndex++;
|
|
if (currentIndex < text.Text.Length && text.Text[currentIndex] == '[')
|
|
{
|
|
for (int k = currentIndex + 1; k < text.Text.Length; k++)
|
|
{
|
|
currentIndex++;
|
|
if (text.Text[k] == ']')
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
text.VisibleCharacters++;
|
|
}
|
|
while (text.VisibleCharacters < text.Text.Length && currentIndex < text.Text.Length && !char.IsLetterOrDigit(text.Text[currentIndex]) && !punctuation.Contains(text.Text[currentIndex - 1]));
|
|
if (currentIndex < text.Text.Length && punctuation.Contains(text.Text[currentIndex - 1]))
|
|
{
|
|
wait = 10;
|
|
bleepPlayer.Stop();
|
|
}
|
|
else if (slow)
|
|
{
|
|
wait = 3;
|
|
}
|
|
else
|
|
{
|
|
wait = current[0].delay;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TalkerIdle();
|
|
portrait.Stop();
|
|
if (bleepPlayer.Playing)
|
|
{
|
|
string soundEnd = current[0].soundEnd;
|
|
if (soundEnd != null && soundEnd.Length > 1)
|
|
{
|
|
extraSound = Audio.PlaySound(current[0].soundEnd);
|
|
}
|
|
}
|
|
bleepPlayer.Stop();
|
|
DoMiniText();
|
|
}
|
|
if (GodotObject.IsInstanceValid(extraSound) && extraSound.Playing && current[0].waitSound)
|
|
{
|
|
return;
|
|
}
|
|
if (Input.IsActionJustPressed(Main.keys[6]))
|
|
{
|
|
text.VisibleRatio = 999f;
|
|
}
|
|
if (firstFrame && (Input.IsActionJustPressed(Main.keys[4]) || Input.IsActionJustPressed(Main.keys[5]) || current[0].instEnd || Input.IsActionPressed(Main.keys[7])))
|
|
{
|
|
if (text.VisibleRatio >= 1f)
|
|
{
|
|
if (current.Count > 1)
|
|
{
|
|
current.RemoveAt(0);
|
|
DoText();
|
|
return;
|
|
}
|
|
if (current[0].callSave)
|
|
{
|
|
base.Modulate = Main.colorClear;
|
|
CameraController.instance.AddChild(savePrompt = GD.Load<PackedScene>("res://Objects/UI/SavePrompt.tscn").Instantiate<SavePrompt>(PackedScene.GenEditState.Disabled), forceReadableName: false, InternalMode.Disabled);
|
|
if (bleepPlayer.Playing)
|
|
{
|
|
bleepPlayer.Stop();
|
|
}
|
|
}
|
|
else if (current[0].prompts != null)
|
|
{
|
|
DestroyMiniText();
|
|
if (Player.instance.controlling.id == Entity.IDs.Kanako)
|
|
{
|
|
instance.soul.RotationDegrees = 180f;
|
|
instance.soul.Modulate = Main.colorWhite;
|
|
}
|
|
else
|
|
{
|
|
instance.soul.RotationDegrees = 0f;
|
|
instance.soul.Modulate = Main.colorYellow;
|
|
}
|
|
bleepPlayer.Stop();
|
|
inPrompt = true;
|
|
currentPrompt = -1;
|
|
soul.Position = new Vector2(149f, 39f);
|
|
redirects = current[0].redirects;
|
|
portrait.Visible = portrait.Visible && current[0].keepTextOnPrompt;
|
|
if (!current[0].keepTextOnPrompt)
|
|
{
|
|
text.Text = "";
|
|
}
|
|
for (int l = 0; l < 4; l++)
|
|
{
|
|
promptText[l].Visible = l < current[0].prompts.Length;
|
|
if (!promptText[l].Visible)
|
|
{
|
|
continue;
|
|
}
|
|
Array<SaveFile.Flags> promptReq = current[0].promptReq;
|
|
if (promptReq == null || promptReq.Count <= 0)
|
|
{
|
|
Array<SaveFile.Flags> promptLimit = current[0].promptLimit;
|
|
if (promptLimit == null || promptLimit.Count <= 0)
|
|
{
|
|
goto IL_084c;
|
|
}
|
|
}
|
|
Array<SaveFile.Flags> spawn = ((current[0].promptReq == null) ? null : new Array<SaveFile.Flags> { current[0].promptReq[l] });
|
|
Array<SaveFile.Flags> despawn = ((current[0].promptLimit == null) ? null : new Array<SaveFile.Flags> { current[0].promptReq[l] });
|
|
if (!SaveFile.CanDo(spawn, despawn))
|
|
{
|
|
promptText[l].Visible = false;
|
|
continue;
|
|
}
|
|
goto IL_084c;
|
|
IL_084c:
|
|
promptText[l].Text = current[0].prompts[l];
|
|
if (l < 2)
|
|
{
|
|
if (promptText[l].GetLineCount() > 2)
|
|
{
|
|
promptText[l].Position = new Vector2(promptText[l].Position.X, 10f);
|
|
}
|
|
else
|
|
{
|
|
promptText[l].Position = new Vector2(promptText[l].Position.X, 27f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
StringName next = current[0].next;
|
|
if ((object)next != null && next.ToString().Length > 1)
|
|
{
|
|
if (SaveFile.CanDo(current[0].nextFlags, current[0].nextLimitFlags))
|
|
{
|
|
GetText(current[0].next);
|
|
return;
|
|
}
|
|
End();
|
|
}
|
|
else
|
|
{
|
|
End();
|
|
}
|
|
}
|
|
}
|
|
else if (text.VisibleRatio > 0.1f)
|
|
{
|
|
text.VisibleRatio = 999f;
|
|
}
|
|
}
|
|
firstFrame = true;
|
|
}
|
|
}
|
|
|
|
private static void TalkerIdle()
|
|
{
|
|
Entity talking = current[0].talking;
|
|
if (talking != null)
|
|
{
|
|
AnimationPlayer anim = talking.anim;
|
|
string idleOverride = current[0].talking.idleOverride;
|
|
anim.Play((idleOverride != null && idleOverride.Length > 0) ? ((StringName)current[0].talking.idleOverride) : current[0].endAnim);
|
|
}
|
|
}
|
|
|
|
private static void DoMiniText()
|
|
{
|
|
List<MiniText> mini = current[0].mini;
|
|
if (mini == null || mini.Count <= 0)
|
|
{
|
|
return;
|
|
}
|
|
if (instance.miniTexts.Count == 0)
|
|
{
|
|
for (int i = 0; i < current[0].mini.Count; i++)
|
|
{
|
|
AnimatedSprite2D animatedSprite2D = miniTextObj.Instantiate<AnimatedSprite2D>(PackedScene.GenEditState.Disabled);
|
|
instance.AddChild(animatedSprite2D, forceReadableName: false, InternalMode.Disabled);
|
|
instance.miniTexts.Add(new MiniText
|
|
{
|
|
portraitObj = animatedSprite2D,
|
|
textObj = animatedSprite2D.GetChild<RichTextLabel>(0),
|
|
startP = current[0].mini[i].pos + Vector2.Right * 10f,
|
|
pos = current[0].mini[i].pos
|
|
});
|
|
List<MiniText> list = instance.miniTexts;
|
|
list[list.Count - 1].textObj.Text = current[0].mini[i].text;
|
|
animatedSprite2D.Play(current[0].mini[i].portraitSprite);
|
|
animatedSprite2D.Stop();
|
|
List<MiniText> list2 = instance.miniTexts;
|
|
animatedSprite2D.Position = list2[list2.Count - 1].startP;
|
|
animatedSprite2D.Modulate = Main.colorClear;
|
|
}
|
|
}
|
|
for (int j = 0; j < current[0].mini.Count; j++)
|
|
{
|
|
if (instance.miniTexts[j].time < 10f)
|
|
{
|
|
instance.miniTexts[j].time += Main.deltaTime;
|
|
}
|
|
instance.miniTexts[j].portraitObj.Position = instance.miniTexts[j].startP.Lerp(instance.miniTexts[j].pos, Mathf.Min(instance.miniTexts[j].time / 10f, 1f));
|
|
instance.miniTexts[j].portraitObj.Modulate = instance.miniTexts[j].portraitObj.Modulate.Lerp(Main.colorWhite, Main.deltaTime * 0.1f);
|
|
}
|
|
}
|
|
|
|
private static void DestroyMiniText()
|
|
{
|
|
List<MiniText> list = instance.miniTexts;
|
|
if (list != null && list.Count > 0)
|
|
{
|
|
for (int i = 0; i < instance.miniTexts.Count; i++)
|
|
{
|
|
instance.miniTexts[i].portraitObj.QueueFree();
|
|
}
|
|
instance.miniTexts.Clear();
|
|
}
|
|
}
|
|
|
|
public static void GetText(string key)
|
|
{
|
|
current = new List<Texts.TextBlock>(Texts.FindDiag(in key));
|
|
DoText();
|
|
}
|
|
|
|
public static void End()
|
|
{
|
|
if (current[0].callEvent != null)
|
|
{
|
|
Room.current.DoEvent((int)current[0].callEvent[0], (string)current[0].callEvent[1]);
|
|
}
|
|
TalkerIdle();
|
|
for (int i = 0; i < instance.promptText.Length; i++)
|
|
{
|
|
instance.promptText[i].Modulate = Main.colorWhite;
|
|
}
|
|
caller = null;
|
|
if (Main.inEvent == null || Main.inEvent.done)
|
|
{
|
|
Player.instance.EndInteraction();
|
|
}
|
|
instance.Visible = false;
|
|
instance.EmitSignal(SignalName.DiagEnd);
|
|
Room room = Room.current;
|
|
if (room != null && room.stopOnDiag?.Length > 0)
|
|
{
|
|
for (int j = 0; j < Room.current.stopOnDiag.Length; j++)
|
|
{
|
|
Room.current.stopOnDiag[j].ProcessMode = ProcessModeEnum.Inherit;
|
|
}
|
|
}
|
|
instance.soul.Visible = false;
|
|
bleepPlayer.Stop();
|
|
bleepPlayer.PitchScale = 1f;
|
|
bleepPlayer.VolumeDb = Mathf.LinearToDb(1f);
|
|
overridePlayer = true;
|
|
}
|
|
|
|
private static void DoText()
|
|
{
|
|
firstFrame = false;
|
|
currentIndex = 0;
|
|
List<object[]> redirectOnFlag = current[0].redirectOnFlag;
|
|
if (redirectOnFlag != null && redirectOnFlag.Count > 0)
|
|
{
|
|
for (int i = 0; i < current[0].redirectOnFlag.Count; i++)
|
|
{
|
|
if ((SaveFile.Flags)current[0].redirectOnFlag[i][0] == SaveFile.Flags.None || SaveFile.HasFlag((SaveFile.Flags)current[0].redirectOnFlag[i][0]))
|
|
{
|
|
GetText((string)current[0].redirectOnFlag[i][1]);
|
|
DoText();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if (current[0].redirectOnMapFlag != null && Room.current.tempFlags.Contains(current[0].redirectOnMapFlag[0]))
|
|
{
|
|
GetText(current[0].redirectOnMapFlag[1]);
|
|
DoText();
|
|
return;
|
|
}
|
|
Room room = Room.current;
|
|
if (room != null && room.entities?.Count > 0)
|
|
{
|
|
List<StringName[]> anims = current[0].anims;
|
|
if (anims != null && anims.Count > 0)
|
|
{
|
|
for (int j = 0; j < current[0].anims.Count; j++)
|
|
{
|
|
Entity entity = Room.GetEntity(current[0].anims[j][0], removeNull: true);
|
|
if (entity != null)
|
|
{
|
|
if (current[0].anims[j][1] == (StringName)"force")
|
|
{
|
|
entity.UpdateAnim(force: true);
|
|
}
|
|
else
|
|
{
|
|
entity.anim.Play(current[0].anims[j][1]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DestroyMiniText();
|
|
if (BattleDR.current == null)
|
|
{
|
|
DWMenu.instance.showHP = 0f;
|
|
}
|
|
string input = current[0].text;
|
|
foreach (StringName key in regex.Keys)
|
|
{
|
|
MatchCollection matchCollection = Regex.Matches(input, regex[key]);
|
|
for (int k = 0; k < matchCollection.Count; k++)
|
|
{
|
|
string text = key;
|
|
if (text == "money" || text == "var")
|
|
{
|
|
int num = SaveFile.current.values[Convert.ToInt32(matchCollection[k].Groups[2].Value)];
|
|
input = current[0].text.Replace(matchCollection[k].Value, num.ToString());
|
|
if (key == (StringName)"money")
|
|
{
|
|
SaveFile.current.dollars = Mathf.Clamp(SaveFile.current.dollars + num, 0, 9999);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
List<int[]> setValue = current[0].setValue;
|
|
if (setValue != null && setValue.Count > 0)
|
|
{
|
|
for (int l = 0; l < current[0].setValue.Count; l++)
|
|
{
|
|
switch (current[0].setValue[l][2])
|
|
{
|
|
case 0:
|
|
if (current[0].setValue[l][0] == -1)
|
|
{
|
|
SaveFile.current.dollars += current[0].setValue[l][1];
|
|
}
|
|
else
|
|
{
|
|
SaveFile.current.values[current[0].setValue[l][0]] += current[0].setValue[l][1];
|
|
}
|
|
break;
|
|
case 1:
|
|
if (current[0].setValue[l][0] == -1)
|
|
{
|
|
SaveFile.current.dollars -= current[0].setValue[l][1];
|
|
}
|
|
else
|
|
{
|
|
SaveFile.current.values[current[0].setValue[l][0]] -= current[0].setValue[l][1];
|
|
}
|
|
break;
|
|
case 2:
|
|
if (current[0].setValue[l][0] == -1)
|
|
{
|
|
SaveFile.current.dollars = current[0].setValue[l][1];
|
|
}
|
|
else
|
|
{
|
|
SaveFile.current.values[current[0].setValue[l][0]] = current[0].setValue[l][1];
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
List<object[]> addItem = current[0].addItem;
|
|
if (addItem != null && addItem.Count > 0)
|
|
{
|
|
bool flag = false;
|
|
for (int m = 0; m < current[0].addItem.Count; m++)
|
|
{
|
|
for (int n = 0; n < Mathf.Abs((int)current[0].addItem[m][2]); n++)
|
|
{
|
|
if ((int)current[0].addItem[m][2] > 0)
|
|
{
|
|
switch ((Items.Type)current[0].addItem[m][0])
|
|
{
|
|
case Items.Type.Equip:
|
|
SaveFile.current.dwArmor.Add((Items.IDs)current[0].addItem[m][1]);
|
|
break;
|
|
case Items.Type.Weapon:
|
|
SaveFile.current.dwWeapon.Add((Items.IDs)current[0].addItem[m][1]);
|
|
break;
|
|
case Items.Type.Normal:
|
|
SaveFile.current.dwItems.Add((Items.IDs)current[0].addItem[m][1]);
|
|
break;
|
|
case Items.Type.Key:
|
|
SaveFile.current.dwKey.Add((Items.IDs)current[0].addItem[m][1]);
|
|
break;
|
|
case Items.Type.LightWorld:
|
|
SaveFile.current.lwItems.Add((Items.IDs)current[0].addItem[m][1]);
|
|
break;
|
|
}
|
|
flag = true;
|
|
}
|
|
else
|
|
{
|
|
switch ((Items.Type)current[0].addItem[m][0])
|
|
{
|
|
case Items.Type.Equip:
|
|
SaveFile.current.dwArmor.Remove((Items.IDs)current[0].addItem[m][1]);
|
|
break;
|
|
case Items.Type.Weapon:
|
|
SaveFile.current.dwWeapon.Remove((Items.IDs)current[0].addItem[m][1]);
|
|
break;
|
|
case Items.Type.Normal:
|
|
SaveFile.current.dwItems.Remove((Items.IDs)current[0].addItem[m][1]);
|
|
break;
|
|
case Items.Type.Key:
|
|
SaveFile.current.dwKey.Remove((Items.IDs)current[0].addItem[m][1]);
|
|
break;
|
|
case Items.Type.LightWorld:
|
|
SaveFile.current.lwItems.Remove((Items.IDs)current[0].addItem[m][1]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (flag)
|
|
{
|
|
Audio.PlaySound("snd_item_ch1.wav");
|
|
}
|
|
}
|
|
instance.text.Text = input;
|
|
if ((current[0].instant && current[0].instEnd) || current[0].hide)
|
|
{
|
|
instance.Position = new Vector2(999f, 999f);
|
|
}
|
|
else if (current[0].top)
|
|
{
|
|
instance.Position = new Vector2(-149f, -115f);
|
|
}
|
|
else
|
|
{
|
|
instance.Position = new Vector2(-149f, 40f);
|
|
}
|
|
string soundStart = current[0].soundStart;
|
|
if (soundStart != null && soundStart.Length > 1)
|
|
{
|
|
if (current[0].soundStart.Contains("RoomMusic"))
|
|
{
|
|
Room.current.DoMusic(Convert.ToInt32(current[0].soundStart.Replace("RoomMusic", "")));
|
|
}
|
|
else if (current[0].soundStart == "StopMusic")
|
|
{
|
|
Audio.music.Stop();
|
|
}
|
|
else
|
|
{
|
|
extraSound = Audio.PlaySound(current[0].soundStart);
|
|
}
|
|
}
|
|
instance.text.VisibleRatio = (current[0].instant ? 1 : 0);
|
|
int num2;
|
|
if (!SaveFile.current.flags.Contains(SaveFile.Flags.IsInDW))
|
|
{
|
|
Player player = Player.instance;
|
|
num2 = ((player != null && player.animMod == Entity.AnimMods.DW) ? 1 : 0);
|
|
}
|
|
else
|
|
{
|
|
num2 = 1;
|
|
}
|
|
bool flag2 = (byte)num2 != 0;
|
|
instance.text.AddThemeColorOverride(dropShadowColor, flag2 ? shadowColor : Main.colorClear);
|
|
instance.Texture = (flag2 ? dwTex : lwTex);
|
|
instance.Visible = true;
|
|
string getTalker = current[0].getTalker;
|
|
if (getTalker != null && getTalker.Length > 1)
|
|
{
|
|
if (current[0].getTalker.ToLower() == "caller")
|
|
{
|
|
current[0].talking = caller;
|
|
}
|
|
else
|
|
{
|
|
Room.current.entities.RemoveWhere((Entity x) => !GodotObject.IsInstanceValid(x));
|
|
current[0].talking = Room.current?.entities?.FirstOrDefault((Entity x) => x.Name == (StringName)current[0].getTalker);
|
|
}
|
|
}
|
|
if (overridePlayer)
|
|
{
|
|
Player.instance.StopMoving(Entity.Animations.Idle);
|
|
}
|
|
Player.instance.canInput = false;
|
|
if (current[0].heal)
|
|
{
|
|
Party.Heal();
|
|
}
|
|
Array<SaveFile.Flags> setFlags = current[0].setFlags;
|
|
if (setFlags != null && setFlags.Count > 0)
|
|
{
|
|
for (int num3 = 0; num3 < current[0].setFlags.Count; num3++)
|
|
{
|
|
SaveFile.AddFlag(current[0].setFlags[num3]);
|
|
}
|
|
}
|
|
List<StringName> setMapFlag = current[0].setMapFlag;
|
|
if (setMapFlag != null && setMapFlag.Count > 0)
|
|
{
|
|
for (int num4 = 0; num4 < current[0].setMapFlag.Count; num4++)
|
|
{
|
|
Room.current.tempFlags.Add(current[0].setMapFlag[num4]);
|
|
}
|
|
}
|
|
if (current[0].changeHP != 0)
|
|
{
|
|
for (int num5 = 0; num5 < SaveFile.current.activeParty.Count; num5++)
|
|
{
|
|
Party.party[SaveFile.current.activeParty[num5]].HP = Mathf.Clamp(current[0].changeHP + Party.party[SaveFile.current.activeParty[num5]].HP, 0, Party.party[SaveFile.current.activeParty[num5]].MAXHP);
|
|
}
|
|
}
|
|
float volume = 1f;
|
|
Texts.TextBlock textBlock = current[0];
|
|
if (textBlock != null && textBlock.portrait?.ToString()?.Length > 1)
|
|
{
|
|
if (current[0].portrait != (StringName)"KEEP")
|
|
{
|
|
instance.portrait.Play(current[0].portrait);
|
|
string bleep = current[0].bleep;
|
|
if (bleep != null && bleep.Length > 1)
|
|
{
|
|
AssignBleep(current[0].bleep, ref volume);
|
|
}
|
|
else
|
|
{
|
|
AssignBleep(current[0].portrait, ref volume);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
volume = -1f;
|
|
}
|
|
instance.portrait.Visible = true;
|
|
instance.portrait.Play();
|
|
}
|
|
else
|
|
{
|
|
string bleep2 = current[0].bleep;
|
|
if (bleep2 != null && bleep2.Length > 1)
|
|
{
|
|
AssignBleep(current[0].bleep, ref volume);
|
|
}
|
|
else
|
|
{
|
|
bleepPlayer.Bus = "Sound";
|
|
bleepPlayer.Stream = defaultBleep;
|
|
bleepPlayer.PitchScale = 1f;
|
|
}
|
|
instance.portrait.Visible = false;
|
|
}
|
|
if (volume != -1f)
|
|
{
|
|
bleepPlayer.VolumeDb = Mathf.LinearToDb(volume);
|
|
}
|
|
bleepPlayer.Play();
|
|
if (current[0].talking?.anim != null)
|
|
{
|
|
string talkOverride = current[0].talking.talkOverride;
|
|
string text2 = ((talkOverride != null && talkOverride.Length > 0) ? current[0].talking.talkOverride : ((string?)current[0].talkAnim));
|
|
if (current[0].talking.anim.HasAnimation(text2))
|
|
{
|
|
current[0].talking.anim.Play(text2);
|
|
}
|
|
}
|
|
Room room2 = Room.current;
|
|
if (room2 != null && room2.stopOnDiag?.Length > 0)
|
|
{
|
|
for (int num6 = 0; num6 < Room.current.stopOnDiag.Length; num6++)
|
|
{
|
|
Room.current.stopOnDiag[num6].ProcessMode = ProcessModeEnum.Disabled;
|
|
}
|
|
}
|
|
if (instance.portrait.Visible)
|
|
{
|
|
instance.text.Size = textDiagSize;
|
|
instance.text.Position = textDiagPos;
|
|
}
|
|
else
|
|
{
|
|
instance.text.Size = textDefaultSize;
|
|
instance.text.Position = textDefaultPos;
|
|
}
|
|
if (current[0].noBG)
|
|
{
|
|
instance.SelfModulate = Main.colorClear;
|
|
}
|
|
else
|
|
{
|
|
instance.SelfModulate = Main.colorWhite;
|
|
}
|
|
if (Main.inEvent == null)
|
|
{
|
|
Player.instance.CallDeferred(Player.MethodName.PartyStop);
|
|
}
|
|
}
|
|
|
|
public static void AssignBleep(string name, ref float volume)
|
|
{
|
|
bool flag = false;
|
|
bleepPlayer.Bus = "Sound";
|
|
if (name != null && name.Length > 0)
|
|
{
|
|
foreach (string key in bleeps.Keys)
|
|
{
|
|
if (name.Contains(key))
|
|
{
|
|
flag = true;
|
|
object[] array = bleeps[key];
|
|
bleepPlayer.Stream = (AudioStream)array[0];
|
|
bleepPlayer.PitchScale = (float)array[1];
|
|
if (array.Length > 2)
|
|
{
|
|
volume = (float)array[2];
|
|
}
|
|
if (array.Length > 3)
|
|
{
|
|
bleepPlayer.Bus = (string)array[3];
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!flag)
|
|
{
|
|
bleepPlayer.Stream = defaultBleep;
|
|
bleepPlayer.PitchScale = 1f;
|
|
}
|
|
}
|
|
|
|
public static void SingleText(Texts.TextBlock[] texts)
|
|
{
|
|
current = new List<Texts.TextBlock>(texts);
|
|
DoText();
|
|
}
|
|
|
|
public static void SingleText(string text, string portrait = null, string next = null, string[] prompts = null)
|
|
{
|
|
current = new List<Texts.TextBlock>
|
|
{
|
|
new Texts.TextBlock
|
|
{
|
|
text = text,
|
|
portrait = portrait,
|
|
next = next,
|
|
prompts = prompts
|
|
}
|
|
};
|
|
DoText();
|
|
}
|
|
|
|
public static void TextBlock(Texts.TextBlock[] blocks)
|
|
{
|
|
current = new List<Texts.TextBlock>(blocks);
|
|
DoText();
|
|
}
|
|
|
|
}
|