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 miniTexts = new List(); 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 current; private static readonly Texture2D dwTex = GD.Load("res://Sprites/Menus/dwbox.png"); private static readonly Texture2D lwTex = GD.Load("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 bleeps = new System.Collections.Generic.Dictionary { { "Kanako", new object[3] { GD.Load("res://Audio/Bleeps/kanakoTalk.wav"), 0.85f, 0.5f } }, { "KanaFB", new object[4] { GD.Load("res://Audio/Bleeps/kanakoTalk.wav"), 1f, 0.5f, "Reverb" } }, { "Warden", new object[2] { GD.Load("res://Audio/Bleeps/edTalk.wav"), 0.85f } }, { "Bearing", new object[2] { GD.Load("res://Audio/Bleeps/aceTalk.wav"), 0.85f } }, { "Ceroba", new object[2] { GD.Load("res://Audio/Bleeps/cerobaTalk.wav"), 1f } }, { "Necklace", new object[3] { GD.Load("res://Audio/Bleeps/cerobaTalk.wav"), 0.85f, 0.75f } }, { "Chujin", new object[2] { GD.Load("res://Audio/Bleeps/chujinTalk.wav"), 1f } }, { "Dalv", new object[2] { GD.Load("res://Audio/Bleeps/dalvTalk.wav"), 1f } }, { "Axis", new object[2] { GD.Load("res://Audio/Bleeps/axisTalk.wav"), 1f } }, { "June", new object[2] { GD.Load("res://Audio/Bleeps/juneTalk.wav"), 1f } }, { "Martlet", new object[2] { GD.Load("res://Audio/Bleeps/martletTalk.wav"), 1f } }, { "Starlo", new object[2] { GD.Load("res://Audio/Bleeps/starloTalk.wav"), 1f } }, { "Melody", new object[2] { GD.Load("res://Audio/Bleeps/melodyTalk.wav"), 1f } }, { "Ace", new object[2] { GD.Load("res://Audio/Bleeps/aceTalk.wav"), 1f } }, { "Mooch", new object[2] { GD.Load("res://Audio/Bleeps/moochTalk.wav"), 1f } }, { "Moray", new object[2] { GD.Load("res://Audio/Bleeps/morayTalk.wav"), 1f } }, { "Ed", new object[2] { GD.Load("res://Audio/Bleeps/edTalk.wav"), 1f } }, { "System", new object[2] { GD.Load("res://Audio/Bleeps/SND_TXT2.wav"), 1f } }, { "Toast", new object[3] { GD.Load("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("res://Audio/Bleeps/snd_text.wav"); public static readonly AudioStream defaultBleep2 = GD.Load("res://Audio/Bleeps/SND_TXT2.wav"); private static char[] punctuation = new char[4] { '.', ',', '?', '!' }; private static readonly PackedScene miniTextObj = GD.Load("res://Objects/UI/MiniText.tscn"); private static readonly System.Collections.Generic.Dictionary regex = new System.Collections.Generic.Dictionary { { "money", "@(m)(\\d+)" }, { "var", "@(v)(\\d+)" } }; public static void LoadText(in string filename, ref System.Collections.Generic.Dictionary 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 list = new List(); 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(); 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 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(); for (int n = 0; n < array2.Length - 1; n++) { if (array2[n].Length > 2 && Enum.TryParse(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(); for (int m = 0; m < array2.Length - 1; m++) { if (array2[m].Length > 2 && Enum.TryParse(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("res://Objects/UI/SavePrompt.tscn").Instantiate(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 promptReq = current[0].promptReq; if (promptReq == null || promptReq.Count <= 0) { Array promptLimit = current[0].promptLimit; if (promptLimit == null || promptLimit.Count <= 0) { goto IL_084c; } } Array spawn = ((current[0].promptReq == null) ? null : new Array { current[0].promptReq[l] }); Array despawn = ((current[0].promptLimit == null) ? null : new Array { 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 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(PackedScene.GenEditState.Disabled); instance.AddChild(animatedSprite2D, forceReadableName: false, InternalMode.Disabled); instance.miniTexts.Add(new MiniText { portraitObj = animatedSprite2D, textObj = animatedSprite2D.GetChild(0), startP = current[0].mini[i].pos + Vector2.Right * 10f, pos = current[0].mini[i].pos }); List list = instance.miniTexts; list[list.Count - 1].textObj.Text = current[0].mini[i].text; animatedSprite2D.Play(current[0].mini[i].portraitSprite); animatedSprite2D.Stop(); List 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 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.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 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 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 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 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 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 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); DoText(); } public static void SingleText(string text, string portrait = null, string next = null, string[] prompts = null) { current = new List { new Texts.TextBlock { text = text, portrait = portrait, next = next, prompts = prompts } }; DoText(); } public static void TextBlock(Texts.TextBlock[] blocks) { current = new List(blocks); DoText(); } }