Decompiled source of DeathHeadHopper v2.1.5

DeathHeadHopper.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DeathHeadHopper.Abilities;
using DeathHeadHopper.Abilities.Charge;
using DeathHeadHopper.DeathHead;
using DeathHeadHopper.DeathHead.Handlers;
using DeathHeadHopper.Helpers;
using DeathHeadHopper.Items;
using DeathHeadHopper.Managers;
using DeathHeadHopper.Models;
using DeathHeadHopper.UI;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using REPOLib.Modules;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
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: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("Autodesk.Fbx")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("FbxBuildTestAssets")]
[assembly: IgnoresAccessChecksTo("Klattersynth")]
[assembly: IgnoresAccessChecksTo("Photon3Unity3D")]
[assembly: IgnoresAccessChecksTo("PhotonChat")]
[assembly: IgnoresAccessChecksTo("PhotonRealtime")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Utilities")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.API")]
[assembly: IgnoresAccessChecksTo("PhotonVoice")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.PUN")]
[assembly: IgnoresAccessChecksTo("SingularityGroup.HotReload.Runtime")]
[assembly: IgnoresAccessChecksTo("SingularityGroup.HotReload.Runtime.Public")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Attributes")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization.Config")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Utilities")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Formats.Fbx.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Postprocessing.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Antlr3.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Core")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Flow")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.State")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("websocket-sharp")]
[assembly: AssemblyCompany("Cronchy")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.1.5.0")]
[assembly: AssemblyInformationalVersion("2.1.5+c0f92c92ffee3a3a30cc0cc60f1954250aaef606")]
[assembly: AssemblyProduct("DeathHeadHopper")]
[assembly: AssemblyTitle("DeathHeadHopper")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.1.5.0")]
[module: UnverifiableCode]
[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.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]
	[Microsoft.CodeAnalysis.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]
	[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 DeathHeadHopper
{
	[BepInPlugin("Cronchy.DeathHeadHopper", "DeathHeadHopper", "2.1.5")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class DeathHeadHopper : BaseUnityPlugin
	{
		internal static DeathHeadHopper Instance { get; private set; }

		internal static Version Version { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

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

		internal Harmony? Harmony { get; set; }

		internal void Awake()
		{
			Instance = this;
			Version = ((BaseUnityPlugin)this).Info.Metadata.Version;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			DHHConfigManager.BindConfig(((BaseUnityPlugin)this).Config);
			Patch();
			DHHAssetManager.LoadAssets();
			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();
			}
		}
	}
}
namespace DeathHeadHopper.UI
{
	public class AbilityCooldown : MonoBehaviour
	{
		private float startCooldown;

		private float cooldownTimer;

		private Image cooldownIcon;

		protected void Awake()
		{
			cooldownIcon = ((Component)this).GetComponent<Image>();
		}

		protected void Update()
		{
			if (cooldownTimer > 0f)
			{
				cooldownTimer = Mathf.Max(cooldownTimer - Time.deltaTime, 0f);
				UpdateCooldownCircle();
			}
		}

		public void SetCooldown(float cooldown)
		{
			startCooldown = (cooldownTimer = cooldown);
		}

		private void UpdateCooldownCircle()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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)
			cooldownIcon.fillAmount = -1f / startCooldown * cooldownTimer + 1f;
			if (cooldownIcon.fillAmount < 1f)
			{
				Color color = ((Graphic)cooldownIcon).color;
				color.a = 0.3f;
				((Graphic)cooldownIcon).color = color;
			}
			else
			{
				Color color2 = ((Graphic)cooldownIcon).color;
				color2.a = 1f;
				((Graphic)cooldownIcon).color = color2;
			}
		}
	}
	public class AbilityEnergyUI : SemiUI
	{
		public static AbilityEnergyUI instance;

		public TextMeshProUGUI textCurrent;

		public TextMeshProUGUI textMax;

		public float energyLerpSpeed = 5f;

		private float energyLerp;

		private float actualEnergy;

		private float maxEnergy;

		private Transform? scanlines;

		protected void Awake()
		{
			instance = this;
		}

		public override void Start()
		{
			((SemiUI)this).Start();
			base.uiText = null;
			Transform obj = DHHUIManager.instance.gameHUD.transform.Find("Energy");
			scanlines = ((obj != null) ? obj.Find("Scanlines") : null);
			if (scanlines != null)
			{
				Object.Instantiate<Transform>(scanlines, ((Component)this).transform);
			}
		}

		public override void Update()
		{
			if (LevelGenerator.Instance.Generated)
			{
				((SemiUI)this).Update();
				((SemiUI)this).Hide();
			}
			if ((Object)(object)SpectateCamera.instance == (Object)null || (Object)(object)SpectateCamera.instance.player == (Object)null || (Object)(object)SpectateCamera.instance.player.playerDeathHead == (Object)null || !SpectateCamera.instance.CheckState((State)1))
			{
				return;
			}
			DeathHeadController component = ((Component)SpectateCamera.instance.player.playerDeathHead).GetComponent<DeathHeadController>();
			if ((Object)(object)component != (Object)null && component.deathHead.triggered)
			{
				actualEnergy = component.abilityEnergyHandler.Energy;
				maxEnergy = component.abilityEnergyHandler.EnergyMax;
			}
			if (actualEnergy != energyLerp)
			{
				energyLerp = Mathf.Lerp(energyLerp, actualEnergy, Time.deltaTime * energyLerpSpeed);
				if (Mathf.Abs(actualEnergy - energyLerp) < 0.3f)
				{
					energyLerp = actualEnergy;
				}
			}
			((TMP_Text)textCurrent).text = Mathf.Floor(energyLerp).ToString();
			((TMP_Text)textMax).text = "<b><color=orange>/</color></b>" + Mathf.Floor(maxEnergy);
		}
	}
	public class AbilitySpot : SemiUI
	{
		public int abilitySpotIndex;

		public TextMeshProUGUI noAbility;

		public TextMeshProUGUI energyCost;

		public TextMeshProUGUI level;

		public Image backgroundIcon;

		private AbilityCooldown cooldownUI;

		private Image cooldownIcon;

		internal float lastUseTime;

		private AbilityBase? _currentAbility;

		public AbilityBase? CurrentAbility
		{
			get
			{
				return _currentAbility;
			}
			private set
			{
				_currentAbility = value;
			}
		}

		protected void Awake()
		{
			cooldownUI = ((Component)this).GetComponentInChildren<AbilityCooldown>();
			cooldownIcon = ((Component)cooldownUI).GetComponent<Image>();
		}

		public override void Start()
		{
			UpdateUI();
			((SemiUI)this).Start();
			base.uiText = null;
			SetIcon(null);
			if (SemiFunc.RunIsLevel() || SemiFunc.RunIsShop())
			{
				DHHAbilityManager.instance.SetAbilitySpotAtIndex(this, abilitySpotIndex);
			}
		}

		public void SetIcon(Sprite? sprite)
		{
			if (!Object.op_Implicit((Object)(object)sprite))
			{
				((Behaviour)backgroundIcon).enabled = false;
				((Behaviour)cooldownIcon).enabled = false;
				((Behaviour)noAbility).enabled = true;
			}
			else
			{
				((Behaviour)backgroundIcon).enabled = true;
				backgroundIcon.sprite = sprite;
				((Behaviour)cooldownIcon).enabled = true;
				cooldownIcon.sprite = sprite;
				((Behaviour)noAbility).enabled = false;
			}
		}

		public void UpdateUI()
		{
			if (CurrentAbility != null)
			{
				((SemiUI)this).SemiUISpringScale(0.5f, 2f, 0.2f);
				SetIcon(CurrentAbility.icon);
				((Behaviour)level).enabled = true;
			}
			else
			{
				SetIcon(null);
				((SemiUI)this).SemiUISpringScale(0.5f, 2f, 0.2f);
				((Behaviour)level).enabled = false;
			}
		}

		public void EquipAbility(AbilityBase ability)
		{
			CurrentAbility = ability;
			((TMP_Text)energyCost).text = CurrentAbility.EnergyCost.ToString();
			UpdateUI();
		}

		public void RemoveAbility()
		{
			CurrentAbility = null;
			((TMP_Text)energyCost).text = "0";
			UpdateUI();
		}

		public override void Update()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (CurrentAbility == null)
			{
				((SemiUI)this).SemiUIScoot(new Vector2(0f, -20f));
			}
			else
			{
				((TMP_Text)level).text = $"LV. {CurrentAbility.AbilityLevel}";
			}
			((SemiUI)this).Update();
		}

		public void SetCooldown(float cooldown)
		{
			cooldownUI.SetCooldown(cooldown);
		}
	}
	public class AbilityUI : SemiUI
	{
		public static AbilityUI instance;

		protected void Awake()
		{
			instance = this;
		}

		public override void Start()
		{
			((SemiUI)this).Start();
			base.uiText = null;
		}

		public override void Update()
		{
			if (LevelGenerator.Instance.Generated)
			{
				((SemiUI)this).Update();
				((SemiUI)this).Hide();
			}
		}
	}
}
namespace DeathHeadHopper.Patches
{
	[HarmonyPatch(typeof(GameDirector))]
	public static class GameDirectorPatch
	{
		[HarmonyPatch("gameStateLoad")]
		[HarmonyPrefix]
		public static void GameStateLoad_Prefix()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)DHHStatsManager.instance == (Object)null)
			{
				new GameObject("DHHStatsManager").AddComponent<DHHStatsManager>();
			}
			if (SemiFunc.RunIsLevel() || SemiFunc.RunIsShop() || SemiFunc.RunIsLobby())
			{
				if ((Object)(object)DHHPunManager.instance == (Object)null || (Object)(object)((Component)DHHPunManager.instance).gameObject == (Object)null)
				{
					DHHPunManager dHHPunManager = new GameObject("DHHPunManager").AddComponent<DHHPunManager>();
					dHHPunManager.VersionCheck();
				}
				else if ((Object)(object)((Component)DHHPunManager.instance).GetComponent<PhotonView>() == (Object)null)
				{
					DHHPunManager.instance.EnsurePhotonView();
				}
			}
		}

		[HarmonyPatch("gameStateStart")]
		[HarmonyPostfix]
		public static void GameStateStart_Postfix()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			if ((int)GameDirector.instance.currentState != 2 || (!SemiFunc.RunIsLevel() && !SemiFunc.RunIsShop()))
			{
				return;
			}
			string text = "DHHInputManager";
			if (((Object)((Component)PlayerAvatar.instance.spectatePoint).gameObject).name == text)
			{
				DeathHeadHopper.Logger.LogDebug((object)"Player already has DeathHeadHopper enabled");
				return;
			}
			new GameObject("DHHAbilityManager").AddComponent<DHHAbilityManager>();
			new GameObject("DHHUIManager").AddComponent<DHHUIManager>();
			DeathHeadHopper.Logger.LogDebug((object)"DeathHeadHopper object instance created!");
			foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
			{
				ComponentHolderProtocol.AddComponent<DeathHeadController>((Object)(object)player.playerDeathHead);
			}
			DeathHeadHopper.Logger.LogDebug((object)"Added DeathHeadController to player heads!");
			DeathHeadHopper.Logger.LogDebug((object)"Creating DeathHeadHopper object instance...");
			DHHFunc.DeathHeadHopperObj = new GameObject(text);
			DHHFunc.DeathHeadHopperObj.AddComponent<DHHInputManager>();
			DHHFunc.DeathHeadHopperObj.SetActive(false);
			DHHFunc.DeathHeadHopperObj.transform.SetParent(((Component)PlayerAvatar.instance).transform.parent, false);
		}

		[HarmonyPatch("Revive")]
		[HarmonyPrefix]
		private static void Revive_Prefix()
		{
			if (!((Object)(object)DHHFunc.DeathHeadHopperObj == (Object)null) && DHHFunc.DeathHeadHopperObj.activeSelf)
			{
				DeathHeadHopper.Logger.LogInfo((object)"You are revived! Disabling DeathHeadHopper");
				DHHFunc.DeathHeadHopperObj.SetActive(false);
			}
		}
	}
	[HarmonyPatch(typeof(ItemBattery))]
	public class ItemBatteryPatch
	{
		private static readonly FieldInfo f_batteryActive = AccessTools.Field(typeof(ItemBattery), "batteryActive");

		private static readonly FieldInfo f_batteryLifeInt = AccessTools.Field(typeof(ItemBattery), "batteryLifeInt");

		private static readonly FieldInfo f_batteryVisualLogic = AccessTools.Field(typeof(ItemBattery), "batteryVisualLogic");

		[HarmonyPatch("BatteryLookAt")]
		[HarmonyPrefix]
		public static bool BatteryLookAt_Prefix(ItemBattery __instance)
		{
			return (Object)(object)((Component)__instance).GetComponent<DHHItemHeadCharger>() == (Object)null;
		}

		[HarmonyPatch("Update")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Update_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Expected O, but got Unknown
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Expected O, but got Unknown
			if (f_batteryVisualLogic == null)
			{
				DeathHeadHopper.Logger.LogDebug((object)"Could not find batteryVisualLogic field in ItemBattery, this is REPO v0.1.2 or below. Skipping transpiler");
				return instructions;
			}
			List<CodeInstruction> list = instructions.ToList();
			int num = list.FindIndex((CodeInstruction ci) => CodeInstructionExtensions.LoadsField(ci, f_batteryActive, false));
			if (num <= 0)
			{
				return instructions;
			}
			DeathHeadHopper.Logger.LogDebug((object)string.Format("{0}_{1} batteryActiveIndex: {2}", "ItemBatteryPatch", "Update_Transpiler", num));
			int num2 = list.FindIndex(num, (CodeInstruction ci) => CodeInstructionExtensions.LoadsField(ci, f_batteryLifeInt, false));
			if (num2 <= 0 || !(list[num2 + 2].operand is Label label))
			{
				DeathHeadHopper.Logger.LogError((object)"Could not find itemBattery.batteryLifeInt check in Update");
				return instructions;
			}
			DeathHeadHopper.Logger.LogDebug((object)string.Format("{0}_{1} index: {2}", "ItemBatteryPatch", "Update_Transpiler", num2));
			DeathHeadHopper.Logger.LogDebug((object)"Found itemBattery.batteryLifeInt check in Update, replacing code instructions");
			list.InsertRange(num2, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[3]
			{
				CodeInstruction.Call(typeof(DHHFunc), "IsHeadChargerBattery", new Type[1] { typeof(ItemBattery) }, (Type[])null),
				new CodeInstruction(OpCodes.Brtrue, (object)label),
				new CodeInstruction(OpCodes.Ldarg_0, (object)null)
			});
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(LevelGenerator))]
	public class LevelGeneratorPatch
	{
		[HarmonyPatch("ItemSetup")]
		[HarmonyPrefix]
		public static void ItemSetup_Prefix()
		{
			if (SemiFunc.IsMultiplayer())
			{
				foreach (KeyValuePair<string, Item> shopItem in DHHAssetManager.shopItems)
				{
					if (!StatsManager.instance.itemDictionary.ContainsKey(shopItem.Key))
					{
						StatsManager.instance.itemDictionary.Add(shopItem.Key, shopItem.Value);
					}
				}
				return;
			}
			foreach (string key in DHHAssetManager.shopItems.Keys)
			{
				if (StatsManager.instance.itemDictionary.ContainsKey(key))
				{
					StatsManager.instance.itemDictionary.Remove(key);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PunManager))]
	public class PunManagerPatch
	{
		[HarmonyPatch("ShopPopulateItemVolumes")]
		[HarmonyPrefix]
		public static void ShopPopulateItemVolumes_Prefix(PunManager __instance)
		{
			DHHShopManager.ShopPopulateItemVolumes(__instance);
		}
	}
	[HarmonyPatch(typeof(SemiIconMaker))]
	public class SemiIconMakerPatch
	{
		[HarmonyPatch("CreateIconFromRenderTexture")]
		[HarmonyPrefix]
		public static void CreateIconFromRenderTexture_Prefix(SemiIconMaker __instance)
		{
			if ((Object)(object)__instance.iconCamera.targetTexture == (Object)null)
			{
				__instance.iconCamera.targetTexture = __instance.renderTexture;
			}
		}
	}
	[HarmonyPatch(typeof(ShopManager))]
	public static class ShopManagerPatch
	{
		[HarmonyPatch("GetAllItemVolumesInScene")]
		[HarmonyPostfix]
		public static void GetAllItemVolumesInScene_Postfix()
		{
			DHHPunManager.instance.LoadShopAtticShelves();
		}

		[HarmonyPatch("GetAllItemsFromStatsManager")]
		[HarmonyPostfix]
		public static void GetAllItemsFromStatsManager_Postfix()
		{
			DHHShopManager.LoadItems();
		}
	}
	[HarmonyPatch(typeof(SpectateCamera))]
	internal static class SpectateCameraPatch
	{
		private static readonly FieldInfo f_isDisabled = AccessTools.Field(typeof(PlayerAvatar), "isDisabled");

		private static readonly MethodInfo m_inputDown = AccessTools.Method(typeof(SemiFunc), "InputDown", (Type[])null, (Type[])null);

		private static readonly MethodInfo m_playerSwitch = AccessTools.Method(typeof(SpectateCamera), "PlayerSwitch", (Type[])null, (Type[])null);

		private static readonly MethodInfo m_componentTransform = AccessTools.Method(typeof(Component), "get_transform", (Type[])null, (Type[])null);

		private static readonly MethodInfo m_transformPosition = AccessTools.Method(typeof(Transform), "get_position", (Type[])null, (Type[])null);

		private static readonly FieldInfo f_vector3Y = AccessTools.Field(typeof(Vector3), "y");

		[HarmonyPatch("LateUpdate")]
		[HarmonyPostfix]
		private static void LateUpdate_Postfix()
		{
			DeathHeadController deathHeadController = default(DeathHeadController);
			if ((SemiFunc.RunIsLevel() || SemiFunc.RunIsShop()) && MenuManager.instance.currentMenuState == 1 && (Object)(object)PlayerAvatar.instance.playerDeathHead != (Object)null && ((Component)PlayerAvatar.instance.playerDeathHead).TryGetComponent<DeathHeadController>(ref deathHeadController) && deathHeadController.spectated && DHHAbilityManager.instance.HasEquippedAbility())
			{
				((SemiUI)AbilityUI.instance).Show();
				((SemiUI)AbilityEnergyUI.instance).Show();
			}
		}

		[HarmonyPatch("StateNormal")]
		[HarmonyPrefix]
		private static void StateNormal_Prefix()
		{
			if ((SemiFunc.RunIsLevel() || SemiFunc.RunIsShop()) && Object.op_Implicit((Object)(object)DHHFunc.DeathHeadHopperObj) && !((Object)(object)DHHFunc.DeathHeadHopperObj == (Object)null) && !DHHFunc.DeathHeadHopperObj.activeSelf)
			{
				DeathHeadHopper.Logger.LogInfo((object)"You died! Enabling DeathHeadHopper");
				DHHFunc.DeathHeadHopperObj.SetActive(true);
			}
		}

		[HarmonyPatch("PlayerSwitch")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> PlayerSwitch_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Expected O, but got Unknown
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			int num = list.FindIndex((CodeInstruction ci) => CodeInstructionExtensions.LoadsField(ci, f_isDisabled, false));
			if (num <= 0 || !(list[num + 1].operand is Label item))
			{
				return instructions;
			}
			DeathHeadHopper.Logger.LogDebug((object)string.Format("{0} index: {1}", "PlayerSwitch_Transpiler", num));
			int num2 = list.FindIndex(num, (CodeInstruction ci) => ci.opcode == OpCodes.Ret);
			if (num2 <= 0)
			{
				DeathHeadHopper.Logger.LogError((object)"Could not find playerAvatar.isDisabled check in PlayerSwitch");
				return instructions;
			}
			DeathHeadHopper.Logger.LogDebug((object)string.Format("{0} returnIndex: {1}", "PlayerSwitch_Transpiler", num2));
			DeathHeadHopper.Logger.LogDebug((object)"Found playerAvatar.isDisabled check in PlayerSwitch, replacing code instructions");
			Label label = generator.DefineLabel();
			list[num2 + 1].labels.Add(label);
			list[num2 + 1].labels.Remove(item);
			list[num + 1].opcode = OpCodes.Brfalse_S;
			list[num + 2].labels.Add(item);
			list.InsertRange(num + 2, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[3]
			{
				new CodeInstruction(OpCodes.Ldloc_3, (object)null),
				CodeInstruction.Call(typeof(DHHFunc), "IsDeathHeadSpectatable", new Type[1] { typeof(PlayerAvatar) }, (Type[])null),
				new CodeInstruction(OpCodes.Brfalse, (object)label)
			});
			return list.AsEnumerable();
		}

		[HarmonyPatch("StateNormal")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> StateNormal_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			int num = list.FindIndex((CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, m_inputDown)) - 1;
			if (num <= 0 || list[num].opcode != OpCodes.Ldc_I4_1)
			{
				return instructions;
			}
			DeathHeadHopper.Logger.LogDebug((object)string.Format("{0} start: {1}", "StateNormal_Transpiler", num));
			int num2 = list.FindIndex(num, (CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, m_playerSwitch));
			if (num2 == -1)
			{
				return instructions;
			}
			DeathHeadHopper.Logger.LogDebug((object)string.Format("{0} end: {1}", "StateNormal_Transpiler", num2));
			DeathHeadHopper.Logger.LogDebug((object)"Found jump check in StateNormal, removing code instructions");
			CodeInstruction val = list[num];
			val.opcode = OpCodes.Nop;
			list.RemoveRange(num + 1, num2 - num);
			int num3 = -1;
			for (int i = 0; i < list.Count; i++)
			{
				if (CodeInstructionExtensions.IsLdarg(list[i], (int?)0) && CodeInstructionExtensions.Calls(list[i + 1], m_componentTransform) && CodeInstructionExtensions.Calls(list[i + 2], m_transformPosition) && CodeInstructionExtensions.LoadsField(list[i + 3], f_vector3Y, false))
				{
					num3 = i;
					break;
				}
			}
			if (num3 < 0)
			{
				DeathHeadHopper.Logger.LogWarning((object)"Camera Y lock not found in StateNormal");
				return list.AsEnumerable();
			}
			DeathHeadHopper.Logger.LogDebug((object)"Adding player is disabled check to camera Y lock in StateNormal");
			Label label = generator.DefineLabel();
			val.labels.Add(label);
			list.InsertRange(num3, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[4]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				CodeInstruction.LoadField(typeof(SpectateCamera), "player", false),
				CodeInstruction.LoadField(typeof(PlayerAvatar), "isDisabled", false),
				new CodeInstruction(OpCodes.Brtrue, (object)label)
			});
			return list.AsEnumerable();
		}
	}
}
namespace DeathHeadHopper.Models
{
	public class Tether : MonoBehaviour
	{
		public Vector3 origin;

		public Vector3 point;

		public Color tetherStartColor;

		public Color tetherEndColor;

		public float curveSpeed;

		public int curveResolution;

		public float colorInterpolation;

		public bool curveEnabled;

		public float width;

		[Header("Texture Scrolling")]
		public Vector2 scrollSpeed;

		private Vector3 curvePointSmooth;

		private LineRenderer lineRenderer;

		[HideInInspector]
		public Material lineMaterial;

		protected void Awake()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			lineRenderer = ((Component)this).gameObject.AddComponent<LineRenderer>();
			LineRenderer component = ((Component)PlayerAvatar.instance).GetComponent<PhysGrabber>().physGrabBeam.gameObject.GetComponent<LineRenderer>();
			((Renderer)lineRenderer).material = ((Renderer)component).material;
			lineRenderer.textureMode = component.textureMode;
			((Renderer)lineRenderer).shadowCastingMode = (ShadowCastingMode)0;
			lineMaterial = ((Renderer)lineRenderer).material;
		}

		protected void Start()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0033: 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)
			ResetCurvePointSmooth();
			AnimationCurve val = new AnimationCurve();
			val.AddKey(0f, 0f);
			val.AddKey(new Keyframe(0.1f, width, 0f, 0f));
			val.AddKey(new Keyframe(0.9f, width * 0.64f, 0f, 0f));
			val.AddKey(1f, width * 0.45f);
			lineRenderer.widthCurve = val;
		}

		protected void LateUpdate()
		{
			DrawLine();
			ScrollTexture();
		}

		internal void ResetCurvePointSmooth()
		{
			//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_000d: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			curvePointSmooth = (origin + point) / 2f;
		}

		private void DrawLine()
		{
			//IL_0016: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			float num = curveSpeed;
			if (!curveEnabled)
			{
				num = 20f;
			}
			Vector3 val = (origin + point) / 2f;
			Vector3[] array = (Vector3[])(object)new Vector3[curveResolution];
			curvePointSmooth = Vector3.Lerp(curvePointSmooth, val, Time.deltaTime * num);
			for (int i = 0; i < curveResolution; i++)
			{
				float t = (float)i / ((float)curveResolution - 1f);
				array[i] = CalculateBezierPoint(t, origin, curvePointSmooth, point);
			}
			lineRenderer.positionCount = curveResolution;
			lineRenderer.SetPositions(array);
		}

		private Vector3 CalculateBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
		{
			//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_0027: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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)
			return Mathf.Pow(1f - t, 2f) * p0 + 2f * (1f - t) * t * p1 + Mathf.Pow(t, 2f) * p2;
		}

		private void ScrollTexture()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0041: 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_0054: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)lineMaterial))
			{
				lineMaterial.mainTextureScale = new Vector2(1f, 1f);
				Vector2 mainTextureOffset = Time.time * scrollSpeed;
				lineMaterial.mainTextureOffset = mainTextureOffset;
				lineMaterial.color = Color.Lerp(tetherStartColor, tetherEndColor, colorInterpolation);
				lineMaterial.EnableKeyword("_EMISSION");
				lineMaterial.SetColor("_EmissionColor", lineMaterial.color);
			}
		}

		public Tether()
		{
			//IL_0016: 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_0022: 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_000f: 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_004d: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_009e: 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)
			Color val = default(Color);
			tetherStartColor = (Color)(ColorUtility.TryParseHtmlString("#00C4FD", ref val) ? new Color(val.r, val.g, val.b, 0.1f) : Color.blue);
			Color val2 = default(Color);
			tetherEndColor = (Color)(ColorUtility.TryParseHtmlString("#E70A17", ref val2) ? new Color(val2.r, val2.g, val2.b, 0.4f) : Color.red);
			curveSpeed = 2f;
			curveResolution = 20;
			curveEnabled = true;
			width = 0.11f;
			scrollSpeed = new Vector2(4f, 0f);
			((MonoBehaviour)this)..ctor();
		}
	}
}
namespace DeathHeadHopper.Managers
{
	public class DHHAbilityManager : MonoBehaviour
	{
		internal static List<AbilityBase> abilities = new List<AbilityBase>();

