Decompiled source of UpgradeEveryRoundUpdated v3.0.0

plugins/UpgradeEveryRound.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using MenuLib;
using MenuLib.MonoBehaviors;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using REPOLib.Modules;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("UpgradeEveryRound")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.0.3")]
[assembly: AssemblyInformationalVersion("2.0.3+5afcb5a3443f338f580af04e2dbfb911a7c75e80")]
[assembly: AssemblyProduct("Upgrade Every Round")]
[assembly: AssemblyTitle("UpgradeEveryRound")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.3.0")]
[module: UnverifiableCode]
[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 UpgradeEveryRound
{
	[HarmonyPatch(typeof(StatsUI), "Update")]
	public static class StatsUIPatch
	{
		private static void Prefix(ref float ___showStatsTimer)
		{
			if (UpgradeMenu.isOpen)
			{
				___showStatsTimer = 5f;
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager))]
	[HarmonyPatch("Start")]
	public static class StatsManagerStartPatch
	{
		private static void Prefix(StatsManager __instance)
		{
			UpgradeUsageData.Initialize(__instance);
		}

		private static void Postfix(StatsManager __instance)
		{
			ModUpgradeHandler.BuildExtraUpgradeList();
		}
	}
	[HarmonyPatch(typeof(StatsManager), "LoadGame")]
	public static class StatsManagerLoadGamePatch
	{
		private static void Postfix(StatsManager __instance)
		{
			UpgradeUsageData.Initialize(__instance);
		}
	}
	[HarmonyPatch(typeof(RunManager))]
	[HarmonyPatch("LeaveToMainMenu")]
	public static class RunManagerMainMenuPatch
	{
		private static void Prefix()
		{
			UpgradeMenu.isOpen = false;
			Plugin.remoteNetworkData = null;
		}
	}
	internal static class ModUpgradeHandler
	{
		private static bool initialized = false;

		public static Dictionary<int, ConfigEntry<bool>> AllowExtras = new Dictionary<int, ConfigEntry<bool>>();

		public static Dictionary<int, string> ExtraLabels = new Dictionary<int, string>();

		public static Dictionary<int, string> ExtraKeys = new Dictionary<int, string>();

		public static Dictionary<string, GameObject> ExtraUpgrades = new Dictionary<string, GameObject>();

		public static Dictionary<string, string> ExtraUpgradeIds = new Dictionary<string, string>();

		public static Dictionary<string, GameObject> ExtraUpgradePrefabs = new Dictionary<string, GameObject>();

		internal static bool DoUpgrade(string upgradeKey, string _steamID)
		{
			if (ExtraUpgradeIds.TryGetValue(upgradeKey, out var value))
			{
				PlayerUpgrade upgrade = Upgrades.GetUpgrade(value);
				if (upgrade == null)
				{
					Plugin.Logger.LogError((object)("Registered upgrade '" + value + "' is no longer available."));
					return false;
				}
				upgrade.AddLevel(_steamID, 1);
				return true;
			}
			if (!ExtraUpgradePrefabs.TryGetValue(upgradeKey, out var value2) || (Object)(object)value2 == (Object)null)
			{
				Plugin.Logger.LogError((object)("No registered upgrade ID or item prefab found for key '" + upgradeKey + "'."));
				return false;
			}
			GameObject val = Object.Instantiate<GameObject>(value2);
			MonoBehaviour[] components = val.GetComponents<MonoBehaviour>();
			for (int i = 0; i < components.Length; i++)
			{
				Traverse val2 = Traverse.Create((object)components[i]).Method("Start", Array.Empty<Type>(), (object[])null);
				if (val2.MethodExists())
				{
					val2.GetValue(Array.Empty<object>());
				}
			}
			ItemToggle component = val.GetComponent<ItemToggle>();
			ItemUpgrade component2 = val.GetComponent<ItemUpgrade>();
			Traverse.Create((object)component).Field<int>("playerTogglePhotonID").Value = SemiFunc.PlayerGetFromSteamID(_steamID).photonView.ViewID;
			Traverse obj = Traverse.Create((object)component2);
			obj.Field<PhysGrabObjectImpactDetector>("impactDetector").Value.destroyDisable = true;
			obj.Method("PlayerUpgrade", Array.Empty<Type>(), (object[])null).GetValue(Array.Empty<object>());
			Object.Destroy((Object)(object)val);
			return true;
		}

		public static void BuildExtraUpgradeList()
		{
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Expected O, but got Unknown
			if (initialized)
			{
				return;
			}
			Plugin.Logger.LogMessage((object)"Building extra upgrades list");
			int num = 0;
			Regex regex = new Regex("(?<!^)(?=[A-Z])");
			AllowExtras.Clear();
			ExtraLabels.Clear();
			ExtraKeys.Clear();
			ExtraUpgrades.Clear();
			ExtraUpgradeIds.Clear();
			ExtraUpgradePrefabs.Clear();
			foreach (PlayerUpgrade item in Upgrades.PlayerUpgrades.OrderBy<PlayerUpgrade, string>((PlayerUpgrade x) => x.UpgradeId, StringComparer.Ordinal))
			{
				string text = string.Join(" ", regex.Split(item.UpgradeId));
				ConfigEntry<bool> val = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Enabled upgrades", "Enable " + text, true, new ConfigDescription("Allows " + text + " Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
				AllowExtras.Add(num, val);
				ExtraLabels.Add(num, text);
				string text2 = "upgrade:" + item.UpgradeId;
				ExtraKeys.Add(num, text2);
				ExtraUpgrades.Add(text, null);
				ExtraUpgradeIds.Add(text2, item.UpgradeId);
				BindExtraConfig(val);
				num++;
			}
			string[] source = new string[12]
			{
				"Map Player Count", "Stamina", "Extra Jump", "Range", "Strength", "Health", "Sprint Speed", "Tumble Launch", "Tumble Climb", "Death Head Battery",
				"Tumble Wings", "Crouch Rest"
			};
			string[] source2 = new string[1] { "Throw Strength" };
			foreach (Item item2 in Items.AllItems.Where((Item x) => (int)x.itemType == 3).OrderBy<Item, string>((Item x) => x.itemName, StringComparer.Ordinal).ThenBy<Item, string>((Item x) => ((Object)x).name, StringComparer.Ordinal))
			{
				string itemName = item2.itemName;
				string text3 = itemName.Substring(0, itemName.Length - 8).Trim();
				if (!ExtraUpgrades.ContainsKey(text3) && !source.Contains(text3) && !source2.Contains(text3))
				{
					GameObject prefab = ((PrefabRef<GameObject>)(object)item2.prefab).Prefab;
					if ((Object)(object)prefab == (Object)null)
					{
						Plugin.Logger.LogWarning((object)("Ignoring item upgrade '" + item2.itemName + "' because it has no prefab."));
						continue;
					}
					ConfigEntry<bool> val2 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Enabled upgrades", "Enable " + text3, true, new ConfigDescription("Allows " + text3 + " Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
					AllowExtras.Add(num, val2);
					ExtraLabels.Add(num, text3);
					string text4 = "item:" + ((Object)item2).name;
					ExtraKeys.Add(num, text4);
					ExtraUpgrades.Add(text3, prefab);
					ExtraUpgradePrefabs.Add(text4, prefab);
					BindExtraConfig(val2);
					num++;
				}
			}
			Plugin.ConfigUpdated(null, EventArgs.Empty);
			initialized = true;
		}

		private static void BindExtraConfig(ConfigEntry<bool> allowCustomUpgrade)
		{
			allowCustomUpgrade.SettingChanged += Plugin.ConfigUpdated;
		}

		public static bool AllowCustomUpgradeByIndex(int configIndex)
		{
			NetworkData currentNetworkData = Plugin.CurrentNetworkData;
			if (currentNetworkData?.extraData == null || currentNetworkData.extraConfigHash != GetExtraConfigSchemaHash())
			{
				return false;
			}
			int num = configIndex / 32;
			if (num >= currentNetworkData.extraData.Length)
			{
				return false;
			}
			int num2 = 1 << configIndex % 32;
			return (currentNetworkData.extraData[num] & num2) != 0;
		}

		internal static int[] GetExtraConfigBits()
		{
			int[] array = new int[(AllowExtras.Count + 31) / 32];
			foreach (KeyValuePair<int, ConfigEntry<bool>> allowExtra in AllowExtras)
			{
				if (allowExtra.Value.Value)
				{
					int num = allowExtra.Key / 32;
					int num2 = 1 << allowExtra.Key % 32;
					array[num] |= num2;
				}
			}
			return array;
		}

		internal static int GetExtraConfigSchemaHash()
		{
			uint num = 2166136261u;
			foreach (KeyValuePair<int, string> item in ExtraKeys.OrderBy((KeyValuePair<int, string> x) => x.Key))
			{
				string value = item.Value;
				foreach (char c in value)
				{
					num = (num ^ c) * 16777619;
				}
				num = (num ^ 0xFF) * 16777619;
			}
			return (int)num;
		}
	}
	[Serializable]
	public record NetworkData
	{
		public int upgradesPerRound;

		public bool limitedChoices;

		public int numChoices;

		public bool allowMapCount;

		public bool allowEnergy;

		public bool allowExtraJump;

		public bool allowRange;

		public bool allowStrength;

		public bool allowHealth;

		public bool allowSpeed;

		public bool allowTumbleLaunch;

		public bool allowTumbleClimb;

		public bool allowDeathHeadBattery;

		public bool allowTumbleWings;

		public bool allowCrouchRest;

		public int extraConfigHash;

		public int[] extraData;

		public NetworkData()
		{
			upgradesPerRound = Plugin.upgradesPerRound.Value;
			limitedChoices = Plugin.limitedChoices.Value;
			numChoices = Plugin.numChoices.Value;
			allowMapCount = Plugin.allowMapCount.Value;
			allowEnergy = Plugin.allowEnergy.Value;
			allowExtraJump = Plugin.allowExtraJump.Value;
			allowRange = Plugin.allowRange.Value;
			allowStrength = Plugin.allowStrength.Value;
			allowHealth = Plugin.allowHealth.Value;
			allowSpeed = Plugin.allowSpeed.Value;
			allowTumbleLaunch = Plugin.allowTumbleLaunch.Value;
			allowTumbleClimb = Plugin.allowTumbleClimb.Value;
			allowDeathHeadBattery = Plugin.allowDeathHeadBattery.Value;
			allowTumbleWings = Plugin.allowTumbleWings.Value;
			allowCrouchRest = Plugin.allowCrouchRest.Value;
			extraConfigHash = ModUpgradeHandler.GetExtraConfigSchemaHash();
			extraData = ModUpgradeHandler.GetExtraConfigBits();
		}

		public static byte[] Serealize(object data)
		{
			BinaryFormatter binaryFormatter = new BinaryFormatter();
			using MemoryStream memoryStream = new MemoryStream();
			binaryFormatter.Serialize(memoryStream, data);
			return memoryStream.ToArray();
		}

		public static NetworkData Deserialize(byte[] arrBytes)
		{
			using MemoryStream memoryStream = new MemoryStream();
			BinaryFormatter binaryFormatter = new BinaryFormatter();
			memoryStream.Write(arrBytes, 0, arrBytes.Length);
			memoryStream.Seek(0L, SeekOrigin.Begin);
			return (NetworkData)binaryFormatter.Deserialize(memoryStream);
		}
	}
	[HarmonyPatch(typeof(SemiFunc))]
	[HarmonyPatch("OnLevelGenDone")]
	internal static class OnLevelGenDonePatch
	{
		internal static void Postfix()
		{
			UERNetworkManager.levelLoaded = true;
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				UpgradeMenu.OpenMenu();
			}
		}
	}
	[BepInPlugin("dev.redfops.repo.upgradeeveryround", "Upgrade Every Round Updated", "3.0.0")]
	[BepInDependency("nickklmao.menulib", "2.1.3")]
	[BepInDependency("REPOLib", "4.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static EventHandler <0>__ConfigUpdated;

			public static Action<EventData> <1>__HandleConfigUpdateEvent;

			public static Action<EventData> <2>__HandleClientUpgradeEvent;

			public static DeserializeMethod <3>__Deserialize;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static SerializeMethod <>9__29_0;

			internal byte[] <Awake>b__29_0(object x)
			{
				return NetworkData.Serealize(x);
			}
		}

		public const string modGUID = "dev.redfops.repo.upgradeeveryround";

		public const string modName = "Upgrade Every Round Updated";

		public const string modVersion = "3.0.0";

		public static ConfigEntry<int> upgradesPerRound;

		public static ConfigEntry<bool> limitedChoices;

		public static ConfigEntry<int> numChoices;

		public static Plugin Instance;

		public static ConfigEntry<bool> allowMapCount;

		public static ConfigEntry<bool> allowEnergy;

		public static ConfigEntry<bool> allowExtraJump;

		public static ConfigEntry<bool> allowRange;

		public static ConfigEntry<bool> allowStrength;

		public static ConfigEntry<bool> allowHealth;

		public static ConfigEntry<bool> allowSpeed;

		public static ConfigEntry<bool> allowTumbleLaunch;

		public static ConfigEntry<bool> allowTumbleClimb;

		public static ConfigEntry<bool> allowDeathHeadBattery;

		public static ConfigEntry<bool> allowTumbleWings;

		public static ConfigEntry<bool> allowCrouchRest;

		public static NetworkData localNetworkData;

		public static NetworkData remoteNetworkData;

		public static NetworkedEvent ConfigUpdateEvent;

		public static NetworkedEvent ClientUpgradeEvent;

		public static RaiseEventOptions ConfigUpdateEventOptions = new RaiseEventOptions
		{
			CachingOption = (EventCaching)4,
			Receivers = (ReceiverGroup)0
		};

		public static RaiseEventOptions ClientUpgradeEventOptions = new RaiseEventOptions
		{
			Receivers = (ReceiverGroup)2
		};

		internal static ManualLogSource Logger;

		private readonly Harmony harmony = new Harmony("dev.redfops.repo.upgradeeveryround");

		public static NetworkData CurrentNetworkData
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)GameManager.instance) || SemiFunc.IsMasterClientOrSingleplayer())
				{
					return localNetworkData;
				}
				if (remoteNetworkData == null)
				{
					Logger.LogError((object)"Missing remote data");
					return localNetworkData;
				}
				return remoteNetworkData;
			}
		}

		public static int UpgradesPerRound => CurrentNetworkData.upgradesPerRound;

		public static bool LimitedChoices => CurrentNetworkData.limitedChoices;

		public static int NumChoices => CurrentNetworkData.numChoices;

		public static bool AllowMapCount => CurrentNetworkData.allowMapCount;

		public static bool AllowEnergy => CurrentNetworkData.allowEnergy;

		public static bool AllowExtraJump => CurrentNetworkData.allowExtraJump;

		public static bool AllowRange => CurrentNetworkData.allowRange;

		public static bool AllowStrength => CurrentNetworkData.allowStrength;

		public static bool AllowHealth => CurrentNetworkData.allowHealth;

		public static bool AllowSpeed => CurrentNetworkData.allowSpeed;

		public static bool AllowTumbleLaunch => CurrentNetworkData.allowTumbleLaunch;

		public static bool AllowTumbleClimb => CurrentNetworkData.allowTumbleClimb;

		public static bool AllowDeathHeadBattery => CurrentNetworkData.allowDeathHeadBattery;

		public static bool AllowTumbleWings => CurrentNetworkData.allowTumbleWings;

		public static bool AllowCrouchRest => CurrentNetworkData.allowCrouchRest;

		private void Awake()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Expected O, but got Unknown
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Expected O, but got Unknown
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Expected O, but got Unknown
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Expected O, but got Unknown
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Expected O, but got Unknown
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Expected O, but got Unknown
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Expected O, but got Unknown
			//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f8: Expected O, but got Unknown
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_0522: Expected O, but got Unknown
			//IL_05e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ef: Expected O, but got Unknown
			//IL_05ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0604: Unknown result type (might be due to invalid IL or missing references)
			//IL_060a: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			upgradesPerRound = ((BaseUnityPlugin)this).Config.Bind<int>("Upgrades", "Upgrades Per Round", 1, new ConfigDescription("Number of upgrades per round", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 7), Array.Empty<object>()));
			limitedChoices = ((BaseUnityPlugin)this).Config.Bind<bool>("Upgrades", "Limited random choices", false, new ConfigDescription("Only presents a fixed number of random options", (AcceptableValueBase)null, Array.Empty<object>()));
			numChoices = ((BaseUnityPlugin)this).Config.Bind<int>("Upgrades", "Number of choices", 3, new ConfigDescription("Number of options to choose from per upgrade", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 12), Array.Empty<object>()));
			allowMapCount = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Map Player Count", true, new ConfigDescription("Allows Map Player Count Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
			allowEnergy = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Stamina", true, new ConfigDescription("Allows Stamina Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
			allowExtraJump = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Extra Jump", true, new ConfigDescription("Allows Extra Jump Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
			allowRange = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Range", true, new ConfigDescription("Allows Range Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
			allowStrength = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Strength", true, new ConfigDescription("Allows Strength Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
			allowHealth = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Health", true, new ConfigDescription("Allows Health Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
			allowSpeed = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Speed", true, new ConfigDescription("Allows Speed Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
			allowTumbleLaunch = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Tumble Launch", true, new ConfigDescription("Allows Tumble Launch Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
			allowTumbleClimb = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Tumble Climb", true, new ConfigDescription("Allows Tumble Climb Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
			allowDeathHeadBattery = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Death Head Battery", true, new ConfigDescription("Allows Death Head Battery Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
			allowTumbleWings = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Tumble Wings", true, new ConfigDescription("Allows Tumble Wings Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
			allowCrouchRest = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Crouch Rest", true, new ConfigDescription("Allows Crouch Rest Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>()));
			upgradesPerRound.SettingChanged += ConfigUpdated;
			limitedChoices.SettingChanged += ConfigUpdated;
			numChoices.SettingChanged += ConfigUpdated;
			allowMapCount.SettingChanged += ConfigUpdated;
			allowEnergy.SettingChanged += ConfigUpdated;
			allowExtraJump.SettingChanged += ConfigUpdated;
			allowRange.SettingChanged += ConfigUpdated;
			allowStrength.SettingChanged += ConfigUpdated;
			allowHealth.SettingChanged += ConfigUpdated;
			allowSpeed.SettingChanged += ConfigUpdated;
			allowTumbleLaunch.SettingChanged += ConfigUpdated;
			allowTumbleClimb.SettingChanged += ConfigUpdated;
			allowDeathHeadBattery.SettingChanged += ConfigUpdated;
			allowTumbleWings.SettingChanged += ConfigUpdated;
			allowCrouchRest.SettingChanged += ConfigUpdated;
			ConfigUpdateEvent = new NetworkedEvent("ConfigUpdate", (Action<EventData>)HandleConfigUpdateEvent);
			ClientUpgradeEvent = new NetworkedEvent("ClientUpgrade", (Action<EventData>)HandleClientUpgradeEvent);
			((Component)this).gameObject.AddComponent<UpgradeEveryRoundPhotonCallbacks>();
			harmony.PatchAll(typeof(SceneSwitchPatch));
			harmony.PatchAll(typeof(OnLevelGenDonePatch));
			harmony.PatchAll(typeof(SteamManagerPatch));
			harmony.PatchAll(typeof(RunManagerMainMenuPatch));
			harmony.PatchAll(typeof(StatsManagerStartPatch));
			harmony.PatchAll(typeof(StatsManagerLoadGamePatch));
			harmony.PatchAll(typeof(StatsUIPatch));
			Type? typeFromHandle = typeof(NetworkData);
			object obj = <>c.<>9__29_0;
			if (obj == null)
			{
				SerializeMethod val = (object x) => NetworkData.Serealize(x);
				<>c.<>9__29_0 = val;
				obj = (object)val;
			}
			object obj2 = <>O.<3>__Deserialize;
			if (obj2 == null)
			{
				DeserializeMethod val2 = NetworkData.Deserialize;
				<>O.<3>__Deserialize = val2;
				obj2 = (object)val2;
			}
			PhotonPeer.RegisterType(typeFromHandle, (byte)248, (SerializeMethod)obj, (DeserializeMethod)obj2);
			((MonoBehaviour)this).StartCoroutine(UERNetworkManager.Go());
			Logger.LogInfo((object)"Plugin UpgradeEveryRound is loaded!");
		}

		internal static void ConfigUpdated(object sender, EventArgs args)
		{
			localNetworkData = new NetworkData();
			if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient)
			{
				SendConfig();
			}
		}

		public static void SendConfig()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient)
			{
				if ((object)localNetworkData == null)
				{
					localNetworkData = new NetworkData();
				}
				ConfigUpdateEvent.RaiseEvent((object)localNetworkData, ConfigUpdateEventOptions, SendOptions.SendReliable);
			}
		}

		private static void HandleConfigUpdateEvent(EventData eventData)
		{
			if (PhotonNetwork.MasterClient == null || eventData.Sender != PhotonNetwork.MasterClient.ActorNumber)
			{
				Logger.LogWarning((object)"Ignoring upgrade configuration sent by a non-master client.");
			}
			else if (!(eventData.CustomData is NetworkData networkData))
			{
				Logger.LogWarning((object)"Ignoring invalid upgrade configuration data.");
			}
			else
			{
				remoteNetworkData = networkData;
			}
		}

		public static void DoUpgradeClient(string upgradeId, string _steamID)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_001e: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			Hashtable val = new Hashtable();
			((Dictionary<object, object>)val).Add((object)"upgrade", (object)upgradeId);
			((Dictionary<object, object>)val).Add((object)"steamID", (object)_steamID);
			Hashtable val2 = val;
			ClientUpgradeEvent.RaiseEvent((object)val2, ClientUpgradeEventOptions, SendOptions.SendReliable);
		}

		private static void HandleClientUpgradeEvent(EventData eventData)
		{
			object customData = eventData.CustomData;
			Hashtable val = (Hashtable)((customData is Hashtable) ? customData : null);
			if (val == null || !(val[(object)"upgrade"] is string text) || !(val[(object)"steamID"] is string text2))
			{
				Logger.LogWarning((object)"Ignoring invalid upgrade request data.");
				return;
			}
			switch (text)
			{
			case "Stamina":
				PunManager.instance.UpgradePlayerEnergy(text2, 1);
				break;
			case "Extra Jump":
				PunManager.instance.UpgradePlayerExtraJump(text2, 1);
				break;
			case "Range":
				PunManager.instance.UpgradePlayerGrabRange(text2, 1);
				break;
			case "Strength":
				PunManager.instance.UpgradePlayerGrabStrength(text2, 1);
				break;
			case "Health":
				PunManager.instance.UpgradePlayerHealth(text2, 1);
				break;
			case "Sprint Speed":
				PunManager.instance.UpgradePlayerSprintSpeed(text2, 1);
				break;
			case "Tumble Launch":
				PunManager.instance.UpgradePlayerTumbleLaunch(text2, 1);
				break;
			case "Map Player Count":
				PunManager.instance.UpgradeMapPlayerCount(text2, 1);
				break;
			case "Tumble Climb":
				PunManager.instance.UpgradePlayerTumbleClimb(text2, 1);
				break;
			case "Death Head Battery":
				PunManager.instance.UpgradeDeathHeadBattery(text2, 1);
				break;
			case "Tumble Wings":
				PunManager.instance.UpgradePlayerTumbleWings(text2, 1);
				break;
			case "Crouch Rest":
				PunManager.instance.UpgradePlayerCrouchRest(text2, 1);
				break;
			default:
				if (!ModUpgradeHandler.DoUpgrade(text, text2))
				{
					return;
				}
				break;
			}
			int num = UpgradeUsageData.GetCount(StatsManager.instance, text2) + 1;
			PunManager.instance.UpdateStat("upgradeEveryRoundUsage", text2, num);
		}

		public static void ApplyUpgrade(string _steamID, REPOPopupPage popupPage)
		{
			StatsUI.instance.Fetch();
			StatsUI.instance.ShowStats();
			CameraGlitch.Instance.PlayUpgrade();
			int num = (UERNetworkManager.upgradesUsedLocal = NumUpgradesUsed(_steamID) + 1);
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				PunManager.instance.UpdateStat("upgradeEveryRoundUsage", _steamID, num);
			}
			UpgradeMenu.isOpen = false;
			popupPage.ClosePage(true);
			if (RunManager.instance.levelsCompleted * UpgradesPerRound > num)
			{
				UpgradeMenu.createMenu(_steamID).OpenPage(false);
				UpgradeMenu.isOpen = true;
			}
		}

		public static int NumUpgradesUsed(string _steamID)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return UERNetworkManager.upgradesUsedLocal;
			}
			return UpgradeUsageData.GetCount(StatsManager.instance, _steamID);
		}
	}
	internal sealed class UpgradeEveryRoundPhotonCallbacks : MonoBehaviourPunCallbacks
	{
		public override void OnMasterClientSwitched(Player newMasterClient)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				Plugin.SendConfig();
			}
		}
	}
	[HarmonyPatch(typeof(SemiFunc))]
	[HarmonyPatch("OnSceneSwitch")]
	internal static class SceneSwitchPatch
	{
		private static void Prefix()
		{
			UERNetworkManager.LevelChange();
		}
	}
	[HarmonyPatch(typeof(SteamManager))]
	internal static class SteamManagerPatch
	{
		[HarmonyPatch("UnlockLobby")]
		[HarmonyPostfix]
		internal static void UnlockLobbyPostfix()
		{
			Plugin.SendConfig();
		}
	}
	public static class UERNetworkManager
	{
		public static bool synced = false;

		public static bool levelLoaded = false;

		public static bool menuOpened = false;

		private static bool joinedGame = false;

		public static int upgradesUsedLocal = -1;

		public static IEnumerator Go()
		{
			while (true)
			{
				yield return (object)new WaitForFixedUpdate();
				if (!Object.op_Implicit((Object)(object)GameManager.instance) || SemiFunc.IsMasterClientOrSingleplayer())
				{
					synced = false;
					levelLoaded = false;
					menuOpened = false;
					upgradesUsedLocal = -1;
					continue;
				}
				if (!joinedGame)
				{
					UpgradeUsageData.SetCount(StatsManager.instance, SteamClient.SteamId.Value.ToString(), -1);
					joinedGame = true;
				}
				if (!levelLoaded)
				{
					continue;
				}
				synced = StatsManager.instance.statsSynced;
				if (!synced || !levelLoaded || menuOpened || Plugin.remoteNetworkData == null)
				{
					continue;
				}
				int count = UpgradeUsageData.GetCount(StatsManager.instance, SteamClient.SteamId.Value.ToString());
				if (count != -1)
				{
					if (upgradesUsedLocal == -1)
					{
						upgradesUsedLocal = count;
					}
					UpgradeMenu.OpenMenu();
					menuOpened = true;
				}
			}
		}

		public static void LevelChange()
		{
			synced = false;
			levelLoaded = false;
			menuOpened = false;
		}
	}
	public static class UpgradeMenu
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__3_0;

			internal void <createMenu>b__3_0()
			{
				isOpen = false;
			}
		}

		public static bool isOpen;

		public static bool choseUpgrade;

		public static void OpenMenu()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if (!isOpen && !((IEnumerable<Level>)(object)new Level[3]
			{
				RunManager.instance.levelMainMenu,
				RunManager.instance.levelLobbyMenu,
				RunManager.instance.levelTutorial
			}).Contains(RunManager.instance.levelCurrent))
			{
				string steamID = SteamClient.SteamId.Value.ToString();
				int num = RunManager.instance.levelsCompleted * Plugin.UpgradesPerRound;
				if (Plugin.NumUpgradesUsed(steamID) < num)
				{
					MenuManager.instance.PageCloseAll();
					REPOPopupPage obj = createMenu(steamID);
					isOpen = true;
					obj.OpenPage(false);
				}
			}
		}

		public static REPOPopupPage createMenu(string _steamID)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Expected O, but got Unknown
			//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b6: Expected O, but got Unknown
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Expected O, but got Unknown
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Expected O, but got Unknown
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Expected O, but got Unknown
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			//IL_046a: Expected O, but got Unknown
			//IL_048d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0497: Expected O, but got Unknown
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c4: Expected O, but got Unknown
			//IL_04e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f1: Expected O, but got Unknown
			//IL_0514: Unknown result type (might be due to invalid IL or missing references)
			//IL_051e: Expected O, but got Unknown
			//IL_0541: Unknown result type (might be due to invalid IL or missing references)
			//IL_054b: Expected O, but got Unknown
			//IL_056b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0575: Expected O, but got Unknown
			//IL_05bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c7: Expected O, but got Unknown
			choseUpgrade = false;
			StatsUI.instance.Fetch();
			StatsUI.instance.ShowStats();
			REPOPopupPage repoPopupPage = MenuAPI.CreateREPOPopupPage("Choose an upgrade", (PresetSide)1, false, true, 1.5f);
			UnityEvent onPageEnd = repoPopupPage.menuPage.onPageEnd;
			object obj = <>c.<>9__3_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
					isOpen = false;
				};
				<>c.<>9__3_0 = val;
				obj = (object)val;
			}
			onPageEnd.AddListener((UnityAction)obj);
			List<int> list = new List<int>(12)
			{
				0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
				10, 11
			};
			List<bool> list2 = new List<bool>(12)
			{
				Plugin.AllowEnergy,
				Plugin.AllowExtraJump,
				Plugin.AllowRange,
				Plugin.AllowStrength,
				Plugin.AllowHealth,
				Plugin.AllowSpeed,
				Plugin.AllowTumbleLaunch,
				Plugin.AllowMapCount,
				Plugin.AllowTumbleClimb,
				Plugin.AllowDeathHeadBattery,
				Plugin.AllowTumbleWings,
				Plugin.AllowCrouchRest
			};
			foreach (KeyValuePair<int, ConfigEntry<bool>> allowExtra in ModUpgradeHandler.AllowExtras)
			{
				int key = allowExtra.Key;
				list.Add(list.Count);
				list2.Add(ModUpgradeHandler.AllowCustomUpgradeByIndex(key));
			}
			int numChoices = (Plugin.LimitedChoices ? Plugin.NumChoices : list.Count);
			int num = 0;
			for (int num2 = 0; num2 < list.Count; num2++)
			{
				if (!list2[num2])
				{
					list.RemoveAt(num2 - num);
					num++;
				}
			}
			numChoices = Mathf.Min(numChoices, list.Count);
			_ = new Vector2[8]
			{
				new Vector2(390f, 18f),
				new Vector2(530f, 18f),
				new Vector2(390f, 60f),
				new Vector2(530f, 60f),
				new Vector2(390f, 102f),
				new Vector2(530f, 102f),
				new Vector2(390f, 144f),
				new Vector2(530f, 144f)
			};
			for (int i = 0; i < numChoices; i++)
			{
				int index = (Plugin.LimitedChoices ? Random.Range(0, list.Count) : 0);
				int num3 = list[index];
				list.RemoveAt(index);
				_ = i;
				switch (num3)
				{
				case 0:
					repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent)
					{
						CreateButton(parent, "Stamina", delegate
						{
							if (SemiFunc.IsMasterClientOrSingleplayer())
							{
								PunManager.instance.UpgradePlayerEnergy(_steamID, 1);
							}
							else
							{
								Plugin.DoUpgradeClient("Stamina", _steamID);
							}
						}, i, numChoices, _steamID, repoPopupPage);
					});
					continue;
				case 1:
					repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent)
					{
						CreateButton(parent, "Extra Jump", delegate
						{
							if (SemiFunc.IsMasterClientOrSingleplayer())
							{
								PunManager.instance.UpgradePlayerExtraJump(_steamID, 1);
							}
							else
							{
								Plugin.DoUpgradeClient("Extra Jump", _steamID);
							}
						}, i, numChoices, _steamID, repoPopupPage);
					});
					continue;
				case 2:
					repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent)
					{
						CreateButton(parent, "Range", delegate
						{
							if (SemiFunc.IsMasterClientOrSingleplayer())
							{
								PunManager.instance.UpgradePlayerGrabRange(_steamID, 1);
							}
							else
							{
								Plugin.DoUpgradeClient("Range", _steamID);
							}
						}, i, numChoices, _steamID, repoPopupPage);
					});
					continue;
				case 3:
					repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent)
					{
						CreateButton(parent, "Strength", delegate
						{
							if (SemiFunc.IsMasterClientOrSingleplayer())
							{
								PunManager.instance.UpgradePlayerGrabStrength(_steamID, 1);
							}
							else
							{
								Plugin.DoUpgradeClient("Strength", _steamID);
							}
						}, i, numChoices, _steamID, repoPopupPage);
					});
					continue;
				case 4:
					repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent)
					{
						CreateButton(parent, "Health", delegate
						{
							if (SemiFunc.IsMasterClientOrSingleplayer())
							{
								PunManager.instance.UpgradePlayerHealth(_steamID, 1);
							}
							else
							{
								Plugin.DoUpgradeClient("Health", _steamID);
							}
						}, i, numChoices, _steamID, repoPopupPage);
					});
					continue;
				case 5:
					repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent)
					{
						CreateButton(parent, "Sprint Speed", delegate
						{
							if (SemiFunc.IsMasterClientOrSingleplayer())
							{
								PunManager.instance.UpgradePlayerSprintSpeed(_steamID, 1);
							}
							else
							{
								Plugin.DoUpgradeClient("Sprint Speed", _steamID);
							}
						}, i, numChoices, _steamID, repoPopupPage);
					});
					continue;
				case 6:
					repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent)
					{
						CreateButton(parent, "Tumble Launch", delegate
						{
							if (SemiFunc.IsMasterClientOrSingleplayer())
							{
								PunManager.instance.UpgradePlayerTumbleLaunch(_steamID, 1);
							}
							else
							{
								Plugin.DoUpgradeClient("Tumble Launch", _steamID);
							}
						}, i, numChoices, _steamID, repoPopupPage);
					});
					continue;
				case 7:
					repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent)
					{
						CreateButton(parent, "Map Player Count", delegate
						{
							if (SemiFunc.IsMasterClientOrSingleplayer())
							{
								PunManager.instance.UpgradeMapPlayerCount(_steamID, 1);
							}
							else
							{
								Plugin.DoUpgradeClient("Map Player Count", _steamID);
							}
						}, i, numChoices, _steamID, repoPopupPage);
					});
					continue;
				case 8:
					repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent)
					{
						CreateButton(parent, "Tumble Climb", delegate
						{
							if (SemiFunc.IsMasterClientOrSingleplayer())
							{
								PunManager.instance.UpgradePlayerTumbleClimb(_steamID, 1);
							}
							else
							{
								Plugin.DoUpgradeClient("Tumble Climb", _steamID);
							}
						}, i, numChoices, _steamID, repoPopupPage);
					});
					continue;
				case 9:
					repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent)
					{
						CreateButton(parent, "Death Head Battery", delegate
						{
							if (SemiFunc.IsMasterClientOrSingleplayer())
							{
								PunManager.instance.UpgradeDeathHeadBattery(_steamID, 1);
							}
							else
							{
								Plugin.DoUpgradeClient("Death Head Battery", _steamID);
							}
						}, i, numChoices, _steamID, repoPopupPage);
					});
					continue;
				case 10:
					repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent)
					{
						CreateButton(parent, "Tumble Wings", delegate
						{
							if (SemiFunc.IsMasterClientOrSingleplayer())
							{
								PunManager.instance.UpgradePlayerTumbleWings(_steamID, 1);
							}
							else
							{
								Plugin.DoUpgradeClient("Tumble Wings", _steamID);
							}
						}, i, numChoices, _steamID, repoPopupPage);
					});
					continue;
				case 11:
					repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent)
					{
						CreateButton(parent, "Crouch Rest", delegate
						{
							if (SemiFunc.IsMasterClientOrSingleplayer())
							{
								PunManager.instance.UpgradePlayerCrouchRest(_steamID, 1);
							}
							else
							{
								Plugin.DoUpgradeClient("Crouch Rest", _steamID);
							}
						}, i, numChoices, _steamID, repoPopupPage);
					});
					continue;
				}
				int key2 = num3 - 12;
				string extraLabel = ModUpgradeHandler.ExtraLabels[key2];
				string extraKey = ModUpgradeHandler.ExtraKeys[key2];
				repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent)
				{
					CreateButton(parent, extraLabel, delegate
					{
						if (SemiFunc.IsMasterClientOrSingleplayer())
						{
							ModUpgradeHandler.DoUpgrade(extraKey, _steamID);
						}
						else
						{
							Plugin.DoUpgradeClient(extraKey, _steamID);
						}
					}, i, numChoices, _steamID, repoPopupPage);
				});
			}
			return repoPopupPage;
		}

		private static REPOButton CreateButton(Transform parent, string buttonText, Action upgradeStat, int buttonNumber, int totalButtons, string _steamID, REPOPopupPage page)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			(Vector2, float) buttonPos = GetButtonPos(buttonNumber, totalButtons);
			Vector2 item = buttonPos.Item1;
			float item2 = buttonPos.Item2;
			REPOButton obj = MenuAPI.CreateREPOButton(buttonText, (Action)delegate
			{
				if (!choseUpgrade)
				{
					choseUpgrade = true;
					upgradeStat();
					Plugin.ApplyUpgrade(_steamID, page);
				}
			}, parent, item);
			TextMeshProUGUI labelTMP = obj.labelTMP;
			((TMP_Text)labelTMP).fontSize = ((TMP_Text)labelTMP).fontSize * item2;
			return obj;
		}

		private static (Vector2, float) GetButtonPos(int buttonNumber, int totalButtons)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			if (totalButtons <= 8)
			{
				return (new Vector2(370f + (float)(140 * (buttonNumber % 2)), 270f - 52f * (float)(buttonNumber / 2)), 0.9f);
			}
			float num = 252f;
			int num2 = 8;
			float num3 = num / (42f * (float)(totalButtons / num2));
			float num4 = num3 * 42f;
			float num5 = num3 * 180f;
			num2 = Math.Max((int)(370f / num5), 2);
			while (num2 != 1)
			{
				num2--;
				num3 = Math.Min(num / (42f * (float)(totalButtons / num2)), 2f / (float)num2);
				num4 = num3 * 42f;
				num5 = num3 * 180f;
				if (!((float)(totalButtons / num2) * num4 < num))
				{
					break;
				}
			}
			num2++;
			num3 = Math.Min(num / (42f * (float)(totalButtons / num2)), 2f / (float)num2);
			num4 = num3 * 42f;
			num5 = num3 * 180f;
			return (new Vector2(370f + (float)(buttonNumber % num2) * num5, 270f - (float)(buttonNumber / num2) * num4), num3 * 0.9f);
		}
	}
	internal static class UpgradeUsageData
	{
		internal const string DictionaryName = "upgradeEveryRoundUsage";

		private const string LegacyDictionaryName = "playerUpgradesUsed";

		internal static void Initialize(StatsManager statsManager)
		{
			IDictionary<string, Dictionary<string, int>> dictionaries = GetDictionaries(statsManager);
			if (!dictionaries.TryGetValue("upgradeEveryRoundUsage", out var value))
			{
				value = new Dictionary<string, int>();
				dictionaries.Add("upgradeEveryRoundUsage", value);
			}
			if (!dictionaries.TryGetValue("playerUpgradesUsed", out var value2))
			{
				return;
			}
			foreach (KeyValuePair<string, int> item in value2)
			{
				if (!value.ContainsKey(item.Key))
				{
					value[item.Key] = item.Value;
				}
			}
			dictionaries.Remove("playerUpgradesUsed");
		}

		internal static int GetCount(StatsManager statsManager, string steamId)
		{
			if (!GetCounts(statsManager).TryGetValue(steamId, out var value))
			{
				return 0;
			}
			return value;
		}

		internal static void SetCount(StatsManager statsManager, string steamId, int count)
		{
			GetCounts(statsManager)[steamId] = count;
		}

		private static Dictionary<string, int> GetCounts(StatsManager statsManager)
		{
			IDictionary<string, Dictionary<string, int>> dictionaries = GetDictionaries(statsManager);
			if (!dictionaries.TryGetValue("upgradeEveryRoundUsage", out var value))
			{
				value = new Dictionary<string, int>();
				dictionaries.Add("upgradeEveryRoundUsage", value);
			}
			return value;
		}

		private static IDictionary<string, Dictionary<string, int>> GetDictionaries(StatsManager statsManager)
		{
			if ((Object)(object)statsManager == (Object)null)
			{
				throw new ArgumentNullException("statsManager");
			}
			return (Traverse.Create((object)statsManager).Field("dictionaryOfDictionaries").GetValue() as IDictionary<string, Dictionary<string, int>>) ?? throw new MissingFieldException(typeof(StatsManager).FullName, "dictionaryOfDictionaries");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "UpgradeEveryRound";

		public const string PLUGIN_NAME = "Upgrade Every Round";

		public const string PLUGIN_VERSION = "2.0.3";
	}
}