using System; using System.Diagnostics; 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 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(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("CompareUpgrades")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CompareUpgrades")] [assembly: AssemblyTitle("CompareUpgrades")] [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; } } } public static class CompareController { private static UpgradeInstance lockedUpgrade; private static SelectionMark lockMark; private static GearUpgradeUI markedUi; public static UpgradeInstance LockedUpgrade => lockedUpgrade; public static bool HasLock => lockedUpgrade != null; public static void Tick() { if (!IsGearDetailsOpen(out var _)) { if (HasLock) { ClearLock(); } } else if (lockedUpgrade != null && (Object)(object)lockedUpgrade.Upgrade == (Object)null) { ClearLock(); } else { HandleHotkey(); UpdateComparisonView(); UpdateLockMark(); } } public static void OnGearWindowReset() { ClearLock(); } public static void Shutdown() { ClearLock(); CompareDisplay.Destroy(); } public static void OnMainHoverRefreshed() { if (HasLock && CompareDisplay.IsVisible) { CompareDisplay.RefreshIfVisible(); } } private static void HandleHotkey() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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) Keyboard current = Keyboard.current; if (current == null) { return; } Key compareKey = CompareUpgradesPlugin.CompareKey; if ((int)compareKey == 0) { return; } KeyControl val = current[compareKey]; if (val == null || !((ButtonControl)val).wasPressedThisFrame || IsSearchFocused()) { return; } if (HasLock) { ClearLock(); return; } GearUpgradeUI hoveredUpgradeUi = GetHoveredUpgradeUi(); if ((Object)(object)hoveredUpgradeUi != (Object)null && ((HoverInfoUpgrade)hoveredUpgradeUi).Upgrade != null) { Lock(((HoverInfoUpgrade)hoveredUpgradeUi).Upgrade, hoveredUpgradeUi); } } private static void UpdateComparisonView() { if (!HasLock) { CompareDisplay.Hide(); return; } GearUpgradeUI hoveredUpgradeUi = GetHoveredUpgradeUi(); bool num = (Object)(object)hoveredUpgradeUi != (Object)null && ((HoverInfoUpgrade)hoveredUpgradeUi).Upgrade != null && ((HoverInfoUpgrade)hoveredUpgradeUi).Upgrade != lockedUpgrade; HoverInfoDisplay instance = HoverInfoDisplay.Instance; bool flag = (Object)(object)instance != (Object)null && ((Component)instance).gameObject.activeSelf && !CompareDisplay.IsCompareInstance(instance) && (Object)(object)instance.SelectedInfo != (Object)null; if (num && flag) { CompareDisplay.Show(lockedUpgrade); CompareDisplay.TickPosition(); } else { CompareDisplay.Hide(); } } private static void Lock(UpgradeInstance upgrade, GearUpgradeUI ui) { lockedUpgrade = upgrade; CompareDisplay.EnsureCreated(); ApplyLockMark(ui); ManualLogSource log = CompareUpgradesPlugin.Log; if (log != null) { log.LogInfo((object)("Locked upgrade for comparison: " + GetUpgradeName(upgrade))); } } private static void ClearLock() { if (lockedUpgrade != null) { ManualLogSource log = CompareUpgradesPlugin.Log; if (log != null) { log.LogInfo((object)"Unlocked upgrade comparison."); } } lockedUpgrade = null; CompareDisplay.Hide(); ReleaseLockMark(); } private static void UpdateLockMark() { if (!HasLock) { ReleaseLockMark(); return; } GearUpgradeUI val = FindUiForLocked(); if ((Object)(object)val != (Object)(object)markedUi) { ApplyLockMark(val); } } private static void ApplyLockMark(GearUpgradeUI ui) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown ReleaseLockMark(); markedUi = ui; if ((Object)(object)ui == (Object)null || (Object)(object)Menu.Instance == (Object)null) { return; } try { lockMark = Menu.Instance.GetSelectionMark(); lockMark.Setup((RectTransform)((Component)ui).transform, Vector2.zero, true); } catch { lockMark = null; } } private static void ReleaseLockMark() { if ((Object)(object)lockMark != (Object)null) { try { lockMark.Release(); } catch { } lockMark = null; } markedUi = null; } private static GearUpgradeUI FindUiForLocked() { if (lockedUpgrade == null) { return null; } GearUpgradeUI hoveredUpgradeUi = GetHoveredUpgradeUi(); if ((Object)(object)hoveredUpgradeUi != (Object)null && ((HoverInfoUpgrade)hoveredUpgradeUi).Upgrade == lockedUpgrade) { return hoveredUpgradeUi; } if ((Object)(object)markedUi != (Object)null && Object.op_Implicit((Object)(object)markedUi) && ((Component)markedUi).gameObject.activeInHierarchy && ((HoverInfoUpgrade)markedUi).Upgrade == lockedUpgrade) { return markedUi; } return null; } private static GearUpgradeUI GetHoveredUpgradeUi() { GearUpgradeUI val = default(GearUpgradeUI); if (UIRaycaster.RaycastForComponent(ref val) && (Object)(object)val != (Object)null) { return val; } return null; } private static bool IsGearDetailsOpen(out GearDetailsWindow window) { window = null; if ((Object)(object)Menu.Instance == (Object)null || !Menu.Instance.IsOpen) { return false; } if ((Object)(object)Menu.Instance.WindowSystem == (Object)null) { return false; } Window top = Menu.Instance.WindowSystem.GetTop(); window = (GearDetailsWindow)(object)((top is GearDetailsWindow) ? top : null); return (Object)(object)window != (Object)null; } private static bool IsSearchFocused() { GameObject val = (((Object)(object)EventSystem.current != (Object)null) ? EventSystem.current.currentSelectedGameObject : null); if ((Object)(object)val == (Object)null) { return false; } if ((Object)(object)val.GetComponent() != (Object)null) { return true; } MonoBehaviour[] components = val.GetComponents(); for (int i = 0; i < components.Length; i++) { if (!((Object)(object)components[i] == (Object)null)) { string name = ((object)components[i]).GetType().Name; if (name == "TMP_InputField" || name == "InputField") { return true; } } } return false; } private static string GetUpgradeName(UpgradeInstance upgrade) { try { if ((Object)(object)((upgrade != null) ? upgrade.Upgrade : null) != (Object)null) { return upgrade.Upgrade.GetInstanceName(upgrade); } } catch { } return "(unknown)"; } } public static class CompareDisplay { private const float Gap = 24f; private const float EdgePadding = 20f; private static HoverInfoDisplay clone; private static LockedUpgradeProxy proxy; private static GameObject proxyRoot; private static bool visible; private static UpgradeInstance shownUpgrade; public static HoverInfoDisplay Clone => clone; public static bool IsVisible => visible; public static bool IsCompareInstance(HoverInfoDisplay display) { if ((Object)(object)clone != (Object)null) { return (Object)(object)display == (Object)(object)clone; } return false; } public static void EnsureCreated() { if ((Object)(object)clone != (Object)null) { return; } HoverInfoDisplay instance = HoverInfoDisplay.Instance; if ((Object)(object)instance == (Object)null) { return; } Transform parent = ((Component)instance).transform.parent; if (!((Object)(object)parent == (Object)null)) { clone = Object.Instantiate(instance, parent); ((Object)((Component)clone).gameObject).name = "CompareUpgrades_HoverInfoDisplay"; RestoreMainInstance(instance); DisableRaycasts(((Component)clone).gameObject); try { clone.Deactivate(); } catch { ((Component)clone).gameObject.SetActive(false); } EnsureProxy(); ManualLogSource log = CompareUpgradesPlugin.Log; if (log != null) { log.LogInfo((object)"Created comparison hover display."); } } } public static void Show(UpgradeInstance upgrade) { if (upgrade == null) { return; } EnsureCreated(); if ((Object)(object)clone == (Object)null || (Object)(object)proxy == (Object)null) { return; } bool num = !visible || shownUpgrade != upgrade || !((Component)clone).gameObject.activeSelf; proxy.SetLockedUpgrade(upgrade); shownUpgrade = upgrade; if (num) { try { clone.ShowInfo((HoverInfo)(object)proxy); } catch (Exception ex) { ManualLogSource log = CompareUpgradesPlugin.Log; if (log != null) { log.LogWarning((object)("ShowInfo on compare display failed: " + ex.Message)); } return; } } visible = ((Component)clone).gameObject.activeSelf; if (visible) { PositionBesideMain(); } } public static void RefreshIfVisible() { if (!visible || (Object)(object)clone == (Object)null || (Object)(object)proxy == (Object)null || shownUpgrade == null) { return; } try { clone.Refresh(); PositionBesideMain(); } catch (Exception ex) { ManualLogSource log = CompareUpgradesPlugin.Log; if (log != null) { log.LogWarning((object)("Refresh compare display failed: " + ex.Message)); } } } public static void Hide() { if ((Object)(object)clone == (Object)null) { visible = false; shownUpgrade = null; return; } if (((Component)clone).gameObject.activeSelf) { try { clone.Deactivate(); } catch { ((Component)clone).gameObject.SetActive(false); } } visible = false; shownUpgrade = null; } public static void TickPosition() { if (visible && !((Object)(object)clone == (Object)null) && ((Component)clone).gameObject.activeSelf) { PositionBesideMain(); } } public static void Destroy() { Hide(); if ((Object)(object)clone != (Object)null) { Object.Destroy((Object)(object)((Component)clone).gameObject); clone = null; } if ((Object)(object)proxyRoot != (Object)null) { Object.Destroy((Object)(object)proxyRoot); proxyRoot = null; proxy = null; } shownUpgrade = null; visible = false; } private static void EnsureProxy() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!((Object)(object)proxy != (Object)null)) { proxyRoot = new GameObject("CompareUpgrades_LockedProxy"); Object.DontDestroyOnLoad((Object)(object)proxyRoot); ((Object)proxyRoot).hideFlags = (HideFlags)61; proxy = proxyRoot.AddComponent(); } } private static void RestoreMainInstance(HoverInfoDisplay main) { try { PropertyInfo propertyInfo = AccessTools.Property(typeof(HoverInfoDisplay), "Instance"); if (propertyInfo != null) { propertyInfo.SetValue(null, main, null); return; } } catch (Exception ex) { ManualLogSource log = CompareUpgradesPlugin.Log; if (log != null) { log.LogWarning((object)("Failed to restore HoverInfoDisplay.Instance via AccessTools: " + ex.Message)); } } try { typeof(HoverInfoDisplay).GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.SetValue(null, main, null); } catch (Exception arg) { ManualLogSource log2 = CompareUpgradesPlugin.Log; if (log2 != null) { log2.LogError((object)$"Failed to restore HoverInfoDisplay.Instance: {arg}"); } } } private static void DisableRaycasts(GameObject root) { Graphic[] componentsInChildren = root.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].raycastTarget = false; } CanvasGroup[] componentsInChildren2 = root.GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren2.Length; j++) { componentsInChildren2[j].blocksRaycasts = false; componentsInChildren2[j].interactable = false; } } private static void PositionBesideMain() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //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_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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_012c: 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) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) HoverInfoDisplay instance = HoverInfoDisplay.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)clone == (Object)null || (Object)(object)instance == (Object)(object)clone || !((Component)instance).gameObject.activeSelf) { return; } RectTransform rectTransform = instance.RectTransform; RectTransform rectTransform2 = clone.RectTransform; if (!((Object)(object)rectTransform == (Object)null) && !((Object)(object)rectTransform2 == (Object)null)) { Transform parent = ((Transform)rectTransform).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); if (!((Object)(object)val == (Object)null)) { Vector2 anchoredPosition = rectTransform.anchoredPosition; Vector2 sizeDelta = rectTransform.sizeDelta; Vector2 sizeDelta2 = rectTransform2.sizeDelta; Rect rect = val.rect; Vector2 size = ((Rect)(ref rect)).size; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(anchoredPosition.x + (sizeDelta.x + sizeDelta2.x) * 0.5f + 24f, anchoredPosition.y); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(anchoredPosition.x - (sizeDelta.x + sizeDelta2.x) * 0.5f - 24f, anchoredPosition.y); Vector2 val4 = (Fits(val2, sizeDelta2, size) ? val2 : (Fits(val3, sizeDelta2, size) ? val3 : Clamp(val2, sizeDelta2, size))); val4.y = ClampY(val4.y, sizeDelta2.y, size.y); rectTransform2.anchoredPosition = val4; } } } private static bool Fits(Vector2 center, Vector2 size, Vector2 bounds) { //IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) float num = bounds.x * 0.5f; float num2 = bounds.y * 0.5f; float num3 = center.x - size.x * 0.5f; float num4 = center.x + size.x * 0.5f; float num5 = center.y - size.y * 0.5f; float num6 = center.y + size.y * 0.5f; if (num3 >= 0f - num + 20f && num4 <= num - 20f && num5 >= 0f - num2 + 20f) { return num6 <= num2 - 20f; } return false; } private static Vector2 Clamp(Vector2 center, Vector2 size, Vector2 bounds) { //IL_0000: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0057: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) float num = bounds.x * 0.5f; float num2 = bounds.y * 0.5f; center.x = Mathf.Clamp(center.x, 0f - num + size.x * 0.5f + 20f, num - size.x * 0.5f - 20f); center.y = Mathf.Clamp(center.y, 0f - num2 + size.y * 0.5f + 20f, num2 - size.y * 0.5f - 20f); return center; } private static float ClampY(float y, float height, float boundsY) { float num = boundsY * 0.5f; return Mathf.Clamp(y, 0f - num + height * 0.5f + 20f, num - height * 0.5f - 20f); } } internal static class ComparePatches { [HarmonyPatch(typeof(HoverInfoDisplay), "UpdatePosition")] [HarmonyPrefix] private static bool UpdatePositionPrefix(HoverInfoDisplay __instance) { if (CompareDisplay.IsCompareInstance(__instance)) { return false; } return true; } [HarmonyPatch(typeof(HoverInfoDisplay), "Refresh")] [HarmonyPostfix] private static void RefreshPostfix(HoverInfoDisplay __instance) { if (!CompareDisplay.IsCompareInstance(__instance)) { CompareController.OnMainHoverRefreshed(); } } [HarmonyPatch(typeof(GearDetailsWindow), "Setup")] [HarmonyPostfix] private static void GearDetailsSetupPostfix() { CompareController.OnGearWindowReset(); } [HarmonyPatch(typeof(GearDetailsWindow), "OnCloseCallback")] [HarmonyPostfix] private static void GearDetailsClosePostfix() { CompareController.OnGearWindowReset(); } } public sealed class LockedUpgradeProxy : HoverInfoUpgrade { public override bool EnableHoverInfoEvents => false; public override bool GetPrimaryBinding(out InputAction binding, out string label) { binding = null; label = null; return false; } public override bool GetSecondaryBinding(out InputAction binding, out string label) { binding = null; label = null; return false; } public override int GetAdditionalBindingCount() { return 0; } public override bool HasUnlockAction(out UnlockActionParams data) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) data = default(UnlockActionParams); return false; } public override bool HasUnlockInfo(out string text) { text = null; return false; } public void SetLockedUpgrade(UpgradeInstance upgrade) { ((HoverInfoUpgrade)this).Upgrade = upgrade; } } [BepInPlugin("sparroh.compareupgrades", "CompareUpgrades", "2.0.0")] [MycoMod(/*Could not decode attribute arguments.*/)] public class CompareUpgradesPlugin : BaseUnityPlugin { public const string PluginGUID = "sparroh.compareupgrades"; public const string PluginName = "CompareUpgrades"; public const string PluginVersion = "2.0.0"; internal static ManualLogSource Log; internal static CompareUpgradesPlugin Instance; private ConfigEntry compareKey; private Harmony harmony; internal static Key CompareKey { get { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Instance != (Object)null)) { return (Key)17; } return Instance.compareKey.Value; } } private void Awake() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; compareKey = ((BaseUnityPlugin)this).Config.Bind("Keybinds", "Compare Key", (Key)17, "Hotkey to lock/unlock an upgrade for side-by-side comparison while the gear details window is open."); try { harmony = new Harmony("sparroh.compareupgrades"); harmony.PatchAll(typeof(ComparePatches)); Log.LogInfo((object)"CompareUpgrades v2.0.0 loaded."); } catch (Exception arg) { Log.LogError((object)$"Failed to initialize: {arg}"); } } private void Update() { try { CompareController.Tick(); } catch (Exception arg) { Log.LogError((object)$"CompareController tick failed: {arg}"); } } private void OnDestroy() { try { CompareController.Shutdown(); } catch (Exception arg) { Log.LogError((object)$"Shutdown failed: {arg}"); } try { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } catch (Exception arg2) { Log.LogError((object)$"Unpatch failed: {arg2}"); } Instance = null; } } namespace CompareUpgrades { public static class MyPluginInfo { public const string PLUGIN_GUID = "CompareUpgrades"; public const string PLUGIN_NAME = "CompareUpgrades"; 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) { } } }