		internal const int abilitySlots = 3;

		internal bool spotsFeched;

		private readonly AbilitySpot[] abilitySpots = new AbilitySpot[3];

		private AbilitySpot? currentAbilitySpotDown;

		private AbilitySpot? currentAbilitySpot;

		private Dictionary<InputKey, int> inputKeyToAbilitySpot = new Dictionary<InputKey, int>
		{
			{
				(InputKey)19,
				0
			},
			{
				(InputKey)20,
				1
			},
			{
				(InputKey)21,
				2
			}
		};

		internal static DHHAbilityManager instance { get; private set; }

		internal static ChargeAbility ChargeAbility => (ChargeAbility)abilities.First((AbilityBase x) => x is ChargeAbility);

		protected void Awake()
		{
			instance = this;
		}

		protected void Start()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			DHHStatsManager.instance.m_LocalPlayerUpgrade.AddListener(new UnityAction(EquipAbilities));
		}

		protected void Update()
		{
			//IL_004a: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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)
			if (!spotsFeched || !DHHFunc.LocalDeathHeadActive())
			{
				if (currentAbilitySpot != null)
				{
					currentAbilitySpot.CurrentAbility?.OnAbilityCancel();
					currentAbilitySpot = null;
				}
				return;
			}
			foreach (InputKey key in inputKeyToAbilitySpot.Keys)
			{
				AbilitySpot abilitySpot = abilitySpots[inputKeyToAbilitySpot[key]];
				if (SemiFunc.InputDown(key) && currentAbilitySpotDown == null)
				{
					HandleInputDown(abilitySpot);
				}
				else if (SemiFunc.InputHold(key) && (Object)(object)currentAbilitySpotDown == (Object)(object)abilitySpot)
				{
					HandleInputHold(abilitySpot);
				}
				else if (SemiFunc.InputUp(key) && (Object)(object)currentAbilitySpotDown == (Object)(object)abilitySpot)
				{
					HandleInputUp(abilitySpot);
				}
			}
			if (currentAbilitySpot != null && (SemiFunc.InputDown((InputKey)1) || SemiFunc.InputDown((InputKey)24) || SemiFunc.InputDown((InputKey)23)))
			{
				currentAbilitySpot.CurrentAbility?.OnAbilityCancel();
				currentAbilitySpot = null;
			}
		}

		internal void EquipAbilities()
		{
			if (spotsFeched)
			{
				int headChargeUpgrade = DHHStatsManager.GetHeadChargeUpgrade(PlayerAvatar.instance.steamID);
				if (headChargeUpgrade > 0)
				{
					EquipAbility(ChargeAbility);
				}
				else
				{
					RemoveAbility(ChargeAbility);
				}
			}
		}

		public void EquipAbility(AbilityBase ability)
		{
			AbilityBase ability2 = ability;
			if (abilitySpots.Any((AbilitySpot x) => (Object)(object)x.CurrentAbility == (Object)(object)ability2))
			{
				DeathHeadHopper.Logger.LogDebug((object)("Ability " + ability2.AbilityName + " already equipped"));
				return;
			}
			AbilitySpot[] array = abilitySpots;
			foreach (AbilitySpot abilitySpot in array)
			{
				if ((Object)(object)abilitySpot.CurrentAbility == (Object)null)
				{
					DeathHeadHopper.Logger.LogDebug((object)$"Equipping {ability2.AbilityName} to spot {Array.IndexOf(abilitySpots, abilitySpot) + 1}");
					abilitySpot.EquipAbility(ability2);
					ability2.m_AbilityUsedLocal.AddListener((UnityAction<AbilityBase>)OnAbilityUsed);
					break;
				}
			}
		}

		public void RemoveAbility(AbilityBase ability)
		{
			AbilityBase ability2 = ability;
			AbilitySpot abilitySpot = abilitySpots.FirstOrDefault((AbilitySpot x) => (Object)(object)x.CurrentAbility == (Object)(object)ability2);
			if ((Object)(object)abilitySpot != (Object)null)
			{
				DeathHeadHopper.Logger.LogDebug((object)$"Removing {ability2.AbilityName} from spot {Array.IndexOf(abilitySpots, abilitySpot) + 1}");
				abilitySpot.RemoveAbility();
				ability2.m_AbilityUsedLocal.RemoveListener((UnityAction<AbilityBase>)OnAbilityUsed);
			}
		}

		internal bool HasEquippedAbility()
		{
			if (!spotsFeched)
			{
				return false;
			}
			AbilitySpot[] array = abilitySpots;
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i]?.CurrentAbility != (Object)null)
				{
					return true;
				}
			}
			return false;
		}

		internal void SetAbilitySpotAtIndex(AbilitySpot spot, int index)
		{
			if (SemiFunc.RunIsLevel() || SemiFunc.RunIsShop())
			{
				abilitySpots[index] = spot;
				if (abilitySpots.Count((AbilitySpot spot) => (Object)(object)spot != (Object)null) == 3)
				{
					spotsFeched = true;
					EquipAbilities();
				}
			}
		}

		private void HandleInputDown(AbilitySpot abilitySpot)
		{
			if (abilitySpot.CurrentAbility != null)
			{
				abilitySpot.CurrentAbility.OnAbilityDown();
				currentAbilitySpotDown = abilitySpot;
				if (currentAbilitySpot != null && (Object)(object)currentAbilitySpot != (Object)(object)abilitySpot)
				{
					currentAbilitySpot.CurrentAbility?.OnAbilityCancel();
				}
				currentAbilitySpot = abilitySpot;
			}
		}

		private void HandleInputHold(AbilitySpot abilitySpot)
		{
			abilitySpot.CurrentAbility?.OnAbilityHold();
		}

		private void HandleInputUp(AbilitySpot abilitySpot)
		{
			abilitySpot.lastUseTime = Time.time;
			abilitySpot.CurrentAbility?.OnAbilityUp();
			currentAbilitySpotDown = null;
		}

		private void OnAbilityUsed(AbilityBase ability)
		{
			DeathHeadController localDeathHeadController = DHHFunc.GetLocalDeathHeadController();
			if (localDeathHeadController != null)
			{
				GetAbilitySpot(ability)?.SetCooldown(ability.Cooldown);
			}
			currentAbilitySpot = null;
		}

		private AbilitySpot? GetAbilitySpot(AbilityBase ability)
		{
			AbilitySpot[] array = abilitySpots;
			foreach (AbilitySpot abilitySpot in array)
			{
				if ((Object)(object)abilitySpot.CurrentAbility == (Object)(object)ability)
				{
					return abilitySpot;
				}
			}
			return null;
		}
	}
	public static class DHHAssetManager
	{
		public static Material headPhaseMaterial = null;

		internal static readonly Dictionary<string, Item> shopItems = new Dictionary<string, Item>();

		private const string _mainAssetBundle = "deathheadhopper";

		public static void LoadAssets()
		{
			DeathHeadHopper.Logger.LogInfo((object)"Loading Assets...");
			AssetBundle val = LoadAssetBundle("deathheadhopper");
			if ((Object)(object)val == (Object)null)
			{
				DeathHeadHopper.Logger.LogError((object)"Failed to load asset bundle :(");
				return;
			}
			headPhaseMaterial = val.LoadAsset<Material>("Assets/DeathHeadHopper/Materials/Head Phase.mat");
			LoadItems(val);
			LoadAbilities(val);
			DHHShopManager.shopAtticShelvesPrefab = val.LoadAsset<GameObject>("Assets/DeathHeadHopper/Shop Attic Shelves.prefab");
			DHHUIManager.abilityUIPrefab = val.LoadAsset<GameObject>("Assets/DeathHeadHopper/Ability UI.prefab");
			LoadChargeAssets(val);
		}

		private static AssetBundle LoadAssetBundle(string name)
		{
			DeathHeadHopper.Logger.LogDebug((object)("DeathHeadHopper: Loading Asset Bundle: " + name));
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), name);
			return AssetBundle.LoadFromFile(text);
		}

		private static void LoadItems(AssetBundle assetBundle)
		{
			foreach (string item in from x in assetBundle.GetAllAssetNames()
				where x.ToLower().Contains("/items/") && x.EndsWith(".asset")
				select x)
			{
				Item val = assetBundle.LoadAsset<Item>(item);
				if ((Object)(object)val == (Object)null)
				{
					DeathHeadHopper.Logger.LogError((object)("Failed to load item; " + item + " :("));
					continue;
				}
				string text = item.Replace(".asset", ".prefab");
				val.prefab = assetBundle.LoadAsset<GameObject>(text);
				if ((Object)(object)val.prefab == (Object)null)
				{
					DeathHeadHopper.Logger.LogError((object)("Failed to load item prefab; " + text + " :("));
					continue;
				}
				DeathHeadHopper.Logger.LogDebug((object)("Loaded item: " + val.itemName));
				shopItems.Add(val.itemAssetName, val);
				Items.RegisterItem(val);
			}
		}

		private static void LoadAbilities(AssetBundle assetBundle)
		{
			foreach (string item in from x in assetBundle.GetAllAssetNames()
				where x.ToLower().Contains("/abilities/") && x.EndsWith(".asset")
				select x)
			{
				AbilityBase abilityBase = assetBundle.LoadAsset<AbilityBase>(item);
				if ((Object)(object)abilityBase == (Object)null)
				{
					DeathHeadHopper.Logger.LogError((object)("Failed to load ability " + item + " :("));
					continue;
				}
				DeathHeadHopper.Logger.LogDebug((object)("Loaded ability " + item));
				DHHAbilityManager.abilities.Add(abilityBase);
			}
		}

		private static void LoadChargeAssets(AssetBundle assetBundle)
		{
			ChargeEffects.prefab = assetBundle.LoadAsset<GameObject>("Assets/DeathHeadHopper/Abilities/Charge/Charge Effects.prefab");
		}
	}
	public static class DHHConfigManager
	{
		public static ConfigEntry<bool> flashLightFlicker;

		public static ConfigEntry<AnchorMode> anchorMode;

		public static ConfigEntry<bool> itemsAppearInShop;

		public static void BindConfig(ConfigFile Config)
		{
			DeathHeadHopper.Logger.LogInfo((object)"Binding Config...");
			string text = "General";
			string text2 = "Host Client Config";
			flashLightFlicker = Config.Bind<bool>(text, "FlashlightFlicker", true, "The head flickers its flashlight to indicate when something is wrong.");
			anchorMode = Config.Bind<AnchorMode>(text2, "AnchorMode", AnchorMode.ExtractionPointsCompleted, "Always anchor head with a tether | anchor once the last extraction point is completed | never anchor.");
			itemsAppearInShop = Config.Bind<bool>(text2, "ItemsAppearInShop", true, "Enable DeathHeadHopper items in the shop");
			RemoveOrphanedEntries(Config);
		}

		public static void RemoveOrphanedEntries(ConfigFile Config)
		{
			HashSet<string> hashSet = Config.Keys.Select((ConfigDefinition x) => x.Key).ToHashSet();
			Dictionary<int, string> orphanedEntries = new Dictionary<int, string>();
			string[] array = File.ReadAllLines(Config.ConfigFilePath);
			bool result = default(bool);
			for (int j = 0; j < array.Length; j++)
			{
				string text = array[j];
				string[] array2 = text.Split(new char[1] { '=' }, 2);
				if (array2.Length != 2)
				{
					continue;
				}
				string text2 = array2[0].Trim();
				string value = array2[1].Trim();
				if (!hashSet.Contains(text2))
				{
					if (text2 == "AnchorOnAllStages" && bool.TryParse(value, out result) && result)
					{
						DeathHeadHopper.Logger.LogWarning((object)("Config entry " + text2 + " is deprecated, loading value into new config entry " + ((ConfigEntryBase)anchorMode).Definition.Key));
						anchorMode.Value = AnchorMode.Always;
						Config.Save();
					}
					orphanedEntries.Add(j, text2);
				}
			}
			if (orphanedEntries.Count > 0)
			{
				DeathHeadHopper.Logger.LogWarning((object)("Removing orphaned " + string.Join(", ", orphanedEntries.Values) + " from config file"));
				string[] contents = File.ReadAllLines(Config.ConfigFilePath).Where((string _, int i) => !orphanedEntries.Keys.Contains(i)).ToArray();
				File.WriteAllLines(Config.ConfigFilePath, contents);
				Config.Reload();
			}
		}
	}
	public class DHHInputManager : MonoBehaviour
	{
		public Vector3 spectateOffset = new Vector3(0f, 0.6f, 0f);

		public float lowChargePitch = 0.8f;

		public float highChargePitch = 1.4f;

		private PlayerDeathHead deathHead;

		private Transform headTransform;

		private PhotonView headPhotonView;

		private DeathHeadController headController;

		private Transform _tMainCamera;

		public static DHHInputManager instance { get; internal set; }

		protected void Awake()
		{
			instance = this;
			if (string.IsNullOrWhiteSpace(DHHPunManager.hostVersion))
			{
				DeathHeadHopper.Logger.LogWarning((object)"Host does not have DeathHeadHopper installed!");
			}
			deathHead = PlayerAvatar.instance.playerDeathHead;
			headTransform = ((Component)deathHead).transform;
			headPhotonView = ((Component)deathHead).GetComponent<PhotonView>();
			headController = ((Component)deathHead).GetComponent<DeathHeadController>();
			PlayerAvatar.instance.spectatePoint = ((Component)this).transform;
			_tMainCamera = ((Component)Camera.main).transform;
		}

		protected void Update()
		{
			//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_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)
			//IL_0053: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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)
			if ((Object)(object)_tMainCamera == (Object)null)
			{
				_tMainCamera = ((Component)Camera.main).transform;
			}
			if (Object.op_Implicit((Object)(object)headTransform) && Object.op_Implicit((Object)(object)((Component)this).transform))
			{
				Quaternion val = Quaternion.LookRotation(Vector3.ProjectOnPlane(headTransform.forward, Vector3.up));
				Quaternion rotation = ((Component)this).transform.rotation;
				float x = ((Quaternion)(ref rotation)).eulerAngles.x;
				float y = ((Quaternion)(ref val)).eulerAngles.y;
				rotation = ((Component)this).transform.rotation;
				Quaternion val2 = Quaternion.Euler(x, y, ((Quaternion)(ref rotation)).eulerAngles.z);
				((Component)this).transform.SetPositionAndRotation(headTransform.position + spectateOffset, val2);
				if (headController.chargeHandler.State == ChargeHandler.ChargeState.Windup)
				{
					UpdateChargeWindup();
				}
			}
		}

		protected void LateUpdate()
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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)
			if ((Object)(object)SpectateCamera.instance.player != (Object)(object)PlayerAvatar.instance)
			{
				return;
			}
			if (SemiFunc.InputDown((InputKey)1))
			{
				Jump();
			}
			if (SemiFunc.InputDown((InputKey)14))
			{
				Vector3 val = Vector3.ProjectOnPlane(((Component)_tMainCamera).transform.forward, Vector3.up);
				Vector3 normalized = ((Vector3)(ref val)).normalized;
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					headController.hopHandler.HopRealign(normalized, GetMoveDirection());
				}
				else
				{
					headPhotonView.RPC("HopRealign", (RpcTarget)2, new object[2]
					{
						normalized,
						GetMoveDirection()
					});
				}
			}
			Vector3 val2 = ((Component)_tMainCamera).transform.forward;
			val2 = Vector3.RotateTowards(val2, Vector3.up, 0.34906584f, 0f);
			Debug.DrawRay(((Component)this).transform.position, ((Vector3)(ref val2)).normalized * 10f, Color.blue);
		}

		private Vector3 GetMoveDirection()
		{
			//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_0015: 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_001e: 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_0024: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_004e: 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_005d: 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_0060: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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_0083: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.ProjectOnPlane(((Component)_tMainCamera).transform.forward, Vector3.up);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			Vector3 val2 = Vector3.Cross(Vector3.up, normalized);
			float num = SemiFunc.InputMovementX();
			float num2 = SemiFunc.InputMovementY();
			Vector3 val3 = Vector3.zero;
			if (num2 > 0f)
			{
				val3 += normalized;
			}
			if (num2 < 0f)
			{
				val3 -= normalized;
			}
			if (num < 0f)
			{
				val3 -= val2;
			}
			if (num > 0f)
			{
				val3 += val2;
			}
			return ((Vector3)(ref val3)).normalized;
		}

		private void Jump()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Vector3 moveDirection = GetMoveDirection();
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				headController.jumpHandler.JumpHead(moveDirection);
				return;
			}
			headPhotonView.RPC("JumpHead", (RpcTarget)2, new object[1] { moveDirection });
		}

		public void ChargeWindup()
		{
			//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_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_0054: 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)
			Vector3 forward = ((Component)_tMainCamera).transform.forward;
			forward = Vector3.RotateTowards(forward, Vector3.up, MathF.PI * 2f / 45f, 0f);
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				headController.chargeHandler.ChargeWindup(forward);
				return;
			}
			headPhotonView.RPC("ChargeWindup", (RpcTarget)2, new object[1] { forward });
		}

		private void UpdateChargeWindup()
		{
			//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_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_0054: 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)
			Vector3 forward = ((Component)_tMainCamera).transform.forward;
			forward = Vector3.RotateTowards(forward, Vector3.up, MathF.PI * 2f / 45f, 0f);
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				headController.chargeHandler.UpdateWindupDirection(forward);
				return;
			}
			headPhotonView.RPC("UpdateWindupDirection", (RpcTarget)2, new object[1] { forward });
		}

		public void CancelCharge()
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				headController.chargeHandler.CancelCharge();
			}
			else
			{
				headPhotonView.RPC("CancelCharge", (RpcTarget)2, Array.Empty<object>());
			}
		}
	}
	public class DHHPunManager : MonoBehaviour
	{
		internal static string hostVersion = string.Empty;

		internal static string localVersion = string.Empty;

		internal PhotonView photonView;

		private DHHStatsManager statsManager;

		public static DHHPunManager instance { get; private set; }

		protected void Awake()
		{
			if ((Object)(object)instance == (Object)null || (Object)(object)((Component)instance).gameObject == (Object)null)
			{
				instance = this;
				EnsurePhotonView();
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		protected void Start()
		{
			statsManager = DHHStatsManager.instance;
		}

		internal void EnsurePhotonView()
		{
			if ((Object)(object)((Component)this).gameObject.GetComponent<PhotonView>() == (Object)null)
			{
				photonView = ((Component)this).gameObject.AddComponent<PhotonView>();
				photonView.ViewID = 745;
			}
			else if ((Object)(object)photonView == (Object)null)
			{
				photonView = ((Component)this).gameObject.GetComponent<PhotonView>();
			}
		}

		internal void VersionCheck()
		{
			localVersion = DeathHeadHopper.Version.ToString();
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				hostVersion = localVersion;
			}
			if (SemiFunc.IsMultiplayer() && PhotonNetwork.PlayerList.Length != 1)
			{
				if (SemiFunc.IsMasterClient())
				{
					photonView.RPC("VersionCheckRPC", (RpcTarget)1, new object[1] { localVersion });
				}
				else
				{
					photonView.RPC("VersionCheckRPC", (RpcTarget)2, new object[1] { localVersion });
				}
			}
		}

		[PunRPC]
		internal void VersionCheckRPC(string remoteVersion, PhotonMessageInfo info)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			string text = DeathHeadHopper.Version.ToString();
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				hostVersion = remoteVersion;
				if (text != remoteVersion)
				{
					DeathHeadHopper.Logger.LogWarning((object)("Master client has a different version of DeathHeadHopper! Local version: " + text + ", Remote version: " + remoteVersion + ". Some features may not work correctly or may be disabled."));
				}
				return;
			}
			Player sender = info.Sender;
			if (text != remoteVersion)
			{
				DeathHeadHopper.Logger.LogWarning((object)("Player " + sender.NickName + " has a different version of DeathHeadHopper! Local version: " + text + ", Remote version: " + remoteVersion + ". Some features may not work correctly or may be disabled."));
			}
		}

		internal void LoadShopAtticShelves()
		{
			if (SemiFunc.IsMasterClient() && DHHConfigManager.itemsAppearInShop.Value)
			{
				DHHShopManager.LoadShopAtticShelves();
				if (PhotonNetwork.PlayerList.Length > 1)
				{
					photonView.RPC("LoadShopAtticShelvesRPC", (RpcTarget)1, Array.Empty<object>());
				}
			}
		}

		[PunRPC]
		internal void LoadShopAtticShelvesRPC()
		{
			DHHShopManager.LoadShopAtticShelves();
		}

		internal void AbilityUsed(string playerId, AbilityBase ability)
		{
			if (!SemiFunc.IsMultiplayer())
			{
				AbilityUsedRPC(playerId, ability.AbilityName);
				return;
			}
			photonView.RPC("AbilityUsedRPC", (RpcTarget)0, new object[2] { playerId, ability.AbilityName });
		}

		[PunRPC]
		internal void AbilityUsedRPC(string playerId, string abilityName)
		{
			string abilityName2 = abilityName;
			PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(playerId);
			AbilityBase abilityBase = DHHAbilityManager.abilities.FirstOrDefault((AbilityBase x) => x.AbilityName == abilityName2);
			if ((Object)(object)abilityBase == (Object)null)
			{
				DeathHeadHopper.Logger.LogWarning((object)("Ability " + abilityName2 + " not found"));
				return;
			}
			if ((Object)(object)val == (Object)(object)SemiFunc.PlayerAvatarLocal())
			{
				abilityBase.m_AbilityUsedLocal.Invoke(abilityBase);
			}
			((Component)val.playerDeathHead).GetComponent<DeathHeadController>().abilityEnergyHandler.DecreaseEnergy(abilityBase.EnergyCost);
		}

		[PunRPC]
		public void UpgradeHeadChargeRPC(string _steamID, int value)
		{
			statsManager.UpdateHeadChargeStat(_steamID, value);
		}

		[PunRPC]
		public void UpgradeHeadPowerRPC(string _steamID, int value)
		{
			statsManager.UpdateHeadPowerStat(_steamID, value);
		}
	}
	public class DHHShopManager
	{
		public static GameObject shopAtticShelvesPrefab;

		private static readonly List<ItemVolume> itemVolumes = new List<ItemVolume>();

		private static readonly List<Item> potentialItems = new List<Item>();

		public static void LoadShopAtticShelves()
		{
			Module val = (from x in Object.FindObjectsOfType<Module>()
				where ((Object)x).name.Contains("Shop") && ((Object)x).name.Contains("Generic")
				select x).FirstOrDefault();
			GameObject val2 = Object.Instantiate<GameObject>(shopAtticShelvesPrefab, ((Component)val).transform, false);
			DeathHeadHopper.Logger.LogInfo((object)("Added " + ((Object)shopAtticShelvesPrefab).name + " to " + ((Object)val).name));
			if (!SemiFunc.IsNotMasterClient())
			{
				itemVolumes.Clear();
				itemVolumes.AddRange(val2.GetComponentsInChildren<ItemVolume>());
				ListExtension.Shuffle<ItemVolume>((IList<ItemVolume>)itemVolumes);
			}
		}

		public static void LoadItems()
		{
			if (!SemiFunc.IsNotMasterClient())
			{
				ShopManager instance = ShopManager.instance;
				potentialItems.Clear();
				potentialItems.AddRange(instance.potentialItemUpgrades.Where((Item x) => DHHAssetManager.shopItems.ContainsKey(x.itemAssetName)));
				potentialItems.AddRange(instance.potentialItems.Where((Item x) => DHHAssetManager.shopItems.ContainsKey(x.itemAssetName)));
				instance.potentialItemUpgrades.RemoveAll((Item x) => DHHAssetManager.shopItems.ContainsKey(x.itemAssetName));
				instance.potentialItems.RemoveAll((Item x) => DHHAssetManager.shopItems.ContainsKey(x.itemAssetName));
			}
		}

		public static void ShopPopulateItemVolumes(PunManager punManager)
		{
			if (SemiFunc.IsNotMasterClient())
			{
				return;
			}
			int num = 0;
			foreach (ItemVolume itemVolume in itemVolumes)
			{
				punManager.SpawnShopItem(itemVolume, potentialItems, ref num, false);
			}
		}
	}
	public class DHHStatsManager : MonoBehaviour
	{
		private readonly Dictionary<string, int> playerUpgradeHeadCharge = new Dictionary<string, int>();

		private readonly Dictionary<string, int> playerUpgradeHeadPower = new Dictionary<string, int>();

		internal UnityEvent m_LocalPlayerUpgrade = new UnityEvent();

		public static DHHStatsManager instance { get; private set; }

		protected void Awake()
		{
			if ((Object)(object)instance == (Object)null)
			{
				instance = this;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		protected void Start()
		{
			if (!StatsManager.instance.dictionaryOfDictionaries.TryAdd("playerUpgradeHeadCharge", playerUpgradeHeadCharge))
			{
				DeathHeadHopper.Logger.LogError((object)"Failed to add playerUpgradeHeadCharge dictionary to StatsManager");
			}
			if (!StatsManager.instance.dictionaryOfDictionaries.TryAdd("playerUpgradeHeadPower", playerUpgradeHeadPower))
			{
				DeathHeadHopper.Logger.LogError((object)"Failed to add playerUpgradeHeadPower dictionary to StatsManager");
			}
		}

		internal int UpgradeHeadCharge(string playerId)
		{
			playerUpgradeHeadCharge[playerId]++;
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				UpdateHeadChargeStat(playerId, playerUpgradeHeadCharge[playerId]);
			}
			if (SemiFunc.IsMasterClient())
			{
				DHHPunManager.instance.photonView.RPC("UpgradeHeadChargeRPC", (RpcTarget)1, new object[2]
				{
					playerId,
					playerUpgradeHeadCharge[playerId]
				});
			}
			return playerUpgradeHeadCharge[playerId];
		}

		internal void UpdateHeadChargeStat(string playerId, int value)
		{
			playerUpgradeHeadCharge[playerId] = value;
			if (PlayerAvatar.instance.steamID == playerId)
			{
				m_LocalPlayerUpgrade.Invoke();
			}
		}

		public static int GetHeadChargeUpgrade(string playerId)
		{
			if (instance.playerUpgradeHeadCharge.TryGetValue(playerId, out var value))
			{
				return value;
			}
			return 0;
		}

		internal int UpgradeHeadPower(string playerId)
		{
			playerUpgradeHeadPower[playerId]++;
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				UpdateHeadPowerStat(playerId, playerUpgradeHeadPower[playerId]);
			}
			if (SemiFunc.IsMasterClient())
			{
				DHHPunManager.instance.photonView.RPC("UpgradeHeadPowerRPC", (RpcTarget)1, new object[2]
				{
					playerId,
					playerUpgradeHeadPower[playerId]
				});
			}
			return playerUpgradeHeadPower[playerId];
		}

		internal void UpdateHeadPowerStat(string playerId, int value)
		{
			playerUpgradeHeadPower[playerId] = value;
			if (PlayerAvatar.instance.steamID == playerId)
			{
				PlayerDeathHead playerDeathHead = PlayerAvatar.instance.playerDeathHead;
				AbilityEnergyHandler abilityEnergyHandler = ((playerDeathHead == null) ? null : ((Component)playerDeathHead).GetComponent<DeathHeadController>()?.abilityEnergyHandler);
				abilityEnergyHandler?.IncreaseEnergy(abilityEnergyHandler.energyIncrease);
			}
		}

		public static int GetHeadPowerUpgrade(string playerId)
		{
			if (instance.playerUpgradeHeadPower.TryGetValue(playerId, out var value))
			{
				return value;
			}
			return 0;
		}
	}
	public class DHHUIManager : MonoBehaviour
	{
		internal static GameObject abilityUIPrefab;

		internal GameObject gameHUD;

		internal static DHHUIManager instance { get; private set; }

		protected void Awake()
		{
			instance = this;
			gameHUD = ((Component)((Component)InventoryUI.instance).transform.parent).gameObject;
			if (gameHUD == null)
			{
				DeathHeadHopper.Logger.LogError((object)"Game Hud not found!");
			}
			else
			{
				Object.Instantiate<GameObject>(abilityUIPrefab, gameHUD.transform, false);
			}
		}
	}
}
namespace DeathHeadHopper.Items
{
	public class DHHItemHeadCharger : MonoBehaviour
	{
		public Transform chargePoint;

