Decompiled source of ExtraBattleUpgrades v1.0.0

ExtraBattleUpgrades.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExtraBattleUpgrades.Combat;
using ExtraBattleUpgrades.Hud;
using ExtraBattleUpgrades.Upgrades;
using ExtraBattleUpgrades.Visuals;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using REPOLib.Modules;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 ExtraBattleUpgrades
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("DarkSpider90.ExtraBattleUpgrades", "Extra Battle Upgrades", "1.0.0")]
	public sealed class ExtraBattleUpgradesPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "DarkSpider90.ExtraBattleUpgrades";

		public const string PluginName = "Extra Battle Upgrades";

		public const string PluginVersion = "1.0.0";

		private Harmony _harmony;

		private bool _statsLabelsReady;

		internal static ExtraBattleUpgradesPlugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static ArmorShopUpgrade Armor { get; private set; }

		internal static OverchargeShopUpgrade Overcharge { get; private set; }

		internal static EnergyLeechShopUpgrade EnergyLeech { get; private set; }

		internal static ShockGripShopUpgrade ShockGrip { get; private set; }

		internal static SecondChanceShopUpgrade SecondChance { get; private set; }

		internal static PanicResponseShopUpgrade PanicResponse { get; private set; }

		internal static BattleUpgradeHudConfig HudConfig { get; private set; }

		private void Awake()
		{
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			AssetBundle val = ReadBundledAssets();
			((Object)val).name = "extra_battle_upgrades_assets";
			Armor = new ArmorShopUpgrade(((BaseUnityPlugin)this).Config, val);
			Overcharge = new OverchargeShopUpgrade(((BaseUnityPlugin)this).Config, val);
			EnergyLeech = new EnergyLeechShopUpgrade(((BaseUnityPlugin)this).Config, val);
			ShockGrip = new ShockGripShopUpgrade(((BaseUnityPlugin)this).Config, val);
			SecondChance = new SecondChanceShopUpgrade(((BaseUnityPlugin)this).Config, val);
			PanicResponse = new PanicResponseShopUpgrade(((BaseUnityPlugin)this).Config, val);
			HudConfig = new BattleUpgradeHudConfig(((BaseUnityPlugin)this).Config);
			Armor.Register();
			Overcharge.Register();
			EnergyLeech.Register();
			ShockGrip.Register();
			SecondChance.Register();
			PanicResponse.Register();
			_harmony = new Harmony("DarkSpider90.ExtraBattleUpgrades");
			_harmony.PatchAll();
			Log.LogInfo((object)"Extra Battle Upgrades v1.0.0 loaded for R.E.P.O. v0.4.0.");
		}

		private void Update()
		{
			if (!_statsLabelsReady && (Object)(object)StatsManager.instance != (Object)null)
			{
				RefreshStatsLabels(StatsManager.instance);
				_statsLabelsReady = true;
			}
			if (SemiFunc.IsMasterClientOrSingleplayer() && !((Object)(object)LevelGenerator.Instance == (Object)null))
			{
				_ = LevelGenerator.Instance.Generated;
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		internal static void RefreshStatsLabels(StatsManager statsManager)
		{
			SetStatsLabel(statsManager, "playerUpgradeArmor", "Armor");
			SetStatsLabel(statsManager, "playerUpgradeOvercharge", "Overcharge");
			SetStatsLabel(statsManager, "playerUpgradeEnergyLeech", "Energy Leech");
			SetStatsLabel(statsManager, "playerUpgradeShockGrip", "Shock Grip");
			SetStatsLabel(statsManager, "playerUpgradeSecondChance", "Second Chance");
			SetStatsLabel(statsManager, "playerUpgradePanicResponse", "Panic Response");
			if ((Object)(object)StatsUI.instance != (Object)null)
			{
				StatsUI.instance.ResetPlayerUpgradeNames();
			}
		}

		private static void SetStatsLabel(StatsManager statsManager, string statsKey, string displayName)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			if (statsManager.upgradesInfo.TryGetValue(statsKey, out var value))
			{
				value.displayName = displayName;
				value.displayNameLocalized = null;
			}
			else
			{
				statsManager.upgradesInfo.Add(statsKey, new UpgradeInfo
				{
					displayName = displayName,
					displayNameLocalized = null
				});
			}
		}

		private static AssetBundle ReadBundledAssets()
		{
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ExtraBattleUpgrades.Assets.extra_battle_upgrades_assets");
			if (stream == null)
			{
				throw new FileNotFoundException("Embedded asset bundle ExtraBattleUpgrades.Assets.extra_battle_upgrades_assets was not found.");
			}
			byte[] array = new byte[stream.Length];
			int num;
			for (int i = 0; i < array.Length; i += num)
			{
				num = stream.Read(array, i, array.Length - i);
				if (num == 0)
				{
					break;
				}
			}
			AssetBundle obj = AssetBundle.LoadFromMemory(array);
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidDataException("Failed to load embedded extra_battle_upgrades_assets asset bundle.");
			}
			return obj;
		}
	}
}
namespace ExtraBattleUpgrades.Visuals
{
	internal sealed class ShockGripVisualRelay : MonoBehaviour
	{
		private PlayerAvatar _player;

		private PhotonView _photonView;

		private void Awake()
		{
			_player = ((Component)this).GetComponent<PlayerAvatar>();
			_photonView = ((Component)this).GetComponent<PhotonView>();
		}

		internal static void Ensure(PlayerAvatar player)
		{
			if (!((Object)(object)player == (Object)null) && (Object)(object)((Component)player).GetComponent<ShockGripVisualRelay>() == (Object)null)
			{
				((Component)player).gameObject.AddComponent<ShockGripVisualRelay>();
			}
		}

		internal static void Broadcast(PlayerAvatar holder)
		{
			if ((Object)(object)holder == (Object)null)
			{
				return;
			}
			Ensure(holder);
			PhotonView photonView = holder.photonView;
			if (!((Object)(object)photonView == (Object)null))
			{
				if (GameManager.Multiplayer())
				{
					photonView.RPC("ShockGripVisualRPC", (RpcTarget)0, Array.Empty<object>());
				}
				else
				{
					ShockGripVisuals.PlayLocal(holder);
				}
			}
		}

		[PunRPC]
		private void ShockGripVisualRPC(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			if ((Object)(object)_player == (Object)null)
			{
				_player = ((Component)this).GetComponent<PlayerAvatar>();
			}
			ShockGripVisuals.PlayLocal(_player);
		}
	}
	internal static class ShockGripVisuals
	{
		private static readonly Dictionary<int, ShockGripBeamEffect> Effects = new Dictionary<int, ShockGripBeamEffect>();

		internal static void PlayLocal(PlayerAvatar holder)
		{
			if ((Object)(object)holder == (Object)null || (Object)(object)holder.physGrabber == (Object)null)
			{
				return;
			}
			PhysGrabBeam physGrabBeamComponent = holder.physGrabber.physGrabBeamComponent;
			if (!((Object)(object)physGrabBeamComponent == (Object)null))
			{
				int instanceID = ((Object)holder).GetInstanceID();
				if (!Effects.TryGetValue(instanceID, out var value) || (Object)(object)value == (Object)null)
				{
					value = ((Component)physGrabBeamComponent).gameObject.AddComponent<ShockGripBeamEffect>();
					value.Setup(physGrabBeamComponent);
					Effects[instanceID] = value;
				}
				value.Play();
			}
		}
	}
	internal sealed class ShockGripBeamEffect : MonoBehaviour
	{
		private const int BoltCount = 5;

		private const int PointsPerBolt = 4;

		private PhysGrabBeam _beam;

		private readonly List<LineRenderer> _bolts = new List<LineRenderer>();

		private float _timer;

		private float _redrawTimer;

		private Material _beamMaterial;

		private Color _beamOriginalColor;

		private bool _hasBeamOriginalColor;

		internal void Setup(PhysGrabBeam beam)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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)
			_beam = beam;
			if ((Object)(object)beam.lineRenderer != (Object)null)
			{
				_beamMaterial = ((Renderer)beam.lineRenderer).material;
				if ((Object)(object)_beamMaterial != (Object)null && _beamMaterial.HasProperty("_Color"))
				{
					_beamOriginalColor = _beamMaterial.color;
					_hasBeamOriginalColor = true;
				}
			}
			Color val3 = default(Color);
			for (int i = 0; i < 5; i++)
			{
				GameObject val = new GameObject($"Extra Battle Upgrades Shock Grip Bolt {i}");
				val.transform.SetParent(((Component)beam).transform, false);
				LineRenderer val2 = val.AddComponent<LineRenderer>();
				val2.positionCount = 4;
				val2.useWorldSpace = true;
				((Renderer)val2).enabled = false;
				((Renderer)val2).material = new Material(Shader.Find("Sprites/Default"));
				val2.widthMultiplier = 0.025f;
				val2.numCapVertices = 2;
				val2.numCornerVertices = 2;
				((Color)(ref val3))..ctor(0.05f, 0.85f, 1f, 0.9f);
				val2.startColor = val3;
				val2.endColor = new Color(0.25f, 0.95f, 1f, 0.55f);
				((Renderer)val2).material.color = val3;
				_bolts.Add(val2);
			}
		}

		internal void Play()
		{
			_timer = 0.28f;
			_redrawTimer = 0f;
			foreach (LineRenderer bolt in _bolts)
			{
				((Renderer)bolt).enabled = true;
			}
		}

		private void LateUpdate()
		{
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_beam == (Object)null || _bolts.Count == 0)
			{
				return;
			}
			if (_timer <= 0f)
			{
				foreach (LineRenderer bolt in _bolts)
				{
					((Renderer)bolt).enabled = false;
				}
				RestoreBeamColor();
				return;
			}
			_timer -= Time.deltaTime;
			_redrawTimer -= Time.deltaTime;
			float num = 0.45f + Mathf.Sin(Time.time * 18f) * 0.25f;
			float num2 = Mathf.Clamp01(_timer / 0.28f);
			float num3 = Mathf.Clamp01((0.35f + num) * num2);
			PulseBeamColor(num3);
			Color val = default(Color);
			Color endColor = default(Color);
			foreach (LineRenderer bolt2 in _bolts)
			{
				((Color)(ref val))..ctor(0.05f, 0.85f, 1f, num3);
				((Color)(ref endColor))..ctor(0.25f, 0.95f, 1f, num3 * 0.55f);
				bolt2.startColor = val;
				bolt2.endColor = endColor;
				if ((Object)(object)((Renderer)bolt2).material != (Object)null)
				{
					((Renderer)bolt2).material.color = val;
				}
			}
			if (_redrawTimer <= 0f)
			{
				_redrawTimer = 0.045f;
				DrawBolts();
			}
		}

		private void DrawBolts()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: 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_0197: 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_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_beam.PhysGrabPointOrigin == (Object)null || (Object)(object)_beam.PhysGrabPoint == (Object)null || (Object)(object)_beam.PhysGrabPointPuller == (Object)null)
			{
				Disable();
				return;
			}
			Vector3 position = _beam.PhysGrabPointOrigin.position;
			Vector3 val = _beam.PhysGrabPoint.position - position;
			if (((Vector3)(ref val)).magnitude <= 0.2f)
			{
				Disable();
				return;
			}
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			Vector3 val2 = (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform.forward : Vector3.forward);
			Vector3 val3 = Vector3.Cross(normalized, val2);
			Vector3 normalized2 = ((Vector3)(ref val3)).normalized;
			if (((Vector3)(ref normalized2)).sqrMagnitude < 0.001f)
			{
				val3 = Vector3.Cross(normalized, Vector3.up);
				normalized2 = ((Vector3)(ref val3)).normalized;
			}
			val3 = Vector3.Cross(normalized2, normalized);
			Vector3 normalized3 = ((Vector3)(ref val3)).normalized;
			for (int i = 0; i < _bolts.Count; i++)
			{
				LineRenderer val4 = _bolts[i];
				float num = Random.Range(0.02f, 0.72f);
				float num2 = Random.Range(0.08f, 0.18f);
				for (int j = 0; j < 4; j++)
				{
					float num3 = (float)j / 3f;
					float t = Mathf.Clamp01(num + num2 * num3);
					Vector3 val5 = CalculateBeamPoint(t);
					float num4 = Random.Range(0.035f, 0.09f);
					float num5 = Random.Range(0f, MathF.PI * 2f);
					Vector3 val6 = normalized2 * Mathf.Cos(num5) * num4 + normalized3 * Mathf.Sin(num5) * num4;
					Vector3 val7 = normalized2 * Random.Range(-0.035f, 0.035f) + normalized3 * Random.Range(-0.035f, 0.035f);
					val4.SetPosition(j, val5 + val6 + val7);
				}
			}
		}

		private void Disable()
		{
			foreach (LineRenderer bolt in _bolts)
			{
				((Renderer)bolt).enabled = false;
			}
		}

		private Vector3 CalculateBeamPoint(float t)
		{
			//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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = _beam.PhysGrabPointOrigin.position;
			Vector3 position2 = _beam.PhysGrabPoint.position;
			Vector3 position3 = _beam.PhysGrabPointPuller.position;
			_beam.physGrabPointPullerSmoothPosition = Vector3.Lerp(_beam.physGrabPointPullerSmoothPosition, position3, Time.deltaTime * 10f);
			Vector3 val = _beam.physGrabPointPullerSmoothPosition * _beam.CurveStrength;
			return Mathf.Pow(1f - t, 2f) * position + 2f * (1f - t) * t * val + Mathf.Pow(t, 2f) * position2;
		}

		private void PulseBeamColor(float alpha)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if (_hasBeamOriginalColor && !((Object)(object)_beamMaterial == (Object)null))
			{
				Color val = Color.Lerp(new Color(0.05f, 0.85f, 1f, _beamOriginalColor.a), Color.white, 0.65f);
				float num = Mathf.Sin(Time.time * 22f) * 0.5f + 0.5f;
				float num2 = Mathf.Clamp01(alpha * num * 0.65f);
				_beamMaterial.color = Color.Lerp(_beamOriginalColor, val, num2);
			}
		}

		private void RestoreBeamColor()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (_hasBeamOriginalColor && (Object)(object)_beamMaterial != (Object)null)
			{
				_beamMaterial.color = _beamOriginalColor;
			}
		}
	}
}
namespace ExtraBattleUpgrades.Upgrades
{
	internal sealed class ArmorShopUpgrade : ShopUpgrade
	{
		internal const string StatsDictionaryKey = "playerUpgradeArmor";

		private readonly ConfigEntry<float> _bonusPerLevelFirstTen;

		private readonly ConfigEntry<float> _bonusPerLevelAfterTen;

		protected override string UpgradeId => "Armor";

		internal ArmorShopUpgrade(ConfigFile config, AssetBundle bundle)
			: base(config, bundle, "Armor", "assets/extrabattleupgrades/items/item upgrade player armor.prefab", 1f)
		{
			_bonusPerLevelFirstTen = config.Bind<float>("Armor Upgrade", "Bonus Per Level First Ten", 0.05f, "Damage Reduction per Armor level 1 to 10. 0.05 = 5%.");
			_bonusPerLevelAfterTen = config.Bind<float>("Armor Upgrade", "Damage Reduction Per Level After Ten", 0.05f, "Damage reduction per Armor level 10. 0.01 = 1%.");
		}

		internal int ReduceDamage(int damage, PlayerAvatar player)
		{
			int level = GetLevel(player);
			if (damage <= 0 || level <= 0)
			{
				return damage;
			}
			float num = Math.Max(0f, 1f - DamageReduction(level));
			return Math.Max(1, (int)Math.Ceiling((float)damage * num));
		}

		private float DamageReduction(int level)
		{
			int num = Math.Min(level, 10);
			int num2 = Math.Max(0, level - 10);
			return (float)num * Math.Max(0f, _bonusPerLevelFirstTen.Value) + (float)num2 * Math.Max(0f, _bonusPerLevelAfterTen.Value);
		}
	}
	internal sealed class EnergyLeechShopUpgrade : ShopUpgrade
	{
		internal const string StatsDictionaryKey = "playerUpgradeEnergyLeech";

		private readonly ConfigEntry<float> _bonusPerLevelFirstTen;

		private readonly ConfigEntry<float> _bonusPerLevelAfterTen;

		protected override string UpgradeId => "EnergyLeech";

		internal EnergyLeechShopUpgrade(ConfigFile config, AssetBundle bundle)
			: base(config, bundle, "Energy Leech", "assets/extrabattleupgrades/items/item upgrade player energy leech.prefab", 1f)
		{
			_bonusPerLevelFirstTen = config.Bind<float>("Energy Leech Upgrade", "Healing Percent Per Level First Ten", 0.025f, "Healing Percent Per Energy Leech level from level 1 to 10. 0.025 = 2.5%.");
			_bonusPerLevelAfterTen = config.Bind<float>("Energy Leech Upgrade", "Healing Percent Per Level After Ten", 0.01f, "Percent Of Steel HP per Energy Leech level after level 10. 0.01 = 1%.");
		}

		internal int HealingFromDamage(int damage, PlayerAvatar player)
		{
			int level = GetLevel(player);
			if (damage <= 0 || level <= 0)
			{
				return 0;
			}
			return Math.Max(1, (int)Math.Ceiling((float)damage * HealingPercent(level)));
		}

		private float HealingPercent(int level)
		{
			int num = Math.Min(level, 10);
			int num2 = Math.Max(0, level - 10);
			return (float)num * Math.Max(0f, _bonusPerLevelFirstTen.Value) + (float)num2 * Math.Max(0f, _bonusPerLevelAfterTen.Value);
		}
	}
	internal sealed class OverchargeShopUpgrade : ShopUpgrade
	{
		internal const string StatsDictionaryKey = "playerUpgradeOvercharge";

		private readonly ConfigEntry<float> _bonusPerLevelFirstTen;

		private readonly ConfigEntry<float> _bonusPerLevelAfterTen;

		private readonly ConfigEntry<float> _holdStabilityEffectMultiplier;

		private readonly ConfigEntry<float> _recoveryBasePerSecond;

		protected override string UpgradeId => "Overcharge";

		internal OverchargeShopUpgrade(ConfigFile config, AssetBundle bundle)
			: base(config, bundle, "Overcharge", "assets/extrabattleupgrades/items/item upgrade player overcharge.prefab", 0.75f)
		{
			_bonusPerLevelFirstTen = config.Bind<float>("Overcharge Upgrade", "Bonus Per Level First Ten", 0.1f, "Bonus per Overcharge level from level 1 to 10. 0.10 = 10%.");
			_bonusPerLevelAfterTen = config.Bind<float>("Overcharge Upgrade", "Bonus Per Level After Ten", 0.05f, "Bonus per Overcharge level after level 10. 0.05 = 5%.");
			_holdStabilityEffectMultiplier = config.Bind<float>("Overcharge Upgrade", "Hold Stability Effect Multiplier", 0.25f, "How strongly Overcharge affects enemy hold stability. 0.25 = 25% of the Overcharge bonus.");
			_recoveryBasePerSecond = config.Bind<float>("Overcharge Upgrade", "Recovery Base Per Second", 0.1f, "Base vanilla overcharge recovery per second used by this mod. Default vanilla-like value is 0.1.");
		}

		internal float SlowOvercharge(float value, PlayerAvatar player)
		{
			int level = GetLevel(player);
			if (value <= 0f || level <= 0)
			{
				return value;
			}
			return value / (1f + BonusMultiplier(player));
		}

		internal float BonusMultiplier(PlayerAvatar player)
		{
			return BonusTime(GetLevel(player));
		}

		internal float HoldStabilityBonus(PlayerAvatar player)
		{
			return BonusMultiplier(player) * _holdStabilityEffectMultiplier.Value;
		}

		internal float RecoveryBasePerSecond()
		{
			return Mathf.Max(0f, _recoveryBasePerSecond.Value);
		}

		private float BonusTime(int level)
		{
			if (level <= 0)
			{
				return 0f;
			}
			int num = Math.Min(level, 10);
			int num2 = Math.Max(0, level - 10);
			return (float)num * Mathf.Max(0f, _bonusPerLevelFirstTen.Value) + (float)num2 * Mathf.Max(0f, _bonusPerLevelAfterTen.Value);
		}
	}
	internal sealed class PanicResponseShopUpgrade : ShopUpgrade
	{
		internal const string StatsDictionaryKey = "playerUpgradePanicResponse";

		private readonly ConfigEntry<float> _durationLevel1;

		private readonly ConfigEntry<float> _durationLevel2To3;

		private readonly ConfigEntry<float> _durationLevel4Plus;

		private readonly ConfigEntry<float> _cooldownBase;

		private readonly ConfigEntry<float> _cooldownReductionStartLevel;

		private readonly ConfigEntry<float> _cooldownReductionPerLevel;

		private readonly ConfigEntry<float> _cooldownMin;

		private readonly ConfigEntry<float> _speedMultiplierLevel1To2;

		private readonly ConfigEntry<float> _speedMultiplierLevel3Plus;

		protected override string UpgradeId => "PanicResponse";

		internal PanicResponseShopUpgrade(ConfigFile config, AssetBundle bundle)
			: base(config, bundle, "Panic Response", "assets/extrabattleupgrades/items/item upgrade player panic response.prefab", 1f)
		{
			_durationLevel1 = config.Bind<float>("Panic Response Upgrade", "Duration Level 1", 5f, "Panic Response duration at level 1, in seconds.");
			_durationLevel2To3 = config.Bind<float>("Panic Response Upgrade", "Duration Level 2 To 3", 6f, "Panic Response duration from level 2 to level 3, in seconds.");
			_durationLevel4Plus = config.Bind<float>("Panic Response Upgrade", "Duration Level 4 Plus", 7f, "Panic Response duration from level 4 and above, in seconds.");
			_cooldownBase = config.Bind<float>("Panic Response Upgrade", "Cooldown Base", 60f, "Base Panic Response cooldown, in seconds.");
			_cooldownReductionStartLevel = config.Bind<float>("Panic Response Upgrade", "Cooldown Reduction Start Level", 5f, "Level where cooldown reduction starts. Default 5 means level 5+ starts reducing cooldown.");
			_cooldownReductionPerLevel = config.Bind<float>("Panic Response Upgrade", "Cooldown Reduction Per Level", 5f, "Cooldown reduction per level after the reduction start level, in seconds.");
			_cooldownMin = config.Bind<float>("Panic Response Upgrade", "Cooldown Minimum", 30f, "Minimum Panic Response cooldown, in seconds.");
			_speedMultiplierLevel1To2 = config.Bind<float>("Panic Response Upgrade", "Speed Multiplier Level 1 To 2", 1.2f, "Speed multiplier from level 1 to level 2. 1.2 = 20% faster.");
			_speedMultiplierLevel3Plus = config.Bind<float>("Panic Response Upgrade", "Speed Multiplier Level 3 Plus", 1.35f, "Speed multiplier from level 3 and above. 1.35 = 35% faster.");
		}

		internal float DurationSeconds(PlayerAvatar player)
		{
			int num = Math.Min(GetLevel(player), 10);
			if (num <= 0)
			{
				return 0f;
			}
			if (num == 1)
			{
				return Math.Max(0f, _durationLevel1.Value);
			}
			if (num <= 3)
			{
				return Math.Max(0f, _durationLevel2To3.Value);
			}
			return Math.Max(0f, _durationLevel4Plus.Value);
		}

		internal float CooldownSeconds(PlayerAvatar player)
		{
			int num = Math.Min(GetLevel(player), 10);
			if (num <= 0)
			{
				return 9999f;
			}
			float num2 = Math.Max(0f, _cooldownBase.Value);
			float val = Math.Max(0f, _cooldownMin.Value);
			int num3 = Math.Max(1, Mathf.RoundToInt(_cooldownReductionStartLevel.Value));
			if (num < num3)
			{
				return num2;
			}
			float num4 = (float)(num - num3 + 1) * Math.Max(0f, _cooldownReductionPerLevel.Value);
			return Math.Max(val, num2 - num4);
		}

		internal float SpeedMultiplier(PlayerAvatar player)
		{
			int num = Math.Min(GetLevel(player), 10);
			if (num <= 0)
			{
				return 1f;
			}
			if (num <= 2)
			{
				return Math.Max(1f, _speedMultiplierLevel1To2.Value);
			}
			return Math.Max(1f, _speedMultiplierLevel3Plus.Value);
		}
	}
	internal sealed class SecondChanceShopUpgrade : ShopUpgrade
	{
		private readonly Dictionary<string, float> _cooldownEnds = new Dictionary<string, float>();

		private readonly Dictionary<string, float> _protectionEnds = new Dictionary<string, float>();

		internal const string StatsDictionaryKey = "playerUpgradeSecondChance";

		private readonly ConfigEntry<float> _invulnerabilitySecondsPerLevel;

		private readonly ConfigEntry<int> _invulnerabilityMaxScalingLevel;

		private readonly ConfigEntry<float> _cooldownBase;

		private readonly ConfigEntry<int> _cooldownReductionStartLevel;

		private readonly ConfigEntry<int> _cooldownFastReductionMaxLevel;

		private readonly ConfigEntry<float> _cooldownReductionPerLevel;

		private readonly ConfigEntry<float> _cooldownReductionPerExtraLevel;

		private readonly ConfigEntry<float> _cooldownMin;

		protected override string UpgradeId => "SecondChance";

		internal SecondChanceShopUpgrade(ConfigFile config, AssetBundle bundle)
			: base(config, bundle, "Second Chance", "assets/extrabattleupgrades/items/item upgrade player second chance.prefab", 1f)
		{
			_invulnerabilitySecondsPerLevel = config.Bind<float>("Second Chance Upgrade", "Invulnerability Seconds Per Level", 1f, "Invulnerability duration gained per level before the cap. 1 = 1 second.");
			_invulnerabilityMaxScalingLevel = config.Bind<int>("Second Chance Upgrade", "Invulnerability Max Scaling Level", 5, "Level where invulnerability duration stops increasing.");
			_cooldownBase = config.Bind<float>("Second Chance Upgrade", "Cooldown Base", 120f, "Base Second Chance cooldown, in seconds.");
			_cooldownReductionStartLevel = config.Bind<int>("Second Chance Upgrade", "Cooldown Reduction Start Level", 6, "Level where cooldown reduction starts.");
			_cooldownFastReductionMaxLevel = config.Bind<int>("Second Chance Upgrade", "Cooldown Fast Reduction Max Level", 10, "Last level that uses the main cooldown reduction value.");
			_cooldownReductionPerLevel = config.Bind<float>("Second Chance Upgrade", "Cooldown Reduction Per Level", 5f, "Cooldown reduction per level during the main reduction range, in seconds.");
			_cooldownReductionPerExtraLevel = config.Bind<float>("Second Chance Upgrade", "Cooldown Reduction Per Extra Level", 0.5f, "Cooldown reduction per level after the fast reduction range, in seconds.");
			_cooldownMin = config.Bind<float>("Second Chance Upgrade", "Cooldown Minimum", 30f, "Minimum Second Chance cooldown, in seconds.");
		}

		internal bool TryActivate(PlayerAvatar player, out float invulnerabilitySeconds)
		{
			invulnerabilitySeconds = 0f;
			int level = GetLevel(player);
			if (level <= 0)
			{
				return false;
			}
			string text = PlayerId(player);
			if (string.IsNullOrWhiteSpace(text))
			{
				return false;
			}
			float time = Time.time;
			if (_cooldownEnds.TryGetValue(text, out var value) && value > time)
			{
				return false;
			}
			invulnerabilitySeconds = InvulnerabilitySeconds(level);
			_protectionEnds[text] = time + invulnerabilitySeconds;
			_cooldownEnds[text] = time + CooldownSeconds(level);
			return true;
		}

		internal bool TryRescueFromPit(PlayerAvatar player, out float invulnerabilitySeconds, out bool activatedNow)
		{
			activatedNow = false;
			invulnerabilitySeconds = RemainingProtectionSeconds(player);
			if (invulnerabilitySeconds > 0f)
			{
				return true;
			}
			activatedNow = TryActivate(player, out invulnerabilitySeconds);
			return activatedNow;
		}

		internal float RemainingProtectionSeconds(PlayerAvatar player)
		{
			string text = PlayerId(player);
			if (string.IsNullOrWhiteSpace(text) || !_protectionEnds.TryGetValue(text, out var value))
			{
				return 0f;
			}
			return Math.Max(0f, value - Time.time);
		}

		internal float RemainingCooldownSeconds(PlayerAvatar player)
		{
			string text = PlayerId(player);
			if (string.IsNullOrWhiteSpace(text) || !_cooldownEnds.TryGetValue(text, out var value))
			{
				return 0f;
			}
			return Math.Max(0f, value - Time.time);
		}

		internal bool IsReady(PlayerAvatar player)
		{
			if ((Object)(object)player != (Object)null && base.Enabled.Value && base.RegisteredUpgrade != null && GetLevel(player) > 0)
			{
				return RemainingCooldownSeconds(player) <= 0f;
			}
			return false;
		}

		internal bool HasUpgrade(PlayerAvatar player)
		{
			if ((Object)(object)player != (Object)null && base.Enabled.Value && base.RegisteredUpgrade != null)
			{
				return GetLevel(player) > 0;
			}
			return false;
		}

		internal void ResetState()
		{
			_cooldownEnds.Clear();
			_protectionEnds.Clear();
		}

		private float InvulnerabilitySeconds(int level)
		{
			int val = Math.Max(1, _invulnerabilityMaxScalingLevel.Value);
			int num = Math.Min(level, val);
			return Math.Max(0f, (float)num * _invulnerabilitySecondsPerLevel.Value);
		}

		private float CooldownSeconds(int level)
		{
			float num = Math.Max(0f, _cooldownBase.Value);
			float val = Math.Max(0f, _cooldownMin.Value);
			int num2 = Math.Max(1, _cooldownReductionStartLevel.Value);
			int num3 = Math.Max(num2, _cooldownFastReductionMaxLevel.Value);
			float num4 = 0f;
			if (level >= num2)
			{
				int val2 = Math.Min(level, num3) - num2 + 1;
				num4 += (float)Math.Max(0, val2) * Math.Max(0f, _cooldownReductionPerLevel.Value);
			}
			if (level > num3)
			{
				int num5 = level - num3;
				num4 += (float)num5 * Math.Max(0f, _cooldownReductionPerExtraLevel.Value);
			}
			return Math.Max(val, num - num4);
		}

