Decompiled source of DeathHeadHopperFix v0.1.6

DeathHeadHopperFix.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.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.DeathHead.Handlers;
using DeathHeadHopperFix.Modules.Battery;
using DeathHeadHopperFix.Modules.Config;
using DeathHeadHopperFix.Modules.Gameplay;
using DeathHeadHopperFix.Modules.Patches;
using DeathHeadHopperFix.Modules.Utilities;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.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 DeathHeadHopperFix
{
	[HarmonyPatch(typeof(SpectateCamera), "StateNormal")]
	internal static class SpectateCameraStateNormalPatchMarker
	{
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return SpectateCameraStateNormalPatch.Transpiler(instructions);
		}
	}
	[BepInPlugin("AdrenSnyder.DeathHeadHopperFix", "Death Head Hopper - Fix", "0.1.6")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private readonly struct DiminishingReturnsResult
		{
			public float BaseValue { get; }

			public float IncreasePerLevel { get; }

			public int AppliedLevel { get; }

			public int ThresholdLevel { get; }

			public float DiminishingFactor { get; }

			public int LinearLevels { get; }

			public int ExtraLevels { get; }

			public float LinearContribution { get; }

			public float DiminishingContribution { get; }

			public float DiminishingComponent { get; }

			public float FinalValue { get; }

			public DiminishingReturnsResult(float baseValue, float increasePerLevel, int appliedLevel, int thresholdLevel, float diminishingFactor, int linearLevels, int extraLevels, float linearContribution, float diminishingContribution, float diminishingComponent, float finalValue)
			{
				BaseValue = baseValue;
				IncreasePerLevel = increasePerLevel;
				AppliedLevel = appliedLevel;
				ThresholdLevel = thresholdLevel;
				DiminishingFactor = diminishingFactor;
				LinearLevels = linearLevels;
				ExtraLevels = extraLevels;
				LinearContribution = linearContribution;
				DiminishingContribution = diminishingContribution;
				DiminishingComponent = diminishingComponent;
				FinalValue = finalValue;
			}
		}

		private const string TargetAssemblyName = "DeathHeadHopper";

		private const string HopForceLogKey = "Fix:Hop.JumpForce";

		private const string JumpForceLogKey = "Fix:Jump.HeadJumpForce";

		private const string ChargeStrengthLogKey = "Fix:Charge.Strength";

		private Harmony? _harmony;

		private bool _patched;

		private static ManualLogSource? _log;

		private static bool _guardMissingLocalCameraPosition;

		private static FieldInfo? _jumpHandlerJumpBufferField;

		private static FieldInfo? s_playerAvatarDeadSetField = AccessTools.Field(typeof(PlayerAvatar), "deadSet");

		private static FieldInfo? s_abilityEnergyHandlerControllerField;

		private static FieldInfo? s_deathHeadControllerDeathHeadField;

		private static FieldInfo? s_playerDeathHeadAvatarField;

		private static FieldInfo? s_playerAvatarIsDisabledField = AccessTools.Field(typeof(PlayerAvatar), "isDisabled");

		private static MethodInfo? s_hopHandlerPowerLevelGetter;

		private static MethodInfo? s_jumpHandlerPowerLevelGetter;

		private static FieldInfo? s_chargeHandlerChargeStrengthField;

		private static MethodInfo? s_chargeHandlerAbilityLevelGetter;

		private static FieldInfo? s_chargeHandlerImpactDetectorField;

		private static FieldInfo? s_impactDetectorPhysGrabObjectField;

		private static FieldInfo? s_cachedPhysGrabObjectGrabbedField;

		private void Awake()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			_log = ((BaseUnityPlugin)this).Logger;
			ConfigManager.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			_harmony = new Harmony("AdrenSnyder.DeathHeadHopperFix");
			PatchSpectateCameraStateNormal();
			_harmony.PatchAll(typeof(Plugin).Assembly);
			DetectGameApiChanges();
			ApplyEarlyPatches();
			AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly asm in assemblies)
			{
				TryPatchIfTargetAssembly(asm);
			}
		}

		private void OnDestroy()
		{
			AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad;
		}

		private void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args)
		{
			TryPatchIfTargetAssembly(args.LoadedAssembly);
		}

		private void ApplyEarlyPatches()
		{
			if (_harmony != null)
			{
				StatsModule.ApplyHooks(_harmony);
				ItemUpgradeModule.Apply(_harmony);
			}
		}

		private void PatchSpectateCameraStateNormal()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(SpectateCamera), "StateNormal", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					return;
				}
				MethodInfo method = typeof(SpectateCameraStateNormalPatch).GetMethod("Transpiler", BindingFlags.Static | BindingFlags.NonPublic);
				if (!(method == null))
				{
					Harmony? harmony = _harmony;
					if (harmony != null)
					{
						harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogError((object)ex);
				}
			}
		}

		private void TryPatchIfTargetAssembly(Assembly asm)
		{
			if (_patched || asm == null)
			{
				return;
			}
			string name = asm.GetName().Name;
			if (!string.Equals(name, "DeathHeadHopper", StringComparison.OrdinalIgnoreCase))
			{
				return;
			}
			try
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogInfo((object)"Detected DeathHeadHopper assembly load. Applying patches...");
				}
				Harmony harmony = _harmony;
				if (harmony == null)
				{
					throw new InvalidOperationException("Harmony instance is null.");
				}
				PrefabModule.Apply(harmony, asm, _log);
				AudioModule.Apply(harmony, asm, _log);
				DHHShopModule.Apply(harmony, asm, _log);
				PatchDeathHeadControllerGuardsIfPossible(harmony, asm);
				PatchDeathHeadControllerModulesIfPossible(harmony, asm);
				PatchJumpHandlerUpdateIfPossible(harmony, asm);
				PatchChargeHandlerDamageModeIfPossible(harmony, asm);
				PatchJumpHandlerJumpForceIfPossible(harmony, asm);
				PatchHopHandlerJumpForceIfPossible(harmony, asm);
				InputModule.Apply(harmony, asm, _log);
				PatchAbilityEnergyHandlerRechargeSoundIfPossible(harmony, asm);
				AbilityModule.ApplyAbilitySpotLabelOverlay(harmony, asm);
				if (!FeatureFlags.DisableAbilityPatches)
				{
					AbilityModule.ApplyAbilityManagerHooks(harmony, asm);
					PatchChargeAbilityGettersIfPossible(harmony, asm);
				}
				_patched = true;
				ManualLogSource? log2 = _log;
				if (log2 != null)
				{
					log2.LogInfo((object)"Patches applied successfully.");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? log3 = _log;
				if (log3 != null)
				{
					log3.LogError((object)ex);
				}
			}
		}

		private static void PatchAbilityEnergyHandlerRechargeSoundIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Expected O, but got Unknown
			Type type = asm.GetType("DeathHeadHopper.DeathHead.Handlers.AbilityEnergyHandler", throwOnError: false);
			if (type == null)
			{
				return;
			}
			if ((object)s_abilityEnergyHandlerControllerField == null)
			{
				s_abilityEnergyHandlerControllerField = type.GetField("controller", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			Type type2 = asm.GetType("DeathHeadHopper.DeathHead.DeathHeadController", throwOnError: false);
			if (type2 != null && (object)s_deathHeadControllerDeathHeadField == null)
			{
				s_deathHeadControllerDeathHeadField = type2.GetField("deathHead", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			Type type3 = asm.GetType("PlayerDeathHead", throwOnError: false);
			if (type3 != null && (object)s_playerDeathHeadAvatarField == null)
			{
				s_playerDeathHeadAvatarField = type3.GetField("playerAvatar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			MethodInfo methodInfo = AccessTools.Method(type, "PlayRechargeSound", Type.EmptyTypes, (Type[])null);
			if (!(methodInfo == null))
			{
				MethodInfo method = typeof(Plugin).GetMethod("AbilityEnergyHandler_PlayRechargeSound_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (!(method == null))
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static bool AbilityEnergyHandler_PlayRechargeSound_Prefix(object __instance)
		{
			if (SemiFunc.IsSpectating() || IsLocalPlayerDead())
			{
				return false;
			}
			PlayerAvatar abilityEnergyHandlerPlayerAvatar = GetAbilityEnergyHandlerPlayerAvatar(__instance);
			if (IsAbilityPlayerDisabled(abilityEnergyHandlerPlayerAvatar))
			{
				return false;
			}
			return true;
		}

		private static PlayerAvatar? GetAbilityEnergyHandlerPlayerAvatar(object? handler)
		{
			if (handler == null || s_abilityEnergyHandlerControllerField == null)
			{
				return null;
			}
			object value = s_abilityEnergyHandlerControllerField.GetValue(handler);
			if (value == null || s_deathHeadControllerDeathHeadField == null)
			{
				return null;
			}
			object value2 = s_deathHeadControllerDeathHeadField.GetValue(value);
			if (value2 == null || s_playerDeathHeadAvatarField == null)
			{
				return null;
			}
			object? value3 = s_playerDeathHeadAvatarField.GetValue(value2);
			return (PlayerAvatar?)((value3 is PlayerAvatar) ? value3 : null);
		}

		private static bool IsAbilityPlayerDisabled(PlayerAvatar? avatar)
		{
			if ((Object)(object)avatar == (Object)null || s_playerAvatarIsDisabledField == null)
			{
				return false;
			}
			object value = s_playerAvatarIsDisabledField.GetValue(avatar);
			bool flag = default(bool);
			int num;
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		private static bool IsLocalPlayerDead()
		{
			PlayerAvatar instance = PlayerAvatar.instance;
			if ((Object)(object)instance == (Object)null || s_playerAvatarDeadSetField == null)
			{
				return false;
			}
			object value = s_playerAvatarDeadSetField.GetValue(instance);
			bool flag = default(bool);
			int num;
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		private static void PatchChargeAbilityGettersIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			Type type = asm.GetType("DeathHeadHopper.Abilities.Charge.ChargeAbility", throwOnError: false);
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.PropertyGetter(type, "EnergyCost");
			MethodInfo methodInfo2 = AccessTools.PropertyGetter(type, "Cooldown");
			if (methodInfo == null)
			{
				return;
			}
			MethodInfo method = typeof(Plugin).GetMethod("ChargeAbility_EnergyCost_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
			MethodInfo method2 = typeof(Plugin).GetMethod("ChargeAbility_Cooldown_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
			if (!(method == null) && !(method2 == null))
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				if (methodInfo2 != null)
				{
					harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void ChargeAbility_EnergyCost_Postfix(Object __instance, ref float __result)
		{
			if (__instance == (Object)null)
			{
				return;
			}
			float num = Mathf.Max(0f, __result);
			float num2 = Mathf.Max(0f, (float)FeatureFlags.ChargeAbilityStaminaCost);
			if (num2 <= 0f)
			{
				__result = num;
				return;
			}
			__result = num2;
			if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("DHHCharge.Cost"))
			{
				Debug.Log((object)$"[Fix:DHHCharge] Charge cost override: custom={num2:F3} base={num:F3}");
			}
		}

		private static bool ChargeAbility_Cooldown_Prefix(Object __instance, ref float __result)
		{
			if (__instance == (Object)null)
			{
				return true;
			}
			float num = (__result = Mathf.Max(0f, (float)FeatureFlags.ChargeAbilityCooldown));
			if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("DHHCharge.Cooldown"))
			{
				Debug.Log((object)$"[Fix:DHHCharge] Cooldown override: custom={num:F3}");
			}
			return false;
		}

		private static void DetectGameApiChanges()
		{
			try
			{
				Type type = AccessTools.TypeByName("PlayerAvatar");
				if (type == null)
				{
					_guardMissingLocalCameraPosition = true;
					return;
				}
				FieldInfo field = type.GetField("localCameraPosition", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_guardMissingLocalCameraPosition = field == null;
			}
			catch
			{
				_guardMissingLocalCameraPosition = true;
			}
		}

		private static void PatchDeathHeadControllerGuardsIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			if (!_guardMissingLocalCameraPosition)
			{
				return;
			}
			Type type = asm.GetType("DeathHeadHopper.DeathHead.DeathHeadController", throwOnError: false);
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "CancelReviveInCart", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				MethodInfo method = typeof(Plugin).GetMethod("DeathHeadController_CancelReviveInCart_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (method != null)
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			MethodInfo methodInfo2 = AccessTools.Method(type, "Update", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				MethodInfo method2 = typeof(Plugin).GetMethod("DeathHeadController_Update_Finalizer", BindingFlags.Static | BindingFlags.NonPublic);
				if (method2 != null)
				{
					harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null);
				}
			}
		}

		private static bool DeathHeadController_CancelReviveInCart_Prefix()
		{
			if (_guardMissingLocalCameraPosition)
			{
				return false;
			}
			return true;
		}

		private static Exception? DeathHeadController_Update_Finalizer(Exception? __exception)
		{
			if (__exception == null)
			{
				return null;
			}
			if (_guardMissingLocalCameraPosition && __exception is MissingFieldException)
			{
				return null;
			}
			return __exception;
		}

		private static void PatchDeathHeadControllerModulesIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			Type type = asm.GetType("DeathHeadHopper.DeathHead.DeathHeadController", throwOnError: false);
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "Start", (Type[])null, (Type[])null);
			if (!(methodInfo == null))
			{
				MethodInfo method = typeof(Plugin).GetMethod("DeathHeadController_Start_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
				if (!(method == null))
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void DeathHeadController_Start_Postfix(object __instance)
		{
			MonoBehaviour val = (MonoBehaviour)((__instance is MonoBehaviour) ? __instance : null);
			if (val != null)
			{
				GameObject gameObject = ((Component)val).gameObject;
				if (FeatureFlags.BatteryJumpEnabled && !FeatureFlags.DisableBatteryModule && (Object)(object)gameObject.GetComponent<BatteryModule>() == (Object)null)
				{
					gameObject.AddComponent<BatteryModule>();
				}
			}
		}

		private static void PatchJumpHandlerUpdateIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			Type type = asm.GetType("DeathHeadHopper.DeathHead.Handlers.JumpHandler", throwOnError: false);
			if (type == null)
			{
				return;
			}
			_jumpHandlerJumpBufferField = AccessTools.Field(type, "jumpBufferTimer");
			if (_jumpHandlerJumpBufferField == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "Update", (Type[])null, (Type[])null);
			if (!(methodInfo == null))
			{
				MethodInfo method = typeof(Plugin).GetMethod("JumpHandler_Update_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (!(method == null))
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void JumpHandler_Update_Prefix(MonoBehaviour __instance)
		{
			if (!FeatureFlags.BatteryJumpEnabled || (Object)(object)__instance == (Object)null || _jumpHandlerJumpBufferField == null)
			{
				return;
			}
			object value = _jumpHandlerJumpBufferField.GetValue(__instance);
			if (!(value is float))
			{
				return;
			}
			float num = (float)value;
			if (num <= 0f)
			{
				return;
			}
			BatteryModule component = ((Component)__instance).gameObject.GetComponent<BatteryModule>();
			if (!((Object)(object)component == (Object)null))
			{
				(bool, bool?, float, float) tuple = DHHBatteryHelper.EvaluateJumpAllowance();
				if (!tuple.Item1)
				{
					_jumpHandlerJumpBufferField.SetValue(__instance, 0f);
					component.NotifyJumpBlocked(tuple.Item4, tuple.Item3, tuple.Item2);
				}
			}
		}

		private static void PatchChargeHandlerDamageModeIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected O, but got Unknown
			Type type = asm.GetType("DeathHeadHopper.DeathHead.Handlers.ChargeHandler", throwOnError: false);
			if (!(type == null))
			{
				MethodInfo methodInfo = AccessTools.Method(type, "ChargeWindup", new Type[1] { typeof(Vector3) }, (Type[])null);
				MethodInfo method = typeof(Plugin).GetMethod("ChargeHandler_ChargeWindup_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (methodInfo != null && method != null)
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo2 = AccessTools.Method(type, "ResetState", Type.EmptyTypes, (Type[])null);
				if (s_chargeHandlerChargeStrengthField == null)
				{
					s_chargeHandlerChargeStrengthField = AccessTools.Field(type, "chargeStrength");
				}
				if (s_chargeHandlerAbilityLevelGetter == null)
				{
					s_chargeHandlerAbilityLevelGetter = AccessTools.PropertyGetter(type, "AbilityLevel");
				}
				MethodInfo method2 = typeof(Plugin).GetMethod("ChargeHandler_ResetState_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
				if (methodInfo2 != null && method2 != null)
				{
					harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void PatchJumpHandlerJumpForceIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			Type type = asm.GetType("DeathHeadHopper.DeathHead.Handlers.JumpHandler", throwOnError: false);
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.PropertyGetter(type, "JumpForce");
			if (!(methodInfo == null))
			{
				if (s_jumpHandlerPowerLevelGetter == null)
				{
					s_jumpHandlerPowerLevelGetter = AccessTools.PropertyGetter(type, "PowerLevel");
				}
				MethodInfo method = typeof(Plugin).GetMethod("JumpHandler_JumpForce_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (!(method == null))
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static bool JumpHandler_JumpForce_Prefix(object __instance, ref float __result)
		{
			if (__instance == null || s_jumpHandlerPowerLevelGetter == null)
			{
				return true;
			}
			int num2 = ((s_jumpHandlerPowerLevelGetter.Invoke(__instance, null) is int num) ? num : 0);
			int num3 = num2 + 1;
			DiminishingReturnsResult stat = EvaluateStatWithDiminishingReturns(FeatureFlags.DHHJumpForceBaseValue, FeatureFlags.DHHJumpForceIncreasePerLevel, num3, FeatureFlags.DHHJumpForceThresholdLevel, FeatureFlags.DHHJumpForceDiminishingFactor);
			__result = stat.FinalValue;
			LogJumpForce(__instance, num2, num3, stat);
			return false;
		}

		private static bool ChargeHandler_ChargeWindup_Prefix(object __instance)
		{
			if (__instance == null)
			{
				return true;
			}
			if (IsChargeHandlerHeadGrabbed(__instance))
			{
				if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:Charge.Grabbed", 30))
				{
					Debug.Log((object)"[Fix:Charge] Charge windup blocked because the head is grabbed.");
				}
				return false;
			}
			return true;
		}

		private static bool IsChargeHandlerHeadGrabbed(object chargeHandler)
		{
			object chargeImpactDetector = GetChargeImpactDetector(chargeHandler);
			if (chargeImpactDetector == null)
			{
				return false;
			}
			object impactPhysGrabObject = GetImpactPhysGrabObject(chargeImpactDetector);
			if (impactPhysGrabObject == null)
			{
				return false;
			}
			FieldInfo fieldInfo = s_cachedPhysGrabObjectGrabbedField;
			if (fieldInfo == null || fieldInfo.DeclaringType != impactPhysGrabObject.GetType())
			{
				fieldInfo = (s_cachedPhysGrabObjectGrabbedField = AccessTools.Field(impactPhysGrabObject.GetType(), "grabbed"));
			}
			bool flag = default(bool);
			int num;
			if (fieldInfo != null)
			{
				object value = fieldInfo.GetValue(impactPhysGrabObject);
				if (value is bool)
				{
					flag = (bool)value;
					num = 1;
				}
				else
				{
					num = 0;
				}
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		private static object? GetChargeImpactDetector(object chargeHandler)
		{
			FieldInfo fieldInfo = s_chargeHandlerImpactDetectorField;
			if (fieldInfo == null || fieldInfo.DeclaringType != chargeHandler.GetType())
			{
				fieldInfo = (s_chargeHandlerImpactDetectorField = AccessTools.Field(chargeHandler.GetType(), "impactDetector"));
			}
			return fieldInfo?.GetValue(chargeHandler);
		}

		private static object? GetImpactPhysGrabObject(object impactDetector)
		{
			if (impactDetector == null)
			{
				return null;
			}
			FieldInfo fieldInfo = s_impactDetectorPhysGrabObjectField;
			if (fieldInfo == null || fieldInfo.DeclaringType != impactDetector.GetType())
			{
				fieldInfo = (s_impactDetectorPhysGrabObjectField = AccessTools.Field(impactDetector.GetType(), "physGrabObject"));
			}
			return fieldInfo?.GetValue(impactDetector);
		}

		private static void ChargeHandler_ResetState_Postfix(object __instance)
		{
			if (__instance != null && !(s_chargeHandlerChargeStrengthField == null) && !(s_chargeHandlerAbilityLevelGetter == null))
			{
				int currentLevel = ((s_chargeHandlerAbilityLevelGetter.Invoke(__instance, null) is int num) ? num : 0);
				DiminishingReturnsResult stat = EvaluateStatWithDiminishingReturns(FeatureFlags.DHHChargeStrengthBaseValue, FeatureFlags.DHHChargeStrengthIncreasePerLevel, currentLevel, FeatureFlags.DHHChargeStrengthThresholdLevel, FeatureFlags.DHHChargeStrengthDiminishingFactor);
				s_chargeHandlerChargeStrengthField.SetValue(__instance, stat.FinalValue);
				LogChargeStrength(__instance, stat);
			}
		}

		private static void PatchHopHandlerJumpForceIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			Type type = asm.GetType("DeathHeadHopper.DeathHead.Handlers.HopHandler", throwOnError: false);
			if (!(type == null))
			{
				MethodInfo methodInfo = AccessTools.PropertyGetter(type, "JumpForce");
				if (s_hopHandlerPowerLevelGetter == null)
				{
					s_hopHandlerPowerLevelGetter = AccessTools.PropertyGetter(type, "PowerLevel");
				}
				MethodInfo method = typeof(Plugin).GetMethod("HopHandler_JumpForce_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (methodInfo != null && method != null)
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static bool HopHandler_JumpForce_Prefix(object __instance, ref float __result)
		{
			if (__instance == null || s_hopHandlerPowerLevelGetter == null)
			{
				return true;
			}
			int num2 = ((s_hopHandlerPowerLevelGetter.Invoke(__instance, null) is int num) ? num : 0);
			int num3 = num2 + 1;
			DiminishingReturnsResult stat = EvaluateStatWithDiminishingReturns(FeatureFlags.DHHHopJumpBaseValue, FeatureFlags.DHHHopJumpIncreasePerLevel, num3, FeatureFlags.DHHHopJumpThresholdLevel, FeatureFlags.DHHHopJumpDiminishingFactor);
			__result = stat.FinalValue;
			LogHopJumpForce(__instance, num2, num3, stat);
			return false;
		}

		private static float StatWithDiminishingReturns(float baseValue, float increasePerLevel, int currentLevel, int thresholdLevel, float diminishingFactor)
		{
			return EvaluateStatWithDiminishingReturns(baseValue, increasePerLevel, currentLevel, thresholdLevel, diminishingFactor).FinalValue;
		}

		private static DiminishingReturnsResult EvaluateStatWithDiminishingReturns(float baseValue, float increasePerLevel, int currentLevel, int thresholdLevel, float diminishingFactor)
		{
			int num = Math.Max(0, currentLevel - 1);
			int num2 = Math.Max(0, thresholdLevel - 1);
			int num3 = Mathf.Min(num, num2);
			int num4 = Mathf.Max(0, num - num2);
			float num5 = (float)num4 * Mathf.Pow(diminishingFactor, (float)num4);
			float num6 = increasePerLevel * (float)num3;
			float num7 = increasePerLevel * num5;
			float finalValue = baseValue + num6 + num7;
			return new DiminishingReturnsResult(baseValue, increasePerLevel, currentLevel, thresholdLevel, diminishingFactor, num3, num4, num6, num7, num5, finalValue);
		}

		private static void LogHopJumpForce(object hopHandler, int powerLevel, int appliedLevel, DiminishingReturnsResult stat)
		{
			if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:Hop.JumpForce", 30))
			{
				string handlerLabel = GetHandlerLabel(hopHandler, "HopHandler");
				string text = $"[Fix:Hop] {handlerLabel} JumpForce={stat.FinalValue:F3} powerLevel={powerLevel} appliedLevel={appliedLevel} base={stat.BaseValue:F3} inc={stat.IncreasePerLevel:F3} fullUpgrades={stat.LinearLevels} dimUpgrades={stat.ExtraLevels} linearDelta={stat.LinearContribution:F3} dimDelta={stat.DiminishingContribution:F3} thresh={stat.ThresholdLevel} dimFactor={stat.DiminishingFactor:F3}";
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogInfo((object)text);
				}
				Debug.Log((object)text);
			}
		}

		private static void LogJumpForce(object jumpHandler, int powerLevel, int appliedLevel, DiminishingReturnsResult stat)
		{
			if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:Jump.HeadJumpForce", 30))
			{
				string handlerLabel = GetHandlerLabel(jumpHandler, "JumpHandler");
				string text = $"[Fix:Jump] {handlerLabel} JumpForce={stat.FinalValue:F3} powerLevel={powerLevel} appliedLevel={appliedLevel} base={stat.BaseValue:F3} inc={stat.IncreasePerLevel:F3} fullUpgrades={stat.LinearLevels} dimUpgrades={stat.ExtraLevels} linearDelta={stat.LinearContribution:F3} dimDelta={stat.DiminishingContribution:F3} thresh={stat.ThresholdLevel} dimFactor={stat.DiminishingFactor:F3}";
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogInfo((object)text);
				}
				Debug.Log((object)text);
			}
		}

		private static string GetHandlerLabel(object? handler, string fallback)
		{
			Component val = (Component)((handler is Component) ? handler : null);
			if (val != null)
			{
				return ((Object)val).name ?? ((object)val).GetType().Name;
			}
			return handler?.GetType().Name ?? fallback;
		}

		private static void LogChargeStrength(object chargeHandler, DiminishingReturnsResult stat)
		{
			if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:Charge.Strength", 60))
			{
				string handlerLabel = GetHandlerLabel(chargeHandler, "ChargeHandler");
				string text = $"[Fix:Charge] {handlerLabel} Strength={stat.FinalValue:F3} base={stat.BaseValue:F3} inc={stat.IncreasePerLevel:F3} level={stat.AppliedLevel} fullUpgrades={stat.LinearLevels} dimUpgrades={stat.ExtraLevels} linearDelta={stat.LinearContribution:F3} dimDelta={stat.DiminishingContribution:F3} thresh={stat.ThresholdLevel} dimFactor={stat.DiminishingFactor:F3}";
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogInfo((object)text);
				}
				Debug.Log((object)text);
			}
		}

		private static void TryImpactEffect(object impactDetector, Vector3 contactPoint)
		{
			//IL_0072: 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)
			if (impactDetector == null)
			{
				return;
			}
			try
			{
				if (!SemiFunc.IsMultiplayer())
				{
					MethodInfo methodInfo = AccessTools.Method(impactDetector.GetType(), "ImpactEffectRPC", (Type[])null, (Type[])null);
					if (methodInfo != null)
					{
						ParameterInfo[] parameters = methodInfo.GetParameters();
						if (parameters.Length == 2)
						{
							object obj = Activator.CreateInstance(parameters[1].ParameterType);
							methodInfo.Invoke(impactDetector, new object[2] { contactPoint, obj });
							return;
						}
					}
				}
				object? obj2 = AccessTools.Field(impactDetector.GetType(), "photonView")?.GetValue(impactDetector);
				PhotonView val = (PhotonView)((obj2 is PhotonView) ? obj2 : null);
				if (val != null)
				{
					val.RPC("ImpactEffectRPC", (RpcTarget)0, new object[1] { contactPoint });
				}
			}
			catch
			{
			}
		}

		private static Vector3 CalculateEnemyBounceNormal(Transform? self, Vector3 enemyCenterPoint)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_002b: 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_0031: 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_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_0041: 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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)self == (Object)null)
			{
				return Vector3.up;
			}
			Vector3 val = self.TransformPoint(Vector3.up * 0.3f);
			Vector3 val2 = val - enemyCenterPoint;
			Vector3 val3 = Vector3.ProjectOnPlane(val2, Vector3.up);
			return ((Vector3)(ref val3)).normalized;
		}
	}
}
namespace DeathHeadHopperFix.Modules.Utilities
{
	internal static class ItemHelpers
	{
		internal static string? GetItemAssetName(Object? itemAsset)
		{
			if (itemAsset == (Object)null)
			{
				return null;
			}
			Type type = ((object)itemAsset).GetType();
			PropertyInfo property = type.GetProperty("itemAssetName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.PropertyType == typeof(string))
			{
				return ((string)property.GetValue(itemAsset, null)) ?? itemAsset.name;
			}
			FieldInfo field = type.GetField("itemAssetName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null && field.FieldType == typeof(string))
			{
				return ((string)field.GetValue(itemAsset)) ?? itemAsset.name;
			}
			return itemAsset.name;
		}
	}
	internal static class LogLimiter
	{
		public const int DefaultFrameInterval = 120;

		private static readonly Dictionary<string, int> _lastFrameByKey = new Dictionary<string, int>(StringComparer.Ordinal);

		public static bool ShouldLog(string key, int frameInterval = 120)
		{
			if (string.IsNullOrEmpty(key))
			{
				return true;
			}
			if (frameInterval <= 0)
			{
				return true;
			}
			int frameCount = Time.frameCount;
			if (_lastFrameByKey.TryGetValue(key, out var value) && frameCount - value < frameInterval)
			{
				return false;
			}
			_lastFrameByKey[key] = frameCount;
			return true;
		}

		public static void Reset(string key)
		{
			if (!string.IsNullOrEmpty(key))
			{
				_lastFrameByKey.Remove(key);
			}
		}

		public static void Clear()
		{
			_lastFrameByKey.Clear();
		}
	}
	internal static class ReflectionHelper
	{
		internal static object? GetStaticInstanceByName(string typeName)
		{
			Type type = AccessTools.TypeByName(typeName);
			if (type == null)
			{
				return null;
			}
			return GetStaticInstanceValue(type, "instance");
		}

		internal static object? GetStaticInstanceValue(Type type, string name)
		{
			FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				return field.GetValue(null);
			}
			PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null)
			{
				return property.GetValue(null, null);
			}
			return null;
		}
	}
}
namespace DeathHeadHopperFix.Modules.Patches
{
	[HarmonyPatch(typeof(PlayerDeathHead), "Update")]
	internal static class PlayerDeathHeadUpdatePatch
	{
		private static readonly FieldInfo s_triggeredField = AccessTools.Field(typeof(PlayerDeathHead), "triggered");

		private static readonly FieldInfo s_spectatePlayerField = AccessTools.Field(typeof(SpectateCamera), "player");

		private static float _jumpTimer = 1f;

		[HarmonyPrefix]
		private static void Prefix(PlayerDeathHead __instance, PhysGrabObject ___physGrabObject)
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || (Object)(object)___physGrabObject == (Object)null)
			{
				return;
			}
			PlayerAvatar playerAvatar = __instance.playerAvatar;
			if ((Object)(object)playerAvatar == (Object)null || (Object)(object)playerAvatar.photonView == (Object)null || !playerAvatar.photonView.IsMine || s_triggeredField == null)
			{
				return;
			}
			object value = s_triggeredField.GetValue(__instance);
			if (!(value is bool) || !(bool)value)
			{
				return;
			}
			((Component)playerAvatar).transform.position = ((Component)___physGrabObject).transform.position;
			if ((SemiFunc.InputMovementX() != 0f || SemiFunc.InputMovementY() != 0f) && s_spectatePlayerField != null && (Object)(object)SpectateCamera.instance != (Object)null)
			{
				s_spectatePlayerField.SetValue(SpectateCamera.instance, playerAvatar);
			}
			if (_jumpTimer > 0f)
			{
				_jumpTimer -= Time.deltaTime;
			}
			else
			{
				if (!SemiFunc.InputHold((InputKey)1))
				{
					return;
				}
				_jumpTimer = 1f;
				Camera main = Camera.main;
				if ((Object)(object)main == (Object)null)
				{
					return;
				}
				Vector3 val = Vector3.ProjectOnPlane(((Component)main).transform.forward, Vector3.up);
				Vector3 normalized = ((Vector3)(ref val)).normalized;
				Vector3 val2 = Vector3.Cross(Vector3.up, normalized);
				Vector3 val3 = Vector3.zero;
				float num = SemiFunc.InputMovementX();
				float num2 = SemiFunc.InputMovementY();
				if (num2 > 0f)
				{
					val3 += normalized;
				}
				if (num2 < 0f)
				{
					val3 -= normalized;
				}
				if (num < 0f)
				{
					val3 -= val2;
				}
				if (num > 0f)
				{
					val3 += val2;
				}
				val3 += Vector3.up;
				val3 = ((Vector3)(ref val3)).normalized * 4.8f;
				if (DHHBatteryHelper.EvaluateJumpAllowance().allowed)
				{
					PhysGrabber physGrabber = playerAvatar.physGrabber;
					if (!((Object)(object)physGrabber == (Object)null) && !((Object)(object)playerAvatar.photonView == (Object)null))
					{
						___physGrabObject.GrabLink(playerAvatar.photonView.ViewID, 0, physGrabber.physGrabPointPullerPosition - val3, Vector3.zero, Vector3.zero);
						___physGrabObject.GrabStarted(physGrabber);
						___physGrabObject.GrabEnded(physGrabber);
					}
				}
			}
		}
	}
	internal static class SpectateCameraStateNormalPatch
	{
		private static readonly MethodInfo s_inputDown = AccessTools.Method(typeof(SemiFunc), "InputDown", (Type[])null, (Type[])null);

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

		internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			int num = list.FindIndex((CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_inputDown)) - 1;
			if (num <= 0 || list[num].opcode != OpCodes.Ldc_I4_1)
			{
				return instructions;
			}
			int num2 = list.FindIndex(num, (CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_playerSwitch));
			if (num2 == -1)
			{
				return instructions;
			}
			list[num].opcode = OpCodes.Nop;
			list.RemoveRange(num + 1, num2 - num);
			return list.AsEnumerable();
		}
	}
	[HarmonyPatch(typeof(StunHandler), "HandleStun")]
	internal static class StunHandlerReleasePatch
	{
		[CompilerGenerated]
		private sealed class <Transpiler>d__2 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private IEnumerator<CodeInstruction> <>s__1;

			private CodeInstruction <instruction>5__2;

			private MethodInfo <target>5__3;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <Transpiler>d__2(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || (uint)(num - 1) <= 1u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>s__1 = null;
				<instruction>5__2 = null;
				<target>5__3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dd: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>s__1 = instructions.GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						break;
					case 2:
						<>1__state = -3;
						<target>5__3 = null;
						<instruction>5__2 = null;
						break;
					}
					if (<>s__1.MoveNext())
					{
						<instruction>5__2 = <>s__1.Current;
						if (<instruction>5__2.opcode == OpCodes.Call || <instruction>5__2.opcode == OpCodes.Callvirt)
						{
							object operand = <instruction>5__2.operand;
							<target>5__3 = operand as MethodInfo;
							if ((object)<target>5__3 != null && IsPhysObjectHurtCall(<target>5__3))
							{
								<>2__current = new CodeInstruction(OpCodes.Call, (object)Replacement);
								<>1__state = 1;
								return true;
							}
						}
						<>2__current = <instruction>5__2;
						<>1__state = 2;
						return true;
					}
					<>m__Finally1();
					<>s__1 = null;
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>s__1 != null)
				{
					<>s__1.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<Transpiler>d__2 <Transpiler>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<Transpiler>d__ = this;
				}
				else
				{
					<Transpiler>d__ = new <Transpiler>d__2(0);
				}
				<Transpiler>d__.instructions = <>3__instructions;
				return <Transpiler>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		private const int ReleaseObjectViewId = -1;

		private static readonly MethodInfo Replacement = AccessTools.Method(typeof(StunHandlerReleasePatch), "CustomPhysObjectHurt", (Type[])null, (Type[])null);

		[IteratorStateMachine(typeof(<Transpiler>d__2))]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Transpiler>d__2(-2)
			{
				<>3__instructions = instructions
			};
		}

		private static bool IsPhysObjectHurtCall(MethodInfo target)
		{
			if (target == null || target.Name != "PhysObjectHurt")
			{
				return false;
			}
			ParameterInfo[] parameters = target.GetParameters();
			if (parameters.Length != 3)
			{
				return false;
			}
			return parameters[0].ParameterType == typeof(PhysGrabObject) && parameters[1].ParameterType == typeof(BreakImpact) && parameters[2].ParameterType == typeof(float);
		}

		public static void CustomPhysObjectHurt(StunHandler self, PhysGrabObject physGrabObject, BreakImpact impact, float hitForce)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_0016: 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_002a: Expected I4, but got Unknown
			if ((Object)(object)physGrabObject == (Object)null)
			{
				return;
			}
			switch (impact - 1)
			{
			case 0:
				physGrabObject.lightBreakImpulse = true;
				break;
			case 1:
				physGrabObject.mediumBreakImpulse = true;
				break;
			case 2:
				physGrabObject.heavyBreakImpulse = true;
				break;
			}
			if (!(hitForce >= 5f) || physGrabObject.playerGrabbing.Count <= 0)
			{
				return;
			}
			foreach (PhysGrabber item in physGrabObject.playerGrabbing.ToList())
			{
				if (!((Object)(object)item == (Object)null))
				{
					if (!SemiFunc.IsMultiplayer())
					{
						item.ReleaseObjectRPC(true, 2f, -1);
						continue;
					}
					item.photonView.RPC("ReleaseObjectRPC", (RpcTarget)0, new object[3] { false, 1f, -1 });
				}
			}
		}
	}
}
namespace DeathHeadHopperFix.Modules.Gameplay
{
	internal static class AbilityModule
	{
		private static class AbilitySpotLabelOverlay
		{
			private static readonly Dictionary<object, Component> Labels = new Dictionary<object, Component>();

			private static readonly Type? LabelType = AccessTools.TypeByName("TMPro.TextMeshProUGUI");

			private static readonly Type? AlignmentType = AccessTools.TypeByName("TMPro.TextAlignmentOptions");

			private static readonly PropertyInfo? TextProperty = LabelType?.GetProperty("text");

			private static readonly PropertyInfo? ColorProperty = LabelType?.GetProperty("color");

			private static readonly PropertyInfo? AlignmentProperty = LabelType?.GetProperty("alignment");

			private static readonly PropertyInfo? FontSizeProperty = LabelType?.GetProperty("fontSize");

			private static readonly PropertyInfo? AutoSizeProperty = LabelType?.GetProperty("enableAutoSizing");

			private static readonly PropertyInfo? WordWrapProperty = LabelType?.GetProperty("enableWordWrapping");

			private static readonly PropertyInfo? RichTextProperty = LabelType?.GetProperty("richText");

			private static readonly object? CenterAlignment = ((AlignmentType != null) ? Enum.Parse(AlignmentType, "Center") : null);

			private static Type? SpotType;

			private static FieldInfo? SpotIndexField;

			internal static void EnsureLabel(object spot)
			{
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_006a: Expected O, but got Unknown
				//IL_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				if (spot != null && !(LabelType == null) && !Labels.ContainsKey(spot))
				{
					Component val = (Component)((spot is Component) ? spot : null);
					if (val != null)
					{
						GameObject val2 = new GameObject("DHHAbilityLabel", new Type[1] { typeof(RectTransform) });
						val2.transform.SetParent(val.transform, false);
						RectTransform component = val2.GetComponent<RectTransform>();
						component.anchorMin = Vector2.zero;
						component.anchorMax = Vector2.one;
						component.offsetMin = Vector2.zero;
						component.offsetMax = Vector2.zero;
						((Transform)component).localScale = Vector3.one;
						((Transform)component).SetAsLastSibling();
						Component val3 = val2.AddComponent(LabelType);
						SetLabelDefaults(val3);
						Labels[spot] = val3;
						UpdateLabel(spot);
					}
				}
			}

			internal static void UpdateLabel(object spot)
			{
				if (spot != null)
				{
					Component label = GetLabel(spot);
					if (!((Object)(object)label == (Object)null))
					{
						string slotTag = GetSlotTag(spot);
						SetLabelText(label, slotTag);
					}
				}
			}

			internal static void ClearLabel(object spot)
			{
				if (spot == null || !Labels.TryGetValue(spot, out Component value))
				{
					return;
				}
				Labels.Remove(spot);
				if (value != null)
				{
					Component val = value;
					if (true)
					{
						Object.Destroy((Object)(object)val.gameObject);
					}
				}
			}

			private static Component? GetLabel(object spot)
			{
				Component value;
				return Labels.TryGetValue(spot, out value) ? value : null;
			}

			private static string GetSlotTag(object spot)
			{
				int abilityIndex = GetAbilityIndex(spot);
				if (1 == 0)
				{
				}
				string empty = string.Empty;
				if (1 == 0)
				{
				}
				return empty;
			}

			private static int GetAbilityIndex(object spot)
			{
				if (spot == null)
				{
					return -1;
				}
				Type type = spot.GetType();
				if (SpotType == null || SpotType != type)
				{
					SpotType = type;
					SpotIndexField = type.GetField("abilitySpotIndex", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				if (SpotIndexField == null)
				{
					return -1;
				}
				return (SpotIndexField.GetValue(spot) is int num) ? num : (-1);
			}

			private static void SetLabelDefaults(Component label)
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)label == (Object)null))
				{
					if (ColorProperty != null)
					{
						ColorProperty.SetValue(label, Color.white);
					}
					if (FontSizeProperty != null)
					{
						FontSizeProperty.SetValue(label, 10f);
					}
					if (AutoSizeProperty != null)
					{
						AutoSizeProperty.SetValue(label, false);
					}
					if (WordWrapProperty != null)
					{
						WordWrapProperty.SetValue(label, false);
					}
					if (RichTextProperty != null)
					{
						RichTextProperty.SetValue(label, false);
					}
					if (AlignmentProperty != null && CenterAlignment != null)
					{
						AlignmentProperty.SetValue(label, CenterAlignment);
					}
					SetLabelText(label, string.Empty);
				}
			}

			private static void SetLabelText(Component label, string text)
			{
				if (!((Object)(object)label == (Object)null))
				{
					if (TextProperty != null)
					{
						TextProperty.SetValue(label, text);
					}
					Behaviour val = (Behaviour)(object)((label is Behaviour) ? label : null);
					if (val != null)
					{
						val.enabled = !string.IsNullOrEmpty(text);
					}
				}
			}
		}

		private static Type? s_abilityBaseType;

		private static MethodInfo? s_abilityCooldownGetter;

		private static MethodInfo? s_abilityEnergyCostGetter;

		private static MethodInfo? s_abilityNameGetter;

		private static Type? s_abilitySpotType;

		private static MethodInfo? s_abilitySpotSetCooldown;

		private static FieldInfo? s_abilitySpotsField;

		internal static void ApplyAbilitySpotLabelOverlay(Harmony harmony, Assembly asm)
		{
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			Type type = asm.GetType("DeathHeadHopper.UI.AbilitySpot", throwOnError: false);
			if (!(type == null))
			{
				MethodInfo methodInfo = AccessTools.Method(type, "Start", (Type[])null, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(type, "UpdateUI", (Type[])null, (Type[])null);
				MethodInfo method = type.GetMethod("OnDestroy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				MethodInfo method2 = typeof(AbilityModule).GetMethod("AbilitySpot_Start_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo method3 = typeof(AbilityModule).GetMethod("AbilitySpot_UpdateUI_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo method4 = typeof(AbilityModule).GetMethod("AbilitySpot_OnDestroy_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
				if (methodInfo != null && method2 != null)
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				if (methodInfo2 != null && method3 != null)
				{
					harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				if (method != null && method4 != null)
				{
					harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		internal static void ApplyAbilityManagerHooks(Harmony harmony, Assembly asm)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			Type type = asm.GetType("DeathHeadHopper.Managers.DHHAbilityManager", throwOnError: false);
			if (type == null)
			{
				return;
			}
			EnsureAbilityReflection();
			if (s_abilityBaseType == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "OnAbilityUsed", new Type[1] { s_abilityBaseType }, (Type[])null);
			if (!(methodInfo == null))
			{
				MethodInfo method = typeof(AbilityModule).GetMethod("DHHAbilityManager_OnAbilityUsed_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
				if (!(method == null))
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void AbilitySpot_Start_Postfix(object? __instance)
		{
			if (__instance != null)
			{
				AbilitySpotLabelOverlay.EnsureLabel(__instance);
			}
		}

		private static void AbilitySpot_UpdateUI_Postfix(object? __instance)
		{
			if (__instance != null)
			{
				AbilitySpotLabelOverlay.UpdateLabel(__instance);
			}
		}

		private static void AbilitySpot_OnDestroy_Postfix(object? __instance)
		{
			if (__instance != null)
			{
				AbilitySpotLabelOverlay.ClearLabel(__instance);
			}
		}

		private static void EnsureAbilityReflection()
		{
			if (s_abilityBaseType == null)
			{
				s_abilityBaseType = AccessTools.TypeByName("DeathHeadHopper.Abilities.AbilityBase");
			}
			if (s_abilityCooldownGetter == null && s_abilityBaseType != null)
			{
				s_abilityCooldownGetter = AccessTools.PropertyGetter(s_abilityBaseType, "Cooldown");
			}
			if (s_abilityEnergyCostGetter == null && s_abilityBaseType != null)
			{
				s_abilityEnergyCostGetter = AccessTools.PropertyGetter(s_abilityBaseType, "EnergyCost");
			}
			if (s_abilityNameGetter == null && s_abilityBaseType != null)
			{
				s_abilityNameGetter = AccessTools.PropertyGetter(s_abilityBaseType, "AbilityName");
			}
			if (s_abilitySpotType == null)
			{
				s_abilitySpotType = AccessTools.TypeByName("DeathHeadHopper.UI.AbilitySpot");
			}
			if (s_abilitySpotSetCooldown == null && s_abilitySpotType != null)
			{
				s_abilitySpotSetCooldown = AccessTools.Method(s_abilitySpotType, "SetCooldown", new Type[1] { typeof(float) }, (Type[])null);
			}
		}

		private static void DHHAbilityManager_OnAbilityUsed_Postfix(object __instance, object ability)
		{
			if (ability == null)
			{
				return;
			}
			EnsureAbilityReflection();
			if (s_abilityCooldownGetter == null || s_abilitySpotSetCooldown == null)
			{
				return;
			}
			float num2 = ((s_abilityCooldownGetter.Invoke(ability, null) is float num) ? num : 0f);
			if (num2 <= 0f)
			{
				return;
			}
			FieldInfo fieldInfo = s_abilitySpotsField ?? (s_abilitySpotsField = __instance?.GetType().GetField("abilitySpots", BindingFlags.Instance | BindingFlags.NonPublic));
			if (fieldInfo == null || !(fieldInfo.GetValue(__instance) is Array array))
			{
				return;
			}
			foreach (object item in array)
			{
				if (item != null)
				{
					try
					{
						s_abilitySpotSetCooldown?.Invoke(item, new object[1] { num2 });
					}
					catch
					{
					}
				}
			}
		}
	}
	internal static class AudioModule
	{
		[CompilerGenerated]
		private sealed class <AudioHandler_InitWhenReady>d__4 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public MonoBehaviour handler;

			private int <frames>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <AudioHandler_InitWhenReady>d__4(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<frames>5__1 = 0;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (<frames>5__1++ < 600)
				{
					if ((Object)(object)handler == (Object)null)
					{
						return false;
					}
					if (TryInitAudioHandlerSafe(handler))
					{
						return false;
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogWarning((object)"[Fix] AudioHandler init timed out; audio may be partially disabled.");
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static readonly HashSet<int> AudioInitDone = new HashSet<int>();

		private static ManualLogSource? _log;

		internal static void Apply(Harmony harmony, Assembly asm, ManualLogSource? log)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			_log = log;
			if (harmony == null || asm == null)
			{
				return;
			}
			Type type = asm.GetType("DeathHeadHopper.DeathHead.Handlers.AudioHandler", throwOnError: false);
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "Awake", Type.EmptyTypes, (Type[])null);
			if (!(methodInfo == null))
			{
				MethodInfo method = typeof(AudioModule).GetMethod("AudioHandler_Awake_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (!(method == null))
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static bool AudioHandler_Awake_Prefix(MonoBehaviour __instance)
		{
			try
			{
				int instanceID = ((Object)__instance).GetInstanceID();
				if (AudioInitDone.Contains(instanceID))
				{
					return false;
				}
				__instance.StartCoroutine(AudioHandler_InitWhenReady(__instance));
			}
			catch (Exception ex)
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogError((object)ex);
				}
			}
			return false;
		}

		[IteratorStateMachine(typeof(<AudioHandler_InitWhenReady>d__4))]
		private static IEnumerator AudioHandler_InitWhenReady(MonoBehaviour handler)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <AudioHandler_InitWhenReady>d__4(0)
			{
				handler = handler
			};
		}

		private static bool TryInitAudioHandlerSafe(MonoBehaviour handler)
		{
			int instanceID = ((Object)handler).GetInstanceID();
			if (AudioInitDone.Contains(instanceID))
			{
				return true;
			}
			Type type = ((object)handler).GetType();
			FieldInfo fieldInfo = AccessTools.Field(type, "controller");
			object obj = fieldInfo?.GetValue(handler);
			if (obj == null)
			{
				Type type2 = type.Assembly.GetType("DeathHeadHopper.DeathHead.DeathHeadController", throwOnError: false);
				obj = ((type2 != null) ? ((Component)handler).GetComponent(type2) : null);
				if (obj == null)
				{
					return false;
				}
				fieldInfo?.SetValue(handler, obj);
			}
			object obj2 = ((obj == null) ? null : AccessTools.Field(obj.GetType(), "deathHead")?.GetValue(obj));
			object obj3 = ((obj2 == null) ? null : AccessTools.Field(obj2.GetType(), "playerAvatar")?.GetValue(obj2));
			object obj4 = TryGetAudioPreset(handler);
			if (obj4 == null && obj3 == null && obj2 == null)
			{
				return false;
			}
			if (!TryEnsureSound(handler, type, obj4, obj2, obj3))
			{
				return false;
			}
			AudioInitDone.Add(instanceID);
			if (FeatureFlags.DebugLogging)
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogInfo((object)"[Fix] AudioHandler initialized safely (deferred).");
				}
			}
			return true;
		}

		private static object? TryGetAudioPreset(MonoBehaviour handler)
		{
			try
			{
				Type type = AccessTools.TypeByName("NotValuableObject");
				Component val = ((type != null) ? ((Component)handler).gameObject.GetComponent(type) : null);
				return (!((Object)(object)val != (Object)null)) ? null : AccessTools.Field(((object)val).GetType(), "audioPreset")?.GetValue(val);
			}
			catch
			{
				return null;
			}
		}

		private static bool TryEnsureSound(MonoBehaviour handler, Type t, object? audioPreset, object? deathHead, object? playerAvatar)
		{
			Type t2 = t;
			MonoBehaviour handler2 = handler;
			Type type = AccessTools.TypeByName("Sound");
			if (type == null)
			{
				return false;
			}
			try
			{
				if (AccessTools.Field(t2, "jumpSound")?.GetValue(handler2) == null && audioPreset != null)
				{
					object soundLike2 = AccessTools.Field(audioPreset.GetType(), "impactMedium")?.GetValue(audioPreset);
					AudioClip[] clips2 = CloneClipsFromSoundLike(soundLike2);
					object obj = CreateSound(type, clips2, null, 0.12f, 0f, 0.8f, 0f);
					if (obj != null)
					{
						AccessTools.Field(t2, "jumpSound")?.SetValue(handler2, obj);
					}
				}
			}
			catch
			{
			}
			try
			{
				if (AccessTools.Field(t2, "anchorBreakSound")?.GetValue(handler2) == null && playerAvatar != null)
				{
					object soundLike3 = AccessTools.Field(playerAvatar.GetType(), "tumbleBreakFreeSound")?.GetValue(playerAvatar);
					AudioClip[] clips3 = CloneClipsFromSoundLike(soundLike3);
					object obj3 = CreateSound(type, clips3, CreateSrc(), 0.1f, 0f, 1f, 0f);
					if (obj3 != null)
					{
						AccessTools.Field(t2, "anchorBreakSound")?.SetValue(handler2, obj3);
					}
				}
			}
			catch
			{
			}
			try
			{
				if (AccessTools.Field(t2, "anchorAttachSound")?.GetValue(handler2) == null && deathHead != null)
				{
					object soundLike4 = AccessTools.Field(deathHead.GetType(), "eyeFlashNegativeSound")?.GetValue(deathHead);
					AudioClip[] clips4 = CloneClipsFromSoundLike(soundLike4);
					object obj5 = CreateSound(type, clips4, CreateSrc(), 0.5f, 0f, 0.3f, 0.03f);
					if (obj5 != null)
					{
						AccessTools.Field(t2, "anchorAttachSound")?.SetValue(handler2, obj5);
					}
				}
			}
			catch
			{
			}
			try
			{
				if (AccessTools.Field(t2, "windupSound")?.GetValue(handler2) == null)
				{
					Type type2 = AccessTools.TypeByName("PlayerAvatar");
					object obj7 = null;
					if (type2 != null)
					{
						obj7 = ReflectionHelper.GetStaticInstanceValue(type2, "instance");
					}
					object obj8 = ((obj7 == null) ? null : AccessTools.Field(obj7.GetType(), "tumble")?.GetValue(obj7));
					object soundLike5 = ((obj8 == null) ? null : AccessTools.Field(obj8.GetType(), "tumbleMoveSound")?.GetValue(obj8));
					AudioClip[] clips5 = CloneClipsFromSoundLike(soundLike5);
					object obj9 = CreateSound(type, clips5, CreateSrc(), 0.4f, 0.02f, 0.8f, 0f);
					if (obj9 != null)
					{
						AccessTools.Field(t2, "windupSound")?.SetValue(handler2, obj9);
					}
				}
			}
			catch
			{
			}
			try
			{
				if (AccessTools.Field(t2, "rechargeSound")?.GetValue(handler2) == null)
				{
					Type type3 = AccessTools.TypeByName("AssetManager");
					object obj11 = null;
					if (type3 != null)
					{
						obj11 = ReflectionHelper.GetStaticInstanceValue(type3, "instance");
					}
					object soundLike6 = ((obj11 == null) ? null : AccessTools.Field(obj11.GetType(), "batteryChargeSound")?.GetValue(obj11));
					AudioClip[] clips6 = CloneClipsFromSoundLike(soundLike6);
					object obj12 = CreateSound(type, clips6, CreateSrc(), 0.2f, 0.01f, 1f, 0.02f);
					if (obj12 != null)
					{
						AccessTools.Field(t2, "rechargeSound")?.SetValue(handler2, obj12);
					}
				}
			}
			catch
			{
			}
			try
			{
				if (AccessTools.Field(t2, "unAnchoringSound")?.GetValue(handler2) == null)
				{
					Type type4 = AccessTools.TypeByName("MaterialPreset");
					if (type4 != null)
					{
						Object[] array = Resources.FindObjectsOfTypeAll(type4);
						object obj14 = null;
						FieldInfo fieldInfo = AccessTools.Field(type4, "Type");
						Object[] array2 = array;
						foreach (Object val in array2)
						{
							if (!(val == (Object)null) && fieldInfo?.GetValue(val) is int num && num == 2)
							{
								obj14 = val;
								break;
							}
						}
						if (obj14 != null)
						{
							object soundLike7 = AccessTools.Field(type4, "SlideOneShot")?.GetValue(obj14);
							AudioClip[] clips7 = CloneClipsFromSoundLike(soundLike7);
							object obj15 = CreateSound(type, clips7, CreateSrc(), 1f, 0f, 0.6f, 0f);
							if (obj15 != null)
							{
								AccessTools.Field(t2, "unAnchoringSound")?.SetValue(handler2, obj15);
							}
						}
					}
				}
			}
			catch
			{
			}
			return true;
			static AudioClip[]? CloneClipsFromSoundLike(object? soundLike)
			{
				if (soundLike == null)
				{
					return null;
				}
				object obj19 = AccessTools.Field(soundLike.GetType(), "Sounds")?.GetValue(soundLike);
				if (!(obj19 is AudioClip[] array3) || array3.Length == 0)
				{
					return null;
				}
				return array3.Clone() as AudioClip[];
			}
			static object? CreateSound(Type tSound, AudioClip[]? clips, AudioSource? src, float vol, float volRand, float pitch, float pitchRand)
			{
				if (clips == null || clips.Length == 0)
				{
					return null;
				}
				object obj18 = Activator.CreateInstance(tSound);
				if (obj18 == null)
				{
					return null;
				}
				if ((Object)(object)src != (Object)null)
				{
					AccessTools.Field(tSound, "Source")?.SetValue(obj18, src);
				}
				AccessTools.Field(tSound, "Sounds")?.SetValue(obj18, clips);
				AccessTools.Field(tSound, "Volume")?.SetValue(obj18, vol);
				AccessTools.Field(tSound, "VolumeRandom")?.SetValue(obj18, volRand);
				AccessTools.Field(tSound, "Pitch")?.SetValue(obj18, pitch);
				AccessTools.Field(tSound, "PitchRandom")?.SetValue(obj18, pitchRand);
				return obj18;
			}
			AudioSource CreateSrc()
			{
				MethodInfo methodInfo = AccessTools.Method(t2, "CreateAudioSource", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					throw new NullReferenceException("CreateAudioSource() not found.");
				}
				object obj17 = methodInfo.Invoke(handler2, Array.Empty<object>());
				AudioSource val2 = (AudioSource)((obj17 is AudioSource) ? obj17 : null);
				if (val2 == null)
				{
					throw new NullReferenceException("CreateAudioSource() returned invalid type.");
				}
				return val2;
			}
		}
	}
	internal static class DHHShopModule
	{
		private static bool _hooksApplied;

		private static ManualLogSource? _log;

		private static FieldInfo? _itemVolumesField;

		private static FieldInfo? _potentialItemsField;

		private static MethodInfo? _spawnShopItemMethod;

		internal static void Apply(Harmony harmony, Assembly asm, ManualLogSource? log)
		{
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			_log = log;
			if (harmony == null || _hooksApplied)
			{
				return;
			}
			Type type = asm.GetType("DeathHeadHopper.Managers.DHHShopManager", throwOnError: false);
			if (type == null)
			{
				return;
			}
			if ((object)_itemVolumesField == null)
			{
				_itemVolumesField = AccessTools.Field(type, "itemVolumes");
			}
			if ((object)_potentialItemsField == null)
			{
				_potentialItemsField = AccessTools.Field(type, "potentialItems");
			}
			if ((object)_spawnShopItemMethod == null)
			{
				_spawnShopItemMethod = AccessTools.Method(typeof(PunManager), "SpawnShopItem", new Type[4]
				{
					typeof(ItemVolume),
					typeof(List<Item>),
					typeof(int).MakeByRefType(),
					typeof(bool)
				}, (Type[])null);
			}
			MethodInfo methodInfo = AccessTools.Method(type, "ShopPopulateItemVolumes", new Type[1] { typeof(PunManager) }, (Type[])null);
			if (methodInfo != null)
			{
				MethodInfo method = typeof(DHHShopModule).GetMethod("ShopPopulateItemVolumes_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (method != null)
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			_hooksApplied = true;
		}

		private static bool ShopPopulateItemVolumes_Prefix(object punManager)
		{
			if (SemiFunc.IsNotMasterClient())
			{
				return false;
			}
			IList<ItemVolume> list = _itemVolumesField?.GetValue(null) as IList<ItemVolume>;
			List<Item> list2 = _potentialItemsField?.GetValue(null) as List<Item>;
			if (list == null || list2 == null)
			{
				return true;
			}
			if (_spawnShopItemMethod == null)
			{
				return true;
			}
			int num = 0;
			int num2 = ((FeatureFlags.DHHShopMaxItems < 0) ? int.MaxValue : FeatureFlags.DHHShopMaxItems);
			float num3 = Mathf.Clamp01(FeatureFlags.DHHShopSpawnChance);
			float num4 = Mathf.Clamp01(FeatureFlags.ShopItemsSpawnChance);
			if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:DHHShop.Populate", 30))
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogInfo((object)$"[Fix:DHHShop] Populate volumes={list.Count} items={list2.Count} limit={num2} slotChance={num3:F3} itemChance={num4:F3}");
				}
			}
			foreach (ItemVolume item in list)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				if (num >= num2)
				{
					break;
				}
				float num5 = 1f;
				if (num3 < 1f)
				{
					num5 = Random.value;
					if (num5 > num3)
					{
						if (FeatureFlags.DebugLogging)
						{
							ManualLogSource? log2 = _log;
							if (log2 != null)
							{
								log2.LogInfo((object)$"[Fix:DHHShop] Slot skip '{((Object)item).name}' slotRoll={num5:F3} slotChance={num3:F3} spawned={num}");
							}
						}
						continue;
					}
				}
				float num6 = 1f;
				if (num4 < 1f)
				{
					num6 = Random.value;
					if (num6 > num4)
					{
						if (FeatureFlags.DebugLogging)
						{
							ManualLogSource? log3 = _log;
							if (log3 != null)
							{
								log3.LogInfo((object)$"[Fix:DHHShop] Item skip '{((Object)item).name}' itemRoll={num6:F3} itemChance={num4:F3} spawned={num}");
							}
						}
						continue;
					}
				}
				if (FeatureFlags.DebugLogging)
				{
					ManualLogSource? log4 = _log;
					if (log4 != null)
					{
						log4.LogInfo((object)$"[Fix:DHHShop] Spawn '{((Object)item).name}' slotRoll={num5:F3} itemRoll={num6:F3} slotChance={num3:F3} itemChance={num4:F3} spawned={num}");
					}
				}
				object[] array = new object[4] { item, list2, num, false };
				object obj = _spawnShopItemMethod.Invoke(punManager, array);
				num = (int)array[2];
				if (num2 == int.MaxValue || num < num2)
				{
					continue;
				}
				break;
			}
			return false;
		}
	}
	internal static class InputModule
	{
		[CompilerGenerated]
		private sealed class <DHHInputManager_WaitForHostVersion>d__5 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			private Type <tPun>5__1;

			private FieldInfo <fHost>5__2;

			private int <i>5__3;

			private string <host>5__4;

			private string <host>5__5;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DHHInputManager_WaitForHostVersion>d__5(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<tPun>5__1 = null;
				<fHost>5__2 = null;
				<host>5__4 = null;
				<host>5__5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<tPun>5__1 = AccessTools.TypeByName("DeathHeadHopper.Managers.DHHPunManager");
					<fHost>5__2 = <tPun>5__1?.GetField("hostVersion", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					<i>5__3 = 0;
					break;
				case 1:
					<>1__state = -1;
					<host>5__4 = null;
					<i>5__3++;
					break;
				}
				if (<i>5__3 < 300)
				{
					<host>5__4 = <fHost>5__2?.GetValue(null) as string;
					if (!string.IsNullOrWhiteSpace(<host>5__4) && !string.Equals(<host>5__4, "pending", StringComparison.OrdinalIgnoreCase))
					{
						return false;
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				if (<fHost>5__2 != null)
				{
					<host>5__5 = <fHost>5__2.GetValue(null) as string;
					if (string.Equals(<host>5__5, "pending", StringComparison.OrdinalIgnoreCase))
					{
						<fHost>5__2.SetValue(null, string.Empty);
						ManualLogSource? log = _log;
						if (log != null)
						{
							log.LogWarning((object)"Host does not have DeathHeadHopper installed!");
						}
					}
					<host>5__5 = null;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static ManualLogSource? _log;

		internal static void Apply(Harmony harmony, Assembly asm, ManualLogSource? log)
		{
			_log = log;
			PatchDhhInputManagerAwakeIfPossible(harmony, asm);
			PatchDhhPunManagerAwakeIfPossible(harmony, asm);
		}

		private static void PatchDhhInputManagerAwakeIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			if (harmony == null || asm == null)
			{
				return;
			}
			Type type = asm.GetType("DeathHeadHopper.Managers.DHHInputManager", throwOnError: false);
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null);
			if (!(methodInfo == null))
			{
				MethodInfo method = typeof(InputModule).GetMethod("DHHInputManager_Awake_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (!(method == null))
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void PatchDhhPunManagerAwakeIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			if (harmony == null || asm == null)
			{
				return;
			}
			Type type = asm.GetType("DeathHeadHopper.Managers.DHHPunManager", throwOnError: false);
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null);
			if (!(methodInfo == null))
			{
				MethodInfo method = typeof(InputModule).GetMethod("DHHPunManager_Awake_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
				if (!(method == null))
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void DHHInputManager_Awake_Prefix(MonoBehaviour __instance)
		{
			try
			{
				Type type = AccessTools.TypeByName("DeathHeadHopper.Managers.DHHPunManager");
				if (type == null)
				{
					return;
				}
				FieldInfo field = type.GetField("hostVersion", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field2 = type.GetField("localVersion", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null)
				{
					return;
				}
				string value = field.GetValue(null) as string;
				if (!string.IsNullOrWhiteSpace(value))
				{
					return;
				}
				if (IsMasterClientOrSingleplayer())
				{
					string value2 = field2?.GetValue(null) as string;
					if (string.IsNullOrWhiteSpace(value2))
					{
						value2 = GetDeathHeadHopperVersionString();
					}
					if (!string.IsNullOrWhiteSpace(value2))
					{
						field.SetValue(null, value2);
					}
				}
				else
				{
					field.SetValue(null, "pending");
					object staticInstanceByName = ReflectionHelper.GetStaticInstanceByName("DeathHeadHopper.Managers.DHHPunManager");
					(staticInstanceByName?.GetType().GetMethod("VersionCheck", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.Invoke(staticInstanceByName, Array.Empty<object>());
					__instance.StartCoroutine(DHHInputManager_WaitForHostVersion());
				}
			}
			catch
			{
			}
		}

		[IteratorStateMachine(typeof(<DHHInputManager_WaitForHostVersion>d__5))]
		private static IEnumerator DHHInputManager_WaitForHostVersion()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DHHInputManager_WaitForHostVersion>d__5(0);
		}

		private static bool IsMasterClientOrSingleplayer()
		{
			try
			{
				MethodInfo methodInfo = AccessTools.TypeByName("SemiFunc")?.GetMethod("IsMasterClientOrSingleplayer", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (methodInfo != null)
				{
					object obj = methodInfo.Invoke(null, Array.Empty<object>());
					if (obj is bool)
					{
						bool result = (bool)obj;
						if (true)
						{
							return result;
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static string? GetDeathHeadHopperVersionString()
		{
			try
			{
				return ((AccessTools.TypeByName("DeathHeadHopper.DeathHeadHopper")?.GetProperty("Version", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(null))?.ToString();
			}
			catch
			{
			}
			return null;
		}

		private static void DHHPunManager_Awake_Postfix(MonoBehaviour __instance)
		{
			try
			{
				Object.DontDestroyOnLoad((Object)(object)((Component)__instance).gameObject);
				Type type = ((object)__instance).GetType();
				AccessTools.Method(type, "EnsurePhotonView", (Type[])null, (Type[])null)?.Invoke(__instance, Array.Empty<object>());
				object? obj = AccessTools.Field(type, "photonView")?.GetValue(__instance);
				PhotonView val = (PhotonView)((obj is PhotonView) ? obj : null);
				if (val != null && val.ViewID == 0)
				{
					val.ViewID = 745;
				}
			}
			catch
			{
			}
		}
	}
	internal static class ItemUpgradeModule
	{
		private const string DhhUpgradePowerTypeName = "DeathHeadHopper.Items.DHHItemUpgradePower";

		private const string DhhUpgradeChargeTypeName = "DeathHeadHopper.Items.DHHItemUpgradeCharge";

		private static Type? _dhhUpgradePowerType;

		private static Type? _dhhUpgradeChargeType;

		private static MethodInfo? _dhhUpgradePowerMethod;

		private static MethodInfo? _dhhUpgradeChargeMethod;

		internal static void Apply(Harmony harmony)
		{
			PatchItemToggleUpgradeHook(harmony);
		}

		private static void PatchItemToggleUpgradeHook(Harmony harmony)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			if (harmony == null)
			{
				return;
			}
			Type type = AccessTools.TypeByName("ItemToggle");
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "ToggleItemLogic", new Type[2]
			{
				typeof(bool),
				typeof(int)
			}, (Type[])null);
			if (!(methodInfo == null))
			{
				MethodInfo method = typeof(ItemUpgradeModule).GetMethod("ItemToggle_ToggleItemLogic_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
				if (!(method == null))
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void ItemToggle_ToggleItemLogic_Postfix(ItemToggle __instance, bool toggle, int player)
		{
			if (toggle && !((Object)(object)__instance == (Object)null))
			{
				bool flag = TryInvokeUpgrade(__instance, ref _dhhUpgradePowerType, ref _dhhUpgradePowerMethod, "DeathHeadHopper.Items.DHHItemUpgradePower");
				bool flag2 = TryInvokeUpgrade(__instance, ref _dhhUpgradeChargeType, ref _dhhUpgradeChargeMethod, "DeathHeadHopper.Items.DHHItemUpgradeCharge");
				if (flag || flag2)
				{
					PlayUpgradeFx(__instance, player);
					DestroyUpgradeItem(__instance);
					RegisterConsumedUpgrade(__instance);
				}
			}
		}

		private static bool TryInvokeUpgrade(ItemToggle toggle, ref Type? upgradeType, ref MethodInfo? upgradeMethod, string typeName)
		{
			Type type = upgradeType ?? (upgradeType = AccessTools.TypeByName(typeName));
			if (type == null)
			{
				return false;
			}
			Component component = ((Component)toggle).GetComponent(type);
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			MethodInfo methodInfo = upgradeMethod ?? (upgradeMethod = AccessTools.Method(type, "Upgrade", (Type[])null, (Type[])null));
			if (methodInfo == null)
			{
				return false;
			}
			methodInfo.Invoke(component, Array.Empty<object>());
			return true;
		}

		private static void DestroyUpgradeItem(ItemToggle toggle)
		{
			if (!((Object)(object)toggle == (Object)null))
			{
				PhysGrabObjectImpactDetector val = ((Component)toggle).GetComponent<PhysGrabObjectImpactDetector>() ?? ((Component)toggle).GetComponentInChildren<PhysGrabObjectImpactDetector>();
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)toggle).GetComponentInParent<PhysGrabObjectImpactDetector>();
				}
				if (val != null)
				{
					val.DestroyObject(false);
				}
			}
		}

		private static void PlayUpgradeFx(ItemToggle toggle, int player)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonID(player);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				PhotonView photonView = val.photonView;
				if (!GameManager.Multiplayer() || ((Object)(object)photonView != (Object)null && photonView.IsMine))
				{
					StatsUI instance = StatsUI.instance;
					if (instance != null)
					{
						instance.Fetch();
					}
					StatsUI instance2 = StatsUI.instance;
					if (instance2 != null)
					{
						instance2.ShowStats();
					}
					CameraGlitch instance3 = CameraGlitch.Instance;
					if (instance3 != null)
					{
						instance3.PlayUpgrade();
					}
				}
				else
				{
					GameDirector instance4 = GameDirector.instance;
					if (instance4 != null)
					{
						CameraShake cameraImpact = instance4.CameraImpact;
						if (cameraImpact != null)
						{
							cameraImpact.ShakeDistance(5f, 1f, 6f, ((Component)toggle).transform.position, 0.2f);
						}
					}
				}
				if (!GameManager.Multiplayer() || PhotonNetwork.IsMasterClient)
				{
					PlayerHealth playerHealth = val.playerHealth;
					if (playerHealth != null)
					{
						playerHealth.MaterialEffectOverride((Effect)0);
					}
				}
			}
			catch
			{
			}
		}

		private static void RegisterConsumedUpgrade(ItemToggle toggle)
		{
			if ((Object)(object)toggle == (Object)null)
			{
				return;
			}
			string text = TryGetStatsItemName(toggle);
			if (!string.IsNullOrWhiteSpace(text))
			{
				StatsModule.EnsureStatsManagerKey(text);
				StatsManager instance = StatsManager.instance;
				if (!((Object)(object)instance == (Object)null))
				{
					instance.itemsPurchased[text] = Mathf.Max(instance.itemsPurchased[text] - 1, 0);
				}
			}
		}

		private static string? TryGetStatsItemName(ItemToggle toggle)
		{
			try
			{
				ItemAttributes val = ((Component)toggle).GetComponent<ItemAttributes>() ?? ((Component)toggle).GetComponentInChildren<ItemAttributes>() ?? ((Component)toggle).GetComponentInParent<ItemAttributes>();
				if ((Object)(object)val?.item != (Object)null && !string.IsNullOrWhiteSpace(((Object)val.item).name))
				{
					return ((Object)val.item).name;
				}
			}
			catch
			{
			}
			string text = ItemHelpers.GetItemAssetName((Object?)(object)toggle) ?? ((Object)toggle).name;
			return string.IsNullOrWhiteSpace(text) ? null : text;
		}
	}
	internal static class PrefabModule
	{
		private static readonly Dictionary<string, GameObject> PendingPool = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);

		private static AssetBundle? _dhhBundle;

		private static ManualLogSource? _log;

		private static readonly HashSet<string> _knownPrefabKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		internal static void Apply(Harmony harmony, Assembly asm, ManualLogSource? log)
		{
			_log = log;
			if (harmony != null && !(asm == null))
			{
				PatchDhhAssetManagerIfPossible(harmony, asm);
				PatchDhhShopManagerIfPossible(harmony, asm);
				PatchRunManagerAwakeIfPossible(harmony);
				PatchPhotonDefaultPoolIfPossible(harmony);
			}
		}

		private static void PatchDhhAssetManagerIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			Type type = asm.GetType("DeathHeadHopper.Managers.DHHAssetManager", throwOnError: false);
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "LoadAssets", (Type[])null, (Type[])null);
			if (!(methodInfo == null))
			{
				MethodInfo method = typeof(PrefabModule).GetMethod("DHHAssetManager_LoadAssets_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (!(method == null))
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static bool DHHAssetManager_LoadAssets_Prefix()
		{
			try
			{
				string text = Path.Combine(Paths.PluginPath, "Cronchy-DeathHeadHopper", "deathheadhopper");
				if (!File.Exists(text))
				{
					ManualLogSource? log = _log;
					if (log != null)
					{
						log.LogError((object)("AssetBundle not found at: " + text));
					}
					return false;
				}
				AssetBundle val = _dhhBundle;
				if ((Object)(object)val != (Object)null)
				{
					ManualLogSource? log2 = _log;
					if (log2 != null)
					{
						log2.LogInfo((object)"[Fix] Reusing already loaded AssetBundle instance.");
					}
				}
				else
				{
					string text2 = "Assets/DeathHeadHopper/Materials/Head Phase.mat";
					foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles())
					{
						if ((Object)(object)allLoadedAssetBundle == (Object)null || (!string.Equals(((Object)allLoadedAssetBundle).name, "deathheadhopper", StringComparison.OrdinalIgnoreCase) && !string.Equals(((Object)allLoadedAssetBundle).name, Path.GetFileName(text), StringComparison.OrdinalIgnoreCase) && !allLoadedAssetBundle.Contains(text2) && !LooksLikeDhhBundle(allLoadedAssetBundle)))
						{
							continue;
						}
						val = allLoadedAssetBundle;
						break;
					}
					if ((Object)(object)val != (Object)null)
					{
						ManualLogSource? log3 = _log;
						if (log3 != null)
						{
							log3.LogInfo((object)"[Fix] Found already loaded DeathHeadHopper AssetBundle.");
						}
					}
					else
					{
						ManualLogSource? log4 = _log;
						if (log4 != null)
						{
							log4.LogInfo((object)("[Fix] Loading AssetBundle from: " + text));
						}
						val = AssetBundle.LoadFromFile(text);
						if ((Object)(object)val == (Object)null)
						{
							ManualLogSource? log5 = _log;
							if (log5 != null)
							{
								log5.LogError((object)"[Fix] AssetBundle.LoadFromFile returned null.");
							}
							return false;
						}
					}
					if ((Object)(object)val == (Object)null)
					{
						ManualLogSource? log6 = _log;
						if (log6 != null)
						{
							log6.LogError((object)"[Fix] AssetBundle not available.");
						}
						return false;
					}
					_dhhBundle = val;
				}
				SetStaticFieldIfExists("DeathHeadHopper.Managers.DHHAssetManager", "headPhaseMaterial", val.LoadAsset<Material>("Assets/DeathHeadHopper/Materials/Head Phase.mat"));
				LoadItemsCompatible(val);
				InvokeStaticIfExists("DeathHeadHopper.Managers.DHHAssetManager", "LoadAbilities", val);
				InvokeStaticIfExists("DeathHeadHopper.Managers.DHHAssetManager", "LoadChargeAssets", val);
				SetStaticFieldIfExists("DeathHeadHopper.Managers.DHHShopManager", "shopAtticShelvesPrefab", val.LoadAsset<GameObject>("Assets/DeathHeadHopper/Shop Attic Shelves.prefab"));
				SetStaticFieldIfExists("DeathHeadHopper.Managers.DHHUIManager", "abilityUIPrefab", val.LoadAsset<GameObject>("Assets/DeathHeadHopper/Ability UI.prefab"));
				ManualLogSource? log7 = _log;
				if (log7 != null)
				{
					log7.LogInfo((object)"[Fix] LoadAssets compatible flow completed.");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? log8 = _log;
				if (log8 != null)
				{
					log8.LogError((object)ex);
				}
			}
			return false;
		}

		private static void LoadItemsCompatible(AssetBundle bundle)
		{
			Type type = AccessTools.TypeByName("DeathHeadHopper.Managers.DHHAssetManager");
			if (type == null)
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogError((object)"[Fix] DHHAssetManager type not found.");
				}
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(type, "shopItems");
			if (fieldInfo == null)
			{
				ManualLogSource? log2 = _log;
				if (log2 != null)
				{
					log2.LogError((object)"[Fix] DHHAssetManager.shopItems field not found.");
				}
				return;
			}
			if (!(fieldInfo.GetValue(null) is IDictionary dict))
			{
				ManualLogSource? log3 = _log;
				if (log3 != null)
				{
					log3.LogError((object)"[Fix] DHHAssetManager.shopItems is not an IDictionary.");
				}
				return;
			}
			Type type2 = AccessTools.TypeByName("Item");
			if (type2 == null)
			{
				ManualLogSource? log4 = _log;
				if (log4 != null)
				{
					log4.LogError((object)"[Fix] Game type Item not found.");
				}
				return;
			}
			FieldInfo fieldInfo2 = AccessTools.Field(type2, "prefab");
			if (fieldInfo2 == null)
			{
				ManualLogSource? log5 = _log;
				if (log5 != null)
				{
					log5.LogError((object)"[Fix] Field Item.prefab not found.");
				}
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(fieldInfo2.FieldType, "SetPrefab", new Type[2]
			{
				typeof(GameObject),
				typeof(string)
			}, (Type[])null);
			List<string> list = (from x in bundle.GetAllAssetNames()
				where x.EndsWith(".asset", StringComparison.OrdinalIgnoreCase) && x.IndexOf("/items/", StringComparison.OrdinalIgnoreCase) >= 0
				select x).ToList();
			ManualLogSource? log6 = _log;
			if (log6 != null)
			{
				log6.LogInfo((object)$"[Fix] Found {list.Count} item assets in bundle.");
			}
			foreach (string item in list)
			{
				Object val = null;
				try
				{
					val = bundle.LoadAsset(item, type2);
				}
				catch (Exception arg)
				{
					ManualLogSource? log7 = _log;
					if (log7 != null)
					{
						log7.LogError((object)$"[Fix] Exception loading item asset '{item}': {arg}");
					}
				}
				if (val == (Object)null)
				{
					ManualLogSource? log8 = _log;
					if (log8 != null)
					{
						log8.LogError((object)("[Fix] Failed to load item asset: " + item));
					}
					continue;
				}
				string text = item.Replace(".asset", ".prefab");
				GameObject val2 = bundle.LoadAsset<GameObject>(text);
				if ((Object)(object)val2 == (Object)null)
				{
					ManualLogSource? log9 = _log;
					if (log9 != null)
					{
						log9.LogError((object)("[Fix] Failed to load item prefab: " + text));
					}
					continue;
				}
				object obj = fieldInfo2.GetValue(val) ?? Activator.CreateInstance(fieldInfo2.FieldType);
				if (obj == null)
				{
					ManualLogSource? log10 = _log;
					if (log10 != null)
					{
						log10.LogError((object)"[Fix] Failed to create PrefabRef instance.");
					}
					continue;
				}
				fieldInfo2.SetValue(val, obj);
				methodInfo?.Invoke(obj, new object[2] { val2, text });
				string name = val.name;
				string text2 = ItemHelpers.GetItemAssetName(val) ?? name;
				CachePrefabEntry(text, val2);
				string fileName = Path.GetFileName(text);
				if (!string.IsNullOrEmpty(fileName))
				{
					CachePrefabEntry(fileName, val2);
				}
				if (!string.IsNullOrWhiteSpace(text2))
				{
					CachePrefabEntry(text2, val2);
					CachePrefabEntry("Items/" + text2, val2);
				}
				CacheShopItemKey(dict, text2, val);
				CacheShopItemKey(dict, name, val);
				TryRegisterItemWithRepolib(val);
				StatsModule.EnsureStatsEntriesForItem(val);
				ManualLogSource? log11 = _log;
				if (log11 != null)
				{
					log11.LogInfo((object)("[Fix] Loaded item '" + name + "' from '" + item + "' and bound prefab '" + text + "'."));
				}
			}
		}

		private static void PatchDhhShopManagerIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			Type type = asm.GetType("DeathHeadHopper.Managers.DHHShopManager", throwOnError: false);
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "LoadItems", (Type[])null, (Type[])null);
			if (!(methodInfo == null))
			{
				MethodInfo method = typeof(PrefabModule).GetMethod("DHHShopManager_LoadItems_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (!(method == null))
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static bool DHHShopManager_LoadItems_Prefix()
		{
			try
			{
				object staticInstanceByName = ReflectionHelper.GetStaticInstanceByName("ShopManager");
				if (staticInstanceByName == null)
				{
					return false;
				}
				Type type = AccessTools.TypeByName("DeathHeadHopper.Managers.DHHAssetManager");
				IDictionary shopItemsDict = ((type != null) ? (AccessTools.Field(type, "shopItems")?.GetValue(null) as IDictionary) : null);
				if (shopItemsDict == null)
				{
					return false;
				}
				Type type2 = AccessTools.TypeByName("DeathHeadHopper.Managers.DHHShopManager");
				object obj = ((type2 != null) ? AccessTools.Field(type2, "potentialItems") : null)?.GetValue(null);
				IList dhhPotential = obj as IList;
				if (dhhPotential == null)
				{
					return false;
				}
				FieldInfo fieldInfo = AccessTools.Field(staticInstanceByName.GetType(), "potentialItemUpgrades");
				FieldInfo fieldInfo2 = AccessTools.Field(staticInstanceByName.GetType(), "potentialItems");
				IList list = fieldInfo?.GetValue(staticInstanceByName) as IList;
				IList list2 = fieldInfo2?.GetValue(staticInstanceByName) as IList;
				dhhPotential.Clear();
				CollectAndRemove(list);
				CollectAndRemove(list2);
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogInfo((object)$"[Fix] DHHShopManager potential list size {dhhPotential.Count} (upgrades left={list?.Count ?? 0}, items left={list2?.Count ?? 0})");
				}
				void CollectAndRemove(IList? source)
				{
					if (source == null)
					{
						return;
					}
					List<object> list3 = new List<object>();
					foreach (object item in source)
					{
						Object val = (Object)((item is Object) ? item : null);
						if (val != null)
						{
							string text = ItemHelpers.GetItemAssetName(val) ?? val.name;
							if (!string.IsNullOrWhiteSpace(text) && ShopItemsDictContains(shopItemsDict,