using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using OpenShot.Core; using OpenShot.UI; using Shooterlatro.DebugTools; using Shooterlatro.Game; using Shooterlatro.Gameplay.RunSetup; using Shooterlatro.Score; using Shooterlatro.Shop; using Shooterlatro.Upgrades; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("LuckyTest")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Sandbox build tester for Lucky Shot. Pick holos/bullets/charms/drinks, then jump into endless. Configure via OpenShot MODS hub.")] [assembly: AssemblyFileVersion("1.1.3.0")] [assembly: AssemblyInformationalVersion("1.1.3+4135dd1490a61fe647f2a0e54287f36471f5cf7f")] [assembly: AssemblyProduct("LuckyTest")] [assembly: AssemblyTitle("LuckyTest")] [assembly: AssemblyVersion("1.1.3.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 LuckyTest { internal sealed class CatalogEntry { public string Id; public string Label; public Object Asset; } internal static class CatalogCache { public static List Holos { get; private set; } = new List(); public static List Bullets { get; private set; } = new List(); public static List Charms { get; private set; } = new List(); public static List Drinks { get; private set; } = new List(); public static void Refresh() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0020: Expected O, but got Unknown UnityDeveloperConsoleRuntime val = new UnityDeveloperConsoleRuntime(); Holos = BuildHolos(val); Bullets = BuildBullets(val); Charms = BuildCharms(val); Drinks = BuildDrinks(); } private static List BuildHolos(UnityDeveloperConsoleRuntime runtime) { List list = new List(); HashSet seen = new HashSet(StringComparer.OrdinalIgnoreCase); IReadOnlyList readOnlyList = null; try { readOnlyList = runtime.GetHolos(); } catch { } if (readOnlyList != null) { foreach (HoloItemData item in readOnlyList) { TryAddHolo(list, seen, runtime, item); } } HoloItemData[] array = Resources.FindObjectsOfTypeAll(); foreach (HoloItemData holo in array) { TryAddHolo(list, seen, runtime, holo); } return list.OrderBy((CatalogEntry e) => e.Id, StringComparer.OrdinalIgnoreCase).ToList(); } private static void TryAddHolo(List list, HashSet seen, UnityDeveloperConsoleRuntime runtime, HoloItemData holo) { if ((Object)(object)holo == (Object)null) { return; } string text = ((!string.IsNullOrEmpty(holo.catalogId)) ? holo.catalogId : ((Object)holo).name); if (!string.IsNullOrEmpty(text) && seen.Add(text)) { string text2 = null; try { text2 = runtime.GetHoloTitle(holo); } catch { } if (string.IsNullOrWhiteSpace(text2)) { text2 = ((Object)holo).name; } list.Add(new CatalogEntry { Id = text, Label = text + " " + text2, Asset = (Object)(object)holo }); } } private static List BuildBullets(UnityDeveloperConsoleRuntime runtime) { List list = new List(); HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); BulletItemData[] array = Resources.FindObjectsOfTypeAll(); foreach (BulletItemData val in array) { if (!((Object)(object)val == (Object)null) && !val.isNormalBullet) { string name = ((Object)val).name; if (!string.IsNullOrEmpty(name) && hashSet.Add(name)) { list.Add(new CatalogEntry { Id = name, Label = name, Asset = (Object)(object)val }); } } } return list.OrderBy((CatalogEntry e) => e.Label, StringComparer.OrdinalIgnoreCase).ToList(); } private static List BuildCharms(UnityDeveloperConsoleRuntime runtime) { List list = new List(); HashSet seen = new HashSet(StringComparer.OrdinalIgnoreCase); IReadOnlyList readOnlyList = null; try { readOnlyList = runtime.GetTrinkets(); } catch { } if (readOnlyList != null) { foreach (CharmItemData item in readOnlyList) { TryAddCharm(list, seen, runtime, item); } } CharmItemData[] array = Resources.FindObjectsOfTypeAll(); foreach (CharmItemData charm in array) { TryAddCharm(list, seen, runtime, charm); } return list.OrderBy((CatalogEntry e) => e.Label, StringComparer.OrdinalIgnoreCase).ToList(); } private static void TryAddCharm(List list, HashSet seen, UnityDeveloperConsoleRuntime runtime, CharmItemData charm) { if ((Object)(object)charm == (Object)null) { return; } string name = ((Object)charm).name; if (!string.IsNullOrEmpty(name) && seen.Add(name)) { string text = null; try { text = runtime.GetTrinketTitle(charm); } catch { } if (string.IsNullOrWhiteSpace(text)) { text = name; } list.Add(new CatalogEntry { Id = name, Label = text, Asset = (Object)(object)charm }); } } private static List BuildDrinks() { List list = new List(); HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); EnergyDrinkItemData[] array = Resources.FindObjectsOfTypeAll(); foreach (EnergyDrinkItemData val in array) { if (!((Object)(object)val == (Object)null)) { string name = ((Object)val).name; if (!string.IsNullOrEmpty(name) && hashSet.Add(name)) { list.Add(new CatalogEntry { Id = name, Label = name, Asset = (Object)(object)val }); } } } return list.OrderBy((CatalogEntry e) => e.Label, StringComparer.OrdinalIgnoreCase).ToList(); } } internal static class LoadoutApplier { public static bool IsLaunching { get; private set; } public static void BeginLaunch(MonoBehaviour host, HashSet holoIds, HashSet bulletNames, HashSet charmNames, HashSet drinkNames) { if (!((Object)(object)host == (Object)null) && !IsLaunching) { host.StartCoroutine(LaunchRoutine(holoIds, bulletNames, charmNames, drinkNames)); } } private static IEnumerator LaunchRoutine(HashSet holoIds, HashSet bulletNames, HashSet charmNames, HashSet drinkNames) { IsLaunching = true; UnityDeveloperConsoleRuntime runtime = new UnityDeveloperConsoleRuntime(); try { PersistSelection(holoIds, bulletNames, charmNames, drinkNames); GameManager gm = GameManager.Instance; if ((Object)(object)gm == (Object)null) { LuckyTestPlugin.Log.LogError((object)"[LuckyTest] GameManager missing."); yield break; } if ((int)gm.Phase == 7 || (int)gm.Phase == 8) { if ((int)gm.Phase == 7) { gm.ShowRunSetup(); } yield return null; yield return null; RunSetupSelectionManager instance = RunSetupSelectionManager.Instance; bool flag = false; if ((Object)(object)instance != (Object)null) { flag = instance.TryCommitAndStartRun(); } if (!flag) { gm.StartGameFromRunSetup(); } float wait = 20f; while (wait > 0f) { gm = GameManager.Instance; if ((Object)(object)gm != (Object)null && ((int)gm.Phase == 3 || (int)gm.Phase == 5 || (int)gm.Phase == 1 || (int)gm.Phase == 0 || (int)gm.Phase == 2)) { break; } wait -= Time.unscaledDeltaTime; yield return null; } if (wait <= 0f) { LuckyTestPlugin.Log.LogWarning((object)"[LuckyTest] Timed out waiting for run start; applying loadout anyway."); } } yield return null; int num = 0; int num2 = 0; string text = default(string); runtime.TryExpandHoloSlots(Mathf.Max(0, LuckyTestPlugin.ExtraHoloSlots.Value), ref num, ref num2, ref text); HoloItemManager instance2 = HoloItemManager.Instance; if ((Object)(object)instance2 != (Object)null) { instance2.ClearAllEquipped(); AccessTools.Method(typeof(HoloItemManager), "ClearAllGrantedNonPhysical", (Type[])null, (Type[])null)?.Invoke(instance2, null); } int equipped = 0; foreach (string item in holoIds.OrderBy((string s) => s, StringComparer.OrdinalIgnoreCase)) { HoloItemData val = ResolveHolo(runtime, item); if ((Object)(object)val == (Object)null) { LuckyTestPlugin.Log.LogWarning((object)("[LuckyTest] Holo not found: " + item)); } else if (runtime.TryEquipHolo(val, ref text)) { equipped++; } else { LuckyTestPlugin.Log.LogWarning((object)("[LuckyTest] Equip failed " + item + ": " + text)); } } int bulletsAdded = 0; int num3 = Mathf.Max(1, LuckyTestPlugin.DefaultBulletAmount.Value); foreach (string bulletName in bulletNames) { BulletItemData val2 = runtime.FindBullet(bulletName) ?? FindBulletByAssetName(bulletName); if ((Object)(object)val2 == (Object)null) { LuckyTestPlugin.Log.LogWarning((object)("[LuckyTest] Bullet not found: " + bulletName)); } else { bulletsAdded += runtime.AddBullets(val2, num3); } } int charms = 0; foreach (string charmName in charmNames) { CharmItemData val3 = runtime.FindTrinket(charmName) ?? FindCharmByAssetName(charmName); if ((Object)(object)val3 == (Object)null) { LuckyTestPlugin.Log.LogWarning((object)("[LuckyTest] Charm not found: " + charmName)); } else if (runtime.TryEquipTrinket(val3, ref text)) { charms++; } else { LuckyTestPlugin.Log.LogWarning((object)("[LuckyTest] Charm failed " + charmName + ": " + text)); } } int drinks = 0; string text2 = default(string); foreach (string drinkName in drinkNames) { if (runtime.TryDrink(drinkName, ref text2, ref text)) { drinks++; } else { LuckyTestPlugin.Log.LogWarning((object)("[LuckyTest] Drink failed " + drinkName + ": " + text)); } } int num4 = Mathf.Max(0, LuckyTestPlugin.StartingMoney.Value); int num5 = default(int); if (num4 > 0 && !runtime.TryAddMoney(num4, ref num5, ref text)) { LuckyTestPlugin.Log.LogWarning((object)("[LuckyTest] Money failed: " + text)); } yield return null; int num6 = Mathf.Clamp(LuckyTestPlugin.StartingRound.Value, 1, 99); if (!runtime.TryGoToLevel(num6, ref text)) { LuckyTestPlugin.Log.LogWarning((object)$"[LuckyTest] TryGoToLevel({num6}) failed: {text}. Falling back to round index."); ForceRoundIndex(num6); } gm = GameManager.Instance; if ((Object)(object)gm != (Object)null) { try { gm.TryContinueAfterWinIntoEndless(); } catch (Exception ex) { LuckyTestPlugin.Log.LogInfo((object)("[LuckyTest] TryContinueAfterWinIntoEndless: " + ex.Message)); } } runtime.MarkRunCheated("LuckyTest sandbox launch"); LuckyTestPlugin.Log.LogInfo((object)$"[LuckyTest] Ready — holos={equipped}, bullets={bulletsAdded}, charms={charms}, drinks={drinks}, level={num6}"); } finally { IsLaunching = false; } } private static void ForceRoundIndex(int oneBasedLevel) { ScoreManager instance = ScoreManager.Instance; if ((Object)(object)instance == (Object)null) { return; } int roundIndex = Mathf.Max(0, oneBasedLevel - 1); instance.SetRoundIndex(roundIndex); ShopManager instance2 = ShopManager.Instance; if (!((Object)(object)instance2 != (Object)null)) { return; } try { AccessTools.Method(typeof(ShopManager), "DebugSetAnteForDeveloperTools", (Type[])null, (Type[])null)?.Invoke(instance2, new object[1] { oneBasedLevel }); } catch (Exception ex) { LuckyTestPlugin.Log.LogInfo((object)("[LuckyTest] DebugSetAnte: " + ex.Message)); } } private static HoloItemData ResolveHolo(UnityDeveloperConsoleRuntime runtime, string id) { if (string.IsNullOrEmpty(id)) { return null; } HoloItemData val = runtime.FindHolo(id); if ((Object)(object)val != (Object)null) { return val; } foreach (CatalogEntry holo in CatalogCache.Holos) { if (string.Equals(holo.Id, id, StringComparison.OrdinalIgnoreCase)) { Object asset = holo.Asset; HoloItemData val2 = (HoloItemData)(object)((asset is HoloItemData) ? asset : null); if (val2 != null) { return val2; } } } HoloItemData[] array = Resources.FindObjectsOfTypeAll(); foreach (HoloItemData val3 in array) { if ((Object)(object)val3 != (Object)null && (string.Equals(val3.catalogId, id, StringComparison.OrdinalIgnoreCase) || string.Equals(((Object)val3).name, id, StringComparison.OrdinalIgnoreCase))) { return val3; } } return null; } private static BulletItemData FindBulletByAssetName(string name) { BulletItemData[] array = Resources.FindObjectsOfTypeAll(); foreach (BulletItemData val in array) { if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, name, StringComparison.OrdinalIgnoreCase)) { return val; } } return null; } private static CharmItemData FindCharmByAssetName(string name) { CharmItemData[] array = Resources.FindObjectsOfTypeAll(); foreach (CharmItemData val in array) { if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, name, StringComparison.OrdinalIgnoreCase)) { return val; } } return null; } private static void PersistSelection(HashSet holos, HashSet bullets, HashSet charms, HashSet drinks) { LuckyTestPlugin.SavedHoloIds.Value = string.Join(",", holos.OrderBy((string s) => s)); LuckyTestPlugin.SavedBulletNames.Value = string.Join(",", bullets.OrderBy((string s) => s)); LuckyTestPlugin.SavedCharmNames.Value = string.Join(",", charms.OrderBy((string s) => s)); LuckyTestPlugin.SavedDrinkNames.Value = string.Join(",", drinks.OrderBy((string s) => s)); ((BaseUnityPlugin)LuckyTestPlugin.Instance).Config.Save(); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.liamgaming.luckytest", "LuckyTest", "1.1.3")] public class LuckyTestPlugin : BaseUnityPlugin { public const string PluginGuid = "com.liamgaming.luckytest"; public const string PluginName = "LuckyTest"; public const string PluginVersion = "1.1.3"; private TesterPanel _panel; private KeyCode _boundKey; private static readonly KeyCode[] HotkeyCycle; public static LuckyTestPlugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } public static ConfigEntry Enabled { get; private set; } public static ConfigEntry StartingRound { get; private set; } public static ConfigEntry StartingMoney { get; private set; } public static ConfigEntry ExtraHoloSlots { get; private set; } public static ConfigEntry DefaultBulletAmount { get; private set; } public static ConfigEntry OpenPanelOnMainMenu { get; private set; } public static ConfigEntry ToggleKey { get; private set; } public static ConfigEntry SavedHoloIds { get; private set; } public static ConfigEntry SavedBulletNames { get; private set; } public static ConfigEntry SavedCharmNames { get; private set; } public static ConfigEntry SavedDrinkNames { get; private set; } private void Awake() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Expected O, but got Unknown //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Master switch for LuckyTest."); OpenPanelOnMainMenu = ((BaseUnityPlugin)this).Config.Bind("General", "OpenPanelOnMainMenu", true, "When shooting the LUCKY TEST main-menu card, open the builder panel."); StartingRound = ((BaseUnityPlugin)this).Config.Bind("Launch", "StartingRound", 9, new ConfigDescription("1-based level/ante to jump to after applying the loadout (endless-friendly).", (AcceptableValueBase)(object)new AcceptableValueRange(1, 99), Array.Empty())); StartingMoney = ((BaseUnityPlugin)this).Config.Bind("Launch", "StartingMoney", 1000, new ConfigDescription("Money granted when launching a test run.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999999), Array.Empty())); ExtraHoloSlots = ((BaseUnityPlugin)this).Config.Bind("Launch", "ExtraHoloSlots", 20, new ConfigDescription("Extra holo slots unlocked before equipping.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 50), Array.Empty())); DefaultBulletAmount = ((BaseUnityPlugin)this).Config.Bind("Launch", "DefaultBulletAmount", 8, new ConfigDescription("How many of each selected special bullet to grant.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 64), Array.Empty())); ToggleKey = ((BaseUnityPlugin)this).Config.Bind("General", "ToggleKey", (KeyCode)288, "Keyboard key to open/close the LuckyTest panel."); SavedHoloIds = ((BaseUnityPlugin)this).Config.Bind("SavedLoadout", "HoloIds", "", "Comma-separated holo catalog IDs remembered between sessions."); SavedBulletNames = ((BaseUnityPlugin)this).Config.Bind("SavedLoadout", "BulletNames", "", "Comma-separated bullet asset names."); SavedCharmNames = ((BaseUnityPlugin)this).Config.Bind("SavedLoadout", "CharmNames", "", "Comma-separated charm/trinket asset names."); SavedDrinkNames = ((BaseUnityPlugin)this).Config.Bind("SavedLoadout", "DrinkNames", "", "Comma-separated energy drink asset names."); ModMenu.Tab("LuckyTest").Toggle(Enabled).Info("— Launch —") .Int("Start Round", StartingRound, 1) .Int("Start Money", StartingMoney, 50) .Int("Extra Holo Slots", ExtraHoloSlots, 1) .Int("Bullet Amount", DefaultBulletAmount, 1) .Info("— Panel —") .Bool("Menu Card Opens Panel", OpenPanelOnMainMenu) .Cycle("Hotkey", (Func)(() => ((object)ToggleKey.Value/*cast due to .constrained prefix*/).ToString()), (Action)CycleToggleKey) .Button("Open Panel", (Action)delegate { if ((Object)(object)_panel != (Object)null) { _panel.Toggle(); } }); GameObject val = new GameObject("LuckyTest"); Object.DontDestroyOnLoad((Object)(object)val); _panel = val.AddComponent(); _boundKey = ToggleKey.Value; InputAPI.RegisterKeyCallback(_boundKey, (Action)OnHotkey); ToggleKey.SettingChanged += delegate { }; MainMenu.WhenReady((Action)delegate { MainMenu.AddButton("LUCKY TEST", (Action)delegate { if (Enabled.Value && OpenPanelOnMainMenu.Value) { _panel?.Open(); } }); }); new Harmony("com.liamgaming.luckytest").PatchAll(typeof(LuckyTestPlugin).Assembly); Log.LogInfo((object)string.Format("{0} v{1} loaded (OpenShot {2}). Hotkey {3}.", "LuckyTest", "1.1.3", "2.0.3", ToggleKey.Value)); } private void OnHotkey() { if (Enabled.Value && !((Object)(object)_panel == (Object)null)) { _panel.Toggle(); } } private static void CycleToggleKey() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) int num = Array.IndexOf(HotkeyCycle, ToggleKey.Value); if (num < 0) { num = 0; } ToggleKey.Value = HotkeyCycle[(num + 1) % HotkeyCycle.Length]; } static LuckyTestPlugin() { KeyCode[] array = new KeyCode[7]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); HotkeyCycle = (KeyCode[])(object)array; } } internal sealed class TesterPanel : MonoBehaviour { private enum Tab { Holos, Bullets, Charms, Drinks, Launch } private bool _visible; private Tab _tab; private Vector2 _scroll; private string _filter = ""; private string _status = "Pick a loadout, then Launch."; private Rect _window = new Rect(80f, 60f, 820f, 560f); private readonly HashSet _holos = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly HashSet _bullets = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly HashSet _charms = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly HashSet _drinks = new HashSet(StringComparer.OrdinalIgnoreCase); private CursorLockMode _prevLock; private bool _prevCursor; private bool _catalogReady; public void Open() { //IL_000a: 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) if (!_visible) { _prevLock = Cursor.lockState; _prevCursor = Cursor.visible; _visible = true; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; EnsureCatalog(); LoadSavedSelection(); } } public void Close() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (_visible) { _visible = false; Cursor.lockState = _prevLock; Cursor.visible = _prevCursor; } } public void Toggle() { if (_visible) { Close(); } else { Open(); } } private void Update() { if (_visible && InputAPI.WasPressedThisFrame((KeyCode)27)) { Close(); } } private void OnGUI() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //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) if (_visible && LuckyTestPlugin.Enabled.Value) { _window = GUI.Window(8742101, _window, new WindowFunction(DrawWindow), "LuckyTest — Build Sandbox"); } } private void DrawWindow(int id) { //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal(Array.Empty()); DrawTabButton(Tab.Holos, $"Holos ({_holos.Count})"); DrawTabButton(Tab.Bullets, $"Bullets ({_bullets.Count})"); DrawTabButton(Tab.Charms, $"Charms ({_charms.Count})"); DrawTabButton(Tab.Drinks, $"Drinks ({_drinks.Count})"); DrawTabButton(Tab.Launch, "Launch"); GUILayout.EndHorizontal(); GUILayout.Space(6f); GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label("Filter", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) }); _filter = GUILayout.TextField(_filter ?? "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (GUILayout.Button("Refresh", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) })) { CatalogCache.Refresh(); _catalogReady = true; _status = $"Catalog refreshed — holos={CatalogCache.Holos.Count}, bullets={CatalogCache.Bullets.Count}"; } if (GUILayout.Button("Clear Tab", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { ClearCurrentTab(); } GUILayout.EndHorizontal(); GUILayout.Space(4f); _scroll = GUILayout.BeginScrollView(_scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) }); switch (_tab) { case Tab.Holos: DrawPicker(CatalogCache.Holos, _holos); break; case Tab.Bullets: DrawPicker(CatalogCache.Bullets, _bullets); break; case Tab.Charms: DrawPicker(CatalogCache.Charms, _charms); break; case Tab.Drinks: DrawPicker(CatalogCache.Drinks, _drinks); break; case Tab.Launch: DrawLaunchTab(); break; } GUILayout.EndScrollView(); GUILayout.Space(4f); GUILayout.Label(_status, Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); if (GUILayout.Button("Close", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) })) { Close(); } GUI.enabled = !LoadoutApplier.IsLaunching; if (GUILayout.Button(LoadoutApplier.IsLaunching ? "Launching…" : "START TEST RUN", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) })) { StartTest(); } GUI.enabled = true; GUILayout.EndHorizontal(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f)); } private void DrawTabButton(Tab tab, string label) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) Color backgroundColor = GUI.backgroundColor; if (_tab == tab) { GUI.backgroundColor = new Color(0.2f, 0.75f, 0.55f); } if (GUILayout.Button(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f) })) { _tab = tab; } GUI.backgroundColor = backgroundColor; } private void DrawPicker(List entries, HashSet selected) { if (entries == null || entries.Count == 0) { GUILayout.Label("No items found yet. Enter a run once, or hit Refresh after the game has loaded assets.", Array.Empty()); return; } string value = (_filter ?? "").Trim(); foreach (CatalogEntry entry in entries) { if (!string.IsNullOrEmpty(value) && entry.Label.IndexOf(value, StringComparison.OrdinalIgnoreCase) < 0 && entry.Id.IndexOf(value, StringComparison.OrdinalIgnoreCase) < 0) { continue; } bool flag = selected.Contains(entry.Id); bool flag2 = GUILayout.Toggle(flag, entry.Label, Array.Empty()); if (flag2 != flag) { if (flag2) { selected.Add(entry.Id); } else { selected.Remove(entry.Id); } } } } private void DrawLaunchTab() { GUILayout.Label("Launch jumps into a run (if needed), equips your picks, then GoToLevel(StartingRound).", Array.Empty()); GUILayout.Space(6f); GUILayout.Label($"Starting round (1-based): {LuckyTestPlugin.StartingRound.Value}", Array.Empty()); LuckyTestPlugin.StartingRound.Value = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)LuckyTestPlugin.StartingRound.Value, 1f, 40f, Array.Empty())); GUILayout.Label($"Starting money: {LuckyTestPlugin.StartingMoney.Value}", Array.Empty()); LuckyTestPlugin.StartingMoney.Value = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)LuckyTestPlugin.StartingMoney.Value, 0f, 5000f, Array.Empty()) / 50f) * 50; GUILayout.Label($"Extra holo slots: {LuckyTestPlugin.ExtraHoloSlots.Value}", Array.Empty()); LuckyTestPlugin.ExtraHoloSlots.Value = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)LuckyTestPlugin.ExtraHoloSlots.Value, 0f, 40f, Array.Empty())); GUILayout.Label($"Bullets per type: {LuckyTestPlugin.DefaultBulletAmount.Value}", Array.Empty()); LuckyTestPlugin.DefaultBulletAmount.Value = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)LuckyTestPlugin.DefaultBulletAmount.Value, 1f, 32f, Array.Empty())); GUILayout.Space(8f); GUILayout.Label($"Selected — Holos {_holos.Count} | Bullets {_bullets.Count} | Charms {_charms.Count} | Drinks {_drinks.Count}", Array.Empty()); GUILayout.Label("Tip: set Starting Round past the normal win ante (default 9) to land in endless scoring.", Array.Empty()); } private void StartTest() { EnsureCatalog(); _status = "Launching test run…"; Close(); LoadoutApplier.BeginLaunch((MonoBehaviour)(object)this, Clone(_holos), Clone(_bullets), Clone(_charms), Clone(_drinks)); } private static HashSet Clone(HashSet src) { return new HashSet(src, StringComparer.OrdinalIgnoreCase); } private void ClearCurrentTab() { switch (_tab) { case Tab.Holos: _holos.Clear(); break; case Tab.Bullets: _bullets.Clear(); break; case Tab.Charms: _charms.Clear(); break; case Tab.Drinks: _drinks.Clear(); break; } } private void EnsureCatalog() { if (!_catalogReady || CatalogCache.Holos.Count <= 0) { CatalogCache.Refresh(); _catalogReady = true; } } private void LoadSavedSelection() { Fill(_holos, LuckyTestPlugin.SavedHoloIds.Value); Fill(_bullets, LuckyTestPlugin.SavedBulletNames.Value); Fill(_charms, LuckyTestPlugin.SavedCharmNames.Value); Fill(_drinks, LuckyTestPlugin.SavedDrinkNames.Value); } private static void Fill(HashSet set, string csv) { set.Clear(); if (string.IsNullOrWhiteSpace(csv)) { return; } string[] array = csv.Split(new char[3] { ',', ';', '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { set.Add(text); } } } } }