		private static string PlayerId(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return string.Empty;
			}
			string text = SemiFunc.PlayerGetSteamID(player);
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			return ((Object)player).GetInstanceID().ToString();
		}
	}
	internal sealed class ShockGripShopUpgrade : ShopUpgrade
	{
		internal const string StatsDictionaryKey = "playerUpgradeShockGrip";

		private readonly ConfigEntry<int> _damagePerLevelFirstTen;

		private readonly ConfigEntry<int> _damagePerLevelAfterTen;

		protected override string UpgradeId => "ShockGrip";

		internal ShockGripShopUpgrade(ConfigFile config, AssetBundle bundle)
			: base(config, bundle, "Shock Grip", "assets/extrabattleupgrades/items/item upgrade player shock grip.prefab", 1f)
		{
			_damagePerLevelFirstTen = config.Bind<int>("Shock Grip Upgrade", "Damage Per Level First Ten", 2, "Damage per second gained per Shock Grip level from level 1 to 10.");
			_damagePerLevelAfterTen = config.Bind<int>("Shock Grip Upgrade", "Damage Per Level After Ten", 1, "Damage per second gained per Shock Grip level after level 10.");
		}

		internal int DamagePerSecond(PlayerAvatar player)
		{
			int level = GetLevel(player);
			if (level <= 0)
			{
				return 0;
			}
			int num = Math.Min(level, 10);
			int num2 = Math.Max(0, level - 10);
			return num * Math.Max(0, _damagePerLevelFirstTen.Value) + num2 * Math.Max(0, _damagePerLevelAfterTen.Value);
		}
	}
	internal abstract class ShopUpgrade
	{
		private readonly AssetBundle _bundle;

		private readonly string _prefabPath;

		private readonly string _label;

		private readonly float _defaultPriceMultiplier;

		internal ConfigEntry<bool> Enabled { get; }

		internal ConfigEntry<float> PriceMultiplier { get; }

		internal PlayerUpgrade RegisteredUpgrade { get; private set; }

		protected abstract string UpgradeId { get; }

		protected ShopUpgrade(ConfigFile config, AssetBundle bundle, string label, string prefabPath, float defaultPriceMultiplier)
		{
			_bundle = bundle;
			_prefabPath = prefabPath;
			_label = label;
			_defaultPriceMultiplier = defaultPriceMultiplier;
			string text = _label + " Upgrade";
			Enabled = config.Bind<bool>(text, "Enabled", true, "Enable the " + _label + " upgrade.");
			PriceMultiplier = config.Bind<float>(text, "Price Multiplier", _defaultPriceMultiplier, "Multiplier applied to the base shop price.");
		}

		internal void Register()
		{
			if (!Enabled.Value)
			{
				ExtraBattleUpgradesPlugin.Log.LogInfo((object)(_label + " upgrade disabled by config."));
				return;
			}
			GameObject val = _bundle.LoadAsset<GameObject>(_prefabPath);
			ItemAttributes val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemAttributes>() : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val2.item == (Object)null)
			{
				ExtraBattleUpgradesPlugin.Log.LogError((object)("Could not load " + _label + " upgrade prefab '" + _prefabPath + "'."));
				return;
			}
			Item item = val2.item;
			item.value = MakePriceRange(item.value, PriceMultiplier.Value);
			Items.RegisterItem(val2);
			RegisteredUpgrade = Upgrades.RegisterUpgrade(UpgradeId, item, (Action<PlayerAvatar, int>)OnRunStart, (Action<PlayerAvatar, int>)OnUpgradeBought);
			if (RegisteredUpgrade == null)
			{
				ExtraBattleUpgradesPlugin.Log.LogError((object)("Failed to register " + _label + " upgrade with REPOLib."));
			}
			else
			{
				ExtraBattleUpgradesPlugin.Log.LogInfo((object)("Registered " + _label + " upgrade."));
			}
		}

		internal int GetLevel(PlayerAvatar player)
		{
			if (!((Object)(object)player == (Object)null))
			{
				PlayerUpgrade registeredUpgrade = RegisteredUpgrade;
				if (registeredUpgrade == null)
				{
					return 0;
				}
				return registeredUpgrade.GetLevel(player);
			}
			return 0;
		}

		protected virtual void OnRunStart(PlayerAvatar player, int level)
		{
			if ((Object)(object)player != (Object)null && player == SemiFunc.PlayerAvatarLocal())
			{
				ExtraBattleUpgradesPlugin.Log.LogDebug((object)$"Initialized {_label} level {level} for {SemiFunc.PlayerGetName(player)}.");
			}
		}

		protected virtual void OnUpgradeBought(PlayerAvatar player, int level)
		{
			if ((Object)(object)player != (Object)null && player == SemiFunc.PlayerAvatarLocal())
			{
				ExtraBattleUpgradesPlugin.Log.LogDebug((object)$"Applied {_label} level {level} for {SemiFunc.PlayerGetName(player)}.");
			}
		}

		private static Value MakePriceRange(Value source, float multiplier)
		{
			Value val = ScriptableObject.CreateInstance<Value>();
			if ((Object)(object)source == (Object)null)
			{
				val.valueMin = 100f * multiplier;
				val.valueMax = 200f * multiplier;
				return val;
			}
			val.valueMin = source.valueMin * multiplier;
			val.valueMax = source.valueMax * multiplier;
			return val;
		}
	}
}
namespace ExtraBattleUpgrades.Patches
{
	[HarmonyPatch(typeof(PlayerHealth), "Hurt")]
	internal static class ArmorDamagePatch
	{
		private static void Prefix(ref int damage, PlayerAvatar ___playerAvatar)
		{
			ApplyProtection(ref damage, ___playerAvatar);
		}

		private static void ApplyProtection(ref int damage, PlayerAvatar player)
		{
			if (damage > 0 && !((Object)(object)player == (Object)null) && ExtraBattleUpgradesPlugin.Armor != null && ExtraBattleUpgradesPlugin.Armor.Enabled.Value && ExtraBattleUpgradesPlugin.Armor.RegisteredUpgrade != null)
			{
				damage = ExtraBattleUpgradesPlugin.Armor.ReduceDamage(damage, player);
			}
		}
	}
	[HarmonyPatch]
	internal static class BattleUpgradeStatusUIPatch
	{
		private static readonly Color PanicActiveColor = new Color(0.1f, 0.85f, 1f, 1f);

		private static readonly Color PanicReadyColor = new Color(1f, 0.25f, 0.75f, 1f);

		private static readonly Color SecondChanceActiveColor = new Color(0.1f, 0.85f, 1f, 1f);

		private static readonly Color SecondChanceReadyColor = new Color(1f, 0.86f, 0.05f, 1f);

		private static readonly Color CooldownColor = new Color(0.45f, 0.45f, 0.45f, 1f);

		private static readonly FieldRef<EnergyUI, TextMeshProUGUI> EnergyTextRef = AccessTools.FieldRefAccess<EnergyUI, TextMeshProUGUI>("Text");

		private static readonly FieldRef<HealthUI, TextMeshProUGUI> HealthTextRef = AccessTools.FieldRefAccess<HealthUI, TextMeshProUGUI>("Text");

		private static Image _panicIcon;

		private static Image _secondChanceIcon;

		private static Color? _energyDefaultColor;

		private static Color? _healthDefaultColor;

		[HarmonyPatch(typeof(EnergyUI), "Update")]
		[HarmonyPostfix]
		private static void EnergyUIPostfix(EnergyUI __instance)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar val = PlayerController.instance?.playerAvatarScript;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			TextMeshProUGUI val2 = EnergyTextRef.Invoke(__instance);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			Color valueOrDefault = _energyDefaultColor.GetValueOrDefault();
			if (!_energyDefaultColor.HasValue)
			{
				valueOrDefault = ((Graphic)val2).color;
				_energyDefaultColor = valueOrDefault;
			}
			EnsurePanicIcon(((Component)__instance).transform, val2);
			bool flag = PanicResponsePatch.HasUpgrade(val);
			bool active = ExtraBattleUpgradesPlugin.HudConfig.PanicIconEnabled.Value && flag;
			((Component)_panicIcon).gameObject.SetActive(active);
			if (flag)
			{
				if (PanicResponsePatch.IsActive(val))
				{
					SetTextColor(val2, PanicActiveColor);
				}
				else
				{
					SetTextColor(val2, _energyDefaultColor.Value);
				}
				((Graphic)_panicIcon).color = (PanicResponsePatch.IsReady(val) ? PanicReadyColor : CooldownColor);
			}
		}

		[HarmonyPatch(typeof(HealthUI), "Update")]
		[HarmonyPostfix]
		private static void HealthUIPostfix(HealthUI __instance)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar val = PlayerController.instance?.playerAvatarScript;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			TextMeshProUGUI val2 = HealthTextRef.Invoke(__instance);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			Color valueOrDefault = _healthDefaultColor.GetValueOrDefault();
			if (!_healthDefaultColor.HasValue)
			{
				valueOrDefault = ((Graphic)val2).color;
				_healthDefaultColor = valueOrDefault;
			}
			EnsureSecondChanceIcon(((Component)__instance).transform, val2);
			SecondChanceShopUpgrade secondChance = ExtraBattleUpgradesPlugin.SecondChance;
			bool flag = secondChance?.HasUpgrade(val) ?? false;
			bool active = ExtraBattleUpgradesPlugin.HudConfig.SecondChanceIconEnabled.Value && flag;
			((Component)_secondChanceIcon).gameObject.SetActive(active);
			if (flag)
			{
				if (secondChance.RemainingProtectionSeconds(val) > 0f)
				{
					SetTextColor(val2, SecondChanceActiveColor);
				}
				else
				{
					SetTextColor(val2, _healthDefaultColor.Value);
				}
				((Graphic)_secondChanceIcon).color = (secondChance.IsReady(val) ? SecondChanceReadyColor : CooldownColor);
			}
		}

		private static void EnsurePanicIcon(Transform parent, TextMeshProUGUI sourceText)
		{
			//IL_003f: 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)
			if (!((Object)(object)_panicIcon != (Object)null))
			{
				BattleUpgradeHudConfig hudConfig = ExtraBattleUpgradesPlugin.HudConfig;
				_panicIcon = CreateIcon(((TMP_Text)sourceText).transform, BattleUpgradeIconPainter.LightningSprite(), "Panic Response Icon", new Vector3(hudConfig.PanicIconX.Value, hudConfig.PanicIconY.Value, 0f), new Vector2(hudConfig.PanicIconSize.Value, hudConfig.PanicIconSize.Value));
			}
		}

		private static void EnsureSecondChanceIcon(Transform parent, TextMeshProUGUI sourceText)
		{
			//IL_003f: 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)
			if (!((Object)(object)_secondChanceIcon != (Object)null))
			{
				BattleUpgradeHudConfig hudConfig = ExtraBattleUpgradesPlugin.HudConfig;
				_secondChanceIcon = CreateIcon(((TMP_Text)sourceText).transform, BattleUpgradeIconPainter.HeartSprite(), "Second Chance Icon", new Vector3(hudConfig.SecondChanceIconX.Value, hudConfig.SecondChanceIconY.Value, 0f), new Vector2(hudConfig.SecondChanceIconSize.Value, hudConfig.SecondChanceIconSize.Value));
			}
		}

		private static Image CreateIcon(Transform parent, Sprite sprite, string objectName, Vector3 localOffset, Vector2 size)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(objectName, new Type[1] { typeof(RectTransform) });
			Type type = Type.GetType("UnityEngine.CanvasRenderer, UnityEngine.CoreModule");
			if (type != null)
			{
				val.AddComponent(type);
			}
			val.transform.SetParent(parent, false);
			val.transform.localPosition = localOffset;
			val.transform.localScale = Vector3.one;
			val.GetComponent<RectTransform>().sizeDelta = size;
			Image obj = val.AddComponent<Image>();
			obj.sprite = sprite;
			((Graphic)obj).color = CooldownColor;
			((Graphic)obj).raycastTarget = false;
			obj.preserveAspect = true;
			return obj;
		}

		private static void SetTextColor(TextMeshProUGUI text, Color color)
		{
			//IL_0001: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			((Graphic)text).color = color;
			((TMP_Text)text).fontMaterial.SetColor(ShaderUtilities.ID_FaceColor, color);
			((TMP_Text)text).fontMaterial.SetColor(ShaderUtilities.ID_GlowColor, color);
		}
	}
	[HarmonyPatch(typeof(EnemyHealth), "Hurt")]
	internal static class EnergyLeechDamagePatch
	{
		private readonly struct DamageSnapshot
		{
			internal readonly int HealthBefore;

			internal readonly PlayerAvatar[] Owners;

			internal DamageSnapshot(int healthBefore, PlayerAvatar[] owners)
			{
				HealthBefore = healthBefore;
				Owners = owners;
			}
		}

		private static void Prefix(int ___healthCurrent, out DamageSnapshot __state)
		{
			__state = new DamageSnapshot(___healthCurrent, CombatDamageTracker.CurrentOwners);
		}

		private static void Postfix(int ___healthCurrent, DamageSnapshot __state)
		{
			CombatDamageTracker.ApplyEnergyLeech(__state.HealthBefore - ___healthCurrent, __state.Owners);
		}
	}
	[HarmonyPatch(typeof(HurtCollider), "EnemyHurt")]
	internal static class EnergyLeechHurtColliderPatch
	{
		private static void Prefix(HurtCollider __instance, PlayerAvatar ___playerCausingHurt, PlayerAvatar ___playerCausingHurtOverride, PhysGrabObject ___parentPhysGrabObject)
		{
			if (__instance.deathPit)
			{
				CombatDamageTracker.Push(null);
			}
			else if ((Object)(object)___playerCausingHurtOverride != (Object)null)
			{
				CombatDamageTracker.Push(___playerCausingHurtOverride);
			}
			else if ((Object)(object)___parentPhysGrabObject != (Object)null)
			{
				CombatDamageTracker.PushFromPhysGrabObject(___parentPhysGrabObject);
			}
			else
			{
				CombatDamageTracker.Push(___playerCausingHurt);
			}
		}

		private static void Finalizer()
		{
			CombatDamageTracker.Pop();
		}
	}
	[HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "OnCollisionStay")]
	internal static class EnergyLeechHeldObjectImpactPatch
	{
		private static void Prefix(PhysGrabObject ___physGrabObject)
		{
			CombatDamageTracker.PushFromPhysGrabObject(___physGrabObject);
		}

		private static void Finalizer()
		{
			CombatDamageTracker.Pop();
		}
	}
	[HarmonyPatch(typeof(PhysGrabber))]
	internal static class OverchargeGrabPatch
	{
		private static readonly FieldRef<PhysGrabber, PlayerAvatar> OwnerRef = AccessTools.FieldRefAccess<PhysGrabber, PlayerAvatar>("playerAvatar");

		private static readonly FieldRef<PhysGrabber, float> OverchargeFloatRef = AccessTools.FieldRefAccess<PhysGrabber, float>("physGrabBeamOverChargeFloat");

		private static readonly FieldRef<PhysGrabber, byte> OverchargeByteRef = AccessTools.FieldRefAccess<PhysGrabber, byte>("physGrabBeamOverCharge");

		private static readonly FieldRef<PhysGrabber, float> OverchargeAmountRef = AccessTools.FieldRefAccess<PhysGrabber, float>("physGrabBeamOverChargeAmount");

		[HarmonyPatch("PhysGrabOverCharge")]
		[HarmonyPostfix]
		private static void ReduceFinalOverchargeGain(PhysGrabber __instance, float __state)
		{
			if (TryGetChargeUpgrade(out var player, __instance))
			{
				float value = OverchargeAmountRef.Invoke(__instance);
				float num = ExtraBattleUpgradesPlugin.Overcharge.SlowOvercharge(value, player);
				OverchargeAmountRef.Invoke(__instance) = num;
				float num2 = OverchargeFloatRef.Invoke(__instance);
				if (!(num2 <= __state))
				{
					float value2 = num2 - __state;
					float num3 = ExtraBattleUpgradesPlugin.Overcharge.SlowOvercharge(value2, player);
					OverchargeFloatRef.Invoke(__instance) = Mathf.Clamp01(__state + num3);
					OverchargeByteRef.Invoke(__instance) = (byte)(OverchargeFloatRef.Invoke(__instance) * 200f);
				}
			}
		}

		[HarmonyPatch("PhysGrabOverCharge")]
		[HarmonyPrefix]
		private static void RememberOverchargeBeforeGain(PhysGrabber __instance, out float __state)
		{
			__state = OverchargeFloatRef.Invoke(__instance);
		}

		[HarmonyPatch("PhysGrabOverChargeLogic")]
		[HarmonyPrefix]
		private static void RememberChargeBeforeTick(float ___physGrabBeamOverChargeFloat, out float __state)
		{
			__state = ___physGrabBeamOverChargeFloat;
		}

		[HarmonyPatch("PhysGrabOverChargeLogic")]
		[HarmonyPostfix]
		private static void ImproveChargeRecovery(PhysGrabber __instance, float __state, ref float ___physGrabBeamOverChargeFloat, ref byte ___physGrabBeamOverCharge)
		{
			if (!(__state <= 0f) && !(__state <= ___physGrabBeamOverChargeFloat) && TryGetChargeUpgrade(out var player, __instance))
			{
				float num = ExtraBattleUpgradesPlugin.Overcharge.RecoveryBasePerSecond() * Time.deltaTime;
				float num2 = ExtraBattleUpgradesPlugin.Overcharge.SlowOvercharge(num, player);
				float num3 = Math.Max(0f, num - num2);
				if (!(num3 <= 0f))
				{
					___physGrabBeamOverChargeFloat = Math.Max(0f, ___physGrabBeamOverChargeFloat - num3);
					___physGrabBeamOverCharge = (byte)(___physGrabBeamOverChargeFloat * 200f);
				}
			}
		}

		private static bool TryGetChargeUpgrade(out PlayerAvatar player, PhysGrabber grabber)
		{
			player = OwnerRef.Invoke(grabber);
			if ((Object)(object)player != (Object)null && ExtraBattleUpgradesPlugin.Overcharge != null && ExtraBattleUpgradesPlugin.Overcharge.Enabled.Value)
			{
				return ExtraBattleUpgradesPlugin.Overcharge.RegisteredUpgrade != null;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(EnemyRigidbody), "FixedUpdate")]
	internal static class OverchargeHoldPatch
	{
		private static readonly FieldRef<EnemyRigidbody, PhysGrabObject> EnemyGrabObjectRef = AccessTools.FieldRefAccess<EnemyRigidbody, PhysGrabObject>("physGrabObject");

		private static readonly FieldRef<EnemyRigidbody, float> GrabStrengthTimerRef = AccessTools.FieldRefAccess<EnemyRigidbody, float>("grabStrengthTimer");

		private static readonly FieldRef<EnemyRigidbody, float> GrabTimeCurrentRef = AccessTools.FieldRefAccess<EnemyRigidbody, float>("grabTimeCurrent");

		private static void Prefix(EnemyRigidbody __instance, ref float ___grabStrengthTimer)
		{
			PhysGrabObject val = EnemyGrabObjectRef.Invoke(__instance);
			if ((Object)(object)val == (Object)null || val.playerGrabbing == null || val.playerGrabbing.Count <= 0)
			{
				return;
			}
			float num = 0f;
			foreach (PhysGrabber item in val.playerGrabbing)
			{
				PlayerAvatar val2 = item?.playerAvatar;
				if (!((Object)(object)val2 == (Object)null))
				{
					float num2 = ExtraBattleUpgradesPlugin.Overcharge.HoldStabilityBonus(val2);
					if (num2 > num)
					{
						num = num2;
					}
				}
			}
			if (!(num <= 0f))
			{
				float num3 = GrabTimeCurrentRef.Invoke(__instance);
				GrabTimeCurrentRef.Invoke(__instance) = Mathf.Max(0f, num3 - Time.fixedDeltaTime * num);
				if (GrabStrengthTimerRef.Invoke(__instance) > 0f)
				{
					___grabStrengthTimer += Time.fixedDeltaTime * num;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerHealth), "Hurt")]
	internal static class PanicResponsePatch
	{
		private readonly struct HurtState
		{
			internal readonly int HealthBefore;

			internal HurtState(int healthBefore)
			{
				HealthBefore = healthBefore;
			}
		}

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

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

		private static void Prefix(int ___health, out HurtState __state)
		{
			__state = new HurtState(___health);
		}

		private static void Postfix(PlayerAvatar ___playerAvatar, int ___health, HurtState __state)
		{
			if (!CanActivate(___playerAvatar, __state.HealthBefore, ___health))
			{
				return;
			}
			PanicResponseShopUpgrade panicResponse = ExtraBattleUpgradesPlugin.PanicResponse;
			if (panicResponse == null)
			{
				return;
			}
			string key = PlayerId(___playerAvatar);
			float time = Time.time;
			if (!CooldownEnds.TryGetValue(key, out var value) || !(value > time))
			{
				float num = panicResponse.DurationSeconds(___playerAvatar);
				float num2 = panicResponse.CooldownSeconds(___playerAvatar);
				float num3 = panicResponse.SpeedMultiplier(___playerAvatar);
				if (!(num <= 0f))
				{
					BuffEnds[key] = time + num;
					CooldownEnds[key] = time + num2;
					PlayerController.instance.OverrideSpeed(num3, num);
				}
			}
		}

		internal static bool IsActive(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if (BuffEnds.TryGetValue(PlayerId(player), out var value))
			{
				return value > Time.time;
			}
			return false;
		}

		private static bool CanActivate(PlayerAvatar player, int healthBefore, int healthAfter)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Invalid comparison between Unknown and I4
			if ((Object)(object)player == (Object)null || healthBefore <= 0)
			{
				return false;
			}
			if (healthAfter >= healthBefore)
			{
				return false;
			}
			if (GameManager.Multiplayer() && ((Object)(object)player.photonView == (Object)null || !player.photonView.IsMine))
			{
				return false;
			}
			if ((Object)(object)GameDirector.instance == (Object)null || (int)GameDirector.instance.currentState != 2)
			{
				return false;
			}
			PanicResponseShopUpgrade panicResponse = ExtraBattleUpgradesPlugin.PanicResponse;
			if (panicResponse != null && panicResponse.Enabled.Value && panicResponse.RegisteredUpgrade != null)
			{
				return panicResponse.GetLevel(player) > 0;
			}
			return false;
		}

		private static string PlayerId(PlayerAvatar player)
		{
			string text = SemiFunc.PlayerGetSteamID(player);
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			return ((Object)player).GetInstanceID().ToString();
		}

		internal static float RemainingCooldownSeconds(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return 0f;
			}
			string key = PlayerId(player);
			if (!CooldownEnds.TryGetValue(key, out var value))
			{
				return 0f;
			}
			return Mathf.Max(0f, value - Time.time);
		}

		internal static bool IsReady(PlayerAvatar player)
		{
			PanicResponseShopUpgrade panicResponse = ExtraBattleUpgradesPlugin.PanicResponse;
			if ((Object)(object)player != (Object)null && panicResponse != null && panicResponse.Enabled.Value && panicResponse.RegisteredUpgrade != null && panicResponse.GetLevel(player) > 0)
			{
				return RemainingCooldownSeconds(player) <= 0f;
			}
			return false;
		}

		internal static bool HasUpgrade(PlayerAvatar player)
		{
			PanicResponseShopUpgrade panicResponse = ExtraBattleUpgradesPlugin.PanicResponse;
			if ((Object)(object)player != (Object)null && panicResponse != null && panicResponse.Enabled.Value && panicResponse.RegisteredUpgrade != null)
			{
				return panicResponse.GetLevel(player) > 0;
			}
			return false;
		}

		internal static void ResetState()
		{
			BuffEnds.Clear();
			CooldownEnds.Clear();
		}
	}
	[HarmonyPatch(typeof(PlayerController), "FixedUpdate")]
	internal static class PanicResponseEnergyPatch
	{
		private static void Prefix(PlayerAvatar ___playerAvatarScript)
		{
			if (!((Object)(object)___playerAvatarScript == (Object)null) && PanicResponsePatch.IsActive(___playerAvatarScript))
			{
				PlayerController instance = PlayerController.instance;
				if (!((Object)(object)instance == (Object)null))
				{
					instance.EnergyCurrent = instance.EnergyStart;
				}
			}
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "GenerateDone")]
	internal static class RunStateResetPatch
	{
		private static void Postfix()
		{
			PanicResponsePatch.ResetState();
			SecondChancePatch.ResetState();
			ExtraBattleUpgradesPlugin.SecondChance?.ResetState();
		}
	}
	[HarmonyPatch(typeof(PlayerHealth), "Hurt")]
	internal static class SecondChancePatch
	{
		private readonly struct RescueState
		{
			internal readonly bool Activated;

			internal readonly float InvulnerabilitySeconds;

			internal RescueState(bool activated, float invulnerabilitySeconds)
			{
				Activated = activated;
				InvulnerabilitySeconds = invulnerabilitySeconds;
			}
		}

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

		private static readonly FieldRef<PlayerTumble, PhysGrabObject> TumbleBodyRef = AccessTools.FieldRefAccess<PlayerTumble, PhysGrabObject>("physGrabObject");

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

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

		private static readonly Dictionary<int, float> PitRescueTimes = new Dictionary<int, float>();

		[HarmonyPriority(0)]
		private static void Prefix(ref int damage, bool savingGrace, float ___invincibleTimer, PlayerAvatar ___playerAvatar, int ___health, out RescueState __state)
		{
			__state = new RescueState(activated: false, 0f);
			if (CanTryRescue(damage, savingGrace, ___invincibleTimer, ___playerAvatar, ___health))
			{
				SecondChanceShopUpgrade secondChance = ExtraBattleUpgradesPlugin.SecondChance;
				if (secondChance != null && secondChance.TryActivate(___playerAvatar, out var invulnerabilitySeconds))
				{
					damage = Mathf.Max(0, ___health - 1);
					__state = new RescueState(activated: true, invulnerabilitySeconds);
				}
			}
		}

		private static void Postfix(PlayerHealth __instance, PlayerAvatar ___playerAvatar, ref int ___health, RescueState __state)
		{
			if (__state.Activated && !((Object)(object)___playerAvatar == (Object)null))
			{
				if (___health <= 0)
				{
					___health = 1;
				}
				ApplyProtectionFeel(___playerAvatar, __state.InvulnerabilitySeconds, launchUp: true);
			}
		}

		private static bool CanTryRescue(int damage, bool savingGrace, float invincibleTimer, PlayerAvatar player, int health)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Invalid comparison between Unknown and I4
			if (damage <= 0 || (Object)(object)player == (Object)null || health <= 0 || invincibleTimer > 0f)
			{
				return false;
			}
			if (GameManager.Multiplayer() && ((Object)(object)player.photonView == (Object)null || !player.photonView.IsMine))
			{
				return false;
			}
			if ((Object)(object)GameDirector.instance == (Object)null || (int)GameDirector.instance.currentState != 2)
			{
				return false;
			}
			if (savingGrace && damage <= 25 && health > 5 && health <= 20)
			{
				return false;
			}
			if (health - damage > 0)
			{
				return false;
			}
			SecondChanceShopUpgrade secondChance = ExtraBattleUpgradesPlugin.SecondChance;
			if (secondChance != null && secondChance.Enabled.Value)
			{
				return secondChance.RegisteredUpgrade != null;
			}
			return false;
		}

		internal static bool TryRescueFromPit(PlayerAvatar player)
		{
			if (!CanTryPitRescue(player))
			{
				return false;
			}
			SecondChanceShopUpgrade secondChance = ExtraBattleUpgradesPlugin.SecondChance;
			if (secondChance == null || !secondChance.TryRescueFromPit(player, out var invulnerabilitySeconds, out var activatedNow))
			{
				return false;
			}
			ForceHealthToOne(player);
			ApplyProtectionFeel(player, invulnerabilitySeconds, launchUp: true);
			LaunchFromPit(player, activatedNow);
			return true;
		}

		private static bool CanTryPitRescue(PlayerAvatar player)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			if ((Object)(object)player == (Object)null || (Object)(object)player.playerHealth == (Object)null || (Object)(object)GameDirector.instance == (Object)null)
			{
				return false;
			}
			if ((int)GameDirector.instance.currentState != 2)
			{
				return false;
			}
			if (GameManager.Multiplayer() && ((Object)(object)player.photonView == (Object)null || !player.photonView.IsMine))
			{
				return false;
			}
			SecondChanceShopUpgrade secondChance = ExtraBattleUpgradesPlugin.SecondChance;
			if (secondChance != null && secondChance.Enabled.Value)
			{
				return secondChance.RegisteredUpgrade != null;
			}
			return false;
		}

		private static void ForceHealthToOne(PlayerAvatar player)
		{
			PlayerHealth playerHealth = player.playerHealth;
			if (HealthRef.Invoke(playerHealth) != 1)
			{
				HealthRef.Invoke(playerHealth) = 1;
				StatsManager instance = StatsManager.instance;
				if (instance != null)
				{
					instance.SetPlayerHealth(SemiFunc.PlayerGetSteamID(player), 1, false);
				}
			}
			if (GameManager.Multiplayer() && (Object)(object)player.photonView != (Object)null)
			{
				player.photonView.RPC("UpdateHealthRPC", (RpcTarget)1, new object[4]
				{
					1,
					MaxHealthRef.Invoke(playerHealth),
					true,
					false
				});
			}
		}

		private static void ApplyProtectionFeel(PlayerAvatar player, float invulnerabilitySeconds, bool launchUp)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			PlayerHealth playerHealth = player.playerHealth;
			playerHealth.InvincibleSet(invulnerabilitySeconds);
			playerHealth.SetMaterialSpecial(new Color(1f, 0.86f, 0.05f, 1f));
			playerHealth.EyeMaterialOverride((EyeOverrideState)4, invulnerabilitySeconds, 50);
			PlayerTumble val = PlayerTumbleRef.Invoke(player);
			if (!((Object)(object)val == (Object)null))
			{
				val.TumbleRequest(true, false);
				val.TumbleOverrideTime(Mathf.Max(0.75f, invulnerabilitySeconds * 0.35f));
				if (launchUp)
				{
					val.TumbleForce(Vector3.up * 8f);
				}
			}
		}

		private static void LaunchFromPit(PlayerAvatar player, bool activatedNow)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)player).GetInstanceID();
			float time = Time.time;
			if (PitRescueTimes.TryGetValue(instanceID, out var value) && value > time)
			{
				return;
			}
			PitRescueTimes[instanceID] = time + 0.25f;
			PlayerTumble val = PlayerTumbleRef.Invoke(player);
			PhysGrabObject val2 = (((Object)(object)val != (Object)null) ? TumbleBodyRef.Invoke(val) : null);
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.rb == (Object)null))
			{
				val2.DeathPitEffectCreate();
				Vector3 velocity = val2.rb.velocity;
				if (velocity.y < 0f)
				{
					velocity.y = 0f;
					val2.rb.velocity = velocity;
				}
				float num = (activatedNow ? 18f : 14f);
				Vector3 val3 = default(Vector3);
				((Vector3)(ref val3))..ctor(Random.Range(-2f, 2f), 0f, Random.Range(-2f, 2f));
				val2.rb.AddForce((Vector3.up * num + val3) * val2.rb.mass, (ForceMode)1);
				val2.rb.AddTorque(Random.insideUnitSphere * val2.rb.mass, (ForceMode)1);
			}
		}

		internal static void ResetState()
		{
			PitRescueTimes.Clear();
		}
	}
	[HarmonyPatch(typeof(HurtCollider), "PlayerHurt")]
	internal static class SecondChanceDeathPitPatch
	{
		private static bool Prefix(HurtCollider __instance, PlayerAvatar _player)
		{
			if (__instance.deathPit)
			{
				return !SecondChancePatch.TryRescueFromPit(_player);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerHealth), "Update")]
	internal static class SecondChanceHealthColorPatch
	{
		private static readonly int AlbedoColor = Shader.PropertyToID("_AlbedoColor");

		private static readonly int EmissionColor = Shader.PropertyToID("_EmissionColor");

		private static readonly Color ProtectedHealthColor = new Color(1f, 0.86f, 0.05f, 1f);

		private static void Postfix(PlayerAvatar ___playerAvatar, Material ___healthMaterial)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			SecondChanceShopUpgrade secondChance = ExtraBattleUpgradesPlugin.SecondChance;
			if (secondChance != null && !((Object)(object)___playerAvatar == (Object)null) && !((Object)(object)___healthMaterial == (Object)null) && !(secondChance.RemainingProtectionSeconds(___playerAvatar) <= 0f))
			{
				___healthMaterial.SetColor(AlbedoColor, ProtectedHealthColor);
				Color protectedHealthColor = ProtectedHealthColor;
				if (___healthMaterial.HasProperty(EmissionColor))
				{
					protectedHealthColor.a = ___healthMaterial.GetColor(EmissionColor).a;
				}
				___healthMaterial.SetColor(EmissionColor, protectedHealthColor);
			}
		}
	}
	[HarmonyPatch(typeof(EnemyRigidbody), "FixedUpdate")]
	internal static class ShockGripPatch
	{
		private readonly struct ShockTarget
		{
			internal readonly int EnemyId;

			private readonly int _playerId;

			internal ShockTarget(int enemyId, int playerId)
			{
				EnemyId = enemyId;
				_playerId = playerId;
			}
		}

		private const float DamageTickSeconds = 0.5f;

		private static readonly Dictionary<ShockTarget, float> DamageTimers = new Dictionary<ShockTarget, float>();

		private static readonly FieldRef<EnemyRigidbody, PhysGrabObject> EnemyGrabObjectRef = AccessTools.FieldRefAccess<EnemyRigidbody, PhysGrabObject>("physGrabObject");

		private static readonly FieldRef<EnemyRigidbody, bool> EnemyGrabbedRef = AccessTools.FieldRefAccess<EnemyRigidbody, bool>("grabbed");

		private static readonly FieldRef<EnemyRigidbody, float> GrabStrengthTimerRef = AccessTools.FieldRefAccess<EnemyRigidbody, float>("grabStrengthTimer");

		private static readonly FieldRef<PhysGrabObject, PlayerAvatar> LastPlayerGrabbingRef = AccessTools.FieldRefAccess<PhysGrabObject, PlayerAvatar>("lastPlayerGrabbing");

		private static readonly FieldRef<PhysGrabObject, float> GrabbedTimerRef = AccessTools.FieldRefAccess<PhysGrabObject, float>("grabbedTimer");

		private static readonly FieldRef<EnemyGrounded, bool> GroundedRef = AccessTools.FieldRefAccess<EnemyGrounded, bool>("grounded");

		private static void Postfix(EnemyRigidbody __instance)
		{
			if (!CanRunShockGrip())
			{
				return;
			}
			Enemy enemy = __instance.enemy;
			PhysGrabObject grabObject = EnemyGrabObjectRef.Invoke(__instance);
			EnemyHealth health = (((Object)(object)enemy != (Object)null) ? ((Component)enemy).GetComponent<EnemyHealth>() : null);
			List<PlayerAvatar> holders = GetHolders(grabObject);
			if (!CanDamageEnemy(__instance, enemy, grabObject, health, holders))
			{
				ClearEnemyTimers(((Object)__instance).GetInstanceID());
				return;
			}
			foreach (PlayerAvatar item in holders)
			{
				int num = ExtraBattleUpgradesPlugin.ShockGrip.DamagePerSecond(item);
				if (num > 0)
				{
					TickDamage(((Object)__instance).GetInstanceID(), item, health, num);
				}
			}
		}

		private static List<PlayerAvatar> GetHolders(PhysGrabObject grabObject)
		{
			List<PlayerAvatar> list = new List<PlayerAvatar>();
			if ((Object)(object)grabObject == (Object)null)
			{
				return list;
			}
			if (grabObject.playerGrabbing != null)
			{
				foreach (PhysGrabber item in grabObject.playerGrabbing)
				{
					AddHolder(list, item?.playerAvatar);
				}
			}
			if (list.Count == 0 && GrabbedTimerRef.Invoke(grabObject) > 0f)
			{
				AddHolder(list, LastPlayerGrabbingRef.Invoke(grabObject));
			}
			return list;
		}

		private static void TickDamage(int enemyId, PlayerAvatar holder, EnemyHealth health, int damagePerSecond)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			ShockTarget key = new ShockTarget(enemyId, ((Object)holder).GetInstanceID());
			DamageTimers.TryGetValue(key, out var value);
			value += Time.fixedDeltaTime;
			if (value < 0.5f)
			{
				DamageTimers[key] = value;
				return;
			}
			DamageTimers[key] = value - 0.5f;
			int num = Mathf.CeilToInt((float)damagePerSecond * 0.5f);
			CombatDamageTracker.Push(holder);
			try
			{
				health.Hurt(num, Vector3.up);
				ShockGripVisuals.PlayLocal(holder);
				if (GameManager.Multiplayer())
				{
					ShockGripVisualRelay.Broadcast(holder);
				}
			}
			finally
			{
				CombatDamageTracker.Pop();
			}
		}

		private static bool CanRunShockGrip()
		{
			if (SemiFunc.IsMasterClientOrSingleplayer() && ExtraBattleUpgradesPlugin.ShockGrip != null && ExtraBattleUpgradesPlugin.ShockGrip.Enabled.Value)
			{
				return ExtraBattleUpgradesPlugin.ShockGrip.RegisteredUpgrade != null;
			}
			return false;
		}

		private static bool CanDamageEnemy(EnemyRigidbody enemyBody, Enemy enemy, PhysGrabObject grabObject, EnemyHealth health, List<PlayerAvatar> holders)
		{
			if ((Object)(object)enemyBody == (Object)null || (Object)(object)enemy == (Object)null || (Object)(object)grabObject == (Object)null || (Object)(object)health == (Object)null || holders.Count == 0)
			{
				return false;
			}
			if (!enemy.IsStunned() && !EnemyGrabbedRef.Invoke(enemyBody) && GrabStrengthTimerRef.Invoke(enemyBody) <= 0f)
			{
				return false;
			}
			return IsAirborne(enemyBody, enemy, grabObject);
		}

		private static bool IsAirborne(EnemyRigidbody enemyBody, Enemy enemy, PhysGrabObject grabObject)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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)
			EnemyGrounded componentInChildren = ((Component)enemy).GetComponentInChildren<EnemyGrounded>();
			if ((Object)(object)componentInChildren != (Object)null && !GroundedRef.Invoke(componentInChildren))
			{
				return true;
			}
			return !SemiFunc.OnGroundCheck((grabObject.centerPoint != Vector3.zero) ? grabObject.centerPoint : ((Component)enemyBody).transform.position, 0.75f, grabObject);
		}

		private static void AddHolder(List<PlayerAvatar> holders, PlayerAvatar holder)
		{
			if ((Object)(object)holder != (Object)null && !holders.Contains(holder))
			{
				holders.Add(holder);
			}
		}

		private static void ClearEnemyTimers(int enemyId)
		{
			foreach (ShockTarget item in new List<ShockTarget>(DamageTimers.Keys))
			{
				if (item.EnemyId == enemyId)
				{
					DamageTimers.Remove(item);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "Start")]
	internal static class ShockGripVisualRelayPatch
	{
		private static void Postfix(PlayerAvatar __instance)
		{
			ShockGripVisualRelay.Ensure(__instance);
		}
	}
	[HarmonyPatch(typeof(StatsManager), "Start")]
	internal static class StatsLabelPatch
	{
		private static void Postfix(StatsManager __instance)
		{
			ExtraBattleUpgradesPlugin.RefreshStatsLabels(__instance);
		}
	}
}
namespace ExtraBattleUpgrades.Hud
{
	internal sealed class BattleUpgradeHudConfig
	{
		internal ConfigEntry<bool> PanicIconEnabled { get; }

