Decompiled source of MoreUpgrades v1.0.2

plugins/MoreUpgrades/MoreUpgrades.dll

Decompiled 5 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Extensions;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using MoreMountains.Tools;
using MoreUpgrades.Menu;
using Steamworks;
using TMPro;
using TryConnect;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 MoreUpgrades
{
	public class ExtraDailyTimeUpgrade : Upgrade
	{
		public const float SecondsPerUse = 30f;

		private static readonly FieldRef<Upgrade, TextMeshPro> ValueTextField = AccessTools.FieldRefAccess<Upgrade, TextMeshPro>("valueText");

		private bool _hasBeenUsed;

		private void Start()
		{
			TextMeshPro val = ValueTextField.Invoke((Upgrade)(object)this);
			if ((Object)(object)val != (Object)null)
			{
				((TMP_Text)val).text = $"+{30f:0.#}s";
			}
		}

		protected override void OnUseItem(bool isPressed)
		{
			if (!_hasBeenUsed)
			{
				_hasBeenUsed = true;
				if (((NetworkBehaviour)this).isServer)
				{
					((MonoBehaviour)this).StartCoroutine(UseRoutine());
				}
			}
		}

		private IEnumerator UseRoutine()
		{
			yield return (object)new WaitForSecondsRealtime(0.5f);
			GameManager val = Object.FindFirstObjectByType<GameManager>();
			if ((Object)(object)val != (Object)null)
			{
				GameUpgradeState.ShareAcrossLobby(GamePlayerUpgradeType.ExtraDailyTime, 30f);
				GrantExtraTime(val, 30f);
				PluginMain.Log.LogInfo((object)$"Extra Time granted +{30f}s of day duration (state={val.state}).");
			}
			else
			{
				PluginMain.Log.LogWarning((object)"Extra Time: no GameManager found — skipping.");
			}
			((ConsumableItem)this).DestroyItem();
		}

		internal static void GrantExtraTime(GameManager gameManager, float seconds)
		{
			if (NetworkServer.active && !((Object)(object)gameManager == (Object)null) && !(seconds <= 0f))
			{
				gameManager.Network_dayDuration += seconds;
			}
		}

		public override bool Weaved()
		{
			return true;
		}
	}
	public class GameFlavoredUpgrade : Upgrade
	{
		private static readonly FieldRef<Upgrade, Animator> AnimField = AccessTools.FieldRefAccess<Upgrade, Animator>("anim");

		private static readonly FieldRef<Upgrade, SFXComponent> UpgradeSfxField = AccessTools.FieldRefAccess<Upgrade, SFXComponent>("upgradeSfx");

		private static readonly FieldRef<Upgrade, TextMeshPro> ValueTextField = AccessTools.FieldRefAccess<Upgrade, TextMeshPro>("valueText");

		[SerializeField]
		private GamePlayerUpgradeType _upgradeType;

		[SerializeField]
		private float _amount;

		[SerializeField]
		private bool _configured;

		private bool _hasBeenUsed;

		protected GamePlayerUpgradeType UpgradeType => _upgradeType;

		protected float Amount => _amount;

		public void Configure(GamePlayerUpgradeType upgradeType, float amount)
		{
			_upgradeType = upgradeType;
			_amount = amount;
			_configured = true;
		}

		private void Start()
		{
			TextMeshPro val = ValueTextField.Invoke((Upgrade)(object)this);
			if ((Object)(object)val != (Object)null)
			{
				((TMP_Text)val).text = (_amount * 100f).ToString("0.#") + "%";
			}
		}

		protected override void OnUseItem(bool isPressed)
		{
			if (!_hasBeenUsed && _configured)
			{
				_hasBeenUsed = true;
				Animator val = AnimField.Invoke((Upgrade)(object)this);
				if ((Object)(object)val != (Object)null)
				{
					val.SetTrigger("Use");
				}
				if (((NetworkBehaviour)this).isServer)
				{
					((MonoBehaviour)this).StartCoroutine(UseRoutine());
				}
			}
		}

		private IEnumerator UseRoutine()
		{
			yield return (object)new WaitForSecondsRealtime(0.5f);
			PlayerProfile[] array = Object.FindObjectsByType<PlayerProfile>((FindObjectsSortMode)0);
			foreach (PlayerProfile val in array)
			{
				GameUpgradeState.Add(val.steamId, _upgradeType, _amount);
				RpcUpgradeChanged(val.steamId, _upgradeType, GameUpgradeState.Get(val.steamId, _upgradeType));
			}
			PluginMain.Log.LogInfo((object)$"Granted {_upgradeType} +{_amount} to the lobby.");
			SFXComponent val2 = UpgradeSfxField.Invoke((Upgrade)(object)this);
			if ((Object)(object)val2 != (Object)null)
			{
				val2.RpcPlayOneShotWith3DPos();
			}
			((ConsumableItem)this).DestroyItem();
		}

		[ClientRpc]
		private void RpcUpgradeChanged(ulong steamId, GamePlayerUpgradeType type, float newTotal)
		{
			UpgradeHudSync.OnUpgradeChanged(steamId, type, newTotal);
		}

		public override bool Weaved()
		{
			return true;
		}
	}
	public enum GamePlayerUpgradeType
	{
		SlotsLuck,
		RouletteLuck,
		WheelLuck,
		BlackjackLuck,
		PokerLuck,
		BaccaratLuck,
		CrapsLuck,
		MinesweeperLuck,
		CrashLuck,
		PlinkoLuck,
		KenoLuck,
		HiLoLuck,
		DuckRaceLuck,
		CrossyRoadLuck,
		CoinFlipLuck,
		ExtraShopItems,
		ExtraDailyTime
	}
	internal static class GameTypeMap
	{
		private static readonly Dictionary<CasinoGameType, GamePlayerUpgradeType> Map = new Dictionary<CasinoGameType, GamePlayerUpgradeType>
		{
			[(CasinoGameType)12] = GamePlayerUpgradeType.SlotsLuck,
			[(CasinoGameType)11] = GamePlayerUpgradeType.RouletteLuck,
			[(CasinoGameType)9] = GamePlayerUpgradeType.WheelLuck,
			[(CasinoGameType)13] = GamePlayerUpgradeType.WheelLuck,
			[(CasinoGameType)0] = GamePlayerUpgradeType.BlackjackLuck,
			[(CasinoGameType)14] = GamePlayerUpgradeType.PokerLuck,
			[(CasinoGameType)16] = GamePlayerUpgradeType.BaccaratLuck,
			[(CasinoGameType)1] = GamePlayerUpgradeType.CrapsLuck,
			[(CasinoGameType)8] = GamePlayerUpgradeType.MinesweeperLuck,
			[(CasinoGameType)5] = GamePlayerUpgradeType.MinesweeperLuck,
			[(CasinoGameType)2] = GamePlayerUpgradeType.CrashLuck,
			[(CasinoGameType)10] = GamePlayerUpgradeType.PlinkoLuck,
			[(CasinoGameType)7] = GamePlayerUpgradeType.KenoLuck,
			[(CasinoGameType)4] = GamePlayerUpgradeType.HiLoLuck,
			[(CasinoGameType)6] = GamePlayerUpgradeType.DuckRaceLuck,
			[(CasinoGameType)3] = GamePlayerUpgradeType.CrossyRoadLuck,
			[(CasinoGameType)15] = GamePlayerUpgradeType.CoinFlipLuck
		};

		public static GamePlayerUpgradeType? ToUpgrade(CasinoGameType gameType)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (!Map.TryGetValue(gameType, out var value))
			{
				return null;
			}
			return value;
		}
	}
	[Serializable]
	public sealed class GameUpgradeSaveData
	{
		[Serializable]
		public sealed class PlayerEntry
		{
			public string steamId = "";

			public List<ValueEntry> upgrades = new List<ValueEntry>();
		}

		[Serializable]
		public sealed class ValueEntry
		{
			public GamePlayerUpgradeType type;

			public float value;
		}

		public List<PlayerEntry> players = new List<PlayerEntry>();
	}
	internal static class GameUpgradeState
	{
		private static readonly ConcurrentDictionary<ulong, ConcurrentDictionary<GamePlayerUpgradeType, float>> Values = new ConcurrentDictionary<ulong, ConcurrentDictionary<GamePlayerUpgradeType, float>>();

		public static float Get(ulong steamId, GamePlayerUpgradeType type)
		{
			if (Values.TryGetValue(steamId, out ConcurrentDictionary<GamePlayerUpgradeType, float> value) && value.TryGetValue(type, out var value2))
			{
				return value2;
			}
			return 0f;
		}

		public static void Add(ulong steamId, GamePlayerUpgradeType type, float amount)
		{
			Values.GetOrAdd(steamId, (ulong _) => new ConcurrentDictionary<GamePlayerUpgradeType, float>()).AddOrUpdate(type, amount, (GamePlayerUpgradeType _, float existing) => existing + amount);
		}

		public static void Set(ulong steamId, GamePlayerUpgradeType type, float value)
		{
			Values.GetOrAdd(steamId, (ulong _) => new ConcurrentDictionary<GamePlayerUpgradeType, float>())[type] = value;
		}

		public static void ShareAcrossLobby(GamePlayerUpgradeType type, float amount)
		{
			PlayerProfile[] array = Object.FindObjectsByType<PlayerProfile>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				Add(array[i].steamId, type, amount);
			}
		}

		public static void ResetAll()
		{
			Values.Clear();
		}

		public static IEnumerable<(ulong SteamId, GamePlayerUpgradeType Type, float Value)> All()
		{
			foreach (KeyValuePair<ulong, ConcurrentDictionary<GamePlayerUpgradeType, float>> kvp in Values)
			{
				foreach (KeyValuePair<GamePlayerUpgradeType, float> item in kvp.Value)
				{
					yield return (SteamId: kvp.Key, Type: item.Key, Value: item.Value);
				}
			}
		}
	}
	internal static class ItemDescriptionRegistry
	{
		private static readonly ConcurrentDictionary<int, string> DescriptionsBySpawnableId = new ConcurrentDictionary<int, string>();

		private static readonly ConcurrentDictionary<int, string> NamesBySpawnableId = new ConcurrentDictionary<int, string>();

		public static void Register(int spawnableId, string displayName, string description)
		{
			NamesBySpawnableId[spawnableId] = displayName;
			DescriptionsBySpawnableId[spawnableId] = description;
		}

		public static bool TryGetDescription(int spawnableId, out string description)
		{
			return DescriptionsBySpawnableId.TryGetValue(spawnableId, out description);
		}

		public static bool TryGetName(int spawnableId, out string name)
		{
			return NamesBySpawnableId.TryGetValue(spawnableId, out name);
		}
	}
	internal static class ItemRegistrar
	{
		private readonly struct OddsUpgradeDefinition
		{
			public readonly string Key;

			public readonly string DisplayName;

			public readonly string GameLabel;

			public readonly GamePlayerUpgradeType UpgradeType;

			public readonly Color Tint;

			public OddsUpgradeDefinition(string key, string displayName, string gameLabel, GamePlayerUpgradeType upgradeType, Color tint)
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				Key = key;
				DisplayName = displayName;
				GameLabel = gameLabel;
				UpgradeType = upgradeType;
				Tint = tint;
			}
		}

		private const float DefaultOddsBoost = 0.15f;

		private const string ScrollBundlePath = "Assets/moreupgrades.scroll";

		private const string ScrollVisualPrefabName = "scroll";

		private static readonly Vector3 ScrollVisualScale = new Vector3(0.8f, 0.8f, 1.15f);

		private const string PillsBundlePath = "Assets/moreupgrades.pills";

		private const string PillsVisualPrefabName = "pills";

		private static readonly Vector3 PillsVisualScale = Vector3.one * 0.32f;

		private static readonly Vector3 PillsVisualEulerAngles = new Vector3(0f, -180f, 0f);

		private static readonly OddsUpgradeDefinition[] OddsUpgrades = new OddsUpgradeDefinition[15]
		{
			new OddsUpgradeDefinition("slots_luck", "Slots Luck", "Slots", GamePlayerUpgradeType.SlotsLuck, HsvColor(0f, 0.85f, 0.9f)),
			new OddsUpgradeDefinition("roulette_reader", "Roulette Reader", "Roulette", GamePlayerUpgradeType.RouletteLuck, HsvColor(24f, 0.9f, 0.75f)),
			new OddsUpgradeDefinition("wheel_whisperer", "Wheel Whisperer", "Money Wheel and Wheel of Fortune", GamePlayerUpgradeType.WheelLuck, HsvColor(48f, 0.9f, 0.95f)),
			new OddsUpgradeDefinition("card_counter", "Card Counter", "Blackjack", GamePlayerUpgradeType.BlackjackLuck, HsvColor(72f, 0.75f, 0.75f)),
			new OddsUpgradeDefinition("poker_face", "Poker Face", "Poker", GamePlayerUpgradeType.PokerLuck, HsvColor(96f, 0.8f, 0.65f)),
			new OddsUpgradeDefinition("baccarat_instinct", "Baccarat Instinct", "Baccarat", GamePlayerUpgradeType.BaccaratLuck, HsvColor(120f, 0.75f, 0.6f)),
			new OddsUpgradeDefinition("loaded_dice", "Loaded Dice", "Craps", GamePlayerUpgradeType.CrapsLuck, HsvColor(144f, 0.85f, 0.7f)),
			new OddsUpgradeDefinition("steady_hands", "Steady Hands", "Minesweeper and Dragon Tower", GamePlayerUpgradeType.MinesweeperLuck, HsvColor(168f, 0.8f, 0.75f)),
			new OddsUpgradeDefinition("crash_sense", "Crash Sense", "Crash", GamePlayerUpgradeType.CrashLuck, HsvColor(192f, 0.85f, 0.9f)),
			new OddsUpgradeDefinition("plinko_precision", "Plinko Precision", "Plinko", GamePlayerUpgradeType.PlinkoLuck, HsvColor(216f, 0.85f, 0.9f)),
			new OddsUpgradeDefinition("keno_clairvoyance", "Keno Clairvoyance", "Keno", GamePlayerUpgradeType.KenoLuck, HsvColor(240f, 0.75f, 0.85f)),
			new OddsUpgradeDefinition("hilo_hunch", "Hi-Lo Hunch", "Hi-Lo", GamePlayerUpgradeType.HiLoLuck, HsvColor(264f, 0.8f, 0.8f)),
			new OddsUpgradeDefinition("duck_whisperer", "Duck Whisperer", "Duck Race", GamePlayerUpgradeType.DuckRaceLuck, HsvColor(288f, 0.85f, 0.85f)),
			new OddsUpgradeDefinition("crossy_confidence", "Crossy Confidence", "Crossy Road", GamePlayerUpgradeType.CrossyRoadLuck, HsvColor(312f, 0.85f, 0.85f)),
			new OddsUpgradeDefinition("coin_sense", "Coin Sense", "Coin Flip", GamePlayerUpgradeType.CoinFlipLuck, HsvColor(336f, 0.9f, 0.8f))
		};

		private static string DurationWord
		{
			get
			{
				if (!PluginMain.PersistentUpgradesPresent)
				{
					return "Boosts (for the rest of today)";
				}
				return "Permanently boosts";
			}
		}

		private static Color HsvColor(float hueDegrees, float saturation, float value)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return Color.HSVToRGB(hueDegrees / 360f, saturation, value);
		}

		public static void RegisterAll(BaseUnityPlugin plugin)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			SpawnableSO val = TryConnectApi.FindVanillaSpawnable<Upgrade>();
			if ((Object)(object)val == (Object)null)
			{
				PluginMain.Log.LogError((object)"Could not find the vanilla Upgrade spawnable — no items were registered.");
				return;
			}
			OddsUpgradeDefinition[] oddsUpgrades = OddsUpgrades;
			for (int i = 0; i < oddsUpgrades.Length; i++)
			{
				OddsUpgradeDefinition oddsUpgradeDefinition = oddsUpgrades[i];
				string description = DurationWord + " your winnings at " + oddsUpgradeDefinition.GameLabel + ".";
				RegisterGameFlavoredUpgrade(plugin, val, oddsUpgradeDefinition.Key, oddsUpgradeDefinition.DisplayName, description, oddsUpgradeDefinition.UpgradeType, 0.15f, oddsUpgradeDefinition.Tint);
			}
			RegisterGameFlavoredUpgrade(plugin, val, "shop_scout", "Shop Scout", DurationWord + " the shop by one extra random item each day.", GamePlayerUpgradeType.ExtraShopItems, 1f, new Color(0.4f, 0.75f, 0.9f));
			RegisterExtraDailyTime(plugin, val);
			RegisterSecondWind(plugin, val);
		}

		private static void RegisterGameFlavoredUpgrade(BaseUnityPlugin plugin, SpawnableSO baseSpawnable, string key, string displayName, string description, GamePlayerUpgradeType upgradeType, float amount, Color tint)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = CreateScrollPrefab(plugin, baseSpawnable, key, "CustomPrefab");
			GameObject val2 = CreateScrollPrefab(plugin, baseSpawnable, key, "MarkerPrefab");
			TryConnectApi.SwapPrefabComponent<Upgrade, GameFlavoredUpgrade>(val).Configure(upgradeType, amount);
			TryConnectApi.SwapPrefabComponent<Upgrade, GameFlavoredUpgrade>(val2).Configure(upgradeType, amount);
			Register(plugin, key, displayName, description, baseSpawnable, val, val2, tint);
		}

		private static void RegisterExtraDailyTime(BaseUnityPlugin plugin, SpawnableSO baseSpawnable)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			Color tint = default(Color);
			((Color)(ref tint))..ctor(0.95f, 0.55f, 0.75f);
			GameObject val = CreateScrollPrefab(plugin, baseSpawnable, "extra_time", "CustomPrefab");
			GameObject val2 = CreateScrollPrefab(plugin, baseSpawnable, "extra_time", "MarkerPrefab");
			TryConnectApi.SwapPrefabComponent<Upgrade, ExtraDailyTimeUpgrade>(val);
			TryConnectApi.SwapPrefabComponent<Upgrade, ExtraDailyTimeUpgrade>(val2);
			string description = "Adds 30 seconds to today's gambling timer." + (PluginMain.PersistentUpgradesPresent ? " Carries over to future days too." : "");
			Register(plugin, "extra_time", "Extra Time", description, baseSpawnable, val, val2, tint);
		}

		private static GameObject CreateScrollPrefab(BaseUnityPlugin plugin, SpawnableSO baseSpawnable, string key, string suffix)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			return CreateBundledVisualPrefab(plugin, baseSpawnable, key, suffix, "Assets/moreupgrades.scroll", "scroll", ScrollVisualScale, Vector3.zero);
		}

		private static GameObject CreatePillsPrefab(BaseUnityPlugin plugin, SpawnableSO baseSpawnable, string key, string suffix)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			return CreateBundledVisualPrefab(plugin, baseSpawnable, key, suffix, "Assets/moreupgrades.pills", "pills", PillsVisualScale, PillsVisualEulerAngles);
		}

		private static GameObject CreateBundledVisualPrefab(BaseUnityPlugin plugin, SpawnableSO baseSpawnable, string key, string suffix, string bundlePath, string visualPrefabName, Vector3 visualScale, Vector3 visualEulerAngles)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = TryConnectApi.CreatePrefabTemplate(baseSpawnable, key + "_" + suffix);
			AssetBundle val2 = TryConnectAssetBundles.LoadRelativeToPlugin(plugin, bundlePath);
			try
			{
				GameObject val3 = TryConnectAssetBundles.LoadAsset<GameObject>(val2, visualPrefabName);
				TryConnectApi.ReplaceVisualsWithPrefab(val, val3, visualScale, true, Vector3.zero, visualEulerAngles);
				return val;
			}
			finally
			{
				val2.Unload(false);
			}
		}

		private static void RegisterSecondWind(BaseUnityPlugin plugin, SpawnableSO baseSpawnable)
		{
			GameObject val = CreatePillsPrefab(plugin, baseSpawnable, "second_wind", "CustomPrefab");
			GameObject val2 = CreatePillsPrefab(plugin, baseSpawnable, "second_wind", "MarkerPrefab");
			TryConnectApi.SwapPrefabComponent<Upgrade, SecondWindItem>(val);
			TryConnectApi.SwapPrefabComponent<Upgrade, SecondWindItem>(val2);
			Register(plugin, "second_wind", "Second Wind", "Regenerates one random missing body part. Single use.", baseSpawnable, val, val2, null, 4);
		}

		private static void Register(BaseUnityPlugin plugin, string key, string displayName, string description, SpawnableSO baseSpawnable, GameObject customPrefab, GameObject markerPrefab, Color tint)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			Register(plugin, key, displayName, description, baseSpawnable, customPrefab, markerPrefab, tint, 4);
		}

		private static void Register(BaseUnityPlugin plugin, string key, string displayName, string description, SpawnableSO baseSpawnable, GameObject customPrefab, GameObject markerPrefab, Color? tint, int replacementChancePercent)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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)
			//IL_00c3: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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)
			int num = TryConnectApi.GenerateSpawnableId(plugin.Info.Metadata.GUID, key);
			ItemDescriptionRegistry.Register(num, displayName, description);
			ApplyInteractableName(customPrefab, displayName);
			ApplyInteractableName(markerPrefab, displayName);
			TryConnectRegistrationResult val = TryConnectApi.RegisterCustomItem(new TryConnectItemRegistration
			{
				OwnerGuid = plugin.Info.Metadata.GUID,
				Key = key,
				SpawnableId = num,
				DisplayName = displayName,
				Description = description,
				BaseSpawnable = baseSpawnable,
				BaseItemComponentType = typeof(Upgrade),
				CustomPrefab = customPrefab,
				MarkerPrefab = markerPrefab,
				ApplyTint = tint.HasValue,
				Tint = tint.GetValueOrDefault(),
				ReplacementChancePercent = replacementChancePercent,
				ExtraBasePrice = 0,
				ExtraFloorPrice = 0
			});
			PluginMain.Log.LogInfo((object)$"Registered '{key}': {val}");
			TryConnectRegisteredItemInfo val2 = default(TryConnectRegisteredItemInfo);
			if (TryConnectApi.TryGetRegisteredItem(num, ref val2) && (Object)(object)val2.Spawnable != (Object)null)
			{
				ApplySpawnableSo(customPrefab, val2.Spawnable);
				ApplySpawnableSo(markerPrefab, val2.Spawnable);
			}
			else
			{
				PluginMain.Log.LogWarning((object)("'" + key + "': could not resolve the registered SpawnableSO — spawnableSo may still point at the wrong item."));
			}
		}

		private static void ApplySpawnableSo(GameObject prefab, SpawnableSO spawnable)
		{
			Item component = prefab.GetComponent<Item>();
			if (!((Object)(object)component == (Object)null))
			{
				component.spawnableSo = spawnable;
			}
		}

		private static void ApplyInteractableName(GameObject prefab, string displayName)
		{
			Item component = prefab.GetComponent<Item>();
			if ((Object)(object)component == (Object)null)
			{
				PluginMain.Log.LogWarning((object)("ApplyInteractableName: '" + ((Object)prefab).name + "' has no Item component — could not set InteractableName."));
				return;
			}
			string interactableName = ((InteractableBase)component).InteractableName;
			((InteractableBase)component).InteractableName = displayName;
			PluginMain.Log.LogInfo((object)("ApplyInteractableName: '" + ((Object)prefab).name + "'.InteractableName '" + interactableName + "' -> '" + displayName + "'."));
		}
	}
	[BepInPlugin("com.cristokos.moreupgrades", "MoreUpgrades", "1.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class PluginMain : BaseUnityPlugin
	{
		public const string PluginGuid = "com.cristokos.moreupgrades";

		public const string PluginName = "MoreUpgrades";

		public const string PluginVersion = "1.0.2";

		private const string TryConnectGuid = "com.Try-4646.TryConnect";

		internal const string PersistentUpgradesGuid = "com.cristokos.persistentupgrades";

		private Harmony? _harmony;

		internal static ManualLogSource Log { get; private set; }

		internal static bool PersistentUpgradesPresent { get; private set; }

		internal static ConfigEntry<bool> UnlockDevConsole { get; private set; }

		internal static ConfigFile ConfigFile { get; private set; }

		private void Awake()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigFile = ((BaseUnityPlugin)this).Config;
			UnlockDevConsole = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "UnlockDevConsole", false, "Unlocks the game's built-in dev console (spawn any item on demand) for testing. Leave off for normal play.");
			PersistentUpgradesPresent = Chainloader.PluginInfos.ContainsKey("com.cristokos.persistentupgrades");
			Log.LogInfo((object)(PersistentUpgradesPresent ? "PersistentUpgrades detected — MoreUpgrades upgrades will be permanent and lobby-shared." : "PersistentUpgrades not detected — MoreUpgrades upgrades will reset daily, like vanilla upgrades."));
			_harmony = new Harmony("com.cristokos.moreupgrades");
			PatchAllSafely(_harmony);
			try
			{
				ItemRegistrar.RegisterAll((BaseUnityPlugin)(object)this);
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"ItemRegistrar.RegisterAll threw — some or all items may not have registered: {arg}");
			}
			Log.LogInfo((object)"MoreUpgrades 1.0.2 initialized.");
		}

		private static void PatchAllSafely(Harmony harmony)
		{
			Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(typeof(PluginMain).Assembly);
			foreach (Type type in typesFromAssembly)
			{
				try
				{
					harmony.CreateClassProcessor(type).Patch();
				}
				catch (Exception arg)
				{
					Log.LogError((object)$"Failed to patch '{type.FullName}' — that patch is disabled, everything else continues: {arg}");
				}
			}
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public class SecondWindItem : Upgrade
	{
		private static readonly Random Random = new Random();

		private bool _hasBeenUsed;

		protected override void OnUseItem(bool isPressed)
		{
			if (!_hasBeenUsed)
			{
				_hasBeenUsed = true;
				if (((NetworkBehaviour)this).isServer)
				{
					((MonoBehaviour)this).StartCoroutine(UseRoutine());
				}
			}
		}

		private IEnumerator UseRoutine()
		{
			yield return (object)new WaitForSecondsRealtime(0.5f);
			GameManager val = Object.FindFirstObjectByType<GameManager>();
			if ((Object)(object)val == (Object)null)
			{
				PluginMain.Log.LogWarning((object)"Second Wind: no GameManager found — skipping.");
			}
			else if ((int)val.state != 1)
			{
				PluginMain.Log.LogWarning((object)$"Second Wind: GameManager.state is '{val.state}', not Game — skipping.");
			}
			else
			{
				PlayerInventory networkHolder = ((Item)this).NetworkHolder;
				if ((Object)(object)networkHolder == (Object)null)
				{
					PluginMain.Log.LogWarning((object)"Second Wind: NetworkHolder is null — skipping.");
				}
				else
				{
					PlayerOrgans component = ((Component)networkHolder).GetComponent<PlayerOrgans>();
					if ((Object)(object)component == (Object)null)
					{
						PluginMain.Log.LogWarning((object)"Second Wind: holder has no PlayerOrgans component — skipping.");
					}
					else
					{
						RegenerateRandomMissingOrgan(component);
					}
				}
			}
			((ConsumableItem)this).DestroyItem();
		}

		private static void RegenerateRandomMissingOrgan(PlayerOrgans organs)
		{
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			OrganManager val = Object.FindFirstObjectByType<OrganManager>();
			if ((Object)(object)val == (Object)null)
			{
				PluginMain.Log.LogWarning((object)"Second Wind: no OrganManager found — skipping.");
				return;
			}
			if (((NetworkBehaviour)organs).connectionToClient == null)
			{
				PluginMain.Log.LogWarning((object)"Second Wind: organs.connectionToClient is null — skipping.");
				return;
			}
			if (!val.OrganData.TryGetValue(((NetworkBehaviour)organs).connectionToClient.connectionId, out var value))
			{
				PluginMain.Log.LogWarning((object)$"Second Wind: no OrganData entry for connectionId {((NetworkBehaviour)organs).connectionToClient.connectionId} — skipping.");
				return;
			}
			PluginMain.Log.LogInfo((object)$"Second Wind: current organ state — leftEye={value.leftEye}, rightEye={value.rightEye}, body={value.body}, mouth={value.mouth}.");
			List<OrganType> list = new List<OrganType>();
			if (!value.leftEye)
			{
				list.Add((OrganType)0);
			}
			if (!value.rightEye)
			{
				list.Add((OrganType)1);
			}
			if (!value.body)
			{
				list.Add((OrganType)2);
			}
			if (!value.mouth)
			{
				list.Add((OrganType)3);
			}
			if (list.Count == 0)
			{
				PluginMain.Log.LogInfo((object)"Second Wind: no missing organs — nothing to regenerate.");
				return;
			}
			OrganType val2 = list[Random.Next(list.Count)];
			val.ServerToggleOrgan(organs, val2, true);
			PluginMain.Log.LogInfo((object)$"Second Wind regenerated {val2}.");
		}

		public override bool Weaved()
		{
			return true;
		}
	}
}
namespace MoreUpgrades.Patches
{
	[HarmonyPatch(typeof(SettingsLayoutRuntimeUI), "ShowTab")]
	internal static class BulkToggleButtonsPatch
	{
		private static readonly FieldInfo? ResetEntryPrefabField = AccessTools.Field(typeof(SettingsLayoutRuntimeUI), "resetEntryPrefab");

		private static readonly FieldInfo? LayoutField = AccessTools.Field(typeof(SettingsLayoutRuntimeUI), "layout");

		private static readonly FieldInfo? TabContentsField = AccessTools.Field(typeof(SettingsLayoutRuntimeUI), "tabContents");

		private static readonly Random Random = new Random();

		private static void Postfix(SettingsLayoutRuntimeUI __instance, string tabName)
		{
			object? obj = LayoutField?.GetValue(__instance);
			SettingsLayout val = (SettingsLayout)((obj is SettingsLayout) ? obj : null);
			if (val == null || val.tabs == null)
			{
				return;
			}
			List<ToggleSettingItem> toggleEntries = (from e in val.tabs.Find((Tab t) => string.Equals(t.tabName, tabName, StringComparison.OrdinalIgnoreCase))?.entries?.OfType<ToggleSettingItem>()
				where ItemToggleMenu.IsShopToggleKey(((SettingItemBase)e).key)
				select e).ToList();
			if (toggleEntries == null || toggleEntries.Count == 0)
			{
				return;
			}
			Transform val2 = FindContentRoot(__instance, tabName);
			object? obj2 = ResetEntryPrefabField?.GetValue(__instance);
			GameObject val3 = (GameObject)((obj2 is GameObject) ? obj2 : null);
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null))
			{
				CreateBulkButton(val3, val2, "\"MoreUpgrades\" — All On", delegate
				{
					SetAll(__instance, tabName, toggleEntries, enabled: true);
				});
				CreateBulkButton(val3, val2, "\"MoreUpgrades\" — All Off", delegate
				{
					SetAll(__instance, tabName, toggleEntries, enabled: false);
				});
				CreateBulkButton(val3, val2, "\"MoreUpgrades\" — Randomize", delegate
				{
					Randomize(__instance, tabName, toggleEntries);
				});
			}
		}

		private static Transform? FindContentRoot(SettingsLayoutRuntimeUI runtimeUi, string tabName)
		{
			if (!(TabContentsField?.GetValue(runtimeUi) is IEnumerable enumerable))
			{
				return null;
			}
			foreach (object item in enumerable)
			{
				FieldInfo? field = item.GetType().GetField("tabName");
				FieldInfo field2 = item.GetType().GetField("contentRoot");
				if (string.Equals(field?.GetValue(item) as string, tabName, StringComparison.OrdinalIgnoreCase))
				{
					object? obj = field2?.GetValue(item);
					object? obj2 = ((obj is RectTransform) ? obj : null);
					return (obj2 != null) ? ((Component)obj2).transform : null;
				}
			}
			return null;
		}

		private static void CreateBulkButton(GameObject resetPrefab, Transform parent, string label, Action onClick)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			GameObject obj = Object.Instantiate<GameObject>(resetPrefab, parent);
			((Object)obj).name = "MoreUpgrades_" + label;
			TMP_Text componentInChildren = obj.GetComponentInChildren<TMP_Text>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.text = label;
			}
			Button componentInChildren2 = obj.GetComponentInChildren<Button>(true);
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				((UnityEvent)componentInChildren2.onClick).AddListener((UnityAction)delegate
				{
					onClick();
				});
			}
		}

		private static void SetAll(SettingsLayoutRuntimeUI runtimeUi, string tabName, List<ToggleSettingItem> entries, bool enabled)
		{
			foreach (ToggleSettingItem entry in entries)
			{
				entry.value = enabled;
				((SettingItemBase)entry).NotifyChanged();
			}
			PluginMain.Log.LogInfo((object)string.Format("MoreUpgrades: bulk-set {0} shop item(s) to {1}.", entries.Count, enabled ? "enabled" : "disabled"));
			runtimeUi.ShowTab(tabName);
		}

		private static void Randomize(SettingsLayoutRuntimeUI runtimeUi, string tabName, List<ToggleSettingItem> entries)
		{
			foreach (ToggleSettingItem entry in entries)
			{
				entry.value = Random.Next(2) == 0;
				((SettingItemBase)entry).NotifyChanged();
			}
			PluginMain.Log.LogInfo((object)$"MoreUpgrades: randomized {entries.Count} shop item(s)' enabled state.");
			runtimeUi.ShowTab(tabName);
		}
	}
	[HarmonyPatch(typeof(UpgradeManager), "ServerResetAllUpgradesToDefaults")]
	internal static class DefaultDailyResetPatch
	{
		private static void Postfix()
		{
			if (NetworkServer.active && !PluginMain.PersistentUpgradesPresent)
			{
				GameUpgradeState.ResetAll();
				PluginMain.Log.LogInfo((object)"Reset MoreUpgrades upgrade values for the new day (PersistentUpgrades not installed).");
			}
		}
	}
	[HarmonyPatch(typeof(NewConsole), "Start")]
	internal static class DevConsoleUnlockPatch
	{
		private static void Postfix(NewConsole __instance)
		{
			if (PluginMain.UnlockDevConsole.Value && (Object)(object)__instance._devConsoleSetting != (Object)null && !__instance._devConsoleSetting.value)
			{
				__instance._devConsoleSetting.value = true;
				PluginMain.Log.LogInfo((object)"Dev console unlocked for testing (MoreUpgrades Debug.UnlockDevConsole is enabled).");
			}
		}
	}
	[HarmonyPatch(typeof(UpgradeManager), "ServerResetAllUpgradesToDefaults")]
	internal static class ExtraDailyTimeDayResetPatch
	{
		private static void Postfix()
		{
			if (!NetworkServer.active)
			{
				return;
			}
			GameManager val = Object.FindFirstObjectByType<GameManager>();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			GameSettings val2 = Resources.Load<GameSettings>("GameSettings");
			float num = (val.Network_dayDuration = (((Object)(object)val2 != (Object)null) ? val2.dayDuration : 300f));
			if (!PluginMain.PersistentUpgradesPresent)
			{
				PluginMain.Log.LogInfo((object)$"Extra Time: day duration reset to base {num}s (PersistentUpgrades not installed).");
				return;
			}
			float num3 = 0f;
			PlayerProfile[] array = Object.FindObjectsByType<PlayerProfile>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				float num4 = GameUpgradeState.Get(array[i].steamId, GamePlayerUpgradeType.ExtraDailyTime);
				if (num4 > num3)
				{
					num3 = num4;
				}
			}
			if (num3 > 0f)
			{
				ExtraDailyTimeUpgrade.GrantExtraTime(val, num3);
			}
			PluginMain.Log.LogInfo((object)$"Extra Time: day duration reset to base {num}s, then restored +{num3}s (PersistentUpgrades installed).");
		}
	}
	internal static class ExtraShopItemSpawner
	{
		private static readonly Random Random = new Random();

		private static readonly List<GameObject> SpawnedInstances = new List<GameObject>();

		private static readonly HashSet<string> ExcludedLootTableNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Cosmetics", "MysteryBox" };

		private static readonly FieldInfo? LootTableField = AccessTools.Field(typeof(ItemStamp), "lootTable");

		public static void SpawnForNewDay(MonoBehaviour coroutineHost)
		{
			SpawnedInstances.RemoveAll((GameObject x) => (Object)(object)x == (Object)null);
			Spawn(coroutineHost, "for the new day");
		}

		public static void RespawnForReroll(MonoBehaviour coroutineHost)
		{
			foreach (GameObject spawnedInstance in SpawnedInstances)
			{
				if ((Object)(object)spawnedInstance != (Object)null)
				{
					NetworkServer.Destroy(spawnedInstance);
				}
			}
			SpawnedInstances.Clear();
			Spawn(coroutineHost, "for the reroll");
		}

		private static void Spawn(MonoBehaviour coroutineHost, string logContext)
		{
			int num = Mathf.RoundToInt(HighestStackedExtraShopItems());
			if (num <= 0)
			{
				return;
			}
			List<ItemStamp> list = FindShopStamps();
			if (list.Count == 0)
			{
				PluginMain.Log.LogWarning((object)("Shop Scout: no shop ItemStamp pedestals found to spawn extra items near (" + logContext + ") — skipping."));
				return;
			}
			List<GameObject> eligiblePrefabs = GetEligiblePrefabs(list);
			if (eligiblePrefabs.Count == 0)
			{
				PluginMain.Log.LogWarning((object)("Shop Scout: found shop pedestals but no eligible items in their loot tables (" + logContext + ") — skipping."));
				return;
			}
			List<Vector3> stampPositions = list.Select((ItemStamp s) => ((Component)s).transform.position).ToList();
			coroutineHost.StartCoroutine(SpawnExtraItems(stampPositions, eligiblePrefabs, num, logContext));
		}

		private static List<ItemStamp> FindShopStamps()
		{
			ItemStamp[] array = Object.FindObjectsByType<ItemStamp>((FindObjectsSortMode)0);
			List<ItemStamp> list = new List<ItemStamp>();
			ItemStamp[] array2 = array;
			foreach (ItemStamp val in array2)
			{
				if (!((Object)(object)val == (Object)null))
				{
					object? obj = LootTableField?.GetValue(val);
					MMLootTableGameObjectSO val2 = (MMLootTableGameObjectSO)((obj is MMLootTableGameObjectSO) ? obj : null);
					string text = (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : null);
					if (text == null || !ExcludedLootTableNames.Contains(text))
					{
						list.Add(val);
					}
				}
			}
			return list;
		}

		private static List<GameObject> GetEligiblePrefabs(List<ItemStamp> shopStamps)
		{
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			foreach (ItemStamp shopStamp in shopStamps)
			{
				object? obj = LootTableField?.GetValue(shopStamp);
				List<MMLootGameObject> list = ((MMLootTable<MMLootGameObject, GameObject>)(object)((MMLootTableGameObjectSO)(((obj is MMLootTableGameObjectSO) ? obj : null)?)).LootTable)?.ObjectsToLoot;
				if (list == null)
				{
					continue;
				}
				foreach (MMLootGameObject item in list)
				{
					if ((Object)(object)((MMLoot<GameObject>)(object)item)?.Loot != (Object)null)
					{
						hashSet.Add(((MMLoot<GameObject>)(object)item).Loot);
					}
				}
			}
			return hashSet.ToList();
		}

		private static IEnumerator SpawnExtraItems(List<Vector3> stampPositions, List<GameObject> eligible, int count, string logContext)
		{
			for (int i = 0; i < count; i++)
			{
				GameObject obj = eligible[Random.Next(eligible.Count)];
				Vector3 val = stampPositions[Random.Next(stampPositions.Count)];
				Vector3 val2 = new Vector3((float)(Random.NextDouble() * 2.0 - 1.0), 0f, (float)(Random.NextDouble() * 2.0 - 1.0)) * 0.75f;
				Vector3 val3 = val + val2 + Vector3.up * 0.5f;
				GameObject val4 = Object.Instantiate<GameObject>(obj, val3, Quaternion.identity);
				NetworkServer.Spawn(val4, (NetworkConnectionToClient)null);
				SpawnedInstances.Add(val4);
				yield return (object)new WaitForSeconds(0.1f);
			}
			PluginMain.Log.LogInfo((object)$"Shop Scout spawned {count} extra item(s) near the shop pedestals ({logContext}).");
		}

		private static float HighestStackedExtraShopItems()
		{
			float num = 0f;
			PlayerProfile[] array = Object.FindObjectsByType<PlayerProfile>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				float num2 = GameUpgradeState.Get(array[i].steamId, GamePlayerUpgradeType.ExtraShopItems);
				if (num2 > num)
				{
					num = num2;
				}
			}
			return num;
		}
	}
	[HarmonyPatch(typeof(ItemManager), "ServerResetItems")]
	internal static class ExtraShopItemDayResetPatch
	{
		private static void Postfix(ItemManager __instance)
		{
			if (NetworkServer.active)
			{
				ExtraShopItemSpawner.SpawnForNewDay((MonoBehaviour)(object)__instance);
			}
		}
	}
	[HarmonyPatch(typeof(ItemStampManager), "RerollAllItemStamps")]
	internal static class ExtraShopItemRerollPatch
	{
		private static void Postfix(ItemStampManager __instance)
		{
			if (NetworkServer.active)
			{
				ExtraShopItemSpawner.RespawnForReroll((MonoBehaviour)(object)__instance);
			}
		}
	}
	[HarmonyPatch(typeof(ItemStampManager), "RetrieveAndRespawnAllItemStamps")]
	internal static class ExtraShopItemRetrievePatch
	{
		private static void Postfix(ItemStampManager __instance)
		{
			if (NetworkServer.active)
			{
				ExtraShopItemSpawner.RespawnForReroll((MonoBehaviour)(object)__instance);
			}
		}
	}
	[HarmonyPatch(typeof(GameBase), "Payout")]
	internal static class GameOddsUpgradePatch
	{
		private static readonly FieldRef<GameBase, PlayerProfile> InteractingPlayerRef = AccessTools.FieldRefAccess<GameBase, PlayerProfile>("interactingPlayer");

		private static void Prefix(GameBase __instance, ref double multiplier)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				return;
			}
			GamePlayerUpgradeType? gamePlayerUpgradeType = GameTypeMap.ToUpgrade(__instance.GameType);
			if (!gamePlayerUpgradeType.HasValue)
			{
				return;
			}
			PlayerProfile val = InteractingPlayerRef.Invoke(__instance);
			if (!((Object)(object)val == (Object)null))
			{
				float num = GameUpgradeState.Get(val.steamId, gamePlayerUpgradeType.Value);
				if (num != 0f)
				{
					multiplier *= 1.0 + (double)num;
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class GameUpgradeSaveLoadPatch
	{
		private static string SaveDirectoryPath => Path.Combine(Application.persistentDataPath, "Saves");

		internal static string SidecarPathFor(string saveName)
		{
			return Path.Combine(SaveDirectoryPath, saveName + ".moreupgrades.json");
		}

		[HarmonyPatch(typeof(SaveManager), "SaveGame")]
		[HarmonyPostfix]
		private static void AfterSaveGame(SaveManager __instance)
		{
			if (!NetworkServer.active || string.IsNullOrEmpty(__instance.CurrentSaveName))
			{
				return;
			}
			GameUpgradeSaveData gameUpgradeSaveData = new GameUpgradeSaveData();
			Dictionary<ulong, GameUpgradeSaveData.PlayerEntry> dictionary = new Dictionary<ulong, GameUpgradeSaveData.PlayerEntry>();
			foreach (var (key, type, value) in GameUpgradeState.All())
			{
				if (!dictionary.TryGetValue(key, out var value2))
				{
					GameUpgradeSaveData.PlayerEntry obj = new GameUpgradeSaveData.PlayerEntry
					{
						steamId = key.ToString()
					};
					value2 = (dictionary[key] = obj);
					gameUpgradeSaveData.players.Add(value2);
				}
				value2.upgrades.Add(new GameUpgradeSaveData.ValueEntry
				{
					type = type,
					value = value
				});
			}
			try
			{
				if (!Directory.Exists(SaveDirectoryPath))
				{
					Directory.CreateDirectory(SaveDirectoryPath);
				}
				File.WriteAllText(SidecarPathFor(__instance.CurrentSaveName), JsonUtility.ToJson((object)gameUpgradeSaveData, true));
				PluginMain.Log.LogInfo((object)$"Saved {gameUpgradeSaveData.players.Count} player(s) worth of MoreUpgrades values.");
			}
			catch (Exception ex)
			{
				PluginMain.Log.LogError((object)("Failed to save MoreUpgrades values: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(SaveManager), "LoadGame")]
		[HarmonyPostfix]
		private static void AfterLoadGame(SaveManager __instance)
		{
			if (!NetworkServer.active || string.IsNullOrEmpty(__instance.CurrentSaveName))
			{
				return;
			}
			string path = SidecarPathFor(__instance.CurrentSaveName);
			if (!File.Exists(path))
			{
				return;
			}
			try
			{
				GameUpgradeSaveData gameUpgradeSaveData = JsonUtility.FromJson<GameUpgradeSaveData>(File.ReadAllText(path));
				if (gameUpgradeSaveData?.players == null)
				{
					return;
				}
				int num = 0;
				foreach (GameUpgradeSaveData.PlayerEntry player in gameUpgradeSaveData.players)
				{
					if (string.IsNullOrEmpty(player.steamId) || !ulong.TryParse(player.steamId, out var result))
					{
						continue;
					}
					foreach (GameUpgradeSaveData.ValueEntry upgrade in player.upgrades)
					{
						GameUpgradeState.Set(result, upgrade.type, upgrade.value);
						num++;
					}
				}
				if (num > 0)
				{
					PluginMain.Log.LogInfo((object)$"Restored {num} MoreUpgrades value(s) from the loaded save.");
				}
			}
			catch (Exception ex)
			{
				PluginMain.Log.LogError((object)("Failed to load MoreUpgrades values: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(ItemDescriptionLocalization), "FetchDescription")]
	internal static class ItemDescriptionLocalizationPatch
	{
		private static bool Prefix(int spawnableId, Action<string> onComplete, ref IEnumerator __result)
		{
			if (!ItemDescriptionRegistry.TryGetDescription(spawnableId, out string description))
			{
				return true;
			}
			onComplete?.Invoke(description);
			__result = NoOp();
			return false;
		}

		private static IEnumerator NoOp()
		{
			yield break;
		}
	}
	[HarmonyPatch(typeof(ItemInteractLocalization), "FetchName")]
	internal static class ItemNameLocalizationPatch
	{
		private static bool Prefix(int spawnableId, Action<string> onComplete, ref IEnumerator __result)
		{
			if (!ItemDescriptionRegistry.TryGetName(spawnableId, out string name))
			{
				return true;
			}
			PluginMain.Log.LogInfo((object)$"ItemNameLocalizationPatch: serving '{name}' for spawnableId {spawnableId}.");
			onComplete?.Invoke(name);
			__result = NoOp();
			return false;
		}

		private static IEnumerator NoOp()
		{
			yield break;
		}
	}
	[HarmonyPatch(typeof(MysteryBox), "GetRandomSpawnableByWeight")]
	internal static class MysteryBoxEnforcementPatch
	{
		private static readonly Random Random = new Random();

		private static readonly FieldInfo? SpawnableListField = AccessTools.Field(typeof(MysteryBox), "spawnableList");

		private static readonly FieldInfo? SpawnableField = ResolveSpawnableEntryField();

		private static void Postfix(MysteryBox __instance, ref SpawnableSO __result)
		{
			if ((Object)(object)__result == (Object)null || ItemEnabledState.IsEnabled(ShopCatalog.KeyForVanilla(__result.spawnableID)) || !(SpawnableListField?.GetValue(__instance) is IEnumerable enumerable))
			{
				return;
			}
			List<SpawnableSO> list = new List<SpawnableSO>();
			foreach (object item in enumerable)
			{
				object? obj = SpawnableField?.GetValue(item);
				SpawnableSO val = (SpawnableSO)((obj is SpawnableSO) ? obj : null);
				if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)__result && ItemEnabledState.IsEnabled(ShopCatalog.KeyForVanilla(val.spawnableID)))
				{
					list.Add(val);
				}
			}
			if (list.Count == 0)
			{
				PluginMain.Log.LogWarning((object)("MysteryBox: no enabled alternative to disabled item '" + __result.spawnableName + "' — spawning it anyway."));
				return;
			}
			SpawnableSO val2 = __result;
			__result = list[Random.Next(list.Count)];
			PluginMain.Log.LogInfo((object)("MysteryBox: replaced disabled item '" + val2.spawnableName + "' with '" + __result.spawnableName + "'."));
		}

		private static FieldInfo? ResolveSpawnableEntryField()
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(MysteryBox), "spawnableList");
			Type type = (((object)fieldInfo != null && fieldInfo.FieldType.IsGenericType) ? fieldInfo.FieldType.GetGenericArguments().FirstOrDefault() : null);
			if (!(type != null))
			{
				return null;
			}
			return AccessTools.Field(type, "spawnable");
		}
	}
	[HarmonyPatch(typeof(UpgradeManager), "ServerResetAllUpgradesToDefaults")]
	internal static class PersistentModeRestorePatch
	{
		private static void Postfix()
		{
			if (NetworkServer.active && PluginMain.PersistentUpgradesPresent)
			{
				PluginMain.Log.LogInfo((object)"PersistentUpgrades active — MoreUpgrades values carried over the new day unchanged.");
			}
		}
	}
	[HarmonyPatch(typeof(SaveManager), "ResetCurrentSaveToDefaults")]
	internal static class GameUpgradeStateResetPatch
	{
		private static void Prefix(SaveManager __instance)
		{
			if (!NetworkServer.active)
			{
				return;
			}
			GameUpgradeState.ResetAll();
			if (!string.IsNullOrEmpty(__instance.CurrentSaveName))
			{
				try
				{
					string path = GameUpgradeSaveLoadPatch.SidecarPathFor(__instance.CurrentSaveName);
					if (File.Exists(path))
					{
						File.Delete(path);
					}
				}
				catch (Exception ex)
				{
					PluginMain.Log.LogError((object)("Failed to delete stale MoreUpgrades save file: " + ex.Message));
				}
			}
			PluginMain.Log.LogInfo((object)"Cleared MoreUpgrades upgrade values for new save.");
		}
	}
	[HarmonyPatch(typeof(SettingItemBase), "NotifyChanged")]
	internal static class SettingsChangePatch
	{
		private static void Postfix(SettingItemBase __instance)
		{
			ToggleSettingItem val = (ToggleSettingItem)(object)((__instance is ToggleSettingItem) ? __instance : null);
			if (val != null && ItemToggleMenu.IsShopToggleKey(((SettingItemBase)val).key))
			{
				string text = ItemToggleMenu.CatalogKeyFromSettingKey(((SettingItemBase)val).key);
				ItemEnabledState.SetEnabled(text, val.value);
				PluginMain.Log.LogInfo((object)("Shop item '" + text + "' " + (val.value ? "enabled" : "disabled") + "."));
			}
		}
	}
	[HarmonyPatch]
	internal static class SettingsInjectionPatch
	{
		private static readonly FieldRef<LobbyModeDropdownButton, SettingsLayout> ButtonLayoutRef = AccessTools.FieldRefAccess<LobbyModeDropdownButton, SettingsLayout>("settingsLayout");

		private static readonly FieldRef<SettingsLayoutRuntimeUI, SettingsLayout> RuntimeUiLayoutRef = AccessTools.FieldRefAccess<SettingsLayoutRuntimeUI, SettingsLayout>("layout");

		[HarmonyPostfix]
		[HarmonyPatch(typeof(LobbyModeDropdownButton), "Awake")]
		private static void LobbyModeDropdownButton_Awake_Postfix(LobbyModeDropdownButton __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				SettingsLayout val = ButtonLayoutRef.Invoke(__instance);
				if ((Object)(object)val != (Object)null)
				{
					ItemToggleMenu.EnsureInjected(val, "LobbyModeDropdownButton.Awake");
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(SettingsLayoutRuntimeUI), "Awake")]
		private static void SettingsLayoutRuntimeUI_Awake_Prefix(SettingsLayoutRuntimeUI __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				SettingsLayout val = RuntimeUiLayoutRef.Invoke(__instance);
				if ((Object)(object)val != (Object)null)
				{
					ItemToggleMenu.EnsureInjected(val, "SettingsLayoutRuntimeUI.Awake");
				}
			}
		}
	}
	[HarmonyPatch(typeof(SettingsLocalization), "ApplyString")]
	internal static class SettingsLabelLocalizationPatch
	{
		private const string KeyPrefix = "settings.label.moreupgrades.";

		private static bool Prefix(TMP_Text label, string key, string fallback, ref IEnumerator __result)
		{
			if ((Object)(object)label == (Object)null || key == null || !key.StartsWith("settings.label.moreupgrades."))
			{
				return true;
			}
			label.text = fallback;
			__result = NoOp();
			return false;
		}

		private static IEnumerator NoOp()
		{
			yield break;
		}
	}
	[HarmonyPatch(typeof(SettingsLayoutRuntimeUI), "CreateDropdownEntry")]
	internal static class SettingsTooltipPatch
	{
		private static void Postfix(RectTransform parent, SettingItemBase entry)
		{
			if (entry is ToggleSettingItem && ItemToggleMenu.IsShopToggleKey(entry.key) && ((Transform)parent).childCount != 0)
			{
				((Component)((Transform)parent).GetChild(((Transform)parent).childCount - 1)).gameObject.AddComponent<SettingsTooltipTrigger>().Description = ItemToggleMenu.DescriptionForSettingKey(entry.key);
			}
		}
	}
	[HarmonyPatch]
	internal static class ShopSpawnEnforcementPatch
	{
		private unsafe static void Postfix(MMLootTableGameObjectSO lootTable, Vector3 stampPosition, GameObject fallbackPrefab, ref GameObject __result)
		{
			if ((Object)(object)fallbackPrefab == (Object)null)
			{
				return;
			}
			PluginMain.Log.LogInfo((object)("ShopSpawnEnforcementPatch.Postfix: fallback='" + ((Object)fallbackPrefab).name + "' result='" + (((Object)(object)__result != (Object)null) ? ((Object)__result).name : "null") + "'."));
			if ((Object)(object)__result != (Object)null && (Object)(object)__result != (Object)(object)fallbackPrefab)
			{
				GameObject rolledPrefab = __result;
				TryConnectRegisteredItemInfo val = ((IEnumerable<TryConnectRegisteredItemInfo>)TryConnectApi.GetRegisteredItems()).FirstOrDefault((Func<TryConnectRegisteredItemInfo, bool>)((TryConnectRegisteredItemInfo i) => i.IsRegistered && (Object)(object)i.Spawnable != (Object)null && (Object)(object)i.Spawnable.prefab == (Object)(object)rolledPrefab));
				if (val != null && !ItemEnabledState.IsEnabled(ShopCatalog.KeyForMod(val.OwnerGuid, val.Key)))
				{
					__result = fallbackPrefab;
				}
			}
			else if (IsDisabledVanillaItem(fallbackPrefab))
			{
				List<(string, string, GameObject, bool)> list = (from r in TryConnectInternals.GetReplacements(fallbackPrefab)
					where r.IsEnabled
					select r).ToList();
				if (list.Count != 0)
				{
					string text = (((Object)(object)lootTable != (Object)null) ? ((Object)lootTable).name : "ItemStamp");
					Random random = new Random((((object)(*(Vector3*)(&stampPosition))/*cast due to .constrained prefix*/).GetHashCode() * 397) ^ (text.GetHashCode() * 31 + ((Object)fallbackPrefab).name.GetHashCode()));
					(string, string, GameObject, bool) tuple = list[random.Next(list.Count)];
					__result = tuple.Item3;
					PluginMain.Log.LogInfo((object)("GetShopReplacement's roll missed every registered item for '" + ((Object)fallbackPrefab).name + "' — forced enabled replacement '" + tuple.Item2 + "' instead of the disabled vanilla fallback."));
				}
			}
		}

		private static bool IsDisabledVanillaItem(GameObject prefab)
		{
			SpawnableSettings val = Resources.Load<SpawnableSettings>("SpawnableSettings");
			if (val?.spawnables == null)
			{
				return false;
			}
			foreach (SpawnableSO spawnable in val.spawnables)
			{
				if ((Object)(object)spawnable != (Object)null && (Object)(object)spawnable.prefab == (Object)(object)prefab)
				{
					return !ItemEnabledState.IsEnabled(ShopCatalog.KeyForVanilla(spawnable.spawnableID));
				}
			}
			return false;
		}

		private static MethodBase? TargetMethod()
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (assembly.GetName().Name.Contains("TryConnect"))
				{
					Type type = assembly.GetType("TryConnect.RuntimeItemRegistry");
					if (type != null)
					{
						return AccessTools.Method(type, "GetShopReplacement", (Type[])null, (Type[])null);
					}
				}
			}
			PluginMain.Log.LogWarning((object)"ShopSpawnEnforcementPatch: could not find TryConnect.RuntimeItemRegistry.GetShopReplacement — the shop item toggle menu will no longer be able to block disabled mod items from spawning. This usually means an incompatible TryConnect update; everything else in this mod is unaffected.");
			return null;
		}
	}
	[HarmonyPatch(typeof(UpgradeManager), "UserCode_RpcClearUpgradeUI")]
	internal static class UpgradeHudClearPatch
	{
		private static void Postfix()
		{
			if (!PluginMain.PersistentUpgradesPresent)
			{
				UpgradeHudSync.Clear();
			}
		}
	}
	[HarmonyPatch(typeof(ItemStampManager), "GetUniqueLoot", new Type[]
	{
		typeof(MMLootTableGameObjectSO),
		typeof(Vector3)
	})]
	internal static class VanillaShopEnforcementPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(ItemStampManager __instance, MMLootTableGameObjectSO lootTable, Vector3 stampPosition, ref GameObject __result)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || (Object)(object)__result == (Object)null || ((MMLootTable<MMLootGameObject, GameObject>)(object)lootTable?.LootTable)?.ObjectsToLoot == null)
			{
				return;
			}
			if (!TryDescribeFinalResult(__result, out string description, out bool isEnabled))
			{
				PluginMain.Log.LogInfo((object)("VanillaShopEnforcementPatch: '" + ((Object)__result).name + "' is not a recognized vanilla or mod catalog entry — skipping enforcement."));
				return;
			}
			PluginMain.Log.LogInfo((object)$"VanillaShopEnforcementPatch: final pick '{description}' isEnabled={isEnabled}.");
			if (!isEnabled)
			{
				GameObject val = PickEnabledAlternative(lootTable, stampPosition, __result);
				if ((Object)(object)val != (Object)null)
				{
					__result = val;
					PluginMain.Log.LogInfo((object)("Replaced disabled item '" + description + "' with '" + ((Object)val).name + "' in the shop."));
				}
				else
				{
					PluginMain.Log.LogWarning((object)("Loot table '" + ((Object)lootTable).name + "' has no enabled alternative to '" + description + "' — spawning it anyway."));
				}
			}
		}

		private static bool TryDescribeFinalResult(GameObject result, out string description, out bool isEnabled)
		{
			if (BuildVanillaLookup().TryGetValue(result, out SpawnableSO value))
			{
				description = $"{value.spawnableName} (id={value.spawnableID})";
				isEnabled = ItemEnabledState.IsEnabled(ShopCatalog.KeyForVanilla(value.spawnableID));
				return true;
			}
			TryConnectRegisteredItemInfo[] registeredItems = TryConnectApi.GetRegisteredItems();
			foreach (TryConnectRegisteredItemInfo val in registeredItems)
			{
				if (val.IsRegistered && (Object)(object)val.Spawnable != (Object)null && (Object)(object)val.Spawnable.prefab == (Object)(object)result)
				{
					description = val.DisplayName;
					isEnabled = ItemEnabledState.IsEnabled(ShopCatalog.KeyForMod(val.OwnerGuid, val.Key));
					return true;
				}
			}
			description = string.Empty;
			isEnabled = false;
			return false;
		}

		private static Dictionary<GameObject, SpawnableSO> BuildVanillaLookup()
		{
			Dictionary<GameObject, SpawnableSO> dictionary = new Dictionary<GameObject, SpawnableSO>();
			SpawnableSettings val = Resources.Load<SpawnableSettings>("SpawnableSettings");
			if (val?.spawnables == null)
			{
				return dictionary;
			}
			foreach (SpawnableSO spawnable in val.spawnables)
			{
				if ((Object)(object)spawnable != (Object)null && (Object)(object)spawnable.prefab != (Object)null && !dictionary.ContainsKey(spawnable.prefab))
				{
					dictionary[spawnable.prefab] = spawnable;
				}
			}
			return dictionary;
		}

		private unsafe static GameObject? PickEnabledAlternative(MMLootTableGameObjectSO lootTable, Vector3 stampPosition, GameObject excluded)
		{
			Dictionary<GameObject, SpawnableSO> dictionary = BuildVanillaLookup();
			List<GameObject> list = new List<GameObject>();
			foreach (MMLootGameObject item in ((MMLootTable<MMLootGameObject, GameObject>)(object)lootTable.LootTable).ObjectsToLoot)
			{
				if ((Object)(object)((MMLoot<GameObject>)(object)item)?.Loot == (Object)null || (Object)(object)((MMLoot<GameObject>)(object)item).Loot == (Object)(object)excluded)
				{
					continue;
				}
				if (!dictionary.TryGetValue(((MMLoot<GameObject>)(object)item).Loot, out var value))
				{
					list.Add(((MMLoot<GameObject>)(object)item).Loot);
					continue;
				}
				if (ItemEnabledState.IsEnabled(ShopCatalog.KeyForVanilla(value.spawnableID)))
				{
					list.Add(((MMLoot<GameObject>)(object)item).Loot);
					continue;
				}
				(string, string, GameObject, bool) tuple = TryConnectInternals.GetReplacements(((MMLoot<GameObject>)(object)item).Loot).FirstOrDefault<(string, string, GameObject, bool)>(((string OwnerGuid, string Key, GameObject MarkerPrefab, bool IsEnabled) r) => r.IsEnabled);
				if ((Object)(object)tuple.Item3 != (Object)null)
				{
					list.Add(tuple.Item3);
				}
			}
			if (list.Count == 0)
			{
				return null;
			}
			SeededRandomManager val = Object.FindFirstObjectByType<SeededRandomManager>();
			GameManager val2 = Object.FindFirstObjectByType<GameManager>();
			int num = (((Object)(object)val != (Object)null) ? val.CurrentSeed : 0);
			int num2 = (((Object)(object)val2 != (Object)null) ? val2.successfulQuota : 0);
			Random random = new Random((((object)(*(Vector3*)(&stampPosition))/*cast due to .constrained prefix*/).GetHashCode() * 397) ^ (num * 31 + num2));
			return list[random.Next(list.Count)];
		}
	}
}
namespace MoreUpgrades.Menu
{
	internal static class ItemEnabledState
	{
		private const string ConfigSection = "ShopItems";

		private const string ConfigDescription = "Whether this shop item can appear in the shop. Set via the in-game settings menu.";

		private static readonly ConcurrentDictionary<string, ConfigEntry<bool>> Entries = new ConcurrentDictionary<string, ConfigEntry<bool>>();

		public static bool IsEnabled(string catalogToggleKey)
		{
			return GetEntry(catalogToggleKey).Value;
		}

		public static void SetEnabled(string catalogToggleKey, bool isEnabled)
		{
			GetEntry(catalogToggleKey).Value = isEnabled;
		}

		public static bool HasSavedValue(string catalogToggleKey)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if (Entries.ContainsKey(catalogToggleKey))
			{
				return true;
			}
			return PluginMain.ConfigFile.ContainsKey(new ConfigDefinition("ShopItems", SanitizeConfigKey(catalogToggleKey)));
		}

		private static ConfigEntry<bool> GetEntry(string catalogToggleKey)
		{
			return Entries.GetOrAdd(catalogToggleKey, (Func<string, ConfigEntry<bool>>)((string key) => PluginMain.ConfigFile.Bind<bool>("ShopItems", SanitizeConfigKey(key), true, "Whether this shop item can appear in the shop. Set via the in-game settings menu.")));
		}

		private static string SanitizeConfigKey(string key)
		{
			return key.Replace('=', '_');
		}
	}
	internal static class ItemToggleMenu
	{
		private const string HeaderKey = "moreupgrades.section";

		private const string StatusKey = "moreupgrades.status";

		private const string ToggleKeyPrefix = "moreupgrades.toggle.";

		private const string NoDescriptionFallback = "No description available.";

		private static readonly HashSet<string> DefaultDisabledCatalogKeys = new HashSet<string> { ShopCatalog.KeyForMod("com.Try-4646.TryConnect", "ticket_fizz") };

		private static readonly Dictionary<string, string> DescriptionsBySettingKey = new Dictionary<string, string>();

		private static string StatusLabel
		{
			get
			{
				if (!PluginMain.PersistentUpgradesPresent)
				{
					return "\"PersistentUpgrades\" not installed — upgrades from \"MoreUpgrades\" reset each day.";
				}
				return "\"PersistentUpgrades\" detected — upgrades from \"MoreUpgrades\" are permanent and lobby-shared.";
			}
		}

		public static string SettingKeyFor(string catalogToggleKey)
		{
			return "moreupgrades.toggle." + catalogToggleKey;
		}

		public static bool IsShopToggleKey(string? key)
		{
			return key?.StartsWith("moreupgrades.toggle.") ?? false;
		}

		public static string CatalogKeyFromSettingKey(string settingKey)
		{
			return settingKey.Substring("moreupgrades.toggle.".Length);
		}

		public static string DescriptionForSettingKey(string settingKey)
		{
			if (!DescriptionsBySettingKey.TryGetValue(settingKey, out string value))
			{
				return "No description available.";
			}
			return value;
		}

		public static bool EnsureInjected(SettingsLayout layout, string source)
		{
			if ((Object)(object)layout == (Object)null || layout.tabs == null || layout.tabs.Count == 0)
			{
				return false;
			}
			Tab val = FindTargetTab(layout);
			if (val == null)
			{
				return false;
			}
			Tab val2 = val;
			if (val2.entries == null)
			{
				val2.entries = new List<SettingItemBase>();
			}
			int num = 0;
			num += EnsureTitleEntry(val.entries, "moreupgrades.section", "\"MoreUpgrades\" — Shop Items");
			num += EnsureTitleEntry(val.entries, "moreupgrades.status", StatusLabel);
			RefreshStatusLabel(val.entries);
			foreach (ShopCatalogEntry item in ShopCatalog.GetAll())
			{
				string key = SettingKeyFor(item.ToggleKey);
				DescriptionsBySettingKey[key] = (string.IsNullOrWhiteSpace(item.Description) ? "No description available." : item.Description);
				if (!ItemEnabledState.HasSavedValue(item.ToggleKey) && DefaultDisabledCatalogKeys.Contains(item.ToggleKey))
				{
					ItemEnabledState.SetEnabled(item.ToggleKey, isEnabled: false);
				}
				bool defaultEnabled = ItemEnabledState.IsEnabled(item.ToggleKey);
				bool flag = EnsureToggleEntry(val.entries, key, item.DisplayName, defaultEnabled) > 0;
				num += (flag ? 1 : 0);
			}
			if (num > 0)
			{
				PluginMain.Log.LogInfo((object)$"Injected {num} MoreUpgrades settings entries from {source}. Tab='{val.tabName}'.");
			}
			return true;
		}

		private static Tab? FindTargetTab(SettingsLayout layout)
		{
			foreach (Tab tab in layout.tabs)
			{
				if (tab.entries != null && tab.entries.Any(IsLobbyModeEntry))
				{
					return tab;
				}
			}
			foreach (Tab tab2 in layout.tabs)
			{
				if (tab2.entries != null && tab2.entries.Count != 0 && !string.IsNullOrWhiteSpace(tab2.tabName) && string.Equals(tab2.tabName.Trim(), "Settings", StringComparison.OrdinalIgnoreCase))
				{
					return tab2;
				}
			}
			return null;
		}

		private static bool IsLobbyModeEntry(SettingItemBase entry)
		{
			if (!(entry is DropdownSettingItem) || entry.key == "moreupgrades.section")
			{
				return false;
			}
			return string.Equals(entry.label?.Trim(), "Lobby Mode", StringComparison.OrdinalIgnoreCase);
		}

		private static void RefreshStatusLabel(ICollection<SettingItemBase> entries)
		{
			TitleSettingItem val = entries.OfType<TitleSettingItem>().FirstOrDefault((Func<TitleSettingItem, bool>)((TitleSettingItem entry) => ((SettingItemBase)entry).key == "moreupgrades.status"));
			if ((Object)(object)val != (Object)null)
			{
				((SettingItemBase)val).label = StatusLabel;
			}
		}

		private static int EnsureTitleEntry(ICollection<SettingItemBase> entries, string key, string label)
		{
			if (entries.Any((SettingItemBase entry) => entry.key == key))
			{
				return 0;
			}
			TitleSettingItem val = ScriptableObject.CreateInstance<TitleSettingItem>();
			((Object)val).hideFlags = (HideFlags)61;
			((SettingItemBase)val).key = key;
			((SettingItemBase)val).label = label;
			entries.Add((SettingItemBase)(object)val);
			return 1;
		}

		private static int EnsureToggleEntry(ICollection<SettingItemBase> entries, string key, string label, bool defaultEnabled)
		{
			if (entries.Any((SettingItemBase entry) => entry.key == key))
			{
				return 0;
			}
			ToggleSettingItem val = ScriptableObject.CreateInstance<ToggleSettingItem>();
			((Object)val).hideFlags = (HideFlags)61;
			((SettingItemBase)val).key = key;
			((SettingItemBase)val).label = label;
			val.value = defaultEnabled;
			val.defaultValue = defaultEnabled;
			val.loadOnSceneStart = false;
			entries.Add((SettingItemBase)(object)val);
			return 1;
		}
	}
	internal static class SettingsTooltip
	{
		private const float MaxWidth = 420f;

		private const float Padding = 10f;

		private const float CursorOffset = 36f;

		private static Canvas? _canvas;

		private static RectTransform? _root;

		private static TextMeshProUGUI? _text;

		public static void Show(string message, TMP_FontAsset? fontToMatch, Vector2 screenPosition)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			EnsureBuilt(fontToMatch);
			if (!((Object)(object)_text == (Object)null) && !((Object)(object)_root == (Object)null))
			{
				((TMP_Text)_text).text = message;
				((Component)_root).gameObject.SetActive(true);
				SetPosition(screenPosition);
			}
		}

		public static void Hide()
		{
			if ((Object)(object)_root != (Object)null)
			{
				((Component)_root).gameObject.SetActive(false);
			}
		}

		public static void SetPosition(Vector2 screenPosition)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_root == (Object)null) && ((Component)_root).gameObject.activeSelf)
			{
				((Transform)_root).position = new Vector3(screenPosition.x + 36f, screenPosition.y + 36f, 0f);
			}
		}

		private static void EnsureBuilt(TMP_FontAsset? fontToMatch)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root != (Object)null)
			{
				if ((Object)(object)fontToMatch != (Object)null && (Object)(object)_text != (Object)null)
				{
					((TMP_Text)_text).font = fontToMatch;
				}
				return;
			}
			GameObject val = new GameObject("MoreUpgrades_TooltipCanvas");
			Object.DontDestroyOnLoad((Object)(object)val);
			_canvas = val.AddComponent<Canvas>();
			_canvas.renderMode = (RenderMode)0;
			_canvas.sortingOrder = 32767;
			val.AddComponent<CanvasScaler>();
			((Behaviour)val.AddComponent<GraphicRaycaster>()).enabled = false;
			GameObject val2 = new GameObject("MoreUpgrades_Tooltip", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val2.transform.SetParent(val.transform, false);
			_root = (RectTransform)val2.transform;
			_root.pivot = new Vector2(0f, 1f);
			_root.sizeDelta = new Vector2(420f, 40f);
			Image component = val2.GetComponent<Image>();
			((Graphic)component).color = new Color(0.05f, 0.05f, 0.06f, 0.95f);
			((Graphic)component).raycastTarget = false;
			GameObject val3 = new GameObject("Text", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			val3.transform.SetParent(val2.transform, false);
			RectTransform val4 = (RectTransform)val3.transform;
			val4.anchorMin = Vector2.zero;
			val4.anchorMax = Vector2.one;
			val4.offsetMin = new Vector2(10f, 10f);
			val4.offsetMax = new Vector2(-10f, -10f);
			_text = val3.GetComponent<TextMeshProUGUI>();
			((TMP_Text)_text).fontSize = 22f;
			((Graphic)_text).color = Color.white;
			((TMP_Text)_text).textWrappingMode = (TextWrappingModes)1;
			((Graphic)_text).raycastTarget = false;
			if ((Object)(object)fontToMatch != (Object)null)
			{
				((TMP_Text)_text).font = fontToMatch;
			}
			ContentSizeFitter obj = val2.AddComponent<ContentSizeFitter>();
			obj.horizontalFit = (FitMode)0;
			obj.verticalFit = (FitMode)2;
			((Component)_text).GetComponent<RectTransform>().sizeDelta = new Vector2(400f, 0f);
			val2.SetActive(false);
		}
	}
	internal sealed class SettingsTooltipTrigger : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerMoveHandler, IPointerExitHandler
	{
		public string? Description { get; set; }

		private void Awake()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Graphic componentInChildren = ((Component)this).GetComponentInChildren<Graphic>(true);
			if (componentInChildren == null || !componentInChildren.raycastTarget)
			{
				((Graphic)((Component)this).gameObject.AddComponent<Image>()).color = Color.clear;
			}
		}

		public void OnPointerEnter(PointerEventData eventData)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrWhiteSpace(Description))
			{
				TMP_Text componentInChildren = ((Component)this).GetComponentInChildren<TMP_Text>(true);
				TMP_FontAsset fontToMatch = ((componentInChildren != null) ? componentInChildren.font : null);
				SettingsTooltip.Show(Description, fontToMatch, eventData.position);
			}
		}

		public void OnPointerMove(PointerEventData eventData)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			SettingsTooltip.SetPosition(eventData.position);
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			SettingsTooltip.Hide();
		}

		private void OnDisable()
		{
			SettingsTooltip.Hide();
		}
	}
	internal readonly struct ShopCatalogEntry
	{
		public readonly string ToggleKey;

		public readonly string DisplayName;

		public readonly string Description;

		public readonly SpawnableSO Spawnable;

		public readonly bool IsVanilla;

		public ShopCatalogEntry(string toggleKey, string displayName, string description, SpawnableSO spawnable, bool isVanilla)
		{
			ToggleKey = toggleKey;
			DisplayName = displayName;
			Description = description;
			Spawnable = spawnable;
			IsVanilla = isVanilla;
		}
	}
	internal static class ShopCatalog
	{
		private const string VanillaKeyPrefix = "vanilla.";

		private const string ModKeyPrefix = "mod.";

		public static string KeyForVanilla(int spawnableId)
		{
			return "vanilla." + spawnableId;
		}

		public static string KeyForMod(string ownerGuid, string itemKey)
		{
			return "mod." + ownerGuid + ":" + itemKey;
		}

		public static bool IsVanillaKey(string toggleKey)
		{
			return toggleKey.StartsWith("vanilla.");
		}

		public static bool TryParseVanillaSpawnableId(string toggleKey, out int spawnableId)
		{
			if (IsVanillaKey(toggleKey) && int.TryParse(toggleKey.Substring("vanilla.".Length), out spawnableId))
			{
				return true;
			}
			spawnableId = 0;
			return false;
		}

		public static IReadOnlyList<ShopCatalogEntry> GetAll()
		{
			List<ShopCatalogEntry> list = new List<ShopCatalogEntry>();
			HashSet<int> hashSet = new HashSet<int>();
			ItemDescriptionSettings descriptionSettings = Resources.Load<ItemDescriptionSettings>("ItemDescriptionSettings");
			TryConnectRegisteredItemInfo[] registeredItems = TryConnectApi.GetRegisteredItems();
			foreach (TryConnectRegisteredItemInfo val in registeredItems)
			{
				if (val.IsRegistered && !((Object)(object)val.Spawnable == (Object)null))
				{
					hashSet.Add(val.SpawnableId);
					string description = ResolveDescription(descriptionSettings, val.Spawnable, val.Description);
					list.Add(new ShopCatalogEntry(KeyForMod(val.OwnerGuid, val.Key), val.DisplayName, description, val.Spawnable, isVanilla: false));
				}
			}
			SpawnableSettings val2 = Resources.Load<SpawnableSettings>("SpawnableSettings");
			if (val2?.spawnables != null)
			{
				foreach (SpawnableSO spawnable in val2.spawnables)
				{
					if (!((Object)(object)spawnable == (Object)null) && !((Object)(object)spawnable.prefab == (Object)null) && !hashSet.Contains(spawnable.spawnableID) && !((Object)(object)spawnable.prefab.GetComponent<Item>() == (Object)null))
					{
						hashSet.Add(spawnable.spawnableID);
						string displayName = (string.IsNullOrWhiteSpace(spawnable.spawnableName) ? ((Object)spawnable.prefab).name : spawnable.spawnableName);
						string description2 = ResolveDescription(descriptionSettings, spawnable, spawnable.spawnableDescription);
						list.Add(new ShopCatalogEntry(KeyForVanilla(spawnable.spawnableID), displayName, description2, spawnable, isVanilla: true));
					}
				}
			}
			return list.OrderBy((ShopCatalogEntry e) => e.DisplayName).ToList();
		}

		private static string ResolveDescription(ItemDescriptionSettings? descriptionSettings, SpawnableSO spawnable, string fallback)
		{
			string text = (((Object)(object)descriptionSettings != (Object)null) ? descriptionSettings.GetDescription(spawnable) : null);
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			return fallback;
		}
	}
	internal static class TryConnectInternals
	{
		private static readonly Type? RuntimeItemRegistryType = FindType("TryConnect.RuntimeItemRegistry");

		private static readonly FieldInfo? DefinitionsByBasePrefabField = RuntimeItemRegistryType?.GetField("DefinitionsByBasePrefab", BindingFlags.Static | BindingFlags.NonPublic);

		private static readonly Type? CustomItemDefinitionType = RuntimeItemRegistryType?.GetNestedType("CustomItemDefinition", BindingFlags.NonPublic);

		private static readonly FieldInfo? OwnerGuidField = CustomItemDefinitionType?.GetField("OwnerGuid", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo? KeyField = CustomItemDefinitionType?.GetField("Key", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo? MarkerPrefabField = CustomItemDefinitionType?.GetField("MarkerPrefab", BindingFlags.Instance | BindingFlags.NonPublic);

		private static Type? FindType(string fullName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType(fullName);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}

		public static IReadOnlyList<(string OwnerGuid, string Key, GameObject MarkerPrefab, bool IsEnabled)> GetReplacements(GameObject basePrefab)
		{
			try
			{
				if (DefinitionsByBasePrefabField == null || OwnerGuidField == null || KeyField == null || MarkerPrefabField == null)
				{
					return Array.Empty<(string, string, GameObject, bool)>();
				}
				if (!(DefinitionsByBasePrefabField.GetValue(null) is IDictionary dictionary) || !dictionary.Contains(basePrefab) || !(dictionary[basePrefab] is IEnumerable enumerable))
				{
					return Array.Empty<(string, string, GameObject, bool)>();
				}
				List<(string, string, GameObject, bool)> list = new List<(string, string, GameObject, bool)>();
				foreach (object item2 in enumerable)
				{
					string text = OwnerGuidField.GetValue(item2) as string;
					string text2 = KeyField.GetValue(item2) as string;
					object? value = MarkerPrefabField.GetValue(item2);
					GameObject val = (GameObject)((value is GameObject) ? value : null);
					if (text != null && text2 != null && !((Object)(object)val == (Object)null))
					{
						bool item = ItemEnabledState.IsEnabled(ShopCatalog.KeyForMod(text, text2));
						list.Add((text, text2, val, item));
					}
				}
				return list;
			}
			catch (Exception ex)
			{
				PluginMain.Log.LogWarning((object)("TryConnectInternals.GetReplacements: reflection into TryConnect internals failed: " + ex.Message));
				return Array.Empty<(string, string, GameObject, bool)>();
			}
		}

		public static bool HasEnabledReplacement(GameObject basePrefab)
		{
			return GetReplacements(basePrefab).Any<(string, string, GameObject, bool)>(((string OwnerGuid, string Key, GameObject MarkerPrefab, bool IsEnabled) r) => r.IsEnabled);
		}
	}
	internal static class UpgradeHudSync
	{
		private static readonly Dictionary<GamePlayerUpgradeType, UpgradeEntryUI> Entries = new Dictionary<GamePlayerUpgradeType, UpgradeEntryUI>();

		private static readonly Dictionary<GamePlayerUpgradeType, float> LastKnownTotals = new Dictionary<GamePlayerUpgradeType, float>();

		private static Transform? _lastEntryParent;

		private static readonly Dictionary<GamePlayerUpgradeType, (string Label, string Description)> Display = new Dictionary<GamePlayerUpgradeType, (string, string)>
		{
			[GamePlayerUpgradeType.SlotsLuck] = ("Slots Luck", "Boosts winnings at Slots"),
			[GamePlayerUpgradeType.RouletteLuck] = ("Roulette Reader", "Boosts winnings at Roulette"),
			[GamePlayerUpgradeType.WheelLuck] = ("Wheel Whisperer", "Boosts winnings at Money Wheel and Wheel of Fortune"),
			[GamePlayerUpgradeType.BlackjackLuck] = ("Card Counter", "Boosts winnings at Blackjack"),
			[GamePlayerUpgradeType.PokerLuck] = ("Poker Face", "Boosts winnings at Poker"),
			[GamePlayerUpgradeType.BaccaratLuck] = ("Baccarat Instinct", "Boosts winnings at Baccarat"),
			[GamePlayerUpgradeType.CrapsLuck] = ("Loaded Dice", "Boosts winnings at Craps"),
			[GamePlayerUpgradeType.MinesweeperLuck] = ("Steady Hands", "Boosts winnings at Minesweeper and Dragon Tower"),
			[GamePlayerUpgradeType.CrashLuck] = ("Crash Sense", "Boosts winnings at Crash"),
			[GamePlayerUpgradeType.PlinkoLuck] = ("Plinko Precision", "Boosts winnings at Plinko"),
			[GamePlayerUpgradeType.KenoLuck] = ("Keno Clairvoyance", "Boosts winnings at Keno"),
			[GamePlayerUpgradeType.HiLoLuck] = ("Hi-Lo Hunch", "Boosts winnings at Hi-Lo"),
			[GamePlayerUpgradeType.DuckRaceLuck] = ("Duck Whisperer", "Boosts winnings at Duck Race"),
			[GamePlayerUpgradeType.CrossyRoadLuck] = ("Crossy Confidence", "Boosts winnings at Crossy Road"),
			[GamePlayerUpgradeType.CoinFlipLuck] = ("Coin Sense", "Boosts winnings at Coin Flip"),
			[GamePlayerUpgradeType.ExtraShopItems] = ("Shop Scout", "Adds extra items to the shop")
		};

		public static void OnUpgradeChanged(ulong steamId, GamePlayerUpgradeType type, float newTotal)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (SteamUser.GetSteamID().m_SteamID != steamId)
			{
				return;
			}
			if (newTotal <= 0f)
			{
				LastKnownTotals.Remove(type);
			}
			else
			{
				LastKnownTotals[type] = newTotal;
			}
			UpgradeUI instance = MonoSingleton<UpgradeUI>.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Transform val = UpgradeUiAccess.EntryParent(instance);
			UpgradeEntryUI val2 = UpgradeUiAccess.EntryTemplate(instance);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return;
			}
			if (_lastEntryParent != val)
			{
				Entries.Clear();
				_lastEntryParent = val;
				foreach (var (gamePlayerUpgradeType2, newTotal2) in LastKnownTotals)
				{
					if (gamePlayerUpgradeType2 != type)
					{
						Draw(val, val2, gamePlayerUpgradeType2, newTotal2);
					}
				}
			}
			if (newTotal <= 0f)
			{
				if (Entries.TryGetValue(type, out UpgradeEntryUI value) && (Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
				Entries.Remove(type);
			}
			else
			{
				Draw(val, val2, type, newTotal);
			}
		}

		private static void Draw(Transform parent, UpgradeEntryUI template, GamePlayerUpgradeType type, float newTotal)
		{
			if (Display.TryGetValue(type, out (string, string) value))
			{
				if (!Entries.TryGetValue(type, out UpgradeEntryUI value2) || (Object)(object)value2 == (Object)null)
				{
					value2 = Object.Instantiate<UpgradeEntryUI>(template, parent);
					Entries[type] = value2;
				}
				string formattedValue = ((type == GamePlayerUpgradeType.ExtraShopItems) ? $"+{newTotal:0.#}" : ((newTotal * 100f).ToString("0.#") + "%"));
				UpgradeEntryUiText.Set(value2, value.Item1, value.Item2, formattedValue);
			}
		}

		public static void Clear()
		{
			foreach (UpgradeEntryUI value in Entries.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
			}
			Entries.Clear();
			LastKnownTotals.Clear();
		}
	}
	internal static class UpgradeUiAccess
	{
		private static readonly FieldRef<UpgradeUI, Transform> EntryParentField = AccessTools.FieldRefAccess<UpgradeUI, Transform>("entryParent");

		private static readonly FieldRef<UpgradeUI, UpgradeEntryUI> EntryTemplateField = AccessTools.FieldRefAccess<UpgradeUI, UpgradeEntryUI>("upgradeEntryUI");

		public static Transform EntryParent(UpgradeUI ui)
		{
			return UpgradeHudScroll.EnsureScrollable(EntryParentField.Invoke(ui));
		}

		public static UpgradeEntryUI EntryTemplate(UpgradeUI ui)
		{
			return EntryTemplateField.Invoke(ui);
		}
	}
	internal static class UpgradeHudScroll
	{
		private const float VisibleHeight = 548.4f;

		private const float ScrollbarWidth = 12f;

		private static Transform? _wrappedSource;

		private static Transform? _scrollableParent;

		public static Transform EnsureScrollable(Transform entryParent)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Expected O, but got Unknown
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Expected O, but got Unknown
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Expected O, but got Unknown
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_wrappedSource == (Object)(object)entryParent && (Object)(object)_scrollableParent != (Object)null)
			{
				return _scrollableParent;
			}
			Transform parent = entryParent.parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			Transform val2 = ((val != null) ? ((Transform)val).parent : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return entryParent;
			}
			int siblingIndex = ((Transform)val).GetSiblingIndex();
			float x = val.sizeDelta.x;
			GameObject val3 = new GameObject("MoreUpgrades_UpgradeScrollViewport", new Type[1] { typeof(RectTransform) });
			RectTransform val4 = (RectTransform)val3.transform;
			((Transform)val4).SetParent(val2, false);
			((Transform)val4).SetSiblingIndex(siblingIndex);
			val4.anchorMin = val.anchorMin;
			val4.anchorMax = val.anchorMax;
			val4.pivot = val.pivot;
			val4.anchoredPosition = val.anchoredPosition;
			val4.sizeDelta = new Vector2(x + 4f + 12f, 548.4f);
			GameObject val5 = new GameObject("MoreUpgrades_UpgradeScrollMask", new Type[3]
			{
				typeof(RectTransform),
				typeof(RectMask2D),
				typeof(Image)
			});
			RectTransform val6 = (RectTransform)val5.transform;
			((Transform)val6).SetParent((Transform)(object)val4, false);
			val6.anchorMin = new Vector2(0f, 0f);
			val6.anchorMax = new Vector2(0f, 1f);
			val6.pivot = new Vector2(0f, 1f);
			val6.anchoredPosition = Vector2.zero;
			val6.sizeDelta = new Vector2(x, 0f);
			Image component = val5.GetComponent<Image>();
			((Graphic)component).color = new Color(0f, 0f, 0f, 0f);
			((Graphic)component).raycastTarget = true;
			((Transform)val).SetParent((Transform)(object)val6, false);
			val.anchorMin = new Vector2(0f, 1f);
			val.anchorMax = new Vector2(0f, 1f);
			val.pivot = new Vector2(0f, 1f);
			val.anchoredPosition = Vector2.zero;
			GameObject val7 = new GameObject("MoreUpgrades_UpgradeScrollbar", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Scrollbar)
			});
			RectTransform val8 = (RectTransform)val7.transform;
			((Transform)val8).SetParent((Transform)(object)val4, false);
			val8.anchorMin = new Vector2(1f, 0f);
			val8.anchorMax = new Vector2(1f, 1f);
			val8.pivot = new Vector2(1f, 1f);
			val8.sizeDelta = new Vector2(12f, 0f);
			val8.anchoredPosition = Vector2.zero;
			((Graphic)val7.GetComponent<Image>()).color = new Color(1f, 1f, 1f, 0.15f);
			GameObject val9 = new GameObject("Handle", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val10 = (RectTransform)val9.transform;
			((Transform)val10).SetParent((Transform)(object)val8, false);
			val10.anchorMin = Vector2.zero;
			val10.anchorMax = Vector2.one;
			val10.sizeDelta = Vector2.zero;
			Image component2 = val9.GetComponent<Image>();
			((Graphic)component2).color = new Color(1f, 1f, 1f, 0.6f);
			Scrollbar component3 = val7.GetComponent<Scrollbar>();
			component3.direction = (Direction)2;
			((Selectable)component3).targetGraphic = (Graphic)(object)component2;
			component3.handleRect = val10;
			ScrollRect val11 = val3.AddComponent<ScrollRect>();
			val11.content = val;
			val11.viewport = val6;
			val11.horizontal = false;
			val11.vertical = true;
			val11.verticalScrollbar = component3;
			val11.verticalScrollbarVisibility = (ScrollbarVisibility)1;
			val11.movementType = (MovementType)2;
			val11.scrollSensitivity = 20f;
			val3.AddComponent<UpgradeHudWheelScroll>().Target = val11;
			_wrappedSource = entryParent;
			_scrollableParent = entryParent;
			return entryParent;
		}
	}
	internal sealed class UpgradeHudWheelScroll : MonoBehaviour
	{
		private const float PixelsPerRawUnit = 64.05f;

		public ScrollRect? Target;

		private void Update()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Target == (Object)null || !((Component)Target.content).gameObject.activeInHierarchy)
			{
				return;
			}
			Mouse current = Mouse.current;
			float num = ((current != null) ? ((InputControl<float>)(object)((Vector2Control)current.scroll).y).ReadValue() : 0f);
			if (num != 0f)
			{
				Rect rect = Target.content.rect;
				float height = ((Rect)(ref rect)).height;
				rect = Target.viewport.rect;
				float num2 = height - ((Rect)(ref rect)).height;
				if (!(num2 <= 0f))
				{
					float num3 = num * 64.05f;
					Target.verticalNormalizedPosition = Mathf.Clamp01(Target.verticalNormalizedPosition + num3 / num2);
				}
			}
		}
	}
	internal static class UpgradeEntryUiText
	{
		private static readonly FieldRef<UpgradeEntryUI, TextMeshProUGUI> LabelField = AccessTools.FieldRefAccess<UpgradeEntryUI, TextMeshProUGUI>("labelText");

		private static readonly FieldRef<UpgradeEntryUI, TextMeshProUGUI> DescriptionField = AccessTools.FieldRefAccess<UpgradeEntryUI, TextMeshProUGUI>("descriptionText");

		private static readonly FieldRef<UpgradeEntryUI, TextMeshProUGUI> ValueField = AccessTools.FieldRefAccess<UpgradeEntryUI, TextMeshProUGUI>("valueText");

		public static void Set(UpgradeEntryUI entry, string label, string description, string formattedValue)
		{
			TextMeshProUGUI val = LabelField.Invoke(entry);
			if ((Object)(object)val != (Object)null)
			{
				((TMP_Text)val).text = label;
			}
			TextMeshProUGUI val2 = DescriptionField.Invoke(entry);
			if ((Object)(object)val2 != (Object)null)
			{
				((TMP_Text)val2).text = description;
			}
			TextMeshProUGUI val3 = ValueField.Invoke(entry);
			if ((Object)(object)val3 != (Object)null)
			{
				((TMP_Text)val3).text = formattedValue;
			}
		}
	}
}