Decompiled source of MoreShopUpgrades v1.4.1

MorePots.dll

Decompiled 10 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Assets.Scripts.Actors;
using Assets.Scripts.Actors.Enemies;
using Assets.Scripts.Actors.Player;
using Assets.Scripts.Game.Combat.ConstantAttacks;
using Assets.Scripts.Game.MapGeneration;
using Assets.Scripts.Inventory__Items__Pickups;
using Assets.Scripts.Inventory__Items__Pickups.GoldAndMoney;
using Assets.Scripts.Inventory__Items__Pickups.Interactables;
using Assets.Scripts.Inventory__Items__Pickups.Items;
using Assets.Scripts.Inventory__Items__Pickups.Items.ItemImplementations;
using Assets.Scripts.Inventory__Items__Pickups.Stats;
using Assets.Scripts.Inventory__Items__Pickups.Weapons;
using Assets.Scripts.Inventory__Items__Pickups.Weapons.Projectiles;
using Assets.Scripts.Managers;
using Assets.Scripts.Menu.Shop;
using Assets.Scripts.Saves___Serialization.Progression;
using Assets.Scripts.Saves___Serialization.Progression.Achievements;
using Assets.Scripts.Saves___Serialization.SaveFiles;
using Assets.Scripts.Saves___Serialization.SaveFiles.Configs;
using Assets.Scripts.Saves___Serialization.SaveFiles.Configs.ConfigSettingsTypes;
using Assets.Scripts.Settings___Saves.SaveFiles;
using Assets.Scripts.Settings___Saves.SaveFiles.ConfigSaves;
using Assets.Scripts.Settings___Saves.SaveFiles.ConfigSettingsTypes;
using Assets.Scripts.UI.InGame.Rewards;
using Assets.Scripts.Utility;
using Assets.Scripts._Data;
using Assets.Scripts._Data.ShopItems;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Common;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Inventory__Items__Pickups.Pickups;
using Microsoft.CodeAnalysis;
using Rewired;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MorePots")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.38.0.0")]
[assembly: AssemblyInformationalVersion("0.38.0+9583c9456c88608702ad5b96818742c7ac815822")]
[assembly: AssemblyProduct("MorePots")]
[assembly: AssemblyTitle("MorePots")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.38.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;
		}
	}
}
namespace MorePots
{
	internal static class AuraTint
	{
		private class Tinted
		{
			internal readonly List<Renderer> renderers = new List<Renderer>();

			internal readonly List<MaterialPropertyBlock> saved = new List<MaterialPropertyBlock>();

			internal readonly List<ParticleSystem> particles = new List<ParticleSystem>();

			internal readonly List<MinMaxGradient> savedStart = new List<MinMaxGradient>();

			internal CombatAura combatAura;

			internal Color[] savedDefaults;

			internal bool on;
		}

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<string> TintColor;

		private static readonly Dictionary<IntPtr, Tinted> byWeapon = new Dictionary<IntPtr, Tinted>();

		private static float nextScan;

		private static readonly int[] colorIds = new int[5]
		{
			Shader.PropertyToID("_Tint"),
			Shader.PropertyToID("_Color"),
			Shader.PropertyToID("_TintColor"),
			Shader.PropertyToID("_BaseColor"),
			Shader.PropertyToID("_MainColor")
		};

		private static readonly Dictionary<IntPtr, bool> wasActive = new Dictionary<IntPtr, bool>();

		private static string lastScanReport;

		internal static void Bind(ConfigFile config)
		{
			Enabled = config.Bind<bool>("ManualFire", "PassiveIdleTint", true, "Passive weapons' effect is tinted (gray) while not triggered, and shows its normal colour while triggered or while holding with Auto Fire.");
			TintColor = config.Bind<string>("ManualFire", "PassiveIdleColor", "#7A7A7AFF", "Tint colour for passive weapons while not triggered, as #RRGGBB or #RRGGBBAA.");
		}

		internal static void Tick(List<WeaponBase> alwaysOnSelected, bool holdingAuto)
		{
			PassiveFx.SetHum(holdingAuto && alwaysOnSelected.Count > 0);
			if (!Enabled.Value)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime >= nextScan)
			{
				nextScan = unscaledTime + 2f;
				Scan();
			}
			foreach (KeyValuePair<IntPtr, Tinted> kv in byWeapon)
			{
				WeaponBase val = null;
				foreach (WeaponBase item in AllAlwaysOn())
				{
					if (((Il2CppObjectBase)item).Pointer == kv.Key)
					{
						val = item;
						break;
					}
				}
				bool flag = val != null && (ManualFire.InFullWindow(val) || (holdingAuto && alwaysOnSelected.Exists((WeaponBase w) => ((Il2CppObjectBase)w).Pointer == kv.Key)));
				bool flag2 = val != null && !flag;
				if (flag2 != kv.Value.on)
				{
					Set(kv.Value, flag2);
				}
				else if (flag2)
				{
					Reapply(kv.Value);
				}
			}
		}

		private static Color Tint()
		{
			//IL_002d: 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)
			Color result = default(Color);
			if (!ColorUtility.TryParseHtmlString(TintColor.Value, ref result))
			{
				return new Color(0.48f, 0.48f, 0.48f, 1f);
			}
			return result;
		}

		internal static void Clear()
		{
			wasActive.Clear();
			foreach (Tinted value in byWeapon.Values)
			{
				if (value.on)
				{
					Set(value, on: false);
				}
			}
			byWeapon.Clear();
		}

		private static List<WeaponBase> AllAlwaysOn()
		{
			List<WeaponBase> list = new List<WeaponBase>();
			MyPlayer instance = MyPlayer.Instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				PlayerInventory inventory = instance.inventory;
				obj = ((inventory != null) ? inventory.weaponInventory : null);
			}
			WeaponInventory val = (WeaponInventory)obj;
			if (val == null)
			{
				return list;
			}
			Enumerator<EWeapon, WeaponBase> enumerator = val.weapons.GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyValuePair<EWeapon, WeaponBase> current = enumerator.Current;
				if (ManualFire.IsAlwaysOn(current.Value))
				{
					list.Add(current.Value);
				}
			}
			return list;
		}

		private static void Scan()
		{
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Expected O, but got Unknown
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Expected O, but got Unknown
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0421: Unknown result type (might be due to invalid IL or missing references)
			//IL_0428: Expected O, but got Unknown
			Il2CppArrayBase<ConstantAttack> val = Object.FindObjectsOfType<ConstantAttack>(true);
			List<string> list = new List<string>();
			foreach (ConstantAttack item in val)
			{
				DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 4);
				defaultInterpolatedStringHandler.AppendFormatted(((MemberInfo)((Object)item).GetIl2CppType()).Name);
				defaultInterpolatedStringHandler.AppendLiteral(":");
				WeaponBase weaponBase = item.weaponBase;
				defaultInterpolatedStringHandler.AppendFormatted(((Object)(object)((weaponBase != null) ? weaponBase.weaponData : null) != (Object)null) ? ((object)item.weaponBase.weaponData.eWeapon/*cast due to .constrained prefix*/).ToString() : "no weapon");
				defaultInterpolatedStringHandler.AppendLiteral(":");
				defaultInterpolatedStringHandler.AppendFormatted(((Component)item).gameObject.activeInHierarchy ? "active" : "inactive");
				defaultInterpolatedStringHandler.AppendLiteral(":");
				defaultInterpolatedStringHandler.AppendFormatted((item.weaponBase != null && ManualFire.IsAlwaysOn(item.weaponBase)) ? "passive" : "-");
				list.Add(defaultInterpolatedStringHandler.ToStringAndClear());
			}
			string text = string.Join(", ", list);
			bool flag = default(bool);
			if (text != lastScanReport)
			{
				lastScanReport = text;
				ManualLogSource log = Plugin.Log;
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(43, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Aura tint: scan found ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(val.Length);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" constant attack(s): ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text);
				}
				log.LogInfo(val2);
			}
			foreach (ConstantAttack item2 in val)
			{
				WeaponBase weaponBase2 = item2.weaponBase;
				if (weaponBase2 == null || !ManualFire.IsAlwaysOn(weaponBase2) || byWeapon.ContainsKey(((Il2CppObjectBase)weaponBase2).Pointer))
				{
					continue;
				}
				Tinted tinted = new Tinted();
				foreach (Renderer componentsInChild in ((Component)item2).gameObject.GetComponentsInChildren<Renderer>(true))
				{
					tinted.renderers.Add(componentsInChild);
					MaterialPropertyBlock val3 = new MaterialPropertyBlock();
					componentsInChild.GetPropertyBlock(val3);
					tinted.saved.Add(val3);
				}
				foreach (ParticleSystem componentsInChild2 in ((Component)item2).gameObject.GetComponentsInChildren<ParticleSystem>(true))
				{
					tinted.particles.Add(componentsInChild2);
					tinted.savedStart.Add(componentsInChild2.main.startColor);
				}
				tinted.combatAura = ((Component)item2).gameObject.GetComponent<CombatAura>();
				byWeapon[((Il2CppObjectBase)weaponBase2).Pointer] = tinted;
				ManualLogSource log2 = Plugin.Log;
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(73, 4, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Aura tint: ");
					BepInExInfoLogInterpolatedStringHandler obj = val2;
					WeaponData weaponData = weaponBase2.weaponData;
					((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<EWeapon?>((weaponData != null) ? new EWeapon?(weaponData.eWeapon) : ((EWeapon?)null));
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" has ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(tinted.renderers.Count);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" renderer(s), ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(tinted.particles.Count);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" particle system(s), combat aura colours: ");
					BepInExInfoLogInterpolatedStringHandler obj2 = val2;
					CombatAura combatAura = tinted.combatAura;
					((BepInExLogInterpolatedStringHandler)obj2).AppendFormatted<int>((((combatAura != null) ? combatAura.defaultColors : null) != null) ? ((Il2CppArrayBase<Color>)(object)tinted.combatAura.defaultColors).Length : 0);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
				}
				log2.LogInfo(val2);
				foreach (Renderer renderer in tinted.renderers)
				{
					Material val4 = ((renderer != null) ? renderer.sharedMaterial : null);
					if ((Object)(object)((val4 != null) ? val4.shader : null) == (Object)null)
					{
						continue;
					}
					List<string> list2 = new List<string>();
					for (int i = 0; i < val4.shader.GetPropertyCount(); i++)
					{
						if ((int)val4.shader.GetPropertyType(i) == 0)
						{
							list2.Add(val4.shader.GetPropertyName(i));
						}
					}
					ManualLogSource log3 = Plugin.Log;
					val2 = new BepInExInfoLogInterpolatedStringHandler(46, 3, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Aura tint:   ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)renderer).name);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": shader '");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)val4.shader).name);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("', colour properties [");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(string.Join(", ", list2));
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("]");
					}
					log3.LogInfo(val2);
				}
			}
		}

		private static void Reapply(Tinted t)
		{
			//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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			Color val = Tint();
			foreach (Renderer renderer in t.renderers)
			{
				if (!((Object)(object)renderer == (Object)null))
				{
					MaterialPropertyBlock val2 = new MaterialPropertyBlock();
					renderer.GetPropertyBlock(val2);
					int[] array = colorIds;
					foreach (int num in array)
					{
						val2.SetColor(num, val);
					}
					renderer.SetPropertyBlock(val2);
				}
			}
			CombatAura combatAura = t.combatAura;
			Il2CppStructArray<Color> val3 = ((combatAura != null) ? combatAura.defaultColors : null);
			if (val3 != null)
			{
				for (int j = 0; j < ((Il2CppArrayBase<Color>)(object)val3).Length; j++)
				{
					((Il2CppArrayBase<Color>)(object)val3)[j] = new Color(val.r, val.g, val.b, ((Il2CppArrayBase<Color>)(object)val3)[j].a);
				}
			}
		}

		private static void Set(Tinted t, bool on)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_002e: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			t.on = on;
			for (int i = 0; i < t.renderers.Count; i++)
			{
				Renderer val = t.renderers[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				if (on)
				{
					MaterialPropertyBlock val2 = new MaterialPropertyBlock();
					val.GetPropertyBlock(val2);
					t.saved[i] = val2;
					MaterialPropertyBlock val3 = new MaterialPropertyBlock();
					val.GetPropertyBlock(val3);
					int[] array = colorIds;
					foreach (int num in array)
					{
						val3.SetColor(num, Tint());
					}
					val.SetPropertyBlock(val3);
				}
				else
				{
					val.SetPropertyBlock(t.saved[i]);
				}
			}
			Color val4 = Tint();
			CombatAura combatAura = t.combatAura;
			Il2CppStructArray<Color> val5 = ((combatAura != null) ? combatAura.defaultColors : null);
			if (val5 == null)
			{
				return;
			}
			if (on)
			{
				t.savedDefaults = (Color[])(object)new Color[((Il2CppArrayBase<Color>)(object)val5).Length];
				for (int k = 0; k < ((Il2CppArrayBase<Color>)(object)val5).Length; k++)
				{
					t.savedDefaults[k] = ((Il2CppArrayBase<Color>)(object)val5)[k];
					((Il2CppArrayBase<Color>)(object)val5)[k] = new Color(val4.r, val4.g, val4.b, ((Il2CppArrayBase<Color>)(object)val5)[k].a);
				}
			}
			else if (t.savedDefaults != null)
			{
				for (int l = 0; l < ((Il2CppArrayBase<Color>)(object)val5).Length && l < t.savedDefaults.Length; l++)
				{
					((Il2CppArrayBase<Color>)(object)val5)[l] = t.savedDefaults[l];
				}
			}
		}
	}
	internal static class AutoPots
	{
		internal enum SilverMode
		{
			Fly,
			Instant,
			Drop
		}

		internal static CustomShopItem Shop;

		internal static ConfigEntry<float> Radius;

		internal static ConfigEntry<float> RangeMultiplierPerLevel;

		internal static ConfigEntry<int> MaxPerCheck;

		internal static ConfigEntry<SilverMode> Silver;

		internal static int CoinsSent;

		internal static int SilverCollected;

		private static int loggedSent = -1;

		private static float nextSummary;

		internal static bool Breaking;

		private static readonly List<InteractablePot> pots = new List<InteractablePot>();

		private static readonly List<(float d2, int index)> inRange = new List<(float, int)>();

		private static bool listDirty = true;

		private static float nextCheck;

		internal static bool Active => Shop.CurrentLevel > 0;

		internal static float CurrentRange => RangeAt(Shop.CurrentLevel);

		internal static void Bind(ConfigFile config, ConfigFile progress)
		{
			ConfigEntry<string> prices = config.Bind<string>("AutoPots", "Prices", "200,200,200,200,200,200", "Silver price of each Auto Pots level, comma separated. The count sets the max level.");
			Radius = config.Bind<float>("AutoPots", "Radius", 4f, "Range at level 1, in world units.");
			RangeMultiplierPerLevel = config.Bind<float>("AutoPots", "RangeMultiplierPerLevel", 2f, "Each level after the first multiplies the range by this.");
			Silver = config.Bind<SilverMode>("AutoPots", "SilverFromAutoPots", SilverMode.Fly, "Fly: silver coins from auto-broken pots fly to you from wherever the pot was. Instant: added straight to your silver, no coins. Drop: coins stay where the pot was (the game's default; far ones are rarely collected).");
			MaxPerCheck = config.Bind<int>("AutoPots", "MaxPotsPerCheck", 25, "Most pots broken per check (10 checks a second), closest first, so a huge range can't freeze the game.");
			Shop = new CustomShopItem(104, "Auto Pots", progress.Bind<int>("Progress", "AutoPotsLevel", 0, "Levels of the Auto Pots shop upgrade bought. Managed by the mod."), () => CustomShopItem.ParsePrices(prices.Value), Description, (string name) => name == "ItemPot");
		}

		internal static float RangeAt(int level)
		{
			if (level > 0)
			{
				return Radius.Value * MathF.Pow(RangeMultiplierPerLevel.Value, level - 1);
			}
			return 0f;
		}

		private static string Description()
		{
			return $"Pots within range break automatically, no button needed, and their silver flies to you. Each level after the first multiplies the range by {RangeMultiplierPerLevel.Value:0.#}.";
		}

		internal static void MarkDirty()
		{
			listDirty = true;
		}

		private static void LogSummary()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			float unscaledTime = Time.unscaledTime;
			if (!(unscaledTime < nextSummary) && CoinsSent != loggedSent)
			{
				nextSummary = unscaledTime + 10f;
				loggedSent = CoinsSent;
				MyPlayer instance = MyPlayer.Instance;
				object obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					PlayerInventory inventory = instance.inventory;
					obj = ((inventory != null) ? inventory.playerStats : null);
				}
				PlayerStatsNew val = (PlayerStatsNew)obj;
				string text = ((val == null) ? "?" : val.GetStat((EStat)49).ToString("0.##"));
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(106, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Auto Pots: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(CoinsSent);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" silver coins sent flying to you; ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(SilverCollected);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" silver collected this session (all sources); silver bonus x");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
				}
				log.LogInfo(val2);
			}
		}

		internal static void Tick()
		{
			//IL_00e7: 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_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: 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_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			if (!Active || MyTime.paused)
			{
				return;
			}
			LogSummary();
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime < nextCheck)
			{
				return;
			}
			nextCheck = unscaledTime + 0.1f;
			MyPlayer instance = MyPlayer.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			if (listDirty)
			{
				listDirty = false;
				pots.Clear();
				foreach (InteractablePot item2 in Object.FindObjectsOfType<InteractablePot>())
				{
					if (!item2.broken)
					{
						pots.Add(item2);
					}
				}
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(26, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Auto Pots: tracking ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(pots.Count);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" pots.");
				}
				log.LogInfo(val);
			}
			Vector3 position = ((Component)instance).transform.position;
			float currentRange = CurrentRange;
			float num = currentRange * currentRange;
			pots.RemoveAll((InteractablePot pot) => (Object)(object)pot == (Object)null || pot.broken);
			inRange.Clear();
			for (int num2 = 0; num2 < pots.Count; num2++)
			{
				Vector3 val2 = ((Component)pots[num2]).transform.position - position;
				float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
				if (sqrMagnitude <= num)
				{
					inRange.Add((sqrMagnitude, num2));
				}
			}
			if (inRange.Count == 0)
			{
				return;
			}
			inRange.Sort(((float d2, int index) a, (float d2, int index) b) => a.d2.CompareTo(b.d2));
			int num3 = Math.Min(inRange.Count, Math.Max(1, MaxPerCheck.Value));
			List<int> list = new List<int>(num3);
			for (int num4 = 0; num4 < num3; num4++)
			{
				int item = inRange[num4].index;
				Breaking = true;
				try
				{
					((BaseInteractable)pots[item]).Interact();
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Auto Pots: breaking a pot failed: " + ex.Message));
				}
				finally
				{
					Breaking = false;
				}
				list.Add(item);
			}
			list.Sort();
			for (int num5 = list.Count - 1; num5 >= 0; num5--)
			{
				pots.RemoveAt(list[num5]);
			}
		}
	}
	[HarmonyPatch(typeof(RandomObjectPlacer), "RandomObjectSpawner")]
	internal static class RandomObjectPlacer_RandomObjectSpawner_AutoPots
	{
		private static void Postfix()
		{
			AutoPots.MarkDirty();
		}
	}
	[HarmonyPatch(typeof(MyTime), "OnNewStageStarted")]
	internal static class MyTime_OnNewStageStarted_AutoPots
	{
		private static void Postfix()
		{
			AutoPots.MarkDirty();
		}
	}
	[HarmonyPatch(typeof(MyTime), "Update")]
	internal static class MyTime_Update_AutoPots
	{
		private static void Postfix()
		{
			AutoPots.Tick();
		}
	}
	[HarmonyPatch(typeof(MoneyUtility), "SpawnSilverNoTimerImpact")]
	internal static class MoneyUtility_SpawnSilverNoTimerImpact_AutoPots
	{
		private static bool Prefix(int amount)
		{
			if (!AutoPots.Breaking || AutoPots.Silver.Value != AutoPots.SilverMode.Instant)
			{
				return true;
			}
			MyPlayer instance = MyPlayer.Instance;
			PlayerInventory val = ((instance != null) ? instance.inventory : null);
			if (val == null)
			{
				return true;
			}
			val.AddSilver(amount);
			return false;
		}
	}
	[HarmonyPatch(typeof(SilverFlying), "Set")]
	internal static class SilverFlying_Set_AutoPots
	{
		private static void Postfix(SilverFlying __instance)
		{
			if (AutoPots.Breaking && AutoPots.Silver.Value == AutoPots.SilverMode.Fly)
			{
				MyPlayer instance = MyPlayer.Instance;
				if (!((Object)(object)instance == (Object)null))
				{
					__instance.target = ((Component)instance).transform;
					AutoPots.CoinsSent++;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerInventory), "AddSilver")]
	internal static class PlayerInventory_AddSilver_AutoPots
	{
		private static void Postfix(int amount)
		{
			AutoPots.SilverCollected += amount;
		}
	}
	internal static class AutoShrineRewards
	{
		internal enum PickMode
		{
			Best,
			Random
		}

		internal static CustomShopItem Shop;

		internal static ConfigEntry<PickMode> Mode;

		internal static ConfigEntry<string> Encounters;

		internal static ConfigEntry<float> Delay;

		internal static EEncounter OpenType;

		internal static float OpenedAt;

		internal static bool Pending;

		internal static bool Active => Shop.CurrentLevel > 0;

		internal static void Bind(ConfigFile config, ConfigFile progress)
		{
			Mode = config.Bind<PickMode>("AutoShrineRewards", "Mode", PickMode.Best, "Best: highest rarity offer. Random: any offer.");
			Encounters = config.Bind<string>("AutoShrineRewards", "Encounters", "RandomStats", "Reward windows to auto-pick, comma separated (RandomStats = charge shrine). The log names each window type as it opens.");
			Delay = config.Bind<float>("AutoShrineRewards", "DelaySeconds", 0f, "0 = pick instantly, before the window is ever drawn. Above 0: seconds the window stays open (so you can see the offers) before picking.");
			ConfigEntry<int> price = config.Bind<int>("AutoShrineRewards", "Price", 300, "Silver price of the Auto Shrine Rewards upgrade.");
			Shop = new CustomShopItem(106, "Auto Shrine Rewards", progress.Bind<int>("Progress", "AutoShrineRewardsLevel", 0, "1 when the Auto Shrine Rewards shop upgrade is owned. Managed by the mod."), () => new int[1] { price.Value }, Description, null);
		}

		private static string Description()
		{
			return "Free. Charge shrine rewards are picked for you instantly (" + ((Mode.Value == PickMode.Best) ? "highest rarity" : "random") + "). Refund to turn it off.";
		}

		internal unsafe static bool Handles(EEncounter type)
		{
			string[] array = Encounters.Value.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
			for (int i = 0; i < array.Length; i++)
			{
				if (string.Equals(array[i], ((object)(*(EEncounter*)(&type))/*cast due to .constrained prefix*/).ToString(), StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static int Rank(ERarity r)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Expected I4, but got Unknown
			if ((int)r != 0)
			{
				return (int)r;
			}
			return -1;
		}

		internal static void TryPick(EncounterUi ui)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Expected O, but got Unknown
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if (!Pending || Time.unscaledTime - OpenedAt < Delay.Value)
			{
				return;
			}
			Pending = false;
			Il2CppReferenceArray<EncounterOffer> offers = ui.offers;
			if (offers == null || ((Il2CppArrayBase<EncounterOffer>)(object)offers).Length == 0)
			{
				return;
			}
			List<int> list = new List<int>();
			string text = default(string);
			for (int i = 0; i < ((Il2CppArrayBase<EncounterOffer>)(object)offers).Length; i++)
			{
				EncounterOffer val = ((Il2CppArrayBase<EncounterOffer>)(object)offers)[i];
				if (val != null && val.CanAccept(ref text))
				{
					list.Add(i);
				}
			}
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2;
			if (list.Count == 0)
			{
				ManualLogSource log = Plugin.Log;
				val2 = new BepInExInfoLogInterpolatedStringHandler(64, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Auto Shrine Rewards: no acceptable offer in ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<EEncounter>(OpenType);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; leaving it to you.");
				}
				log.LogInfo(val2);
				return;
			}
			int num;
			if (Mode.Value == PickMode.Random)
			{
				num = list[Random.Range(0, list.Count)];
			}
			else
			{
				num = list[0];
				foreach (int item in list)
				{
					if (Rank(((Il2CppArrayBase<EncounterOffer>)(object)offers)[item].rarity) > Rank(((Il2CppArrayBase<EncounterOffer>)(object)offers)[num].rarity))
					{
						num = item;
					}
				}
			}
			ManualLogSource log2 = Plugin.Log;
			val2 = new BepInExInfoLogInterpolatedStringHandler(46, 6, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Auto Shrine Rewards: ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<EEncounter>(OpenType);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" picked offer ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num + 1);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" of ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(((Il2CppArrayBase<EncounterOffer>)(object)offers).Length);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<ERarity>(((Il2CppArrayBase<EncounterOffer>)(object)offers)[num].rarity);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<PickMode>(Mode.Value);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("): ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Il2CppArrayBase<EncounterOffer>)(object)offers)[num].GetEffectsDescription());
			}
			log2.LogInfo(val2);
			((BaseEncounterWindow)ui).ChooseOffer(num);
		}
	}
	[HarmonyPatch(typeof(EncounterUi), "Open")]
	internal static class EncounterUi_Open
	{
		private static void Postfix(EncounterUi __instance, EEncounter encounterType)
		{
			//IL_0007: 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_0021: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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)
			bool flag = AutoShrineRewards.Active && AutoShrineRewards.Handles(encounterType);
			ManualLogSource log = Plugin.Log;
			bool flag2 = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(22, 2, ref flag2);
			if (flag2)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Reward window opened: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<EEncounter>(encounterType);
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(flag ? " (auto-pick)" : "");
			}
			log.LogInfo(val);
			AutoShrineRewards.OpenType = encounterType;
			AutoShrineRewards.OpenedAt = Time.unscaledTime;
			AutoShrineRewards.Pending = flag;
			if (flag && AutoShrineRewards.Delay.Value <= 0f)
			{
				try
				{
					AutoShrineRewards.TryPick(__instance);
				}
				catch (Exception ex)
				{
					AutoShrineRewards.Pending = false;
					Plugin.Log.LogError((object)("Auto Shrine Rewards failed: " + ex));
				}
			}
		}
	}
	[HarmonyPatch(typeof(EncounterUi), "Update")]
	internal static class EncounterUi_Update
	{
		private static void Postfix(EncounterUi __instance)
		{
			if (!AutoShrineRewards.Pending)
			{
				return;
			}
			try
			{
				AutoShrineRewards.TryPick(__instance);
			}
			catch (Exception ex)
			{
				AutoShrineRewards.Pending = false;
				Plugin.Log.LogError((object)("Auto Shrine Rewards failed: " + ex));
			}
		}
	}
	[HarmonyPatch(typeof(EncounterUi), "OnClose")]
	internal static class EncounterUi_OnClose
	{
		private static void Postfix()
		{
			AutoShrineRewards.Pending = false;
		}
	}
	internal static class ButtonFit
	{
		internal const float SidePadding = 40f;

		private static readonly HashSet<string> logged = new HashSet<string>();

		internal static void Fit(GameObject button, TextMeshProUGUI label)
		{
			//IL_001b: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Expected O, but got Unknown
			RectTransform component = button.GetComponent<RectTransform>();
			((TMP_Text)label).enableAutoSizing = false;
			((TMP_Text)label).textWrappingMode = (TextWrappingModes)0;
			float x = ((TMP_Text)label).GetPreferredValues(((TMP_Text)label).text).x;
			TextSizer component2 = ((Component)label).gameObject.GetComponent<TextSizer>();
			if ((Object)(object)component2 != (Object)null)
			{
				if (component2.MaxSize.x > 0f && component2.MaxSize.x < x + component2.Padding.x * 2f)
				{
					component2.MaxSize = new Vector2(x + component2.Padding.x * 2f, component2.MaxSize.y);
				}
				component2.Refresh();
			}
			ButtonTextWrapper component3 = button.GetComponent<ButtonTextWrapper>();
			if (component3 != null)
			{
				component3.Refresh();
			}
			float num = x + 80f;
			LayoutElement obj = button.GetComponent<LayoutElement>() ?? button.AddComponent<LayoutElement>();
			obj.minWidth = num;
			obj.preferredWidth = num;
			component.SetSizeWithCurrentAnchors((Axis)0, num);
			if ((Object)(object)button.transform.parent != (Object)null)
			{
				LayoutRebuilder.MarkLayoutForRebuild(((Component)button.transform.parent).gameObject.GetComponent<RectTransform>());
			}
			if (logged.Add(((Object)button).name))
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(49, 4, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Button '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)button).name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("': width ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num, "F0");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" for text ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(x, "F0");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" + ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(40f, "F0");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" padding each side.");
				}
				log.LogInfo(val);
			}
		}
	}
	internal static class ChestSkip
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<KeyCode> ExtraKey;

		internal static ConfigEntry<KeyCode> ExtraPadButton;

		internal static bool Forcing;

		private static bool loggedAction;

		internal static void Bind(ConfigFile config)
		{
			Enabled = config.Bind<bool>("Chests", "JumpSkipsChestAnimation", true, "Press jump to skip the chest opening animation.");
			ExtraKey = config.Bind<KeyCode>("Chests", "SkipKey", (KeyCode)32, "Keyboard key that also skips (in case jump is disabled while the chest window is open).");
			ExtraPadButton = config.Bind<KeyCode>("Chests", "SkipPadButton", (KeyCode)330, "Controller button that also skips (JoystickButton0 = A on Xbox pads).");
		}

		internal static bool JumpPressed()
		{
			//IL_001a: 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)
			bool flag = false;
			try
			{
				flag = MyInputManager.GetButtonDown(MyInputManager.Jump);
			}
			catch
			{
			}
			if (!flag && !Input.GetKeyDown(ExtraKey.Value))
			{
				return Input.GetKeyDown(ExtraPadButton.Value);
			}
			return true;
		}

		internal static void LogForcedAction(string action)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!loggedAction)
			{
				loggedAction = true;
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(49, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Chest skip: chest asked for '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(action);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("', answered pressed.");
				}
				log.LogInfo(val);
			}
		}
	}
	[HarmonyPatch(typeof(ChestOpening), "Update")]
	internal static class ChestOpening_Update
	{
		private static void Prefix(ChestOpening __instance)
		{
			ChestSkip.Forcing = ChestSkip.Enabled.Value && __instance.canSkip && !__instance.skipped && ChestSkip.JumpPressed();
		}

		private static void Postfix(ChestOpening __instance)
		{
			if (ChestSkip.Forcing)
			{
				ChestSkip.Forcing = false;
				if (__instance.skipped)
				{
					Plugin.Log.LogInfo((object)"Chest skip: skipped via the game's own skip.");
					return;
				}
				__instance.skipped = true;
				Plugin.Log.LogInfo((object)"Chest skip: set skipped directly (game didn't ask for a button this frame).");
			}
		}
	}
	[HarmonyPatch(typeof(MyInputManager), "GetButtonDown")]
	internal static class MyInputManager_GetButtonDown
	{
		private static void Postfix(string action, ref bool __result)
		{
			if (!(!ChestSkip.Forcing | __result))
			{
				__result = true;
				ChestSkip.LogForcedAction(action);
			}
		}
	}
	internal class CustomShopItem
	{
		internal static readonly List<CustomShopItem> All = new List<CustomShopItem>();

		internal readonly EShopItem Id;

		internal readonly string Title;

		internal readonly ConfigEntry<int> Level;

		internal readonly Func<int[]> Prices;

		internal readonly Func<string> Description;

		internal readonly Func<string, bool> IconMatch;

		internal ShopItemData Data;

		internal Func<int, string> LevelStat;

		internal int MaxLevel => Prices().Length;

		internal int CurrentLevel => Math.Clamp(Level.Value, 0, MaxLevel);

		internal string FullDescription()
		{
			string text = Description();
			if (LevelStat == null || MaxLevel <= 1)
			{
				return text;
			}
			List<string> list = new List<string>();
			int currentLevel = CurrentLevel;
			for (int i = 1; i <= MaxLevel; i++)
			{
				string text2 = $"Lv{i} {LevelStat(i)}";
				if (i == currentLevel)
				{
					text2 = "<color=#ffd84d><b>" + text2 + "</b></color>";
				}
				else if (i > currentLevel)
				{
					text2 = "<color=#8a8a8a>" + text2 + "</color>";
				}
				list.Add(text2);
			}
			return text + "\n" + string.Join(" · ", list);
		}

		internal CustomShopItem(int id, string title, ConfigEntry<int> level, Func<int[]> prices, Func<string> description, Func<string, bool> iconMatch)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			Id = (EShopItem)id;
			Title = title;
			Level = level;
			Prices = prices;
			Description = description;
			IconMatch = iconMatch;
			All.Add(this);
		}

		internal int LevelPrice(int level)
		{
			int[] array = Prices();
			return array[Math.Clamp(level, 0, array.Length - 1)];
		}

		internal static void RefundLevelsOverCap()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			SaveManager instance = SaveManager.Instance;
			ProgressionSaveFile val = ((instance != null) ? instance.progression : null);
			if (val == null)
			{
				return;
			}
			bool flag = default(bool);
			foreach (CustomShopItem item in All)
			{
				int value = item.Level.Value;
				int maxLevel = item.MaxLevel;
				if (value > maxLevel)
				{
					int num = 0;
					for (int i = maxLevel; i < value; i++)
					{
						num += item.LevelPrice(i);
					}
					val.AddSilver(num);
					item.Level.Value = maxLevel;
					SaveManager.Instance.SaveProgression();
					ManualLogSource log = Plugin.Log;
					BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(61, 4, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(item.Title);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": max level is now ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(maxLevel);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; refunded ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(value - maxLevel);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" level(s) above it for ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" silver.");
					}
					log.LogInfo(val2);
				}
			}
		}

		internal int RefundAmount()
		{
			if (CurrentLevel <= 0)
			{
				return 0;
			}
			return LevelPrice(CurrentLevel - 1);
		}

		internal static CustomShopItem For(EShopItem id)
		{
			//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)
			foreach (CustomShopItem item in All)
			{
				if (item.Id == id)
				{
					return item;
				}
			}
			return null;
		}

		internal static CustomShopItem For(ShopItemData data)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)data == (Object)null))
			{
				return For(data.eShopItem);
			}
			return null;
		}

		internal static int[] ParsePrices(string csv)
		{
			return Array.ConvertAll(csv.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries), int.Parse);
		}

		internal void Register(DataManager dm, ShopItemData template)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			if (!dm.shopItems.ContainsKey(Id))
			{
				ShopItemData val = Object.Instantiate<ShopItemData>(template);
				((Object)val).name = "ShopItem_" + Title.Replace(" ", "");
				val.eShopItem = Id;
				val.maxLevel = MaxLevel;
				val.unlockRequirement = null;
				val.canRefund = true;
				val.sortingOrder = template.sortingOrder + 1 + All.IndexOf(this);
				Object.DontDestroyOnLoad((Object)(object)val);
				Texture val2 = ((IconMatch == null) ? null : FindTexture(IconMatch));
				if ((Object)(object)val2 != (Object)null)
				{
					val.icon = val2;
				}
				dm.shopItems[Id] = val;
				dm.unsortedShopItems.Add(val);
				Data = val;
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(47, 4, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Added '");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(Title);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' shop item (max level ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(MaxLevel);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", level ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(CurrentLevel);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", icon ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "from template");
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(").");
				}
				log.LogInfo(val3);
			}
		}

		private static Texture FindTexture(Func<string, bool> match)
		{
			foreach (Texture2D item in Resources.FindObjectsOfTypeAll<Texture2D>())
			{
				if (match(((Object)item).name))
				{
					return (Texture)(object)item;
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(DataManager), "Load")]
	internal static class DataManager_Load
	{
		private static void Postfix(DataManager __instance)
		{
			ShopItemData shopItemData = __instance.GetShopItemData((EShopItem)6);
			if ((Object)(object)shopItemData == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Silver shop item not found; custom shop items not added.");
				return;
			}
			foreach (CustomShopItem item in CustomShopItem.All)
			{
				item.Register(__instance, shopItemData);
			}
		}
	}
	[HarmonyPatch(typeof(ProgressionSaveFile), "GetShopItemLevel")]
	internal static class Progression_GetShopItemLevel
	{
		private static bool Prefix(EShopItem eShopItem, ref int __result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			CustomShopItem customShopItem = CustomShopItem.For(eShopItem);
			if (customShopItem == null)
			{
				return true;
			}
			__result = customShopItem.CurrentLevel;
			return false;
		}
	}
	[HarmonyPatch(typeof(ProgressionSaveFile), "HasShopItem")]
	internal static class Progression_HasShopItem
	{
		private static bool Prefix(EShopItem eShopItem, ref bool __result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			CustomShopItem customShopItem = CustomShopItem.For(eShopItem);
			if (customShopItem == null)
			{
				return true;
			}
			__result = customShopItem.CurrentLevel > 0;
			return false;
		}
	}
	[HarmonyPatch(typeof(ShopItemData), "GetLevel")]
	internal static class ShopItemData_GetLevel
	{
		private static bool Prefix(ShopItemData __instance, ref int __result)
		{
			CustomShopItem customShopItem = CustomShopItem.For(__instance);
			if (customShopItem == null)
			{
				return true;
			}
			__result = customShopItem.CurrentLevel;
			return false;
		}
	}
	[HarmonyPatch(typeof(ShopItemData), "GetMaxLevel")]
	internal static class ShopItemData_GetMaxLevel
	{
		private static bool Prefix(ShopItemData __instance, ref int __result)
		{
			CustomShopItem customShopItem = CustomShopItem.For(__instance);
			if (customShopItem == null)
			{
				return true;
			}
			__result = customShopItem.MaxLevel;
			return false;
		}
	}
	[HarmonyPatch(typeof(ShopItemData), "IsMaxLevel")]
	internal static class ShopItemData_IsMaxLevel
	{
		private static bool Prefix(ShopItemData __instance, ref bool __result)
		{
			CustomShopItem customShopItem = CustomShopItem.For(__instance);
			if (customShopItem == null)
			{
				return true;
			}
			__result = customShopItem.CurrentLevel >= customShopItem.MaxLevel;
			return false;
		}
	}
	[HarmonyPatch(typeof(ShopItemData), "GetLevelPrice")]
	internal static class ShopItemData_GetLevelPrice
	{
		private static bool Prefix(ShopItemData __instance, int level, ref int __result)
		{
			CustomShopItem customShopItem = CustomShopItem.For(__instance);
			if (customShopItem == null)
			{
				return true;
			}
			__result = customShopItem.LevelPrice(level);
			return false;
		}
	}
	[HarmonyPatch(typeof(ShopItemData), "GetRefundPrice")]
	internal static class ShopItemData_GetRefundPrice
	{
		private static bool Prefix(ShopItemData __instance, ref int __result)
		{
			CustomShopItem customShopItem = CustomShopItem.For(__instance);
			if (customShopItem == null)
			{
				return true;
			}
			__result = customShopItem.RefundAmount();
			return false;
		}
	}
	[HarmonyPatch(typeof(ProgressionSaveFile), "PurchaseShopItem")]
	internal static class Progression_PurchaseShopItem
	{
		private static bool Prefix(ProgressionSaveFile __instance, ShopItemData shopItemData, ref bool __result)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			CustomShopItem customShopItem = CustomShopItem.For(shopItemData);
			if (customShopItem == null)
			{
				return true;
			}
			int currentLevel = customShopItem.CurrentLevel;
			int num = customShopItem.LevelPrice(currentLevel);
			__result = currentLevel < customShopItem.MaxLevel && __instance.silver >= num;
			if (__result)
			{
				if (num > 0)
				{
					__instance.RemoveSilver(num);
				}
				customShopItem.Level.Value = currentLevel + 1;
				SaveManager.Instance.SaveProgression();
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Bought ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(customShopItem.Title);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" level ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(currentLevel + 1);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" for ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" silver.");
				}
				log.LogInfo(val);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ProgressionSaveFile), "RefundShopItem")]
	internal static class Progression_RefundShopItem
	{
		private static bool Prefix(ProgressionSaveFile __instance, ShopItemData shopItemData, ref bool __result)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			CustomShopItem customShopItem = CustomShopItem.For(shopItemData);
			if (customShopItem == null)
			{
				return true;
			}
			int currentLevel = customShopItem.CurrentLevel;
			__result = currentLevel > 0;
			if (__result)
			{
				int num = customShopItem.RefundAmount();
				if (num > 0)
				{
					__instance.AddSilver(num);
				}
				customShopItem.Level.Value = currentLevel - 1;
				SaveManager.Instance.SaveProgression();
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(29, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Refunded ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(customShopItem.Title);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" level ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(currentLevel);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" for ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" silver.");
				}
				log.LogInfo(val);
			}
			return false;
		}
	}
	internal static class ShopSilverGuard
	{
		internal struct Before
		{
			internal bool Valid;

			internal int Silver;

			internal int Level;

			internal int Amount;
		}

		internal static Before Capture(ShopWindow window, bool refund)
		{
			ShopContainer currentContainer = window.currentContainer;
			ShopItemData val = ((currentContainer != null) ? currentContainer.data : null);
			SaveManager instance = SaveManager.Instance;
			ProgressionSaveFile val2 = ((instance != null) ? instance.progression : null);
			if ((Object)(object)val == (Object)null || val2 == null)
			{
				return default(Before);
			}
			return new Before
			{
				Valid = true,
				Silver = val2.silver,
				Level = val.GetLevel(),
				Amount = (refund ? val.GetRefundPrice() : ((UnlockableBase)val).GetPrice())
			};
		}

		internal static void Settle(ShopWindow window, Before before, bool refund)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Expected O, but got Unknown
			ShopContainer currentContainer = window.currentContainer;
			ShopItemData val = ((currentContainer != null) ? currentContainer.data : null);
			SaveManager instance = SaveManager.Instance;
			ProgressionSaveFile val2 = ((instance != null) ? instance.progression : null);
			if (!before.Valid || (Object)(object)val == (Object)null || val2 == null)
			{
				return;
			}
			int level = val.GetLevel();
			int silver = val2.silver;
			string text = (refund ? "Refund" : "Buy");
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(38, 8, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(text);
				((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<EShopItem>(val.eShopItem);
				((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": level ");
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(before.Level);
				((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" -> ");
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(level);
				((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", silver ");
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(before.Silver);
				((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" -> ");
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(silver);
				((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" (expected ");
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(refund ? "+" : "-");
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(before.Amount);
				((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(")");
			}
			log.LogInfo(val3);
			CustomShopItem customShopItem = CustomShopItem.For(val);
			if (customShopItem == null || level == before.Level)
			{
				return;
			}
			int num = (refund ? (before.Silver + before.Amount) : (before.Silver - before.Amount));
			if (silver != num)
			{
				if (silver > num)
				{
					val2.RemoveSilver(silver - num);
				}
				else
				{
					val2.AddSilver(num - silver);
				}
				SaveManager.Instance.SaveProgression();
				ManualLogSource log2 = Plugin.Log;
				BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(25, 4, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(text);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(customShopItem.Title);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(": corrected silver ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(silver);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" -> ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(num);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(".");
				}
				log2.LogWarning(val4);
			}
		}
	}
	[HarmonyPatch(typeof(ShopWindow), "Refund")]
	internal static class ShopWindow_Refund
	{
		private static void Prefix(ShopWindow __instance, out ShopSilverGuard.Before __state)
		{
			__state = ShopSilverGuard.Capture(__instance, refund: true);
		}

		private static void Postfix(ShopWindow __instance, ShopSilverGuard.Before __state)
		{
			ShopSilverGuard.Settle(__instance, __state, refund: true);
		}
	}
	[HarmonyPatch(typeof(ShopWindow), "Buy")]
	internal static class ShopWindow_Buy
	{
		private static void Prefix(ShopWindow __instance, out ShopSilverGuard.Before __state)
		{
			__state = ShopSilverGuard.Capture(__instance, refund: false);
		}

		private static void Postfix(ShopWindow __instance, ShopSilverGuard.Before __state)
		{
			ShopSilverGuard.Settle(__instance, __state, refund: false);
		}
	}
	[HarmonyPatch(typeof(ShopFooter), "Set")]
	internal static class ShopFooter_Set
	{
		private static void Postfix(ShopFooter __instance, ShopContainer shopContainerClicked)
		{
			CustomShopItem customShopItem = (((Object)(object)shopContainerClicked == (Object)null) ? null : CustomShopItem.For(shopContainerClicked.data));
			if (customShopItem != null)
			{
				((TMP_Text)__instance.t_title).text = customShopItem.Title;
				((TMP_Text)__instance.t_description).text = customShopItem.FullDescription();
			}
		}
	}
	[HarmonyPatch(typeof(MainMenu), "Start")]
	internal static class MainMenu_Start_RefundOverCap
	{
		private static void Postfix()
		{
			try
			{
				CustomShopItem.RefundLevelsOverCap();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Refunding levels over the cap failed: " + ex));
			}
		}
	}
	internal static class FasterShrines
	{
		internal static CustomShopItem Shop;

		private static bool loggedThisMap;

		private const float InstantSeconds = 0.001f;

		private static readonly Dictionary<IntPtr, float> originalTime = new Dictionary<IntPtr, float>();

		internal static void Bind(ConfigFile config, ConfigFile progress)
		{
			ConfigEntry<string> prices = config.Bind<string>("FasterShrines", "Prices", "200,200,200,200,200,200,200,200,200,200", "Silver price of each Faster Shrines level, comma separated. The count sets the max level (the last level is instant).");
			Shop = new CustomShopItem(105, "Faster Shrines", progress.Bind<int>("Progress", "FasterShrinesLevel", 0, "Levels of the Faster Shrines shop upgrade bought. Managed by the mod."), () => CustomShopItem.ParsePrices(prices.Value), Description, null);
		}

		internal static float TimeFraction(int level)
		{
			return Math.Clamp(1f - (float)level / (float)Math.Max(1, Shop.MaxLevel), 0f, 1f);
		}

		private static string Describe(int level)
		{
			float num = TimeFraction(level);
			if (!(num <= 0f))
			{
				return $"{num:P0} of the normal time";
			}
			return "instant";
		}

		private static string Description()
		{
			return $"Charge shrines fill faster. Each level cuts the charge time by {100f / (float)Shop.MaxLevel:0}% of normal; the last level fills them instantly.";
		}

		internal static void BeforeUpdate(ChargeShrine shrine)
		{
			int currentLevel = Shop.CurrentLevel;
			IntPtr pointer = ((Il2CppObjectBase)shrine).Pointer;
			if (!originalTime.TryGetValue(pointer, out var value))
			{
				if (currentLevel <= 0)
				{
					return;
				}
				value = (originalTime[pointer] = shrine.chargeTime);
			}
			float num = TimeFraction(currentLevel);
			float num2 = ((currentLevel <= 0) ? value : Math.Max(0.001f, value * num));
			if (shrine.chargeTime != num2)
			{
				shrine.chargeTime = num2;
				if (!loggedThisMap && currentLevel > 0)
				{
					loggedThisMap = true;
					Plugin.Log.LogInfo((object)($"Faster Shrines level {currentLevel}: shrine charge time {value:0.##}s -> " + ((num <= 0f) ? "instant." : $"{num2:0.##}s.")));
				}
			}
		}

		internal static void NewMap()
		{
			loggedThisMap = false;
			originalTime.Clear();
		}
	}
	[HarmonyPatch(typeof(ChargeShrine), "Update")]
	internal static class ChargeShrine_Update
	{
		private static void Prefix(ChargeShrine __instance)
		{
			try
			{
				FasterShrines.BeforeUpdate(__instance);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Faster Shrines failed: " + ex));
			}
		}
	}
	[HarmonyPatch(typeof(MyTime), "OnNewStageStarted")]
	internal static class MyTime_OnNewStageStarted_FasterShrines
	{
		private static void Postfix()
		{
			FasterShrines.NewMap();
		}
	}
	internal static class FoldCheck
	{
		internal unsafe static void Run()
		{
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Expected O, but got Unknown
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Expected O, but got Unknown
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Expected O, but got Unknown
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Expected O, but got Unknown
			List<MethodBase> list = Harmony.GetAllPatchedMethods().ToList();
			Dictionary<IntPtr, MethodBase> dictionary = new Dictionary<IntPtr, MethodBase>();
			foreach (MethodBase item in list)
			{
				IntPtr intPtr = NativeAddress(item);
				if (intPtr != IntPtr.Zero)
				{
					dictionary[intPtr] = item;
				}
			}
			Dictionary<IntPtr, List<string>> dictionary2 = new Dictionary<IntPtr, List<string>>();
			int num = 0;
			uint num2 = 0u;
			IntPtr* ptr = IL2CPP.il2cpp_domain_get_assemblies(IL2CPP.il2cpp_domain_get(), ref num2);
			for (uint num3 = 0u; num3 < num2; num3++)
			{
				IntPtr intPtr2 = IL2CPP.il2cpp_assembly_get_image(ptr[num3]);
				uint num4 = IL2CPP.il2cpp_image_get_class_count(intPtr2);
				for (uint num5 = 0u; num5 < num4; num5++)
				{
					IntPtr intPtr3 = IL2CPP.il2cpp_image_get_class(intPtr2, num5);
					IntPtr zero = IntPtr.Zero;
					IntPtr intPtr4;
					while ((intPtr4 = IL2CPP.il2cpp_class_get_methods(intPtr3, ref zero)) != IntPtr.Zero)
					{
						num++;
						IntPtr intPtr5 = *(IntPtr*)(void*)intPtr4;
						if (!(intPtr5 == IntPtr.Zero) && dictionary.ContainsKey(intPtr5))
						{
							if (!dictionary2.TryGetValue(intPtr5, out var value))
							{
								value = (dictionary2[intPtr5] = new List<string>());
							}
							string text = Marshal.PtrToStringAnsi(IL2CPP.il2cpp_class_get_namespace(intPtr3));
							string text2 = Marshal.PtrToStringAnsi(IL2CPP.il2cpp_class_get_name(intPtr3));
							string text3 = Marshal.PtrToStringAnsi(IL2CPP.il2cpp_method_get_name(intPtr4));
							value.Add((string.IsNullOrEmpty(text) ? "" : (text + ".")) + text2 + "." + text3);
						}
					}
				}
			}
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(52, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Fold check: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(dictionary.Count);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" patched methods, ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" game methods scanned.");
			}
			log.LogInfo(val);
			foreach (KeyValuePair<IntPtr, List<string>> item2 in dictionary2)
			{
				item2.Deconstruct(out var key, out var value2);
				IntPtr key2 = key;
				List<string> list3 = value2;
				MethodBase methodBase = dictionary[key2];
				if (list3.Count <= 1)
				{
					continue;
				}
				ManualLogSource log2 = Plugin.Log;
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(59, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Fold check: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(methodBase.DeclaringType?.Name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(methodBase.Name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" shares its native code with ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(list3.Count - 1);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" other method(s):");
				}
				log2.LogWarning(val2);
				foreach (string item3 in list3.Take(15))
				{
					ManualLogSource log3 = Plugin.Log;
					val2 = new BepInExWarningLogInterpolatedStringHandler(4, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("    ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(item3);
					}
					log3.LogWarning(val2);
				}
				if (list3.Count > 15)
				{
					ManualLogSource log4 = Plugin.Log;
					val2 = new BepInExWarningLogInterpolatedStringHandler(17, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("    ... and ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(list3.Count - 15);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" more");
					}
					log4.LogWarning(val2);
				}
			}
		}

		private static IntPtr NativeAddress(MethodBase method)
		{
			try
			{
				FieldInfo il2CppMethodInfoPointerFieldForGeneratedMethod = Il2CppInteropUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(method);
				return (il2CppMethodInfoPointerFieldForGeneratedMethod == null) ? IntPtr.Zero : Read(il2CppMethodInfoPointerFieldForGeneratedMethod);
			}
			catch
			{
				return IntPtr.Zero;
			}
		}

		private unsafe static IntPtr Read(FieldInfo methodInfoField)
		{
			IntPtr intPtr = (IntPtr)methodInfoField.GetValue(null);
			if (!(intPtr == IntPtr.Zero))
			{
				return *(IntPtr*)(void*)intPtr;
			}
			return IntPtr.Zero;
		}
	}
	[HarmonyPatch(typeof(DataManager), "Load")]
	internal static class DataManager_Load_FoldCheck
	{
		private static bool done;

		private static void Postfix()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			if (!done)
			{
				done = true;
				Stopwatch stopwatch = Stopwatch.StartNew();
				try
				{
					FoldCheck.Run();
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("Fold check failed: " + ex));
				}
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Fold check took ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<long>(stopwatch.ElapsedMilliseconds);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ms.");
				}
				log.LogInfo(val);
			}
		}
	}
	internal static class LevelupChoices
	{
		internal static CustomShopItem Shop;

		internal static bool ShufflingLevelup;

		private static RectTransform viewport;

		private static RectTransform content;

		private static ScrollRect scrollRect;

		private static bool loggedLayout;

		internal static int Extra => Shop.CurrentLevel;

		internal static void Bind(ConfigFile config, ConfigFile progress)
		{
			ConfigEntry<string> prices = config.Bind<string>("LevelUp", "MoreChoicesPrices", "200,200,200,200", "Silver price of each More Choices level, comma separated. The count sets the max level.");
			Shop = new CustomShopItem(103, "More Choices", progress.Bind<int>("Progress", "MoreChoicesLevel", 0, "Levels of the More Choices shop upgrade bought. Managed by the mod."), () => CustomShopItem.ParsePrices(prices.Value), Description, null);
		}

		private static string Description()
		{
			return "Each level adds one more option to choose from when you level up. The list scrolls.";
		}

		internal static void Prepare(UpgradePicker picker)
		{
			Il2CppReferenceArray<UpgradeButton> buttons = picker.buttons;
			if (buttons != null && ((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length != 0)
			{
				LogLayout(picker);
				EnsureScrollView(((Il2CppArrayBase<UpgradeButton>)(object)buttons)[0]);
			}
		}

		private static void AddExtraOptions(UpgradePicker picker)
		{
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			Il2CppReferenceArray<UpgradeButton> buttons = picker.buttons;
			int num = 0;
			HashSet<IntPtr> hashSet = new HashSet<IntPtr>();
			foreach (UpgradeButton item in (Il2CppArrayBase<UpgradeButton>)(object)buttons)
			{
				if ((Object)(object)item != (Object)null && ((Component)item).gameObject.activeSelf)
				{
					num++;
					if (item.upgradable != null)
					{
						hashSet.Add(((Il2CppObjectBase)item.upgradable).Pointer);
					}
				}
			}
			int needed = num + Extra;
			EnsureButtonPool(picker, needed);
			buttons = picker.buttons;
			int num2 = 0;
			for (int i = 0; i < 10; i++)
			{
				if (num2 >= Extra)
				{
					break;
				}
				List<IUpgradable> randomUpgrades = InventoryUtility.GetRandomUpgrades();
				if (randomUpgrades == null || randomUpgrades.Count == 0)
				{
					break;
				}
				Enumerator<IUpgradable> enumerator2 = randomUpgrades.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					IUpgradable current2 = enumerator2.Current;
					if (num2 >= Extra)
					{
						break;
					}
					if (current2 != null && hashSet.Add(((Il2CppObjectBase)current2).Pointer))
					{
						UpgradeButton obj = ((Il2CppArrayBase<UpgradeButton>)(object)buttons)[num + num2];
						((Component)obj).gameObject.SetActive(true);
						obj.SetUpgrade(current2);
						num2++;
					}
				}
			}
			for (int j = num + num2; j < ((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length; j++)
			{
				((Component)((Il2CppArrayBase<UpgradeButton>)(object)buttons)[j]).gameObject.SetActive(false);
			}
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(45, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("More Choices: game showed ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", added ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num2);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" of ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Extra);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" extra.");
			}
			log.LogInfo(val);
		}

		private static void EnsureButtonPool(UpgradePicker picker, int needed)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			Il2CppReferenceArray<UpgradeButton> buttons = picker.buttons;
			if (((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length < needed)
			{
				UpgradeButton[] array = (UpgradeButton[])(object)new UpgradeButton[needed];
				for (int i = 0; i < ((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length; i++)
				{
					array[i] = ((Il2CppArrayBase<UpgradeButton>)(object)buttons)[i];
				}
				UpgradeButton val = ((Il2CppArrayBase<UpgradeButton>)(object)buttons)[((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length - 1];
				for (int j = ((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length; j < needed; j++)
				{
					UpgradeButton component = UiClone.Clone(((Component)val).gameObject, ((Component)val).transform.parent, $"Mod_UpgradeButton{j}", stripLocalization: false).GetComponent<UpgradeButton>();
					component.upgradePicker = picker;
					array[j] = component;
				}
				picker.buttons = new Il2CppReferenceArray<UpgradeButton>(array);
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(36, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("More Choices: level-up buttons ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" -> ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(needed);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
				}
				log.LogInfo(val2);
			}
		}

		private static void EnsureScrollView(UpgradeButton first)
		{
			//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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: 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_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Expected O, but got Unknown
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = ((Component)first).transform.parent;
			RectTransform val = ((parent != null) ? ((Component)parent).gameObject.GetComponent<RectTransform>() : null);
			if ((Object)(object)val == (Object)null || ((Object)(object)content != (Object)null && ((Il2CppObjectBase)content).Pointer == ((Il2CppObjectBase)val).Pointer))
			{
				return;
			}
			Transform parent2 = ((Transform)val).parent;
			if (!((Object)(object)parent2 == (Object)null))
			{
				GameObject val2 = new GameObject("Mod_ChoicesViewport");
				RectTransform val3 = val2.AddComponent<RectTransform>();
				((Transform)val3).SetParent(parent2, false);
				((Transform)val3).SetSiblingIndex(((Transform)val).GetSiblingIndex());
				val3.anchorMin = val.anchorMin;
				val3.anchorMax = val.anchorMax;
				val3.pivot = val.pivot;
				val3.anchoredPosition = val.anchoredPosition;
				val3.sizeDelta = val.sizeDelta;
				((Transform)val3).localScale = ((Transform)val).localScale;
				Rect rect = val.rect;
				Vector2 size = ((Rect)(ref rect)).size;
				LayoutElement val4 = val2.AddComponent<LayoutElement>();
				LayoutElement component = ((Component)val).gameObject.GetComponent<LayoutElement>();
				if ((Object)(object)component != (Object)null)
				{
					val4.minWidth = component.minWidth;
					val4.minHeight = component.minHeight;
					val4.preferredWidth = component.preferredWidth;
					val4.preferredHeight = component.preferredHeight;
					val4.flexibleWidth = component.flexibleWidth;
					val4.flexibleHeight = component.flexibleHeight;
					val4.layoutPriority = component.layoutPriority;
					((Behaviour)component).enabled = false;
				}
				else
				{
					val4.preferredWidth = size.x;
					val4.preferredHeight = size.y;
				}
				val2.AddComponent<RectMask2D>();
				Image obj = val2.AddComponent<Image>();
				((Graphic)obj).color = new Color(0f, 0f, 0f, 0f);
				((Graphic)obj).raycastTarget = false;
				((Transform)val).SetParent((Transform)(object)val3, false);
				val.anchorMin = new Vector2(0f, 1f);
				val.anchorMax = new Vector2(1f, 1f);
				val.pivot = new Vector2(0.5f, 1f);
				val.anchoredPosition = Vector2.zero;
				val.sizeDelta = new Vector2(0f, size.y);
				((Transform)val).localScale = Vector3.one;
				(((Component)val).gameObject.GetComponent<ContentSizeFitter>() ?? ((Component)val).gameObject.AddComponent<ContentSizeFitter>()).verticalFit = (FitMode)2;
				ScrollRect obj2 = val2.AddComponent<ScrollRect>();
				obj2.content = val;
				obj2.viewport = val3;
				obj2.horizontal = false;
				obj2.vertical = true;
				obj2.movementType = (MovementType)2;
				obj2.scrollSensitivity = 40f;
				viewport = val3;
				scrollRect = obj2;
				content = val;
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(44, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("More Choices: wrapped '");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(((Object)val).name);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("' in a scroll view ");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<float>(size.x, "F0");
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("x");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<float>(size.y, "F0");
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(".");
				}
				log.LogInfo(val5);
			}
		}

		internal static void AfterShuffle(UpgradePicker picker)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			AddExtraOptions(picker);
			if (!((Object)(object)content == (Object)null))
			{
				LayoutRebuilder.ForceRebuildLayoutImmediate(content);
				ScrollRect obj = scrollRect;
				if (obj != null)
				{
					obj.StopMovement();
				}
				content.anchoredPosition = Vector2.zero;
				LinkNavigation(picker);
			}
		}

		private static void LinkNavigation(UpgradePicker picker)
		{
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Invalid comparison between Unknown and I4
			List<Button> list = new List<Button>();
			foreach (UpgradeButton item in (Il2CppArrayBase<UpgradeButton>)(object)picker.buttons)
			{
				Button val = ((item != null) ? ((Component)item).gameObject.GetComponent<Button>() : null);
				if ((Object)(object)val != (Object)null && ((Component)item).gameObject.activeSelf)
				{
					list.Add(val);
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			List<Button> list2 = FooterButtons(picker.levelupScreen);
			Button val2 = ((list2.Count > 0) ? list2[0] : null);
			for (int i = 0; i < list.Count; i++)
			{
				Navigation navigation = ((Selectable)list[i]).navigation;
				navigation.mode = (Mode)4;
				navigation.selectOnUp = (Selectable)((i > 0) ? ((object)list[i - 1]) : ((object)navigation.selectOnUp));
				navigation.selectOnDown = (Selectable)((i < list.Count - 1) ? list[i + 1] : (((object)val2) ?? ((object)navigation.selectOnDown)));
				((Selectable)list[i]).navigation = navigation;
			}
			Button selectOnUp = list[list.Count - 1];
			foreach (Button item2 in list2)
			{
				Navigation navigation2 = ((Selectable)item2).navigation;
				if ((int)navigation2.mode == 4)
				{
					navigation2.selectOnUp = (Selectable)(object)selectOnUp;
					((Selectable)item2).navigation = navigation2;
				}
			}
		}

		private static List<Button> FooterButtons(LevelupScreen screen)
		{
			List<Button> list = new List<Button>();
			if ((Object)(object)screen == (Object)null)
			{
				return list;
			}
			GameObject[] array = new GameObject[4];
			MyButtonOffersUtility b_banish = screen.b_banish;
			array[0] = ((b_banish != null) ? ((Component)b_banish).gameObject : null);
			MyButtonOffersUtility b_skip = screen.b_skip;
			array[1] = ((b_skip != null) ? ((Component)b_skip).gameObject : null);
			MyButtonOffersUtility b_refresh = screen.b_refresh;
			array[2] = ((b_refresh != null) ? ((Component)b_refresh).gameObject : null);
			MyButtonNormal b_leave = screen.b_leave;
			array[3] = ((b_leave != null) ? ((Component)b_leave).gameObject : null);
			GameObject[] array2 = (GameObject[])(object)array;
			foreach (GameObject val in array2)
			{
				Button val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<Button>());
				if ((Object)(object)val2 != (Object)null && val.activeInHierarchy && ((Selectable)val2).interactable)
				{
					list.Add(val2);
				}
			}
			list.Sort((Button a, Button b) => ((Component)a).transform.position.x.CompareTo(((Component)b).transform.position.x));
			return list;
		}

		internal static void FollowSelection()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)content == (Object)null || (Object)(object)viewport == (Object)null || (Object)(object)EventSystem.current == (Object)null)
			{
				return;
			}
			GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject;
			if ((Object)(object)currentSelectedGameObject == (Object)null || !currentSelectedGameObject.transform.IsChildOf((Transform)(object)content))
			{
				return;
			}
			RectTransform component = currentSelectedGameObject.GetComponent<RectTransform>();
			if (!((Object)(object)component == (Object)null))
			{
				Il2CppStructArray<Vector3> val = new Il2CppStructArray<Vector3>(4L);
				component.GetWorldCorners(val);
				float y = ((Il2CppArrayBase<Vector3>)(object)val)[1].y;
				float y2 = ((Il2CppArrayBase<Vector3>)(object)val)[0].y;
				viewport.GetWorldCorners(val);
				float y3 = ((Il2CppArrayBase<Vector3>)(object)val)[1].y;
				float y4 = ((Il2CppArrayBase<Vector3>)(object)val)[0].y;
				float num = 0f;
				if (y > y3)
				{
					num = y - y3;
				}
				else if (y2 < y4)
				{
					num = y2 - y4;
				}
				if (num != 0f)
				{
					RectTransform obj = content;
					((Transform)obj).position = ((Transform)obj).position - new Vector3(0f, num, 0f);
				}
			}
		}

		private static void LogLayout(UpgradePicker picker)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: 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)
			if (loggedLayout)
			{
				return;
			}
			loggedLayout = true;
			UpgradeButton val = ((Il2CppArrayBase<UpgradeButton>)(object)picker.buttons)[0];
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(63, 4, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("More Choices: picker has ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(((Il2CppArrayBase<UpgradeButton>)(object)picker.buttons).Length);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" buttons, numUpgrades=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(picker.numUpgrades);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", parent '");
				BepInExInfoLogInterpolatedStringHandler obj = val2;
				Transform parent = ((Component)val).transform.parent;
				((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<string>((parent != null) ? ((Object)parent).name : null);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' > '");
				BepInExInfoLogInterpolatedStringHandler obj2 = val2;
				Transform parent2 = ((Component)val).transform.parent;
				object obj3;
				if (parent2 == null)
				{
					obj3 = null;
				}
				else
				{
					Transform parent3 = parent2.parent;
					obj3 = ((parent3 != null) ? ((Object)parent3).name : null);
				}
				((BepInExLogInterpolatedStringHandler)obj2).AppendFormatted<string>((string)obj3);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("'");
			}
			log.LogInfo(val2);
			Transform parent4 = ((Component)val).transform.parent;
			while ((Object)(object)parent4 != (Object)null)
			{
				string text = string.Join(",", ((IEnumerable<Component>)((Component)parent4).gameObject.GetComponents<Component>()).Select((Component c) => ((MemberInfo)((Object)c).GetIl2CppType()).Name));
				RectTransform component = ((Component)parent4).gameObject.GetComponent<RectTransform>();
				ManualLogSource log2 = Plugin.Log;
				val2 = new BepInExInfoLogInterpolatedStringHandler(12, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("  ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)parent4).name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": size=");
					BepInExInfoLogInterpolatedStringHandler obj4 = val2;
					Vector2? obj5;
					if (component == null)
					{
						obj5 = null;
					}
					else
					{
						Rect rect = component.rect;
						obj5 = ((Rect)(ref rect)).size;
					}
					((BepInExLogInterpolatedStringHandler)obj4).AppendFormatted<Vector2?>(obj5);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" [");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("]");
				}
				log2.LogInfo(val2);
				if (!((Object)(object)((Component)parent4).gameObject.GetComponent<Canvas>() != (Object)null))
				{
					parent4 = parent4.parent;
					continue;
				}
				break;
			}
		}
	}
	[HarmonyPatch(typeof(UpgradePicker), "ShuffleUpgrades")]
	internal static class UpgradePicker_ShuffleUpgrades
	{
		private static readonly Stopwatch timer = new Stopwatch();

		private static double prepareMs;

		private static void Prefix(UpgradePicker __instance, EEncounter encounterType)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			timer.Restart();
			prepareMs = 0.0;
			LevelupChoices.ShufflingLevelup = (int)encounterType == 0 && LevelupChoices.Extra > 0;
			if (LevelupChoices.ShufflingLevelup)
			{
				try
				{
					LevelupChoices.Prepare(__instance);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("More Choices: prepare failed: " + ex));
				}
				prepareMs = timer.Elapsed.TotalMilliseconds;
				timer.Restart();
			}
		}

		private static void Postfix(UpgradePicker __instance, EEncounter encounterType)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			double totalMilliseconds = timer.Elapsed.TotalMilliseconds;
			timer.Restart();
			if (LevelupChoices.ShufflingLevelup)
			{
				LevelupChoices.ShufflingLevelup = false;
				try
				{
					LevelupChoices.AfterShuffle(__instance);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("More Choices: after shuffle failed: " + ex));
				}
			}
			Performance.Mark($"shuffle {encounterType} (game {totalMilliseconds:F1}ms, mod {prepareMs + timer.Elapsed.TotalMilliseconds:F1}ms)");
		}
	}
	[HarmonyPatch(typeof(UpgradePicker), "Update")]
	internal static class UpgradePicker_Update
	{
		private static void Postfix()
		{
			LevelupChoices.FollowSelection();
		}
	}
	[HarmonyPatch(typeof(LevelupScreen), "ShowLevelupScreen")]
	internal static class LevelupScreen_ShowLevelupScreen_Timing
	{
		private static readonly Stopwatch timer = new Stopwatch();

		private static void Prefix()
		{
			timer.Restart();
		}

		private static void Postfix()
		{
			Performance.Mark($"opened level-up ({timer.Elapsed.TotalMilliseconds:F1}ms)");
		}
	}
	internal static class LinearKeys
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> ChancePerKey;

		internal static void Bind(ConfigFile config)
		{
			Enabled = config.Bind<bool>("Keys", "LinearKeys", true, "Each key adds a flat chance to open a chest for free.");
			ChancePerKey = config.Bind<float>("Keys", "ChancePerKey", 0.1f, "Free-chest chance per key (0.1 = 10%, so 10 keys = 100%).");
		}
	}
	[HarmonyPatch(typeof(ItemKey), "OnInitOrAmountChanged")]
	internal static class ItemKey_OnInitOrAmountChanged
	{
		private static void Postfix(ItemKey __instance)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			if (LinearKeys.Enabled.Value && __instance != null)
			{
				float currentChance = __instance.currentChance;
				__instance.currentChance = Math.Clamp((float)((ItemBase)__instance).amount * LinearKeys.ChancePerKey.Value, 0f, 1f);
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(51, 4, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Keys: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(((ItemBase)__instance).amount);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" -> free chest chance ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(__instance.currentChance, "P0");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (vanilla ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(currentChance, "P1");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", GetChance ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(__instance.GetChance(), "P1");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
				}
				log.LogInfo(val);
			}
		}
	}
	internal static class ManualFire
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<KeyCode> MouseButton;

		internal static ConfigEntry<KeyCode> PadButton;

		internal static ConfigEntry<string> PadButtonNames;

		internal static ConfigEntry<bool> FireButtonDoesNotJump;

		internal static ConfigEntry<bool> LogButtons;

		internal static ConfigEntry<string> JumpButtonNames;

		internal static ConfigEntry<string> KeyboardJumpKeys;

		internal static ConfigEntry<string> JumpAxisNames;

		internal static ConfigEntry<bool> LogAxes;

		internal static ConfigEntry<float> BaseInterval;

		internal static ConfigEntry<float> BaseStamina;

		internal static ConfigEntry<float> StaminaPerLevel;

		internal static ConfigEntry<float> RegenPerSecond;

		internal static ConfigEntry<float> BaseCost;

		internal static ConfigEntry<float> CostReductionPerLevel;

		internal static ConfigEntry<float> MinCost;

		internal static ConfigEntry<float> LateCostReduction;

		internal static ConfigEntry<string> AlwaysOnWeapons;

		internal static ConfigEntry<float> AlwaysOnDamage;

		internal static ConfigEntry<string> UnaffectedWeapons;

		internal static CustomShopItem AutoFire;

		internal static CustomShopItem StaminaUp;

		internal static CustomShopItem Efficiency;

		internal static CustomShopItem FireRate;

		internal static CustomShopItem Recharge;

		internal static ConfigEntry<float> RegenPerLevel;

		internal static float Stamina;

		internal static bool InRun;

		private static float nextActionAt;

		private static bool wasHeld;

		private static float lastLog;

		private static float lastHitLog;

		private static int loggedHits = -1;

		internal static bool Releasing;

		internal static readonly HashSet<string> PassiveWeapons = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		internal static readonly Dictionary<IntPtr, float> FullDamageUntil = new Dictionary<IntPtr, float>();

		internal static int ReducedHits;

		internal static int FullHits;

		internal static float MaxStamina => MaxStaminaAt(StaminaUp?.CurrentLevel ?? 0);

		internal static float CostPerWeapon => CostAt(Efficiency?.CurrentLevel ?? 0);

		internal static float Regen => RegenAt(Recharge?.CurrentLevel ?? 0);

		internal static float Interval => BaseInterval.Value / (float)(1 + (FireRate?.CurrentLevel ?? 0));

		internal static bool Active => Enabled.Value;

		internal static void Bind(ConfigFile config, ConfigFile progress)
		{
			Enabled = config.Bind<bool>("ManualFire", "Enabled", true, "Weapons only fire when you press the fire button (false = the game's normal auto attacks).");
			MouseButton = config.Bind<KeyCode>("ManualFire", "MouseButton", (KeyCode)323, "Fire button on mouse / keyboard.");
			PadButton = config.Bind<KeyCode>("ManualFire", "PadButton", (KeyCode)335, "Fire button on a controller through Unity input (JoystickButton5 = R1 / RB); usually not seen, the game reads controllers through Rewired.");
			PadButtonNames = config.Bind<string>("ManualFire", "PadButtonNames", "Button 5,Right Shoulder,Right Shoulder 1,RB,R1,Right Bumper", "Controller fire button, by the game controller system's (Rewired) button name. The log lists your controller's button names once.");
			LogButtons = config.Bind<bool>("ManualFire", "LogControllerButtons", false, "Log each controller button name as it's pressed (to find a button's name).");
			FireButtonDoesNotJump = config.Bind<bool>("ManualFire", "OnlyJumpButtonsJump", true, "On a controller, only the buttons in OtherJumpButtonNames (A) jump; R1 and any other button bound to jump don't. The keyboard keys in KeyboardJumpKeys still jump.");
			JumpButtonNames = config.Bind<string>("ManualFire", "OtherJumpButtonNames", "Button 0", "The controller buttons that jump (Button 0 = A).");
			KeyboardJumpKeys = config.Bind<string>("ManualFire", "KeyboardJumpKeys", "Space", "Keyboard keys that still jump (Unity KeyCode names, comma separated).");
			JumpAxisNames = config.Bind<string>("ManualFire", "JumpTriggerNames", "", "Controller trigger(s) that also jump, by the controller system's axis name (Axis 4 = L2, which the game uses to aim). Empty = off.");
			LogAxes = config.Bind<bool>("ManualFire", "LogControllerTriggers", false, "Log each controller axis/trigger as it's pulled past halfway (to find a trigger's name).");
			BaseInterval = config.Bind<float>("ManualFire", "SecondsPerAction", 0.5f, "Time between fire actions at Fire Rate level 0. Each Fire Rate level adds one more action in this time.");
			BaseStamina = config.Bind<float>("ManualFire", "BaseStamina", 5f, "Stamina points at Stamina level 0.");
			StaminaPerLevel = config.Bind<float>("ManualFire", "StaminaPerLevel", 2f, "Extra stamina points per Stamina upgrade level.");
			RegenPerSecond = config.Bind<float>("ManualFire", "RegenPerSecond", 1f, "Stamina refilled per second while not firing.");
			BaseCost = config.Bind<float>("ManualFire", "StaminaPerWeapon", 1f, "Stamina each weapon costs per action at Efficiency level 0.");
			CostReductionPerLevel = config.Bind<float>("ManualFire", "CostReductionPerLevel", 0.1f, "Stamina per weapon saved per Efficiency upgrade level.");
			LateCostReduction = config.Bind<float>("ManualFire", "CostReductionPerLevelAfter5", 0.05f, "Stamina per weapon saved by each Efficiency level above 5.");
			MinCost = config.Bind<float>("ManualFire", "MinStaminaPerWeapon", 0.25f, "Efficiency can't lower the cost per weapon below this.");
			AlwaysOnWeapons = config.Bind<string>("ManualFire", "AlwaysOnWeapons", "auto", "Passive weapons that keep working on their own (at reduced damage) instead of waiting for the fire button. \"auto\" = every weapon whose attack is a constant attack in the game data (the log lists them); or a comma-separated list of weapon names.");
			UnaffectedWeapons = config.Bind<string>("ManualFire", "UnaffectedWeapons", "Aegis,Chunkers", "Weapons left exactly as in the normal game: they fire on their own at full damage and cost no stamina.");
			AlwaysOnDamage = config.Bind<float>("ManualFire", "AlwaysOnDamage", 0.1f, "Damage multiplier for passive weapons while not triggered (0.1 = 10%); triggering releases full damage.");
			ConfigEntry<string> autoPrice = config.Bind<string>("ManualFire", "AutoFirePrice", "200", "Silver price of Auto Fire (hold to keep firing).");
			ConfigEntry<string> staminaPrices = config.Bind<string>("ManualFire", "StaminaPrices", "50,50,50,50,100,100,100,100,150,150", "Silver price of each Stamina level.");
			ConfigEntry<string> efficiencyPrices = config.Bind<string>("ManualFire", "EfficiencyPrices", "50,50,50,50,100,100,100,100,150,150", "Silver price of each Efficiency level.");
			ConfigEntry<string> ratePrices = config.Bind<string>("ManualFire", "FireRatePrices", "50,50,50,50,100,100", "Silver price of each Fire Rate level.");
			ConfigEntry<string> rechargePrices = config.Bind<string>("ManualFire", "RechargePrices", "50,50,50,50,100,100,100,100,150,150", "Silver price of each Recharge level.");
			RegenPerLevel = config.Bind<float>("ManualFire", "RegenPerLevel", 0.5f, "Extra stamina refilled per second per Recharge upgrade level.");
			AutoFire = new CustomShopItem(107, "Auto Fire", progress.Bind<int>("Progress", "AutoFireLevel", 0, "1 when Auto Fire is owned. Managed by the mod."), () => CustomShopItem.ParsePrices(autoPrice.Value), () => "Hold the fire button to keep firing, machine-gun style, while stamina lasts.", null);
			StaminaUp = new CustomShopItem(108, "Stamina", progress.Bind<int>("Progress", "StaminaLevel", 0, "Stamina upgrade levels. Managed by the mod."), () => CustomShopItem.ParsePrices(staminaPrices.Value), () => $"More stamina for firing. Each level adds {StaminaPerLevel.Value:0.#} stamina.", null);
			Efficiency = new CustomShopItem(109, "Efficiency", progress.Bind<int>("Progress", "EfficiencyLevel", 0, "Efficiency upgrade levels. Managed by the mod."), () => CustomShopItem.ParsePrices(efficiencyPrices.Value), () => $"Each weapon costs less stamina to fire. Levels 1-5 save {CostReductionPerLevel.Value:0.##} stamina per weapon each, later levels {LateCostReduction.Value:0.##}.", null

MoreSlots.dll

Decompiled 10 hours ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Assets.Scripts.Inventory__Items__Pickups;
using Assets.Scripts.Saves___Serialization.SaveFiles;
using Assets.Scripts._Data.ShopItems;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MoreSlots")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.0.0")]
[assembly: AssemblyInformationalVersion("0.3.0+9583c9456c88608702ad5b96818742c7ac815822")]
[assembly: AssemblyProduct("MoreSlots")]
[assembly: AssemblyTitle("MoreSlots")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.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;
		}
	}
}
namespace MoreSlots
{
	[BepInPlugin("com.megabonkmods.moreslots", "MoreSlots", "0.3.0")]
	public class Plugin : BasePlugin
	{
		public const string Guid = "com.megabonkmods.moreslots";

		public const string Name = "MoreSlots";

		public const string Version = "0.3.0";

		internal static ManualLogSource Log;

		public override void Load()
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			Log = ((BasePlugin)this).Log;
			SlotShop.Tomes = new SlotShop((EShopItem)4, ((BasePlugin)this).Config.Bind<int>("Tomes", "ExtraSlots", 4, "Additional tome slot levels added to the shop's Tomes upgrade."), ((BasePlugin)this).Config.Bind<int>("Tomes", "PricePerSlot", 135, "Silver cost of each added tome slot level."));
			SlotShop.Weapons = new SlotShop((EShopItem)3, ((BasePlugin)this).Config.Bind<int>("Weapons", "ExtraSlots", 4, "Additional weapon slot levels added to the shop's Weapons upgrade."), ((BasePlugin)this).Config.Bind<int>("Weapons", "PricePerSlot", 125, "Silver cost of each added weapon slot level."));
			Harmony val = new Harmony("com.megabonkmods.moreslots");
			val.PatchAll();
			MaxSlotPatches.Apply(val);
			ManualLogSource log = Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(13, 4, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("MoreSlots");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("0.3.0");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" loaded. ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<SlotShop>(SlotShop.Tomes);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" | ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<SlotShop>(SlotShop.Weapons);
			}
			log.LogInfo(val2);
		}
	}
	internal class SlotShop
	{
		internal static SlotShop Tomes;

		internal static SlotShop Weapons;

		internal readonly EShopItem Item;

		internal readonly ConfigEntry<int> Extra;

		internal readonly ConfigEntry<int> Price;

		internal int OrigMax = -1;

		internal bool Ready => OrigMax >= 0;

		internal SlotShop(EShopItem item, ConfigEntry<int> extra, ConfigEntry<int> price)
		{
			//IL_000e: 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)
			Item = item;
			Extra = extra;
			Price = price;
		}

		internal static SlotShop For(EShopItem item)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if ((int)item != 4)
			{
				if ((int)item != 3)
				{
					return null;
				}
				return Weapons;
			}
			return Tomes;
		}

		internal static SlotShop For(ShopItemData data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			SlotShop slotShop = For(data.eShopItem);
			if (slotShop == null || !slotShop.Ready)
			{
				return null;
			}
			return slotShop;
		}

		internal int CurrentLevel()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			SaveManager instance = SaveManager.Instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				ProgressionSaveFile progression = instance.progression;
				obj = ((progression != null) ? progression.shopItems : null);
			}
			Dictionary<EShopItem, int> val = (Dictionary<EShopItem, int>)obj;
			int result = default(int);
			if (val == null || !val.TryGetValue(Item, ref result))
			{
				return 0;
			}
			return result;
		}

		internal int BoughtExtra()
		{
			if (!Ready)
			{
				return 0;
			}
			return Math.Max(0, CurrentLevel() - OrigMax);
		}

		public override string ToString()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			return $"{Item}: +{Extra.Value} @ {Price.Value} silver";
		}
	}
	[HarmonyPatch(typeof(DataManager), "Load")]
	internal static class DataManager_Load
	{
		private static void Postfix(DataManager __instance)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			SlotShop[] array = new SlotShop[2]
			{
				SlotShop.Tomes,
				SlotShop.Weapons
			};
			bool flag = default(bool);
			foreach (SlotShop slotShop in array)
			{
				ShopItemData shopItemData = __instance.GetShopItemData(slotShop.Item);
				if ((Object)(object)shopItemData == (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(34, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<EShopItem>(slotShop.Item);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" shop item not found; not patched.");
					}
					log.LogWarning(val);
					continue;
				}
				if (slotShop.OrigMax < 0)
				{
					slotShop.OrigMax = shopItemData.maxLevel;
				}
				shopItemData.maxLevel = slotShop.OrigMax + slotShop.Extra.Value;
				ManualLogSource log2 = Plugin.Log;
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(25, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<EShopItem>(slotShop.Item);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" shop item: maxLevel ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(slotShop.OrigMax);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" -> ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(shopItemData.maxLevel);
				}
				log2.LogInfo(val2);
			}
		}
	}
	[HarmonyPatch(typeof(ShopItemData), "GetMaxLevel")]
	internal static class ShopItemData_GetMaxLevel
	{
		private static void Postfix(ShopItemData __instance, ref int __result)
		{
			if (SlotShop.For(__instance) != null)
			{
				__result = __instance.maxLevel;
			}
		}
	}
	[HarmonyPatch(typeof(ShopItemData), "IsMaxLevel")]
	internal static class ShopItemData_IsMaxLevel
	{
		private static void Postfix(ShopItemData __instance, ref bool __result)
		{
			SlotShop slotShop = SlotShop.For(__instance);
			if (slotShop != null)
			{
				__result = slotShop.CurrentLevel() >= __instance.maxLevel;
			}
		}
	}
	[HarmonyPatch(typeof(ShopItemData), "GetLevelPrice")]
	internal static class ShopItemData_GetLevelPrice
	{
		private static bool Prefix(ShopItemData __instance, int level, ref int __result)
		{
			SlotShop slotShop = SlotShop.For(__instance);
			if (slotShop == null || level < slotShop.OrigMax)
			{
				return true;
			}
			__result = slotShop.Price.Value;
			return false;
		}
	}
	internal static class MaxSlotPatches
	{
		private enum Kind
		{
			None,
			Tomes,
			Weapons,
			Both
		}

		[ThreadStatic]
		private static int depth;

		[ThreadStatic]
		private static Kind kind;

		internal static void Apply(Harmony harmony)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(InventoryUtility), "GetNumMaxTomeSlots", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(InventoryUtility), "GetNumMaxWeaponSlots", (Type[])null, (Type[])null);
			bool flag = NativeAddress("NativeMethodInfoPtr_GetNumMaxTomeSlots_Public_Static_Int32_0") == NativeAddress("NativeMethodInfoPtr_GetNumMaxWeaponSlots_Public_Static_Int32_0");
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(MaxSlotPatches), "CapPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			if (!flag)
			{
				harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(MaxSlotPatches), "CapPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			Scope(harmony, "GetNumAvailableTomeSlots", "TomesPrefix");
			Scope(harmony, "CanUnlockTomes", "TomesPrefix");
			Scope(harmony, "GetNumAvailableWeaponSlots", "WeaponsPrefix");
			Scope(harmony, "CanUnlockWeapons", "WeaponsPrefix");
			ScopeOn(harmony, AccessTools.Method(typeof(InventoryHud), "Refresh", (Type[])null, (Type[])null), "BothPrefix");
			ScopeOn(harmony, AccessTools.Method(typeof(UpgradeInventoryUI), "Refresh", (Type[])null, (Type[])null), "BothPrefix");
			ManualLogSource log = Plugin.Log;
			bool flag2 = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(65, 1, ref flag2);
			if (flag2)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Slot caps patched (");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(flag ? "tome and weapon caps share one native function" : "separately");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("), applied only inside the game's slot checks.");
			}
			log.LogInfo(val);
		}

		private static void Scope(Harmony harmony, string method, string prefix)
		{
			ScopeOn(harmony, AccessTools.Method(typeof(InventoryUtility), method, (Type[])null, (Type[])null), prefix);
		}

		private static void ScopeOn(Harmony harmony, MethodBase method, string prefix)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0030: Expected O, but got Unknown
			harmony.Patch(method, new HarmonyMethod(typeof(MaxSlotPatches), prefix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(MaxSlotPatches), "ExitScope", (Type[])null), (HarmonyMethod)null);
		}

		private static void Enter(Kind k)
		{
			if (depth++ == 0 || k != Kind.Both)
			{
				kind = k;
			}
		}

		private static void TomesPrefix(out Kind __state)
		{
			__state = kind;
			Enter(Kind.Tomes);
		}

		private static void WeaponsPrefix(out Kind __state)
		{
			__state = kind;
			Enter(Kind.Weapons);
		}

		private static void BothPrefix(out Kind __state)
		{
			__state = kind;
			Enter(Kind.Both);
		}

		private static Exception ExitScope(Exception __exception, Kind __state)
		{
			if (depth > 0 && --depth > 0)
			{
				kind = __state;
			}
			else
			{
				kind = Kind.None;
			}
			return __exception;
		}

		private static void CapPostfix(ref int __result)
		{
			if (depth != 0)
			{
				int num = __result;
				__result = num + kind switch
				{
					Kind.Tomes => SlotShop.Tomes.BoughtExtra(), 
					Kind.Weapons => SlotShop.Weapons.BoughtExtra(), 
					_ => Math.Max(SlotShop.Tomes.BoughtExtra(), SlotShop.Weapons.BoughtExtra()), 
				};
			}
		}

		private unsafe static IntPtr NativeAddress(string methodInfoField)
		{
			return *(IntPtr*)(void*)(IntPtr)AccessTools.Field(typeof(InventoryUtility), methodInfoField).GetValue(null);
		}
	}
}