		public Renderer batteryMaterial;

		public Light batteryLight;

		public Color tetherStartColor;

		public Color tetherEndColor;

		public float tetherWidth;

		internal float chargeRate;

		internal float chargeRadius;

		internal float headChargeMultiplier;

		private float maxBatteryLightIntensity;

		private float chargeBurstTimer;

		private float batteryOutBlinkTimer;

		private float batteryBleepTimer;

		private LayerMask headLayerMask;

		private ItemBattery itemBattery;

		private ItemEquippable itemEquippable;

		private Renderer batteryRenderer;

		private readonly HashSet<DeathHeadController> headsInRange;

		private readonly Dictionary<DeathHeadController, Tether> headTethers;

		private Color transparent;

		protected void Start()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			itemBattery = ((Component)this).GetComponent<ItemBattery>();
			itemEquippable = ((Component)this).GetComponent<ItemEquippable>();
			headLayerMask = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { "PhysGrabObject" }));
			batteryRenderer = ((Component)itemBattery.batteryTransform).GetComponentInChildren<Renderer>();
			itemBattery.batteryLife = 100f;
			ReplaceMaterial();
			maxBatteryLightIntensity = batteryLight.intensity;
		}

		protected void Update()
		{
			if (chargeBurstTimer > 0f)
			{
				chargeBurstTimer -= Time.deltaTime;
			}
			SphereCheck();
			DrawChargeLines();
			UpdateBatteryEffects();
		}

		protected void LateUpdate()
		{
			ReplaceMaterial();
		}

		protected void ReplaceMaterial()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)batteryRenderer != (Object)null && (Object)(object)batteryRenderer.material != (Object)null)
			{
				batteryRenderer.material.color = transparent;
			}
		}

		protected void FixedUpdate()
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer() || itemBattery.batteryLife <= 0f)
			{
				return;
			}
			float num = 0f;
			foreach (DeathHeadController item in headsInRange)
			{
				if (item.abilityEnergyHandler.Energy < item.abilityEnergyHandler.EnergyMax)
				{
					float num2 = item.abilityEnergyHandler.EnergyMax / AbilityEnergyHandler.baseEnergyMax;
					float num3 = Mathf.Min(chargeRate * Time.fixedDeltaTime * num2, item.abilityEnergyHandler.EnergyMax - item.abilityEnergyHandler.Energy);
					item.abilityEnergyHandler.IncreaseEnergy(num3);
					num += num3 / Time.fixedDeltaTime / num2;
				}
			}
			if (num > 0f)
			{
				itemBattery.Drain(num / headChargeMultiplier);
			}
		}

		private void SphereCheck()
		{
			//IL_0011: 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)
			headsInRange.Clear();
			Collider[] array = Physics.OverlapSphere(chargePoint.position, chargeRadius, LayerMask.op_Implicit(headLayerMask));
			Collider[] array2 = array;
			DeathHeadController item = default(DeathHeadController);
			foreach (Collider val in array2)
			{
				if (((Component)((Component)val).transform.parent).TryGetComponent<DeathHeadController>(ref item))
				{
					headsInRange.Add(item);
				}
			}
		}

		private void DrawChargeLines()
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//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_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			List<DeathHeadController> list = headTethers.Keys.Where((DeathHeadController head) => !headsInRange.Contains(head)).ToList();
			foreach (DeathHeadController item in list)
			{
				Object.Destroy((Object)(object)((Component)headTethers[item]).gameObject);
				headTethers.Remove(item);
			}
			foreach (DeathHeadController item2 in headsInRange)
			{
				if (!headTethers.ContainsKey(item2))
				{
					GameObject val = new GameObject("HeadChargeLine");
					val.transform.parent = ((Component)this).transform;
					headTethers[item2] = val.AddComponent<Tether>();
					headTethers[item2].tetherStartColor = tetherStartColor;
					headTethers[item2].tetherEndColor = tetherEndColor;
					headTethers[item2].width = tetherWidth;
				}
			}
			foreach (KeyValuePair<DeathHeadController, Tether> headTether in headTethers)
			{
				DeathHeadController key = headTether.Key;
				Tether value = headTether.Value;
				RepositionTether(value, key);
				if (key.abilityEnergyHandler.Energy < key.abilityEnergyHandler.EnergyMax && itemBattery.batteryLife > 0f)
				{
					if (!((Component)value).gameObject.activeInHierarchy)
					{
						((Component)value).gameObject.SetActive(true);
					}
					value.ResetCurvePointSmooth();
				}
				else if (((Component)value).gameObject.activeInHierarchy)
				{
					((Component)value).gameObject.SetActive(false);
				}
			}
		}

		private void UpdateBatteryEffects()
		{
			if (itemBattery.batteryLife <= 0f)
			{
				if (headsInRange.Any((DeathHeadController x) => x.abilityEnergyHandler.Energy < x.abilityEnergyHandler.EnergyMax))
				{
					batteryBleepTimer += Time.deltaTime;
					bool flag = batteryBleepTimer < 3f;
					if (flag != itemBattery.batteryActive)
					{
						itemBattery.BatteryToggle(flag);
					}
				}
				else
				{
					batteryBleepTimer = 0f;
					if (itemBattery.batteryActive)
					{
						itemBattery.BatteryToggle(false);
					}
				}
				if (itemBattery.batteryActive)
				{
					batteryOutBlinkTimer = (batteryOutBlinkTimer + Time.deltaTime) % 1f;
					BatteryOffsetTexture((batteryOutBlinkTimer >= 0.5f) ? 1 : 0);
				}
				else
				{
					batteryOutBlinkTimer = 0f;
					BatteryOffsetTexture(0);
				}
			}
			else
			{
				batteryOutBlinkTimer = 0f;
				BatteryOffsetTexture(itemBattery.batteryLifeInt);
				bool flag2 = headsInRange.Any((DeathHeadController x) => x.abilityEnergyHandler.Energy < x.abilityEnergyHandler.EnergyMax);
				if (flag2 != itemBattery.batteryActive)
				{
					itemBattery.BatteryToggle(flag2);
				}
			}
		}

		private void RepositionTether(Tether tether, DeathHeadController head)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			tether.origin = chargePoint.position;
			tether.point = ((Component)head).transform.position;
		}

		private void BatteryOffsetTexture(int batteryLife)
		{
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: 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)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)batteryMaterial))
			{
				switch (batteryLife)
				{
				case 6:
					batteryMaterial.material.SetTextureOffset("_MainTex", new Vector2(0f, 0f));
					batteryLight.intensity = maxBatteryLightIntensity;
					break;
				case 5:
					batteryMaterial.material.SetTextureOffset("_MainTex", new Vector2(0.25f, 0f));
					batteryLight.intensity = maxBatteryLightIntensity * 0.9f;
					break;
				case 4:
					batteryMaterial.material.SetTextureOffset("_MainTex", new Vector2(0.5f, 0f));
					batteryLight.intensity = maxBatteryLightIntensity * 0.8f;
					break;
				case 3:
					batteryMaterial.material.SetTextureOffset("_MainTex", new Vector2(0.75f, 0f));
					batteryLight.intensity = maxBatteryLightIntensity * 0.7f;
					break;
				case 2:
					batteryMaterial.material.SetTextureOffset("_MainTex", new Vector2(0f, -0.5f));
					batteryLight.intensity = maxBatteryLightIntensity * 0.6f;
					break;
				case 1:
					batteryMaterial.material.SetTextureOffset("_MainTex", new Vector2(0.25f, -0.5f));
					batteryLight.intensity = maxBatteryLightIntensity * 0.5f;
					break;
				case 0:
					batteryMaterial.material.SetTextureOffset("_MainTex", new Vector2(0.5f, -0.5f));
					batteryLight.intensity = 0f;
					break;
				}
			}
		}

		public DHHItemHeadCharger()
		{
			//IL_0016: 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_0022: 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_000f: 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_004d: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_00c5: 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)
			Color val = default(Color);
			tetherStartColor = (Color)(ColorUtility.TryParseHtmlString("#FCFF00", ref val) ? new Color(val.r, val.g, val.b, 0.6f) : Color.yellow);
			Color val2 = default(Color);
			tetherEndColor = (Color)(ColorUtility.TryParseHtmlString("#FCFF00", ref val2) ? new Color(val2.r, val2.g, val2.b, 0.9f) : Color.yellow);
			tetherWidth = 0.06f;
			chargeRate = 15f;
			chargeRadius = 4f;
			headChargeMultiplier = 2.5f;
			headsInRange = new HashSet<DeathHeadController>();
			headTethers = new Dictionary<DeathHeadController, Tether>();
			transparent = new Color(0f, 0f, 0f, 0f);
			((MonoBehaviour)this)..ctor();
		}
	}
	public class DHHItemUpgradeCharge : MonoBehaviour
	{
		private ItemToggle itemToggle;

		private void Start()
		{
			itemToggle = ((Component)this).GetComponent<ItemToggle>();
		}

		public void Upgrade()
		{
			DHHStatsManager.instance.UpgradeHeadCharge(SemiFunc.PlayerGetSteamID(SemiFunc.PlayerAvatarGetFromPhotonID(itemToggle.playerTogglePhotonID)));
		}
	}
	public class DHHItemUpgradePower : MonoBehaviour
	{
		private ItemToggle itemToggle;

		private void Start()
		{
			itemToggle = ((Component)this).GetComponent<ItemToggle>();
		}

		public void Upgrade()
		{
			DHHStatsManager.instance.UpgradeHeadPower(SemiFunc.PlayerGetSteamID(SemiFunc.PlayerAvatarGetFromPhotonID(itemToggle.playerTogglePhotonID)));
		}
	}
}
namespace DeathHeadHopper.Helpers
{
	public static class DHHFunc
	{
		public static GameObject DeathHeadHopperObj;

		public static bool IsDeathHeadSpectatable(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)(object)PlayerAvatar.instance)
			{
				if (!SemiFunc.RunIsLevel())
				{
					return SemiFunc.RunIsShop();
				}
				return true;
			}
			return false;
		}

		public static bool LocalDeathHeadActive()
		{
			if ((Object)(object)DeathHeadHopperObj != (Object)null)
			{
				return DeathHeadHopperObj.activeSelf;
			}
			return false;
		}

		public static bool DeathHeadActive(string steamId)
		{
			return SemiFunc.PlayerGetFromSteamID(steamId).playerDeathHead.triggered;
		}

		public static bool IsLastPointExtracting()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Invalid comparison between Unknown and I4
			RoundDirector instance = RoundDirector.instance;
			if (instance.extractionPointsCompleted >= instance.extractionPoints - 1 && Object.op_Implicit((Object)(object)instance.extractionPointCurrent))
			{
				if ((int)instance.extractionPointCurrent.currentState != 3 && (int)instance.extractionPointCurrent.currentState != 4)
				{
					return (int)instance.extractionPointCurrent.currentState == 6;
				}
				return true;
			}
			return false;
		}

		public static DeathHeadController? GetLocalDeathHeadController()
		{
			return ((Component)PlayerAvatar.instance.playerDeathHead).GetComponent<DeathHeadController>();
		}

		public static float StatWithDiminishingReturns(float baseValue, float increasePerLevel, int currentLevel, int thresholdLevel = 10, float diminishingFactor = 0.9f)
		{
			currentLevel--;
			thresholdLevel--;
			float num = Mathf.Min(currentLevel, thresholdLevel);
			float num2 = Mathf.Max(0, currentLevel - thresholdLevel);
			float num3 = num2 * Mathf.Pow(diminishingFactor, num2);
			return baseValue + increasePerLevel * (num + num3);
		}

		public static float ActivePlayerNearestDistance(Vector3 position)
		{
			//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_0057: 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)
			float num = 999f;
			List<PlayerAvatar> playerList = GameDirector.instance.PlayerList;
			foreach (PlayerAvatar item in playerList.Where((PlayerAvatar x) => !x.isDisabled))
			{
				Vector3 position2 = item.PlayerVisionTarget.VisionTransform.position;
				float num2 = Vector3.Distance(position, position2);
				if (num2 < num)
				{
					num = num2;
				}
			}
			return num;
		}

		public static bool IsHeadChargerBattery(ItemBattery battery)
		{
			return (Object)(object)((Component)battery).GetComponent<DHHItemHeadCharger>() != (Object)null;
		}
	}
}
namespace DeathHeadHopper.DeathHead
{
	public class DeathHeadController : MonoBehaviourPun
	{
		internal PlayerDeathHead deathHead;

