using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Pigeon; using Pigeon.Math; using Pigeon.Movement; using Sparroh.UI; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("UpgradeOptimizer")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("UpgradeOptimizer")] [assembly: AssemblyTitle("UpgradeOptimizer")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [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; } } } internal static class BoostFeature { public static void TryHandleHotkey(Keyboard keyboard, Key hotkey) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (!PlayerInput.IsMenuEnabled || !UpgradeOptimizerPlugin.WasHotkeyPressed(keyboard, hotkey)) { return; } UpgradeInstance hoveredUpgrade = UpgradeOptimizerPlugin.HoveredUpgrade; if (hoveredUpgrade != null && !((Object)(object)hoveredUpgrade.Upgrade == (Object)null)) { if (hoveredUpgrade.IsTurbocharged) { hoveredUpgrade.IsTurbocharged = false; RefreshUpgradeUI(hoveredUpgrade); UpgradeOptimizerPlugin.Log.LogInfo((object)("Removed boost from '" + hoveredUpgrade.Upgrade.Name + "'.")); } else if (!CanAutoBoost(hoveredUpgrade)) { UpgradeOptimizerPlugin.Log.LogInfo((object)("Upgrade '" + hoveredUpgrade.Upgrade.Name + "' cannot be boosted.")); } else { hoveredUpgrade.IsTurbocharged = true; RefreshUpgradeUI(hoveredUpgrade); PlayBoostFeedback(hoveredUpgrade); UpgradeOptimizerPlugin.Log.LogInfo((object)("Boosted '" + hoveredUpgrade.Upgrade.Name + "'.")); } } } private static bool CanAutoBoost(UpgradeInstance upgrade) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Invalid comparison between Unknown and I4 //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Invalid comparison between Unknown and I4 Upgrade upgrade2 = upgrade.Upgrade; if (upgrade2 == null) { return false; } if (!upgrade.IsUnlocked) { return false; } if (upgrade.RemoveAfterMission) { return false; } Rarity rarity = upgrade2.Rarity; if ((int)rarity > 3) { return false; } if ((int)rarity == 3) { return (upgrade2.Flags & 0x2000) > 0; } if (upgrade2.IsSkin()) { return false; } return (upgrade2.Flags & 0x40020) == 0; } private static void RefreshUpgradeUI(UpgradeInstance upgrade) { if ((Object)(object)HoverInfoDisplay.Instance != (Object)null) { HoverInfoDisplay.Instance.Refresh(); } GearUpgradeUI val = default(GearUpgradeUI); if (UIRaycaster.RaycastForComponent(ref val) && (Object)(object)val != (Object)null && ((HoverInfoUpgrade)val).Upgrade == upgrade) { val.SetUpgrade(upgrade, false); } GearDetailsWindow val2 = null; if ((Object)(object)Menu.Instance != (Object)null && Menu.Instance.IsOpen) { Window top = Menu.Instance.WindowSystem.GetTop(); val2 = (GearDetailsWindow)(object)((top is GearDetailsWindow) ? top : null); } if ((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeSelf && upgrade.IsEquipped(val2.UpgradablePrefab)) { val2.RefreshUpgrade(upgrade); } } private static void PlayBoostFeedback(UpgradeInstance upgrade) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)PlayerLook.Instance == (Object)null)) { Global.GetRarity(upgrade.Upgrade.Rarity).raritySwitch.SetValue(((Component)PlayerLook.Instance).gameObject); Global.Instance.UpgradeUnlockSound.Post(((Component)PlayerLook.Instance).gameObject); Global.Instance.UpgradeDropSound.Post(((Component)PlayerLook.Instance).gameObject); } } } internal static class MaxRollPatches { [HarmonyPatch] internal static class RangeFloatGetValuePatch { private static MethodBase TargetMethod() { return FindGetValue(typeof(Range)); } private static bool Prefix(ref Range __instance, ref Random rand, UpgradeInstance upgrade, BoostParams boostParams, ref float __result) { //IL_0001: 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 (!ShouldForceBest(upgrade, boostParams)) { return true; } __result = __instance.GetValue(ref rand, GetBestAddT(boostParams)); return false; } } [HarmonyPatch] internal static class RangeIntGetValuePatch { private static MethodBase TargetMethod() { return FindGetValue(typeof(Range)); } private static bool Prefix(ref Range __instance, ref Random rand, UpgradeInstance upgrade, BoostParams boostParams, ref int __result) { //IL_0001: 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 (!ShouldForceBest(upgrade, boostParams)) { return true; } __result = __instance.GetValue(ref rand, GetBestAddT(boostParams)); return false; } } [HarmonyPatch] internal static class RangeVector2GetValuePatch { private static MethodBase TargetMethod() { return FindGetValue(typeof(Range)); } private static bool Prefix(ref Range __instance, ref Random rand, UpgradeInstance upgrade, BoostParams boostParams, ref Vector2 __result) { //IL_0001: 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) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!ShouldForceBest(upgrade, boostParams)) { return true; } __result = __instance.GetValue(ref rand, GetBestAddT(boostParams)); return false; } } [HarmonyPatch] internal static class GetUniformRandomValuePatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Range), "GetUniformRandomValue", new Type[4] { typeof(Range), typeof(Random).MakeByRefType(), typeof(UpgradeInstance), typeof(BoostParams) }, (Type[])null); } private static bool Prefix(Range range, ref Random rand, UpgradeInstance upgrade, BoostParams boostParams, ref Vector2 __result) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (!ShouldForceBest(upgrade, boostParams)) { return true; } __result = Vector2.Lerp(range.min, range.max, ((Random)(ref rand)).NextFloat() + GetBestAddT(boostParams)); return false; } } private static bool ShouldForceBest(UpgradeInstance upgrade, BoostParams boostParams) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 if (!UpgradeOptimizerPlugin.EnableMaxRolls.Value) { return false; } if (upgrade == null || !upgrade.IsTurbocharged) { return false; } if (!boostParams.cannotBeBoosted) { return true; } Upgrade upgrade2 = upgrade.Upgrade; if (upgrade2 != null) { return (int)upgrade2.Rarity == 3; } return false; } private static float GetBestAddT(BoostParams boostParams) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (!boostParams.minIsBetter) { return 1f; } return -1f; } private static MethodBase FindGetValue(Type rangeType) { return AccessTools.Method(rangeType, "GetValue", new Type[3] { typeof(Random).MakeByRefType(), typeof(UpgradeInstance), typeof(BoostParams) }, (Type[])null); } } public static class PatternBrowser { private static bool _isOpen; private static UpgradeInstance _target; private static string _search = ""; private static bool _sameGearOnly; private static int _rarityFilterIndex; private static PatternCatalog.SortMode _sortMode = PatternCatalog.SortMode.Name; private static int _selectedIndex = -1; private static string _status = ""; private static int _targetCellCount; private static UIWindow _window; private static UIInputField _searchField; private static UIToggle _sameGearToggle; private static UIDragList _unused; private static RectTransform _listContent; private static UIScrollView _listScroll; private static UIText _headerText; private static UIText _currentPatternText; private static UIText _previewText; private static UIText _statusText; private static UIText _countText; private static readonly List _listButtons = new List(); private static readonly string[] RarityFilterLabels = new string[7] { "All", "Standard", "Rare", "Epic", "Exotic", "Oddity", "Contraband" }; public static bool IsOpen => _isOpen; public static void Open(UpgradeInstance target) { if (target == null) { return; } _target = target; _isOpen = true; _selectedIndex = -1; _status = ""; _targetCellCount = PatternCatalog.SafeCellCount(target.Upgrade); try { HexMap pattern = target.GetPattern(false); if (pattern != null) { _targetCellCount = pattern.GetCellCount(); } } catch { } PatternCatalog.Rebuild(target); RefreshFilters(); EnsureWindow(); RefreshUi(); _window.Show(); ManualLogSource log = UpgradeOptimizerPlugin.Log; Upgrade upgrade = target.Upgrade; log.LogInfo((object)("Opened pattern browser for " + ((upgrade != null) ? upgrade.Name : null))); } public static void Close() { _isOpen = false; _target = null; _selectedIndex = -1; _status = ""; if (_window != null) { _window.Hide(true); } } public static void Draw() { } private static void EnsureWindow() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Expected O, but got Unknown //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Expected O, but got Unknown //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Expected O, but got Unknown //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_04a0: Unknown result type (might be due to invalid IL or missing references) //IL_0547: Unknown result type (might be due to invalid IL or missing references) //IL_0556: Expected O, but got Unknown if (_window != null) { return; } UITheme.Initialize(); _window = UIWindow.Create("PatternBrowser", (Vector2?)new Vector2(720f, 520f), "UpgradeOptimizer — Pattern Browser", false, true, (int?)(UITheme.WindowSortingOrder + 10)); _window.OnClose((Action)Close); Transform content = _window.Content; UIFactory.AddVerticalLayout(((Component)content).gameObject, UITheme.S(6f), UITheme.ScaledPadding(10, 10, 8, 8), (TextAnchor)0, true, false, true, true); _headerText = UIText.Create(content, "Header", "", UITheme.ScaledFontBody, (Color?)UIColors.TextPrimary, (TextAlignmentOptions)513, false); GameObject gameObject = _headerText.GameObject; float? num = UITheme.S(22f); UIHelpers.EnsureLayoutElement(gameObject, (float?)null, num, (float?)null); _currentPatternText = UIText.Create(content, "Current", "", UITheme.ScaledFontSmall, (Color?)UIColors.TextSecondary, (TextAlignmentOptions)513, false); GameObject gameObject2 = _currentPatternText.GameObject; num = UITheme.S(20f); UIHelpers.EnsureLayoutElement(gameObject2, (float?)null, num, (float?)null); RectTransform val = UIFactory.CreateRect("SearchRow", content); GameObject gameObject3 = ((Component)val).gameObject; num = UITheme.ScaledInputHeight + UITheme.S(4f); UIHelpers.EnsureLayoutElement(gameObject3, (float?)null, num, (float?)null); UIFactory.AddHorizontalLayout(((Component)val).gameObject, UITheme.S(8f), new RectOffset(0, 0, 0, 0), (TextAnchor)3, false, false, true, true); UIText.Create((Transform)(object)val, "SearchLbl", "Search", UITheme.ScaledFontSmall, (Color?)UIColors.TextSecondary, (TextAlignmentOptions)513, false); _searchField = UIInputField.Create((Transform)(object)val, _search, "Filter patterns...", (Action)delegate(string s) { _search = s ?? ""; RefreshFilters(); RebuildList(); }, "InputField"); UIHelpers.EnsureLayoutElement(_searchField.GameObject, (float?)UITheme.S(220f), (float?)null, (float?)null); UIText.Create((Transform)(object)val, "LockedFilters", "Same gear · same rarity", UITheme.ScaledFontSmall, (Color?)UIColors.TextMuted, (TextAlignmentOptions)513, false); RectTransform val2 = UIFactory.CreateRect("FilterRow", content); GameObject gameObject4 = ((Component)val2).gameObject; num = UITheme.ScaledButtonHeight; UIHelpers.EnsureLayoutElement(gameObject4, (float?)null, num, (float?)null); UIFactory.AddHorizontalLayout(((Component)val2).gameObject, UITheme.S(8f), new RectOffset(0, 0, 0, 0), (TextAnchor)3, false, false, true, true); UIButton.Create((Transform)(object)val2, "Sort: Name", (Action)delegate { _sortMode = (PatternCatalog.SortMode)((int)(_sortMode + 1) % 4); RefreshFilters(); RebuildList(); RefreshFilterButtons(); }, (UIButtonStyle)0, (string)null, (float?)null).SetWidth(UITheme.S(140f)); _countText = UIText.Create((Transform)(object)val2, "Count", "0 patterns", UITheme.ScaledFontSmall, (Color?)UIColors.TextMuted, (TextAlignmentOptions)513, false); RectTransform obj = UIFactory.CreateRect("Mid", content); GameObject gameObject5 = ((Component)obj).gameObject; num = UITheme.S(280f); UIHelpers.EnsureLayoutElement(gameObject5, (float?)null, (float?)null, num).flexibleHeight = 1f; UIFactory.AddHorizontalLayout(((Component)obj).gameObject, UITheme.S(10f), new RectOffset(0, 0, 0, 0), (TextAnchor)0, true, true, true, true); _listScroll = UIScrollView.Create((Transform)(object)obj, "PatternList", true, false); UIHelpers.EnsureLayoutElement(_listScroll.GameObject, (float?)null, (float?)null, (float?)null).flexibleWidth = 1.2f; _listContent = _listScroll.Content; UIPanel obj2 = UIPanel.Create((Transform)(object)obj, "Preview", (Color?)UIColors.Surface, true); UIHelpers.EnsureLayoutElement(obj2.GameObject, (float?)null, (float?)null, (float?)null).flexibleWidth = 1f; _previewText = UIText.Create(obj2.Content, "PreviewText", "Select a pattern", UITheme.ScaledFontSmall, (Color?)UIColors.TextSecondary, (TextAlignmentOptions)257, true); UIHelpers.SetFillParent(_previewText.Rect, UITheme.S(8f)); _statusText = UIText.Create(content, "Status", "", UITheme.ScaledFontSmall, (Color?)UIColors.Sky, (TextAlignmentOptions)513, false); GameObject gameObject6 = _statusText.GameObject; num = UITheme.S(20f); UIHelpers.EnsureLayoutElement(gameObject6, (float?)null, num, (float?)null); RectTransform obj3 = UIFactory.CreateRect("Footer", content); GameObject gameObject7 = ((Component)obj3).gameObject; num = UITheme.ScaledButtonHeight + UITheme.S(4f); UIHelpers.EnsureLayoutElement(gameObject7, (float?)null, num, (float?)null); UIFactory.AddHorizontalLayout(((Component)obj3).gameObject, UITheme.S(8f), new RectOffset(0, 0, 0, 0), (TextAnchor)3, false, false, true, true); UIButton.Create((Transform)(object)obj3, "Clear Override", (Action)delegate { ApplyOverride(null); }, (UIButtonStyle)2, (string)null, (float?)null).SetWidth(UITheme.S(130f)); UIButton.Create((Transform)(object)obj3, "Apply", (Action)delegate { if (_selectedIndex >= 0 && _selectedIndex < PatternCatalog.CurrentFiltered.Count) { ApplyOverride(PatternCatalog.CurrentFiltered[_selectedIndex].Upgrade); } }, (UIButtonStyle)1, (string)null, (float?)null).SetWidth(UITheme.S(100f)); UIButton.Create((Transform)(object)obj3, "Close", (Action)Close, (UIButtonStyle)0, (string)null, (float?)null).SetWidth(UITheme.S(90f)); } private static void RefreshFilterButtons() { if (_countText != null) { _countText.Text = $"{PatternCatalog.CurrentFiltered.Count} patterns · {RarityFilterLabels[_rarityFilterIndex]} · {_sortMode}"; } } private static void RefreshUi() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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 (_headerText != null && _target != null) { string text = _target.Upgrade.GetInstanceName(_target) ?? _target.Upgrade.Name; _headerText.Text = "Target: " + text; } if (_currentPatternText != null && _target != null) { UpgradeID overriddenPattern = _target.OverriddenPattern; if (overriddenPattern.ID != 0) { Upgrade upgradeFromID = PlayerData.GetUpgradeFromID(overriddenPattern); _currentPatternText.Text = (((Object)(object)upgradeFromID != (Object)null) ? $"Current pattern: {upgradeFromID.Name} ({PatternCatalog.SafeCellCount(upgradeFromID)} cells)" : $"Current pattern: ID {overriddenPattern.ID}"); } else { _currentPatternText.Text = $"Current pattern: Original ({_targetCellCount} cells)"; } } if (_searchField != null) { _searchField.Text = _search ?? ""; } if (_sameGearToggle != null) { _sameGearToggle.IsOn = _sameGearOnly; } if (_statusText != null) { _statusText.Text = _status ?? ""; } RebuildList(); RefreshFilterButtons(); UpdatePreview(); } private static void RebuildList() { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_listContent == (Object)null) { return; } UIHelpers.DestroyChildren((Transform)(object)_listContent); _listButtons.Clear(); IReadOnlyList currentFiltered = PatternCatalog.CurrentFiltered; for (int i = 0; i < currentFiltered.Count; i++) { int index = i; PatternEntry patternEntry = currentFiltered[i]; int num = patternEntry.CellCount - _targetCellCount; string text = ((num > 0) ? $" (+{num})" : ((num < 0) ? $" ({num})" : " (=)")); string text2 = $"{patternEntry.DisplayName} [{patternEntry.Rarity}] {patternEntry.CellCount}c{text}"; UIButton item = UIButton.Create((Transform)(object)_listContent, text2, (Action)delegate { _selectedIndex = index; UpdatePreview(); }, (UIButtonStyle)((index == _selectedIndex) ? 3 : 0), (string)null, (float?)UITheme.S(26f)); _listButtons.Add(item); } if (_countText != null) { _countText.Text = $"{currentFiltered.Count} patterns"; } } private static void UpdatePreview() { //IL_0107: Unknown result type (might be due to invalid IL or missing references) if (_previewText == null) { return; } if (_selectedIndex < 0 || _selectedIndex >= PatternCatalog.CurrentFiltered.Count) { _previewText.Text = "Select a pattern to preview"; return; } PatternEntry patternEntry = PatternCatalog.CurrentFiltered[_selectedIndex]; HexMap val = PatternCatalog.SafePattern(patternEntry.Upgrade); int num = ((val != null) ? val.GetCellCount() : patternEntry.CellCount); int num2 = ((val != null) ? val.Width : 0); int num3 = ((val != null) ? val.Height : 0); string text = ""; if (val != null) { for (int i = 0; i < val.Height; i++) { for (int j = 0; j < val.Width; j++) { text += (val[j, i].enabled ? "■ " : "· "); } text += "\n"; } } _previewText.Text = $"{patternEntry.UpgradeName}\n{patternEntry.GearName} · {patternEntry.Rarity} · {num} cells ({num2}x{num3})\n\n{text}"; } private static void RefreshFilters() { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) bool filterByRarity = false; Rarity val = (Rarity)(-1); _sameGearOnly = true; UpgradeInstance target = _target; if ((Object)(object)((target != null) ? target.Upgrade : null) != (Object)null) { filterByRarity = true; val = _target.Upgrade.Rarity; _rarityFilterIndex = RarityToFilterIndex(val); } IUpgradable targetGear = ((_target != null) ? _target.Gear : null); PatternCatalog.ApplyFilters(_search, _sameGearOnly, targetGear, filterByRarity, val, _sortMode, _targetCellCount); if (_selectedIndex >= PatternCatalog.CurrentFiltered.Count) { _selectedIndex = PatternCatalog.CurrentFiltered.Count - 1; } } private unsafe static int RarityToFilterIndex(Rarity rarity) { string b = ((object)(*(Rarity*)(&rarity))/*cast due to .constrained prefix*/).ToString(); for (int i = 0; i < RarityFilterLabels.Length; i++) { if (string.Equals(RarityFilterLabels[i], b, StringComparison.OrdinalIgnoreCase)) { return i; } } return 0; } private static bool IsUpgradeOnGear(Upgrade upgrade, IUpgradable gear) { if (!((Object)(object)upgrade == (Object)null)) { object obj; if (gear == null) { obj = null; } else { GearInfo info = gear.Info; obj = ((info != null) ? info.Upgrades : null); } if (obj != null) { foreach (Upgrade upgrade2 in gear.Info.Upgrades) { if (upgrade2 == upgrade) { return true; } } return false; } } return false; } private static void ApplyOverride(Upgrade patternSource) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (_target == null) { return; } if ((Object)(object)patternSource != (Object)null) { if (patternSource.IsSkin()) { _status = "Blocked: skin patterns disabled"; if (_statusText != null) { _statusText.Text = _status; } UpgradeOptimizerPlugin.Log.LogWarning((object)("SparrohMode=false blocked skin pattern override: " + patternSource.Name)); return; } Rarity val = (Rarity)((!((Object)(object)_target.Upgrade != (Object)null)) ? (-1) : ((int)_target.Upgrade.Rarity)); bool flag = patternSource.Rarity == val; bool flag2 = _target.Gear == null || IsUpgradeOnGear(patternSource, _target.Gear); if (!flag2 || !flag) { _status = "Blocked: same gear and rarity only"; if (_statusText != null) { _statusText.Text = _status; } UpgradeOptimizerPlugin.Log.LogWarning((object)("SparrohMode=false blocked pattern override: " + patternSource.Name + " " + $"(rarity match={flag}, gear match={flag2})")); return; } } try { List<(IUpgradable, sbyte, sbyte, byte)> list = CaptureEquippedPositions(_target); if (list.Count > 0) { PlayerData.UnequipFromAll(_target); } _target.OverridePattern(patternSource); int num = 0; foreach (var item in list) { if (CanOccupy(item.Item1, _target, item.Item2, item.Item3, item.Item4)) { _target.Equip(item.Item1, item.Item2, item.Item3, item.Item4, true, false); num++; } } string text = (((Object)(object)patternSource != (Object)null) ? patternSource.Name : "Original"); if (list.Count == 0) { _status = "Applied: " + text; } else if (num == list.Count) { _status = "Applied: " + text + " (re-equipped)"; } else if (num == 0) { _status = "Applied: " + text + " (unequipped — new shape doesn't fit)"; } else { _status = $"Applied: {text} (re-equipped {num}/{list.Count})"; } try { HexMap pattern = _target.GetPattern(false); _targetCellCount = ((pattern != null) ? pattern.GetCellCount() : PatternCatalog.SafeCellCount(_target.Upgrade)); } catch { _targetCellCount = PatternCatalog.SafeCellCount(_target.Upgrade); } RefreshFilters(); RefreshUi(); ManualLogSource log = UpgradeOptimizerPlugin.Log; Upgrade upgrade = _target.Upgrade; log.LogInfo((object)("Pattern override on " + ((upgrade != null) ? upgrade.Name : null) + " -> " + text)); } catch (Exception arg) { _status = "Failed to apply override"; UpgradeOptimizerPlugin.Log.LogError((object)$"ApplyOverride failed: {arg}"); if (_statusText != null) { _statusText.Text = _status; } } } private static List<(IUpgradable gear, sbyte x, sbyte y, byte rot)> CaptureEquippedPositions(UpgradeInstance instance) { List<(IUpgradable, sbyte, sbyte, byte)> list = new List<(IUpgradable, sbyte, sbyte, byte)>(); if (instance == null || (Object)(object)Global.Instance == (Object)null) { return list; } try { if (Global.Instance.Characters != null) { Character[] characters = Global.Instance.Characters; sbyte item = default(sbyte); sbyte item2 = default(sbyte); byte item3 = default(byte); foreach (Character val in characters) { if ((Object)(object)val != (Object)null && instance.IsEquipped((IUpgradable)(object)val) && instance.GetPosition((IUpgradable)(object)val, ref item, ref item2, ref item3)) { list.Add(((IUpgradable)(object)val, item, item2, item3)); } } } if (Global.Instance.AllGear != null) { IUpgradable[] allGear = Global.Instance.AllGear; sbyte item4 = default(sbyte); sbyte item5 = default(sbyte); byte item6 = default(byte); foreach (IUpgradable val2 in allGear) { if (val2 != null && instance.IsEquipped(val2) && instance.GetPosition(val2, ref item4, ref item5, ref item6)) { list.Add((val2, item4, item5, item6)); } } } } catch (Exception ex) { UpgradeOptimizerPlugin.Log.LogWarning((object)("CaptureEquippedPositions: " + ex.Message)); } return list; } private static bool CanOccupy(IUpgradable gear, UpgradeInstance upgrade, sbyte x, sbyte y, byte rotation) { try { HexMap pattern = upgrade.GetPattern(false); HexMap val = ((pattern != null) ? pattern.GetModifiedMap((int)rotation, (HexMap)null) : null); if (val == null) { return true; } int num = default(int); int num2 = default(int); gear.Info.GetUpgradeGridSize(ref num, ref num2, false); if (val.Width > num + 2 || val.Height > num2 + 2) { return false; } return true; } catch { return true; } } } public sealed class PatternEntry { public Upgrade Upgrade; public IUpgradable Gear; public string GearName; public string UpgradeName; public string DisplayName; public Rarity Rarity; public int CellCount; public string SearchText; } public static class PatternCatalog { public enum SortMode { Name, Rarity, CellCount, CellDelta } private static readonly List AllEntries = new List(256); private static readonly List Filtered = new List(256); public static IReadOnlyList CurrentFiltered => Filtered; public static void Rebuild(UpgradeInstance target) { //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) AllEntries.Clear(); if (target == null || PlayerData.Instance == null || PlayerData.Instance.collectedGear == null) { Filtered.Clear(); return; } Upgrade upgrade = target.Upgrade; foreach (GearData value in PlayerData.Instance.collectedGear.Values) { if (((value != null) ? value.Gear : null) == null || !value.IsUnlocked || (Object)(object)value.Gear.Info == (Object)null) { continue; } IUpgradable gear = value.Gear; string text = gear.Info.Name; if (string.IsNullOrEmpty(text)) { text = "Unknown Gear"; } List upgrades = gear.Info.Upgrades; if (upgrades == null) { continue; } foreach (Upgrade item in upgrades) { if (item != null && item != upgrade && !item.IsSkin()) { int cellCount = SafeCellCount(item); string text2 = item.Name ?? item.APIName ?? "Upgrade"; string text3 = text + " - " + text2; AllEntries.Add(new PatternEntry { Upgrade = item, Gear = gear, GearName = text, UpgradeName = text2, DisplayName = text3, Rarity = item.Rarity, CellCount = cellCount, SearchText = text3.ToLowerInvariant() }); } } } AllEntries.Sort((PatternEntry a, PatternEntry b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase)); } public static void ApplyFilters(string search, bool sameGearOnly, IUpgradable targetGear, bool filterByRarity, Rarity rarityFilter, SortMode sortMode, int targetCellCount) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) Filtered.Clear(); string text = (string.IsNullOrWhiteSpace(search) ? null : search.Trim().ToLowerInvariant()); sameGearOnly = true; filterByRarity = true; foreach (PatternEntry allEntry in AllEntries) { if ((!sameGearOnly || targetGear == null || allEntry.Gear == targetGear) && (!filterByRarity || allEntry.Rarity == rarityFilter) && (text == null || allEntry.SearchText.IndexOf(text, StringComparison.Ordinal) >= 0)) { Filtered.Add(allEntry); } } switch (sortMode) { case SortMode.Rarity: Filtered.Sort(delegate(PatternEntry a, PatternEntry b) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ref Rarity rarity = ref b.Rarity; object target = a.Rarity; int num = ((Enum)Unsafe.As(ref rarity)/*cast due to .constrained prefix*/).CompareTo(target); return (num == 0) ? string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase) : num; }); break; case SortMode.CellCount: Filtered.Sort(delegate(PatternEntry a, PatternEntry b) { int num = b.CellCount.CompareTo(a.CellCount); return (num == 0) ? string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase) : num; }); break; case SortMode.CellDelta: Filtered.Sort(delegate(PatternEntry a, PatternEntry b) { int num = Math.Abs(a.CellCount - targetCellCount); int value = Math.Abs(b.CellCount - targetCellCount); int num2 = num.CompareTo(value); if (num2 != 0) { return num2; } num2 = b.CellCount.CompareTo(a.CellCount); return (num2 == 0) ? string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase) : num2; }); break; default: Filtered.Sort((PatternEntry a, PatternEntry b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase)); break; } } public static int SafeCellCount(Upgrade upgrade) { try { HexMap pattern = upgrade.GetPattern((UpgradeInstance)null, false); return (pattern != null) ? pattern.GetCellCount() : 0; } catch (Exception ex) { ManualLogSource log = UpgradeOptimizerPlugin.Log; if (log != null) { log.LogWarning((object)("Failed to read pattern for " + ((upgrade != null) ? upgrade.Name : null) + ": " + ex.Message)); } return 0; } } public static HexMap SafePattern(Upgrade upgrade) { try { return (upgrade != null) ? upgrade.GetPattern((UpgradeInstance)null, false) : null; } catch { return null; } } } public static class PatternPreview { private static Texture2D _pixel; private static Texture2D Pixel { get { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_pixel == (Object)null) { _pixel = new Texture2D(1, 1, (TextureFormat)4, false); _pixel.SetPixel(0, 0, Color.white); _pixel.Apply(); } return _pixel; } } public static void DrawHexMap(Rect area, HexMap map, Color cellColor, Color emptyColor) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) if (map == null || map.Width <= 0 || map.Height <= 0) { GUI.Label(area, "No pattern"); return; } float num = ((Rect)(ref area)).width / (float)map.Width; float num2 = ((Rect)(ref area)).height / (float)map.Height; float num3 = Mathf.Min(num, num2) * 0.85f; float num4 = num3 * (float)map.Width; float num5 = num3 * (float)map.Height; float num6 = ((Rect)(ref area)).x + (((Rect)(ref area)).width - num4) * 0.5f; float num7 = ((Rect)(ref area)).y + (((Rect)(ref area)).height - num5) * 0.5f; Color color = GUI.color; for (int i = 0; i < map.Height; i++) { for (int j = 0; j < map.Width; j++) { bool enabled = map[j, i].enabled; float num8 = num6 + (float)j * num3 + ((j % 2 == 1) ? (num3 * 0.15f) : 0f); float num9 = num7 + (float)i * num3; GUI.color = (enabled ? cellColor : emptyColor); GUI.DrawTexture(new Rect(num8, num9, num3 * 0.9f, num3 * 0.9f), (Texture)(object)Pixel); } } GUI.color = color; } public static void DrawSideBySide(Rect area, HexMap current, HexMap selected, Color currentColor, Color selectedColor) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) float num = 8f; float num2 = (((Rect)(ref area)).width - num) * 0.5f; Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref area)).x, ((Rect)(ref area)).y, num2, ((Rect)(ref area)).height); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref area)).x + num2 + num, ((Rect)(ref area)).y, num2, ((Rect)(ref area)).height); GUI.Box(val, GUIContent.none); GUI.Box(val2, GUIContent.none); GUI.Label(new Rect(((Rect)(ref val)).x + 4f, ((Rect)(ref val)).y + 2f, ((Rect)(ref val)).width - 8f, 18f), "Current"); GUI.Label(new Rect(((Rect)(ref val2)).x + 4f, ((Rect)(ref val2)).y + 2f, ((Rect)(ref val2)).width - 8f, 18f), "Selected"); DrawHexMap(new Rect(((Rect)(ref val)).x + 4f, ((Rect)(ref val)).y + 20f, ((Rect)(ref val)).width - 8f, ((Rect)(ref val)).height - 24f), current, currentColor, new Color(1f, 1f, 1f, 0.08f)); DrawHexMap(new Rect(((Rect)(ref val2)).x + 4f, ((Rect)(ref val2)).y + 20f, ((Rect)(ref val2)).width - 8f, ((Rect)(ref val2)).height - 24f), selected, selectedColor, new Color(1f, 1f, 1f, 0.08f)); } } [BepInPlugin("sparroh.upgradeoptimizer", "UpgradeOptimizer", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [MycoMod(/*Could not decode attribute arguments.*/)] public class UpgradeOptimizerPlugin : BaseUnityPlugin { public const string PluginGUID = "sparroh.upgradeoptimizer"; public const string PluginName = "UpgradeOptimizer"; public const string PluginVersion = "1.0.0"; internal const bool SparrohMode = false; internal static ConfigEntry EnableBoost; internal static ConfigEntry EnablePatternBrowser; internal static ConfigEntry EnableMaxRolls; internal static ConfigEntry BoostHotkey; internal static ConfigEntry PatternBrowserHotkey; private Harmony _harmony; private FileSystemWatcher _configWatcher; private volatile bool _configReloadPending; private float _configReloadAt = -1f; internal static ManualLogSource Log { get; private set; } internal static UpgradeInstance HoveredUpgrade { get; private set; } private void Awake() { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; EnableBoost = ((BaseUnityPlugin)this).Config.Bind("Features", "EnableBoost", true, "Enable free boost/turbocharge toggle on hovered upgrades."); EnablePatternBrowser = ((BaseUnityPlugin)this).Config.Bind("Features", "EnablePatternBrowser", true, "Enable the freeform pattern browser for override infusion."); EnableMaxRolls = ((BaseUnityPlugin)this).Config.Bind("Features", "EnableMaxRolls", true, "Force turbocharged upgrades to always roll best property values."); BoostHotkey = ((BaseUnityPlugin)this).Config.Bind("Hotkeys", "BoostHotkey", (Key)29, "Hotkey that toggles boost/turbocharge on the currently hovered upgrade."); PatternBrowserHotkey = ((BaseUnityPlugin)this).Config.Bind("Hotkeys", "PatternBrowserHotkey", (Key)30, "Hotkey that opens/closes the pattern browser on the currently hovered upgrade."); _harmony = new Harmony("sparroh.upgradeoptimizer"); _harmony.PatchAll(); ((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged; SetupConfigWatcher(); Log.LogInfo((object)("UpgradeOptimizer v1.0.0 loaded. " + $"Boost={EnableBoost.Value} ({BoostHotkey.Value}), " + $"Patterns={EnablePatternBrowser.Value} ({PatternBrowserHotkey.Value}), " + $"MaxRolls={EnableMaxRolls.Value}")); } private void OnDestroy() { ((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged; TeardownConfigWatcher(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) try { ProcessPendingConfigReload(); Keyboard current = Keyboard.current; if (current == null) { return; } UpdateHoveredUpgrade(); if (IsTypingInSearchField()) { if (EnablePatternBrowser.Value && PatternBrowser.IsOpen && WasHotkeyPressed(current, (Key)60)) { PatternBrowser.Close(); } return; } if (EnableBoost.Value) { BoostFeature.TryHandleHotkey(current, BoostHotkey.Value); } if (EnablePatternBrowser.Value) { HandlePatternBrowserHotkeys(current); } } catch (Exception ex) { Log.LogError((object)("Update error: " + ex)); } } private void OnGUI() { if (!EnablePatternBrowser.Value) { return; } try { PatternBrowser.Draw(); } catch (Exception ex) { Log.LogError((object)("OnGUI error: " + ex)); } } private void OnSettingChanged(object sender, SettingChangedEventArgs e) { if (e.ChangedSetting != null) { if ((object)e.ChangedSetting == EnablePatternBrowser && !EnablePatternBrowser.Value && PatternBrowser.IsOpen) { PatternBrowser.Close(); } Log.LogInfo((object)$"Config updated: [{e.ChangedSetting.Definition.Section}] {e.ChangedSetting.Definition.Key} = {e.ChangedSetting.BoxedValue}"); } } private void SetupConfigWatcher() { try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; if (string.IsNullOrEmpty(configFilePath)) { return; } string directoryName = Path.GetDirectoryName(configFilePath); string fileName = Path.GetFileName(configFilePath); if (!string.IsNullOrEmpty(directoryName) && !string.IsNullOrEmpty(fileName)) { if (!File.Exists(configFilePath)) { ((BaseUnityPlugin)this).Config.Save(); } _configWatcher = new FileSystemWatcher(directoryName, fileName) { NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite), EnableRaisingEvents = true }; _configWatcher.Changed += OnConfigFileChanged; _configWatcher.Created += OnConfigFileChanged; _configWatcher.Renamed += OnConfigFileChanged; Log.LogInfo((object)("Config hot-reload watching: " + configFilePath)); } } catch (Exception ex) { Log.LogWarning((object)("Config file watcher unavailable: " + ex.Message)); } } private void TeardownConfigWatcher() { if (_configWatcher != null) { try { _configWatcher.EnableRaisingEvents = false; _configWatcher.Changed -= OnConfigFileChanged; _configWatcher.Created -= OnConfigFileChanged; _configWatcher.Renamed -= OnConfigFileChanged; _configWatcher.Dispose(); } catch { } _configWatcher = null; } } private void OnConfigFileChanged(object sender, FileSystemEventArgs e) { _configReloadPending = true; } private void ProcessPendingConfigReload() { if (_configReloadPending) { _configReloadPending = false; _configReloadAt = Time.unscaledTime + 0.25f; } if (_configReloadAt < 0f || Time.unscaledTime < _configReloadAt) { return; } _configReloadAt = -1f; try { ((BaseUnityPlugin)this).Config.Reload(); Log.LogInfo((object)"Config reloaded from disk."); } catch (Exception ex) { Log.LogWarning((object)("Config reload failed: " + ex.Message)); } } private static void HandlePatternBrowserHotkeys(Keyboard keyboard) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (WasHotkeyPressed(keyboard, (Key)60) && PatternBrowser.IsOpen) { PatternBrowser.Close(); } else if (WasHotkeyPressed(keyboard, PatternBrowserHotkey.Value)) { if (PatternBrowser.IsOpen) { PatternBrowser.Close(); } else if (HoveredUpgrade != null && HoveredUpgrade.IsUnlocked) { PatternBrowser.Open(HoveredUpgrade); } } } private static void UpdateHoveredUpgrade() { if ((Object)(object)HoverInfoDisplay.Instance != (Object)null) { HoverInfo selectedInfo = HoverInfoDisplay.Instance.SelectedInfo; HoverInfoUpgrade val = (HoverInfoUpgrade)(object)((selectedInfo is HoverInfoUpgrade) ? selectedInfo : null); if (val != null && val.Upgrade != null) { HoveredUpgrade = val.Upgrade; return; } } GearUpgradeUI val2 = default(GearUpgradeUI); UpgradeIcon val3 = default(UpgradeIcon); if (UIRaycaster.RaycastForComponent(ref val2) && (Object)(object)val2 != (Object)null && ((HoverInfoUpgrade)val2).Upgrade != null) { HoveredUpgrade = ((HoverInfoUpgrade)val2).Upgrade; } else if (UIRaycaster.RaycastForComponent(ref val3) && (Object)(object)val3 != (Object)null && ((HoverInfoUpgrade)val3).Upgrade != null) { HoveredUpgrade = ((HoverInfoUpgrade)val3).Upgrade; } else { HoveredUpgrade = null; } } internal static bool WasHotkeyPressed(Keyboard keyboard, Key key) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) try { return ((ButtonControl)keyboard[key]).wasPressedThisFrame; } catch { return false; } } internal static bool IsTypingInSearchField() { EventSystem current = EventSystem.current; GameObject val = ((current != null) ? current.currentSelectedGameObject : null); if ((Object)(object)val != (Object)null) { return (Object)(object)val.GetComponent() != (Object)null; } return false; } } namespace UpgradeOptimizer { public static class MyPluginInfo { public const string PLUGIN_GUID = "UpgradeOptimizer"; public const string PLUGIN_NAME = "UpgradeOptimizer"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }