Decompiled source of UpgradeOptimizer v1.0.0

BepInEx/plugins/UpgradeOptimizer.dll

Decompiled 15 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Pigeon;
using Pigeon.Math;
using Pigeon.Movement;
using Sparroh.UI;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("UpgradeOptimizer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("UpgradeOptimizer")]
[assembly: AssemblyTitle("UpgradeOptimizer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal static class BoostFeature
{
	public static void TryHandleHotkey(Keyboard keyboard, Key hotkey)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		if (!PlayerInput.IsMenuEnabled || !UpgradeOptimizerPlugin.WasHotkeyPressed(keyboard, hotkey))
		{
			return;
		}
		UpgradeInstance hoveredUpgrade = UpgradeOptimizerPlugin.HoveredUpgrade;
		if (hoveredUpgrade != null && !((Object)(object)hoveredUpgrade.Upgrade == (Object)null))
		{
			if (hoveredUpgrade.IsTurbocharged)
			{
				hoveredUpgrade.IsTurbocharged = false;
				RefreshUpgradeUI(hoveredUpgrade);
				UpgradeOptimizerPlugin.Log.LogInfo((object)("Removed boost from '" + hoveredUpgrade.Upgrade.Name + "'."));
			}
			else if (!CanAutoBoost(hoveredUpgrade))
			{
				UpgradeOptimizerPlugin.Log.LogInfo((object)("Upgrade '" + hoveredUpgrade.Upgrade.Name + "' cannot be boosted."));
			}
			else
			{
				hoveredUpgrade.IsTurbocharged = true;
				RefreshUpgradeUI(hoveredUpgrade);
				PlayBoostFeedback(hoveredUpgrade);
				UpgradeOptimizerPlugin.Log.LogInfo((object)("Boosted '" + hoveredUpgrade.Upgrade.Name + "'."));
			}
		}
	}

	private static bool CanAutoBoost(UpgradeInstance upgrade)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Invalid comparison between Unknown and I4
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Invalid comparison between Unknown and I4
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Invalid comparison between Unknown and I4
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Invalid comparison between Unknown and I4
		Upgrade upgrade2 = upgrade.Upgrade;
		if (upgrade2 == null)
		{
			return false;
		}
		if (!upgrade.IsUnlocked)
		{
			return false;
		}
		if (upgrade.RemoveAfterMission)
		{
			return false;
		}
		Rarity rarity = upgrade2.Rarity;
		if ((int)rarity > 3)
		{
			return false;
		}
		if ((int)rarity == 3)
		{
			return (upgrade2.Flags & 0x2000) > 0;
		}
		if (upgrade2.IsSkin())
		{
			return false;
		}
		return (upgrade2.Flags & 0x40020) == 0;
	}

	private static void RefreshUpgradeUI(UpgradeInstance upgrade)
	{
		if ((Object)(object)HoverInfoDisplay.Instance != (Object)null)
		{
			HoverInfoDisplay.Instance.Refresh();
		}
		GearUpgradeUI val = default(GearUpgradeUI);
		if (UIRaycaster.RaycastForComponent<GearUpgradeUI>(ref val) && (Object)(object)val != (Object)null && ((HoverInfoUpgrade)val).Upgrade == upgrade)
		{
			val.SetUpgrade(upgrade, false);
		}
		GearDetailsWindow val2 = null;
		if ((Object)(object)Menu.Instance != (Object)null && Menu.Instance.IsOpen)
		{
			Window top = Menu.Instance.WindowSystem.GetTop();
			val2 = (GearDetailsWindow)(object)((top is GearDetailsWindow) ? top : null);
		}
		if ((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeSelf && upgrade.IsEquipped(val2.UpgradablePrefab))
		{
			val2.RefreshUpgrade(upgrade);
		}
	}

	private static void PlayBoostFeedback(UpgradeInstance upgrade)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)PlayerLook.Instance == (Object)null))
		{
			Global.GetRarity(upgrade.Upgrade.Rarity).raritySwitch.SetValue(((Component)PlayerLook.Instance).gameObject);
			Global.Instance.UpgradeUnlockSound.Post(((Component)PlayerLook.Instance).gameObject);
			Global.Instance.UpgradeDropSound.Post(((Component)PlayerLook.Instance).gameObject);
		}
	}
}
internal static class MaxRollPatches
{
	[HarmonyPatch]
	internal static class RangeFloatGetValuePatch
	{
		private static MethodBase TargetMethod()
		{
			return FindGetValue(typeof(Range<float>));
		}

		private static bool Prefix(ref Range<float> __instance, ref Random rand, UpgradeInstance upgrade, BoostParams boostParams, ref float __result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (!ShouldForceBest(upgrade, boostParams))
			{
				return true;
			}
			__result = __instance.GetValue(ref rand, GetBestAddT(boostParams));
			return false;
		}
	}

	[HarmonyPatch]
	internal static class RangeIntGetValuePatch
	{
		private static MethodBase TargetMethod()
		{
			return FindGetValue(typeof(Range<int>));
		}

		private static bool Prefix(ref Range<int> __instance, ref Random rand, UpgradeInstance upgrade, BoostParams boostParams, ref int __result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (!ShouldForceBest(upgrade, boostParams))
			{
				return true;
			}
			__result = __instance.GetValue(ref rand, GetBestAddT(boostParams));
			return false;
		}
	}

	[HarmonyPatch]
	internal static class RangeVector2GetValuePatch
	{
		private static MethodBase TargetMethod()
		{
			return FindGetValue(typeof(Range<Vector2>));
		}

		private static bool Prefix(ref Range<Vector2> __instance, ref Random rand, UpgradeInstance upgrade, BoostParams boostParams, ref Vector2 __result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!ShouldForceBest(upgrade, boostParams))
			{
				return true;
			}
			__result = __instance.GetValue(ref rand, GetBestAddT(boostParams));
			return false;
		}
	}

	[HarmonyPatch]
	internal static class GetUniformRandomValuePatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(Range<Vector2>), "GetUniformRandomValue", new Type[4]
			{
				typeof(Range<Vector2>),
				typeof(Random).MakeByRefType(),
				typeof(UpgradeInstance),
				typeof(BoostParams)
			}, (Type[])null);
		}

		private static bool Prefix(Range<Vector2> range, ref Random rand, UpgradeInstance upgrade, BoostParams boostParams, ref Vector2 __result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (!ShouldForceBest(upgrade, boostParams))
			{
				return true;
			}
			__result = Vector2.Lerp(range.min, range.max, ((Random)(ref rand)).NextFloat() + GetBestAddT(boostParams));
			return false;
		}
	}

	private static bool ShouldForceBest(UpgradeInstance upgrade, BoostParams boostParams)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Invalid comparison between Unknown and I4
		if (!UpgradeOptimizerPlugin.EnableMaxRolls.Value)
		{
			return false;
		}
		if (upgrade == null || !upgrade.IsTurbocharged)
		{
			return false;
		}
		if (!boostParams.cannotBeBoosted)
		{
			return true;
		}
		Upgrade upgrade2 = upgrade.Upgrade;
		if (upgrade2 != null)
		{
			return (int)upgrade2.Rarity == 3;
		}
		return false;
	}

	private static float GetBestAddT(BoostParams boostParams)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		if (!boostParams.minIsBetter)
		{
			return 1f;
		}
		return -1f;
	}

	private static MethodBase FindGetValue(Type rangeType)
	{
		return AccessTools.Method(rangeType, "GetValue", new Type[3]
		{
			typeof(Random).MakeByRefType(),
			typeof(UpgradeInstance),
			typeof(BoostParams)
		}, (Type[])null);
	}
}
public static class PatternBrowser
{
	private static bool _isOpen;

	private static UpgradeInstance _target;

	private static string _search = "";

	private static bool _sameGearOnly;

	private static int _rarityFilterIndex;

	private static PatternCatalog.SortMode _sortMode = PatternCatalog.SortMode.Name;

	private static int _selectedIndex = -1;

	private static string _status = "";

	private static int _targetCellCount;

	private static UIWindow _window;

	private static UIInputField _searchField;

	private static UIToggle _sameGearToggle;

	private static UIDragList _unused;

	private static RectTransform _listContent;

	private static UIScrollView _listScroll;

	private static UIText _headerText;

	private static UIText _currentPatternText;

	private static UIText _previewText;

	private static UIText _statusText;

	private static UIText _countText;

	private static readonly List<UIButton> _listButtons = new List<UIButton>();

	private static readonly string[] RarityFilterLabels = new string[7] { "All", "Standard", "Rare", "Epic", "Exotic", "Oddity", "Contraband" };

	public static bool IsOpen => _isOpen;

	public static void Open(UpgradeInstance target)
	{
		if (target == null)
		{
			return;
		}
		_target = target;
		_isOpen = true;
		_selectedIndex = -1;
		_status = "";
		_targetCellCount = PatternCatalog.SafeCellCount(target.Upgrade);
		try
		{
			HexMap pattern = target.GetPattern(false);
			if (pattern != null)
			{
				_targetCellCount = pattern.GetCellCount();
			}
		}
		catch
		{
		}
		PatternCatalog.Rebuild(target);
		RefreshFilters();
		EnsureWindow();
		RefreshUi();
		_window.Show();
		ManualLogSource log = UpgradeOptimizerPlugin.Log;
		Upgrade upgrade = target.Upgrade;
		log.LogInfo((object)("Opened pattern browser for " + ((upgrade != null) ? upgrade.Name : null)));
	}

	public static void Close()
	{
		_isOpen = false;
		_target = null;
		_selectedIndex = -1;
		_status = "";
		if (_window != null)
		{
			_window.Hide(true);
		}
	}

	public static void Draw()
	{
	}

	private static void EnsureWindow()
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Expected O, but got Unknown
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0263: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d5: Expected O, but got Unknown
		//IL_032b: Unknown result type (might be due to invalid IL or missing references)
		//IL_039f: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ae: Expected O, but got Unknown
		//IL_0409: Unknown result type (might be due to invalid IL or missing references)
		//IL_045d: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0547: Unknown result type (might be due to invalid IL or missing references)
		//IL_0556: Expected O, but got Unknown
		if (_window != null)
		{
			return;
		}
		UITheme.Initialize();
		_window = UIWindow.Create("PatternBrowser", (Vector2?)new Vector2(720f, 520f), "UpgradeOptimizer — Pattern Browser", false, true, (int?)(UITheme.WindowSortingOrder + 10));
		_window.OnClose((Action)Close);
		Transform content = _window.Content;
		UIFactory.AddVerticalLayout(((Component)content).gameObject, UITheme.S(6f), UITheme.ScaledPadding(10, 10, 8, 8), (TextAnchor)0, true, false, true, true);
		_headerText = UIText.Create(content, "Header", "", UITheme.ScaledFontBody, (Color?)UIColors.TextPrimary, (TextAlignmentOptions)513, false);
		GameObject gameObject = _headerText.GameObject;
		float? num = UITheme.S(22f);
		UIHelpers.EnsureLayoutElement(gameObject, (float?)null, num, (float?)null);
		_currentPatternText = UIText.Create(content, "Current", "", UITheme.ScaledFontSmall, (Color?)UIColors.TextSecondary, (TextAlignmentOptions)513, false);
		GameObject gameObject2 = _currentPatternText.GameObject;
		num = UITheme.S(20f);
		UIHelpers.EnsureLayoutElement(gameObject2, (float?)null, num, (float?)null);
		RectTransform val = UIFactory.CreateRect("SearchRow", content);
		GameObject gameObject3 = ((Component)val).gameObject;
		num = UITheme.ScaledInputHeight + UITheme.S(4f);
		UIHelpers.EnsureLayoutElement(gameObject3, (float?)null, num, (float?)null);
		UIFactory.AddHorizontalLayout(((Component)val).gameObject, UITheme.S(8f), new RectOffset(0, 0, 0, 0), (TextAnchor)3, false, false, true, true);
		UIText.Create((Transform)(object)val, "SearchLbl", "Search", UITheme.ScaledFontSmall, (Color?)UIColors.TextSecondary, (TextAlignmentOptions)513, false);
		_searchField = UIInputField.Create((Transform)(object)val, _search, "Filter patterns...", (Action<string>)delegate(string s)
		{
			_search = s ?? "";
			RefreshFilters();
			RebuildList();
		}, "InputField");
		UIHelpers.EnsureLayoutElement(_searchField.GameObject, (float?)UITheme.S(220f), (float?)null, (float?)null);
		UIText.Create((Transform)(object)val, "LockedFilters", "Same gear · same rarity", UITheme.ScaledFontSmall, (Color?)UIColors.TextMuted, (TextAlignmentOptions)513, false);
		RectTransform val2 = UIFactory.CreateRect("FilterRow", content);
		GameObject gameObject4 = ((Component)val2).gameObject;
		num = UITheme.ScaledButtonHeight;
		UIHelpers.EnsureLayoutElement(gameObject4, (float?)null, num, (float?)null);
		UIFactory.AddHorizontalLayout(((Component)val2).gameObject, UITheme.S(8f), new RectOffset(0, 0, 0, 0), (TextAnchor)3, false, false, true, true);
		UIButton.Create((Transform)(object)val2, "Sort: Name", (Action)delegate
		{
			_sortMode = (PatternCatalog.SortMode)((int)(_sortMode + 1) % 4);
			RefreshFilters();
			RebuildList();
			RefreshFilterButtons();
		}, (UIButtonStyle)0, (string)null, (float?)null).SetWidth(UITheme.S(140f));
		_countText = UIText.Create((Transform)(object)val2, "Count", "0 patterns", UITheme.ScaledFontSmall, (Color?)UIColors.TextMuted, (TextAlignmentOptions)513, false);
		RectTransform obj = UIFactory.CreateRect("Mid", content);
		GameObject gameObject5 = ((Component)obj).gameObject;
		num = UITheme.S(280f);
		UIHelpers.EnsureLayoutElement(gameObject5, (float?)null, (float?)null, num).flexibleHeight = 1f;
		UIFactory.AddHorizontalLayout(((Component)obj).gameObject, UITheme.S(10f), new RectOffset(0, 0, 0, 0), (TextAnchor)0, true, true, true, true);
		_listScroll = UIScrollView.Create((Transform)(object)obj, "PatternList", true, false);
		UIHelpers.EnsureLayoutElement(_listScroll.GameObject, (float?)null, (float?)null, (float?)null).flexibleWidth = 1.2f;
		_listContent = _listScroll.Content;
		UIPanel obj2 = UIPanel.Create((Transform)(object)obj, "Preview", (Color?)UIColors.Surface, true);
		UIHelpers.EnsureLayoutElement(obj2.GameObject, (float?)null, (float?)null, (float?)null).flexibleWidth = 1f;
		_previewText = UIText.Create(obj2.Content, "PreviewText", "Select a pattern", UITheme.ScaledFontSmall, (Color?)UIColors.TextSecondary, (TextAlignmentOptions)257, true);
		UIHelpers.SetFillParent(_previewText.Rect, UITheme.S(8f));
		_statusText = UIText.Create(content, "Status", "", UITheme.ScaledFontSmall, (Color?)UIColors.Sky, (TextAlignmentOptions)513, false);
		GameObject gameObject6 = _statusText.GameObject;
		num = UITheme.S(20f);
		UIHelpers.EnsureLayoutElement(gameObject6, (float?)null, num, (float?)null);
		RectTransform obj3 = UIFactory.CreateRect("Footer", content);
		GameObject gameObject7 = ((Component)obj3).gameObject;
		num = UITheme.ScaledButtonHeight + UITheme.S(4f);
		UIHelpers.EnsureLayoutElement(gameObject7, (float?)null, num, (float?)null);
		UIFactory.AddHorizontalLayout(((Component)obj3).gameObject, UITheme.S(8f), new RectOffset(0, 0, 0, 0), (TextAnchor)3, false, false, true, true);
		UIButton.Create((Transform)(object)obj3, "Clear Override", (Action)delegate
		{
			ApplyOverride(null);
		}, (UIButtonStyle)2, (string)null, (float?)null).SetWidth(UITheme.S(130f));
		UIButton.Create((Transform)(object)obj3, "Apply", (Action)delegate
		{
			if (_selectedIndex >= 0 && _selectedIndex < PatternCatalog.CurrentFiltered.Count)
			{
				ApplyOverride(PatternCatalog.CurrentFiltered[_selectedIndex].Upgrade);
			}
		}, (UIButtonStyle)1, (string)null, (float?)null).SetWidth(UITheme.S(100f));
		UIButton.Create((Transform)(object)obj3, "Close", (Action)Close, (UIButtonStyle)0, (string)null, (float?)null).SetWidth(UITheme.S(90f));
	}

	private static void RefreshFilterButtons()
	{
		if (_countText != null)
		{
			_countText.Text = $"{PatternCatalog.CurrentFiltered.Count} patterns · {RarityFilterLabels[_rarityFilterIndex]} · {_sortMode}";
		}
	}

	private static void RefreshUi()
	{
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		if (_headerText != null && _target != null)
		{
			string text = _target.Upgrade.GetInstanceName(_target) ?? _target.Upgrade.Name;
			_headerText.Text = "Target: " + text;
		}
		if (_currentPatternText != null && _target != null)
		{
			UpgradeID overriddenPattern = _target.OverriddenPattern;
			if (overriddenPattern.ID != 0)
			{
				Upgrade upgradeFromID = PlayerData.GetUpgradeFromID(overriddenPattern);
				_currentPatternText.Text = (((Object)(object)upgradeFromID != (Object)null) ? $"Current pattern: {upgradeFromID.Name} ({PatternCatalog.SafeCellCount(upgradeFromID)} cells)" : $"Current pattern: ID {overriddenPattern.ID}");
			}
			else
			{
				_currentPatternText.Text = $"Current pattern: Original ({_targetCellCount} cells)";
			}
		}
		if (_searchField != null)
		{
			_searchField.Text = _search ?? "";
		}
		if (_sameGearToggle != null)
		{
			_sameGearToggle.IsOn = _sameGearOnly;
		}
		if (_statusText != null)
		{
			_statusText.Text = _status ?? "";
		}
		RebuildList();
		RefreshFilterButtons();
		UpdatePreview();
	}

	private static void RebuildList()
	{
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_listContent == (Object)null)
		{
			return;
		}
		UIHelpers.DestroyChildren((Transform)(object)_listContent);
		_listButtons.Clear();
		IReadOnlyList<PatternEntry> currentFiltered = PatternCatalog.CurrentFiltered;
		for (int i = 0; i < currentFiltered.Count; i++)
		{
			int index = i;
			PatternEntry patternEntry = currentFiltered[i];
			int num = patternEntry.CellCount - _targetCellCount;
			string text = ((num > 0) ? $" (+{num})" : ((num < 0) ? $" ({num})" : " (=)"));
			string text2 = $"{patternEntry.DisplayName}  [{patternEntry.Rarity}]  {patternEntry.CellCount}c{text}";
			UIButton item = UIButton.Create((Transform)(object)_listContent, text2, (Action)delegate
			{
				_selectedIndex = index;
				UpdatePreview();
			}, (UIButtonStyle)((index == _selectedIndex) ? 3 : 0), (string)null, (float?)UITheme.S(26f));
			_listButtons.Add(item);
		}
		if (_countText != null)
		{
			_countText.Text = $"{currentFiltered.Count} patterns";
		}
	}

	private static void UpdatePreview()
	{
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		if (_previewText == null)
		{
			return;
		}
		if (_selectedIndex < 0 || _selectedIndex >= PatternCatalog.CurrentFiltered.Count)
		{
			_previewText.Text = "Select a pattern to preview";
			return;
		}
		PatternEntry patternEntry = PatternCatalog.CurrentFiltered[_selectedIndex];
		HexMap val = PatternCatalog.SafePattern(patternEntry.Upgrade);
		int num = ((val != null) ? val.GetCellCount() : patternEntry.CellCount);
		int num2 = ((val != null) ? val.Width : 0);
		int num3 = ((val != null) ? val.Height : 0);
		string text = "";
		if (val != null)
		{
			for (int i = 0; i < val.Height; i++)
			{
				for (int j = 0; j < val.Width; j++)
				{
					text += (val[j, i].enabled ? "■ " : "· ");
				}
				text += "\n";
			}
		}
		_previewText.Text = $"{patternEntry.UpgradeName}\n{patternEntry.GearName} · {patternEntry.Rarity} · {num} cells ({num2}x{num3})\n\n{text}";
	}

	private static void RefreshFilters()
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		bool filterByRarity = false;
		Rarity val = (Rarity)(-1);
		_sameGearOnly = true;
		UpgradeInstance target = _target;
		if ((Object)(object)((target != null) ? target.Upgrade : null) != (Object)null)
		{
			filterByRarity = true;
			val = _target.Upgrade.Rarity;
			_rarityFilterIndex = RarityToFilterIndex(val);
		}
		IUpgradable targetGear = ((_target != null) ? _target.Gear : null);
		PatternCatalog.ApplyFilters(_search, _sameGearOnly, targetGear, filterByRarity, val, _sortMode, _targetCellCount);
		if (_selectedIndex >= PatternCatalog.CurrentFiltered.Count)
		{
			_selectedIndex = PatternCatalog.CurrentFiltered.Count - 1;
		}
	}

	private unsafe static int RarityToFilterIndex(Rarity rarity)
	{
		string b = ((object)(*(Rarity*)(&rarity))/*cast due to .constrained prefix*/).ToString();
		for (int i = 0; i < RarityFilterLabels.Length; i++)
		{
			if (string.Equals(RarityFilterLabels[i], b, StringComparison.OrdinalIgnoreCase))
			{
				return i;
			}
		}
		return 0;
	}

	private static bool IsUpgradeOnGear(Upgrade upgrade, IUpgradable gear)
	{
		if (!((Object)(object)upgrade == (Object)null))
		{
			object obj;
			if (gear == null)
			{
				obj = null;
			}
			else
			{
				GearInfo info = gear.Info;
				obj = ((info != null) ? info.Upgrades : null);
			}
			if (obj != null)
			{
				foreach (Upgrade upgrade2 in gear.Info.Upgrades)
				{
					if (upgrade2 == upgrade)
					{
						return true;
					}
				}
				return false;
			}
		}
		return false;
	}

	private static void ApplyOverride(Upgrade patternSource)
	{
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		if (_target == null)
		{
			return;
		}
		if ((Object)(object)patternSource != (Object)null)
		{
			if (patternSource.IsSkin())
			{
				_status = "Blocked: skin patterns disabled";
				if (_statusText != null)
				{
					_statusText.Text = _status;
				}
				UpgradeOptimizerPlugin.Log.LogWarning((object)("SparrohMode=false blocked skin pattern override: " + patternSource.Name));
				return;
			}
			Rarity val = (Rarity)((!((Object)(object)_target.Upgrade != (Object)null)) ? (-1) : ((int)_target.Upgrade.Rarity));
			bool flag = patternSource.Rarity == val;
			bool flag2 = _target.Gear == null || IsUpgradeOnGear(patternSource, _target.Gear);
			if (!flag2 || !flag)
			{
				_status = "Blocked: same gear and rarity only";
				if (_statusText != null)
				{
					_statusText.Text = _status;
				}
				UpgradeOptimizerPlugin.Log.LogWarning((object)("SparrohMode=false blocked pattern override: " + patternSource.Name + " " + $"(rarity match={flag}, gear match={flag2})"));
				return;
			}
		}
		try
		{
			List<(IUpgradable, sbyte, sbyte, byte)> list = CaptureEquippedPositions(_target);
			if (list.Count > 0)
			{
				PlayerData.UnequipFromAll(_target);
			}
			_target.OverridePattern(patternSource);
			int num = 0;
			foreach (var item in list)
			{
				if (CanOccupy(item.Item1, _target, item.Item2, item.Item3, item.Item4))
				{
					_target.Equip(item.Item1, item.Item2, item.Item3, item.Item4, true, false);
					num++;
				}
			}
			string text = (((Object)(object)patternSource != (Object)null) ? patternSource.Name : "Original");
			if (list.Count == 0)
			{
				_status = "Applied: " + text;
			}
			else if (num == list.Count)
			{
				_status = "Applied: " + text + " (re-equipped)";
			}
			else if (num == 0)
			{
				_status = "Applied: " + text + " (unequipped — new shape doesn't fit)";
			}
			else
			{
				_status = $"Applied: {text} (re-equipped {num}/{list.Count})";
			}
			try
			{
				HexMap pattern = _target.GetPattern(false);
				_targetCellCount = ((pattern != null) ? pattern.GetCellCount() : PatternCatalog.SafeCellCount(_target.Upgrade));
			}
			catch
			{
				_targetCellCount = PatternCatalog.SafeCellCount(_target.Upgrade);
			}
			RefreshFilters();
			RefreshUi();
			ManualLogSource log = UpgradeOptimizerPlugin.Log;
			Upgrade upgrade = _target.Upgrade;
			log.LogInfo((object)("Pattern override on " + ((upgrade != null) ? upgrade.Name : null) + " -> " + text));
		}
		catch (Exception arg)
		{
			_status = "Failed to apply override";
			UpgradeOptimizerPlugin.Log.LogError((object)$"ApplyOverride failed: {arg}");
			if (_statusText != null)
			{
				_statusText.Text = _status;
			}
		}
	}

	private static List<(IUpgradable gear, sbyte x, sbyte y, byte rot)> CaptureEquippedPositions(UpgradeInstance instance)
	{
		List<(IUpgradable, sbyte, sbyte, byte)> list = new List<(IUpgradable, sbyte, sbyte, byte)>();
		if (instance == null || (Object)(object)Global.Instance == (Object)null)
		{
			return list;
		}
		try
		{
			if (Global.Instance.Characters != null)
			{
				Character[] characters = Global.Instance.Characters;
				sbyte item = default(sbyte);
				sbyte item2 = default(sbyte);
				byte item3 = default(byte);
				foreach (Character val in characters)
				{
					if ((Object)(object)val != (Object)null && instance.IsEquipped((IUpgradable)(object)val) && instance.GetPosition((IUpgradable)(object)val, ref item, ref item2, ref item3))
					{
						list.Add(((IUpgradable)(object)val, item, item2, item3));
					}
				}
			}
			if (Global.Instance.AllGear != null)
			{
				IUpgradable[] allGear = Global.Instance.AllGear;
				sbyte item4 = default(sbyte);
				sbyte item5 = default(sbyte);
				byte item6 = default(byte);
				foreach (IUpgradable val2 in allGear)
				{
					if (val2 != null && instance.IsEquipped(val2) && instance.GetPosition(val2, ref item4, ref item5, ref item6))
					{
						list.Add((val2, item4, item5, item6));
					}
				}
			}
		}
		catch (Exception ex)
		{
			UpgradeOptimizerPlugin.Log.LogWarning((object)("CaptureEquippedPositions: " + ex.Message));
		}
		return list;
	}

	private static bool CanOccupy(IUpgradable gear, UpgradeInstance upgrade, sbyte x, sbyte y, byte rotation)
	{
		try
		{
			HexMap pattern = upgrade.GetPattern(false);
			HexMap val = ((pattern != null) ? pattern.GetModifiedMap((int)rotation, (HexMap)null) : null);
			if (val == null)
			{
				return true;
			}
			int num = default(int);
			int num2 = default(int);
			gear.Info.GetUpgradeGridSize(ref num, ref num2, false);
			if (val.Width > num + 2 || val.Height > num2 + 2)
			{
				return false;
			}
			return true;
		}
		catch
		{
			return true;
		}
	}
}
public sealed class PatternEntry
{
	public Upgrade Upgrade;

	public IUpgradable Gear;

	public string GearName;

	public string UpgradeName;

	public string DisplayName;

	public Rarity Rarity;

	public int CellCount;

	public string SearchText;
}
public static class PatternCatalog
{
	public enum SortMode
	{
		Name,
		Rarity,
		CellCount,
		CellDelta
	}

	private static readonly List<PatternEntry> AllEntries = new List<PatternEntry>(256);

	private static readonly List<PatternEntry> Filtered = new List<PatternEntry>(256);

	public static IReadOnlyList<PatternEntry> CurrentFiltered => Filtered;

	public static void Rebuild(UpgradeInstance target)
	{
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		AllEntries.Clear();
		if (target == null || PlayerData.Instance == null || PlayerData.Instance.collectedGear == null)
		{
			Filtered.Clear();
			return;
		}
		Upgrade upgrade = target.Upgrade;
		foreach (GearData value in PlayerData.Instance.collectedGear.Values)
		{
			if (((value != null) ? value.Gear : null) == null || !value.IsUnlocked || (Object)(object)value.Gear.Info == (Object)null)
			{
				continue;
			}
			IUpgradable gear = value.Gear;
			string text = gear.Info.Name;
			if (string.IsNullOrEmpty(text))
			{
				text = "Unknown Gear";
			}
			List<Upgrade> upgrades = gear.Info.Upgrades;
			if (upgrades == null)
			{
				continue;
			}
			foreach (Upgrade item in upgrades)
			{
				if (item != null && item != upgrade && !item.IsSkin())
				{
					int cellCount = SafeCellCount(item);
					string text2 = item.Name ?? item.APIName ?? "Upgrade";
					string text3 = text + " - " + text2;
					AllEntries.Add(new PatternEntry
					{
						Upgrade = item,
						Gear = gear,
						GearName = text,
						UpgradeName = text2,
						DisplayName = text3,
						Rarity = item.Rarity,
						CellCount = cellCount,
						SearchText = text3.ToLowerInvariant()
					});
				}
			}
		}
		AllEntries.Sort((PatternEntry a, PatternEntry b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase));
	}

	public static void ApplyFilters(string search, bool sameGearOnly, IUpgradable targetGear, bool filterByRarity, Rarity rarityFilter, SortMode sortMode, int targetCellCount)
	{
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		Filtered.Clear();
		string text = (string.IsNullOrWhiteSpace(search) ? null : search.Trim().ToLowerInvariant());
		sameGearOnly = true;
		filterByRarity = true;
		foreach (PatternEntry allEntry in AllEntries)
		{
			if ((!sameGearOnly || targetGear == null || allEntry.Gear == targetGear) && (!filterByRarity || allEntry.Rarity == rarityFilter) && (text == null || allEntry.SearchText.IndexOf(text, StringComparison.Ordinal) >= 0))
			{
				Filtered.Add(allEntry);
			}
		}
		switch (sortMode)
		{
		case SortMode.Rarity:
			Filtered.Sort(delegate(PatternEntry a, PatternEntry b)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				ref Rarity rarity = ref b.Rarity;
				object target = a.Rarity;
				int num = ((Enum)Unsafe.As<Rarity, Rarity>(ref rarity)/*cast due to .constrained prefix*/).CompareTo(target);
				return (num == 0) ? string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase) : num;
			});
			break;
		case SortMode.CellCount:
			Filtered.Sort(delegate(PatternEntry a, PatternEntry b)
			{
				int num = b.CellCount.CompareTo(a.CellCount);
				return (num == 0) ? string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase) : num;
			});
			break;
		case SortMode.CellDelta:
			Filtered.Sort(delegate(PatternEntry a, PatternEntry b)
			{
				int num = Math.Abs(a.CellCount - targetCellCount);
				int value = Math.Abs(b.CellCount - targetCellCount);
				int num2 = num.CompareTo(value);
				if (num2 != 0)
				{
					return num2;
				}
				num2 = b.CellCount.CompareTo(a.CellCount);
				return (num2 == 0) ? string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase) : num2;
			});
			break;
		default:
			Filtered.Sort((PatternEntry a, PatternEntry b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase));
			break;
		}
	}

	public static int SafeCellCount(Upgrade upgrade)
	{
		try
		{
			HexMap pattern = upgrade.GetPattern((UpgradeInstance)null, false);
			return (pattern != null) ? pattern.GetCellCount() : 0;
		}
		catch (Exception ex)
		{
			ManualLogSource log = UpgradeOptimizerPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("Failed to read pattern for " + ((upgrade != null) ? upgrade.Name : null) + ": " + ex.Message));
			}
			return 0;
		}
	}

	public static HexMap SafePattern(Upgrade upgrade)
	{
		try
		{
			return (upgrade != null) ? upgrade.GetPattern((UpgradeInstance)null, false) : null;
		}
		catch
		{
			return null;
		}
	}
}
public static class PatternPreview
{
	private static Texture2D _pixel;

	private static Texture2D Pixel
	{
		get
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_pixel == (Object)null)
			{
				_pixel = new Texture2D(1, 1, (TextureFormat)4, false);
				_pixel.SetPixel(0, 0, Color.white);
				_pixel.Apply();
			}
			return _pixel;
		}
	}

	public static void DrawHexMap(Rect area, HexMap map, Color cellColor, Color emptyColor)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		if (map == null || map.Width <= 0 || map.Height <= 0)
		{
			GUI.Label(area, "No pattern");
			return;
		}
		float num = ((Rect)(ref area)).width / (float)map.Width;
		float num2 = ((Rect)(ref area)).height / (float)map.Height;
		float num3 = Mathf.Min(num, num2) * 0.85f;
		float num4 = num3 * (float)map.Width;
		float num5 = num3 * (float)map.Height;
		float num6 = ((Rect)(ref area)).x + (((Rect)(ref area)).width - num4) * 0.5f;
		float num7 = ((Rect)(ref area)).y + (((Rect)(ref area)).height - num5) * 0.5f;
		Color color = GUI.color;
		for (int i = 0; i < map.Height; i++)
		{
			for (int j = 0; j < map.Width; j++)
			{
				bool enabled = map[j, i].enabled;
				float num8 = num6 + (float)j * num3 + ((j % 2 == 1) ? (num3 * 0.15f) : 0f);
				float num9 = num7 + (float)i * num3;
				GUI.color = (enabled ? cellColor : emptyColor);
				GUI.DrawTexture(new Rect(num8, num9, num3 * 0.9f, num3 * 0.9f), (Texture)(object)Pixel);
			}
		}
		GUI.color = color;
	}

	public static void DrawSideBySide(Rect area, HexMap current, HexMap selected, Color currentColor, Color selectedColor)
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		float num = 8f;
		float num2 = (((Rect)(ref area)).width - num) * 0.5f;
		Rect val = default(Rect);
		((Rect)(ref val))..ctor(((Rect)(ref area)).x, ((Rect)(ref area)).y, num2, ((Rect)(ref area)).height);
		Rect val2 = default(Rect);
		((Rect)(ref val2))..ctor(((Rect)(ref area)).x + num2 + num, ((Rect)(ref area)).y, num2, ((Rect)(ref area)).height);
		GUI.Box(val, GUIContent.none);
		GUI.Box(val2, GUIContent.none);
		GUI.Label(new Rect(((Rect)(ref val)).x + 4f, ((Rect)(ref val)).y + 2f, ((Rect)(ref val)).width - 8f, 18f), "Current");
		GUI.Label(new Rect(((Rect)(ref val2)).x + 4f, ((Rect)(ref val2)).y + 2f, ((Rect)(ref val2)).width - 8f, 18f), "Selected");
		DrawHexMap(new Rect(((Rect)(ref val)).x + 4f, ((Rect)(ref val)).y + 20f, ((Rect)(ref val)).width - 8f, ((Rect)(ref val)).height - 24f), current, currentColor, new Color(1f, 1f, 1f, 0.08f));
		DrawHexMap(new Rect(((Rect)(ref val2)).x + 4f, ((Rect)(ref val2)).y + 20f, ((Rect)(ref val2)).width - 8f, ((Rect)(ref val2)).height - 24f), selected, selectedColor, new Color(1f, 1f, 1f, 0.08f));
	}
}
[BepInPlugin("sparroh.upgradeoptimizer", "UpgradeOptimizer", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[MycoMod(/*Could not decode attribute arguments.*/)]
public class UpgradeOptimizerPlugin : BaseUnityPlugin
{
	public const string PluginGUID = "sparroh.upgradeoptimizer";

	public const string PluginName = "UpgradeOptimizer";

	public const string PluginVersion = "1.0.0";

	internal const bool SparrohMode = false;

	internal static ConfigEntry<bool> EnableBoost;

	internal static ConfigEntry<bool> EnablePatternBrowser;

	internal static ConfigEntry<bool> EnableMaxRolls;

	internal static ConfigEntry<Key> BoostHotkey;

	internal static ConfigEntry<Key> PatternBrowserHotkey;

	private Harmony _harmony;

	private FileSystemWatcher _configWatcher;

	private volatile bool _configReloadPending;

	private float _configReloadAt = -1f;

	internal static ManualLogSource Log { get; private set; }

	internal static UpgradeInstance HoveredUpgrade { get; private set; }

	private void Awake()
	{
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Expected O, but got Unknown
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		EnableBoost = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "EnableBoost", true, "Enable free boost/turbocharge toggle on hovered upgrades.");
		EnablePatternBrowser = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "EnablePatternBrowser", true, "Enable the freeform pattern browser for override infusion.");
		EnableMaxRolls = ((BaseUnityPlugin)this).Config.Bind<bool>("Features", "EnableMaxRolls", true, "Force turbocharged upgrades to always roll best property values.");
		BoostHotkey = ((BaseUnityPlugin)this).Config.Bind<Key>("Hotkeys", "BoostHotkey", (Key)29, "Hotkey that toggles boost/turbocharge on the currently hovered upgrade.");
		PatternBrowserHotkey = ((BaseUnityPlugin)this).Config.Bind<Key>("Hotkeys", "PatternBrowserHotkey", (Key)30, "Hotkey that opens/closes the pattern browser on the currently hovered upgrade.");
		_harmony = new Harmony("sparroh.upgradeoptimizer");
		_harmony.PatchAll();
		((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged;
		SetupConfigWatcher();
		Log.LogInfo((object)("UpgradeOptimizer v1.0.0 loaded. " + $"Boost={EnableBoost.Value} ({BoostHotkey.Value}), " + $"Patterns={EnablePatternBrowser.Value} ({PatternBrowserHotkey.Value}), " + $"MaxRolls={EnableMaxRolls.Value}"));
	}

	private void OnDestroy()
	{
		((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged;
		TeardownConfigWatcher();
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	private void Update()
	{
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			ProcessPendingConfigReload();
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return;
			}
			UpdateHoveredUpgrade();
			if (IsTypingInSearchField())
			{
				if (EnablePatternBrowser.Value && PatternBrowser.IsOpen && WasHotkeyPressed(current, (Key)60))
				{
					PatternBrowser.Close();
				}
				return;
			}
			if (EnableBoost.Value)
			{
				BoostFeature.TryHandleHotkey(current, BoostHotkey.Value);
			}
			if (EnablePatternBrowser.Value)
			{
				HandlePatternBrowserHotkeys(current);
			}
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Update error: " + ex));
		}
	}

	private void OnGUI()
	{
		if (!EnablePatternBrowser.Value)
		{
			return;
		}
		try
		{
			PatternBrowser.Draw();
		}
		catch (Exception ex)
		{
			Log.LogError((object)("OnGUI error: " + ex));
		}
	}

	private void OnSettingChanged(object sender, SettingChangedEventArgs e)
	{
		if (e.ChangedSetting != null)
		{
			if ((object)e.ChangedSetting == EnablePatternBrowser && !EnablePatternBrowser.Value && PatternBrowser.IsOpen)
			{
				PatternBrowser.Close();
			}
			Log.LogInfo((object)$"Config updated: [{e.ChangedSetting.Definition.Section}] {e.ChangedSetting.Definition.Key} = {e.ChangedSetting.BoxedValue}");
		}
	}

	private void SetupConfigWatcher()
	{
		try
		{
			string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
			if (string.IsNullOrEmpty(configFilePath))
			{
				return;
			}
			string directoryName = Path.GetDirectoryName(configFilePath);
			string fileName = Path.GetFileName(configFilePath);
			if (!string.IsNullOrEmpty(directoryName) && !string.IsNullOrEmpty(fileName))
			{
				if (!File.Exists(configFilePath))
				{
					((BaseUnityPlugin)this).Config.Save();
				}
				_configWatcher = new FileSystemWatcher(directoryName, fileName)
				{
					NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite),
					EnableRaisingEvents = true
				};
				_configWatcher.Changed += OnConfigFileChanged;
				_configWatcher.Created += OnConfigFileChanged;
				_configWatcher.Renamed += OnConfigFileChanged;
				Log.LogInfo((object)("Config hot-reload watching: " + configFilePath));
			}
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Config file watcher unavailable: " + ex.Message));
		}
	}

	private void TeardownConfigWatcher()
	{
		if (_configWatcher != null)
		{
			try
			{
				_configWatcher.EnableRaisingEvents = false;
				_configWatcher.Changed -= OnConfigFileChanged;
				_configWatcher.Created -= OnConfigFileChanged;
				_configWatcher.Renamed -= OnConfigFileChanged;
				_configWatcher.Dispose();
			}
			catch
			{
			}
			_configWatcher = null;
		}
	}

	private void OnConfigFileChanged(object sender, FileSystemEventArgs e)
	{
		_configReloadPending = true;
	}

	private void ProcessPendingConfigReload()
	{
		if (_configReloadPending)
		{
			_configReloadPending = false;
			_configReloadAt = Time.unscaledTime + 0.25f;
		}
		if (_configReloadAt < 0f || Time.unscaledTime < _configReloadAt)
		{
			return;
		}
		_configReloadAt = -1f;
		try
		{
			((BaseUnityPlugin)this).Config.Reload();
			Log.LogInfo((object)"Config reloaded from disk.");
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Config reload failed: " + ex.Message));
		}
	}

	private static void HandlePatternBrowserHotkeys(Keyboard keyboard)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		if (WasHotkeyPressed(keyboard, (Key)60) && PatternBrowser.IsOpen)
		{
			PatternBrowser.Close();
		}
		else if (WasHotkeyPressed(keyboard, PatternBrowserHotkey.Value))
		{
			if (PatternBrowser.IsOpen)
			{
				PatternBrowser.Close();
			}
			else if (HoveredUpgrade != null && HoveredUpgrade.IsUnlocked)
			{
				PatternBrowser.Open(HoveredUpgrade);
			}
		}
	}

	private static void UpdateHoveredUpgrade()
	{
		if ((Object)(object)HoverInfoDisplay.Instance != (Object)null)
		{
			HoverInfo selectedInfo = HoverInfoDisplay.Instance.SelectedInfo;
			HoverInfoUpgrade val = (HoverInfoUpgrade)(object)((selectedInfo is HoverInfoUpgrade) ? selectedInfo : null);
			if (val != null && val.Upgrade != null)
			{
				HoveredUpgrade = val.Upgrade;
				return;
			}
		}
		GearUpgradeUI val2 = default(GearUpgradeUI);
		UpgradeIcon val3 = default(UpgradeIcon);
		if (UIRaycaster.RaycastForComponent<GearUpgradeUI>(ref val2) && (Object)(object)val2 != (Object)null && ((HoverInfoUpgrade)val2).Upgrade != null)
		{
			HoveredUpgrade = ((HoverInfoUpgrade)val2).Upgrade;
		}
		else if (UIRaycaster.RaycastForComponent<UpgradeIcon>(ref val3) && (Object)(object)val3 != (Object)null && ((HoverInfoUpgrade)val3).Upgrade != null)
		{
			HoveredUpgrade = ((HoverInfoUpgrade)val3).Upgrade;
		}
		else
		{
			HoveredUpgrade = null;
		}
	}

	internal static bool WasHotkeyPressed(Keyboard keyboard, Key key)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			return ((ButtonControl)keyboard[key]).wasPressedThisFrame;
		}
		catch
		{
			return false;
		}
	}

	internal static bool IsTypingInSearchField()
	{
		EventSystem current = EventSystem.current;
		GameObject val = ((current != null) ? current.currentSelectedGameObject : null);
		if ((Object)(object)val != (Object)null)
		{
			return (Object)(object)val.GetComponent<TMP_InputField>() != (Object)null;
		}
		return false;
	}
}
namespace UpgradeOptimizer
{
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "UpgradeOptimizer";

		public const string PLUGIN_NAME = "UpgradeOptimizer";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}