Decompiled source of SLRUpgradePack v0.5.1

plugins/SLRUpgradePack.dll

Decompiled 2 days ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
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 KeybindLib.Classes;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Photon.Pun;
using Photon.Realtime;
using REPOLib.Modules;
using REPOLib.Objects.Sdk;
using SLRUpgradePack.Properties;
using SLRUpgradePack.UpgradeManagers;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.UIElements;

[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("SolarAaron")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+c1597210e846d56390baa80b3d73081f87399f8c")]
[assembly: AssemblyProduct("SLRUpgradePack")]
[assembly: AssemblyTitle("SLRUpgradePack")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.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 SLRUpgradePack
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("SolarAaron.SLRUpgradePack", "SLRUpgradePack", "0.5.1")]
	public class SLRUpgradePack : BaseUnityPlugin
	{
		private static readonly FieldRef<PlayerUpgrade, Action<PlayerAvatar, int>> PlayerUpgradeStartActionRef = AccessTools.FieldRefAccess<PlayerUpgrade, Action<PlayerAvatar, int>>("StartAction");

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

		private readonly HashSet<(string Upgrade, string SteamId)> _initializedStartingLevels = new HashSet<(string, string)>();

		private readonly Dictionary<(string Upgrade, string SteamId), int> _initializedStartActionLevels = new Dictionary<(string, string), int>();

		private readonly HashSet<string> _playersWithStartActions = new HashSet<string>();

		internal Dictionary<string, Action> Actions { get; private set; } = new Dictionary<string, Action>();

		internal static SLRUpgradePack Instance { get; private set; } = null;

		internal static ManualLogSource Logger => Instance._logger;

		internal Harmony? Harmony { get; set; }

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		public static OverchargeUpgrade OverchargeUpgradeInstance { get; private set; }

		public static ArmorUpgrade ArmorUpgradeInstance { get; private set; }

		public static ObjectValueUpgrade ObjectValueUpgradeInstance { get; private set; }

		public static ObjectDurabilityUpgrade ObjectDurabilityUpgradeInstance { get; private set; }

		public static ValuableDensityUpgrade ValuableDensityUpgradeInstance { get; private set; }

		public static HeartOfGoldUpgrade HeartOfGoldUpgradeInstance { get; private set; }

		public static RegenerationUpgrade RegenerationUpgradeInstance { get; private set; }

		public static ExtraLifeUpgrade ExtraLifeUpgradeInstance { get; private set; }

		public static InventorySlotUpgrade InventorySlotUpgradeInstance { get; private set; }

		private void Awake()
		{
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			_logger.LogInfo((object)"Configuring upgrade pack...");
			AssetBundle val = AssetBundle.LoadFromMemory(Resources.slr_assets);
			((Object)val).name = "slr";
			string[] allAssetNames = val.GetAllAssetNames();
			foreach (string text in allAssetNames)
			{
				_logger.LogInfo((object)("Found asset: " + text));
			}
			if (PhysGrabberPatch.Prepare())
			{
				OverchargeUpgradeInstance = new OverchargeUpgrade(enabled: true, 0.1f, exponential: false, 1.1f, ((BaseUnityPlugin)this).Config, val, 0.75f);
			}
			ArmorUpgradeInstance = new ArmorUpgrade(enabled: true, 0.1f, exponential: false, 1.1f, ((BaseUnityPlugin)this).Config, val, 1f);
			ObjectValueUpgradeInstance = new ObjectValueUpgrade(enabled: true, 0.1f, exponential: false, 1.1f, ((BaseUnityPlugin)this).Config, val, 2.5f);
			ObjectDurabilityUpgradeInstance = new ObjectDurabilityUpgrade(enabled: true, 0.1f, exponential: false, 1.1f, ((BaseUnityPlugin)this).Config, val, 2.5f);
			ValuableDensityUpgradeInstance = new ValuableDensityUpgrade(enabled: true, 0.1f, exponential: false, 1.1f, ((BaseUnityPlugin)this).Config, val, 2.5f);
			HeartOfGoldUpgradeInstance = new HeartOfGoldUpgrade(enabled: true, 0.1f, exponential: false, 1.1f, ((BaseUnityPlugin)this).Config, val, 10f, 3.5f);
			RegenerationUpgradeInstance = new RegenerationUpgrade(enabled: true, 0.1f, exponential: false, 1.1f, ((BaseUnityPlugin)this).Config, val, 0.1f, 4.5f);
			ExtraLifeUpgradeInstance = new ExtraLifeUpgrade(enabled: true, 0.1f, exponential: false, 1.1f, ((BaseUnityPlugin)this).Config, val, 5, 10f);
			InventorySlotUpgradeInstance = new InventorySlotUpgrade(enabled: true, 1, ((BaseUnityPlugin)this).Config, val, 2f);
			Patch();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		internal void Patch()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0025: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !Object.op_Implicit((Object)(object)LevelGenerator.Instance) || !LevelGenerator.Instance.Generated)
			{
				return;
			}
			foreach (Action item in new List<Action>(Actions.Values))
			{
				item();
			}
		}

		internal void InitializeStartingLevelsForPlayer(string steamId)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && !string.IsNullOrWhiteSpace(steamId))
			{
				if (PhysGrabberPatch.Prepare())
				{
					InitializeStartingLevel("Overcharge", OverchargeUpgradeInstance, steamId);
				}
				InitializeStartingLevel("Armor", ArmorUpgradeInstance, steamId);
				InitializeStartingLevel("ObjectValue", ObjectValueUpgradeInstance, steamId);
				InitializeStartingLevel("ObjectDurability", ObjectDurabilityUpgradeInstance, steamId);
				InitializeStartingLevel("ValuableDensity", ValuableDensityUpgradeInstance, steamId);
				InitializeStartingLevel("HeartOfGold", HeartOfGoldUpgradeInstance, steamId);
				InitializeStartingLevel("Regeneration", RegenerationUpgradeInstance, steamId);
				InitializeStartingLevel("ExtraLife", ExtraLifeUpgradeInstance, steamId);
				InitializeStartingLevel("InventorySlot", InventorySlotUpgradeInstance, steamId);
			}
		}

		internal void InitializeStartingLevelsForActivePlayers()
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			PlayerAvatar[] array = Object.FindObjectsOfType<PlayerAvatar>();
			foreach (PlayerAvatar val in array)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					InitializeStartingLevelsForPlayer(SemiFunc.PlayerGetSteamID(val));
				}
			}
		}

		private void InitializeStartingLevel<T>(string upgradeName, UpgradeBase<T> upgrade, string steamId)
		{
			if (upgrade == null || !upgrade.UpgradeEnabled.Value || upgrade.UpgradeRegister == null)
			{
				return;
			}
			int value = upgrade.StartingAmount.Value;
			if (value <= 0)
			{
				return;
			}
			(string, string) item = (upgradeName, steamId);
			if (!_initializedStartingLevels.Add(item))
			{
				return;
			}
			try
			{
				int level = upgrade.UpgradeRegister.GetLevel(steamId);
				if (level < value)
				{
					Logger.LogInfo((object)$"Applying configured starting level for {upgradeName} to player {steamId}: {level} -> {value}");
					upgrade.UpgradeRegister.SetLevel(steamId, value);
				}
			}
			catch (Exception arg)
			{
				_initializedStartingLevels.Remove(item);
				Logger.LogError((object)$"Failed to initialize {upgradeName} for player {steamId}: {arg}");
			}
		}

		internal void RecordPlayerStartActions(string steamId)
		{
			if (string.IsNullOrWhiteSpace(steamId))
			{
				return;
			}
			_playersWithStartActions.Add(steamId);
			foreach (PlayerUpgrade playerUpgrade in Upgrades.PlayerUpgrades)
			{
				_initializedStartActionLevels[(playerUpgrade.UpgradeId, steamId)] = playerUpgrade.GetLevel(steamId);
			}
		}

		internal void RepairRemotePlayerStartAction(PlayerUpgrade upgrade, string steamId, int level)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() || string.IsNullOrWhiteSpace(steamId) || !_playersWithStartActions.Contains(steamId))
			{
				return;
			}
			int configuredStartingLevel = GetConfiguredStartingLevel(upgrade);
			Action<PlayerAvatar, int> action = PlayerUpgradeStartActionRef.Invoke(upgrade);
			if (configuredStartingLevel <= 0 || level < configuredStartingLevel || action == null)
			{
				return;
			}
			(string, string) key = (upgrade.UpgradeId, steamId);
			if (_initializedStartActionLevels.TryGetValue(key, out var value) && value >= configuredStartingLevel)
			{
				return;
			}
			PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(steamId);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			try
			{
				action(val, upgrade.GetLevel(steamId));
				_initializedStartActionLevels[key] = upgrade.GetLevel(steamId);
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"Failed to initialize synchronized {upgrade.UpgradeId} for player {steamId}: {arg}");
			}
		}

		private int GetConfiguredStartingLevel(PlayerUpgrade upgrade)
		{
			if (OverchargeUpgradeInstance?.UpgradeRegister == upgrade)
			{
				return OverchargeUpgradeInstance.StartingAmount.Value;
			}
			if (ArmorUpgradeInstance?.UpgradeRegister == upgrade)
			{
				return ArmorUpgradeInstance.StartingAmount.Value;
			}
			if (ObjectValueUpgradeInstance?.UpgradeRegister == upgrade)
			{
				return ObjectValueUpgradeInstance.StartingAmount.Value;
			}
			if (ObjectDurabilityUpgradeInstance?.UpgradeRegister == upgrade)
			{
				return ObjectDurabilityUpgradeInstance.StartingAmount.Value;
			}
			if (ValuableDensityUpgradeInstance?.UpgradeRegister == upgrade)
			{
				return ValuableDensityUpgradeInstance.StartingAmount.Value;
			}
			if (HeartOfGoldUpgradeInstance?.UpgradeRegister == upgrade)
			{
				return HeartOfGoldUpgradeInstance.StartingAmount.Value;
			}
			if (RegenerationUpgradeInstance?.UpgradeRegister == upgrade)
			{
				return RegenerationUpgradeInstance.StartingAmount.Value;
			}
			if (ExtraLifeUpgradeInstance?.UpgradeRegister == upgrade)
			{
				return ExtraLifeUpgradeInstance.StartingAmount.Value;
			}
			if (InventorySlotUpgradeInstance?.UpgradeRegister == upgrade)
			{
				return InventorySlotUpgradeInstance.StartingAmount.Value;
			}
			return 0;
		}

		internal void ResetStartingLevelInitialization()
		{
			_initializedStartingLevels.Clear();
			_initializedStartActionLevels.Clear();
			_playersWithStartActions.Clear();
		}
	}
	[HarmonyPatch(typeof(MenuPageSaves), "OnNewGame")]
	internal static class NewGameStartingUpgradeLevelsPatch
	{
		private static void Prefix()
		{
			SLRUpgradePack.Instance.ResetStartingLevelInitialization();
		}
	}
	[HarmonyPatch(typeof(RunManager), "ResetProgress")]
	internal static class ResetRunStartingUpgradeLevelsPatch
	{
		private static void Postfix()
		{
			if ((Object)(object)SLRUpgradePack.Instance != (Object)null)
			{
				SLRUpgradePack.Instance.ResetStartingLevelInitialization();
			}
		}
	}
	[HarmonyPatch(typeof(Upgrades), "InvokeStartActions")]
	internal static class InitializeStartingUpgradeLevelsPatch
	{
		private static void Prefix(string steamId)
		{
			if ((Object)(object)SLRUpgradePack.Instance != (Object)null)
			{
				SLRUpgradePack.Instance.InitializeStartingLevelsForPlayer(steamId);
			}
		}

		private static void Postfix(string steamId)
		{
			if ((Object)(object)SLRUpgradePack.Instance != (Object)null)
			{
				SLRUpgradePack.Instance.RecordPlayerStartActions(steamId);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerUpgrade), "ApplyUpgrade")]
	internal static class RepairRemoteStartingUpgradeActionsPatch
	{
		private static void Postfix(PlayerUpgrade __instance, string steamId, int level)
		{
			if ((Object)(object)SLRUpgradePack.Instance != (Object)null)
			{
				SLRUpgradePack.Instance.RepairRemotePlayerStartAction(__instance, steamId, level);
			}
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "Start")]
	internal static class LevelGeneratorStartingUpgradeLevelsPatch
	{
		[HarmonyPriority(800)]
		private static void Prefix()
		{
			if ((Object)(object)SLRUpgradePack.Instance != (Object)null)
			{
				SLRUpgradePack.Instance.InitializeStartingLevelsForActivePlayers();
			}
		}
	}
}
namespace SLRUpgradePack.UpgradeManagers
{
	public class ArmorUpgrade : UpgradeBase<float>
	{
		public ArmorUpgrade(bool enabled, float upgradeAmount, bool exponential, float exponentialAmount, ConfigFile config, AssetBundle assetBundle, float priceMultiplier)
			: base("Armor", "assets/repo/mods/resources/items/items/item upgrade armor lib.asset", enabled, upgradeAmount, exponential, exponentialAmount, config, assetBundle, priceMultiplier, configureAmount: true, canBeExponential: true, (int?)null)
		{
		}

		public override float Calculate(float value, PlayerAvatar player, int level)
		{
			return UpgradeBase<float>.DefaultCalculateFloatReduce(this, "Armor", value, player, level);
		}
	}
	[HarmonyPatch(typeof(PlayerHealth), "Hurt")]
	public class PlayerHealthArmorPatch
	{
		private static void Prefix(PlayerHealth __instance, ref int damage, PlayerAvatar ___playerAvatar)
		{
			ArmorUpgrade armorUpgradeInstance = SLRUpgradePack.ArmorUpgradeInstance;
			if (armorUpgradeInstance.UpgradeEnabled.Value)
			{
				SLRUpgradePack.Logger.LogDebug((object)$"Original damage amount: {damage}");
				damage = (int)Math.Ceiling(armorUpgradeInstance.Calculate(damage, ___playerAvatar, armorUpgradeInstance.UpgradeRegister.GetLevel(___playerAvatar)));
				SLRUpgradePack.Logger.LogDebug((object)string.Format("After calculation with level {0}: {1}", Upgrades.GetUpgrade("Armor").GetLevel(___playerAvatar), damage));
			}
		}
	}
	public class ExtraLifeUpgrade : UpgradeBase<float>
	{
		private readonly Dictionary<string, Coroutine?> _reviveCoroutines = new Dictionary<string, Coroutine>();

		private static readonly FieldRef<PlayerHealth, int>? MaxHealthRef = AccessTools.FieldRefAccess<PlayerHealth, int>("maxHealth");

		private readonly FieldRef<PlayerHealth, int> _healthRef = AccessTools.FieldRefAccess<PlayerHealth, int>("health");

		private static readonly FieldRef<PlayerAvatar, bool> _deadSetRef = AccessTools.FieldRefAccess<PlayerAvatar, bool>("deadSet");

		private readonly FieldRef<PlayerDeathHead, bool> _inExtractionPointRef = AccessTools.FieldRefAccess<PlayerDeathHead, bool>("inExtractionPoint");

		private readonly FieldRef<PlayerDeathHead, PhysGrabObject> _physGrabObjectRef = AccessTools.FieldRefAccess<PlayerDeathHead, PhysGrabObject>("physGrabObject");

		private static readonly FieldRef<PlayerAvatar, PlayerDeathHead> _playerDeathHeadRef = AccessTools.FieldRefAccess<PlayerAvatar, PlayerDeathHead>("playerDeathHead");

		private static readonly FieldRef<RoundDirector, bool> _extractionPointsFetchedRef = AccessTools.FieldRefAccess<RoundDirector, bool>("extractionPointsFetched");

		private static readonly FieldRef<PlayerAvatar, PlayerTumble> _playerTumbleRef = AccessTools.FieldRefAccess<PlayerAvatar, PlayerTumble>("tumble");

		private static readonly FieldRef<PlayerTumble, bool> _isTumblingRef = AccessTools.FieldRefAccess<PlayerTumble, bool>("isTumbling");

		private static readonly Vector3 ExtraLifeRespawnPosition = new Vector3(0f, 0.5f, 0f);

		public ConfigEntry<int> RevivePercent { get; protected set; }

		public ExtraLifeUpgrade(bool enabled, float upgradeAmount, bool exponential, float exponentialAmount, ConfigFile config, AssetBundle assetBundle, int revivePercent, float priceMultiplier)
			: base("Extra Life", "assets/repo/mods/resources/items/items/item upgrade extra life lib.asset", enabled, upgradeAmount, exponential, exponentialAmount, config, assetBundle, priceMultiplier, configureAmount: false, canBeExponential: true, (int?)null)
		{
			RevivePercent = config.Bind<int>("Extra Life Upgrade", "revivePercent", revivePercent, "Percentage of health to recover when revived");
		}

		public override float Calculate(float value, PlayerAvatar player, int level)
		{
			return UpgradeBase<float>.DefaultCalculateFloatIncrease(this, "ExtraLife", value, player, level);
		}

		internal override void InitUpgrade(PlayerAvatar player, int level)
		{
			base.InitUpgrade(player, level);
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				SLRUpgradePack.Instance.Actions["Extra Life"] = ExtraLifeUpdateAction;
			}
		}

		private void ExtraLifeUpdateAction()
		{
			if (!base.UpgradeEnabled.Value || base.UpgradeRegister == null || !Object.op_Implicit((Object)(object)RoundDirector.instance) || !_extractionPointsFetchedRef.Invoke(RoundDirector.instance))
			{
				return;
			}
			foreach (var activePlayerLevel in GetActivePlayerLevels())
			{
				var (val, _) = activePlayerLevel;
				if (activePlayerLevel.Level <= 0 || !Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.playerHealth))
				{
					continue;
				}
				string key = SemiFunc.PlayerGetSteamID(val);
				PlayerDeathHead val2 = _playerDeathHeadRef.Invoke(val);
				if (Object.op_Implicit((Object)(object)val2))
				{
					Coroutine value;
					bool flag = _reviveCoroutines.TryGetValue(key, out value);
					if (_deadSetRef.Invoke(val) && _healthRef.Invoke(val.playerHealth) == 0 && !IsExtractionReviveBlocked(val2) && (!flag || value == null))
					{
						_reviveCoroutines[key] = ((MonoBehaviour)SLRUpgradePack.Instance).StartCoroutine(BeginReviving(val));
					}
				}
			}
		}

		private IEnumerator BeginReviving(PlayerAvatar player)
		{
			string playerID = SemiFunc.PlayerGetSteamID(player);
			try
			{
				yield return (object)new WaitForEndOfFrame();
				if (!Object.op_Implicit((Object)(object)player) || !Object.op_Implicit((Object)(object)player.playerHealth) || !base.UpgradeEnabled.Value || base.UpgradeRegister.GetLevel(player) == 0 || !_deadSetRef.Invoke(player) || _healthRef.Invoke(player.playerHealth) != 0)
				{
					yield break;
				}
				PlayerDeathHead val = _playerDeathHeadRef.Invoke(player);
				if (!Object.op_Implicit((Object)(object)val))
				{
					yield break;
				}
				SLRUpgradePack.Logger.LogInfo((object)("Preparing to revive " + SemiFunc.PlayerGetName(player)));
				if (IsExtractionReviveBlocked(val))
				{
					SLRUpgradePack.Logger.LogInfo((object)"Delaying extra life because the extraction point can revive this dead head");
					yield break;
				}
				ReviveLogic(player);
				while (Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)player.playerHealth) && _deadSetRef.Invoke(player) && _healthRef.Invoke(player.playerHealth) == 0)
				{
					yield return null;
				}
			}
			finally
			{
				_reviveCoroutines.Remove(playerID);
			}
		}

		private bool IsExtractionReviveBlocked(PlayerDeathHead playerHead)
		{
			if (!Object.op_Implicit((Object)(object)playerHead))
			{
				return false;
			}
			return _inExtractionPointRef.Invoke(playerHead);
		}

		private void ReviveLogic(PlayerAvatar player)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			ExtraLifeUpgrade extraLifeUpgradeInstance = SLRUpgradePack.ExtraLifeUpgradeInstance;
			PlayerDeathHead val = _playerDeathHeadRef.Invoke(player);
			PhysGrabObject val2 = (Object.op_Implicit((Object)(object)val) ? _physGrabObjectRef.Invoke(val) : null);
			if (Object.op_Implicit((Object)(object)val2))
			{
				val2.centerPoint = ExtraLifeRespawnPosition + Vector3.up * 0.25f;
			}
			PlayerTumble val3 = _playerTumbleRef.Invoke(player);
			if (Object.op_Implicit((Object)(object)val3) && _isTumblingRef.Invoke(val3))
			{
				val3.TumbleSet(false, false);
			}
			try
			{
				player.Revive(false);
			}
			catch
			{
			}
			player.Spawn(ExtraLifeRespawnPosition, Quaternion.identity);
			player.playerHealth.HealOther(Mathf.FloorToInt((float)MaxHealthRef.Invoke(player.playerHealth) * ((float)extraLifeUpgradeInstance.RevivePercent.Value / 100f)), true);
			extraLifeUpgradeInstance.UpgradeRegister.RemoveLevel(player, 1);
		}
	}
	public class HeartOfGoldUpgrade : UpgradeBase<float>
	{
		internal const byte RegistrationAckMessageType = 1;

		public static NetworkedEvent HeartOfGoldEvent = new NetworkedEvent("Heart Of Gold", (Action<EventData>)HeartOfGoldAction);

		public ConfigEntry<float> BaseHeartValue { get; protected set; }

		internal Dictionary<string, GoldenHeart> GoldenHearts { get; set; } = new Dictionary<string, GoldenHeart>();

		private static void HeartOfGoldAction(EventData e)
		{
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			NetworkMessage networkMessage = NetworkMessage.FromByteArray((byte[])e.CustomData);
			HeartOfGoldUpgrade heartOfGoldUpgradeInstance = SLRUpgradePack.HeartOfGoldUpgradeInstance;
			if (networkMessage.MessageType == 1)
			{
				if (!string.IsNullOrEmpty(networkMessage.PlayerId) && networkMessage.PhotonId.HasValue && heartOfGoldUpgradeInstance.GoldenHearts.TryGetValue(networkMessage.PlayerId, out GoldenHeart value) && Object.op_Implicit((Object)(object)value))
				{
					value.RecordRegistrationAck(networkMessage.PhotonId.Value, e.Sender);
				}
			}
			else
			{
				if (networkMessage.MessageType != 0 || string.IsNullOrEmpty(networkMessage.PlayerId) || !networkMessage.PhotonId.HasValue)
				{
					return;
				}
				PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(networkMessage.PlayerId);
				if (Object.op_Implicit((Object)(object)val))
				{
					if (!heartOfGoldUpgradeInstance.GoldenHearts.TryGetValue(networkMessage.PlayerId, out GoldenHeart value2) || !Object.op_Implicit((Object)(object)value2))
					{
						heartOfGoldUpgradeInstance.InitUpgrade(val, heartOfGoldUpgradeInstance.UpgradeRegister.GetLevel(val));
						value2 = heartOfGoldUpgradeInstance.GoldenHearts[networkMessage.PlayerId];
					}
					if (value2.SetViewId(networkMessage.PhotonId.Value))
					{
						NetworkMessage msg = new NetworkMessage
						{
							PlayerId = networkMessage.PlayerId,
							PhotonId = networkMessage.PhotonId,
							MessageType = 1
						};
						NetworkedEvent heartOfGoldEvent = HeartOfGoldEvent;
						byte[] array = NetworkMessage.ToByteArray(msg);
						RaiseEventOptions val2 = new RaiseEventOptions();
						val2.TargetActors = new int[1] { e.Sender };
						heartOfGoldEvent.RaiseEvent((object)array, val2, SendOptions.SendReliable);
					}
				}
			}
		}

		public HeartOfGoldUpgrade(bool enabled, float upgradeAmount, bool exponential, float exponentialAmount, ConfigFile config, AssetBundle assetBundle, float baseValue, float priceMultiplier)
			: base("Heart Of Gold", "assets/repo/mods/resources/items/items/item upgrade heart of gold lib.asset", enabled, upgradeAmount, exponential, exponentialAmount, config, assetBundle, priceMultiplier, configureAmount: true, canBeExponential: true, (int?)null)
		{
			BaseHeartValue = config.Bind<float>("Heart Of Gold Upgrade", "Base Value", baseValue, "Base value to scale by player health");
		}

		public override float Calculate(float value, PlayerAvatar player, int level)
		{
			return UpgradeBase<float>.DefaultCalculateFloatIncrease(this, "HeartOfGold", value, player, level);
		}

		internal override void InitUpgrade(PlayerAvatar player, int level)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			base.InitUpgrade(player, level);
			if (GoldenHearts.TryGetValue(SemiFunc.PlayerGetSteamID(player), out GoldenHeart value))
			{
				Object.Destroy((Object)(object)value);
			}
			value = new GameObject("Golden Heart: " + SemiFunc.PlayerGetName(player)).AddComponent<GoldenHeart>();
			value.player = player;
			GoldenHearts[SemiFunc.PlayerGetSteamID(player)] = value;
		}
	}
	public class GoldenHeart : MonoBehaviour
	{
		private const float RegistrationRetryInterval = 1f;

		private bool createRpcPending;

		private bool createRequested;

		private bool valueSyncPending = true;

		private bool hasQueuedMasterBaseValue;

		private float queuedMasterBaseValue;

		private bool hasQueuedFinalValue;

		private float queuedFinalBaseValue;

		private float queuedFinalValue;

		private float pendingBaseValue;

		private float nextRegistrationRetryTime;

		private readonly HashSet<int> registeredActorNumbers = new HashSet<int>();

		private readonly HashSet<int> knownRemoteActorNumbers = new HashSet<int>();

		private PhotonView photonView;

		private readonly FieldRef<PlayerHealth, int> _healthRef = AccessTools.FieldRefAccess<PlayerHealth, int>("health");

		private static readonly FieldRef<RoundDirector, bool>? ExtractionPointsFetchedRef = AccessTools.FieldRefAccess<RoundDirector, bool>("extractionPointsFetched");

		private readonly FieldRef<ValuableObject, PhysAttribute> _physAttributePresetRef = AccessTools.FieldRefAccess<ValuableObject, PhysAttribute>("physAttributePreset");

		private readonly FieldRef<ValuableObject, bool> _discoveredRef = AccessTools.FieldRefAccess<ValuableObject, bool>("discovered");

		private readonly FieldRef<ValuableObject, float> _dollarValueCurrentRef = AccessTools.FieldRefAccess<ValuableObject, float>("dollarValueCurrent");

		internal PlayerAvatar player { get; set; }

		internal bool Pause { get; set; }

		internal int lastLevel { get; set; } = -1;

		internal int lastHealth { get; set; } = -1;

		internal ValuableObject? ValuableComponent { get; private set; }

		private void Awake()
		{
			if (!((Component)this).TryGetComponent<PhotonView>(ref photonView))
			{
				photonView = ((Component)this).gameObject.AddComponent<PhotonView>();
			}
		}

		public void DestroyOnlyMe()
		{
			if (Object.op_Implicit((Object)(object)ValuableComponent) || createRequested)
			{
				if (SemiFunc.IsMultiplayer())
				{
					photonView.RPC("DestroyOnlyMeRPC", (RpcTarget)0, Array.Empty<object>());
				}
				else
				{
					DestroyOnlyMeRPC();
				}
			}
		}

		[PunRPC]
		private void DestroyOnlyMeRPC()
		{
			createRequested = false;
			createRpcPending = false;
			hasQueuedMasterBaseValue = false;
			hasQueuedFinalValue = false;
			ValuableObject valuableComponent = ValuableComponent;
			if (!((Object)(object)valuableComponent == (Object)null) && Object.op_Implicit((Object)(object)valuableComponent))
			{
				SLRUpgradePack.Logger.LogInfo((object)("Components in GoldenHeart: " + string.Join(',', from v in ((Component)this).GetComponents<Object>()
					select ((object)v).ToString())));
				PhysGrabObject component = ((Component)valuableComponent).GetComponent<PhysGrabObject>();
				if (Object.op_Implicit((Object)(object)RoundDirector.instance) && Object.op_Implicit((Object)(object)component))
				{
					RoundDirector.instance.PhysGrabObjectRemove(component);
				}
				Object.Destroy((Object)(object)valuableComponent);
				ValuableComponent = null;
			}
		}

		public void CreateOnlyMe()
		{
			if (!Object.op_Implicit((Object)(object)ValuableComponent) && !createRpcPending && !createRequested && !Pause)
			{
				createRpcPending = true;
				if (SemiFunc.IsMultiplayer())
				{
					photonView.RPC("CreateOnlyMeRPC", (RpcTarget)0, Array.Empty<object>());
				}
				else
				{
					CreateOnlyMeRPC();
				}
			}
		}

		[PunRPC]
		private void CreateOnlyMeRPC()
		{
			createRpcPending = false;
			if (Object.op_Implicit((Object)(object)ValuableComponent))
			{
				createRequested = false;
				return;
			}
			createRequested = true;
			TryCreateValuableComponent();
		}

		private void TryCreateValuableComponent()
		{
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Expected O, but got Unknown
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			if (createRequested && !Pause && Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)player.healthGrab) && Object.op_Implicit((Object)(object)player.playerHealth) && !Object.op_Implicit((Object)(object)ValuableComponent))
			{
				HeartOfGoldUpgrade heartOfGoldUpgradeInstance = SLRUpgradePack.HeartOfGoldUpgradeInstance;
				SLRUpgradePack.Logger.LogInfo((object)("Adding valuable component to player " + SemiFunc.PlayerGetName(player)));
				ValuableComponent = ((Component)player.healthGrab).gameObject.AddComponent<ValuableObject>();
				ValuableObjectValuePatch.MarkExcludedFromExtractionGoal(ValuableComponent);
				SLRUpgradePack.Logger.LogInfo((object)("Valuable component " + SemiFunc.PlayerGetName(player) + " instantiated at " + JsonConvert.SerializeObject((object)((Component)ValuableComponent).transform)));
				ValuableComponent.valuePreset = ScriptableObject.CreateInstance<Value>();
				ValuableComponent.valuePreset.valueMin = (ValuableComponent.valuePreset.valueMax = heartOfGoldUpgradeInstance.Calculate((float)_healthRef.Invoke(player.playerHealth) * heartOfGoldUpgradeInstance.BaseHeartValue.Value, player, heartOfGoldUpgradeInstance.UpgradeRegister.GetLevel(player)));
				ValuableComponent.durabilityPreset = ScriptableObject.CreateInstance<Durability>();
				ValuableComponent.durabilityPreset.durability = 999f;
				ValuableComponent.durabilityPreset.fragility = 0f;
				ValuableComponent.physAttributePreset = ScriptableObject.CreateInstance<PhysAttribute>();
				((Component)ValuableComponent).transform.localScale = Vector3.zero;
				((Component)ValuableComponent).transform.SetParent(((Component)player).transform, false);
				((Component)ValuableComponent).gameObject.AddComponent<Rigidbody>();
				PhotonTransformView item = ((Component)ValuableComponent).gameObject.AddComponent<PhotonTransformView>();
				PhysGrabObjectImpactDetector val = ((Component)ValuableComponent).gameObject.AddComponent<PhysGrabObjectImpactDetector>();
				PhysGrabObject val2 = ((Component)ValuableComponent).gameObject.AddComponent<PhysGrabObject>();
				((Component)ValuableComponent).gameObject.AddComponent<PhotonView>().ObservedComponents = new List<Component>(3)
				{
					(Component)(object)val2,
					(Component)(object)val,
					(Component)(object)item
				};
				((Behaviour)val).enabled = false;
				((Behaviour)val2).enabled = false;
				((Component)val2).transform.localScale = Vector3.zero;
				((Component)val2).transform.SetParent(((Component)ValuableComponent).transform, false);
				((Component)val).transform.localScale = Vector3.zero;
				((Component)val).transform.SetParent(((Component)ValuableComponent).transform, false);
				((Component)ValuableComponent).gameObject.AddComponent<RoomVolumeCheck>().CurrentRooms = new List<RoomVolume>();
				ValuableObject? valuableComponent = ValuableComponent;
				Gradient val3 = new Gradient();
				val3.alphaKeys = (GradientAlphaKey[])(object)new GradientAlphaKey[1]
				{
					new GradientAlphaKey(1f, 0f)
				};
				val3.colorKeys = (GradientColorKey[])(object)new GradientColorKey[1]
				{
					new GradientColorKey(Color.yellow, 0f)
				};
				valuableComponent.particleColors = val3;
				_physAttributePresetRef.Invoke(ValuableComponent) = ScriptableObject.CreateInstance<PhysAttribute>();
				int num = (lastLevel = -1);
				lastHealth = num;
				createRequested = false;
				if (hasQueuedMasterBaseValue)
				{
					float baseValue = queuedMasterBaseValue;
					hasQueuedMasterBaseValue = false;
					ApplyHeartValue(baseValue);
				}
				else if (hasQueuedFinalValue)
				{
					float baseValue2 = queuedFinalBaseValue;
					float finalValue = queuedFinalValue;
					hasQueuedFinalValue = false;
					ApplySyncedHeartValue(baseValue2, finalValue);
				}
			}
		}

		private void Update()
		{
			if (!Object.op_Implicit((Object)(object)player))
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			if (createRequested)
			{
				TryCreateValuableComponent();
			}
			if ((Object)(object)SemiFunc.PlayerAvatarLocal() != (Object)(object)player || !Object.op_Implicit((Object)(object)player.playerHealth) || !Object.op_Implicit((Object)(object)RoundDirector.instance) || !ExtractionPointsFetchedRef.Invoke(RoundDirector.instance))
			{
				return;
			}
			HeartOfGoldUpgrade heartOfGoldUpgradeInstance = SLRUpgradePack.HeartOfGoldUpgradeInstance;
			if (!heartOfGoldUpgradeInstance.UpgradeEnabled.Value || Pause)
			{
				return;
			}
			int level = heartOfGoldUpgradeInstance.UpgradeRegister.GetLevel(player);
			int num = _healthRef.Invoke(player.playerHealth);
			if (level == 0 || num == 0)
			{
				return;
			}
			if (lastLevel != level || lastHealth != num)
			{
				lastLevel = level;
				lastHealth = num;
				valueSyncPending = true;
			}
			float num2 = (pendingBaseValue = heartOfGoldUpgradeInstance.Calculate((float)num * heartOfGoldUpgradeInstance.BaseHeartValue.Value, player, level));
			if (SemiFunc.IsMultiplayer() && !EnsureRemoteViewsRegistered())
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)ValuableComponent))
			{
				CreateOnlyMe();
			}
			if (Object.op_Implicit((Object)(object)ValuableComponent) && valueSyncPending)
			{
				if (!SemiFunc.IsMultiplayer())
				{
					ApplyHeartValue(num2);
				}
				else
				{
					photonView.RPC("UpdateOnlyMeRPC", (RpcTarget)2, new object[1] { num2 });
				}
				valueSyncPending = false;
			}
		}

		private bool EnsureRemoteViewsRegistered()
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if (photonView.ViewID == 0)
			{
				PhotonNetwork.AllocateViewID(photonView);
				if (photonView.ViewID == 0)
				{
					return false;
				}
				registeredActorNumbers.Clear();
				knownRemoteActorNumbers.Clear();
			}
			HashSet<int> hashSet = PhotonNetwork.PlayerListOthers.Select((Player remotePlayer) => remotePlayer.ActorNumber).ToHashSet();
			if (!knownRemoteActorNumbers.SetEquals(hashSet))
			{
				knownRemoteActorNumbers.Clear();
				knownRemoteActorNumbers.UnionWith(hashSet);
				registeredActorNumbers.IntersectWith(hashSet);
				valueSyncPending = true;
			}
			if (hashSet.All(registeredActorNumbers.Contains))
			{
				return true;
			}
			if (Time.unscaledTime < nextRegistrationRetryTime)
			{
				return false;
			}
			NetworkMessage msg = new NetworkMessage
			{
				PlayerId = SemiFunc.PlayerGetSteamID(player),
				PhotonId = photonView.ViewID
			};
			HeartOfGoldUpgrade.HeartOfGoldEvent.RaiseEvent((object)NetworkMessage.ToByteArray(msg), NetworkingEvents.RaiseOthers, SendOptions.SendReliable);
			nextRegistrationRetryTime = Time.unscaledTime + 1f;
			return false;
		}

		internal void RecordRegistrationAck(int photonId, int actorNumber)
		{
			if (photonView.ViewID == photonId && actorNumber > 0)
			{
				registeredActorNumbers.Add(actorNumber);
			}
		}

		[PunRPC]
		private void UpdateOnlyMeRPC(float baseValue)
		{
			if (SemiFunc.IsMasterClient())
			{
				ApplyHeartValue(baseValue);
			}
		}

		private void ApplyHeartValue(float baseValue)
		{
			ValuableObject valuableComponent = ValuableComponent;
			if ((Object)(object)valuableComponent == (Object)null || !Object.op_Implicit((Object)(object)valuableComponent))
			{
				queuedMasterBaseValue = baseValue;
				hasQueuedMasterBaseValue = true;
				createRequested = true;
				TryCreateValuableComponent();
				return;
			}
			if (!_discoveredRef.Invoke(valuableComponent))
			{
				valuableComponent.Discover((State)0);
			}
			valuableComponent.valuePreset.valueMin = baseValue;
			valuableComponent.valuePreset.valueMax = baseValue;
			_dollarValueCurrentRef.Invoke(valuableComponent) = baseValue;
			ValuableObjectValuePatch.Action(valuableComponent);
			float num = _dollarValueCurrentRef.Invoke(valuableComponent);
			valuableComponent.valuePreset.valueMin = baseValue;
			valuableComponent.valuePreset.valueMax = baseValue;
			if (!SemiFunc.IsMultiplayer())
			{
				HeartOfGoldValueSetRPC(baseValue, num);
				return;
			}
			photonView.RPC("HeartOfGoldValueSetRPC", (RpcTarget)0, new object[2] { baseValue, num });
		}

		[PunRPC]
		private void HeartOfGoldValueSetRPC(float baseValue, float finalValue)
		{
			ValuableObject valuableComponent = ValuableComponent;
			if ((Object)(object)valuableComponent == (Object)null || !Object.op_Implicit((Object)(object)valuableComponent))
			{
				queuedFinalBaseValue = baseValue;
				queuedFinalValue = finalValue;
				hasQueuedFinalValue = true;
				createRequested = true;
				TryCreateValuableComponent();
			}
			else
			{
				ApplySyncedHeartValue(baseValue, finalValue);
			}
		}

		private void ApplySyncedHeartValue(float baseValue, float finalValue)
		{
			ValuableObject valuableComponent = ValuableComponent;
			if (!((Object)(object)valuableComponent == (Object)null) && Object.op_Implicit((Object)(object)valuableComponent))
			{
				if (!_discoveredRef.Invoke(valuableComponent))
				{
					valuableComponent.Discover((State)0);
				}
				valuableComponent.valuePreset.valueMin = baseValue;
				valuableComponent.valuePreset.valueMax = baseValue;
				_dollarValueCurrentRef.Invoke(valuableComponent) = finalValue;
			}
		}

		public void PauseLogic(bool pause)
		{
			if (!SemiFunc.IsMultiplayer())
			{
				PauseLogicRPC(pause);
				return;
			}
			photonView.RPC("PauseLogicRPC", (RpcTarget)0, new object[1] { pause });
		}

		[PunRPC]
		private void PauseLogicRPC(bool pause)
		{
			Pause = pause;
		}

		internal bool SetViewId(int id)
		{
			if (id <= 0 || !Object.op_Implicit((Object)(object)photonView))
			{
				return false;
			}
			if (photonView.ViewID != id)
			{
				photonView.ViewID = id;
				if (Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)player.photonView))
				{
					photonView.TransferOwnership(player.photonView.Owner);
				}
			}
			return photonView.ViewID == id;
		}
	}
	[HarmonyPatch(typeof(ExtractionPoint))]
	public class ExtractionPointDestroyPatch
	{
		private static readonly FieldRef<RoundDirector, int>? TotalHaulRef = AccessTools.FieldRefAccess<RoundDirector, int>("totalHaul");

		private static readonly FieldRef<ValuableObject, float>? DollarValueCurrentRef = AccessTools.FieldRefAccess<ValuableObject, float>("dollarValueCurrent");

		private static readonly FieldRef<ProgressionManager, float>? HaulingPointsRef = AccessTools.FieldRefAccess<ProgressionManager, float>("roundPointsHauling");

		private static readonly MethodInfo ExtractCosmeticMethod = AccessTools.Method(typeof(ExtractionPoint), "ExtractCosmeticWorldObject", new Type[1] { typeof(bool) }, (Type[])null);

		private static bool TryGetGoldenHeart(HeartOfGoldUpgrade upgrade, ValuableObject valuableObject, out GoldenHeart goldenHeart)
		{
			foreach (GoldenHeart value in upgrade.GoldenHearts.Values)
			{
				if (Object.op_Implicit((Object)(object)value) && (Object)(object)value.ValuableComponent == (Object)(object)valuableObject)
				{
					goldenHeart = value;
					return true;
				}
			}
			goldenHeart = null;
			return false;
		}

		private static void AddGoldenHeartHaulValue(ExtractionPoint extractionPoint, ValuableObject valuableObject)
		{
			float num = DollarValueCurrentRef.Invoke(valuableObject);
			TotalHaulRef.Invoke(RoundDirector.instance) += (int)num;
			float localPlayerHaulScore = valuableObject.GetLocalPlayerHaulScore(((Component)extractionPoint).gameObject);
			if (localPlayerHaulScore > 0f)
			{
				HaulingPointsRef.Invoke(ProgressionManager.instance) += num / 10f * localPlayerHaulScore;
			}
		}

		[HarmonyPatch("DestroyAllPhysObjectsInHaulList")]
		[HarmonyPrefix]
		private static bool DestroyAllPrefix(ExtractionPoint __instance)
		{
			HeartOfGoldUpgrade heartOfGoldUpgradeInstance = SLRUpgradePack.HeartOfGoldUpgradeInstance;
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !heartOfGoldUpgradeInstance.UpgradeEnabled.Value)
			{
				return true;
			}
			List<GameObject> dollarHaulList = RoundDirector.instance.dollarHaulList;
			PhysGrabObject val = default(PhysGrabObject);
			ValuableObject val2 = default(ValuableObject);
			foreach (GameObject item in new List<GameObject>(dollarHaulList))
			{
				if (Object.op_Implicit((Object)(object)item) && item.TryGetComponent<PhysGrabObject>(ref val) && Object.op_Implicit((Object)(object)val) && item.TryGetComponent<ValuableObject>(ref val2) && Object.op_Implicit((Object)(object)val2) && TryGetGoldenHeart(heartOfGoldUpgradeInstance, val2, out GoldenHeart goldenHeart))
				{
					AddGoldenHeartHaulValue(__instance, val2);
					dollarHaulList.Remove(item);
					SLRUpgradePack.Logger.LogInfo((object)("Player " + SemiFunc.PlayerGetName(goldenHeart.player) + " in extraction zone counts as valuable"));
					goldenHeart.PauseLogic(pause: true);
					goldenHeart.DestroyOnlyMe();
				}
			}
			return true;
		}

		[HarmonyPatch("DestroyTheFirstPhysObjectsInHaulList")]
		[HarmonyPrefix]
		private static bool DestroyFirstPrefix(ExtractionPoint __instance)
		{
			HeartOfGoldUpgrade heartOfGoldUpgradeInstance = SLRUpgradePack.HeartOfGoldUpgradeInstance;
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !heartOfGoldUpgradeInstance.UpgradeEnabled.Value)
			{
				return true;
			}
			if ((bool)ExtractCosmeticMethod.Invoke(__instance, new object[1] { false }))
			{
				return false;
			}
			List<GameObject> dollarHaulList = RoundDirector.instance.dollarHaulList;
			PhysGrabObject val = default(PhysGrabObject);
			ValuableObject val2 = default(ValuableObject);
			if (dollarHaulList.Count == 0 || !Object.op_Implicit((Object)(object)dollarHaulList[0]) || !dollarHaulList[0].TryGetComponent<PhysGrabObject>(ref val) || !Object.op_Implicit((Object)(object)val) || !dollarHaulList[0].TryGetComponent<ValuableObject>(ref val2) || !Object.op_Implicit((Object)(object)val2) || !TryGetGoldenHeart(heartOfGoldUpgradeInstance, val2, out GoldenHeart goldenHeart))
			{
				return true;
			}
			AddGoldenHeartHaulValue(__instance, val2);
			dollarHaulList.RemoveAt(0);
			SLRUpgradePack.Logger.LogInfo((object)("Player " + SemiFunc.PlayerGetName(goldenHeart.player) + " in extraction zone counts as valuable"));
			goldenHeart.PauseLogic(pause: true);
			goldenHeart.DestroyOnlyMe();
			return false;
		}
	}
	[HarmonyPatch(typeof(RoundDirector), "Update")]
	public class RoundDirectorUpdatePatch
	{
		private static void Prefix(RoundDirector __instance)
		{
			ValuableObject val = default(ValuableObject);
			__instance.dollarHaulList.RemoveAll((GameObject go) => (Object)(object)go == (Object)null || !go.TryGetComponent<ValuableObject>(ref val) || !Object.op_Implicit((Object)(object)val));
		}
	}
	public class InventorySlotUpgrade : UpgradeBase<int>
	{
		internal static readonly Dictionary<string, Dictionary<int, int>> serverMonitoredInventoryItems = new Dictionary<string, Dictionary<int, int>>();

		private Coroutine? _deferredInventoryRefresh;

		public Keybind ItemSlot4 { get; set; }

		public Keybind ItemSlot5 { get; set; }

		public Keybind ItemSlot6 { get; set; }

		public Keybind ItemSlot7 { get; set; }

		public Keybind ItemSlot8 { get; set; }

		public Keybind ItemSlot9 { get; set; }

		internal string? BoundPlayer { get; set; }

		public Inventory? InventoryRef { get; set; }

		public InventoryUI? UIRef { get; set; }

		public InventorySlotUpgrade(bool enabled, int upgradeAmount, ConfigFile config, AssetBundle assetBundle, float priceMultiplier)
			: base("Inventory Slot", "assets/repo/mods/resources/items/items/item upgrade inventory slot lib.asset", enabled, upgradeAmount, exponential: false, 0, config, assetBundle, priceMultiplier, configureAmount: false, canBeExponential: false, (int?)6)
		{
			AccessTools.Method(typeof(Keybinds), "Register", (Type[])null, (Type[])null);
			((MemberInfo)typeof(SLRUpgradePack)).GetCustomAttribute<BepInPlugin>();
			ItemSlot4 = Keybinds.Bind("Item slots", "Item Slot 4", "<keyboard>/z");
			ItemSlot5 = Keybinds.Bind("Item Slots", "Item Slot 5", "<keyboard>/x");
			ItemSlot6 = Keybinds.Bind("Item Slots", "Item Slot 6", "<keyboard>/c");
			ItemSlot7 = Keybinds.Bind("Item Slots", "Item Slot 7", "<keyboard>/n");
			ItemSlot8 = Keybinds.Bind("Item Slots", "Item Slot 8", "<keyboard>/m");
			ItemSlot9 = Keybinds.Bind("Item Slots", "Item Slot 9", "<keyboard>/,");
		}

		public override int Calculate(int value, PlayerAvatar player, int level)
		{
			return value + level;
		}

		internal override void InitUpgrade(PlayerAvatar player, int level)
		{
			base.InitUpgrade(player, level);
			if ((Object)(object)player == (Object)(object)SemiFunc.PlayerAvatarLocal())
			{
				BoundPlayer = SemiFunc.PlayerGetSteamID(player);
				RefreshLocalInventory();
			}
		}

		internal override void UseUpgrade(PlayerAvatar player, int level)
		{
			base.UseUpgrade(player, level);
			if ((Object)(object)player == (Object)(object)SemiFunc.PlayerAvatarLocal())
			{
				BoundPlayer = SemiFunc.PlayerGetSteamID(player);
				RefreshLocalInventory();
				ScheduleLocalInventoryRefresh();
			}
		}

		private void RefreshLocalInventory()
		{
			if (Object.op_Implicit((Object)(object)InventoryRef))
			{
				InventoryStartPatch.Postfix(InventoryRef);
			}
			if (Object.op_Implicit((Object)(object)UIRef))
			{
				InventoryUIStartPatch.Postfix(UIRef);
			}
		}

		private void ScheduleLocalInventoryRefresh()
		{
			if (_deferredInventoryRefresh != null)
			{
				((MonoBehaviour)SLRUpgradePack.Instance).StopCoroutine(_deferredInventoryRefresh);
			}
			_deferredInventoryRefresh = ((MonoBehaviour)SLRUpgradePack.Instance).StartCoroutine(RefreshLocalInventoryNextFrame());
		}

		private IEnumerator RefreshLocalInventoryNextFrame()
		{
			yield return null;
			_deferredInventoryRefresh = null;
			RefreshLocalInventory();
		}
	}
	[HarmonyPatch(typeof(InventoryUI), "Start")]
	public class InventoryUIStartPatch
	{
		private static readonly FieldRef<InventoryUI, List<GameObject>> allChildren = AccessTools.FieldRefAccess<InventoryUI, List<GameObject>>("allChildren");

		private static readonly FieldRef<SemiUI, Vector3> initialPosition = AccessTools.FieldRefAccess<SemiUI, Vector3>("initialPosition");

		private static readonly FieldRef<SemiUI, Vector2> hidePositionCurrent = AccessTools.FieldRefAccess<SemiUI, Vector2>("hidePositionCurrent");

		private static readonly FieldRef<InventorySpot, ItemEquippable> currentItem = AccessTools.FieldRefAccess<InventorySpot, ItemEquippable>("<CurrentItem>k__BackingField");

		private static readonly FieldRef<BatteryVisualLogic, ItemBattery> previousItemBattery = AccessTools.FieldRefAccess<BatteryVisualLogic, ItemBattery>("itemBatteryPrev");

		private static readonly FieldRef<BatteryVisualLogic, List<GameObject>> batteryBars = AccessTools.FieldRefAccess<BatteryVisualLogic, List<GameObject>>("bars");

		private static readonly FieldRef<InventorySpot, BatteryVisualLogic> inventorySpotBatteryVisual = AccessTools.FieldRefAccess<InventorySpot, BatteryVisualLogic>("batteryVisualLogic");

		private static readonly FieldRef<BatteryVisualLogic, Vector3> batteryTargetPosition = AccessTools.FieldRefAccess<BatteryVisualLogic, Vector3>("targetPosition");

		private static readonly FieldRef<BatteryVisualLogic, Vector3> batteryTargetPositionOriginal = AccessTools.FieldRefAccess<BatteryVisualLogic, Vector3>("targetPositionOriginal");

		private static readonly FieldRef<BatteryVisualLogic, float> batteryTargetScale = AccessTools.FieldRefAccess<BatteryVisualLogic, float>("targetScale");

		private static readonly FieldRef<BatteryVisualLogic, float> batteryTargetScaleOriginal = AccessTools.FieldRefAccess<BatteryVisualLogic, float>("targetScaleOriginal");

		private static readonly FieldRef<BatteryVisualLogic, float> batteryTargetRotation = AccessTools.FieldRefAccess<BatteryVisualLogic, float>("targetRotation");

		private static readonly FieldRef<BatteryVisualLogic, float> batteryTargetRotationOriginal = AccessTools.FieldRefAccess<BatteryVisualLogic, float>("targetRotationOriginal");

		private static readonly FieldRef<BatteryVisualLogic, bool> batteryDoOutro = AccessTools.FieldRefAccess<BatteryVisualLogic, bool>("doOutro");

		private static readonly FieldRef<BatteryVisualLogic, SpringFloat> batterySpringScale = AccessTools.FieldRefAccess<BatteryVisualLogic, SpringFloat>("springScale");

		private static readonly FieldRef<BatteryVisualLogic, SpringFloat> batterySpringRotation = AccessTools.FieldRefAccess<BatteryVisualLogic, SpringFloat>("springRotation");

		private static readonly FieldRef<BatteryVisualLogic, SpringVector3> batterySpringPosition = AccessTools.FieldRefAccess<BatteryVisualLogic, SpringVector3>("springPosition");

		private static readonly FieldRef<SpringFloat, float> springFloatDamping = AccessTools.FieldRefAccess<SpringFloat, float>("damping");

		private static readonly FieldRef<SpringFloat, float> springFloatSpeed = AccessTools.FieldRefAccess<SpringFloat, float>("speed");

		private static readonly FieldRef<SpringFloat, float> springFloatLastPosition = AccessTools.FieldRefAccess<SpringFloat, float>("lastPosition");

		private static readonly FieldRef<SpringVector3, float> springVectorDamping = AccessTools.FieldRefAccess<SpringVector3, float>("damping");

		private static readonly FieldRef<SpringVector3, float> springVectorSpeed = AccessTools.FieldRefAccess<SpringVector3, float>("speed");

		private static readonly FieldRef<SpringVector3, Vector3> springVectorLastPosition = AccessTools.FieldRefAccess<SpringVector3, Vector3>("lastPosition");

		private static readonly FieldRef<InventoryBattery, Vector3> originalBatteryScale = AccessTools.FieldRefAccess<InventoryBattery, Vector3>("originalLocalScale");

		private static readonly Dictionary<int, (int frame, int batteryId)> batteryVisualRefreshes = new Dictionary<int, (int, int)>();

		private static readonly Dictionary<int, (Vector3 position, float scale, float rotation)> clonedBatteryVisualsPendingStart = new Dictionary<int, (Vector3, float, float)>();

		private static int batteryVisualRefreshFrame = -1;

		internal static void Postfix(InventoryUI __instance)
		{
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: 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_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: 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_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: 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_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ac: Expected O, but got Unknown
			//IL_0572: Unknown result type (might be due to invalid IL or missing references)
			//IL_0574: Unknown result type (might be due to invalid IL or missing references)
			//IL_0587: Unknown result type (might be due to invalid IL or missing references)
			//IL_058c: Unknown result type (might be due to invalid IL or missing references)
			//IL_058e: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_046f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_0475: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			InventorySlotUpgrade inventorySlotUpgradeInstance = SLRUpgradePack.InventorySlotUpgradeInstance;
			inventorySlotUpgradeInstance.UIRef = __instance;
			if (!inventorySlotUpgradeInstance.UpgradeEnabled.Value || inventorySlotUpgradeInstance.BoundPlayer == null)
			{
				return;
			}
			int num = inventorySlotUpgradeInstance.Calculate(3, SemiFunc.PlayerAvatarLocal(), inventorySlotUpgradeInstance.UpgradeRegister.GetLevel(inventorySlotUpgradeInstance.BoundPlayer));
			if (num <= 3)
			{
				return;
			}
			SLRUpgradePack.Logger.LogInfo((object)$"Redrawing for {num} slots");
			float num2 = (float)(-(num * 40)) / 2f + 20f;
			Dictionary<int, InventorySpot> dictionary = (from spot in ((Component)__instance).GetComponentsInChildren<InventorySpot>(true)
				where Object.op_Implicit((Object)(object)spot)
				group spot by spot.inventorySpotIndex).ToDictionary((IGrouping<int, InventorySpot> group) => group.Key, (IGrouping<int, InventorySpot> group) => group.First());
			if (!dictionary.TryGetValue(0, out var templateSpot) || !Object.op_Implicit((Object)(object)templateSpot))
			{
				SLRUpgradePack.Logger.LogWarning((object)"Could not resize inventory UI: no base InventorySpot template was found.");
				return;
			}
			BatteryVisualLogic componentInChildren = ((Component)templateSpot).GetComponentInChildren<BatteryVisualLogic>(true);
			SemiUI component = ((Component)templateSpot).GetComponent<SemiUI>();
			Vector2 val = (Object.op_Implicit((Object)(object)component) ? component.showPosition : Vector2.op_Implicit(((Component)templateSpot).transform.localPosition));
			Vector2 val2 = (Object.op_Implicit((Object)(object)component) ? (component.hidePosition - val) : Vector2.zero);
			Vector2 templateHideCurrentOffset = (Object.op_Implicit((Object)(object)component) ? (hidePositionCurrent.Invoke(component) - val) : val2);
			Vector3 templateInitialOffset = (Object.op_Implicit((Object)(object)component) ? (initialPosition.Invoke(component) - Vector2.op_Implicit(val)) : Vector3.zero);
			InventoryBattery val3 = ((IEnumerable<InventoryBattery>)((Component)__instance).GetComponentsInChildren<InventoryBattery>(true)).FirstOrDefault((Func<InventoryBattery, bool>)((InventoryBattery battery) => Object.op_Implicit((Object)(object)battery) && battery.inventorySpot == templateSpot.inventorySpotIndex && !Object.op_Implicit((Object)(object)((Component)battery).GetComponentInParent<InventorySpot>())));
			Vector3 localScale = (Object.op_Implicit((Object)(object)val3) ? GetBatteryDisplayScale(val3) : Vector3.zero);
			Vector3 val4 = (Object.op_Implicit((Object)(object)val3) ? ((Component)templateSpot).transform.InverseTransformPoint(((Component)val3).transform.position) : Vector3.zero);
			Quaternion val5 = (Object.op_Implicit((Object)(object)val3) ? (Quaternion.Inverse(((Component)templateSpot).transform.rotation) * ((Component)val3).transform.rotation) : Quaternion.identity);
			Vector2 position = default(Vector2);
			int num4;
			for (int num3 = 0; num3 < num; num3++)
			{
				((Vector2)(ref position))..ctor(num2 + (float)num3 * 40f, -175.3f);
				if (dictionary.TryGetValue(num3, out var value) && Object.op_Implicit((Object)(object)value))
				{
					SetSpotPosition(value, position, val, val2, templateHideCurrentOffset, templateInitialOffset, startHasRun: true);
					continue;
				}
				Transform val6 = Object.Instantiate<Transform>(((Component)templateSpot).transform, ((Component)templateSpot).transform.parent, false);
				((Object)((Component)val6).gameObject).name = $"Inventory Spot {num3 + 1}";
				BatteryVisualLogic componentInChildren2 = ((Component)val6).GetComponentInChildren<BatteryVisualLogic>(true);
				if (Object.op_Implicit((Object)(object)componentInChildren2))
				{
					((Component)componentInChildren2).gameObject.SetActive(true);
				}
				InventorySpot component2 = ((Component)val6).GetComponent<InventorySpot>();
				if (!Object.op_Implicit((Object)(object)component2))
				{
					Object.Destroy((Object)(object)((Component)val6).gameObject);
					SLRUpgradePack.Logger.LogWarning((object)$"Could not create inventory slot {num3 + 1}: cloned template has no InventorySpot.");
					continue;
				}
				component2.inventorySpotIndex = num3;
				currentItem.Invoke(component2) = null;
				if (Object.op_Implicit((Object)(object)componentInChildren2))
				{
					inventorySpotBatteryVisual.Invoke(component2) = componentInChildren2;
					componentInChildren2.itemBattery = null;
					previousItemBattery.Invoke(componentInChildren2) = null;
					RebindBatteryBars(componentInChildren2);
					if (Object.op_Implicit((Object)(object)componentInChildren))
					{
						ResetClonedBatteryVisual(componentInChildren2, componentInChildren);
					}
				}
				InventoryBattery[] componentsInChildren = ((Component)component2).GetComponentsInChildren<InventoryBattery>(true);
				for (num4 = 0; num4 < componentsInChildren.Length; num4++)
				{
					componentsInChildren[num4].inventorySpot = num3;
				}
				RestoreClonedBatteryScales(templateSpot, val6);
				num4 = num3 + 1;
				string text = num4.ToString();
				if (Object.op_Implicit((Object)(object)component2.noItem))
				{
					((TMP_Text)component2.noItem).text = text;
				}
				Transform obj = val6.Find("Numbers");
				TextMeshProUGUI val7 = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
				if (Object.op_Implicit((Object)(object)val7))
				{
					((TMP_Text)val7).text = text;
				}
				SetSpotPosition(component2, position, val, val2, templateHideCurrentOffset, templateInitialOffset, startHasRun: false);
				dictionary[num3] = component2;
			}
			if (Object.op_Implicit((Object)(object)val3))
			{
				HashSet<int> hashSet = new HashSet<int>();
				InventoryBattery[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<InventoryBattery>(true);
				for (num4 = 0; num4 < componentsInChildren.Length; num4++)
				{
					InventoryBattery val8 = componentsInChildren[num4];
					InventorySpot componentInParent = ((Component)val8).GetComponentInParent<InventorySpot>();
					if (Object.op_Implicit((Object)(object)componentInParent))
					{
						val8.inventorySpot = componentInParent.inventorySpotIndex;
					}
					hashSet.Add(val8.inventorySpot);
				}
				for (int num5 = 3; num5 < num; num5++)
				{
					if (!hashSet.Contains(num5) && dictionary.TryGetValue(num5, out var value2) && Object.op_Implicit((Object)(object)value2))
					{
						Transform val9 = Object.Instantiate<Transform>(((Component)val3).transform, ((Component)val3).transform.parent, false);
						((Object)((Component)val9).gameObject).name = $"Inventory Battery {num5 + 1}";
						val9.position = ((Component)value2).transform.TransformPoint(val4);
						val9.rotation = ((Component)value2).transform.rotation * val5;
						InventoryBattery component3 = ((Component)val9).GetComponent<InventoryBattery>();
						if (!Object.op_Implicit((Object)(object)component3))
						{
							Object.Destroy((Object)(object)((Component)val9).gameObject);
							SLRUpgradePack.Logger.LogWarning((object)$"Could not create battery indicator for inventory slot {num5 + 1}: cloned template has no InventoryBattery.");
						}
						else
						{
							component3.inventorySpot = num5;
							val9.localScale = localScale;
							hashSet.Add(num5);
						}
					}
				}
			}
			foreach (KeyValuePair<int, InventorySpot> item in dictionary)
			{
				item.Deconstruct(out num4, out var value3);
				int num6 = num4;
				InventorySpot val10 = value3;
				if (Object.op_Implicit((Object)(object)val10))
				{
					InventoryBattery[] componentsInChildren = ((Component)val10).GetComponentsInChildren<InventoryBattery>(true);
					for (num4 = 0; num4 < componentsInChildren.Length; num4++)
					{
						componentsInChildren[num4].inventorySpot = num6;
					}
					InventoryStartPatch.RegisterSpot(val10, num6);
				}
			}
			List<GameObject> list = allChildren.Invoke(__instance);
			list.Clear();
			foreach (Transform item2 in ((Component)__instance).transform)
			{
				Transform val11 = item2;
				list.Add(((Component)val11).gameObject);
			}
			Canvas.ForceUpdateCanvases();
		}

		private static void SetSpotPosition(InventorySpot spot, Vector2 position, Vector2 templateShowPosition, Vector2 templateHideOffset, Vector2 templateHideCurrentOffset, Vector3 templateInitialOffset, bool startHasRun)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			_ = position - templateShowPosition;
			Vector3 localPosition = Vector2.op_Implicit(position);
			localPosition.z = ((Component)spot).transform.localPosition.z;
			((Component)spot).transform.localPosition = localPosition;
			SemiUI component = ((Component)spot).GetComponent<SemiUI>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.showPosition = position;
				component.hidePosition = (startHasRun ? (position + templateHideOffset) : templateHideOffset);
				hidePositionCurrent.Invoke(component) = position + templateHideCurrentOffset;
				initialPosition.Invoke(component) = Vector2.op_Implicit(position) + templateInitialOffset;
			}
		}

		private static Vector3 GetBatteryDisplayScale(InventoryBattery battery)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = originalBatteryScale.Invoke(battery);
			if (!(val == Vector3.zero))
			{
				return val;
			}
			return ((Component)battery).transform.localScale;
		}

		private static void RebindBatteryBars(BatteryVisualLogic batteryVisual)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)batteryVisual.batteryBarContainer))
			{
				SLRUpgradePack.Logger.LogWarning((object)"Could not rebind cloned battery bars: the bar container reference is missing.");
				batteryBars.Invoke(batteryVisual) = new List<GameObject>();
				return;
			}
			List<GameObject> list = new List<GameObject>(batteryVisual.batteryBarContainer.childCount);
			foreach (Transform item in batteryVisual.batteryBarContainer)
			{
				Transform val = item;
				list.Add(((Component)val).gameObject);
			}
			batteryBars.Invoke(batteryVisual) = list;
		}

		internal static BatteryVisualLogic? BindBatteryVisual(InventorySpot spot, bool activateForVanillaStart)
		{
			if (!Object.op_Implicit((Object)(object)spot))
			{
				return null;
			}
			BatteryVisualLogic val = inventorySpotBatteryVisual.Invoke(spot);
			if (Object.op_Implicit((Object)(object)val) && (Object)(object)((Component)val).transform != (Object)(object)((Component)spot).transform && !((Component)val).transform.IsChildOf(((Component)spot).transform))
			{
				val = null;
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = ((Component)spot).GetComponentInChildren<BatteryVisualLogic>(true);
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			inventorySpotBatteryVisual.Invoke(spot) = val;
			if (activateForVanillaStart && !((Component)val).gameObject.activeSelf)
			{
				((Component)val).gameObject.SetActive(true);
			}
			return val;
		}

		private static void ResetClonedBatteryVisual(BatteryVisualLogic visual, BatteryVisualLogic template)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_0038: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = batteryTargetPositionOriginal.Invoke(template);
			if (float.IsNaN(val.x) || float.IsInfinity(val.x) || float.IsNaN(val.y) || float.IsInfinity(val.y) || float.IsNaN(val.z) || float.IsInfinity(val.z))
			{
				val = ((Component)visual).transform.localPosition;
			}
			float num = batteryTargetScaleOriginal.Invoke(template);
			if (!IsUsableScale(num))
			{
				num = batteryTargetScale.Invoke(template);
			}
			if (!IsUsableScale(num))
			{
				num = Mathf.Max(((Component)visual).transform.localScale.x, ((Component)visual).transform.localScale.y);
			}
			if (!IsUsableScale(num))
			{
				num = 0.5f;
			}
			float num2 = batteryTargetRotationOriginal.Invoke(template);
			if (float.IsNaN(num2) || float.IsInfinity(num2))
			{
				num2 = 0f;
			}
			ApplyClonedBatteryVisualState(visual, val, num, num2);
			clonedBatteryVisualsPendingStart[((Object)visual).GetInstanceID()] = (val, num, num2);
		}

		private static void ApplyClonedBatteryVisualState(BatteryVisualLogic visual, Vector3 targetPosition, float targetScale, float targetRotation)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			((Component)visual).transform.localPosition = targetPosition;
			((Component)visual).transform.localScale = Vector3.one * targetScale;
			((Component)visual).transform.localRotation = Quaternion.Euler(0f, 0f, targetRotation);
			batteryTargetPosition.Invoke(visual) = targetPosition;
			batteryTargetPositionOriginal.Invoke(visual) = targetPosition;
			batteryTargetScale.Invoke(visual) = targetScale;
			batteryTargetScaleOriginal.Invoke(visual) = targetScale;
			batteryTargetRotation.Invoke(visual) = targetRotation;
			batteryTargetRotationOriginal.Invoke(visual) = targetRotation;
			batteryDoOutro.Invoke(visual) = false;
			ResetBatteryVisualSprings(visual, targetScale);
		}

		private static bool IsUsableScale(float value)
		{
			if (!float.IsNaN(value) && !float.IsInfinity(value))
			{
				return value > 0.001f;
			}
			return false;
		}

		private static void ResetBatteryVisualSprings(BatteryVisualLogic visual, float targetScale)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			SpringFloat val = new SpringFloat();
			springFloatDamping.Invoke(val) = 0.4f;
			springFloatSpeed.Invoke(val) = 30f;
			springFloatLastPosition.Invoke(val) = targetScale;
			batterySpringScale.Invoke(visual) = val;
			SpringFloat val2 = new SpringFloat();
			springFloatDamping.Invoke(val2) = 0.3f;
			springFloatSpeed.Invoke(val2) = 40f;
			springFloatLastPosition.Invoke(val2) = 0f;
			batterySpringRotation.Invoke(visual) = val2;
			SpringVector3 val3 = new SpringVector3();
			springVectorDamping.Invoke(val3) = 0.35f;
			springVectorSpeed.Invoke(val3) = 30f;
			springVectorLastPosition.Invoke(val3) = ((Component)visual).transform.localPosition;
			batterySpringPosition.Invoke(visual) = val3;
		}

		internal static void ResetPendingClonedBatteryVisualStart(BatteryVisualLogic visual)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)visual))
			{
				int instanceID = ((Object)visual).GetInstanceID();
				if (clonedBatteryVisualsPendingStart.TryGetValue(instanceID, out (Vector3, float, float) value))
				{
					clonedBatteryVisualsPendingStart.Remove(instanceID);
					ApplyClonedBatteryVisualState(visual, value.Item1, value.Item2, value.Item3);
				}
			}
		}

		internal static void ClearPendingClonedBatteryVisuals()
		{
			clonedBatteryVisualsPendingStart.Clear();
		}

		internal static void RefreshBatteryVisual(InventorySpot spot, bool forceRefresh = true)
		{
			if (!Object.op_Implicit((Object)(object)spot))
			{
				return;
			}
			ItemEquippable val = spot.CurrentItem;
			ItemBattery val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<ItemBattery>() : null);
			int num = (Object.op_Implicit((Object)(object)val2) ? ((Object)val2).GetInstanceID() : 0);
			int frameCount = Time.frameCount;
			if (batteryVisualRefreshFrame != frameCount)
			{
				batteryVisualRefreshes.Clear();
				batteryVisualRefreshFrame = frameCount;
			}
			int instanceID = ((Object)spot).GetInstanceID();
			if (!forceRefresh && batteryVisualRefreshes.TryGetValue(instanceID, out (int, int) value) && value.Item2 == num)
			{
				return;
			}
			BatteryVisualLogic batteryVisual = BindBatteryVisual(spot, activateForVanillaStart: false);
			if (!Object.op_Implicit((Object)(object)batteryVisual) || !Object.op_Implicit((Object)(object)batteryVisual.batteryBarContainer))
			{
				return;
			}
			List<GameObject> list = batteryBars.Invoke(batteryVisual);
			if (list == null || list.Count != batteryVisual.batteryBarContainer.childCount || list.Any((GameObject bar) => !Object.op_Implicit((Object)(object)bar) || (Object)(object)bar.transform.parent != (Object)(object)batteryVisual.batteryBarContainer))
			{
				RebindBatteryBars(batteryVisual);
			}
			batteryVisual.itemBattery = val2;
			previousItemBattery.Invoke(batteryVisual) = val2;
			if (Object.op_Implicit((Object)(object)val2))
			{
				if (!((Component)batteryVisual).gameObject.activeSelf)
				{
					((Component)batteryVisual).gameObject.SetActive(true);
				}
				if (batteryTargetScale.Invoke(batteryVisual) == 0f)
				{
					batteryVisual.ResetOutro();
				}
			}
			batteryVisual.BatteryBarsSet();
			if (Object.op_Implicit((Object)(object)val2))
			{
				batteryVisual.BatteryBarsUpdate(-1, true);
			}
			else
			{
				batteryVisual.BatteryOutro();
			}
			batteryVisualRefreshes[instanceID] = (frameCount, num);
		}

		private static void RestoreClonedBatteryScales(InventorySpot templateSpot, Transform clonedSpot)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			InventoryBattery[] componentsInChildren = ((Component)templateSpot).GetComponentsInChildren<InventoryBattery>(true);
			InventoryBattery[] componentsInChildren2 = ((Component)clonedSpot).GetComponentsInChildren<InventoryBattery>(true);
			for (int i = 0; i < componentsInChildren.Length && i < componentsInChildren2.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)componentsInChildren[i]) && Object.op_Implicit((Object)(object)componentsInChildren2[i]))
				{
					((Component)componentsInChildren2[i]).transform.localScale = GetBatteryDisplayScale(componentsInChildren[i]);
				}
			}
		}
	}
	[HarmonyPatch(typeof(InventorySpot), "EquipItem")]
	public class InventorySpotEquipBatteryVisualPatch
	{
		private static void Postfix(InventorySpot __instance)
		{
			InventoryUIStartPatch.RefreshBatteryVisual(__instance, forceRefresh: false);
		}
	}
	[HarmonyPatch(typeof(InventorySpot), "UnequipItem")]
	public class InventorySpotUnequipBatteryVisualPatch
	{
		private static void Postfix(InventorySpot __instance)
		{
			InventoryUIStartPatch.RefreshBatteryVisual(__instance, forceRefresh: false);
		}
	}
	[HarmonyPatch(typeof(InventorySpot), "UpdateUI")]
	public class InventorySpotUpdateUIBatteryVisualPatch
	{
		private static void Postfix(InventorySpot __instance)
		{
			InventoryUIStartPatch.RefreshBatteryVisual(__instance);
		}
	}
	[HarmonyPatch(typeof(InventorySpot), "Start")]
	public class InventorySpotStartPatch
	{
		private static void Prefix(InventorySpot __instance)
		{
			InventoryUIStartPatch.BindBatteryVisual(__instance, __instance.inventorySpotIndex >= 3);
		}

		private static void Postfix(InventorySpot __instance)
		{
			InventoryUIStartPatch.BindBatteryVisual(__instance, activateForVanillaStart: false);
		}
	}
	[HarmonyPatch(typeof(BatteryVisualLogic), "Start")]
	public class BatteryVisualLogicStartPatch
	{
		private static void Postfix(BatteryVisualLogic __instance)
		{
			InventoryUIStartPatch.ResetPendingClonedBatteryVisualStart(__instance);
		}
	}
	[HarmonyPatch(typeof(InventorySpot), "StateOccupied")]
	public class InventorySpotStateOccupiedBatteryVisualPatch
	{
		private static void Prefix(InventorySpot __instance)
		{
			InventoryUIStartPatch.BindBatteryVisual(__instance, activateForVanillaStart: false);
		}
	}
	[HarmonyPatch(typeof(StatsManager), "PlayerInventoryUpdate")]
	public class StatsManagerUpdatePatch
	{
		private static void Postfix(StatsManager __instance, string _steamID, string itemName, int spot, bool sync)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer() || spot < 3)
			{
				return;
			}
			Dictionary<int, int> value;
			bool flag = InventorySlotUpgrade.serverMonitoredInventoryItems.TryGetValue(_steamID, out value);
			if (string.IsNullOrEmpty(itemName))
			{
				if (flag)
				{
					value.Remove(spot);
					if (value.Count == 0)
					{
						InventorySlotUpgrade.serverMonitoredInventoryItems.Remove(_steamID);
					}
				}
			}
			else
			{
				if (!flag)
				{
					InventorySlotUpgrade.serverMonitoredInventoryItems.Add(_steamID, value = new Dictionary<int, int>());
				}
				value[spot] = itemName.GetHashCode();
			}
		}
	}
	[HarmonyPatch(typeof(MainMenuOpen), "Start")]
	public class MainMenuOpenStartPatch
	{
		private static void Postfix(MainMenuOpen __instance)
		{
			InventorySlotUpgrade.serverMonitoredInventoryItems.Clear();
			InventoryUIStartPatch.ClearPendingClonedBatteryVisuals();
		}
	}
	[HarmonyPatch(typeof(Inventory), "Start")]
	public class InventoryStartPatch
	{
		private static readonly FieldRef<Inventory, List<InventorySpot>> inventorySpots = AccessTools.FieldRefAccess<Inventory, List<InventorySpot>>("inventorySpots");

		internal static void Postfix(Inventory __instance)
		{
			InventorySlotUpgrade inventorySlotUpgradeInstance = SLRUpgradePack.InventorySlotUpgradeInstance;
			inventorySlotUpgradeInstance.InventoryRef = __instance;
			if (inventorySlotUpgradeInstance.UpgradeEnabled.Value && inventorySlotUpgradeInstance.BoundPlayer != null)
			{
				int num = inventorySlotUpgradeInstance.Calculate(3, SemiFunc.PlayerAvatarLocal(), inventorySlotUpgradeInstance.UpgradeRegister.GetLevel(inventorySlotUpgradeInstance.BoundPlayer));
				SLRUpgradePack.Logger.LogInfo((object)$"Player has {num} slots");
				while (inventorySpots.Invoke(__instance).Count < num)
				{
					inventorySpots.Invoke(__instance).Add(null);
				}
			}
		}

		internal static void RegisterSpot(InventorySpot spot, int index)
		{
			if (index < 3 || !Object.op_Implicit((Object)(object)spot) || SemiFunc.RunIsArena())
			{
				return;
			}
			Inventory instance = Inventory.instance;
			if (Object.op_Implicit((Object)(object)instance))
			{
				List<InventorySpot> list = inventorySpots.Invoke(instance);
				while (list.Count <= index)
				{
					list.Add(null);
				}
				instance.InventorySpotAddAtIndex(spot, index);
			}
		}
	}
	[HarmonyPatch(typeof(InventorySpot), "Update")]
	public class InventorySpotUpdatePatch
	{
		private static readonly MethodInfo HandleInputMethod = AccessTools.Method(typeof(InventorySpot), "HandleInput", (Type[])null, (Type[])null);

		private static void Prefix(InventorySpot __instance)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			InventorySlotUpgrade inventorySlotUpgradeInstance = SLRUpgradePack.InventorySlotUpgradeInstance;
			if (!inventorySlotUpgradeInstance.UpgradeEnabled.Value || inventorySlotUpgradeInstance.BoundPlayer == null)
			{
				return;
			}
			int num = inventorySlotUpgradeInstance.Calculate(3, SemiFunc.PlayerAvatarLocal(), inventorySlotUpgradeInstance.UpgradeRegister.GetLevel(inventorySlotUpgradeInstance.BoundPlayer));
			List<Keybind> list = new List<Keybind>(9) { null, null, null, inventorySlotUpgradeInstance.ItemSlot4, inventorySlotUpgradeInstance.ItemSlot5, inventorySlotUpgradeInstance.ItemSlot6, inventorySlotUpgradeInstance.ItemSlot7, inventorySlotUpgradeInstance.ItemSlot8, inventorySlotUpgradeInstance.ItemSlot9 };
			if (__instance.inventorySpotIndex > 2 && __instance.inventorySpotIndex < num)
			{
				Keybind val = list[__instance.inventorySpotIndex];
				if (val != null && InputManager.instance.KeyDown(val.inputKey))
				{
					HandleInputMethod.Invoke(__instance, null);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PunManager), "SetItemNameLOGIC")]
	public class PunManagerSetItemNameLOGICPatch
	{
		private static bool Prefix(PunManager __instance, string _name, int photonViewID, ItemAttributes _itemAttributes, StatsManager ___statsManager)
		{
			if (photonViewID == -1 && SemiFunc.IsMultiplayer())
			{
				return true;
			}
			ItemAttributes val = _itemAttributes;
			if (SemiFunc.IsMultiplayer())
			{
				PhotonView val2 = PhotonView.Find(photonViewID);
				if (!Object.op_Implicit((Object)(object)val2))
				{
					return true;
				}
				val = ((Component)val2).GetComponent<ItemAttributes>();
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				return true;
			}
			AccessTools.FieldRefAccess<ItemAttributes, string>("instanceName").Invoke(val) = _name;
			ItemBattery component = ((Component)val).GetComponent<ItemBattery>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.SetBatteryLife(___statsManager.GetBatteryLevel(_name));
			}
			ItemEquippable component2 = ((Component)val).GetComponent<ItemEquippable>();
			if (!Object.op_Implicit((Object)(object)component2))
			{
				return true;
			}
			int hashCode = _name.GetHashCode();
			foreach (PlayerAvatar item in SemiFunc.PlayerGetList())
			{
				if (InventorySlotUpgrade.serverMonitoredInventoryItems.TryGetValue(SemiFunc.PlayerGetSteamID(item), out Dictionary<int, int> value) && value.ContainsValue(hashCode))
				{
					component2.RequestEquip(value.First((KeyValuePair<int, int> element) => element.Value == hashCode).Key, SemiFunc.IsMultiplayer() ? item.photonView.ViewID : (-1));
					return false;
				}
			}
			return true;
		}
	}
	public class ObjectDurabilityUpgrade : UpgradeBase<float>
	{
		public ObjectDurabilityUpgrade(bool enabled, float upgradeAmount, bool exponential, float exponentialAmount, ConfigFile config, AssetBundle assetBundle, float priceMultiplier)
			: base("Object Durability", "assets/repo/mods/resources/items/items/item upgrade durability lib.asset", enabled, upgradeAmount, exponential, exponentialAmount, config, assetBundle, priceMultiplier, configureAmount: true, canBeExponential: true, (int?)null)
		{
		}

		public override float Calculate(float damage, PlayerAvatar player, int level)
		{
			return UpgradeBase<float>.DefaultCalculateFloatReduce(this, "ObjectDurability", damage, player, level);
		}
	}
	[HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "Break")]
	public static class ObjectDurabilityDamagePatch
	{
		internal static void Prefix(PhysGrabObjectImpactDetector __instance, ref float valueLost)
		{
			ObjectDurabilityUpgrade objectDurabilityUpgradeInstance = SLRUpgradePack.ObjectDurabilityUpgradeInstance;
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !__instance.isValuable || valueLost <= 0f || !objectDurabilityUpgradeInstance.UpgradeEnabled.Value)
			{
				return;
			}
			int totalActivePlayerLevels = objectDurabilityUpgradeInstance.GetTotalActivePlayerLevels();
			if (totalActivePlayerLevels > 0)
			{
				float num = objectDurabilityUpgradeInstance.Calculate(valueLost, null, totalActivePlayerLevels);
				if (!float.IsNaN(num) && !float.IsInfinity(num))
				{
					valueLost = Math.Min(valueLost, Math.Max(0f, num));
				}
			}
		}
	}
	public class ObjectValueUpgrade : UpgradeBase<float>
	{
		public ConfigEntry<bool> UpgradeScalesSurplus { get; protected set; }

		public ConfigEntry<float> SurplusPercentScale { get; protected set; }

		public ObjectValueUpgrade(bool enabled, float upgradeAmount, bool exponential, float exponentialAmount, ConfigFile config, AssetBundle assetBundle, float priceMultiplier)
			: base("Object Value", "assets/repo/mods/resources/items/items/item upgrade value lib.asset", enabled, upgradeAmount, exponential, exponentialAmount, config, assetBundle, priceMultiplier, configureAmount: true, canBeExponential: true, (int?)null)
		{
			UpgradeScalesSurplus = config.Bind<bool>("Object Value Upgrade", "Scale Surplus Bag", false, "Should the Object Value Upgrade scale the extraction surplus bag?");
			SurplusPercentScale = config.Bind<float>("Object Value Upgrade", "Surplus Scaled Percentage", 0.1f, "Percentage of the extraction surplus bag that is scaled by this upgrade");
		}

		public override float Calculate(float value, PlayerAvatar player, int level)
		{
			return UpgradeBase<float>.DefaultCalculateFloatIncrease(this, "ObjectValue", value, player, level);
		}
	}
	[HarmonyPatch(typeof(ValuableObject), "DollarValueSetLogic")]
	public class ValuableObjectValuePatch
	{
		private sealed class ExtractionGoalValueData
		{
			internal float BaseValue;

			internal float UpgradeBonus;

			internal bool HasBaseValue;

			internal bool Excluded;
		}

		internal static readonly FieldRef<ValuableObject, int> FixedValueRef = AccessTools.FieldRefAccess<ValuableObject, int>("dollarValueOverride");

		internal static readonly FieldRef<ValuableObject, float> DollarValueCurrentRef = AccessTools.FieldRefAccess<ValuableObject, float>("dollarValueCurrent");

		private static readonly FieldRef<ValuableObject, bool> DollarValueSetRef = AccessTools.FieldRefAccess<ValuableObject, bool>("dollarValueSet");

		private static readonly ConditionalWeakTable<ValuableObject, ExtractionGoalValueData> ExtractionGoalValues = new ConditionalWeakTable<ValuableObject, ExtractionGoalValueData>();

		private static readonly FieldInfo DollarValueCurrentField = AccessTools.Field(typeof(ValuableObject), "dollarValueCurrent");

		private static readonly FieldInfo RoundDirectorHaulGoalMaxField = AccessTools.Field(typeof(RoundDirector), "haulGoalMax");

		private static readonly MethodInfo GetExtractionGoalValueMethod = AccessTools.Method(typeof(ValuableObjectValuePatch), "GetExtractionGoalValue", new Type[1] { typeof(ValuableObject) }, (Type[])null);

		internal static readonly Queue<ValuableObject> DollarValueQueue = new Queue<ValuableObject>();

		[HarmonyPriority(800)]
		internal static void Prefix(ValuableObject __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance) && !DollarValueSetRef.Invoke(__instance) && ExtractionGoalValues.TryGetValue(__instance, out ExtractionGoalValueData value))
			{
				value.HasBaseValue = false;
				value.UpgradeBonus = 0f;
			}
		}

		[HarmonyPriority(800)]
		internal static void Postfix(ValuableObject __instance)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			ObjectValueUpgrade objectValueUpgradeInstance = SLRUpgradePack.ObjectValueUpgradeInstance;
			if ((Object)(object)__instance == (Object)null || SemiFunc.RunIsLobby() || SemiFunc.RunIsShop() || SemiFunc.RunIsArena())
			{
				return;
			}
			if (objectValueUpgradeInstance.UpgradeEnabled.Value && (int)LevelGenerator.Instance.State <= 11)
			{
				if (!DollarValueQueue.Contains(__instance))
				{
					DollarValueQueue.Enqueue(__instance);
				}
			}
			else
			{
				Action(__instance);
			}
		}

		internal static void Action(ValuableObject instance)
		{
			if (!Object.op_Implicit((Object)(object)instance))
			{
				return;
			}
			EnsureBaseExtractionGoalValue(instance, DollarValueCurrentRef.Invoke(instance));
			ObjectValueUpgrade objectValueUpgradeInstance = SLRUpgradePack.ObjectValueUpgradeInstance;
			if (SemiFunc.IsMasterClientOrSingleplayer() && objectValueUpgradeInstance.UpgradeEnabled.Value && (objectValueUpgradeInstance.UpgradeScalesSurplus.Value || !StringUtilsExtensions.StartsWithIgnoreCaseFast(((Object)instance).name, "surplus")))
			{
				SLRUpgradePack.Logger.LogDebug((object)$"{((Object)instance).name} Original value: {instance.valuePreset.valueMin} - {instance.valuePreset.valueMax} ({DollarValueCurrentRef.Invoke(instance)} / {FixedValueRef.Invoke(instance)})");
				Value val = Object.Instantiate<Value>(instance.valuePreset);
				float value = DollarValueCurrentRef.Invoke(instance);
				int totalActivePlayerLevels = objectValueUpgradeInstance.GetTotalActivePlayerLevels();
				val.valueMin = objectValueUpgradeInstance.Calculate(instance.valuePreset.valueMin, null, totalActivePlayerLevels);
				val.valueMax = objectValueUpgradeInstance.Calculate(instance.valuePreset.valueMax, null, totalActivePlayerLevels);
				if (FixedValueRef.Invoke(instance) != 0)
				{
					FixedValueRef.Invoke(instance) = (int)Math.Ceiling(objectValueUpgradeInstance.Calculate(FixedValueRef.Invoke(instance), null, totalActivePlayerLevels));
				}
				value = objectValueUpgradeInstance.Calculate(value, null, totalActivePlayerLevels);
				instance.valuePreset = val;
				DollarValueCurrentRef.Invoke(instance) = value;
				UpdateExtractionGoalBonusFromCurrent(instance);
				SLRUpgradePack.Logger.LogDebug((object)string.Format("After calculation with levels {0}: {1} - {2} ({3} / {4})", string.Join(",", from entry in objectValueUpgradeInstance.GetActivePlayerLevels()
					select (SemiFunc.PlayerGetName(entry.Player), Level: entry.Level)), instance.valuePreset.valueMin, instance.valuePreset.valueMax, DollarValueCurrentRef.Invoke(instance), FixedValueRef.Invoke(instance)));
			}
		}

		internal static void EnsureBaseExtractionGoalValue(ValuableObject instance, float value)
		{
			if (Object.op_Implicit((Object)(object)instance))
			{
				ExtractionGoalValueData value2 = ExtractionGoalValues.GetValue(instance, (ValuableObject _) => new ExtractionGoalValueData());
				if (!value2.HasBaseValue)
				{
					value2.BaseValue = value;
					value2.HasBaseValue = true;
				}
			}
		}

		internal static void UpdateExtractionGoalBonusFromCurrent(ValuableObject instance)
		{
			if (Object.op_Implicit((Object)(object)instance) && ExtractionGoalValues.TryGetValue(instance, out ExtractionGoalValueData value) && value.HasBaseValue)
			{
				value.UpgradeBonus = DollarValueCurrentRef.Invoke(instance) - value.BaseValue;
			}
		}

		internal static void MarkExcludedFromExtractionGoal(ValuableObject instance)
		{
			if (Object.op_Implicit((Object)(object)instance))
			{
				ExtractionGoalValues.GetValue(instance, (ValuableObject _) => new ExtractionGoalValueData()).Excluded = true;
			}
		}

		internal static float GetExtractionGoalValue(ValuableObject instance)
		{
			if (!Object.op_Implicit((Object)(object)instance))
			{
				return 0f;
			}
			if (!ExtractionGoalValues.TryGetValue(instance, out ExtractionGoalValueData value))
			{
				return DollarValueCurrentRef.Invoke(instance);
			}
			if (value.Excluded)
			{
				return 0f;
			}
			float num = DollarValueCurrentRef.Invoke(instance);
			if (!value.HasBaseValue)
			{
				return num;
			}
			return Mathf.Max(0f, num - value.UpgradeBonus);
		}

		internal static IEnumerable<CodeInstruction> ReplaceSpawnBudgetValueLoad(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			int num = 0;
			List<CodeInstruction> list = new List<CodeInstruction>();
			foreach (CodeInstruction instruction in instructions)
			{
				CodeInstruction val = new CodeInstruction(instruction);
				if (CodeInstructionExtensions.LoadsField(val, DollarValueCurrentField, false))
				{
					val.opcode = OpCodes.Call;
					val.operand = GetExtractionGoalValueMethod;
					num++;
				}
				list.Add(val);
			}
			if (num != 1)
			{
				SLRUpgradePack.Logger.LogWarning((object)$"Expected one valuable spawn-budget value read in ValuableDirector.SpawnValuable, replaced {num}.");
			}
			return list;
		}

		internal static IEnumerable<CodeInstruction> ReplaceExtractionGoalValueLoad(IEnumerable<CodeInstruction> instructions)
		{
			int num = 0;
			List<CodeInstruction> list = instructions.Select((Func<CodeInstruction, CodeInstruction>)((CodeInstruction instruction) => new CodeInstruction(instruction))).ToList();
			for (int num2 = 0; num2 < list.Count - 3; num2++)
			{
				CodeInstruction val = list[num2];
				if (CodeInstructionExtensions.LoadsField(val, DollarValueCurrentField, false) && !(list[num2 + 1].opcode != OpCodes.Conv_I4) && !(list[num2 + 2].opcode != OpCodes.Add) && CodeInstructionExtensions.StoresField(list[num2 + 3], RoundDirectorHaulGoalMaxField))
				{
					val.opcode = OpCodes.Call;
					val.operand = GetExtractionGoalValueMethod;
					num++;
				}
			}
			if (num != 1)
			{
				SLRUpgradePack.Logger.LogWarning((object)$"Expected one value read when building RoundDirector.haulGoalMax, replaced {num}.");
			}
			return list;
		}
	}
	[HarmonyPatch]
	public static class ValuableObjectExtractionGoalValuePatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.Inner(typeof(ValuableObject), "<DollarValueSet>d__38"), "MoveNext", (Type[])null, (Type[])null);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return ValuableObjectValuePatch.ReplaceExtractionGoalValueLoad(instructions);
		}
	}
	[HarmonyPatch(typeof(ValuableDirector), "SpawnValuable")]
	public static class ValuableDirectorSpawnBudgetGoalValuePatch
	{
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return ValuableObjectValuePatch.ReplaceSpawnBudgetValueLoad(instructions);
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "Start")]
	public class LevelGeneratorObjectValueStartPatch
	{
		internal static void Postfix()
		{
			if (!SemiFunc.RunIsLevel())
			{
				return;
			}
			while (ValuableObjectValuePatch.DollarValueQueue.Count > 0)
			{
				ValuableObject val = ValuableObjectValuePatch.DollarValueQueue.Dequeue();
				if (Object.op_Implicit((Object)(object)val))
				{
					ValuableObjectValuePatch.Action(val);
				}
			}
		}
	}
	public class SpawnedValuableValuePatch<TSVT> where TSVT : MonoBehaviour
	{
		protected static void DoValuableStuff(TSVT spawnedValuable)
		{
			ValuableObject val = default(ValuableObject);
			if (((Component)(object)spawnedValuable).TryGetComponent<ValuableObject>(ref val) && SLRUpgradePack.ObjectValueUpgradeInstance.UpgradeEnabled.Value)
			{
				SLRUpgradePack.Logger.LogDebug((object)$"Valuable {((Object)(object)spawnedValuable).name} spawned with: {val.valuePreset.valueMin} {val.valuePreset.valueMax} {ValuableObjectValuePatch.FixedValueRef.Invoke(val)}");
				ValuableObjectValuePatch.Action(val);
			}
		}
	}
	[HarmonyPatch(typeof(SurplusValuable), "Start")]
	public class SurplusValuableValuePatch : SpawnedValuableValuePatch<SurplusValuable>
	{
		internal static void Prefix(SurplusValuable __instance)
		{
			ObjectValueUpgrade objectValueUpgradeInstance = SLRUpgradePack.ObjectValueUpgradeInstance;
			ValuableObject val = default(ValuableObject);
			if (objectValueUpgradeInstance.UpgradeScalesSurplus.Value && objectValueUpgradeInstance.UpgradeEnabled.Value && ((Component)__instance).TryGetComponent<ValuableObject>(ref val))
			{
				Value val2 = Object.Instantiate<Value>(val.valuePreset);
				float valueMin = val.valuePreset.valueMin;
				float valueMax = val.valuePreset.valueMax;
				int num = ValuableObjectValuePatch.FixedValueRef.Invoke(val);
				float num2 = ValuableObjectValuePatch.DollarValueCurrentRef.Invoke(val);
				ValuableObjectValuePatch.EnsureBaseExtractionGoalValue(val, num2);
				val2.valueMin = valueMin * objectValueUpgradeInstance.SurplusPercentScale.Value;
				val2.valueMax = valueMax * objectValueUpgradeInstance.SurplusPercentScale.Value;
				int num3 = (ValuableObjectValuePatch.FixedValueRef.Invoke(val) = (int)((float)num * objectValueUpgradeInstance.SurplusPercentScale.Value));
				float num4 = (ValuableObjectValuePatch.DollarValueCurrentRef.Invoke(val) = num2 * objectValueUpgradeInstance.SurplusPercentScale.Value);
				val.valuePreset = val2;
				SpawnedValuableValuePatch<SurplusValuable>.DoValuableStuff(__instance);
				Value valuePreset = val.valuePreset;
				valuePreset.valueMin += valueMin - val2.valueMin;
				Value valuePreset2 = val.valuePreset;
				valuePreset2.valueMax += valueMax - val2.valueMax;
				ValuableObjectValuePatch.FixedValueRef.Invoke(val) += num - num3;
				ValuableObjectValuePatch.DollarValueCurrentRef.Invoke(val) += num2 - num4;
				ValuableObjectValuePatch.UpdateExtractionGoalBonusFromCurrent(val);
				SLRUpgradePack.Logger.LogInfo((object)$"Surplus bag worth {num2} scaling {num4} to a total of {ValuableObjectValuePatch.DollarValueCurrentRef.Invoke(val)}");
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObjectImpactDetector))]
	public static class ValuableObjectDynamicGoalValuePatch
	{
		private static readonly FieldRef<PhysGrabObjectImpactDetector, ValuableObject> ValuableObjectRef = AccessTools.FieldRefAccess<PhysGrabObjectImpactDetector, ValuableObject>("valuableObject");

		[HarmonyPatch("HealLogic")]
		[HarmonyPostfix]
		private static void HealLogicPostfix(PhysGrabObjectImpactDetector __instance)
		{
			RefreshGoalValue(__instance);
		}

		[HarmonyPatch("ResetObject")]
		[HarmonyPostfix]
		private static void R