using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; 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.Movement; using Sparroh.UI; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Sparroh")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.2.2.0")] [assembly: AssemblyInformationalVersion("1.2.2")] [assembly: AssemblyProduct("LoadoutImprovements")] [assembly: AssemblyTitle("LoadoutImprovements")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.2.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; } } } public static class ConfigManager { private const float DebounceSeconds = 0.25f; private static ConfigFile config; private static ManualLogSource logger; private static FileSystemWatcher configWatcher; private static volatile bool reloadPending; private static float lastReloadTime; public static ConfigEntry ScrollLeftKey { get; private set; } public static ConfigEntry ScrollRightKey { get; private set; } public static ConfigEntry RenameKey { get; private set; } public static ConfigEntry EnableTextMode { get; private set; } public static void Initialize(ConfigFile configFile, ManualLogSource log) { config = configFile; logger = log; ScrollLeftKey = config.Bind("Keybinds", "Scroll Loadout Left", (Key)7, "Key to scroll to the left loadout page"); ScrollRightKey = config.Bind("Keybinds", "Scroll Loadout Right", (Key)8, "Key to scroll to the right loadout page"); RenameKey = config.Bind("Keybinds", "Rename Loadout", (Key)32, "Key to rename the hovered loadout"); EnableTextMode = config.Bind("General", "Loadout Preview", true, "If true, show upgrade list on hover"); ApplyToMods(); ScrollLeftKey.SettingChanged += OnSettingChanged; ScrollRightKey.SettingChanged += OnSettingChanged; RenameKey.SettingChanged += OnSettingChanged; EnableTextMode.SettingChanged += OnTextModeChanged; try { SetupFileWatcher(); } catch (Exception ex) { logger.LogError((object)("Error setting up config file watcher: " + ex.Message)); } } public static void Tick() { if (!reloadPending || Time.unscaledTime - lastReloadTime < 0.25f) { return; } reloadPending = false; lastReloadTime = Time.unscaledTime; try { config.Reload(); ApplyToMods(); LoadoutPreviewMod.UpdatePreviewMode(); logger.LogInfo((object)"Config reloaded from disk."); } catch (Exception ex) { logger.LogError((object)("Error reloading config: " + ex.Message)); } } public static void Dispose() { if (ScrollLeftKey != null) { ScrollLeftKey.SettingChanged -= OnSettingChanged; } if (ScrollRightKey != null) { ScrollRightKey.SettingChanged -= OnSettingChanged; } if (RenameKey != null) { RenameKey.SettingChanged -= OnSettingChanged; } if (EnableTextMode != null) { EnableTextMode.SettingChanged -= OnTextModeChanged; } if (configWatcher != null) { configWatcher.EnableRaisingEvents = false; configWatcher.Changed -= OnConfigFileChanged; configWatcher.Created -= OnConfigFileChanged; configWatcher.Renamed -= OnConfigFileChanged; configWatcher.Dispose(); configWatcher = null; } } private static void ApplyToMods() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (ScrollLeftKey != null) { LoadoutExpanderMod.ScrollLeftKey = ScrollLeftKey.Value; } if (ScrollRightKey != null) { LoadoutExpanderMod.ScrollRightKey = ScrollRightKey.Value; } if (RenameKey != null) { LoadoutHoverInfoPatches.RenameKey = RenameKey.Value; } if (EnableTextMode != null) { LoadoutPreviewMod.enableTextMode = EnableTextMode; } } private static void SetupFileWatcher() { configWatcher = new FileSystemWatcher(Paths.ConfigPath, "sparroh.loadoutimprovements.cfg"); configWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite; configWatcher.Changed += OnConfigFileChanged; configWatcher.Created += OnConfigFileChanged; configWatcher.Renamed += OnConfigFileChanged; configWatcher.EnableRaisingEvents = true; logger.LogInfo((object)"Config hot reload enabled for sparroh.loadoutimprovements.cfg"); } private static void OnConfigFileChanged(object sender, FileSystemEventArgs e) { reloadPending = true; } private static void OnSettingChanged(object sender, EventArgs e) { ApplyToMods(); } private static void OnTextModeChanged(object sender, EventArgs e) { ApplyToMods(); LoadoutPreviewMod.OnConfigChanged(); } } public static class LoadoutExpanderMod { public static int PageOffset; internal static FieldInfo _loadoutButtonsField; internal static FieldInfo _upgradableField; internal static MethodInfo _updateIconMethod; public static Key ScrollLeftKey; public static Key ScrollRightKey; public static void TogglePage() { PageOffset += 3; if (PageOffset > 6) { PageOffset = 0; } RefreshCurrentWindow(); } public static void ScrollRight() { PageOffset += 3; if (PageOffset > 6) { PageOffset = 0; } RefreshCurrentWindow(); } public static void ScrollLeft() { PageOffset -= 3; if (PageOffset < 0) { PageOffset = 6; } RefreshCurrentWindow(); } public static void RefreshCurrentWindow() { try { GearDetailsWindow[] array = Resources.FindObjectsOfTypeAll(); foreach (GearDetailsWindow val in array) { if (((Component)val).gameObject.activeInHierarchy && _loadoutButtonsField != null && _updateIconMethod != null && _loadoutButtonsField.GetValue(val) is Array array2) { int num = Mathf.Min(array2.Length, 3); for (int j = 0; j < num; j++) { object value = array2.GetValue(j); _updateIconMethod.Invoke(val, new object[2] { value, j }); } } } } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error refreshing window: " + ex.Message)); } } } [HarmonyPatch] public static class GearDetailsWindowPatches { [HarmonyPatch(typeof(GearDetailsWindow), "Setup")] [HarmonyPostfix] public static void SetupPostfix(ref GearDetailsWindow __instance, IUpgradable upgradable) { LoadoutExpanderMod.PageOffset = 0; LoadoutExpanderMod.RefreshCurrentWindow(); try { Type typeFromHandle = typeof(PlayerData); object obj = typeFromHandle.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); object obj2 = typeFromHandle.GetMethod("GetGearData", new Type[1] { typeof(IUpgradable) })?.Invoke(obj, new object[1] { upgradable }); if (obj2 != null) { FieldInfo field = obj2.GetType().GetField("loadouts", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { Array array = field.GetValue(obj2) as Array; Type nestedType = typeFromHandle.GetNestedType("Loadout", BindingFlags.NonPublic); if (array == null || array.Length < 9) { Array array2 = Array.CreateInstance(nestedType, 9); array?.CopyTo(array2, 0); field.SetValue(obj2, array2); } } } } catch (Exception) { } FieldInfo field2 = ((object)__instance).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic); if (field2 != null && field2.GetValue(__instance) is Array { Length: var length } array3) { for (int i = 0; i < Mathf.Min(9, length); i++) { object value = array3.GetValue(i); if (value != null) { object obj3 = value.GetType().GetProperty("gameObject")?.GetValue(value); obj3?.GetType().GetMethod("SetActive")?.Invoke(obj3, new object[1] { true }); } } } try { if (upgradable == null) { return; } Type? typeFromHandle2 = typeof(PlayerData); object obj4 = typeFromHandle2.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); object obj5 = typeFromHandle2.GetMethod("GetGearData", new Type[1] { typeof(IUpgradable) })?.Invoke(obj4, new object[1] { upgradable }); if (obj5 == null) { return; } object? obj6 = obj5.GetType().GetField("gear", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj5); IUpgradable val = (IUpgradable)((obj6 is IUpgradable) ? obj6 : null); if (val == null) { return; } if (!LoadoutHoverInfoPatches.windowLoadoutNames.TryGetValue(__instance, out var value2)) { value2 = new Dictionary(); LoadoutHoverInfoPatches.windowLoadoutNames[__instance] = value2; } for (int j = 0; j < 9; j++) { string text = $"{val.Info.ID}_{j}"; string value3 = PlayerPrefs.GetString("LoadoutName_" + text, ""); if (!string.IsNullOrEmpty(value3)) { value2[j] = value3; } } } catch (Exception) { } } } [HarmonyPatch(typeof(GearDetailsWindow), "UpdateLoadoutIcon")] public static class UpdateIconPatch { [HarmonyPrefix] public static void Prefix(ref int index) { if (index < 3) { index += LoadoutExpanderMod.PageOffset; } } } [HarmonyPatch(typeof(GearData), "EquipLoadout")] public static class EquipLoadoutPatch { [HarmonyPrefix] public static void Prefix(ref int index) { if (index < 3) { index += LoadoutExpanderMod.PageOffset; } } } [HarmonyPatch(typeof(GearData), "IncrementLoadoutIcon")] public static class IncrementIconPatch { [HarmonyPrefix] public static void Prefix(ref int index) { if (index < 3) { index += LoadoutExpanderMod.PageOffset; } } } [HarmonyPatch(typeof(GearData), "SaveLoadout")] public static class SaveLoadoutPatch { [HarmonyPrefix] public static void Prefix(ref int index) { if (index < 3) { index += LoadoutExpanderMod.PageOffset; } } } [HarmonyPatch] public static class LoadoutHighlightMod { private readonly struct EquipKey : IComparable, IEquatable { public readonly int UpgradeId; public readonly sbyte X; public readonly sbyte Y; public readonly byte Rotation; public EquipKey(int upgradeId, sbyte x, sbyte y, byte rotation) { UpgradeId = upgradeId; X = x; Y = y; Rotation = rotation; } public int CompareTo(EquipKey other) { int num = UpgradeId.CompareTo(other.UpgradeId); if (num != 0) { return num; } num = X.CompareTo(other.X); if (num != 0) { return num; } num = Y.CompareTo(other.Y); if (num != 0) { return num; } return Rotation.CompareTo(other.Rotation); } public bool Equals(EquipKey other) { if (UpgradeId == other.UpgradeId && X == other.X && Y == other.Y) { return Rotation == other.Rotation; } return false; } public override bool Equals(object obj) { if (obj is EquipKey other) { return Equals(other); } return false; } public override int GetHashCode() { return (((((UpgradeId * 397) ^ X) * 397) ^ Y) * 397) ^ Rotation; } } private static readonly Color MatchedIconColor = Color.black; private static readonly Color DefaultIconColor = Color.white; private static readonly FieldInfo LoadoutsField = AccessTools.Field(typeof(GearData), "loadouts"); private static readonly FieldInfo EquippedUpgradesField = AccessTools.Field(typeof(GearData), "equippedUpgrades"); private static readonly Type LoadoutType = typeof(PlayerData).GetNestedType("Loadout", BindingFlags.NonPublic); private static readonly FieldInfo LoadoutUpgradesField = LoadoutType?.GetField("upgrades", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly Dictionary OriginalIconColors = new Dictionary(); private static readonly Dictionary OriginalFillColors = new Dictionary(); private static readonly bool[] CachedMatch = new bool[3]; private static GearDetailsWindow CachedWindow; private static int CachedPageOffset = int.MinValue; private static int CachedEquippedHash; private static int CachedLoadoutHash; [HarmonyPatch(typeof(GearDetailsWindow), "UpdateLoadoutIcon")] [HarmonyPostfix] [HarmonyPriority(0)] public static void UpdateLoadoutIconPostfix(GearDetailsWindow __instance, LoadoutHoverInfo button, int index) { try { InvalidateCache(); ApplyHighlight(__instance, button, index); } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)("LoadoutHighlight UpdateLoadoutIcon failed: " + ex.Message)); } } } [HarmonyPatch(typeof(GearDetailsWindow), "Setup")] [HarmonyPostfix] [HarmonyPriority(0)] public static void SetupPostfix(GearDetailsWindow __instance) { try { InvalidateCache(); RefreshAll(__instance); } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)("LoadoutHighlight Setup failed: " + ex.Message)); } } } [HarmonyPatch(typeof(GearDetailsWindow), "SetupUpgrades")] [HarmonyPostfix] public static void SetupUpgradesPostfix(GearDetailsWindow __instance) { try { InvalidateCache(); RefreshAll(__instance); } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)("LoadoutHighlight SetupUpgrades failed: " + ex.Message)); } } } [HarmonyPatch(typeof(GearDetailsWindow), "EquipLoadout")] [HarmonyPostfix] public static void EquipLoadoutPostfix(GearDetailsWindow __instance) { try { InvalidateCache(); RefreshAll(__instance); } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)("LoadoutHighlight EquipLoadout failed: " + ex.Message)); } } } [HarmonyPatch(typeof(GearDetailsWindow), "SaveLoadout")] [HarmonyPostfix] public static void SaveLoadoutPostfix(GearDetailsWindow __instance) { try { InvalidateCache(); RefreshAll(__instance); } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)("LoadoutHighlight SaveLoadout failed: " + ex.Message)); } } } [HarmonyPatch(typeof(GearDetailsWindow), "Update")] [HarmonyPostfix] [HarmonyPriority(0)] public static void UpdatePostfix(GearDetailsWindow __instance) { try { if (!((Object)(object)__instance == (Object)null) && ((Component)__instance).gameObject.activeInHierarchy) { EnsureMatchCache(__instance); ApplyCachedColors(__instance); } } catch (Exception ex) { ManualLogSource logger = SparrohPlugin.Logger; if (logger != null) { logger.LogError((object)("LoadoutHighlight Update failed: " + ex.Message)); } } } private static void InvalidateCache() { CachedWindow = null; CachedPageOffset = int.MinValue; CachedEquippedHash = 0; CachedLoadoutHash = 0; for (int i = 0; i < CachedMatch.Length; i++) { CachedMatch[i] = false; } } public static void RefreshAll(GearDetailsWindow window) { if (!((Object)(object)window == (Object)null)) { EnsureMatchCache(window); ApplyCachedColors(window); } } private static void EnsureMatchCache(GearDetailsWindow window) { int pageOffset = LoadoutExpanderMod.PageOffset; int num = 0; int num2 = 0; try { IUpgradable upgradablePrefab = window.UpgradablePrefab; if (upgradablePrefab != null) { GearData gearData = PlayerData.GetGearData(upgradablePrefab); num = ComputeEquippedHash(gearData); num2 = ComputeLoadoutsHash(gearData); } } catch { } if (!((Object)(object)CachedWindow != (Object)(object)window) && CachedPageOffset == pageOffset && CachedEquippedHash == num && CachedLoadoutHash == num2) { return; } CachedWindow = window; CachedPageOffset = pageOffset; CachedEquippedHash = num; CachedLoadoutHash = num2; Array loadoutButtons = GetLoadoutButtons(window); if (loadoutButtons == null) { for (int i = 0; i < CachedMatch.Length; i++) { CachedMatch[i] = false; } return; } IUpgradable upgradablePrefab2 = window.UpgradablePrefab; GearData gearData2 = ((upgradablePrefab2 != null) ? PlayerData.GetGearData(upgradablePrefab2) : null); int num3 = Mathf.Min(loadoutButtons.Length, 3); for (int j = 0; j < CachedMatch.Length; j++) { if (j < num3 && loadoutButtons.GetValue(j) is LoadoutHoverInfo) { int loadoutIndex = j + pageOffset; CachedMatch[j] = LoadoutMatchesEquipped(gearData2, loadoutIndex); } else { CachedMatch[j] = false; } } } private static void ApplyCachedColors(GearDetailsWindow window) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_017a: 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_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0145: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) Array loadoutButtons = GetLoadoutButtons(window); if (loadoutButtons == null) { return; } Color playerUIColor = GetPlayerUIColor(); int num = Mathf.Min(loadoutButtons.Length, 3); for (int i = 0; i < num; i++) { object? value = loadoutButtons.GetValue(i); LoadoutHoverInfo val = (LoadoutHoverInfo)((value is LoadoutHoverInfo) ? value : null); if (val == null || (Object)(object)val == (Object)null) { continue; } Image iconImage = GetIconImage(val); Graphic fillGraphic = GetFillGraphic(val, iconImage); bool flag = CachedMatch[i]; if ((Object)(object)iconImage != (Object)null && ((Component)iconImage).gameObject.activeSelf) { int instanceID = ((Object)iconImage).GetInstanceID(); if (!OriginalIconColors.ContainsKey(instanceID)) { Color color = ((Graphic)iconImage).color; OriginalIconColors[instanceID] = (IsMatchedIconColor(color) ? DefaultIconColor : ((color.a > 0f) ? color : DefaultIconColor)); } Color val2 = (flag ? MatchedIconColor : OriginalIconColors[instanceID]); if (!ColorsApproximatelyEqual(((Graphic)iconImage).color, val2)) { ((Graphic)iconImage).color = val2; } } if ((Object)(object)fillGraphic != (Object)null) { int instanceID2 = ((Object)fillGraphic).GetInstanceID(); if (!OriginalFillColors.ContainsKey(instanceID2)) { Color color2 = fillGraphic.color; OriginalFillColors[instanceID2] = (IsLikelyHighlightFill(color2, playerUIColor) ? Color.white : ((color2.a > 0f) ? color2 : Color.white)); } Color val3 = (flag ? playerUIColor : OriginalFillColors[instanceID2]); if (flag) { Color val4 = OriginalFillColors[instanceID2]; ((Color)(ref val3))..ctor(playerUIColor.r, playerUIColor.g, playerUIColor.b, (val4.a > 0f) ? val4.a : 1f); } if (!ColorsApproximatelyEqual(fillGraphic.color, val3)) { fillGraphic.color = val3; } } } } private static void ApplyHighlight(GearDetailsWindow window, LoadoutHoverInfo button, int realIndex) { if (!((Object)(object)button == (Object)null) && !((Object)(object)window == (Object)null)) { EnsureMatchCache(window); ApplyCachedColors(window); } } private static Array GetLoadoutButtons(GearDetailsWindow window) { Array array = null; if (LoadoutExpanderMod._loadoutButtonsField != null) { array = LoadoutExpanderMod._loadoutButtonsField.GetValue(window) as Array; } if (array == null) { array = AccessTools.Field(typeof(GearDetailsWindow), "loadoutButtons")?.GetValue(window) as Array; } return array; } private static Image GetIconImage(LoadoutHoverInfo button) { Transform transform = ((Component)button).transform; if (transform.childCount > 1) { Image component = ((Component)transform.GetChild(1)).GetComponent(); if ((Object)(object)component != (Object)null) { return component; } } Image[] componentsInChildren = ((Component)button).GetComponentsInChildren(true); if (componentsInChildren != null && componentsInChildren.Length > 1) { return componentsInChildren[1]; } if (componentsInChildren != null && componentsInChildren.Length == 1) { return componentsInChildren[0]; } return null; } private static Graphic GetFillGraphic(LoadoutHoverInfo button, Image icon) { if ((Object)(object)button == (Object)null) { return null; } Transform transform = ((Component)button).transform; if (transform.childCount > 0) { Graphic component = ((Component)transform.GetChild(0)).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component != (Object)(object)icon) { return component; } } Graphic component2 = ((Component)button).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2 != (Object)(object)icon) { return component2; } Image[] componentsInChildren = ((Component)button).GetComponentsInChildren(true); if (componentsInChildren != null) { for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null && (Object)(object)componentsInChildren[i] != (Object)(object)icon) { return (Graphic)(object)componentsInChildren[i]; } } } return null; } private static Color GetPlayerUIColor() { //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_0009: 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_0011: Unknown result type (might be due to invalid IL or missing references) try { return Global.UIColor; } catch { return Color.white; } } private static bool IsMatchedIconColor(Color c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return ColorsApproximatelyEqual(c, MatchedIconColor); } private static bool IsLikelyHighlightFill(Color current, Color uiColor) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (Mathf.Abs(current.r - uiColor.r) < 0.01f && Mathf.Abs(current.g - uiColor.g) < 0.01f) { return Mathf.Abs(current.b - uiColor.b) < 0.01f; } return false; } private static bool ColorsApproximatelyEqual(Color a, Color b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (Mathf.Abs(a.r - b.r) < 0.01f && Mathf.Abs(a.g - b.g) < 0.01f && Mathf.Abs(a.b - b.b) < 0.01f) { return Mathf.Abs(a.a - b.a) < 0.01f; } return false; } private static int ComputeEquippedHash(GearData gearData) { if (gearData == null || EquippedUpgradesField == null) { return 0; } if (!(EquippedUpgradesField.GetValue(gearData) is IList { Count: not 0 } list)) { return 0; } int num = 17; num = num * 31 + list.Count; List list2 = ToSortedKeys(list); for (int i = 0; i < list2.Count; i++) { num = num * 31 + list2[i].GetHashCode(); } return num; } private static int ComputeLoadoutsHash(GearData gearData) { if (gearData == null || LoadoutsField == null || LoadoutUpgradesField == null) { return 0; } if (!(LoadoutsField.GetValue(gearData) is Array array)) { return 0; } int num = 17; num = num * 31 + array.Length; int num2 = Mathf.Min(array.Length, 9); for (int i = 0; i < num2; i++) { object value = array.GetValue(i); if (value == null) { num *= 31; continue; } if (!(LoadoutUpgradesField.GetValue(value) is IList list)) { num *= 31; continue; } num = num * 31 + list.Count; List list2 = ToSortedKeys(list); for (int j = 0; j < list2.Count; j++) { num = num * 31 + list2[j].GetHashCode(); } } return num; } private static bool LoadoutMatchesEquipped(GearData gearData, int loadoutIndex) { if (gearData == null || LoadoutsField == null || EquippedUpgradesField == null || LoadoutUpgradesField == null) { return false; } if (!(EquippedUpgradesField.GetValue(gearData) is IList { Count: not 0 } list)) { return false; } if (!(LoadoutsField.GetValue(gearData) is Array array) || loadoutIndex < 0 || loadoutIndex >= array.Length) { return false; } object value = array.GetValue(loadoutIndex); if (value == null) { return false; } if (!(LoadoutUpgradesField.GetValue(value) is IList { Count: not 0 } list2)) { return false; } if (list2.Count != list.Count) { return false; } List list3 = ToSortedKeys(list); List list4 = ToSortedKeys(list2); if (list3.Count != list4.Count || list3.Count == 0) { return false; } for (int i = 0; i < list3.Count; i++) { if (!list3[i].Equals(list4[i])) { return false; } } return true; } private static List ToSortedKeys(IList list) { //IL_002a: 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_0031: 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) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) List list2 = new List(list.Count); for (int i = 0; i < list.Count; i++) { object obj = list[i]; if (obj == null) { continue; } if (obj is UpgradeEquipData val) { list2.Add(new EquipKey(val.upgradeID, val.x, val.y, val.rotation)); continue; } try { Type type = obj.GetType(); int upgradeId = Convert.ToInt32(AccessTools.Field(type, "upgradeID")?.GetValue(obj) ?? ((object)0)); sbyte x = Convert.ToSByte(AccessTools.Field(type, "x")?.GetValue(obj) ?? ((object)(sbyte)0)); sbyte y = Convert.ToSByte(AccessTools.Field(type, "y")?.GetValue(obj) ?? ((object)(sbyte)0)); byte rotation = Convert.ToByte(AccessTools.Field(type, "rotation")?.GetValue(obj) ?? ((object)(byte)0)); list2.Add(new EquipKey(upgradeId, x, y, rotation)); } catch { } } list2.Sort(); return list2; } } [HarmonyPatch] public static class LoadoutIconsPatches { private static readonly Type LoadoutType = typeof(PlayerData).GetNestedType("Loadout", BindingFlags.NonPublic); private static readonly Type UpgradeEquipDataType = typeof(UpgradeEquipData); private static readonly FieldInfo LoadoutUpgradesField = LoadoutType?.GetField("upgrades", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo LoadoutIconIndexField = LoadoutType?.GetField("iconIndex", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); [HarmonyPatch(typeof(GearData), "IncrementLoadoutIcon")] [HarmonyPrefix] [HarmonyPriority(0)] public static bool IncrementLoadoutIconPrefix(int index, ref object ___loadouts, ref bool __result) { try { if (LoadoutType == null || LoadoutIconIndexField == null) { SparrohPlugin.Logger.LogError((object)"IncrementLoadoutIcon: Loadout type/fields not resolved."); __result = false; return false; } LoadoutSlotsPatches.EnsureLoadoutsCapacity(ref ___loadouts, index); Array array = ___loadouts as Array; if (index < 0 || array == null) { __result = false; return false; } object value = array.GetValue(index); IList list = LoadoutUpgradesField?.GetValue(value) as IList; if (list == null) { list = Activator.CreateInstance(typeof(List<>).MakeGenericType(UpgradeEquipDataType), 8) as IList; LoadoutUpgradesField?.SetValue(value, list); } int count = list.Count; int num = (((Object)(object)Global.Instance != (Object)null && Global.Instance.LoadoutIcons != null) ? Global.Instance.LoadoutIcons.Length : 0); int num2 = Mathf.Max(1, count + num); int num3 = (((LoadoutIconIndexField.GetValue(value) is int num4) ? num4 : 0) + 1) % num2; LoadoutIconIndexField.SetValue(value, num3); array.SetValue(value, index); __result = true; return false; } catch (Exception arg) { SparrohPlugin.Logger.LogError((object)$"IncrementLoadoutIcon failed: {arg}"); __result = false; return false; } } [HarmonyPatch(typeof(GearData), "GetLoadoutIcon")] [HarmonyPostfix] public static void GetLoadoutIconPostfix(int index, ref object ___loadouts, ref Sprite __result) { try { if (LoadoutType == null || LoadoutUpgradesField == null || LoadoutIconIndexField == null || !(___loadouts is Array array) || index < 0 || index >= array.Length) { return; } object value = array.GetValue(index); if (!(LoadoutUpgradesField.GetValue(value) is IList { Count: not 0, Count: var count } list)) { return; } int num = ((LoadoutIconIndexField.GetValue(value) is int num2) ? num2 : 0); if (num < count) { Sprite upgradeIconFromEquipData = GetUpgradeIconFromEquipData(list[num]); if ((Object)(object)upgradeIconFromEquipData != (Object)null) { __result = upgradeIconFromEquipData; return; } } if (Global.Instance?.LoadoutIcons != null) { int num3 = num - count; if (num3 < 0) { num3 = 0; } Sprite[] loadoutIcons = Global.Instance.LoadoutIcons; if (num3 >= 0 && num3 < loadoutIcons.Length) { __result = loadoutIcons[num3]; } else if (loadoutIcons.Length != 0) { __result = loadoutIcons[Mathf.Min(num, loadoutIcons.Length - 1)]; } } } catch (Exception arg) { SparrohPlugin.Logger.LogError((object)$"GetLoadoutIcon postfix failed: {arg}"); } } private static Sprite GetUpgradeIconFromEquipData(object equipData) { //IL_000f: 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) if (equipData == null) { return null; } try { if (equipData is UpgradeEquipData val) { UpgradeInstance upgrade = ((UpgradeEquipData)(ref val)).GetUpgrade(); object result; if (upgrade == null) { result = null; } else { Upgrade upgrade2 = upgrade.Upgrade; result = ((upgrade2 != null) ? upgrade2.Icon : null); } return (Sprite)result; } object? obj = (UpgradeEquipDataType?.GetMethod("GetUpgrade", BindingFlags.Instance | BindingFlags.Public))?.Invoke(equipData, null); object? obj2 = ((obj is UpgradeInstance) ? obj : null); object result2; if (obj2 == null) { result2 = null; } else { Upgrade upgrade3 = ((UpgradeInstance)obj2).Upgrade; result2 = ((upgrade3 != null) ? upgrade3.Icon : null); } return (Sprite)result2; } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Failed to resolve upgrade icon: " + ex.Message)); return null; } } } [HarmonyPatch] public static class LoadoutPreviewMod { public class UpgradePlacement { public byte Rotation; public UpgradeInstance Upgrade; public int X; public int Y; } private static MonoBehaviour currentPreview; private static int lastHoveredIndex = -1; private static string currentPreviewType; private static readonly int yOffset = 0; internal static ConfigEntry enableTextMode; internal static string CurrentPreviewMode; public static void ApplyPatches(Harmony harmony) { try { Patch(harmony); } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Failed to apply LoadoutPreviewMod patches: " + ex.Message)); } } public static void OnConfigChanged() { try { UpdatePreviewMode(); } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error in LoadoutPreviewMod.OnConfigChanged: " + ex.Message)); } } public static void UpdatePreviewMode() { try { if (enableTextMode.Value) { CurrentPreviewMode = "text"; } else { CurrentPreviewMode = "disabled"; } } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error in LoadoutPreviewMod.UpdatePreviewMode: " + ex.Message)); } } public static void Destroy() { try { if ((Object)(object)currentPreview != (Object)null) { ((LoadoutTextPreview)(object)currentPreview).Hide(); currentPreview = null; } currentPreviewType = null; lastHoveredIndex = -1; } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error destroying LoadoutPreviewMod: " + ex.Message)); } } public static void Patch(Harmony harmony) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown harmony.Patch((MethodBase)AccessTools.Method(typeof(GearDetailsWindow), "OnOpen", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(LoadoutPreviewMod), "OnOpenPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(GearDetailsWindow), "OnCloseCallback", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(LoadoutPreviewMod), "OnCloseCallbackPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(GearDetailsWindow), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(LoadoutPreviewMod), "UpdatePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } [HarmonyPatch(typeof(GearDetailsWindow), "OnOpen")] [HarmonyPostfix] public static void OnOpenPostfix(GearDetailsWindow __instance) { if (CurrentPreviewMode == "disabled") { currentPreview = null; currentPreviewType = "disabled"; lastHoveredIndex = -1; } else { currentPreview = (MonoBehaviour)(object)CreateTextPreview(__instance); currentPreviewType = CurrentPreviewMode; lastHoveredIndex = -1; } } private static LoadoutTextPreview CreateTextPreview(GearDetailsWindow window) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("LoadoutTextPreview"); val.transform.SetParent(((Component)window).transform, false); LoadoutTextPreview result = val.AddComponent(); val.GetComponent().anchoredPosition = new Vector2(10000f, 10000f); val.SetActive(false); return result; } [HarmonyPatch(typeof(GearDetailsWindow), "OnCloseCallback")] [HarmonyPostfix] public static void OnCloseCallbackPostfix() { if ((Object)(object)currentPreview != (Object)null) { ((LoadoutTextPreview)(object)currentPreview).Hide(); } currentPreviewType = null; lastHoveredIndex = -1; } [HarmonyPatch(typeof(GearDetailsWindow), "Update")] [HarmonyPostfix] public static void UpdatePostfix(GearDetailsWindow __instance) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) if (currentPreviewType != CurrentPreviewMode) { if ((Object)(object)currentPreview != (Object)null) { ((LoadoutTextPreview)(object)currentPreview).Hide(); currentPreview = null; } if (CurrentPreviewMode == "text") { currentPreview = (MonoBehaviour)(object)CreateTextPreview(__instance); } currentPreviewType = CurrentPreviewMode; } if ((Object)(object)currentPreview == (Object)null || !(Traverse.Create((object)__instance).Field("loadoutButtons").GetValue() is LoadoutHoverInfo[] array)) { return; } int num = -1; MenuActions menu = PlayerInput.Controls.Menu; Vector2 mousePos = ((MenuActions)(ref menu)).Point.ReadValue(); for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && IsButtonHovered(array[i], mousePos)) { num = i; break; } } if (num == lastHoveredIndex) { return; } if (lastHoveredIndex >= 0) { ((LoadoutTextPreview)(object)currentPreview).Hide(); } if (num >= 0) { List loadoutUpgradePlacements = GetLoadoutUpgradePlacements(__instance, num); if (loadoutUpgradePlacements.Count > 0) { int num2 = loadoutUpgradePlacements.Min((UpgradePlacement p) => p.Y); if (num2 < 0) { foreach (UpgradePlacement item in loadoutUpgradePlacements) { item.Y -= num2; } } Vector2 position = CalculatePreviewPosition(mousePos); ((LoadoutTextPreview)(object)currentPreview).Setup(loadoutUpgradePlacements); ((LoadoutTextPreview)(object)currentPreview).SetPosition(position); ((LoadoutTextPreview)(object)currentPreview).Show(); } } lastHoveredIndex = num; } private static bool IsButtonHovered(LoadoutHoverInfo button, Vector2 mousePos) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown PointerEventData val = new PointerEventData(EventSystem.current) { position = mousePos }; List list = new List(); EventSystem.current.RaycastAll(val, list); return list.Any((RaycastResult r) => (Object)(object)((RaycastResult)(ref r)).gameObject == (Object)(object)((Component)button).gameObject); } private static Vector2 CalculatePreviewPosition(Vector2 mousePos) { //IL_0016: 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_0029: Expected O, but got Unknown //IL_002a: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) Canvas componentInParent = ((Component)Menu.Instance).gameObject.GetComponentInParent(); Vector2 val = default(Vector2); RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)((Component)componentInParent).transform, mousePos, componentInParent.worldCamera, ref val); return val + new Vector2(500f, -250f); } private static List GetLoadoutUpgradePlacements(GearDetailsWindow window, int loadoutIndex) { //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Expected O, but got Unknown List list = new List(); try { object value = Traverse.Create((object)window).Property("UpgradablePrefab", (object[])null).GetValue(); if (value == null) { return list; } object value2 = typeof(PlayerData).GetProperty("Instance").GetValue(null); object obj = typeof(PlayerData).GetMethod("GetGearData", new Type[1] { typeof(IUpgradable) })?.Invoke(value2, new object[1] { value }); if (obj == null) { return list; } Array array = (Array)(obj.GetType().GetField("loadouts", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj)); if (array == null || loadoutIndex < 0 || loadoutIndex >= array.Length) { return list; } object value3 = array.GetValue(loadoutIndex); if (value3 == null) { return list; } object value4 = Traverse.Create(value3).Field("upgrades").GetValue(); if (value4 == null) { return list; } if (!(value4 is IList list2)) { return list; } for (int i = 0; i < list2.Count; i++) { object obj2 = list2[i]; if (obj2 != null) { UpgradeInstance val = (UpgradeInstance)Traverse.Create(obj2).Method("GetUpgrade", Array.Empty()).GetValue(); if (val != null) { UpgradePlacement upgradePlacement = new UpgradePlacement(); sbyte x = (sbyte)Traverse.Create(obj2).Field("x").GetValue(); sbyte b = (sbyte)Traverse.Create(obj2).Field("y").GetValue(); upgradePlacement.X = x; upgradePlacement.Y = b - yOffset; upgradePlacement.Rotation = (byte)Traverse.Create(obj2).Field("rotation").GetValue(); upgradePlacement.Upgrade = val; list.Add(upgradePlacement); } } } } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error getting loadout placements: " + ex.Message)); } return list; } } public class LoadoutRenameDialog : MonoBehaviour { private static LoadoutRenameDialog Instance; private UIInputField inputField; private Action onApplyCallback; private Action onCancelCallback; private UIWindow window; public static bool IsActive => (Object)(object)Instance != (Object)null; private void Update() { Keyboard current = Keyboard.current; if (current != null) { if (((ButtonControl)current.enterKey).wasPressedThisFrame || ((ButtonControl)current.numpadEnterKey).wasPressedThisFrame) { OnApplyClicked(); } else if (((ButtonControl)current.escapeKey).wasPressedThisFrame) { OnCancelClicked(); } } } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } public static void Show(Vector2 screenPosition, string currentName, Action onApply, Action onCancel, GearDetailsWindow targetWindow, int targetLoadoutIndex) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (IsActive) { Close(); } UITheme.Initialize(); UIWindow val = UIWindow.Create("LoadoutRename", (Vector2?)new Vector2(420f, 200f), "Rename Loadout", false, true, (int?)UITheme.DialogSortingOrder); GameObject val2 = new GameObject("LoadoutRenameDialogHost"); val2.transform.SetParent(((Component)val.Canvas).transform, false); LoadoutRenameDialog loadoutRenameDialog = val2.AddComponent(); loadoutRenameDialog.Initialize(val, currentName, onApply, onCancel); Instance = loadoutRenameDialog; } public static void Close() { if (!((Object)(object)Instance == (Object)null)) { LoadoutRenameDialog instance = Instance; Instance = null; instance.onApplyCallback = null; instance.onCancelCallback = null; UIWindow val = instance.window; instance.window = null; if (val != null) { val.Destroy(); } } } private void Initialize(UIWindow uiWindow, string currentName, Action onApply, Action onCancel) { //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Expected O, but got Unknown window = uiWindow; onApplyCallback = onApply; onCancelCallback = onCancel; window.OnClose((Action)OnCancelClicked); Transform content = window.Content; UIFactory.AddVerticalLayout(((Component)content).gameObject, UITheme.S(UITheme.SpacingNormal), UITheme.ScaledPadding(16, 16, 12, 12), (TextAnchor)4, true, false, true, true); inputField = UIInputField.Create(content, currentName ?? string.Empty, "Loadout name", (Action)null, "InputField"); GameObject gameObject = inputField.GameObject; float? num = UITheme.ScaledInputHeight + UITheme.S(4f); float? num2 = UITheme.ScaledInputHeight; UIHelpers.EnsureLayoutElement(gameObject, (float?)null, num, num2); RectTransform obj = UIFactory.CreateRect("Buttons", content); GameObject gameObject2 = ((Component)obj).gameObject; num2 = UITheme.ScaledButtonHeight + UITheme.S(8f); UIHelpers.EnsureLayoutElement(gameObject2, (float?)null, num2, (float?)null); UIFactory.AddHorizontalLayout(((Component)obj).gameObject, UITheme.S(12f), new RectOffset(0, 0, 0, 0), (TextAnchor)4, false, false, true, true); UIButton.Create((Transform)(object)obj, "Cancel", (Action)OnCancelClicked, (UIButtonStyle)0, (string)null, (float?)null).SetWidth(UITheme.S(120f)); UIButton.Create((Transform)(object)obj, "Apply", (Action)OnApplyClicked, (UIButtonStyle)1, (string)null, (float?)null).SetWidth(UITheme.S(120f)); ((MonoBehaviour)this).StartCoroutine(FocusInputNextFrame()); } private IEnumerator FocusInputNextFrame() { yield return null; FocusInput(reenable: true); yield return null; UIInputField obj = inputField; if ((Object)(object)((obj != null) ? obj.Input : null) != (Object)null && !inputField.Input.isFocused) { FocusInput(reenable: true); } } private void FocusInput(bool reenable = false) { UIInputField obj = inputField; if (!((Object)(object)((obj != null) ? obj.Input : null) == (Object)null)) { TMP_InputField input = inputField.Input; if (reenable) { ((Behaviour)input).enabled = false; ((Behaviour)input).enabled = true; } EventSystem current = EventSystem.current; if ((Object)(object)current != (Object)null) { current.SetSelectedGameObject(inputField.GameObject); } input.ActivateInputField(); ((Selectable)input).Select(); string text = inputField.Text ?? string.Empty; input.caretPosition = text.Length; input.selectionAnchorPosition = text.Length; input.selectionFocusPosition = text.Length; input.ForceLabelUpdate(); } } private void OnApplyClicked() { if (!((Object)(object)Instance != (Object)(object)this)) { UIInputField obj = inputField; string text = ((obj != null) ? obj.Text : null); Action action = onApplyCallback; onCancelCallback = null; onApplyCallback = null; if (!string.IsNullOrWhiteSpace(text)) { action?.Invoke(text); } Close(); } } private void OnCancelClicked() { if (!((Object)(object)Instance != (Object)(object)this)) { Action action = onCancelCallback; onCancelCallback = null; onApplyCallback = null; action?.Invoke(); Close(); } } } [HarmonyPatch] public static class LoadoutHoverInfoPatches { private static readonly Type LoadoutHoverInfoType = AccessTools.TypeByName("LoadoutHoverInfo"); private static bool isRenaming = false; private static string currentRenameValue = ""; private static LoadoutHoverInfo currentlyRenamingButton = null; private static readonly Dictionary loadoutNames = new Dictionary(); public static Key RenameKey = (Key)32; internal static readonly Dictionary> windowLoadoutNames = new Dictionary>(); private static string GetLoadoutName(GearDetailsWindow window, int loadoutIndex) { try { if (windowLoadoutNames.TryGetValue(window, out var value) && value.TryGetValue(loadoutIndex, out var value2) && !string.IsNullOrEmpty(value2)) { return value2; } object? obj = ((object)window).GetType().GetField("upgradable", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(window); IUpgradable val = (IUpgradable)((obj is IUpgradable) ? obj : null); if (val != null) { Type? typeFromHandle = typeof(PlayerData); object obj2 = typeFromHandle.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); object obj3 = typeFromHandle.GetMethod("GetGearData", new Type[1] { typeof(IUpgradable) })?.Invoke(obj2, new object[1] { val }); if (obj3 != null) { object? obj4 = obj3.GetType().GetField("gear", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj3); IUpgradable val2 = (IUpgradable)((obj4 is IUpgradable) ? obj4 : null); if (val2 != null) { string text = $"{val2.Info.ID}_{loadoutIndex}"; string text2 = PlayerPrefs.GetString("LoadoutName_" + text, ""); SparrohPlugin.Logger.LogInfo((object)$"Retrieving name for gear {val2.Info.ID} slot {loadoutIndex}: key='{text}' name='{text2}'"); if (!string.IsNullOrEmpty(text2)) { if (!windowLoadoutNames.TryGetValue(window, out var value3)) { value3 = new Dictionary(); windowLoadoutNames[window] = value3; } value3[loadoutIndex] = text2; return text2; } } } } } catch (Exception) { } return $"Loadout {loadoutIndex + 1}"; } private static void SetLoadoutName(GearDetailsWindow window, int loadoutIndex, string newName) { try { if (!windowLoadoutNames.TryGetValue(window, out var value)) { value = new Dictionary(); windowLoadoutNames[window] = value; } if (!string.IsNullOrEmpty(newName)) { value[loadoutIndex] = newName; } else { value.Remove(loadoutIndex); } try { IUpgradable upgradablePrefab = window.UpgradablePrefab; if (upgradablePrefab != null) { Type? typeFromHandle = typeof(PlayerData); object obj = typeFromHandle.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); object obj2 = typeFromHandle.GetMethod("GetGearData", new Type[1] { typeof(IUpgradable) })?.Invoke(obj, new object[1] { upgradablePrefab }); if (obj2 != null) { object? obj3 = obj2.GetType().GetField("gear", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj2); IUpgradable val = (IUpgradable)((obj3 is IUpgradable) ? obj3 : null); if (val != null) { string text = $"{val.Info.ID}_{loadoutIndex}"; SparrohPlugin.Logger.LogInfo((object)$"Saving name for gear {val.Info.ID} slot {loadoutIndex}: key='{text}' name='{newName}'"); if (!string.IsNullOrEmpty(newName)) { PlayerPrefs.SetString("LoadoutName_" + text, newName); PlayerPrefs.Save(); PlayerPrefs.SetString($"ImprovedLoadouts_Name_{val.Info.ID}_{loadoutIndex}", newName); PlayerPrefs.Save(); } else { PlayerPrefs.DeleteKey("LoadoutName_" + text); PlayerPrefs.Save(); } } } } } catch (Exception) { } try { Type type = AccessTools.TypeByName("HoverInfoDisplay"); object obj4 = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj4 == null) { return; } FieldInfo field = type.GetField("currentInfo", BindingFlags.Instance | BindingFlags.NonPublic); MethodInfo method = type.GetMethod("SetInfo", BindingFlags.Instance | BindingFlags.Public); if (!(field != null) || !(method != null)) { return; } object value2 = field.GetValue(obj4); if (((object)window).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(window) is Array array && loadoutIndex < array.Length) { object? value3 = array.GetValue(loadoutIndex); LoadoutHoverInfo val2 = (LoadoutHoverInfo)((value3 is LoadoutHoverInfo) ? value3 : null); if (value2 != null && value2 == val2) { field.SetValue(obj4, null); method.Invoke(obj4, new object[1] { val2 }); } } } catch (Exception) { try { Type type2 = AccessTools.TypeByName("HoverInfoDisplay"); object obj5 = type2.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj5 != null) { type2.GetMethod("Deactivate", BindingFlags.Instance | BindingFlags.Public)?.Invoke(obj5, new object[0]); } } catch (Exception) { } } } catch (Exception) { } } private static int FindHoveredButton(GearDetailsWindow window) { try { try { Type type = AccessTools.TypeByName("HoverInfoDisplay"); object obj = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj != null) { object obj2 = type.GetField("currentInfo", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj); if (obj2 != null && ((object)window).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(window) is Array array) { for (int i = 0; i < array.Length; i++) { object? value = array.GetValue(i); LoadoutHoverInfo val = (LoadoutHoverInfo)((value is LoadoutHoverInfo) ? value : null); if ((Object)(object)val != (Object)null && val == obj2) { return i; } } } } } catch (Exception) { } try { Type type2 = AccessTools.TypeByName("UnityEngine.EventSystems.EventSystem"); object obj3 = type2.GetProperty("current", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj3 != null) { object? obj4 = type2.GetProperty("currentSelectedGameObject", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj3); GameObject val2 = (GameObject)((obj4 is GameObject) ? obj4 : null); if ((Object)(object)val2 != (Object)null) { LoadoutHoverInfo componentInParent = val2.GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && ((object)window).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(window) is Array array2) { for (int j = 0; j < array2.Length; j++) { if (array2.GetValue(j) == componentInParent) { return j; } } } } } } catch (Exception) { } try { if (((object)window).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(window) is Array array3) { for (int k = 0; k < array3.Length; k++) { object? value2 = array3.GetValue(k); LoadoutHoverInfo val3 = (LoadoutHoverInfo)((value2 is LoadoutHoverInfo) ? value2 : null); if ((Object)(object)val3 != (Object)null) { object? obj5 = ((object)val3).GetType().GetProperty("gameObject")?.GetValue(val3); _ = (Object)((obj5 is GameObject) ? obj5 : null) != (Object)null; } } } } catch (Exception) { } } catch (Exception) { } return -1; } [HarmonyPatch(typeof(LoadoutHoverInfo), "GetTitle")] [HarmonyPostfix] public static void GetTitlePostfix(ref LoadoutHoverInfo __instance, ref bool __result, out string title, out Color color) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) try { GearDetailsWindow componentInParent = ((Component)__instance).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && ((object)componentInParent).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(componentInParent) is Array array) { for (int i = 0; i < array.Length; i++) { object? value = array.GetValue(i); LoadoutHoverInfo val = (LoadoutHoverInfo)((value is LoadoutHoverInfo) ? value : null); if ((Object)(object)val != (Object)null && val == __instance) { string loadoutName = GetLoadoutName(componentInParent, i); if (!string.IsNullOrEmpty(loadoutName)) { title = loadoutName; color = Color.white; __result = true; } else { title = $"Loadout {i + 1}"; color = Color.white; __result = true; } return; } } } title = TextBlocks.GetString("loadout"); color = Color.white; __result = true; } catch (Exception) { title = TextBlocks.GetString("loadout"); color = Color.white; __result = true; } } [HarmonyPatch(typeof(GearDetailsWindow), "Update")] [HarmonyPostfix] public static void GearDetailsWindowUpdatePostfix(ref GearDetailsWindow __instance) { //IL_0019: 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_0039: Unknown result type (might be due to invalid IL or missing references) try { if (LoadoutRenameDialog.IsActive) { return; } Keyboard current = Keyboard.current; if (current == null || !((ButtonControl)current[RenameKey]).wasPressedThisFrame) { return; } Vector2.op_Implicit(((InputControl)(object)((Pointer)Mouse.current).position).ReadValue()); if (!(((object)__instance).GetType().GetField("loadoutButtons", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) is Array array)) { return; } for (int i = 0; i < array.Length; i++) { object? value = array.GetValue(i); LoadoutHoverInfo val = (LoadoutHoverInfo)((value is LoadoutHoverInfo) ? value : null); if ((Object)(object)val != (Object)null && IsHovered(val)) { StartRenameProcess(val, i, __instance); break; } } } catch (Exception) { } } private static bool IsHovered(LoadoutHoverInfo button) { //IL_006a: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) try { Type type = AccessTools.TypeByName("HoverInfoDisplay"); object obj = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj != null && type.GetField("currentInfo", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj) == button) { return true; } try { Camera main = Camera.main; if ((Object)(object)main != (Object)null) { Vector2 val = ((InputControl)(object)((Pointer)Mouse.current).position).ReadValue(); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(main.ScreenPointToRay(Vector2.op_Implicit(val)), ref val2, float.PositiveInfinity)) { Collider collider = ((RaycastHit)(ref val2)).collider; GameObject val3 = ((collider != null) ? ((Component)collider).gameObject : null); if ((Object)(object)val3 != (Object)null && (Object)(object)val3.GetComponentInParent() == (Object)(object)button) { return true; } } Type type2 = AccessTools.TypeByName("UnityEngine.EventSystems.PointerEventData"); if (type2 != null) { object obj2 = Activator.CreateInstance(type2, Object.op_Implicit((Object)(object)EventSystem.current)); type2.GetField("position")?.SetValue(obj2, val); List list = new List(); try { Canvas[] array = Object.FindObjectsOfType(); foreach (Canvas val4 in array) { if (!((Object)(object)val4 != (Object)null)) { continue; } GraphicRaycaster component = ((Component)val4).GetComponent(); if (!((Object)(object)component != (Object)null)) { continue; } MethodInfo method = ((object)component).GetType().GetMethod("Raycast", BindingFlags.Instance | BindingFlags.Public); if (!(method != null)) { continue; } list.Clear(); method.Invoke(component, new object[2] { obj2, list }); foreach (RaycastResult item in list) { RaycastResult current = item; if ((Object)(object)((RaycastResult)(ref current)).gameObject != (Object)null && (Object)(object)((RaycastResult)(ref current)).gameObject.GetComponentInParent() == (Object)(object)button) { return true; } } } } finally { list.Clear(); } } } } catch (Exception) { } try { object obj3 = ((object)button).GetType().GetProperty("Active", BindingFlags.Instance | BindingFlags.Public)?.GetValue(button); bool flag = default(bool); int num; if (obj3 is bool) { flag = (bool)obj3; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return true; } } catch (Exception) { } return false; } catch (Exception) { return false; } } private static void StartRenameProcess(LoadoutHoverInfo button, int loadoutIndex, GearDetailsWindow window) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) try { string text = GetLoadoutName(window, loadoutIndex); if (string.IsNullOrEmpty(text)) { text = $"Loadout {loadoutIndex + 1}"; } LoadoutRenameDialog.Show(((InputControl)(object)((Pointer)Mouse.current).position).ReadValue(), text, delegate(string newName) { SetLoadoutName(window, loadoutIndex, newName); }, delegate { }, window, loadoutIndex); } catch (Exception) { } } [HarmonyPatch(typeof(GearData), "SaveLoadout")] [HarmonyPostfix] public static void SaveLoadoutNamesPostfix(ref GearData __instance, int index) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown try { IUpgradable gear = __instance.Gear; if (gear == null) { return; } Type type = AccessTools.TypeByName("GearDetailsWindow"); PropertyInfo property = type.GetProperty("Active", BindingFlags.Static | BindingFlags.Public); object obj = null; if (property != null) { obj = property.GetValue(null); } if (obj == null) { Object[] array = Object.FindObjectsOfType(type); if (array.Length != 0) { obj = array[0]; } } if (obj != null && windowLoadoutNames.TryGetValue((GearDetailsWindow)obj, out var value) && value.TryGetValue(index, out var value2)) { string text = $"{gear.Info.ID}_{((object)gear).GetHashCode()}_{index}"; SparrohPlugin.Logger.LogInfo((object)$"Persisting name for gear {gear.Info.ID} slot {index}: key='{text}' name='{value2}'"); PlayerPrefs.SetString("LoadoutName_" + text, value2); PlayerPrefs.Save(); } } catch (Exception) { } } } [HarmonyPatch] public static class RenameGetPatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(LoadoutHoverInfoPatches), "GetLoadoutName", (Type[])null, (Type[])null); } private static void Prefix(ref int __1) { if (__1 < 3) { __1 += LoadoutExpanderMod.PageOffset; } } } [HarmonyPatch] public static class RenameSetPatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(LoadoutHoverInfoPatches), "SetLoadoutName", (Type[])null, (Type[])null); } private static void Prefix(ref int __1) { if (__1 < 3) { __1 += LoadoutExpanderMod.PageOffset; } } } [HarmonyPatch(typeof(LoadoutHoverInfo), "GetTitle")] public static class TooltipPatch { [HarmonyPostfix] [HarmonyPriority(0)] public static void Postfix(LoadoutHoverInfo __instance, ref string title) { if (LoadoutExpanderMod.PageOffset == 0) { return; } try { GearDetailsWindow componentInParent = ((Component)__instance).GetComponentInParent(); if ((Object)(object)componentInParent == (Object)null) { return; } int num = -1; if (LoadoutExpanderMod._loadoutButtonsField.GetValue(componentInParent) is Array array) { for (int i = 0; i < array.Length; i++) { if (array.GetValue(i) == __instance) { num = i; break; } } } if (num == -1 || num >= 3) { return; } int num2 = num + LoadoutExpanderMod.PageOffset; string text = null; object? obj = ((object)componentInParent).GetType().GetField("upgradable", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(componentInParent); IUpgradable val = (IUpgradable)((obj is IUpgradable) ? obj : null); if (val != null) { Type? typeFromHandle = typeof(PlayerData); object obj2 = typeFromHandle.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); object obj3 = typeFromHandle.GetMethod("GetGearData", new Type[1] { typeof(IUpgradable) })?.Invoke(obj2, new object[1] { val }); if (obj3 != null) { object? obj4 = obj3.GetType().GetField("gear", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj3); IUpgradable val2 = (IUpgradable)((obj4 is IUpgradable) ? obj4 : null); if (val2 != null) { string text2 = $"{val2.Info.ID}_{num2}"; text = PlayerPrefs.GetString("LoadoutName_" + text2, ""); } } } if (!string.IsNullOrEmpty(text)) { title = text; } else { title = $"Loadout {num2 + 1}"; } } catch { } } } [HarmonyPatch] public static class LoadoutSlotsPatches { internal const int MaxLoadoutSlots = 9; private static readonly Type LoadoutType = typeof(PlayerData).GetNestedType("Loadout", BindingFlags.NonPublic); [HarmonyPatch(typeof(GearData), "SaveLoadout")] [HarmonyPrefix] public static bool SaveLoadoutPrefix(ref GearData __instance, int index, ref object ___loadouts) { EnsureLoadoutsCapacity(ref ___loadouts, index); return true; } [HarmonyPatch(typeof(GearData), "EquipLoadout")] [HarmonyPrefix] public static bool EquipLoadoutPrefix(ref GearData __instance, int index, ref object ___loadouts, ref bool __result) { EnsureLoadoutsCapacity(ref ___loadouts, index); Array array = ___loadouts as Array; if (index < 0 || array == null || index >= array.Length) { __result = false; return false; } return true; } internal static void EnsureLoadoutsCapacity(ref object loadouts, int index) { if (!(LoadoutType == null)) { if (!(loadouts is Array array)) { Array array2 = Array.CreateInstance(LoadoutType, Mathf.Max(index + 1, 9)); loadouts = array2; } else if (index >= array.Length) { Array array3 = Array.CreateInstance(LoadoutType, Mathf.Max(index + 1, 9)); array.CopyTo(array3, 0); loadouts = array3; } } } } public class LoadoutTextPreview : MonoBehaviour { private readonly List textElements = new List(); private CanvasGroup canvasGroup; private UIPanel panel; private void Awake() { //IL_0048: 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_0078: Unknown result type (might be due to invalid IL or missing references) UITheme.Initialize(); canvasGroup = ((Component)this).gameObject.AddComponent(); canvasGroup.alpha = 0.95f; Image val = ((Component)this).gameObject.GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)this).gameObject.AddComponent(); } ((Graphic)val).color = UIColors.TooltipBg; UIFactory.ApplyWhiteSprite(val); Outline obj = ((Component)this).gameObject.AddComponent(); ((Shadow)obj).effectColor = UIColors.Border; ((Shadow)obj).effectDistance = new Vector2(1f, -1f); UIFactory.AddVerticalLayout(((Component)this).gameObject, UITheme.S(UITheme.SpacingTight), UITheme.ScaledPadding(10, 10, 10, 10), (TextAnchor)0, true, false, true, true); UIFactory.AddContentSizeFitter(((Component)this).gameObject, (FitMode)2, (FitMode)2); } public void Setup(List placements) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) Clear(); foreach (LoadoutPreviewMod.UpgradePlacement placement in placements) { if (placement.Upgrade != null) { UIText val = UIText.Create(((Component)this).transform, "TextElement", placement.Upgrade.Upgrade.Name, UITheme.ScaledFontSmall, (Color?)placement.Upgrade.Upgrade.Color, (TextAlignmentOptions)513, false); GameObject gameObject = val.GameObject; float? num = UITheme.S(18f); UIHelpers.EnsureLayoutElement(gameObject, (float?)null, num, (float?)null); textElements.Add(val); } } } private void Clear() { foreach (UIText textElement in textElements) { if (textElement != null && (Object)(object)textElement.GameObject != (Object)null) { Object.Destroy((Object)(object)textElement.GameObject); } } textElements.Clear(); } public void SetPosition(Vector2 position) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) ((RectTransform)((Component)this).transform).anchoredPosition = position; } public void Show() { ((Component)this).gameObject.SetActive(true); } public void Hide() { ((Component)this).gameObject.SetActive(false); } } [BepInPlugin("sparroh.loadoutimprovements", "LoadoutImprovements", "1.2.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [MycoMod(/*Could not decode attribute arguments.*/)] public class SparrohPlugin : BaseUnityPlugin { public const string PluginGUID = "sparroh.loadoutimprovements"; public const string PluginName = "LoadoutImprovements"; public const string PluginVersion = "1.2.2"; internal static ManualLogSource Logger; public static SparrohPlugin Instance; private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown try { Logger = ((BaseUnityPlugin)this).Logger; Instance = this; Harmony val = new Harmony("sparroh.loadoutimprovements"); try { LoadoutExpanderMod._loadoutButtonsField = AccessTools.Field(typeof(GearDetailsWindow), "loadoutButtons"); LoadoutExpanderMod._updateIconMethod = AccessTools.Method(typeof(GearDetailsWindow), "UpdateLoadoutIcon", (Type[])null, (Type[])null); } catch (Exception ex) { Logger.LogError((object)("Failed to setup LoadoutExpander reflection: " + ex.Message)); } try { ConfigManager.Initialize(((BaseUnityPlugin)this).Config, Logger); LoadoutPreviewMod.UpdatePreviewMode(); } catch (Exception ex2) { Logger.LogError((object)("Failed to setup configuration bindings: " + ex2.Message)); } try { LoadoutPreviewMod.ApplyPatches(val); } catch (Exception ex3) { Logger.LogError((object)("Failed to apply LoadoutPreviewMod patches: " + ex3.Message)); } try { val.PatchAll(); } catch (Exception ex4) { Logger.LogError((object)("Failed to apply Harmony patches: " + ex4.Message)); } } catch (Exception ex5) { Logger.LogError((object)("Critical error during mod initialization: " + ex5.Message + "\n" + ex5.StackTrace)); } Logger.LogInfo((object)"LoadoutImprovements loaded successfully."); } private void Update() { //IL_0013: 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) try { ConfigManager.Tick(); if (Keyboard.current != null) { if (((ButtonControl)Keyboard.current[LoadoutExpanderMod.ScrollRightKey]).wasPressedThisFrame) { LoadoutExpanderMod.ScrollRight(); } else if (((ButtonControl)Keyboard.current[LoadoutExpanderMod.ScrollLeftKey]).wasPressedThisFrame) { LoadoutExpanderMod.ScrollLeft(); } } } catch (Exception ex) { Logger.LogError((object)("Critical error in Update(): " + ex.Message)); } } private void OnDestroy() { try { ConfigManager.Dispose(); } catch (Exception ex) { Logger.LogError((object)("Failed to dispose config manager: " + ex.Message)); } try { LoadoutPreviewMod.Destroy(); } catch (Exception ex2) { Logger.LogError((object)("Failed to destroy LoadoutPreviewMod: " + ex2.Message)); } } } namespace LoadoutImprovements { public static class MyPluginInfo { public const string PLUGIN_GUID = "LoadoutImprovements"; public const string PLUGIN_NAME = "LoadoutImprovements"; public const string PLUGIN_VERSION = "1.2.2"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }