Decompiled source of DeathHeadHopperFix v0.2.8

plugins\DeathHeadHopperFix.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
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 System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DeathHeadHopper;
using DeathHeadHopper.Abilities;
using DeathHeadHopper.Abilities.Charge;
using DeathHeadHopper.DeathHead;
using DeathHeadHopper.DeathHead.Handlers;
using DeathHeadHopper.Helpers;
using DeathHeadHopper.Items;
using DeathHeadHopper.Managers;
using DeathHeadHopper.Patches;
using DeathHeadHopper.UI;
using DeathHeadHopperFix.API.Abilities;
using DeathHeadHopperFix.API.Battery;
using DeathHeadHopperFix.Modules.Battery;
using DeathHeadHopperFix.Modules.Config;
using DeathHeadHopperFix.Modules.Gameplay.Core.Abilities;
using DeathHeadHopperFix.Modules.Gameplay.Core.Audio;
using DeathHeadHopperFix.Modules.Gameplay.Core.Bootstrap;
using DeathHeadHopperFix.Modules.Gameplay.Core.Input;
using DeathHeadHopperFix.Modules.Gameplay.Core.Interop;
using DeathHeadHopperFix.Modules.Gameplay.Core.Runtime;
using DeathHeadHopperFix.Modules.Gameplay.Spectate;
using DeathHeadHopperFix.Modules.Gameplay.Stun;
using DeathHeadHopperFix.Modules.Stamina;
using DeathHeadHopperFix.Modules.Utilities;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using REPOLib.Modules;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[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]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DeathHeadHopperFix
{
	[BepInPlugin("AdrenSnyder.DeathHeadHopperFix", "Death Head Hopper - Fix", "0.2.8")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private const string TargetAssemblyName = "DeathHeadHopper";

		private Harmony? _harmony;

		private bool _patched;

		private bool _patchAttempted;

		private Assembly? _targetAssembly;

		private static ManualLogSource? _log;

		internal static Plugin? Instance { get; private set; }

		private void Awake()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			Instance = this;
			_log = ((BaseUnityPlugin)this).Logger;
			ConfigManager.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			WarnUnsafeDebugFlagsInRelease();
			_harmony = new Harmony("AdrenSnyder.DeathHeadHopperFix");
			DhhPatchRegistryModule.Initialize(((BaseUnityPlugin)this).Logger);
			if (FeatureFlags.DebugLogging)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[Fix:StartupDiag] Fix Harmony.PatchAll begin.");
			}
			try
			{
				_harmony.PatchAll(typeof(Plugin).Assembly);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[Fix:StartupDiag] Fix Harmony.PatchAll failed.");
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
				throw;
			}
			if (FeatureFlags.DebugLogging)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[Fix:StartupDiag] Fix Harmony.PatchAll complete.");
			}
			DHHApiGuardModule.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;
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

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

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

		private void TryPatchIfTargetAssembly(Assembly asm)
		{
			if (_patched || _patchAttempted || asm == null)
			{
				return;
			}
			string name = asm.GetName().Name;
			if (!string.Equals(name, "DeathHeadHopper", StringComparison.OrdinalIgnoreCase))
			{
				return;
			}
			_patchAttempted = true;
			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.");
				}
				DHHStatsBootstrapModule.Apply(harmony, asm, _log);
				PrefabModule.Apply(harmony, asm, _log);
				AudioModule.Apply(harmony, asm, _log);
				bool flag = DHHShopVanillaPoolModule.Apply(harmony, asm, _log);
				_targetAssembly = asm;
				DHHApiGuardModule.Apply(harmony, asm);
				BatteryJumpPatchModule.Apply(harmony, _log);
				JumpForceModule.Apply(harmony, _log);
				ChargeAbilityTuningModule.Apply(harmony, asm);
				ChargeHoldReleaseModule.Apply(harmony, asm, _log);
				InputModule.Apply(harmony, asm, _log);
				AbilityModule.ApplyAbilitySpotLabelOverlay(harmony);
				AbilityModule.ApplyAbilityManagerHooks(harmony);
				_patched = true;
				if (flag)
				{
					ManualLogSource? log2 = _log;
					if (log2 != null)
					{
						log2.LogInfo((object)"Patches applied successfully.");
					}
				}
				else
				{
					ManualLogSource? log3 = _log;
					if (log3 != null)
					{
						log3.LogWarning((object)"DHH patch setup completed with incomplete shop hook registration; see [Fix:Shop] messages.");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? log4 = _log;
				if (log4 != null)
				{
					log4.LogError((object)ex);
				}
			}
		}

		private void WarnUnsafeDebugFlagsInRelease()
		{
			if (!Debug.isDebugBuild && (InternalDebugFlags.DisableBatteryModule || InternalDebugFlags.DisableAbilityPatches || InternalDebugFlags.DisableSpectateChecks))
			{
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogWarning((object)("[DebugSafety] Internal debug bypass flags are enabled in a non-debug build. " + $"DisableBatteryModule={InternalDebugFlags.DisableBatteryModule}, " + $"DisableAbilityPatches={InternalDebugFlags.DisableAbilityPatches}, " + $"DisableSpectateChecks={InternalDebugFlags.DisableSpectateChecks}"));
				}
			}
		}
	}
}
namespace DeathHeadHopperFix.Modules.Utilities
{
	internal static class LogLimiter
	{
		public const int DefaultFrameInterval = 240;

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

		public static bool ShouldLog(string key, int frameInterval = 240)
		{
			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 NetworkProtocol
	{
		internal const string ModId = "DeathHeadHopperFix";

		internal const int ProtocolVersion = 1;

		internal const string RoomKeyPrefix = "DeathHeadHopperFix.Room.";

		internal static string BuildRoomKey(string localKey)
		{
			return string.IsNullOrWhiteSpace(localKey) ? "DeathHeadHopperFix.Room." : ("DeathHeadHopperFix.Room." + localKey.Trim());
		}
	}
	internal readonly struct NetworkEnvelope
	{
		internal string ModId { get; }

		internal int ProtocolVersion { get; }

		internal string MessageType { get; }

		internal int MessageSeq { get; }

		internal object? Payload { get; }

		internal NetworkEnvelope(string modId, int protocolVersion, string messageType, int messageSeq, object? payload)
		{
			ModId = (string.IsNullOrWhiteSpace(modId) ? string.Empty : modId.Trim());
			ProtocolVersion = protocolVersion;
			MessageType = (string.IsNullOrWhiteSpace(messageType) ? string.Empty : messageType.Trim());
			MessageSeq = messageSeq;
			Payload = payload;
		}

		internal object?[] ToEventPayload()
		{
			return new object[5] { ModId, ProtocolVersion, MessageType, MessageSeq, Payload };
		}

		internal bool IsExpectedSource()
		{
			return ModId == "DeathHeadHopperFix" && ProtocolVersion == 1 && !string.IsNullOrWhiteSpace(MessageType);
		}

		internal static bool TryParse(object? customData, out NetworkEnvelope envelope)
		{
			envelope = default(NetworkEnvelope);
			if (!(customData is object[] array) || array.Length < 5)
			{
				return false;
			}
			if (array[0] is string modId && array[1] is int protocolVersion && array[2] is string messageType)
			{
				object obj = array[3];
				int messageSeq = default(int);
				int num;
				if (obj is int)
				{
					messageSeq = (int)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				if (num != 0)
				{
					envelope = new NetworkEnvelope(modId, protocolVersion, messageType, messageSeq, array[4]);
					return true;
				}
			}
			return false;
		}
	}
	internal static class PhotonEventCodes
	{
		internal const byte ConfigSync = 79;
	}
	internal static class SpectateContextHelper
	{
		private static readonly FieldInfo? s_spectatePlayerField = AccessTools.Field(typeof(SpectateCamera), "player");

		private static readonly FieldInfo? s_playerDeathHeadSpectatedField = AccessTools.Field(typeof(PlayerDeathHead), "spectated");

		internal static bool IsSpectatingLocalPlayerTarget()
		{
			SpectateCamera instance = SpectateCamera.instance;
			PlayerAvatar instance2 = PlayerAvatar.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || s_spectatePlayerField == null)
			{
				return false;
			}
			object? value = s_spectatePlayerField.GetValue(instance);
			PlayerAvatar val = (PlayerAvatar)((value is PlayerAvatar) ? value : null);
			return (Object)(object)val != (Object)null && val == instance2;
		}

		internal static bool IsSpectatingLocalDeathHead()
		{
			SpectateCamera instance = SpectateCamera.instance;
			if ((Object)(object)instance == (Object)null || !instance.CheckState((State)2))
			{
				return false;
			}
			PlayerDeathHead val = PlayerController.instance?.playerAvatarScript?.playerDeathHead;
			if ((Object)(object)val == (Object)null || s_playerDeathHeadSpectatedField == null)
			{
				return false;
			}
			return s_playerDeathHeadSpectatedField.GetValue(val) as bool? == true;
		}

		internal static bool IsLocalDeathHeadSpectated()
		{
			PlayerDeathHead val = PlayerController.instance?.playerAvatarScript?.playerDeathHead;
			if ((Object)(object)val == (Object)null || s_playerDeathHeadSpectatedField == null)
			{
				return false;
			}
			return s_playerDeathHeadSpectatedField.GetValue(val) as bool? == true;
		}
	}
}
namespace DeathHeadHopperFix.Modules.Stamina
{
	internal sealed class StaminaRechargeModule : MonoBehaviour
	{
		private DeathHeadController? _controller;

		private bool _isOwner;

		private float _rechargeAccumulator;

		private Rigidbody? _rb;

		private void Awake()
		{
			_controller = ((Component)this).GetComponent<DeathHeadController>();
			if ((Object)(object)_controller == (Object)null)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			PhotonView component = ((Component)this).GetComponent<PhotonView>();
			_isOwner = !SemiFunc.IsMultiplayer() || ((Object)(object)component != (Object)null && component.IsMine);
			_rb = ((Component)this).GetComponent<Rigidbody>();
		}

		private void Update()
		{
			if (!_isOwner || (Object)(object)_controller == (Object)null)
			{
				return;
			}
			if (!FeatureFlags.RechargeWithStamina)
			{
				_rechargeAccumulator = 0f;
				return;
			}
			_rechargeAccumulator += Time.deltaTime;
			if (!(_rechargeAccumulator < FeatureFlags.RechargeTickInterval))
			{
				if (!FeatureFlags.RechargeStaminaOnlyStationary || IsHeadStationary())
				{
					DHHBatteryHelper.RechargeDhhAbilityEnergy(_controller, _rechargeAccumulator);
				}
				_rechargeAccumulator = 0f;
			}
		}

		private bool IsHeadStationary()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			int result;
			if (!((Object)(object)_rb == (Object)null))
			{
				Vector3 linearVelocity = _rb.linearVelocity;
				result = ((((Vector3)(ref linearVelocity)).sqrMagnitude < FeatureFlags.HeadStationaryVelocitySqrThreshold) ? 1 : 0);
			}
			else
			{
				result = 1;
			}
			return (byte)result != 0;
		}
	}
}
namespace DeathHeadHopperFix.Modules.Gameplay.Stun
{
	internal static class ChargeHoldReleaseModule
	{
		private sealed class ChargeHoldState
		{
			public float StartTime;

			public bool IsHolding;

			public float LaunchScale = 1f;

			public float ChargingStartTime;

			public float RestingTime;
		}

		private sealed class ChargeMotionDiagnosticTrace
		{
			public float LastSampleTime = float.NegativeInfinity;

			public int SampleCount;

			public bool SampleLimitLogged;

			public bool HasPreviousSamplePosition;

			public Vector3 PreviousHeadSamplePosition;

			public Vector3 PreviousTumbleSamplePosition;

			public ChargeHandler? ChargeHandler;

			public PhysGrabObject? PhysGrabObject;

			public int PhysGrabSampleCount;

			public float LastPhysGrabSampleTime = float.NegativeInfinity;

			public bool PhysGrabSampleLimitLogged;

			public int MovePositionLogCount;

			public float LastMovePositionLogTime = float.NegativeInfinity;

			public bool MovePositionLimitLogged;

			public int RigidbodyPositionLogCount;

			public float LastRigidbodyPositionLogTime = float.NegativeInfinity;

			public bool RigidbodyPositionLimitLogged;

			public int TransformPositionLogCount;

			public float LastTransformPositionLogTime = float.NegativeInfinity;

			public bool TransformPositionLimitLogged;
		}

		private struct ChargeMotionSnapshot
		{
			public bool Enabled;

			public int HandlerId;

			public int SampleNumber;

			public ChargeState State;

			public int HeadRigidbodyId;

			public Vector3 HeadPosition;

			public Vector3 HeadDeltaSincePreviousSample;

			public Vector3 HeadVelocity;

			public bool HeadIsKinematic;

			public Vector3 TargetStartOffset;

			public Vector3 CurrentStartOffset;

			public Vector3 StartVelocity;

			public Vector3 ChargeDirection;

			public float ChargeStrength;

			public float WindupTimer;

			public float ChargeTimer;

			public int BounceCount;

			public int EnemiesHit;

			public bool IsColliding;

			public bool IsGrabbed;

			public bool IsFrozen;

			public int TumbleRigidbodyId;

			public Vector3 TumblePosition;

			public Vector3 TumbleDeltaSincePreviousSample;

			public Vector3 TumbleVelocity;

			public bool TumbleIsKinematic;
		}

		private struct PhysGrabMotionSnapshot
		{
			public bool Enabled;

			public ChargeHandler? ChargeHandler;

			public int HandlerId;

			public int SampleNumber;

			public ChargeState ChargeState;

			public int PhysGrabObjectId;

			public int RigidbodyId;

			public Vector3 TransformPosition;

			public Vector3 RigidbodyPosition;

			public Vector3 LinearVelocity;

			public bool IsKinematic;

			public bool Frozen;

			public float FrozenTimer;

			public Vector3 FrozenPosition;

			public Vector3 FrozenVelocity;

			public bool Grabbed;

			public int PlayerGrabberCount;
		}

		[HarmonyPatch(typeof(ChargeHandler), "StartWindup")]
		private static class ChargeHandlerStartWindupPatch
		{
			[HarmonyPrepare]
			private static bool Prepare()
			{
				return s_chargeGroundPatchReady;
			}

			[HarmonyPrefix]
			private static void Prefix(ChargeHandler __instance, out bool __state)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Invalid comparison between Unknown and I4
				__state = (Object)(object)__instance != (Object)null && (int)__instance.State == 0;
			}

			[HarmonyPostfix]
			private static void Postfix(ChargeHandler __instance, bool __state)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Invalid comparison between Unknown and I4
				if (__state && !((Object)(object)__instance == (Object)null) && (int)__instance.State == 1)
				{
					ApplyGroundOffsetGuard(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(ChargeHandler), "FixedUpdate")]
		private static class ChargeHandlerMotionDiagnosticPatch
		{
			[HarmonyPrepare]
			private static bool Prepare()
			{
				return s_chargeMotionDiagnosticPatchReady;
			}

			[HarmonyPrefix]
			private static void Prefix(ChargeHandler __instance, out ChargeMotionSnapshot __state)
			{
				__state = default(ChargeMotionSnapshot);
				try
				{
					__state = BeginChargeMotionDiagnosticSample(__instance);
				}
				catch (Exception exception)
				{
					LogChargeMotionDiagnosticFailure("FixedUpdate prefix", exception);
				}
			}

			[HarmonyPostfix]
			private static void Postfix(ChargeHandler __instance, ChargeMotionSnapshot __state)
			{
				if (!__state.Enabled || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				try
				{
					ChargeMotionSnapshot chargeMotionSnapshot = CaptureChargeMotionSnapshot(__instance, __state.HandlerId);
					LogChargeMotionSample(__state, chargeMotionSnapshot);
					CompleteChargeMotionDiagnosticSample(chargeMotionSnapshot);
				}
				catch (Exception exception)
				{
					LogChargeMotionDiagnosticFailure("FixedUpdate postfix", exception);
				}
			}
		}

		[HarmonyPatch(typeof(PhysGrabObject), "FixedUpdate")]
		private static class PhysGrabObjectMotionDiagnosticPatch
		{
			[HarmonyPrepare]
			private static bool Prepare()
			{
				return s_chargeMotionDiagnosticPatchReady;
			}

			[HarmonyPrefix]
			private static void Prefix(PhysGrabObject __instance, out PhysGrabMotionSnapshot __state)
			{
				__state = default(PhysGrabMotionSnapshot);
				try
				{
					__state = BeginPhysGrabMotionDiagnosticSample(__instance);
				}
				catch (Exception exception)
				{
					LogChargeMotionDiagnosticFailure("PhysGrabObject.FixedUpdate prefix", exception);
				}
			}

			[HarmonyPostfix]
			private static void Postfix(PhysGrabObject __instance, PhysGrabMotionSnapshot __state)
			{
				if (!__state.Enabled || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				try
				{
					PhysGrabMotionSnapshot after = CapturePhysGrabMotionSnapshot(__instance, __state.ChargeHandler, __state.HandlerId, __state.SampleNumber);
					LogPhysGrabMotionSample(__state, after);
				}
				catch (Exception exception)
				{
					LogChargeMotionDiagnosticFailure("PhysGrabObject.FixedUpdate postfix", exception);
				}
			}
		}

		[HarmonyPatch(typeof(Rigidbody), "MovePosition")]
		private static class RigidbodyMovePositionDiagnosticPatch
		{
			[HarmonyPrepare]
			private static bool Prepare()
			{
				return s_chargeMotionDiagnosticPatchReady;
			}

			[HarmonyPrefix]
			private static void Prefix(Rigidbody __instance, [HarmonyArgument(0)] Vector3 requestedPosition)
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					LogChargeRigidbodyPositionCommand(__instance, requestedPosition, "Rigidbody.MovePosition");
				}
				catch (Exception exception)
				{
					LogChargeMotionDiagnosticFailure("Rigidbody.MovePosition observer", exception);
				}
			}
		}

		[HarmonyPatch(typeof(Rigidbody), "set_position")]
		private static class RigidbodyPositionSetterDiagnosticPatch
		{
			[HarmonyPrepare]
			private static bool Prepare()
			{
				return s_chargeMotionDiagnosticPatchReady;
			}

			[HarmonyPrefix]
			private static void Prefix(Rigidbody __instance, [HarmonyArgument(0)] Vector3 requestedPosition)
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					LogChargeRigidbodyPositionCommand(__instance, requestedPosition, "Rigidbody.position");
				}
				catch (Exception exception)
				{
					LogChargeMotionDiagnosticFailure("Rigidbody.position observer", exception);
				}
			}
		}

		[HarmonyPatch(typeof(Transform), "set_position")]
		private static class TransformPositionSetterDiagnosticPatch
		{
			[HarmonyPrepare]
			private static bool Prepare()
			{
				return s_chargeMotionDiagnosticPatchReady;
			}

			[HarmonyPrefix]
			private static void Prefix(Transform __instance, [HarmonyArgument(0)] Vector3 requestedPosition)
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					LogChargeTransformPositionCommand(__instance, requestedPosition);
				}
				catch (Exception exception)
				{
					LogChargeMotionDiagnosticFailure("Transform.position observer", exception);
				}
			}
		}

		[HarmonyPatch(typeof(ChargeHandler), "StartCharge")]
		private static class ChargeHandlerStartChargeDiagnosticPatch
		{
			[HarmonyPrepare]
			private static bool Prepare()
			{
				return s_chargeMotionDiagnosticPatchReady;
			}

			[HarmonyPrefix]
			private static void Prefix(ChargeHandler __instance, out ChargeMotionSnapshot __state)
			{
				__state = default(ChargeMotionSnapshot);
				try
				{
					__state = (FeatureFlags.DebugLogging ? CaptureChargeMotionSnapshot(__instance, GetUnityObjectInstanceId((Object?)(object)__instance)) : default(ChargeMotionSnapshot));
				}
				catch (Exception exception)
				{
					LogChargeMotionDiagnosticFailure("StartCharge prefix", exception);
				}
			}

			[HarmonyPostfix]
			private static void Postfix(ChargeHandler __instance, ChargeMotionSnapshot __state)
			{
				if (!__state.Enabled || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				try
				{
					ChargeMotionSnapshot after = CaptureChargeMotionSnapshot(__instance, __state.HandlerId);
					LogChargeMotionEvent("start-charge", __state, after);
				}
				catch (Exception exception)
				{
					LogChargeMotionDiagnosticFailure("StartCharge postfix", exception);
				}
			}
		}

		[HarmonyPatch(typeof(ChargeHandler), "EndCharge")]
		private static class ChargeHandlerEndChargeDiagnosticPatch
		{
			[HarmonyPrepare]
			private static bool Prepare()
			{
				return s_chargeMotionDiagnosticPatchReady;
			}

			[HarmonyPrefix]
			private static void Prefix(ChargeHandler __instance, out ChargeMotionSnapshot __state)
			{
				__state = default(ChargeMotionSnapshot);
				try
				{
					__state = (FeatureFlags.DebugLogging ? CaptureChargeMotionSnapshot(__instance, GetUnityObjectInstanceId((Object?)(object)__instance)) : default(ChargeMotionSnapshot));
				}
				catch (Exception exception)
				{
					LogChargeMotionDiagnosticFailure("EndCharge prefix", exception);
				}
			}

			[HarmonyPostfix]
			private static void Postfix(ChargeHandler __instance, ChargeMotionSnapshot __state)
			{
				if (!__state.Enabled || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				try
				{
					ChargeMotionSnapshot after = CaptureChargeMotionSnapshot(__instance, __state.HandlerId);
					LogChargeMotionEvent("end-charge", __state, after);
					RemoveChargeMotionDiagnosticTrace(__instance);
				}
				catch (Exception exception)
				{
					LogChargeMotionDiagnosticFailure("EndCharge postfix", exception);
				}
			}
		}

		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 ChargeStrengthLogKey = "Fix:Charge.Strength";

		private const string ChargePermissiveFallbackLogKey = "Fix:Charge.PermissiveFallback";

		private const float RemoteReleaseCommandTag = -777f;

		private const float RemoteCancelCommandTag = -778f;

		private const float ChargeRestStopSeconds = 0.35f;

		private const float ChargeFailsafeSeconds = 10f;

		private const float ChargeRestVelocitySqrThreshold = 0.01f;

		private const float ChargeRestAngularVelocitySqrThreshold = 0.04f;

		private const float GroundContactProbeStartOffset = 0.02f;

		private const float GroundContactProbeDistance = 0.04f;

		private const float GroundContactMinimumNormalY = 0.5f;

		private const float ChargeMotionDiagnosticSampleInterval = 0.5f;

		private const int ChargeMotionDiagnosticMaxSamples = 24;

		private const float PositionCommandDiagnosticInterval = 0.15f;

		private const int PositionCommandDiagnosticMaxSamplesPerApi = 12;

		private static ManualLogSource? s_log;

		private static bool s_chargeGroundPatchReady;

		private static bool s_chargeMotionDiagnosticPatchReady;

		private static readonly Dictionary<int, ChargeHoldState> s_chargeHoldStates = new Dictionary<int, ChargeHoldState>();

		private static readonly Dictionary<int, ChargeMotionDiagnosticTrace> s_chargeMotionDiagnosticTraces = new Dictionary<int, ChargeMotionDiagnosticTrace>();

		private static readonly Dictionary<int, ChargeMotionDiagnosticTrace> s_chargeMotionDiagnosticPhysGrabTraces = new Dictionary<int, ChargeMotionDiagnosticTrace>();

		private static readonly Dictionary<int, ChargeMotionDiagnosticTrace> s_chargeMotionDiagnosticRigidbodyTraces = new Dictionary<int, ChargeMotionDiagnosticTrace>();

		private static readonly Dictionary<int, ChargeMotionDiagnosticTrace> s_chargeMotionDiagnosticTransformTraces = new Dictionary<int, ChargeMotionDiagnosticTrace>();

		private static float s_lastLocalHoldInputStartTime;

		private static bool s_localHoldUiActive;

		private static bool s_localHoldInputPending;

		internal static void Apply(Harmony harmony, Assembly asm, ManualLogSource? log)
		{
			s_log = log;
			s_chargeGroundPatchReady = true;
			harmony.CreateClassProcessor(typeof(ChargeHandlerStartWindupPatch)).Patch();
			if (FeatureFlags.DebugLogging)
			{
				s_chargeMotionDiagnosticPatchReady = true;
				harmony.CreateClassProcessor(typeof(ChargeHandlerMotionDiagnosticPatch)).Patch();
				harmony.CreateClassProcessor(typeof(PhysGrabObjectMotionDiagnosticPatch)).Patch();
				harmony.CreateClassProcessor(typeof(ChargeHandlerStartChargeDiagnosticPatch)).Patch();
				harmony.CreateClassProcessor(typeof(ChargeHandlerEndChargeDiagnosticPatch)).Patch();
				TryInstallChargePositionCommandDiagnosticPatch(harmony, typeof(RigidbodyMovePositionDiagnosticPatch), "Rigidbody.MovePosition");
				TryInstallChargePositionCommandDiagnosticPatch(harmony, typeof(RigidbodyPositionSetterDiagnosticPatch), "Rigidbody.position setter");
				TryInstallChargePositionCommandDiagnosticPatch(harmony, typeof(TransformPositionSetterDiagnosticPatch), "Transform.position setter");
			}
			PatchChargeHandlerDamageModeIfPossible(harmony, asm);
			PatchChargeAbilityHoldReleaseIfPossible(harmony, asm);
			PatchStunHandlerHoldScalingIfPossible(harmony, asm);
		}

		private static void TryInstallChargePositionCommandDiagnosticPatch(Harmony harmony, Type patchType, string targetDescription)
		{
			try
			{
				harmony.CreateClassProcessor(patchType).Patch();
			}
			catch (Exception ex)
			{
				ManualLogSource? obj = s_log;
				if (obj != null)
				{
					obj.LogWarning((object)("[Fix:ChargeMotion] Could not install the " + targetDescription + " observer; other charge diagnostics remain active. error=" + ex.GetType().Name + ": " + ex.Message));
				}
			}
		}

		private static void ApplyGroundOffsetGuard(ChargeHandler chargeHandler)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			Vector3 targetStartOffset = chargeHandler.targetStartOffset;
			bool flag = false;
			float num = 0f;
			bool? flag2 = null;
			try
			{
				DeathHeadController controller = chargeHandler.controller;
				Vector3? obj;
				if (controller == null)
				{
					obj = null;
				}
				else
				{
					CollisionHandler collisionHandler = controller.collisionHandler;
					obj = ((collisionHandler != null) ? collisionHandler.GetGroundPointDown() : ((Vector3?)null));
				}
				Vector3? val = obj;
				flag = val.HasValue;
				if (val.HasValue)
				{
					num = Vector3.Distance(val.Value, ((Component)chargeHandler).transform.position);
				}
				flag2 = HasTightGroundContact(chargeHandler);
				if ((!flag || Mathf.Approximately(num, 0f)) && flag2 == false)
				{
					chargeHandler.targetStartOffset = Vector3.zero;
				}
			}
			catch (Exception ex)
			{
				if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:ChargeGround.ProbeFailure", 600))
				{
					ManualLogSource? obj2 = s_log;
					if (obj2 != null)
					{
						obj2.LogWarning((object)("[Fix:ChargeGround] Ground probe failed; preserving vanilla offset. error=" + ex.GetType().Name + ": " + ex.Message));
					}
				}
			}
			if (FeatureFlags.DebugLogging)
			{
				ManualLogSource? obj3 = s_log;
				if (obj3 != null)
				{
					obj3.LogInfo((object)($"[Fix:ChargeGround] start-windup groundPointAvailable={flag} " + string.Format("groundDistance={0:F3} groundContact={1} ", num, flag2?.ToString() ?? "unknown") + "vanillaOffset=" + FormatVector(targetStartOffset) + " finalOffset=" + FormatVector(chargeHandler.targetStartOffset)));
				}
			}
		}

		private static bool? HasTightGroundContact(ChargeHandler chargeHandler)
		{
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			PlayerDeathHead val = chargeHandler.controller?.deathHead;
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Collider[] componentsInChildren = ((Component)val).GetComponentsInChildren<Collider>(true);
			Collider val2 = null;
			float num = float.PositiveInfinity;
			Collider[] array = componentsInChildren;
			foreach (Collider val3 in array)
			{
				if (!((Object)(object)val3 == (Object)null) && val3.enabled && ((Component)val3).gameObject.activeInHierarchy && !val3.isTrigger)
				{
					Bounds bounds = val3.bounds;
					float y = ((Bounds)(ref bounds)).min.y;
					if (!(y >= num))
					{
						val2 = val3;
						num = y;
					}
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			Bounds bounds2 = val2.bounds;
			Vector3 val4 = default(Vector3);
			((Vector3)(ref val4))..ctor(((Bounds)(ref bounds2)).center.x, ((Bounds)(ref bounds2)).min.y + 0.02f, ((Bounds)(ref bounds2)).center.z);
			int mask = LayerMask.GetMask(new string[1] { "Default" });
			RaycastHit[] array2 = Physics.RaycastAll(val4, Vector3.down, 0.04f, mask, (QueryTriggerInteraction)1);
			PhysGrabObject component = ((Component)val).GetComponent<PhysGrabObject>();
			RaycastHit[] array3 = array2;
			for (int j = 0; j < array3.Length; j++)
			{
				RaycastHit val5 = array3[j];
				Collider collider = ((RaycastHit)(ref val5)).collider;
				if (!((Object)(object)collider == (Object)null) && !(((RaycastHit)(ref val5)).normal.y < 0.5f) && !((Object)(object)((Component)collider).transform == (Object)(object)((Component)val).transform) && !((Component)collider).transform.IsChildOf(((Component)val).transform) && (!((Object)(object)component != (Object)null) || !((Object)(object)((Component)collider).GetComponentInParent<PhysGrabObject>() == (Object)(object)component)))
				{
					return true;
				}
			}
			return false;
		}

		private static string FormatVector(Vector3 value)
		{
			//IL_0006: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			return $"({value.x:F3},{value.y:F3},{value.z:F3})";
		}

		private static void BeginChargeMotionDiagnosticTrace(ChargeHandler chargeHandler)
		{
			int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)chargeHandler);
			if (FeatureFlags.DebugLogging && unityObjectInstanceId != 0)
			{
				if (!s_chargeMotionDiagnosticTraces.TryGetValue(unityObjectInstanceId, out ChargeMotionDiagnosticTrace value))
				{
					value = new ChargeMotionDiagnosticTrace();
					s_chargeMotionDiagnosticTraces[unityObjectInstanceId] = value;
				}
				value.ChargeHandler = chargeHandler;
				RegisterPhysGrabMotionDiagnosticTarget(value, unityObjectInstanceId);
			}
		}

		private static void RemoveChargeMotionDiagnosticTrace(ChargeHandler? chargeHandler)
		{
			if ((Object)(object)chargeHandler == (Object)null)
			{
				return;
			}
			int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)chargeHandler);
			if (unityObjectInstanceId != 0)
			{
				if (s_chargeMotionDiagnosticTraces.TryGetValue(unityObjectInstanceId, out ChargeMotionDiagnosticTrace value) && (Object)(object)value.PhysGrabObject != (Object)null)
				{
					int unityObjectInstanceId2 = GetUnityObjectInstanceId((Object?)(object)value.PhysGrabObject);
					RemoveDiagnosticTraceMapping(s_chargeMotionDiagnosticPhysGrabTraces, unityObjectInstanceId2, value);
					RemoveDiagnosticTraceMapping(s_chargeMotionDiagnosticRigidbodyTraces, GetUnityObjectInstanceId((Object?)(object)value.PhysGrabObject.rb), value);
					RemoveDiagnosticTraceMapping(s_chargeMotionDiagnosticTransformTraces, GetUnityObjectInstanceId((Object?)(object)((Component)value.PhysGrabObject).transform), value);
				}
				s_chargeMotionDiagnosticTraces.Remove(unityObjectInstanceId);
			}
		}

		private static void RemoveDiagnosticTraceMapping(Dictionary<int, ChargeMotionDiagnosticTrace> mappings, int instanceId, ChargeMotionDiagnosticTrace trace)
		{
			if (instanceId != 0 && mappings.TryGetValue(instanceId, out ChargeMotionDiagnosticTrace value) && trace == value)
			{
				mappings.Remove(instanceId);
			}
		}

		private static void RegisterPhysGrabMotionDiagnosticTarget(ChargeMotionDiagnosticTrace trace, int handlerId)
		{
			ChargeHandler chargeHandler = trace.ChargeHandler;
			if ((Object)(object)chargeHandler == (Object)null || handlerId == 0)
			{
				return;
			}
			PhysGrabObject val = (((Object)(object)chargeHandler.impactDetector != (Object)null) ? chargeHandler.impactDetector.physGrabObject : null);
			if (!((Object)(object)val == (Object)null))
			{
				trace.PhysGrabObject = val;
				int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)val);
				if (unityObjectInstanceId != 0)
				{
					s_chargeMotionDiagnosticPhysGrabTraces[unityObjectInstanceId] = trace;
				}
				int unityObjectInstanceId2 = GetUnityObjectInstanceId((Object?)(object)val.rb);
				if (unityObjectInstanceId2 != 0)
				{
					s_chargeMotionDiagnosticRigidbodyTraces[unityObjectInstanceId2] = trace;
				}
				int unityObjectInstanceId3 = GetUnityObjectInstanceId((Object?)(object)((Component)val).transform);
				if (unityObjectInstanceId3 != 0)
				{
					s_chargeMotionDiagnosticTransformTraces[unityObjectInstanceId3] = trace;
				}
			}
		}

		private static ChargeMotionSnapshot BeginChargeMotionDiagnosticSample(ChargeHandler? chargeHandler)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Invalid comparison between Unknown and I4
			//IL_0176: 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_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			if (!FeatureFlags.DebugLogging || (Object)(object)chargeHandler == (Object)null)
			{
				return default(ChargeMotionSnapshot);
			}
			int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)chargeHandler);
			if (unityObjectInstanceId == 0 || (int)chargeHandler.State == 0)
			{
				return default(ChargeMotionSnapshot);
			}
			if (!s_chargeMotionDiagnosticTraces.TryGetValue(unityObjectInstanceId, out ChargeMotionDiagnosticTrace value))
			{
				value = new ChargeMotionDiagnosticTrace();
				value.ChargeHandler = chargeHandler;
				s_chargeMotionDiagnosticTraces[unityObjectInstanceId] = value;
				RegisterPhysGrabMotionDiagnosticTarget(value, unityObjectInstanceId);
			}
			float time = Time.time;
			if (value.SampleCount >= 24)
			{
				if (!value.SampleLimitLogged)
				{
					value.SampleLimitLogged = true;
					ManualLogSource? obj = s_log;
					if (obj != null)
					{
						obj.LogDebug((object)($"[Fix:ChargeMotion] sampling-limit reached handler={unityObjectInstanceId} " + $"samples={value.SampleCount} interval={0.5f:F1}s"));
					}
				}
				return default(ChargeMotionSnapshot);
			}
			if (time - value.LastSampleTime < 0.5f)
			{
				return default(ChargeMotionSnapshot);
			}
			value.LastSampleTime = time;
			value.SampleCount++;
			ChargeMotionSnapshot result = CaptureChargeMotionSnapshot(chargeHandler, unityObjectInstanceId);
			result.SampleNumber = value.SampleCount;
			if (value.HasPreviousSamplePosition)
			{
				result.HeadDeltaSincePreviousSample = result.HeadPosition - value.PreviousHeadSamplePosition;
				result.TumbleDeltaSincePreviousSample = result.TumblePosition - value.PreviousTumbleSamplePosition;
			}
			return result;
		}

		private static void CompleteChargeMotionDiagnosticSample(ChargeMotionSnapshot snapshot)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (snapshot.Enabled && s_chargeMotionDiagnosticTraces.TryGetValue(snapshot.HandlerId, out ChargeMotionDiagnosticTrace value))
			{
				value.PreviousHeadSamplePosition = snapshot.HeadPosition;
				value.PreviousTumbleSamplePosition = snapshot.TumblePosition;
				value.HasPreviousSamplePosition = true;
			}
		}

		private static PhysGrabMotionSnapshot BeginPhysGrabMotionDiagnosticSample(PhysGrabObject? physGrabObject)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Invalid comparison between Unknown and I4
			if (!FeatureFlags.DebugLogging || (Object)(object)physGrabObject == (Object)null)
			{
				return default(PhysGrabMotionSnapshot);
			}
			int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)physGrabObject);
			if (unityObjectInstanceId == 0 || !s_chargeMotionDiagnosticPhysGrabTraces.TryGetValue(unityObjectInstanceId, out ChargeMotionDiagnosticTrace value) || (Object)(object)value.ChargeHandler == (Object)null || (int)value.ChargeHandler.State == 0)
			{
				return default(PhysGrabMotionSnapshot);
			}
			float time = Time.time;
			if (value.PhysGrabSampleCount >= 24)
			{
				if (!value.PhysGrabSampleLimitLogged)
				{
					value.PhysGrabSampleLimitLogged = true;
					ManualLogSource? obj = s_log;
					if (obj != null)
					{
						obj.LogDebug((object)($"[Fix:ChargeMotion] PhysGrabObject sampling-limit reached handler={GetUnityObjectInstanceId((Object?)(object)value.ChargeHandler)} " + $"samples={value.PhysGrabSampleCount} interval={0.5f:F1}s"));
					}
				}
				return default(PhysGrabMotionSnapshot);
			}
			if (time - value.LastPhysGrabSampleTime < 0.5f)
			{
				return default(PhysGrabMotionSnapshot);
			}
			value.LastPhysGrabSampleTime = time;
			value.PhysGrabSampleCount++;
			return CapturePhysGrabMotionSnapshot(physGrabObject, value.ChargeHandler, GetUnityObjectInstanceId((Object?)(object)value.ChargeHandler), value.PhysGrabSampleCount);
		}

		private static PhysGrabMotionSnapshot CapturePhysGrabMotionSnapshot(PhysGrabObject? physGrabObject, ChargeHandler? chargeHandler, int handlerId, int sampleNumber)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			if (!FeatureFlags.DebugLogging || (Object)(object)physGrabObject == (Object)null || (Object)(object)chargeHandler == (Object)null || handlerId == 0 || (Object)(object)physGrabObject.rb == (Object)null)
			{
				return default(PhysGrabMotionSnapshot);
			}
			return new PhysGrabMotionSnapshot
			{
				Enabled = true,
				ChargeHandler = chargeHandler,
				HandlerId = handlerId,
				SampleNumber = sampleNumber,
				ChargeState = chargeHandler.State,
				PhysGrabObjectId = GetUnityObjectInstanceId((Object?)(object)physGrabObject),
				RigidbodyId = GetUnityObjectInstanceId((Object?)(object)physGrabObject.rb),
				TransformPosition = ((Component)physGrabObject).transform.position,
				RigidbodyPosition = physGrabObject.rb.position,
				LinearVelocity = physGrabObject.rb.linearVelocity,
				IsKinematic = physGrabObject.rb.isKinematic,
				Frozen = physGrabObject.frozen,
				FrozenTimer = physGrabObject.frozenTimer,
				FrozenPosition = physGrabObject.frozenPosition,
				FrozenVelocity = physGrabObject.frozenVelocity,
				Grabbed = physGrabObject.grabbed,
				PlayerGrabberCount = ((physGrabObject.playerGrabbing != null) ? physGrabObject.playerGrabbing.Count : 0)
			};
		}

		private static void LogPhysGrabMotionSample(PhysGrabMotionSnapshot before, PhysGrabMotionSnapshot after)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			if (before.Enabled && after.Enabled)
			{
				ManualLogSource? obj = s_log;
				if (obj != null)
				{
					obj.LogDebug((object)($"[Fix:ChargeMotion] physgrab-sample={before.SampleNumber} handler={before.HandlerId} " + $"state={before.ChargeState}->{after.ChargeState} physGrab={before.PhysGrabObjectId} rb={before.RigidbodyId} " + "transformPos=" + FormatVector(before.TransformPosition) + "->" + FormatVector(after.TransformPosition) + " rbPos=" + FormatVector(before.RigidbodyPosition) + "->" + FormatVector(after.RigidbodyPosition) + " fixedTransformDelta=" + FormatVector(after.TransformPosition - before.TransformPosition) + " fixedRbDelta=" + FormatVector(after.RigidbodyPosition - before.RigidbodyPosition) + " velocity=" + FormatVector(before.LinearVelocity) + "->" + FormatVector(after.LinearVelocity) + " " + $"kinematic={before.IsKinematic}->{after.IsKinematic} frozen={before.Frozen}->{after.Frozen} " + $"frozenTimer={before.FrozenTimer:F2}->{after.FrozenTimer:F2} " + "frozenPosition=" + FormatVector(before.FrozenPosition) + "->" + FormatVector(after.FrozenPosition) + " frozenVelocity=" + FormatVector(before.FrozenVelocity) + "->" + FormatVector(after.FrozenVelocity) + " " + $"grabbed={before.Grabbed}->{after.Grabbed} playerGrabbers={before.PlayerGrabberCount}->{after.PlayerGrabberCount}"));
				}
			}
		}

		private static void LogChargeRigidbodyPositionCommand(Rigidbody? rigidbody, Vector3 requestedPosition, string api)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Invalid comparison between Unknown and I4
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			if (!FeatureFlags.DebugLogging || (Object)(object)rigidbody == (Object)null)
			{
				return;
			}
			int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)rigidbody);
			if (unityObjectInstanceId != 0 && s_chargeMotionDiagnosticRigidbodyTraces.TryGetValue(unityObjectInstanceId, out ChargeMotionDiagnosticTrace value) && !((Object)(object)value.ChargeHandler == (Object)null) && (int)value.ChargeHandler.State != 0)
			{
				Vector3 position = rigidbody.position;
				Vector3 val = requestedPosition - position;
				if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f) && TryAcquirePositionCommandLog(value, api))
				{
					LogChargePositionCommand(value, api, unityObjectInstanceId, position, requestedPosition, rigidbody);
				}
			}
		}

		private static void LogChargeTransformPositionCommand(Transform? transform, Vector3 requestedPosition)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Invalid comparison between Unknown and I4
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			if (!FeatureFlags.DebugLogging || (Object)(object)transform == (Object)null)
			{
				return;
			}
			int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)transform);
			if (unityObjectInstanceId != 0 && s_chargeMotionDiagnosticTransformTraces.TryGetValue(unityObjectInstanceId, out ChargeMotionDiagnosticTrace value) && !((Object)(object)value.ChargeHandler == (Object)null) && (int)value.ChargeHandler.State != 0)
			{
				Vector3 position = transform.position;
				Vector3 val = requestedPosition - position;
				if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f) && TryAcquirePositionCommandLog(value, "Transform.position"))
				{
					PhysGrabObject physGrabObject = value.PhysGrabObject;
					Rigidbody val2 = (((Object)(object)physGrabObject != (Object)null) ? physGrabObject.rb : null);
					LogChargePositionCommand(value, "Transform.position", ((Object)(object)val2 != (Object)null) ? GetUnityObjectInstanceId((Object?)(object)val2) : 0, position, requestedPosition, val2);
				}
			}
		}

		private static bool TryAcquirePositionCommandLog(ChargeMotionDiagnosticTrace trace, string api)
		{
			float time = Time.time;
			if (api == "Rigidbody.MovePosition")
			{
				if (trace.MovePositionLogCount >= 12)
				{
					if (!trace.MovePositionLimitLogged)
					{
						trace.MovePositionLimitLogged = true;
						ManualLogSource? obj = s_log;
						if (obj != null)
						{
							obj.LogDebug((object)("[Fix:ChargeMotion] position-command sampling-limit reached api=" + api + " " + $"handler={GetUnityObjectInstanceId((Object?)(object)trace.ChargeHandler)}"));
						}
					}
					return false;
				}
				if (time - trace.LastMovePositionLogTime < 0.15f)
				{
					return false;
				}
				trace.LastMovePositionLogTime = time;
				trace.MovePositionLogCount++;
				return true;
			}
			if (api == "Rigidbody.position")
			{
				if (trace.RigidbodyPositionLogCount >= 12)
				{
					if (!trace.RigidbodyPositionLimitLogged)
					{
						trace.RigidbodyPositionLimitLogged = true;
						ManualLogSource? obj2 = s_log;
						if (obj2 != null)
						{
							obj2.LogDebug((object)("[Fix:ChargeMotion] position-command sampling-limit reached api=" + api + " " + $"handler={GetUnityObjectInstanceId((Object?)(object)trace.ChargeHandler)}"));
						}
					}
					return false;
				}
				if (time - trace.LastRigidbodyPositionLogTime < 0.15f)
				{
					return false;
				}
				trace.LastRigidbodyPositionLogTime = time;
				trace.RigidbodyPositionLogCount++;
				return true;
			}
			if (trace.TransformPositionLogCount >= 12)
			{
				if (!trace.TransformPositionLimitLogged)
				{
					trace.TransformPositionLimitLogged = true;
					ManualLogSource? obj3 = s_log;
					if (obj3 != null)
					{
						obj3.LogDebug((object)("[Fix:ChargeMotion] position-command sampling-limit reached api=" + api + " " + $"handler={GetUnityObjectInstanceId((Object?)(object)trace.ChargeHandler)}"));
					}
				}
				return false;
			}
			if (time - trace.LastTransformPositionLogTime < 0.15f)
			{
				return false;
			}
			trace.LastTransformPositionLogTime = time;
			trace.TransformPositionLogCount++;
			return true;
		}

		private static void LogChargePositionCommand(ChargeMotionDiagnosticTrace trace, string api, int rigidbodyId, Vector3 currentPosition, Vector3 requestedPosition, Rigidbody? rigidbody)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			ChargeHandler chargeHandler = trace.ChargeHandler;
			if (!((Object)(object)chargeHandler == (Object)null))
			{
				PhysGrabObject physGrabObject = trace.PhysGrabObject;
				ManualLogSource? obj = s_log;
				if (obj != null)
				{
					obj.LogDebug((object)($"[Fix:ChargeMotion] position-command api={api} handler={GetUnityObjectInstanceId((Object?)(object)chargeHandler)} " + $"state={chargeHandler.State} physGrab={(((Object)(object)physGrabObject != (Object)null) ? GetUnityObjectInstanceId((Object?)(object)physGrabObject) : 0)} " + $"rb={rigidbodyId} requested={FormatVector(requestedPosition)} " + "current=" + FormatVector(currentPosition) + " delta=" + FormatVector(requestedPosition - currentPosition) + " velocity=" + FormatVector(((Object)(object)rigidbody != (Object)null) ? rigidbody.linearVelocity : Vector3.zero) + " " + $"kinematic={(Object)(object)rigidbody != (Object)null && rigidbody.isKinematic} " + $"frozen={(Object)(object)physGrabObject != (Object)null && physGrabObject.frozen} " + $"grabbed={(Object)(object)physGrabObject != (Object)null && physGrabObject.grabbed}"));
				}
			}
		}

		private static ChargeMotionSnapshot CaptureChargeMotionSnapshot(ChargeHandler? chargeHandler, int handlerId)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			if (!FeatureFlags.DebugLogging || (Object)(object)chargeHandler == (Object)null || handlerId == 0)
			{
				return default(ChargeMotionSnapshot);
			}
			Rigidbody rb = chargeHandler.rb;
			DeathHeadController controller = chargeHandler.controller;
			Rigidbody val = controller?.deathHead?.playerAvatar?.tumble?.rb;
			PhysGrabObject val2 = (((Object)(object)chargeHandler.impactDetector != (Object)null) ? chargeHandler.impactDetector.physGrabObject : null);
			return new ChargeMotionSnapshot
			{
				Enabled = true,
				HandlerId = handlerId,
				State = chargeHandler.State,
				HeadRigidbodyId = GetUnityObjectInstanceId((Object?)(object)rb),
				HeadPosition = (((Object)(object)rb != (Object)null) ? rb.position : ((Component)chargeHandler).transform.position),
				HeadVelocity = (((Object)(object)rb != (Object)null) ? rb.linearVelocity : Vector3.zero),
				HeadIsKinematic = ((Object)(object)rb != (Object)null && rb.isKinematic),
				TargetStartOffset = chargeHandler.targetStartOffset,
				CurrentStartOffset = chargeHandler.currentStartOffset,
				StartVelocity = chargeHandler.startVelocity,
				ChargeDirection = chargeHandler.chargeDirection,
				ChargeStrength = chargeHandler.chargeStrength,
				WindupTimer = chargeHandler.windupTimer,
				ChargeTimer = chargeHandler.chargeTimer,
				BounceCount = ((chargeHandler.bounceColliders != null) ? chargeHandler.bounceColliders.Count : 0),
				EnemiesHit = chargeHandler.enemiesHit,
				IsColliding = (controller?.collisionHandler?.isColliding == true),
				IsGrabbed = ((Object)(object)val2 != (Object)null && val2.grabbed),
				IsFrozen = ((Object)(object)val2 != (Object)null && val2.frozen),
				TumbleRigidbodyId = (((Object)(object)val != (Object)null) ? GetUnityObjectInstanceId((Object?)(object)val) : 0),
				TumblePosition = (((Object)(object)val != (Object)null) ? val.position : Vector3.zero),
				TumbleVelocity = (((Object)(object)val != (Object)null) ? val.linearVelocity : Vector3.zero),
				TumbleIsKinematic = ((Object)(object)val != (Object)null && val.isKinematic)
			};
		}

		private static void LogChargeMotionSample(ChargeMotionSnapshot before, ChargeMotionSnapshot after)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: 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_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
			if (before.Enabled && after.Enabled)
			{
				ChargeHoldState value;
				bool flag = s_chargeHoldStates.TryGetValue(before.HandlerId, out value) && value.IsHolding;
				string text = $"[Fix:ChargeMotion] sample={before.SampleNumber} handler={before.HandlerId} " + $"held={flag} state={before.State}->{after.State} " + $"headRB={before.HeadRigidbodyId} pos={FormatVector(before.HeadPosition)}->{FormatVector(after.HeadPosition)} " + "fixedDelta=" + FormatVector(after.HeadPosition - before.HeadPosition) + " sinceSampleDelta=" + FormatVector(before.HeadDeltaSincePreviousSample) + " vel=" + FormatVector(before.HeadVelocity) + "->" + FormatVector(after.HeadVelocity) + " " + $"kinematic={before.HeadIsKinematic}->{after.HeadIsKinematic} " + "targetOffset=" + FormatVector(before.TargetStartOffset) + "->" + FormatVector(after.TargetStartOffset) + " currentOffset=" + FormatVector(before.CurrentStartOffset) + "->" + FormatVector(after.CurrentStartOffset) + " startVelocity=" + FormatVector(before.StartVelocity) + "->" + FormatVector(after.StartVelocity) + " chargeDirection=" + FormatVector(before.ChargeDirection) + "->" + FormatVector(after.ChargeDirection) + " " + $"strength={before.ChargeStrength:F2}->{after.ChargeStrength:F2} " + $"windupTimer={before.WindupTimer:F2}->{after.WindupTimer:F2} " + $"chargeTimer={before.ChargeTimer:F2}->{after.ChargeTimer:F2} " + $"bounces={before.BounceCount}->{after.BounceCount} enemiesHit={before.EnemiesHit}->{after.EnemiesHit} " + $"colliding={before.IsColliding}->{after.IsColliding} grabbed={before.IsGrabbed}->{after.IsGrabbed} " + $"frozen={before.IsFrozen}->{after.IsFrozen} " + $"tumbleRB={before.TumbleRigidbodyId}->{after.TumbleRigidbodyId} " + "tumblePos=" + FormatVector(before.TumblePosition) + "->" + FormatVector(after.TumblePosition) + " tumbleSinceSampleDelta=" + FormatVector(before.TumbleDeltaSincePreviousSample) + " tumbleVel=" + FormatVector(before.TumbleVelocity) + "->" + FormatVector(after.TumbleVelocity) + " " + $"tumbleKinematic={before.TumbleIsKinematic}->{after.TumbleIsKinematic}";
				ManualLogSource? obj = s_log;
				if (obj != null)
				{
					obj.LogDebug((object)text);
				}
			}
		}

		private static void LogChargeMotionEvent(string eventName, ChargeHandler? chargeHandler)
		{
			if (!FeatureFlags.DebugLogging)
			{
				return;
			}
			try
			{
				int num = (((Object)(object)chargeHandler != (Object)null) ? GetUnityObjectInstanceId((Object?)(object)chargeHandler) : 0);
				ChargeMotionSnapshot chargeMotionSnapshot = CaptureChargeMotionSnapshot(chargeHandler, num);
				if (!chargeMotionSnapshot.Enabled)
				{
					ManualLogSource? obj = s_log;
					if (obj != null)
					{
						obj.LogDebug((object)("[Fix:ChargeMotion] event=" + eventName + " handler=unavailable"));
					}
				}
				else
				{
					ChargeHoldState value;
					bool isHolding = s_chargeHoldStates.TryGetValue(num, out value) && value.IsHolding;
					LogChargeMotionEvent(eventName, chargeMotionSnapshot, chargeMotionSnapshot, isHolding);
				}
			}
			catch (Exception exception)
			{
				LogChargeMotionDiagnosticFailure("event " + eventName, exception);
			}
		}

		private static void LogChargeMotionEvent(string eventName, ChargeMotionSnapshot before, ChargeMotionSnapshot after)
		{
			ChargeHoldState value;
			bool isHolding = s_chargeHoldStates.TryGetValue(before.HandlerId, out value) && value.IsHolding;
			LogChargeMotionEvent(eventName, before, after, isHolding);
		}

		private static void LogChargeMotionEvent(string eventName, ChargeMotionSnapshot before, ChargeMotionSnapshot after, bool isHolding)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			if (FeatureFlags.DebugLogging && before.Enabled && after.Enabled)
			{
				ManualLogSource? obj = s_log;
				if (obj != null)
				{
					obj.LogDebug((object)($"[Fix:ChargeMotion] event={eventName} handler={before.HandlerId} held={isHolding} " + $"state={before.State}->{after.State} headRB={before.HeadRigidbodyId} " + "pos=" + FormatVector(before.HeadPosition) + "->" + FormatVector(after.HeadPosition) + " vel=" + FormatVector(before.HeadVelocity) + "->" + FormatVector(after.HeadVelocity) + " " + $"kinematic={before.HeadIsKinematic}->{after.HeadIsKinematic} " + "targetOffset=" + FormatVector(before.TargetStartOffset) + "->" + FormatVector(after.TargetStartOffset) + " currentOffset=" + FormatVector(before.CurrentStartOffset) + "->" + FormatVector(after.CurrentStartOffset) + " startVelocity=" + FormatVector(before.StartVelocity) + "->" + FormatVector(after.StartVelocity) + " chargeDirection=" + FormatVector(before.ChargeDirection) + "->" + FormatVector(after.ChargeDirection) + " " + $"strength={before.ChargeStrength:F2}->{after.ChargeStrength:F2} " + $"windupTimer={before.WindupTimer:F2}->{after.WindupTimer:F2} " + $"chargeTimer={before.ChargeTimer:F2}->{after.ChargeTimer:F2} " + $"bounces={before.BounceCount}->{after.BounceCount} enemiesHit={before.EnemiesHit}->{after.EnemiesHit} " + $"colliding={before.IsColliding}->{after.IsColliding} grabbed={before.IsGrabbed}->{after.IsGrabbed} " + $"frozen={before.IsFrozen}->{after.IsFrozen} tumbleRB={before.TumbleRigidbodyId}->{after.TumbleRigidbodyId} " + "tumblePos=" + FormatVector(before.TumblePosition) + "->" + FormatVector(after.TumblePosition) + " tumbleVel=" + FormatVector(before.TumbleVelocity) + "->" + FormatVector(after.TumbleVelocity) + " " + $"tumbleKinematic={before.TumbleIsKinematic}->{after.TumbleIsKinematic}"));
				}
			}
		}

		private static void LogChargeMotionDiagnosticFailure(string phase, Exception exception)
		{
			if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:ChargeMotion.DiagnosticFailure", 120))
			{
				ManualLogSource? obj = s_log;
				if (obj != null)
				{
					obj.LogWarning((object)("[Fix:ChargeMotion] Diagnostic failed during " + phase + "; gameplay continues. error=" + exception.GetType().Name + ": " + exception.Message));
				}
			}
		}

		private static void PatchChargeHandlerDamageModeIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Expected O, but got Unknown
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Expected O, but got Unknown
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Expected O, but got Unknown
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Expected O, but got Unknown
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Expected O, but got Unknown
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Expected O, but got Unknown
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Expected O, but got Unknown
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(ChargeHandler), "ChargeWindup", new Type[1] { typeof(Vector3) }, (Type[])null);
			MethodInfo method = typeof(ChargeHoldReleaseModule).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 method2 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_ChargeWindup_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);
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(ChargeHandler), "ResetState", Type.EmptyTypes, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.Method(typeof(ChargeHandler), "FixedUpdate", Type.EmptyTypes, (Type[])null);
			MethodInfo methodInfo4 = AccessTools.Method(typeof(ChargeHandler), "CancelCharge", Type.EmptyTypes, (Type[])null);
			MethodInfo methodInfo5 = AccessTools.Method(typeof(ChargeHandler), "EnemyHit", (Type[])null, (Type[])null);
			MethodInfo methodInfo6 = AccessTools.Method(typeof(ChargeHandler), "UpdateWindupDirection", new Type[1] { typeof(Vector3) }, (Type[])null);
			MethodInfo methodInfo7 = AccessTools.Method(typeof(ChargeHandler), "SyncChargeStateRPC", (Type[])null, (Type[])null);
			MethodInfo method3 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_SyncChargeStateRPC_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
			MethodInfo method4 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_ResetState_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
			if (methodInfo2 != null && method4 != null)
			{
				harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo8 = AccessTools.Method(typeof(ChargeHandler), "EndCharge", Type.EmptyTypes, (Type[])null);
			MethodInfo method5 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_EndCharge_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
			if (methodInfo8 != null && method5 != null)
			{
				harmony.Patch((MethodBase)methodInfo8, (HarmonyMethod)null, new HarmonyMethod(method5), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method6 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_FixedUpdate_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
			if (methodInfo3 != null && method6 != null)
			{
				harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(method6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method7 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_CancelCharge_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
			if (methodInfo4 != null && method7 != null)
			{
				harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(method7), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method8 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_EnemyHit_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
			if (methodInfo5 != null && method8 != null)
			{
				harmony.Patch((MethodBase)methodInfo5, new HarmonyMethod(method8), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method9 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_UpdateWindupDirection_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
			if (methodInfo6 != null && method9 != null)
			{
				harmony.Patch((MethodBase)methodInfo6, new HarmonyMethod(method9), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method10 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_SyncChargeStateRPC_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
			if (methodInfo7 != null)
			{
				if (method3 != null)
				{
					harmony.Patch((MethodBase)methodInfo7, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				if (method10 != null)
				{
					harmony.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, new HarmonyMethod(method10), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static bool ChargeHandler_ChargeWindup_Prefix(ChargeHandler __instance)
		{
			if ((Object)(object)__instance == (Object)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 void ChargeHandler_ChargeWindup_Postfix(ChargeHandler __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && IsChargeState(__instance, "Windup"))
			{
				int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)__instance);
				if (unityObjectInstanceId != 0)
				{
					ChargeHoldState orCreateChargeHoldState = GetOrCreateChargeHoldState(unityObjectInstanceId);
					orCreateChargeHoldState.StartTime = Time.time;
					orCreateChargeHoldState.IsHolding = true;
					orCreateChargeHoldState.LaunchScale = 1f;
					BeginChargeMotionDiagnosticTrace(__instance);
					LogChargeMotionEvent("windup-start", __instance);
					s_localHoldUiActive = true;
					AbilityModule.SetChargeSlotActivationProgress(0f);
				}
			}
		}

		private static void ChargeHandler_FixedUpdate_Postfix(ChargeHandler __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)__instance);
			if (unityObjectInstanceId == 0)
			{
				return;
			}
			if (SemiFunc.IsMasterClientOrSingleplayer() && IsChargeState(__instance, "Charging"))
			{
				if (!TryStopStalledCharge(__instance, unityObjectInstanceId))
				{
					TryStopAtBounceLimit(__instance);
				}
				return;
			}
			if (!IsLocalChargeHandler(__instance))
			{
				if (s_chargeHoldStates.TryGetValue(unityObjectInstanceId, out ChargeHoldState value))
				{
					if (!IsChargeState(__instance, "Windup"))
					{
						s_chargeHoldStates.Remove(unityObjectInstanceId);
					}
					else if (value.IsHolding)
					{
						__instance.windupTimer = Mathf.Max(0.01f, __instance.windupTime);
					}
				}
				return;
			}
			if (!s_chargeHoldStates.TryGetValue(unityObjectInstanceId, out ChargeHoldState value2))
			{
				if (!IsChargeState(__instance, "Windup") || !s_localHoldInputPending)
				{
					if (!s_localHoldUiActive)
					{
						AbilityModule.SetChargeSlotActivationProgress(0f);
					}
					return;
				}
				value2 = GetOrCreateChargeHoldState(unityObjectInstanceId);
				value2.StartTime = ((s_lastLocalHoldInputStartTime > 0f) ? s_lastLocalHoldInputStartTime : Time.time);
				value2.IsHolding = true;
				value2.LaunchScale = 1f;
				s_localHoldUiActive = true;
				AbilityModule.SetChargeSlotActivationProgress(0f);
			}
			if (!IsChargeState(__instance, "Windup"))
			{
				s_chargeHoldStates.Remove(unityObjectInstanceId);
				s_localHoldUiActive = false;
				AbilityModule.SetChargeSlotActivationProgress(0f);
				if (!s_localHoldUiActive)
				{
					AbilityModule.SetChargeSlotActivationProgress(0f);
				}
				return;
			}
			if (s_localHoldUiActive && value2.IsHolding)
			{
				float num = Mathf.Max(0.2f, FeatureFlags.ChargeAbilityHoldSeconds);
				float progress = Mathf.Clamp01((Time.time - value2.StartTime) / num);
				float minimumChargeReleaseScale = GetMinimumChargeReleaseScale(__instance);
				AbilityModule.SetChargeSlotActivationProgress(progress, minimumChargeReleaseScale);
			}
			else
			{
				if (!value2.IsHolding)
				{
					if (!s_localHoldUiActive)
					{
						AbilityModule.SetChargeSlotActivationProgress(0f);
					}
					if (!IsChargeState(__instance, "Windup"))
					{
						s_chargeHoldStates.Remove(unityObjectInstanceId);
					}
					return;
				}
				if (!IsChargeState(__instance, "Windup"))
				{
					s_chargeHoldStates.Remove(unityObjectInstanceId);
					AbilityModule.SetChargeSlotActivationProgress(0f);
					return;
				}
				float num2 = Mathf.Max(0.2f, FeatureFlags.ChargeAbilityHoldSeconds);
				float progress2 = Mathf.Clamp01((Time.time - value2.StartTime) / num2);
				float minimumChargeReleaseScale2 = GetMinimumChargeReleaseScale(__instance);
				AbilityModule.SetChargeSlotActivationProgress(progress2, minimumChargeReleaseScale2);
			}
			if (value2.IsHolding)
			{
				__instance.windupTimer = Mathf.Max(0.01f, __instance.windupTime);
			}
		}

		private static bool TryStopStalledCharge(ChargeHandler chargeHandler, int id)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			ChargeHoldState orCreateChargeHoldState = GetOrCreateChargeHoldState(id);
			if (orCreateChargeHoldState.ChargingStartTime <= 0f)
			{
				orCreateChargeHoldState.ChargingStartTime = Time.time;
			}
			DeathHeadController controller = chargeHandler.controller;
			Rigidbody rb = chargeHandler.rb;
			int num;
			if (controller != null && controller.collisionHandler?.isColliding == true && (Object)(object)rb != (Object)null)
			{
				Vector3 val = rb.linearVelocity;
				if (((Vector3)(ref val)).sqrMagnitude <= 0.01f)
				{
					val = rb.angularVelocity;
					num = ((((Vector3)(ref val)).sqrMagnitude <= 0.04f) ? 1 : 0);
					goto IL_00a0;
				}
			}
			num = 0;
			goto IL_00a0;
			IL_00a0:
			bool flag = (byte)num != 0;
			orCreateChargeHoldState.RestingTime = (flag ? (orCreateChargeHoldState.RestingTime + Time.fixedDeltaTime) : 0f);
			bool flag2 = orCreateChargeHoldState.RestingTime >= 0.35f;
			bool flag3 = Time.time - orCreateChargeHoldState.ChargingStartTime >= 10f;
			if (!flag2 && !flag3)
			{
				return false;
			}
			chargeHandler.EndCharge();
			if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:DHHCharge.StalledStop", 30))
			{
				string text = (flag2 ? "stable-rest" : "failsafe-timeout");
				ManualLogSource? obj = s_log;
				if (obj != null)
				{
					obj.LogDebug((object)("[Fix:DHHCharge] Ended authoritative Charging state (" + text + ")."));
				}
			}
			return true;
		}

		private static void TryStopAtBounceLimit(ChargeHandler chargeHandler)
		{
			int num = Mathf.Max(0, Mathf.CeilToInt(chargeHandler.maxBounces));
			if (num <= 0 || chargeHandler.bounceColliders.Count < num)
			{
				return;
			}
			if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:DHHCharge.BounceLimit", 5))
			{
				ManualLogSource? obj = s_log;
				if (obj != null)
				{
					obj.LogDebug((object)("[Fix:DHHCharge] Ending charge at bounce limit: " + $"bounces={chargeHandler.bounceColliders.Count} maxBounces={num} " + $"chargeTimer={chargeHandler.chargeTimer:F2}."));
				}
			}
			chargeHandler.EndCharge();
		}

		private static void PatchChargeAbilityHoldReleaseIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(ChargeAbility), "OnAbilityDown", Type.EmptyTypes, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(ChargeAbility), "OnAbilityUp", Type.EmptyTypes, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.Method(typeof(ChargeAbility), "OnAbilityCancel", Type.EmptyTypes, (Type[])null);
			if (methodInfo2 == null)
			{
				return;
			}
			MethodInfo method = typeof(ChargeHoldReleaseModule).GetMethod("ChargeAbility_OnAbilityUp_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
			if (!(method == null))
			{
				MethodInfo method2 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeAbility_OnAbilityDown_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo method3 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeAbility_OnAbilityCancel_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);
				}
				harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				if (methodInfo3 != null && method3 != null)
				{
					harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void PatchStunHandlerHoldScalingIfPossible(Harmony harmony, Assembly asm)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(StunHandler), "StunDuration");
			if (!(methodInfo == null))
			{
				MethodInfo method = typeof(ChargeHoldReleaseModule).GetMethod("StunHandler_StunDuration_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 ChargeHandler_CancelCharge_Postfix(ChargeHandler __instance)
		{
			LogChargeMotionEvent("cancel-charge", __instance);
			RemoveChargeMotionDiagnosticTrace(__instance);
			StopChargeWindupLoop(__instance);
			ClearChargeHoldState(__instance);
			SynchronizeFinalChargeState(__instance);
		}

		private static void ChargeHandler_SyncChargeStateRPC_Prefix(ChargeHandler __instance, ChargeState state)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			if (!((Object)(object)__instance == (Object)null) && (int)state != 1 && (int)state != 2)
			{
				LogChargeMotionEvent("sync-state-stop", __instance);
				RemoveChargeMotionDiagnosticTrace(__instance);
				StopChargeWindupLoop(__instance);
				ClearChargeHoldState(__instance);
			}
		}

		private static void ChargeHandler_SyncChargeStateRPC_Postfix(ChargeHandler __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !IsChargeState(__instance, "Windup") && !IsChargeState(__instance, "Charging"))
			{
				StopChargeWindupLoop(__instance);
				ClearChargeHoldState(__instance);
			}
		}

		private static bool ChargeHandler_EnemyHit_Prefix(ChargeHandler __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)__instance);
			if (unityObjectInstanceId == 0 || !s_chargeHoldStates.TryGetValue(unityObjectInstanceId, out ChargeHoldState value))
			{
				return true;
			}
			__instance.enemiesHit++;
			int abilityLevel = __instance.AbilityLevel;
			int num = Mathf.FloorToInt(EvaluateStatWithDiminishingReturns(1f, 0.5f, abilityLevel, 20, 0.9f).FinalValue);
			int num2 = Mathf.Max(1, Mathf.RoundToInt((float)num * Mathf.Clamp01(value.LaunchScale)));
			if (__instance.enemiesHit >= num2)
			{
				if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:DHHCharge.EnemyHitLimit", 5))
				{
					ManualLogSource? obj = s_log;
					if (obj != null)
					{
						obj.LogDebug((object)("[Fix:DHHCharge] Ending charge at enemy-hit limit: " + $"enemiesHit={__instance.enemiesHit} maxEnemies={num2} " + $"bounces={__instance.bounceColliders.Count} chargeTimer={__instance.chargeTimer:F2}."));
					}
				}
				__instance.EndCharge();
			}
			return false;
		}

		private static bool StunHandler_StunDuration_Prefix(StunHandler __instance, ref float __result)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			ChargeHandler chargeHandler = __instance.chargeHandler;
			if ((Object)(object)chargeHandler == (Object)null)
			{
				return true;
			}
			int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)chargeHandler);
			if (unityObjectInstanceId == 0 || !s_chargeHoldStates.TryGetValue(unityObjectInstanceId, out ChargeHoldState value))
			{
				return true;
			}
			int abilityLevel = chargeHandler.AbilityLevel;
			float num = 5f + 1f * (float)abilityLevel;
			__result = num * Mathf.Clamp01(value.LaunchScale);
			return false;
		}

		private static bool ChargeAbility_OnAbilityUp_Prefix()
		{
			return TryReleaseHeldCharge();
		}

		private static void ChargeAbility_OnAbilityDown_Postfix()
		{
			s_lastLocalHoldInputStartTime = Time.time;
			s_localHoldInputPending = true;
			AbilityModule.SetChargeSlotActivationProgress(0f);
			ChargeHandler localChargeHandler = GetLocalChargeHandler();
			LogChargeMotionEvent("input-down", localChargeHandler);
			if ((Object)(object)localChargeHandler != (Object)null && !IsChargeState(localChargeHandler, "Windup"))
			{
				ClearChargeHoldState(localChargeHandler);
			}
		}

		private static void ChargeAbility_OnAbilityCancel_Postfix()
		{
			s_localHoldInputPending = false;
			s_localHoldUiActive = false;
			AbilityModule.SetChargeSlotActivationProgress(0f);
			ChargeHandler localChargeHandler = GetLocalChargeHandler();
			LogChargeMotionEvent("input-cancel", localChargeHandler);
			if (!((Object)(object)localChargeHandler == (Object)null))
			{
				ClearChargeHoldState(localChargeHandler);
			}
		}

		private static bool TryReleaseHeldCharge()
		{
			ChargeHandler localChargeHandler = GetLocalChargeHandler();
			LogChargeMotionEvent("input-release", localChargeHandler);
			if ((Object)(object)localChargeHandler == (Object)null)
			{
				s_localHoldInputPending = false;
				s_localHoldUiActive = false;
				AbilityModule.SetChargeSlotActivationProgress(0f);
				return true;
			}
			if (!IsChargeState(localChargeHandler, "Windup"))
			{
				s_localHoldInputPending = false;
				s_localHoldUiActive = false;
				AbilityModule.SetChargeSlotActivationProgress(0f);
				return true;
			}
			int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)localChargeHandler);
			if (unityObjectInstanceId == 0)
			{
				s_localHoldInputPending = false;
				s_localHoldUiActive = false;
				AbilityModule.SetChargeSlotActivationProgress(0f);
				return true;
			}
			if (!s_chargeHoldStates.TryGetValue(unityObjectInstanceId, out ChargeHoldState value))
			{
				value = GetOrCreateChargeHoldState(unityObjectInstanceId);
				value.StartTime = ((s_lastLocalHoldInputStartTime > 0f) ? s_lastLocalHoldInputStartTime : Time.time);
				value.IsHolding = true;
				value.LaunchScale = 1f;
			}
			if (!value.IsHolding)
			{
				return true;
			}
			if (SemiFunc.IsMultiplayer() && !SemiFunc.IsMasterClientOrSingleplayer())
			{
				if (!ConfigSyncManager.IsRemoteHostFixCompatible())
				{
					value.IsHolding = false;
					value.LaunchScale = 0f;
					s_localHoldInputPending = false;
					s_localHoldUiActive = false;
					AbilityModule.SetChargeSlotActivationProgress(0f);
					StopChargeWindupLoop(localChargeHandler);
					if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:Charge.PermissiveFallback", 120))
					{
						Debug.Log((object)"[Fix:DHHCharge][PermissiveGate] Host fix marker missing. Sending authoritative cancel fallback.");
					}
					TrySendVanillaRemoteCancelCommand(localChargeHandler);
					return false;
				}
				value.IsHolding = false;
				s_localHoldInputPending = false;
				s_localHoldUiActive = false;
				AbilityModule.SetChargeSlotActivationProgress(0f);
				if (!TrySendRemoteReleaseCommand(localChargeHandler))
				{
					StopChargeWindupLoop(localChargeHandler);
					TrySendVanillaRemoteCancelCommand(localChargeHandler);
				}
				return false;
			}
			float num = Mathf.Max(0.2f, FeatureFlags.ChargeAbilityHoldSeconds);
			float num2 = Mathf.Clamp01((Time.time - value.StartTime) / num);
			float minimumChargeReleaseScale = GetMinimumChargeReleaseScale(localChargeHandler);
			if (num2 < minimumChargeReleaseScale)
			{
				value.IsHolding = false;
				value.LaunchScale = 0f;
				s_localHoldInputPending = false;
				s_localHoldUiActive = false;
				AbilityModule.SetChargeSlotActivationProgress(0f);
				StopChargeWindupLoop(localChargeHandler);
				localChargeHandler.CancelCharge();
				return false;
			}
			value.IsHolding = false;
			value.LaunchScale = num2;
			localChargeHandler.chargeStrength *= num2;
			localChargeHandler.maxBounces = Mathf.Max(0f, localChargeHandler.maxBounces * num2);
			localChargeHandler.windupTimer = -1f;
			s_localHoldInputPending = false;
			s_localHoldUiActive = false;
			AbilityModule.SetChargeSlotActivationProgress(0f);
			return true;
		}

		private static bool ChargeHandler_UpdateWindupDirection_Prefix(ChargeHandler __instance, Vector3 chargeDirection)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return true;
			}
			if (Mathf.Abs(chargeDirection.x - -778f) < 0.001f)
			{
				__instance.CancelCharge();
				return false;
			}
			if (Mathf.Abs(chargeDirection.x - -777f) > 0.001f)
			{
				return true;
			}
			LogChargeMotionEvent("remote-release-received", __instance);
			int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)__instance);
			if (unityObjectInstanceId == 0 || !s_chargeHoldStates.TryGetValue(unityObjectInstanceId, out ChargeHoldState value))
			{
				return false;
			}
			if (!IsChargeState(__instance, "Windup"))
			{
				return false;
			}
			float num = Mathf.Max(0.2f, FeatureFlags.ChargeAbilityHoldSeconds);
			float num2 = Mathf.Clamp01((Time.time - value.StartTime) / num);
			float minimumChargeReleaseScale = GetMinimumChargeReleaseScale(__instance);
			value.IsHolding = false;
			if (num2 < minimumChargeReleaseScale)
			{
				value.LaunchScale = 0f;
				__instance.CancelCharge();
				return false;
			}
			value.LaunchScale = num2;
			__instance.chargeStrength *= num2;
			__instance.maxBounces = Mathf.Max(0f, __instance.maxBounces * num2);
			__instance.windupTimer = -1f;
			return false;
		}

		private static bool TrySendRemoteReleaseCommand(ChargeHandler chargeHandler)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			PhotonView chargePhotonView = GetChargePhotonView(chargeHandler);
			if ((Object)(object)chargePhotonView == (Object)null || chargePhotonView.ViewID <= 0)
			{
				return false;
			}
			if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient)
			{
				return false;
			}
			chargePhotonView.RPC("UpdateWindupDirection", (RpcTarget)2, new object[1] { (object)new Vector3(-777f, 0f, 0f) });
			return true;
		}

		private static bool TrySendVanillaRemoteCancelCommand(ChargeHandler chargeHandler)
		{
			PhotonView chargePhotonView = GetChargePhotonView(chargeHandler);
			if ((Object)(object)chargePhotonView == (Object)null || chargePhotonView.ViewID <= 0)
			{
				return false;
			}
			if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient)
			{
				return false;
			}
			chargePhotonView.RPC("CancelCharge", (RpcTarget)2, Array.Empty<object>());
			return true;
		}

		private static PhotonView? GetChargePhotonView(ChargeHandler chargeHandler)
		{
			if (chargeHandler != null)
			{
				PhotonView component = ((Component)chargeHandler).GetComponent<PhotonView>();
				if ((Object)(object)component != (Object)null && component.ViewID > 0)
				{
					return component;
				}
			}
			return GetDhhInputManagerHeadPhotonView();
		}

		private static PhotonView? GetDhhInputManagerHeadPhotonView()
		{
			return ((Object)(object)DHHInputManager.instance != (Object)null) ? DHHInputManager.instance.headPhotonView : null;
		}

		private static float GetMinimumChargeReleaseScale(ChargeHandler chargeHandler)
		{
			if ((Object)(object)chargeHandler == (Object)null)
			{
				return 0f;
			}
			float num = 0f;
			TryGetEffectiveChargeAbilityLevel(chargeHandler, out var abilityLevel);
			float effectiveChargeStrengthForThreshold = GetEffectiveChargeStrengthForThreshold(chargeHandler, abilityLevel);
			if (effectiveChargeStrengthForThreshold > 0f)
			{
				num = Mathf.Max(num, RequiredScaleForMinimumOne(effectiveChargeStrengthForThreshold));
			}
			float effectiveMaxBouncesForThreshold = GetEffectiveMaxBouncesForThreshold(chargeHandler, abilityLevel);
			if (effectiveMaxBouncesForThreshold > 0f)
			{
				num = Mathf.Max(num, RequiredScaleForMinimumOne(effectiveMaxBouncesForThreshold));
			}
			if (abilityLevel > 0)
			{
				float baseValue = 5f + 1f * (float)abilityLevel;
				num = Mathf.Max(num, RequiredScaleForMinimumOne(baseValue));
			}
			if (float.IsNaN(num) || float.IsInfinity(num))
			{
				return 1f;
			}
			return Mathf.Clamp01(num);
		}

		private static float GetEffectiveChargeStrengthForThreshold(ChargeHandler chargeHandler, int abilityLevel)
		{
			if (chargeHandler.chargeStrength > 0f)
			{
				return chargeHandler.chargeStrength;
			}
			if (abilityLevel <= 0)
			{
				return 0f;
			}
			return EvaluateStatWithDiminishingReturns(FeatureFlags.DHHChargeStrengthBaseValue, FeatureFlags.DHHChargeStrengthIncreasePerLevel, abilityLevel, FeatureFlags.DHHChargeStrengthThresholdLevel, FeatureFlags.DHHChargeStrengthDiminishingFactor).FinalValue;
		}

		private static float GetEffectiveMaxBouncesForThreshold(ChargeHandler chargeHandler, int abilityLevel)
		{
			if (chargeHandler.maxBounces > 0f)
			{
				return chargeHandler.maxBounces;
			}
			if (abilityLevel <= 0)
			{
				return 0f;
			}
			float baseValue = ((chargeHandler.baseMaxBounces > 0) ? ((float)chargeHandler.baseMaxBounces) : 3f);
			return Mathf.FloorToInt(EvaluateStatWithDiminishingReturns(baseValue, 0.5f, abilityLevel, 20, 0.9f).FinalValue);
		}

		private static bool TryGetEffectiveChargeAbilityLevel(ChargeHandler chargeHandler, out int abilityLevel)
		{
			abilityLevel = Mathf.Max(0, chargeHandler.AbilityLevel);
			if (abilityLevel > 0)
			{
				return true;
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer() && IsLocalChargeHandler(chargeHandler) && TryGetLocalPlayerChargeUpgrade(out var upgrade))
			{
				abilityLevel = Mathf.Max(0, upgrade);
				return true;
			}
			return abilityLevel >= 0;
		}

		private static bool TryGetLocalPlayerChargeUpgrade(out int upgrade)
		{
			upgrade = 0;
			PlayerAvatar instance = PlayerAvatar.instance;
			string text = (((Object)(object)instance != (Object)null) ? SemiFunc.PlayerGetSteamID(instance) : null);
			if (string.IsNullOrWhiteSpace(text))
			{
				return false;
			}
			try
			{
				upgrade = DHHStatsManager.GetHeadChargeUpgrade(text);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static float RequiredScaleForMinimumOne(float baseValue)
		{
			if (baseValue <= 0f)
			{
				return float.PositiveInfinity;
			}
			return 1f / baseValue;
		}

		private static bool IsChargeHandlerHeadGrabbed(ChargeHandler chargeHandler)
		{
			PhysGrabObjectImpactDetector impactDetector = chargeHandler.impactDetector;
			if ((Object)(object)impactDetector == (Object)null)
			{
				return false;
			}
			PhysGrabObject physGrabObject = impactDetector.physGrabObject;
			if ((Object)(object)physGrabObject == (Object)null)
			{
				return false;
			}
			return physGrabObject.grabbed;
		}

		private static int GetUnityObjectInstanceId(Object? obj)
		{
			return (obj != (Object)null) ? obj.GetInstanceID() : 0;
		}

		private static ChargeHoldState GetOrCreateChargeHoldState(int id)
		{
			if (!s_chargeHoldStates.TryGetValue(id, out ChargeHoldState value))
			{
				value = new ChargeHoldState();
				s_chargeHoldStates[id] = value;
			}
			return value;
		}

		private static bool IsChargeState(ChargeHandler chargeHandler, string stateName)
		{
			//IL_0011: 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)
			if ((Object)(object)chargeHandler == (Object)null)
			{
				return false;
			}
			return string.Equals(((object)chargeHandler.State/*cast due to .constrained prefix*/).ToString(), stateName, StringComparison.Ordinal);
		}

		private static bool IsLocalChargeHandler(ChargeHandler chargeHandler)
		{
			ChargeHandler localChargeHandler = GetLocalChargeHandler();
			if ((Object)(object)localChargeHandler == (Object)null)
			{
				return false;
			}
			return localChargeHandler == chargeHandler;
		}

		private static ChargeHandler? GetLocalChargeHandler()
		{
			PlayerAvatar instance = PlayerAvatar.instance;
			if ((Object)(object)instance?.playerDeathHead == (Object)null)
			{
				return null;
			}
			return ((Component)instance.playerDeathHead).GetComponent<DeathHeadController>()?.chargeHandler;
		}

		private static void ClearChargeHoldState(ChargeHandler? chargeHandler)
		{
			if (!((Object)(object)chargeHandler == (Object)null))
			{
				int unityObjectInstanceId = GetUnityObjectInstanceId((Object?)(object)chargeHandler);
				if (unityObjectInstanceId != 0)
				{
					s_chargeHoldStates.Remove(unityObjectInstance