using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Networking; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("BossVSIntro")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Boss VS Intro")] [assembly: AssemblyTitle("BossVSIntro")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BossVSIntro { [BepInPlugin("com.scout.bossvsintro", "Boss VS Intro", "1.3.0")] public class BossVSIntroPlugin : BaseUnityPlugin { public const string PluginGuid = "com.scout.bossvsintro"; public const string PluginName = "Boss VS Intro"; public const string PluginVersion = "1.3.0"; internal static BossVSIntroPlugin Instance; internal static ManualLogSource Log; internal static string ImagesRoot; internal static string SoundsRoot; internal static string TextRoot; internal static string PluginDir; private void Awake() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; PluginDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); ImagesRoot = Path.Combine(PluginDir, "Images"); SoundsRoot = Path.Combine(PluginDir, "Sounds"); TextRoot = Path.Combine(PluginDir, "Text"); new Harmony("com.scout.bossvsintro").PatchAll(); Log.LogInfo((object)"Boss VS Intro v1.3.0 loaded."); SceneManager.sceneLoaded += delegate { BossVSIntroPatch.ClearOutroWatch(); }; BossVSIntroPatch.BeginPreloadSounds(); } private void Update() { BossVSIntroPatch.EnsureRunner(); } } internal static class VSConfig { public static float introCooldown = 5f; public static float slideInDuration = 0.45f; public static float vsPopDuration = 0.35f; public static float vsStartScale = 3.5f; public static float vsHeightFraction = 0.35f; public static float shakeDuration = 0.4f; public static float colorFadeDuration = 0.35f; public static float shakeAmplitude = 38f; public static float holdDuration = 1f; public static float slideOutDuration = 0.4f; public static float centerGap = -1920f; public static string triggerSoundFile = "Trigger.wav"; public static float soundVolume = 1f; public static float vsDelay = 1f; public static string playerFileName = "Player.png"; public static string vsFileName = "VS.png"; public static string bossFolderName = "Bosses"; public static string bossFallbackName = "Default.png"; public static string backgroundFolderName = "Backgrounds"; public static string backgroundFallbackName = "Default.png"; public static string backgroundPlayerFolder = "Player"; public static string backgroundBossesFolder = "Bosses"; public static string playerTextFileName = "Player.txt"; public static string textFallbackName = "Default.txt"; public static float textFontSize = 72f; public static float textYFraction = -0.32f; public static float textSlideDuration = 0.35f; public static float textOutlineWidth = 0.1f; public static float positionTolerance = 6f; public static float barVisibleTimeout = 5f; public static string crossOutFileName = "CROSSEDOUT.png"; public static string iconFolderName = "Icons"; public static float iconHeightFraction = 1f; public static float crossOutHeightFraction = 0.5f; public static float outroCrossDelay = 0.5f; public static float outroHoldDuration = 1f; public static string ultrakilledTextFileName = "ULTRAKILLED.txt"; public static string objectDeathBosses = "1000_THR_DEFENCE_SYSTEM"; public static string earthmoverBossName = "1000_THR_EARTHMOVER"; public static string earthmoverStyleName = "RAISON D'ETRE"; public static bool logOutroWatch = false; public static string audioTriggerOutros = "LEVEL_4_4|V2|Versus2Outro"; public static float outroTriggerDelay = 1f; public static float outroBossTextX = 0f; public static float outroBossTextY = -256f; public static string outroSoundFile = "Outro.wav"; } public class VSRunner : MonoBehaviour { private void Update() { BossVSIntroPatch.CheckOutroWatch(); BossVSIntroPatch.CheckAudioTrigger(); } } public class RectFollower : MonoBehaviour { public RectTransform target; private RectTransform self; private void Awake() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown self = (RectTransform)((Component)this).transform; } private void LateUpdate() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target != (Object)null && (Object)(object)self != (Object)null) { self.anchoredPosition = target.anchoredPosition; } } } [HarmonyPatch(typeof(BossHealthBarTemplate))] public class BossVSIntroPatch { private class WatchedBoss { public Component eid; public BossHealthBar bar; public string bossName; public Vector3 bossPos; public string level; public bool objectDeath; } private class TextSpec { public string title; public bool hasPos; public Vector2 pos; public bool hasSize; public float size; public bool hasColor; public Color color; } private static bool introPlaying; private static float lastIntroTime = -9999f; private static readonly List watched = new List(); private static bool outroPlaying; private static Type eidType; private static FieldInfo eidDeadField; private static bool eidWarned; private static bool frozeForCard; private static float frozeAt; private static float freezeCheckNext; private static bool earthmoverArmed; private static string earthmoverName; private static Vector3 earthmoverPos; private static bool audioArmed; private static string audioBossName; private static Vector3 audioBossPos; private static string audioClip; private static Canvas introCanvas; private static AudioSource introAudio; private static readonly Dictionary spriteCache = new Dictionary(); private static AudioClip triggerClip; private static AudioClip outroClip; private static MonoBehaviour runner; private static float audioNextScan; private static Type sceneHelperType; private static readonly Dictionary> EncounterMap = BuildEncounterMap(); private static TMP_FontAsset cachedFont; private static readonly Dictionary whiteCache = new Dictionary(); private static MonoBehaviour Runner { get { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)runner == (Object)null) { GameObject val = new GameObject("BossVSIntroRunner"); Object.DontDestroyOnLoad((Object)(object)val); runner = (MonoBehaviour)(object)val.AddComponent(); } return runner; } } public static void EnsureRunner() { MonoBehaviour val = Runner; } [HarmonyPostfix] [HarmonyPatch("Initialize", new Type[] { typeof(BossHealthBar), typeof(SliderLayer[]) })] private static void InitializePostfix(BossHealthBarTemplate __instance, BossHealthBar bossBar, SliderLayer[] colorLayers) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)bossBar == (Object)null) && !string.IsNullOrEmpty(bossBar.bossName)) { EnsureRunner(); Runner.StartCoroutine(WaitForBarThenTrigger(__instance, bossBar, bossBar.bossName)); } } private static IEnumerator WaitForBarThenTrigger(BossHealthBarTemplate template, BossHealthBar bossBar, string bossName) { if ((Object)(object)template == (Object)null) { yield break; } float deadline = Time.unscaledTime + VSConfig.barVisibleTimeout; while (Time.unscaledTime < deadline) { if ((Object)(object)template == (Object)null) { yield break; } if (((Component)template).gameObject.activeInHierarchy) { break; } yield return null; } if ((Object)(object)template == (Object)null || !((Component)template).gameObject.activeInHierarchy) { yield break; } while (outroPlaying) { yield return null; } if (!introPlaying && !(Time.unscaledTime - lastIntroTime < VSConfig.introCooldown)) { Vector3 bossPos = (((Object)(object)bossBar != (Object)null) ? ((Component)bossBar).transform.position : ((Component)template).transform.position); if ((Object)(object)bossBar != (Object)null) { ArmOutroWatch(bossBar, bossName, bossPos); } Runner.StartCoroutine(PlayVSIntro(bossName, bossPos)); } } private static void ArmOutroWatch(BossHealthBar bossBar, string bossName, Vector3 bossPos) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) try { if (Sanitize(bossName) == Sanitize(VSConfig.earthmoverBossName)) { earthmoverArmed = true; earthmoverName = bossName; earthmoverPos = bossPos; if (VSConfig.logOutroWatch) { BossVSIntroPlugin.Log.LogInfo((object)("[OutroWatch] armed '" + bossName + "' (earthmover / style bonus)")); } return; } string text = AudioTriggerClipFor(Sanitize(CurrentLevelName()), Sanitize(bossName)); if (text != null) { audioArmed = true; audioBossName = bossName; audioBossPos = bossPos; audioClip = text; if (VSConfig.logOutroWatch) { BossVSIntroPlugin.Log.LogInfo((object)("[OutroWatch] armed '" + bossName + "' (sound '" + text + "')")); } return; } if (eidType == null) { eidType = AccessTools.TypeByName("EnemyIdentifier"); } if (eidType != null && eidDeadField == null) { eidDeadField = eidType.GetField("dead", BindingFlags.Instance | BindingFlags.Public); } if (eidType == null || eidDeadField == null) { if (!eidWarned) { eidWarned = true; BossVSIntroPlugin.Log.LogWarning((object)"Couldn't find EnemyIdentifier.dead"); } return; } Component val = ((Component)bossBar).GetComponentInParent(eidType); if ((Object)(object)val == (Object)null) { val = ((Component)bossBar).GetComponentInChildren(eidType); } if ((Object)(object)val == (Object)null) { if (VSConfig.logOutroWatch) { BossVSIntroPlugin.Log.LogWarning((object)("[OutroWatch] '" + bossName + "' has NO EnemyIdentifier")); } return; } foreach (WatchedBoss item in watched) { if ((Object)(object)item.eid == (Object)(object)val) { return; } } bool flag = IsObjectDeathBoss(bossName); watched.Add(new WatchedBoss { eid = val, bar = bossBar, bossName = bossName, bossPos = bossPos, level = Sanitize(CurrentLevelName()), objectDeath = flag }); if (VSConfig.logOutroWatch) { BossVSIntroPlugin.Log.LogInfo((object)string.Format("[OutroWatch] armed '{0}' (watched, death signal: {1}). count={2}", bossName, flag ? "bar gone" : "dead flag", watched.Count)); } } catch (Exception ex) { BossVSIntroPlugin.Log.LogError((object)("Outro watch failed to arm: " + ex.Message)); } } private static bool IsObjectDeathBoss(string bossName) { string text = Sanitize(bossName); string[] array = VSConfig.objectDeathBosses.Split(new char[1] { ',' }); foreach (string text2 in array) { if (Sanitize(text2.Trim()) == text) { return true; } } return false; } public static void ClearOutroWatch() { watched.Clear(); earthmoverArmed = false; audioArmed = false; } private static string AudioTriggerClipFor(string levelStem, string bossStem) { string[] array = VSConfig.audioTriggerOutros.Split(new char[1] { ',' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { '|' }); if (array2.Length == 3 && Sanitize(array2[0].Trim()) == levelStem && Sanitize(array2[1].Trim()) == bossStem) { return array2[2].Trim(); } } return null; } public static void CheckAudioTrigger() { //IL_00f6: Unknown result type (might be due to invalid IL or missing references) if (!audioArmed || Time.unscaledTime < audioNextScan) { return; } audioNextScan = Time.unscaledTime + 0.1f; AudioSource[] array = Object.FindObjectsOfType(); AudioSource[] array2 = array; foreach (AudioSource val in array2) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.clip == (Object)null) && val.isPlaying && ((Object)val.clip).name == audioClip) { if (VSConfig.logOutroWatch) { BossVSIntroPlugin.Log.LogInfo((object)("[OutroWatch] '" + audioBossName + "' sound '" + audioClip + "' started -> playing card")); } audioArmed = false; Runner.StartCoroutine(OutroAfterDelay(audioBossName, audioBossPos)); break; } } } public static void OnStyleBonus(string styleName) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (earthmoverArmed && !string.IsNullOrEmpty(styleName) && !(styleName != VSConfig.earthmoverStyleName)) { earthmoverArmed = false; if (VSConfig.logOutroWatch) { BossVSIntroPlugin.Log.LogInfo((object)("[OutroWatch] '" + earthmoverName + "' style bonus -> playing card")); } Runner.StartCoroutine(OutroAfterDelay(earthmoverName, earthmoverPos)); } } public static void CheckOutroWatch() { //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) if (watched.Count == 0) { return; } string text = Sanitize(CurrentLevelName()); for (int num = watched.Count - 1; num >= 0; num--) { WatchedBoss watchedBoss = watched[num]; if (watchedBoss.level != text) { if (VSConfig.logOutroWatch) { BossVSIntroPlugin.Log.LogInfo((object)("[OutroWatch] dropped '" + watchedBoss.bossName + "' (level '" + watchedBoss.level + "' != '" + text + "')")); } watched.RemoveAt(num); continue; } if (watchedBoss.objectDeath) { if ((Object)(object)watchedBoss.bar == (Object)null || !((Component)watchedBoss.bar).gameObject.activeInHierarchy) { if (VSConfig.logOutroWatch) { BossVSIntroPlugin.Log.LogInfo((object)("[OutroWatch] '" + watchedBoss.bossName + "' bar gone -> playing card")); } watched.RemoveAt(num); Runner.StartCoroutine(OutroAfterDelay(watchedBoss.bossName, watchedBoss.bossPos)); } continue; } if ((Object)(object)watchedBoss.eid == (Object)null) { if (VSConfig.logOutroWatch) { BossVSIntroPlugin.Log.LogInfo((object)("[OutroWatch] dropped '" + watchedBoss.bossName + "' (eid null)")); } watched.RemoveAt(num); continue; } bool flag; try { flag = (bool)eidDeadField.GetValue(watchedBoss.eid); } catch (Exception ex) { if (VSConfig.logOutroWatch) { BossVSIntroPlugin.Log.LogWarning((object)("[OutroWatch] '" + watchedBoss.bossName + "' dead-read threw (" + ex.Message + ") — dropped")); } watched.RemoveAt(num); continue; } if (flag) { if (VSConfig.logOutroWatch) { BossVSIntroPlugin.Log.LogInfo((object)("[OutroWatch] '" + watchedBoss.bossName + "' read dead=true -> playing card")); } watched.RemoveAt(num); Runner.StartCoroutine(OutroAfterDelay(watchedBoss.bossName, watchedBoss.bossPos)); } } } private static IEnumerator OutroAfterDelay(string bossName, Vector3 bossPos) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) float t = 0f; while (t < VSConfig.outroTriggerDelay) { t += Time.unscaledDeltaTime; yield return null; } while (introPlaying || outroPlaying) { yield return null; } outroPlaying = true; yield return PlayOutro(bossName, bossPos); } public static void BeginPreloadSounds() { Runner.StartCoroutine(PreloadSounds()); } private static IEnumerator PreloadSounds() { yield return LoadClip(Path.Combine(BossVSIntroPlugin.SoundsRoot, VSConfig.triggerSoundFile), delegate(AudioClip c) { triggerClip = c; }); yield return LoadClip(Path.Combine(BossVSIntroPlugin.SoundsRoot, VSConfig.outroSoundFile), delegate(AudioClip c) { outroClip = c; }); } private static IEnumerator LoadClip(string fullPath, Action onLoaded) { if (!File.Exists(fullPath)) { BossVSIntroPlugin.Log.LogWarning((object)("Sound not found (splash will be silent for this one): " + fullPath)); onLoaded(null); yield break; } AudioType type = GuessAudioType(fullPath); UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip("file://" + fullPath, type); try { yield return req.SendWebRequest(); if ((int)req.result != 1) { BossVSIntroPlugin.Log.LogError((object)("Failed to load sound '" + fullPath + "': " + req.error)); onLoaded(null); yield break; } onLoaded(DownloadHandlerAudioClip.GetContent(req)); } finally { ((IDisposable)req)?.Dispose(); } } private static AudioType GuessAudioType(string path) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) string text = Path.GetExtension(path).ToLowerInvariant(); string text2 = text; if (!(text2 == ".ogg")) { if (text2 == ".mp3") { return (AudioType)13; } return (AudioType)20; } return (AudioType)14; } private static void PlaySound(AudioClip clip) { if (!((Object)(object)clip == (Object)null) && !((Object)(object)introAudio == (Object)null)) { introAudio.PlayOneShot(clip, VSConfig.soundVolume); } } private static string Sanitize(string name) { StringBuilder stringBuilder = new StringBuilder(); string text = name.ToUpperInvariant(); foreach (char c in text) { if (char.IsLetterOrDigit(c)) { stringBuilder.Append(c); } else if (c == ' ' || c == '-' || c == '_') { stringBuilder.Append('_'); } } return stringBuilder.ToString(); } public static string CurrentLevelName() { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) try { if (sceneHelperType == null) { sceneHelperType = AccessTools.TypeByName("SceneHelper"); } if (sceneHelperType != null) { PropertyInfo property = sceneHelperType.GetProperty("CurrentScene", BindingFlags.Static | BindingFlags.Public); if (property != null && property.GetValue(null) is string text && !string.IsNullOrEmpty(text)) { return text; } FieldInfo field = sceneHelperType.GetField("CurrentScene", BindingFlags.Static | BindingFlags.Public); if (field != null && field.GetValue(null) is string text2 && !string.IsNullOrEmpty(text2)) { return text2; } } } catch { } Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).name; } private static Sprite ResolveBackgroundSprite(string sideFolder, string bossName, Vector3 bossPos) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) string text = Sanitize(bossName); string text2 = Sanitize(CurrentLevelName()); string path = Path.Combine(BossVSIntroPlugin.ImagesRoot, VSConfig.backgroundFolderName, sideFolder); int num = EncounterIndex(text2, text, bossPos); List list = new List(); if (num >= 2) { list.Add(Path.Combine(path, text2, $"{text}_{num}.png")); list.Add(Path.Combine(path, $"{text}_{num}.png")); } list.Add(Path.Combine(path, text2, text + ".png")); list.Add(Path.Combine(path, text + ".png")); list.Add(Path.Combine(path, text2 + ".png")); list.Add(Path.Combine(path, text2, VSConfig.backgroundFallbackName)); list.Add(Path.Combine(path, VSConfig.backgroundFallbackName)); foreach (string item in list) { Sprite val = LoadSprite(item); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static Sprite ResolveBossSprite(string bossName, Vector3 bossPos) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) string text = Sanitize(bossName); string text2 = Sanitize(CurrentLevelName()); string path = Path.Combine(BossVSIntroPlugin.ImagesRoot, VSConfig.bossFolderName); int num = EncounterIndex(text2, text, bossPos); List list = new List(); if (num >= 2) { list.Add(Path.Combine(path, text2, $"{text}_{num}.png")); list.Add(Path.Combine(path, $"{text}_{num}.png")); } list.Add(Path.Combine(path, text2, text + ".png")); list.Add(Path.Combine(path, text + ".png")); list.Add(Path.Combine(path, text2, VSConfig.bossFallbackName)); list.Add(Path.Combine(path, VSConfig.bossFallbackName)); foreach (string item in list) { Sprite val = LoadSprite(item); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static Dictionary> BuildEncounterMap() { Dictionary> dictionary = new Dictionary>(); Add(dictionary, "LEVEL_0_5", "CERBERUS_GUARDIAN_OF_HELL", 1, 207.5f, -6.5f, 394.5f); Add(dictionary, "LEVEL_0_5", "CERBERUS_GUARDIAN_OF_HELL", 2, 207.5f, -6.5f, 369.5f); Add(dictionary, "LEVEL_1_E", "HIDEOUS_MASS", 1, 280.25f, 1.5f, 450.75f); Add(dictionary, "LEVEL_1_E", "HIDEOUS_MASS", 2, 346f, 31f, 568f); Add(dictionary, "LEVEL_4_4", "V2", 1, 117.5f, 661f, 263f); Add(dictionary, "LEVEL_4_4", "V2", 2, 200f, 610.5f, 1150f); Add(dictionary, "LEVEL_7_1", "SMINOTAUR", 1, -242.5f, -1f, 60.25f); Add(dictionary, "LEVEL_7_1", "SMINOTAUR", 2, -225.5f, 95f, -414.75f); return dictionary; } private static void Add(Dictionary> m, string level, string boss, int idx, float x, float y, float z) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) string key = level + "|" + boss; if (!m.TryGetValue(key, out var value)) { value = (m[key] = new List<(int, Vector3)>()); } value.Add((idx, new Vector3(x, y, z))); } private static int EncounterIndex(string levelStem, string bossStem, Vector3 pos) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) string key = levelStem + "|" + bossStem; if (!EncounterMap.TryGetValue(key, out List<(int, Vector3)> value)) { return 1; } int num = -1; float num2 = float.MaxValue; foreach (var item in value) { float num3 = Vector3.Distance(pos, item.Item2); if (num3 < num2) { num2 = num3; (num, _) = item; } } return (num <= 0 || !(num2 <= VSConfig.positionTolerance)) ? 1 : num; } private static Sprite LoadSprite(string fullPath) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) if (spriteCache.TryGetValue(fullPath, out var value)) { return value; } if (!File.Exists(fullPath)) { return null; } try { byte[] array = File.ReadAllBytes(fullPath); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ImageConversion.LoadImage(val, array); ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); spriteCache[fullPath] = val2; return val2; } catch (Exception ex) { BossVSIntroPlugin.Log.LogError((object)("Failed to load image '" + fullPath + "': " + ex.Message)); return null; } } private static Canvas GetOrCreateCanvas() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown if ((Object)(object)introCanvas != (Object)null) { return introCanvas; } GameObject val = new GameObject("BossVSIntroCanvas"); Object.DontDestroyOnLoad((Object)(object)val); introCanvas = val.AddComponent(); introCanvas.renderMode = (RenderMode)0; introCanvas.sortingOrder = 32767; CanvasScaler val2 = val.AddComponent(); val2.uiScaleMode = (ScaleMode)0; val2.scaleFactor = 1f; val.AddComponent(); introAudio = val.AddComponent(); introAudio.playOnAwake = false; introAudio.spatialBlend = 0f; introAudio.ignoreListenerPause = true; return introCanvas; } private static string LoadText(string fullPath) { try { if (!File.Exists(fullPath)) { return null; } string text = File.ReadAllText(fullPath).Trim(); return (text.Length == 0) ? null : text; } catch (Exception ex) { BossVSIntroPlugin.Log.LogError((object)("Failed to read text '" + fullPath + "': " + ex.Message)); return null; } } private static TextSpec ResolvePlayerText() { return ParseTextFile(Path.Combine(BossVSIntroPlugin.TextRoot, VSConfig.playerTextFileName)); } private static TextSpec ResolveEnemyText(string bossName, Vector3 bossPos) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) string text = Sanitize(bossName); string text2 = Sanitize(CurrentLevelName()); string textRoot = BossVSIntroPlugin.TextRoot; int num = EncounterIndex(text2, text, bossPos); List list = new List(); if (num >= 2) { list.Add(Path.Combine(textRoot, text2, $"{text}_{num}.txt")); list.Add(Path.Combine(textRoot, $"{text}_{num}.txt")); } list.Add(Path.Combine(textRoot, text2, text + ".txt")); list.Add(Path.Combine(textRoot, text + ".txt")); list.Add(Path.Combine(textRoot, text2, VSConfig.textFallbackName)); list.Add(Path.Combine(textRoot, VSConfig.textFallbackName)); foreach (string item in list) { TextSpec textSpec = ParseTextFile(item); if (textSpec != null) { return textSpec; } } return null; } private static TextSpec ParseTextFile(string fullPath) { //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) string text = LoadText(fullPath); if (text == null) { return null; } TextSpec textSpec = new TextSpec(); string[] array = text.Split(new char[1] { '\n' }); foreach (string text2 in array) { string text3 = text2.Trim(); int num = text3.IndexOf(':'); if (num < 0) { continue; } string text4 = text3.Substring(0, num).Trim().ToLowerInvariant(); string text5 = text3.Substring(num + 1).Trim().Trim(new char[1] { '"' }); switch (text4) { case "title": textSpec.title = text5; break; case "position": { if (TryVec2(text5, out var v)) { textSpec.pos = v; textSpec.hasPos = true; } break; } case "font size": case "fontsize": case "size": { if (float.TryParse(text5, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { textSpec.size = result; textSpec.hasSize = true; } break; } case "color": case "colour": { if (TryColor(text5, out var c)) { textSpec.color = c; textSpec.hasColor = true; } break; } } } return string.IsNullOrEmpty(textSpec.title) ? null : textSpec; } private static bool TryVec2(string s, out Vector2 v) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) v = Vector2.zero; string[] array = s.Split(new char[1] { ',' }); if (array.Length < 2) { return false; } if (float.TryParse(array[0].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { v = new Vector2(result, result2); return true; } return false; } private static bool TryColor(string s, out Color c) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) c = Color.white; string[] array = s.Split(new char[1] { ',' }); if (array.Length < 3) { return false; } if (!byte.TryParse(array[0].Trim(), out var result) || !byte.TryParse(array[1].Trim(), out var result2) || !byte.TryParse(array[2].Trim(), out var result3)) { return false; } byte result4 = byte.MaxValue; if (array.Length >= 4) { byte.TryParse(array[3].Trim(), out result4); } c = Color32.op_Implicit(new Color32(result, result2, result3, result4)); return true; } private static TMP_FontAsset GetFont() { if ((Object)(object)cachedFont != (Object)null) { return cachedFont; } TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll(); if (array != null) { TMP_FontAsset[] array2 = array; foreach (TMP_FontAsset val in array2) { if ((Object)(object)val != (Object)null && ((Object)val).name.IndexOf("VCR", StringComparison.OrdinalIgnoreCase) >= 0) { return cachedFont = val; } } } if ((Object)(object)TMP_Settings.defaultFontAsset != (Object)null) { return cachedFont = TMP_Settings.defaultFontAsset; } if (array != null && array.Length != 0) { cachedFont = array[0]; } return cachedFont; } private static TextMeshProUGUI MakeText(Transform parent, string content, string name, float fontSize, Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); TextMeshProUGUI val2 = val.AddComponent(); TMP_FontAsset font = GetFont(); if ((Object)(object)font != (Object)null) { ((TMP_Text)val2).font = font; } ((TMP_Text)val2).text = content; ((TMP_Text)val2).fontSize = fontSize; ((TMP_Text)val2).fontStyle = (FontStyles)1; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).enableWordWrapping = false; ((TMP_Text)val2).overflowMode = (TextOverflowModes)0; ((Graphic)val2).color = color; ((Graphic)val2).raycastTarget = false; if (VSConfig.textOutlineWidth > 0f) { Material fontMaterial = ((TMP_Text)val2).fontMaterial; fontMaterial.SetColor(ShaderUtilities.ID_OutlineColor, Color.black); fontMaterial.SetFloat(ShaderUtilities.ID_OutlineWidth, VSConfig.textOutlineWidth); } RectTransform rectTransform = ((TMP_Text)val2).rectTransform; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 0.5f); rectTransform.pivot = val3; Vector2 anchorMin = (rectTransform.anchorMax = val3); rectTransform.anchorMin = anchorMin; rectTransform.sizeDelta = new Vector2(fontSize * 12f, fontSize * 2f); return val2; } private static Sprite WhiteSilhouette(Sprite src) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)src == (Object)null) { return null; } if (whiteCache.TryGetValue(src, out var value)) { return value; } Texture2D texture = src.texture; Color32[] pixels = texture.GetPixels32(); for (int i = 0; i < pixels.Length; i++) { pixels[i] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, pixels[i].a); } Texture2D val = new Texture2D(((Texture)texture).width, ((Texture)texture).height, (TextureFormat)4, false); val.SetPixels32(pixels); val.Apply(); ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); whiteCache[src] = val2; return val2; } private static Image MakeFlash(Image fighter, Sprite fighterSprite) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("VS_Flash"); val.transform.SetParent(((Component)fighter).transform, false); Image val2 = val.AddComponent(); val2.sprite = WhiteSilhouette(fighterSprite); ((Graphic)val2).raycastTarget = false; val2.preserveAspect = true; RectTransform rectTransform = ((Graphic)val2).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; Vector2 offsetMin = (rectTransform.offsetMax = Vector2.zero); rectTransform.offsetMin = offsetMin; SetFlashAlpha(val2, 0f); return val2; } private static void SetFlashAlpha(Image flash, float a) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)flash == (Object)null)) { ((Graphic)flash).color = new Color(1f, 1f, 1f, a); } } private static Sprite ResolveIconSprite(string bossName, Vector3 bossPos) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) string text = Sanitize(bossName); string text2 = Sanitize(CurrentLevelName()); string path = Path.Combine(BossVSIntroPlugin.ImagesRoot, VSConfig.iconFolderName); int num = EncounterIndex(text2, text, bossPos); List list = new List(); if (num >= 2) { list.Add(Path.Combine(path, text2, $"{text}_{num}.png")); list.Add(Path.Combine(path, $"{text}_{num}.png")); } list.Add(Path.Combine(path, text2, text + ".png")); list.Add(Path.Combine(path, text + ".png")); list.Add(Path.Combine(path, text2, VSConfig.bossFallbackName)); list.Add(Path.Combine(path, VSConfig.bossFallbackName)); foreach (string item in list) { Sprite val = LoadSprite(item); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static Vector2 ShakeOffset(float since) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (since < 0f || since >= VSConfig.shakeDuration) { return Vector2.zero; } float num = VSConfig.shakeAmplitude * (1f - since / VSConfig.shakeDuration); return new Vector2(Random.Range(0f - num, num), Random.Range(0f - num, num)); } private static IEnumerator PlayOutro(string bossName, Vector3 bossPos) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) outroPlaying = true; Sprite iconSprite = ResolveIconSprite(bossName, bossPos); Sprite crossSprite = LoadSprite(Path.Combine(BossVSIntroPlugin.ImagesRoot, VSConfig.crossOutFileName)); TextSpec bossSpec = ResolveEnemyText(bossName, bossPos); TextSpec ultraSpec = ParseTextFile(Path.Combine(BossVSIntroPlugin.TextRoot, VSConfig.ultrakilledTextFileName)); if ((Object)(object)iconSprite == (Object)null) { BossVSIntroPlugin.Log.LogWarning((object)("Missing icon for '" + bossName + "' in Images/" + VSConfig.iconFolderName + "/ — kill card skipped.")); } if ((Object)(object)crossSprite == (Object)null) { BossVSIntroPlugin.Log.LogWarning((object)("Missing Images/" + VSConfig.crossOutFileName + " — kill card skipped.")); } if ((Object)(object)iconSprite == (Object)null || (Object)(object)crossSprite == (Object)null) { outroPlaying = false; yield break; } float previousTimeScale = Time.timeScale; Time.timeScale = 0f; frozeForCard = true; frozeAt = Time.unscaledTime; Image iconImg = null; Image crossImg = null; TextMeshProUGUI bossTxt = null; TextMeshProUGUI ultraTxt = null; IEnumerator anim = AnimateOutro(iconSprite, crossSprite, bossSpec, ultraSpec, delegate(Image i) { iconImg = i; }, delegate(Image i) { crossImg = i; }, delegate(TextMeshProUGUI tx) { bossTxt = tx; }, delegate(TextMeshProUGUI tx) { ultraTxt = tx; }); while (true) { Time.timeScale = 0f; object current; try { if (!anim.MoveNext()) { break; } current = anim.Current; goto IL_025f; } catch (Exception ex) { Exception e = ex; BossVSIntroPlugin.Log.LogError((object)$"Kill card threw, bailing safely: {e}"); } break; IL_025f: yield return current; } if ((Object)(object)iconImg != (Object)null) { Object.Destroy((Object)(object)((Component)iconImg).gameObject); } if ((Object)(object)crossImg != (Object)null) { Object.Destroy((Object)(object)((Component)crossImg).gameObject); } if ((Object)(object)bossTxt != (Object)null) { Object.Destroy((Object)(object)((Component)bossTxt).gameObject); } if ((Object)(object)ultraTxt != (Object)null) { Object.Destroy((Object)(object)((Component)ultraTxt).gameObject); } Time.timeScale = previousTimeScale; frozeForCard = false; outroPlaying = false; } private static IEnumerator AnimateOutro(Sprite iconSprite, Sprite crossSprite, TextSpec bossSpec, TextSpec ultraSpec, Action outIcon, Action outCross, Action outBossTxt, Action outUltraTxt) { Canvas canvas = GetOrCreateCanvas(); float screenH = Screen.height; float resScale = screenH / 1080f; PlaySound(outroClip); Image iconImg = MakeImage(((Component)canvas).transform, iconSprite, "VS_OutroIcon", screenH * VSConfig.iconHeightFraction); Image crossImg = MakeImage(((Component)canvas).transform, crossSprite, "VS_OutroCross", screenH * VSConfig.crossOutHeightFraction); outIcon(iconImg); outCross(crossImg); ((Transform)((Graphic)crossImg).rectTransform).SetAsLastSibling(); RectTransform iconRT = ((Graphic)iconImg).rectTransform; RectTransform crossRT = ((Graphic)crossImg).rectTransform; float bossSize = ((bossSpec != null && bossSpec.hasSize) ? bossSpec.size : VSConfig.textFontSize) * resScale; Vector2 bossTxtPos = new Vector2(VSConfig.outroBossTextX, VSConfig.outroBossTextY) * resScale; TextMeshProUGUI bossTxt = null; RectTransform bossTxtRT = null; if (bossSpec != null) { bossTxt = MakeText(color: bossSpec.hasColor ? bossSpec.color : Color.white, parent: ((Component)canvas).transform, content: bossSpec.title, name: "VS_OutroBossText", fontSize: bossSize); bossTxtRT = ((TMP_Text)bossTxt).rectTransform; bossTxtRT.anchoredPosition = bossTxtPos; ((Component)bossTxt).gameObject.SetActive(false); outBossTxt(bossTxt); } string ultraTitle = ((ultraSpec != null && !string.IsNullOrEmpty(ultraSpec.title)) ? ultraSpec.title : "ULTRAKILLED"); float ultraSize = ((ultraSpec != null && ultraSpec.hasSize) ? ultraSpec.size : VSConfig.textFontSize) * resScale; Color ultraCol = ((ultraSpec != null && ultraSpec.hasColor) ? ultraSpec.color : Color.white); Vector2 ultraPos = ((ultraSpec != null && ultraSpec.hasPos) ? (ultraSpec.pos * resScale) : (bossTxtPos + new Vector2(0f, 0f - bossSize * 1.25f))); TextMeshProUGUI ultraTxt = MakeText(((Component)canvas).transform, ultraTitle, "VS_OutroKilledText", ultraSize, ultraCol); RectTransform ultraTxtRT = ((TMP_Text)ultraTxt).rectTransform; ultraTxtRT.anchoredPosition = ultraPos; ((Component)ultraTxt).gameObject.SetActive(false); outUltraTxt(ultraTxt); Vector2 iconBase = Vector2.zero; Vector2 crossBase = Vector2.zero; iconRT.anchoredPosition = iconBase; crossRT.anchoredPosition = crossBase; ((Transform)iconRT).localScale = Vector3.one * VSConfig.vsStartScale; ((Transform)crossRT).localScale = Vector3.one * VSConfig.vsStartScale; ((Component)crossImg).gameObject.SetActive(false); float t1 = VSConfig.vsPopDuration; float t2 = t1 + VSConfig.outroCrossDelay; float t3 = t2 + VSConfig.vsPopDuration; float t4 = t3 + VSConfig.shakeDuration; float t5 = t4 + VSConfig.outroHoldDuration; float tEnd = t5 + VSConfig.slideOutDuration; bool crossShown = false; bool bossShown = false; bool ultraShown = false; float T = 0f; while (T < tEnd) { T += Time.unscaledDeltaTime; float ki = EaseOutCubic(Mathf.Clamp01(T / VSConfig.vsPopDuration)); ((Transform)iconRT).localScale = Vector3.one * Mathf.LerpUnclamped(VSConfig.vsStartScale, 1f, ki); if (!bossShown && T >= t1 && (Object)(object)bossTxt != (Object)null) { ((Component)bossTxt).gameObject.SetActive(true); bossShown = true; } if (T >= t2) { if (!crossShown) { ((Component)crossImg).gameObject.SetActive(true); crossShown = true; } float kc = EaseOutCubic(Mathf.Clamp01((T - t2) / VSConfig.vsPopDuration)); ((Transform)crossRT).localScale = Vector3.one * Mathf.LerpUnclamped(VSConfig.vsStartScale, 1f, kc); } if (!ultraShown && T >= t3) { ((Component)ultraTxt).gameObject.SetActive(true); ultraShown = true; } Vector2 off = ShakeOffset(T - t1) + ShakeOffset(T - t3); if (T >= t5) { float ko = EaseInCubic(Mathf.Clamp01((T - t5) / VSConfig.slideOutDuration)); off += new Vector2(0f, screenH * 1.2f * ko); } iconRT.anchoredPosition = iconBase + off; crossRT.anchoredPosition = crossBase + off; if ((Object)(object)bossTxtRT != (Object)null) { bossTxtRT.anchoredPosition = bossTxtPos + off; } ultraTxtRT.anchoredPosition = ultraPos + off; yield return null; } } private static Image MakeImage(Transform parent, Sprite sprite, string name, float targetHeight) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); Image val2 = val.AddComponent(); val2.sprite = sprite; ((Graphic)val2).raycastTarget = false; val2.preserveAspect = true; RectTransform rectTransform = ((Graphic)val2).rectTransform; rectTransform.anchorMin = new Vector2(0.5f, 0.5f); rectTransform.anchorMax = new Vector2(0.5f, 0.5f); rectTransform.pivot = new Vector2(0.5f, 0.5f); float num = (float)((Texture)sprite.texture).width / (float)((Texture)sprite.texture).height; rectTransform.sizeDelta = new Vector2(targetHeight * num, targetHeight); rectTransform.anchoredPosition = Vector2.zero; ((Transform)rectTransform).localScale = Vector3.one; return val2; } private static float EaseOutCubic(float x) { return 1f - Mathf.Pow(1f - x, 3f); } private static float EaseInCubic(float x) { return x * x * x; } private static IEnumerator PlayVSIntro(string bossName, Vector3 bossPos) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) introPlaying = true; string playerPath = Path.Combine(BossVSIntroPlugin.ImagesRoot, VSConfig.playerFileName); string vsPath = Path.Combine(BossVSIntroPlugin.ImagesRoot, VSConfig.vsFileName); Sprite playerSprite = LoadSprite(playerPath); Sprite vsSprite = LoadSprite(vsPath); Sprite bossSprite = ResolveBossSprite(bossName, bossPos); Sprite playerBgSprite = ResolveBackgroundSprite(VSConfig.backgroundPlayerFolder, bossName, bossPos); Sprite enemyBgSprite = ResolveBackgroundSprite(VSConfig.backgroundBossesFolder, bossName, bossPos); TextSpec playerText = ResolvePlayerText(); TextSpec enemyText = ResolveEnemyText(bossName, bossPos); if ((Object)(object)playerSprite == (Object)null) { BossVSIntroPlugin.Log.LogWarning((object)("Missing player image: " + playerPath)); } if ((Object)(object)vsSprite == (Object)null) { BossVSIntroPlugin.Log.LogWarning((object)("Missing VS image: " + vsPath)); } if ((Object)(object)bossSprite == (Object)null) { BossVSIntroPlugin.Log.LogWarning((object)("Missing boss image for '" + bossName + "' (no level override, no generic, no Default.png).")); } if ((Object)(object)playerSprite == (Object)null || (Object)(object)vsSprite == (Object)null || (Object)(object)bossSprite == (Object)null) { introPlaying = false; yield break; } lastIntroTime = Time.unscaledTime; float previousTimeScale = Time.timeScale; Time.timeScale = 0f; frozeForCard = true; frozeAt = Time.unscaledTime; Image playerImg = null; Image bossImg = null; Image vsImg = null; Image playerBgImg = null; Image enemyBgImg = null; TextMeshProUGUI playerTxt = null; TextMeshProUGUI enemyTxt = null; IEnumerator anim = AnimateCard(playerSprite, bossSprite, vsSprite, playerBgSprite, enemyBgSprite, playerText, enemyText, delegate(Image img) { playerImg = img; }, delegate(Image img) { bossImg = img; }, delegate(Image img) { vsImg = img; }, delegate(Image img) { playerBgImg = img; }, delegate(Image img) { enemyBgImg = img; }, delegate(TextMeshProUGUI t) { playerTxt = t; }, delegate(TextMeshProUGUI t) { enemyTxt = t; }); while (true) { Time.timeScale = 0f; object current; try { if (!anim.MoveNext()) { break; } current = anim.Current; goto IL_0345; } catch (Exception ex) { Exception e = ex; BossVSIntroPlugin.Log.LogError((object)$"Boss VS Intro splash threw, bailing safely: {e}"); } break; IL_0345: yield return current; } if ((Object)(object)playerImg != (Object)null) { Object.Destroy((Object)(object)((Component)playerImg).gameObject); } if ((Object)(object)bossImg != (Object)null) { Object.Destroy((Object)(object)((Component)bossImg).gameObject); } if ((Object)(object)vsImg != (Object)null) { Object.Destroy((Object)(object)((Component)vsImg).gameObject); } if ((Object)(object)playerBgImg != (Object)null) { Object.Destroy((Object)(object)((Component)playerBgImg).gameObject); } if ((Object)(object)enemyBgImg != (Object)null) { Object.Destroy((Object)(object)((Component)enemyBgImg).gameObject); } if ((Object)(object)playerTxt != (Object)null) { Object.Destroy((Object)(object)((Component)playerTxt).gameObject); } if ((Object)(object)enemyTxt != (Object)null) { Object.Destroy((Object)(object)((Component)enemyTxt).gameObject); } Time.timeScale = previousTimeScale; frozeForCard = false; introPlaying = false; } private static IEnumerator AnimateCard(Sprite playerSprite, Sprite bossSprite, Sprite vsSprite, Sprite playerBgSprite, Sprite enemyBgSprite, TextSpec playerText, TextSpec enemyText, Action outPlayer, Action outBoss, Action outVs, Action outPlayerBg, Action outEnemyBg, Action outPlayerTxt, Action outEnemyTxt) { Canvas canvas = GetOrCreateCanvas(); PlaySound(triggerClip); float screenW = Screen.width; float screenH = Screen.height; Image playerImg = MakeImage(((Component)canvas).transform, playerSprite, "VS_Player", screenH); Image bossImg = MakeImage(((Component)canvas).transform, bossSprite, "VS_Boss", screenH); Image vsImg = MakeImage(((Component)canvas).transform, vsSprite, "VS_Badge", screenH * VSConfig.vsHeightFraction); ((Graphic)playerImg).color = Color.black; ((Graphic)bossImg).color = Color.black; Image playerFlash = MakeFlash(playerImg, playerSprite); Image bossFlash = MakeFlash(bossImg, bossSprite); outPlayer(playerImg); outBoss(bossImg); outVs(vsImg); RectTransform playerRT = ((Graphic)playerImg).rectTransform; RectTransform bossRT = ((Graphic)bossImg).rectTransform; RectTransform vsRT = ((Graphic)vsImg).rectTransform; float resScale = screenH / 1080f; float halfGap = VSConfig.centerGap * resScale * 0.5f; float playerHalfW = playerRT.sizeDelta.x * 0.5f; float bossHalfW = bossRT.sizeDelta.x * 0.5f; Vector2 playerStart = new Vector2(0f - screenW, 0f); Vector2 bossStart = new Vector2(screenW, 0f); Vector2 playerEnd = new Vector2(0f - (playerHalfW + halfGap), 0f); Vector2 bossEnd = new Vector2(bossHalfW + halfGap, 0f); playerRT.anchoredPosition = playerStart; bossRT.anchoredPosition = bossStart; vsRT.anchoredPosition = Vector2.zero; ((Transform)playerRT).SetAsLastSibling(); ((Transform)bossRT).SetAsLastSibling(); ((Transform)vsRT).SetAsLastSibling(); if ((Object)(object)playerBgSprite != (Object)null) { Image pbg = MakeImage(((Component)canvas).transform, playerBgSprite, "VS_PlayerBg", screenH); ((Graphic)pbg).rectTransform.anchoredPosition = playerStart; ((Transform)((Graphic)pbg).rectTransform).SetAsFirstSibling(); ((Component)pbg).gameObject.AddComponent().target = playerRT; outPlayerBg(pbg); } if ((Object)(object)enemyBgSprite != (Object)null) { Image ebg = MakeImage(((Component)canvas).transform, enemyBgSprite, "VS_EnemyBg", screenH); ((Graphic)ebg).rectTransform.anchoredPosition = bossStart; ((Transform)((Graphic)ebg).rectTransform).SetAsFirstSibling(); ((Component)ebg).gameObject.AddComponent().target = bossRT; outEnemyBg(ebg); } ((Component)vsImg).gameObject.SetActive(false); float resScaleTxt = screenH / 1080f; float textY = screenH * VSConfig.textYFraction; RectTransform playerTxtRT = null; RectTransform enemyTxtRT = null; Vector2 playerTxtStart = Vector2.zero; Vector2 playerTxtEnd = Vector2.zero; Vector2 enemyTxtStart = Vector2.zero; Vector2 enemyTxtEnd = Vector2.zero; if (playerText != null) { float size = (playerText.hasSize ? playerText.size : VSConfig.textFontSize) * resScaleTxt; Color col = (playerText.hasColor ? playerText.color : Color.white); playerTxtEnd = (Vector2)(playerText.hasPos ? (playerText.pos * resScaleTxt) : new Vector2(playerEnd.x, textY)); playerTxtStart = new Vector2(0f - screenW, playerTxtEnd.y); TextMeshProUGUI t2 = MakeText(((Component)canvas).transform, playerText.title, "VS_PlayerText", size, col); ((TMP_Text)t2).rectTransform.anchoredPosition = playerTxtStart; playerTxtRT = ((TMP_Text)t2).rectTransform; outPlayerTxt(t2); } if (enemyText != null) { float size2 = (enemyText.hasSize ? enemyText.size : VSConfig.textFontSize) * resScaleTxt; Color col2 = (enemyText.hasColor ? enemyText.color : Color.white); enemyTxtEnd = (Vector2)(enemyText.hasPos ? (enemyText.pos * resScaleTxt) : new Vector2(bossEnd.x, textY)); enemyTxtStart = new Vector2(screenW, enemyTxtEnd.y); TextMeshProUGUI t3 = MakeText(((Component)canvas).transform, enemyText.title, "VS_EnemyText", size2, col2); ((TMP_Text)t3).rectTransform.anchoredPosition = enemyTxtStart; enemyTxtRT = ((TMP_Text)t3).rectTransform; outEnemyTxt(t3); } float t4 = 0f; while (t4 < VSConfig.slideInDuration) { t4 += Time.unscaledDeltaTime; float k = EaseOutCubic(Mathf.Clamp01(t4 / VSConfig.slideInDuration)); playerRT.anchoredPosition = Vector2.LerpUnclamped(playerStart, playerEnd, k); bossRT.anchoredPosition = Vector2.LerpUnclamped(bossStart, bossEnd, k); yield return null; } playerRT.anchoredPosition = playerEnd; bossRT.anchoredPosition = bossEnd; t4 = 0f; while (t4 < VSConfig.vsDelay) { t4 += Time.unscaledDeltaTime; yield return null; } ((Component)vsImg).gameObject.SetActive(true); float popDuration = Mathf.Max(VSConfig.vsPopDuration, VSConfig.textSlideDuration); t4 = 0f; while (t4 < popDuration) { t4 += Time.unscaledDeltaTime; float kv = EaseOutCubic(Mathf.Clamp01(t4 / VSConfig.vsPopDuration)); ((Transform)vsRT).localScale = Vector3.one * Mathf.LerpUnclamped(VSConfig.vsStartScale, 1f, kv); float kt = EaseOutCubic(Mathf.Clamp01(t4 / VSConfig.textSlideDuration)); if ((Object)(object)playerTxtRT != (Object)null) { playerTxtRT.anchoredPosition = Vector2.LerpUnclamped(playerTxtStart, playerTxtEnd, kt); } if ((Object)(object)enemyTxtRT != (Object)null) { enemyTxtRT.anchoredPosition = Vector2.LerpUnclamped(enemyTxtStart, enemyTxtEnd, kt); } yield return null; } ((Transform)vsRT).localScale = Vector3.one; if ((Object)(object)playerTxtRT != (Object)null) { playerTxtRT.anchoredPosition = playerTxtEnd; } if ((Object)(object)enemyTxtRT != (Object)null) { enemyTxtRT.anchoredPosition = enemyTxtEnd; } ((Graphic)playerImg).color = Color.white; ((Graphic)bossImg).color = Color.white; SetFlashAlpha(playerFlash, 1f); SetFlashAlpha(bossFlash, 1f); t4 = 0f; while (t4 < VSConfig.shakeDuration) { t4 += Time.unscaledDeltaTime; float decay = 1f - Mathf.Clamp01(t4 / VSConfig.shakeDuration); float amp = VSConfig.shakeAmplitude * decay; playerRT.anchoredPosition = playerEnd + new Vector2(Random.Range(0f - amp, amp), Random.Range(0f - amp, amp)); bossRT.anchoredPosition = bossEnd + new Vector2(Random.Range(0f - amp, amp), Random.Range(0f - amp, amp)); float flash = 1f - Mathf.Clamp01(t4 / VSConfig.colorFadeDuration); SetFlashAlpha(playerFlash, flash); SetFlashAlpha(bossFlash, flash); yield return null; } playerRT.anchoredPosition = playerEnd; bossRT.anchoredPosition = bossEnd; SetFlashAlpha(playerFlash, 0f); SetFlashAlpha(bossFlash, 0f); t4 = 0f; while (t4 < VSConfig.holdDuration) { t4 += Time.unscaledDeltaTime; yield return null; } Vector2 vsUpEnd = new Vector2(0f, screenH); t4 = 0f; while (t4 < VSConfig.slideOutDuration) { t4 += Time.unscaledDeltaTime; float k2 = EaseInCubic(Mathf.Clamp01(t4 / VSConfig.slideOutDuration)); playerRT.anchoredPosition = Vector2.LerpUnclamped(playerEnd, playerStart, k2); bossRT.anchoredPosition = Vector2.LerpUnclamped(bossEnd, bossStart, k2); vsRT.anchoredPosition = Vector2.LerpUnclamped(Vector2.zero, vsUpEnd, k2); if ((Object)(object)playerTxtRT != (Object)null) { playerTxtRT.anchoredPosition = Vector2.LerpUnclamped(playerTxtEnd, playerTxtStart, k2); } if ((Object)(object)enemyTxtRT != (Object)null) { enemyTxtRT.anchoredPosition = Vector2.LerpUnclamped(enemyTxtEnd, enemyTxtStart, k2); } yield return null; } } } [HarmonyPatch(typeof(AddStylePoints), "Activate")] public class EarthmoverStylePatch { private static void Postfix(AddStylePoints __instance) { if (!((Object)(object)__instance == (Object)null)) { BossVSIntroPatch.OnStyleBonus(__instance.styleName); } } } }