Decompiled source of LoadoutImprovements v1.2.2

BepInEx/plugins/LoadoutImprovements.dll

Decompiled a month ago
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<Key> ScrollLeftKey { get; private set; }

	public static ConfigEntry<Key> ScrollRightKey { get; private set; }

	public static ConfigEntry<Key> RenameKey { get; private set; }

	public static ConfigEntry<bool> EnableTextMode { get; private set; }

	public static void Initialize(ConfigFile configFile, ManualLogSource log)
	{
		config = configFile;
		logger = log;
		ScrollLeftKey = config.Bind<Key>("Keybinds", "Scroll Loadout Left", (Key)7, "Key to scroll to the left loadout page");
		ScrollRightKey = config.Bind<Key>("Keybinds", "Scroll Loadout Right", (Key)8, "Key to scroll to the right loadout page");
		RenameKey = config.Bind<Key>("Keybinds", "Rename Loadout", (Key)32, "Key to rename the hovered loadout");
		EnableTextMode = config.Bind<bool>("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<GearDetailsWindow>();
			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<int, string>();
				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<EquipKey>, IEquatable<EquipKey>
	{
		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<int, Color> OriginalIconColors = new Dictionary<int, Color>();

	private static readonly Dictionary<int, Color> OriginalFillColors = new Dictionary<int, Color>();

	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<Image>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
		}
		Image[] componentsInChildren = ((Component)button).GetComponentsInChildren<Image>(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<Graphic>();
			if ((Object)(object)component != (Object)null && (Object)(object)component != (Object)(object)icon)
			{
				return component;
			}
		}
		Graphic component2 = ((Component)button).GetComponent<Graphic>();
		if ((Object)(object)component2 != (Object)null && (Object)(object)component2 != (Object)(object)icon)
		{
			return component2;
		}
		Image[] componentsInChildren = ((Component)button).GetComponentsInChildren<Image>(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<EquipKey> 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<EquipKey> 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<EquipKey> list3 = ToSortedKeys(list);
		List<EquipKey> 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<EquipKey> 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<EquipKey> list2 = new List<EquipKey>(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<bool> 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<LoadoutTextPreview>();
		val.GetComponent<RectTransform>().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<Vector2>();
		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<UpgradePlacement> 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<RaycastResult> list = new List<RaycastResult>();
		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<Canvas>();
		Vector2 val = default(Vector2);
		RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)((Component)componentInParent).transform, mousePos, componentInParent.worldCamera, ref val);
		return val + new Vector2(500f, -250f);
	}

	private static List<UpgradePlacement> 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<UpgradePlacement> list = new List<UpgradePlacement>();
		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<object>()).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<string> 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<string> 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>();
		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<string> 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<string>)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<string> 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<int, string> loadoutNames = new Dictionary<int, string>();

	public static Key RenameKey = (Key)32;

	internal static readonly Dictionary<GearDetailsWindow, Dictionary<int, string>> windowLoadoutNames = new Dictionary<GearDetailsWindow, Dictionary<int, string>>();

	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<int, string>();
								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<int, string>();
				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<LoadoutHoverInfo>();
						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<GearDetailsWindow>();
			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<Vector2>)(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<Vector2>)(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<LoadoutHoverInfo>() == (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<RaycastResult> list = new List<RaycastResult>();
						try
						{
							Canvas[] array = Object.FindObjectsOfType<Canvas>();
							foreach (Canvas val4 in array)
							{
								if (!((Object)(object)val4 != (Object)null))
								{
									continue;
								}
								GraphicRaycaster component = ((Component)val4).GetComponent<GraphicRaycaster>();
								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<LoadoutHoverInfo>() == (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<Vector2>)(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<GearDetailsWindow>();
			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<UIText> textElements = new List<UIText>();

	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>();
		canvasGroup.alpha = 0.95f;
		Image val = ((Component)this).gameObject.GetComponent<Image>();
		if ((Object)(object)val == (Object)null)
		{
			val = ((Component)this).gameObject.AddComponent<Image>();
		}
		((Graphic)val).color = UIColors.TooltipBg;
		UIFactory.ApplyWhiteSprite(val);
		Outline obj = ((Component)this).gameObject.AddComponent<Outline>();
		((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<LoadoutPreviewMod.UpgradePlacement> 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)
		{
		}
	}
}