		internal Rigidbody rb;

		internal PhysGrabObjectImpactDetector impactDetector;

		internal CollisionHandler collisionHandler;

		internal HopHandler hopHandler;

		internal JumpHandler jumpHandler;

		internal AudioHandler audioHandler;

		internal ReboundHandler reboundHandler;

		internal AnchorHandler anchorHandler;

		internal EyeHandler eyeHandler;

		internal PhaseHandler phaseHandler;

		internal EffectHandler effectHandler;

		internal ShakeHandler shakeHandler;

		internal ChargeHandler chargeHandler;

		internal AbilityEnergyHandler abilityEnergyHandler;

		public float mouseTalkPlayerDistanceRange = 5f;

		public UnityEvent m_HeadJumpEvent = new UnityEvent();

		public UnityEvent m_HeadHopEvent = new UnityEvent();

		internal bool spectated;

		internal float timeSinceGrabbed = float.PositiveInfinity;

		internal float timeInTruck;

		private bool localSeen;

		private float mouseTalkTimer;

		internal void Start()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			deathHead = ((Component)this).GetComponent<PlayerDeathHead>();
			rb = ((Component)this).GetComponent<Rigidbody>();
			impactDetector = ((Component)this).GetComponent<PhysGrabObjectImpactDetector>();
			impactDetector.playerHurtDisable = false;
			if (m_HeadJumpEvent == null)
			{
				m_HeadJumpEvent = new UnityEvent();
			}
			if (m_HeadHopEvent == null)
			{
				m_HeadHopEvent = new UnityEvent();
			}
			collisionHandler = ((Component)this).gameObject.AddComponent<CollisionHandler>();
			hopHandler = ((Component)this).gameObject.AddComponent<HopHandler>();
			jumpHandler = ((Component)this).gameObject.AddComponent<JumpHandler>();
			audioHandler = ((Component)this).gameObject.AddComponent<AudioHandler>();
			reboundHandler = ((Component)this).gameObject.AddComponent<ReboundHandler>();
			anchorHandler = ((Component)this).gameObject.AddComponent<AnchorHandler>();
			eyeHandler = ((Component)this).gameObject.AddComponent<EyeHandler>();
			phaseHandler = ((Component)this).gameObject.AddComponent<PhaseHandler>();
			effectHandler = ((Component)this).gameObject.AddComponent<EffectHandler>();
			shakeHandler = ((Component)this).gameObject.AddComponent<ShakeHandler>();
			chargeHandler = ((Component)this).gameObject.AddComponent<ChargeHandler>();
			abilityEnergyHandler = ((Component)this).gameObject.AddComponent<AbilityEnergyHandler>();
		}

		internal void Update()
		{
			timeSinceGrabbed = (deathHead.physGrabObject.grabbed ? 0f : (timeSinceGrabbed + Time.deltaTime));
			timeInTruck = (deathHead.roomVolumeCheck.inTruck ? (timeInTruck + Time.deltaTime) : 0f);
			CancelReviveInCart();
			FixDeathHeadTpWhenOutsideRoom();
			MouseTalkUpdate();
		}

		internal void FixDeathHeadTpWhenOutsideRoom()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_0069: 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)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || (int)GameDirector.instance.currentState != 2)
			{
				return;
			}
			if (((Component)this).transform.position.y < -50f)
			{
				if (RoundDirector.instance.extractionPointActive)
				{
					deathHead.physGrabObject.Teleport(RoundDirector.instance.extractionPointCurrent.safetySpawn.position, RoundDirector.instance.extractionPointCurrent.safetySpawn.rotation);
				}
				else
				{
					deathHead.physGrabObject.Teleport(((Component)TruckSafetySpawnPoint.instance).transform.position, ((Component)TruckSafetySpawnPoint.instance).transform.rotation);
				}
				rb.velocity = Vector3.zero;
				if (anchorHandler.isAnchored)
				{
					anchorHandler.DestroyAnchor();
				}
			}
			if (deathHead.outsideLevelTimer > 0f)
			{
				deathHead.outsideLevelTimer = 0f;
			}
		}

		internal void CancelReviveInCart()
		{
			if (!StandardTruckReviveCondition())
			{
				localSeen = false;
				return;
			}
			if (!localSeen && effectHandler.TryCreateDiscoverEffect((State)0))
			{
				localSeen = true;
			}
			if (SemiFunc.IsMasterClientOrSingleplayer() && !ShouldReviveInTruck())
			{
				deathHead.inTruckReviveTimer = 0.4f;
			}
		}

		internal bool StandardTruckReviveCondition()
		{
			if (RoundDirector.instance.allExtractionPointsCompleted && !deathHead.playerAvatar.finalHeal)
			{
				return deathHead.roomVolumeCheck.inTruck;
			}
			return false;
		}

		internal bool ShouldReviveInTruck()
		{
			if (DHHConfigManager.anchorMode.Value == AnchorMode.Never)
			{
				if (timeSinceGrabbed < timeInTruck)
				{
					return true;
				}
				if (collisionHandler.timeSinceCollidedGrabbedCart < 2f)
				{
					return true;
				}
				if (collisionHandler.timeSinceCollidedGrabbedCart < timeInTruck)
				{
					return true;
				}
				return false;
			}
			if (!anchorHandler.isAnchored)
			{
				return true;
			}
			float? timeSinceAnchorCartGrabbed = anchorHandler.timeSinceAnchorCartGrabbed;
			if (timeSinceAnchorCartGrabbed.HasValue)
			{
				timeSinceAnchorCartGrabbed = anchorHandler.timeSinceAnchorCartGrabbed;
				if (timeSinceAnchorCartGrabbed.HasValue && timeSinceAnchorCartGrabbed.GetValueOrDefault() < 2f)
				{
					return true;
				}
			}
			if (timeSinceGrabbed < timeInTruck)
			{
				return true;
			}
			return false;
		}

		internal void LateUpdate()
		{
			UpdateSpectated();
		}

		private void UpdateSpectated()
		{
			if (!deathHead.playerAvatar.isLocal)
			{
				return;
			}
			if (!deathHead.triggered || SpectateCamera.instance?.player == null)
			{
				spectated = false;
			}
			else if ((Object)(object)SpectateCamera.instance.player == (Object)(object)PlayerAvatar.instance && !spectated)
			{
				if (GameManager.Multiplayer())
				{
					((MonoBehaviourPun)this).photonView.RPC("SetSpectated", (RpcTarget)1, new object[1] { true });
				}
				SetSpectated(value: true);
			}
			else if ((Object)(object)SpectateCamera.instance.player != (Object)(object)PlayerAvatar.instance && spectated)
			{
				if (GameManager.Multiplayer())
				{
					((MonoBehaviourPun)this).photonView.RPC("SetSpectated", (RpcTarget)1, new object[1] { false });
				}
				SetSpectated(value: false);
			}
		}

		private void MouseTalkUpdate()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (spectated && (StandardTruckReviveCondition() || deathHead.roomVolumeCheck.inExtractionPoint) && DHHFunc.ActivePlayerNearestDistance(((Component)this).transform.position) < mouseTalkPlayerDistanceRange)
			{
				if (mouseTalkTimer < 10f)
				{
					audioHandler.PlayMouseTalkSound();
					mouseTalkTimer += Time.deltaTime;
				}
			}
			else
			{
				mouseTalkTimer = 0f;
			}
		}

		[PunRPC]
		internal void SetSpectated(bool value)
		{
			spectated = value;
		}
	}
}
namespace DeathHeadHopper.DeathHead.Handlers
{
	public class AbilityEnergyHandler : MonoBehaviourPun
	{
		private DeathHeadController controller;

		public static float baseEnergyMax = 100f;

		public float energyIncrease = 20f;

		public float chargeSpeed = 2f;

		public float rechargeSoundDelay = 0.5f;

		private float lastRechargeSoundTime;

		private int PowerLevel => DHHStatsManager.GetHeadPowerUpgrade(controller.deathHead.playerAvatar.steamID);

		public float Energy { get; private set; }

		public float EnergyMax => baseEnergyMax + energyIncrease * (float)PowerLevel;

		protected void Awake()
		{
			controller = ((Component)this).GetComponent<DeathHeadController>();
			Energy = EnergyMax;
		}

		public void IncreaseEnergy(float amount)
		{
			Energy += amount;
			if (SemiFunc.IsMasterClient())
			{
				((MonoBehaviourPun)this).photonView.RPC("SyncEnergyRPC", (RpcTarget)1, new object[1] { Energy });
			}
			PlayRechargeSound();
		}

		public void DecreaseEnergy(float amount)
		{
			Energy -= amount;
			if (SemiFunc.IsMasterClient())
			{
				((MonoBehaviourPun)this).photonView.RPC("SyncEnergyRPC", (RpcTarget)1, new object[1] { Energy });
			}
		}

		[PunRPC]
		protected void SyncEnergyRPC(float energy)
		{
			Energy = energy;
			PlayRechargeSound();
		}

		private void PlayRechargeSound()
		{
			if (Time.time - lastRechargeSoundTime > rechargeSoundDelay)
			{
				controller.audioHandler.PlayRechargeSound();
				lastRechargeSoundTime = Time.time;
			}
		}
	}
	public enum AnchorMode
	{
		Always,
		ExtractionPointsCompleted,
		Never
	}
	internal class AnchorHandler : MonoBehaviour
	{
		private DeathHeadController controller;

		public Vector3 tetherOffset = new Vector3(0f, 0.2f, 0f);

		public float anchorReboundForce = 0.05f;

		public float lightThreshold = 0.95f;

		public float minGroundedTime = 0.5f;

		public float breakSpeed = 2f;

		public float unAnchorDelay = 0.4f;

		public Vector4 cameraShake = new Vector4(1f, 3f, 5f, 0.4f);

		public Vector4 cameraImpact = new Vector4(2f, 3f, 8f, 0.1f);

		public Vector3 cartAnchorPointOffset = new Vector3(0.5f, -0.2f, 0.2f);

		public Vector3 smallCartAnchorPointOffset = new Vector3(0.4f, -0.2f, 0.1f);

		public Vector3 phasePointOffset = new Vector3(0f, 0.6f, 0f);

		public float shakeMagnitude = 0.3f;

		public float shakeDuration = 0.4f;

		public float shakeInterval = 0.05f;

		internal bool isAnchored;

		internal float? timeSinceAnchorCartGrabbed;

		private Vector3 anchorOrigin = Vector3.zero;

		private float distanceFromAnchor;

		private float unAnchorTimer;

		private float anchoredFor;

		private Tether? anchorTether;

		private bool isBreaking;

		private Vector3 breakPoint = Vector3.zero;

		private float breakingLerp;

		private bool hasAnchoredAfterExtracted;

		private float reAnchorCooldown;

		private PhysGrabCart? anchorCart;

		private bool isUnAnchoringSoundPlaying;

		private float phaseTimer;

		private int PowerLevel => DHHStatsManager.GetHeadPowerUpgrade(controller.deathHead.playerAvatar.steamID);

		public float anchorRadiusIncrease => 2f;

		public float AnchorRadius => DHHFunc.StatWithDiminishingReturns(8f, anchorRadiusIncrease, PowerLevel);

		public float PhaseRadius => AnchorRadius + 6f;

		private Vector3? CartAnchorPoint
		{
			get
			{
				//IL_002f: 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_0034: Unknown result type (might be due to invalid IL or missing references)
				PhysGrabCart? obj = anchorCart;
				if (obj == null)
				{
					return null;
				}
				return obj.cartGrabPoint.TransformPoint(anchorCart.isSmallCart ? smallCartAnchorPointOffset : cartAnchorPointOffset);
			}
		}

		private Vector3? CartCenterPhasePoint
		{
			get
			{
				//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)
				PhysGrabCart? obj = anchorCart;
				if (obj == null)
				{
					return null;
				}
				return ((Component)obj).transform.TransformPoint(phasePointOffset);
			}
		}

		protected void Awake()
		{
			controller = ((Component)this).GetComponent<DeathHeadController>();
		}

		protected void Start()
		{
			controller.reboundHandler.AddReboundForce(new ReboundHandler.Rebound(() => anchorOrigin - ((Component)this).transform.position, () => isAnchored && distanceFromAnchor > AnchorRadius, () => Mathf.Min(distanceFromAnchor / AnchorRadius * anchorReboundForce, controller.reboundHandler.defaultReboundForce), shouldNegateProductVelocity: false));
			controller.eyeHandler.eyeNegativeConditions.Add(delegate
			{
				float num = controller.anchorHandler.anchoredFor;
				return num > 0.1f && num < 1f;
			});
			controller.eyeHandler.eyeNegativeConditions.Add(isOutsideAnchorRange);
			controller.eyeHandler.eyeFlickerConditions.Add(isOutsideAnchorRange);
			bool isOutsideAnchorRange()
			{
				return controller.anchorHandler.distanceFromAnchor / controller.anchorHandler.AnchorRadius > controller.anchorHandler.lightThreshold;
			}
		}

		protected void Update()
		{
			//IL_001b: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			anchorOrigin = (Vector3)(((??)CartAnchorPoint) ?? anchorOrigin);
			UpdateAnchorState();
			UpdatePhasing();
			UpdateUnAnchoringSound();
			if (isAnchored)
			{
				distanceFromAnchor = Vector3.Distance(anchorOrigin, ((Component)this).transform.position);
				anchoredFor += Time.deltaTime;
			}
			else
			{
				distanceFromAnchor = 0f;
				anchoredFor = 0f;
			}
			UpdateTetherBreaking();
			if (isAnchored && !isBreaking)
			{
				RepositionTether();
			}
		}

		private void UpdateAnchorState()
		{
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			if (!RoundDirector.instance.allExtractionPointsCompleted)
			{
				hasAnchoredAfterExtracted = false;
			}
			timeSinceAnchorCartGrabbed = ((anchorCart == null) ? null : (((Component)anchorCart).gameObject.GetComponent<PhysGrabObject>().grabbed ? new float?(0f) : (timeSinceAnchorCartGrabbed + Time.deltaTime)));
			unAnchorTimer = (controller.impactDetector.physGrabObject.grabbed ? (unAnchorTimer + Time.deltaTime) : 0f);
			reAnchorCooldown = (controller.impactDetector.physGrabObject.grabbed ? (reAnchorCooldown - Time.deltaTime) : 0.5f);
			bool flag = DHHConfigManager.anchorMode.Value != AnchorMode.Never && (RoundDirector.instance.allExtractionPointsCompleted || (DHHConfigManager.anchorMode.Value == AnchorMode.Always && SemiFunc.RunIsLevel()));
			if (unAnchorTimer > unAnchorDelay || !controller.deathHead.triggered || !flag)
			{
				if (isAnchored)
				{
					DestroyAnchor();
				}
			}
			else
			{
				if (reAnchorCooldown <= 0f)
				{
					return;
				}
				if (controller.collisionHandler.isCollidingCart && controller.collisionHandler.collidingCart != null)
				{
					if (anchorCart != controller.collisionHandler.collidingCart)
					{
						AnchorToCart(controller.collisionHandler.collidingCart);
					}
					return;
				}
				bool flag2 = !hasAnchoredAfterExtracted && RoundDirector.instance.allExtractionPointsCompleted;
				if (!flag2 && (!controller.collisionHandler.isColliding || controller.collisionHandler.isCollidingCart))
				{
					return;
				}
				Vector3? groundPointDown = controller.collisionHandler.GetGroundPointDown();
				if (groundPointDown.HasValue)
				{
					if (flag2)
					{
						hasAnchoredAfterExtracted = true;
					}
					if (!isAnchored)
					{
						CreateAnchor(groundPointDown.Value);
					}
				}
			}
		}

		private void UpdatePhasing()
		{
			//IL_00bf: 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_00b1: 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)
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				bool flag = isAnchored && distanceFromAnchor > PhaseRadius && anchorCart != null && !controller.phaseHandler.phasing && phaseTimer <= 0f;
				phaseTimer = ((flag || controller.phaseHandler.phasing) ? 0.5f : (phaseTimer - Time.deltaTime));
				if (flag || controller.phaseHandler.phasing)
				{
					controller.phaseHandler.PhaseToPoint((Vector3)(((??)CartCenterPhasePoint) ?? (anchorOrigin + phasePointOffset)));
				}
			}
		}

		private void UpdateUnAnchoringSound()
		{
			if (isAnchored && controller.impactDetector.physGrabObject.grabbed)
			{
				if (!isUnAnchoringSoundPlaying)
				{
					isUnAnchoringSoundPlaying = true;
					controller.audioHandler.PlayUnAnchoringSound();
				}
			}
			else if (isUnAnchoringSoundPlaying)
			{
				isUnAnchoringSoundPlaying = false;
				controller.audioHandler.StopUnAnchoringSound();
			}
		}

		private void UpdateTetherBreaking()
		{
			//IL_0030: 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_0041: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if (isBreaking && anchorTether != null)
			{
				breakingLerp += Time.deltaTime * breakSpeed;
				anchorTether.origin = anchorOrigin;
				anchorTether.point = Vector3.Lerp(breakPoint, anchorOrigin, breakingLerp);
				if (breakingLerp >= 1f)
				{
					((Component)anchorTether).gameObject.SetActive(false);
					isBreaking = false;
				}
			}
		}

		private void RepositionTether()
		{
			//IL_0022: 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_0033: 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_003d: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			if (anchorTether != null && ((Component)anchorTether).gameObject.activeInHierarchy)
			{
				anchorTether.origin = anchorOrigin;
				Vector3 point = ((Component)this).transform.TransformPoint(tetherOffset);
				anchorTether.point = point;
				anchorTether.colorInterpolation = Mathf.Max(0f, (Mathf.Clamp01(distanceFromAnchor / AnchorRadius) - lightThreshold) * (1f / (1f - lightThreshold)));
			}
		}

		private void EnableTether(Vector3? position)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_005c: 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_0061: Unknown result type (might be due to invalid IL or missing references)