		internal ConfigEntry<float> PanicIconX { get; }

		internal ConfigEntry<float> PanicIconY { get; }

		internal ConfigEntry<float> PanicIconSize { get; }

		internal ConfigEntry<bool> SecondChanceIconEnabled { get; }

		internal ConfigEntry<float> SecondChanceIconX { get; }

		internal ConfigEntry<float> SecondChanceIconY { get; }

		internal ConfigEntry<float> SecondChanceIconSize { get; }

		internal BattleUpgradeHudConfig(ConfigFile config)
		{
			PanicIconEnabled = config.Bind<bool>("HUD - Panic Response", "Icon Enabled", true, "Show Panic Response HUD icon.");
			PanicIconX = config.Bind<float>("HUD - Panic Response", "Icon X", 68f, "Panic Response icon local X position.");
			PanicIconY = config.Bind<float>("HUD - Panic Response", "Icon Y", -23f, "Panic Response icon local Y position.");
			PanicIconSize = config.Bind<float>("HUD - Panic Response", "Icon Size", 11f, "Panic Response icon size.");
			SecondChanceIconEnabled = config.Bind<bool>("HUD - Second Chance", "Icon Enabled", true, "Show Second Chance HUD icon.");
			SecondChanceIconX = config.Bind<float>("HUD - Second Chance", "Icon X", 68f, "Second Chance icon local X position.");
			SecondChanceIconY = config.Bind<float>("HUD - Second Chance", "Icon Y", -23f, "Second Chance icon local Y position.");
			SecondChanceIconSize = config.Bind<float>("HUD - Second Chance", "Icon Size", 15f, "Second Chance icon size.");
		}
	}
	internal static class BattleUpgradeIconPainter
	{
		private const int TextureSize = 64;

		private static Sprite _lightningSprite;

		private static Sprite _heartSprite;

		internal static Sprite LightningSprite()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_lightningSprite != (Object)null)
			{
				return _lightningSprite;
			}
			Texture2D obj = DrawLightning();
			((Object)obj).name = "ExtraBattleUpgrades_PanicResponse_Lightning";
			((Texture)obj).wrapMode = (TextureWrapMode)1;
			((Texture)obj).filterMode = (FilterMode)1;
			_lightningSprite = Sprite.Create(obj, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f);
			return _lightningSprite;
		}

		internal static Sprite HeartSprite()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_heartSprite != (Object)null)
			{
				return _heartSprite;
			}
			Texture2D obj = DrawHeart();
			((Object)obj).name = "ExtraBattleUpgrades_SecondChance_Heart";
			((Texture)obj).wrapMode = (TextureWrapMode)1;
			((Texture)obj).filterMode = (FilterMode)1;
			_heartSprite = Sprite.Create(obj, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f);
			return _heartSprite;
		}

		private static Texture2D DrawLightning()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = NewTransparentTexture();
			Vector2[] polygon = (Vector2[])(object)new Vector2[6]
			{
				new Vector2(37f, 4f),
				new Vector2(16f, 34f),
				new Vector2(30f, 34f),
				new Vector2(23f, 60f),
				new Vector2(48f, 25f),
				new Vector2(34f, 25f)
			};
			DrawGlowPolygon(val, polygon, Color.white, 7f, 0.28f);
			FillPolygon(val, polygon, Color.white);
			val.Apply(false, true);
			return val;
		}

		private static Texture2D DrawHeart()
		{
			//IL_0067: 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)
			Texture2D val = NewTransparentTexture();
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num = ((float)j - 32f) / 24f;
					float num2 = ((float)i - 28f) / 24f;
					float num3 = Mathf.Pow(num * num + num2 * num2 - 0.32f, 3f) - num * num * num2 * num2 * num2;
					if (num3 <= 0f)
					{
						val.SetPixel(j, i, Color.white);
					}
					else if (num3 <= 0.08f)
					{
						float num4 = Mathf.Clamp01(1f - num3 / 0.08f) * 0.28f;
						val.SetPixel(j, i, new Color(1f, 1f, 1f, num4));
					}
				}
			}
			val.Apply(false, true);
			return val;
		}

		private static Texture2D NewTransparentTexture()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			Color[] array = (Color[])(object)new Color[4096];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = Color.clear;
			}
			val.SetPixels(array);
			return val;
		}

		private static void FillPolygon(Texture2D texture, Vector2[] polygon, Color color)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					if (PointInPolygon(new Vector2((float)j + 0.5f, (float)i + 0.5f), polygon))
					{
						texture.SetPixel(j, i, color);
					}
				}
			}
		}

		private static void DrawGlowPolygon(Texture2D texture, Vector2[] polygon, Color color, float radius, float strength)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num = DistanceToPolygon(new Vector2((float)j + 0.5f, (float)i + 0.5f), polygon);
					if (num <= radius)
					{
						float alpha = Mathf.Pow(1f - num / radius, 2f) * strength;
						Color pixel = texture.GetPixel(j, i);
						texture.SetPixel(j, i, Blend(pixel, color, alpha));
					}
				}
			}
		}

		private static float DistanceToPolygon(Vector2 point, Vector2[] polygon)
		{
			//IL_000c: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			float num = float.MaxValue;
			for (int i = 0; i < polygon.Length; i++)
			{
				Vector2 a = polygon[i];
				Vector2 b = polygon[(i + 1) % polygon.Length];
				num = Mathf.Min(num, DistanceToSegment(point, a, b));
			}
			if (PointInPolygon(point, polygon))
			{
				return 0f;
			}
			return num;
		}

		private static float DistanceToSegment(Vector2 point, Vector2 a, Vector2 b)
		{
			//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_0007: 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_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = b - a;
			float num = Vector2.Dot(point - a, val) / ((Vector2)(ref val)).sqrMagnitude;
			num = Mathf.Clamp01(num);
			return Vector2.Distance(point, a + val * num);
		}

		private static bool PointInPolygon(Vector2 point, Vector2[] polygon)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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)
			bool flag = false;
			int num = 0;
			int num2 = polygon.Length - 1;
			while (num < polygon.Length)
			{
				if (polygon[num].y > point.y != polygon[num2].y > point.y && point.x < (polygon[num2].x - polygon[num].x) * (point.y - polygon[num].y) / (polygon[num2].y - polygon[num].y) + polygon[num].x)
				{
					flag = !flag;
				}
				num2 = num++;
			}
			return flag;
		}

		private static Color Blend(Color under, Color over, float alpha)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			alpha = Mathf.Clamp01(alpha);
			float num = alpha + under.a * (1f - alpha);
			if (num <= 0f)
			{
				return Color.clear;
			}
			return new Color((over.r * alpha + under.r * under.a * (1f - alpha)) / num, (over.g * alpha + under.g * under.a * (1f - alpha)) / num, (over.b * alpha + under.b * under.a * (1f - alpha)) / num, num);
		}
	}
}
namespace ExtraBattleUpgrades.Combat
{
	internal static class CombatDamageTracker
	{
		private static readonly Stack<PlayerAvatar[]> OwnerStack = new Stack<PlayerAvatar[]>();

		private static readonly FieldRef<PhysGrabObject, PlayerAvatar> LastPlayerGrabbing = AccessTools.FieldRefAccess<PhysGrabObject, PlayerAvatar>("lastPlayerGrabbing");

		private static readonly FieldRef<PhysGrabObject, float> GrabbedTimer = AccessTools.FieldRefAccess<PhysGrabObject, float>("grabbedTimer");

		internal static PlayerAvatar[] CurrentOwners
		{
			get
			{
				if (OwnerStack.Count != 0)
				{
					return OwnerStack.Peek();
				}
				return Array.Empty<PlayerAvatar>();
			}
		}

		internal static void Push(PlayerAvatar owner)
		{
			if ((Object)(object)owner == (Object)null)
			{
				OwnerStack.Push(Array.Empty<PlayerAvatar>());
				return;
			}
			OwnerStack.Push((PlayerAvatar[])(object)new PlayerAvatar[1] { owner });
		}

		internal static void PushFromPhysGrabObject(PhysGrabObject physGrabObject)
		{
			if ((Object)(object)physGrabObject == (Object)null)
			{
				OwnerStack.Push(Array.Empty<PlayerAvatar>());
				return;
			}
			List<PlayerAvatar> list = new List<PlayerAvatar>();
			if (physGrabObject.playerGrabbing != null)
			{
				foreach (PhysGrabber item in physGrabObject.playerGrabbing)
				{
					AddOwner(list, item?.playerAvatar);
				}
			}
			if (list.Count == 0 && GrabbedTimer.Invoke(physGrabObject) > 0f)
			{
				AddOwner(list, LastPlayerGrabbing.Invoke(physGrabObject));
			}
			OwnerStack.Push(list.ToArray());
		}

		internal static void Pop()
		{
			if (OwnerStack.Count > 0)
			{
				OwnerStack.Pop();
			}
		}

		internal static void ApplyEnergyLeech(int actualDamage, PlayerAvatar[] owners)
		{
			if (actualDamage <= 0 || owners == null || owners.Length == 0)
			{
				return;
			}
			EnergyLeechShopUpgrade energyLeech = ExtraBattleUpgradesPlugin.EnergyLeech;
			if (energyLeech == null || !energyLeech.Enabled.Value || energyLeech.RegisteredUpgrade == null)
			{
				return;
			}
			List<PlayerAvatar> list = new List<PlayerAvatar>();
			foreach (PlayerAvatar val in owners)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.playerHealth == (Object)null) && !list.Contains(val))
				{
					int num = energyLeech.HealingFromDamage(actualDamage, val);
					if (num > 0)
					{
						val.playerHealth.HealOther(num, true);
						list.Add(val);
					}
				}
			}
		}

		private static void AddOwner(List<PlayerAvatar> owners, PlayerAvatar owner)
		{
			if ((Object)(object)owner != (Object)null && !owners.Contains(owner))
			{
				owners.Add(owner);
			}
		}
	}
}