Decompiled source of WallGrabJump v1.1.1

Mods/WallGrabJump.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib;
using BoneLib.BoneMenu;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Bonelab;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Interaction;
using Il2CppSLZ.VRMK;
using Il2CppSystem;
using Il2CppSystem.Reflection;
using MelonLoader;
using MelonLoader.Preferences;
using UnityEngine;
using WallGrabJump;
using WallGrabJump.Compatibility;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(WallGrabJumpMod), "WallGrabJump", "1.1.1", "Cesar", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonAdditionalDependencies(new string[] { "BoneLib" })]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("WallGrabJump")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2+d39d6c885da37911b070dabcf9c5897738c72fe7")]
[assembly: AssemblyProduct("WallGrabJump")]
[assembly: AssemblyTitle("WallGrabJump")]
[assembly: AssemblyVersion("1.0.2.0")]
namespace WallGrabJump
{
	internal static class AvatarJump
	{
		private const float BaselineStrength = 1f;

		private const float MinMultiplier = 0.75f;

		private const float MaxMultiplier = 2f;

		private static bool _warned;

		internal static float Multiplier(out float rawStrength)
		{
			rawStrength = 0f;
			if (!Prefs.AvatarStrengthScalingValue)
			{
				return 1f;
			}
			try
			{
				RigManager manager = LocalRig.Manager;
				Avatar val = (((Object)(object)manager != (Object)null) ? manager._avatar : null);
				if ((Object)(object)val == (Object)null)
				{
					return 1f;
				}
				float num = (rawStrength = val.strengthUpper);
				if (float.IsNaN(num) || float.IsInfinity(num) || num <= 0f)
				{
					return 1f;
				}
				return Mathf.Clamp(Mathf.Sqrt(num / 1f), 0.75f, 2f);
			}
			catch (Exception ex)
			{
				if (!_warned)
				{
					_warned = true;
					Log.Warning("Avatar strength unreadable (" + ex.GetType().Name + "); wall jumps stay at 1.0x.");
				}
				return 1f;
			}
		}

		internal static string Describe()
		{
			try
			{
				RigManager manager = LocalRig.Manager;
				Avatar val = (((Object)(object)manager != (Object)null) ? manager._avatar : null);
				if ((Object)(object)val == (Object)null)
				{
					return "stats=none";
				}
				return $"strLower={val.strengthLower:0.00} grip={val.strengthGrip:0.00} agility={val.agility:0.00} speed={val.speed:0.00} mass={val.massTotal:0.0}";
			}
			catch
			{
				return "stats=?";
			}
		}
	}
	internal enum ClimbSource
	{
		None,
		Vanilla,
		ClimbAnything
	}
	internal struct ClimbHold
	{
		internal ClimbSource Source;

		internal Handedness Side;

		internal Hand Hand;

		internal Grip Grip;

		internal object State;

		internal Vector3 Anchor;

		internal Collider Surface;

		internal bool Valid => Source != ClimbSource.None;
	}
	internal static class ClimbDetector
	{
		internal static int Snapshot(out ClimbHold left, out ClimbHold right)
		{
			left = Evaluate(LocalRig.LeftHand, (Handedness)1);
			right = Evaluate(LocalRig.RightHand, (Handedness)2);
			return (left.Valid ? 1 : 0) + (right.Valid ? 1 : 0);
		}

		private static ClimbHold Evaluate(Hand hand, Handedness side)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			ClimbHold result = new ClimbHold
			{
				Side = side,
				Hand = hand
			};
			if ((Object)(object)hand == (Object)null || !PlayerState.IsLocalHand(hand))
			{
				return default(ClimbHold);
			}
			try
			{
				HandReciever attachedReceiver = hand.AttachedReceiver;
				Grip val = (((Object)(object)attachedReceiver != (Object)null) ? ((Il2CppObjectBase)attachedReceiver).TryCast<Grip>() : null);
				if ((Object)(object)val != (Object)null && IsClimbingGrip(val))
				{
					result.Source = ClimbSource.Vanilla;
					result.Grip = val;
					result.Anchor = ((Component)hand).transform.position;
					result.Surface = SurfaceOf(val);
					return result;
				}
			}
			catch (Exception ex)
			{
				Log.Debug("Vanilla climb check failed (" + ex.GetType().Name + ")");
			}
			ClimbHold result2 = ClimbAnythingCompatibility.Evaluate(hand, side);
			if (result2.Valid)
			{
				return result2;
			}
			if (Prefs.DebugLoggingValue)
			{
				DescribeRejection(hand, side);
			}
			return default(ClimbHold);
		}

		internal static bool IsClimbingGrip(Grip grip)
		{
			try
			{
				if ((Object)(object)grip == (Object)null)
				{
					return false;
				}
				if ((Object)(object)((Il2CppObjectBase)grip).TryCast<UIInteractionVolume>() != (Object)null)
				{
					return false;
				}
				if ((Object)(object)((Il2CppObjectBase)grip).TryCast<WorldGrip>() != (Object)null)
				{
					return true;
				}
				if (!((HandReciever)grip).HasHost)
				{
					return true;
				}
				return ((HandReciever)grip).IsStatic || IsImmovableHost(grip);
			}
			catch
			{
				return false;
			}
		}

		internal static string DescribeRig()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			string value = "?";
			try
			{
				PhysicsRig physics = LocalRig.Physics;
				if ((Object)(object)physics != (Object)null)
				{
					value = ((object)physics._stepState/*cast due to .constrained prefix*/).ToString();
				}
			}
			catch
			{
			}
			return $"[rig step={value} left={ReceiverOf(LocalRig.LeftHand)} right={ReceiverOf(LocalRig.RightHand)}]";
		}

		private static string ReceiverOf(Hand hand)
		{
			try
			{
				if ((Object)(object)hand == (Object)null)
				{
					return "no-hand";
				}
				HandReciever attachedReceiver = hand.AttachedReceiver;
				if ((Object)(object)attachedReceiver == (Object)null)
				{
					return "empty";
				}
				return TypeName((Object)(object)attachedReceiver);
			}
			catch
			{
				return "?";
			}
		}

		private static bool IsImmovableHost(Grip grip)
		{
			try
			{
				IGrippable host = ((HandReciever)grip).Host;
				if (host == null)
				{
					return false;
				}
				Rigidbody rb = host.Rb;
				return (Object)(object)rb != (Object)null && rb.isKinematic;
			}
			catch
			{
				return false;
			}
		}

		private static void DescribeRejection(Hand hand, Handedness side)
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				HandReciever attachedReceiver = hand.AttachedReceiver;
				if ((Object)(object)attachedReceiver == (Object)null)
				{
					return;
				}
				Grip val = ((Il2CppObjectBase)attachedReceiver).TryCast<Grip>();
				if ((Object)(object)val == (Object)null)
				{
					Log.Debug($"{side} hand: holding {TypeName((Object)(object)attachedReceiver)}, which is not a Grip — not climbable.");
					return;
				}
				bool flag = false;
				bool value = false;
				bool flag2 = false;
				bool flag3 = false;
				try
				{
					flag = ((HandReciever)val).HasHost;
				}
				catch
				{
				}
				try
				{
					value = flag && ((HandReciever)val).IsStatic;
				}
				catch
				{
				}
				try
				{
					IGrippable val2 = (flag ? ((HandReciever)val).Host : null);
					Rigidbody val3 = ((val2 != null) ? val2.Rb : null);
					flag3 = (Object)(object)val3 != (Object)null;
					flag2 = flag3 && val3.isKinematic;
				}
				catch
				{
				}
				Log.Debug($"{side} hand: holding {TypeName((Object)(object)val)} — hasHost={flag} isStatic={value} body={((!flag3) ? "none" : (flag2 ? "kinematic" : "dynamic"))} — not counted as climbing.");
			}
			catch
			{
			}
		}

		private static string TypeName(Object obj)
		{
			try
			{
				return ((MemberInfo)obj.GetIl2CppType()).Name;
			}
			catch
			{
				return "?";
			}
		}

		private static Collider SurfaceOf(Grip grip)
		{
			try
			{
				if ((Object)(object)((Il2CppObjectBase)grip).TryCast<WorldGrip>() != (Object)null)
				{
					return null;
				}
				return ((Component)grip).GetComponentInParent<Collider>();
			}
			catch
			{
				return null;
			}
		}
	}
	internal sealed class InputController
	{
		private enum Phase
		{
			Unknown,
			Released,
			Held
		}

		private Phase _phase;

		private int _sampledFrame = -1;

		private bool _pressedThisFrame;

		internal bool Held => _phase == Phase.Held;

		internal bool Readable => _phase != Phase.Unknown;

		internal void Reset()
		{
			_phase = Phase.Unknown;
			_sampledFrame = -1;
			_pressedThisFrame = false;
		}

		internal bool PressedThisFrame()
		{
			int frameCount = Time.frameCount;
			if (_sampledFrame == frameCount)
			{
				return _pressedThisFrame;
			}
			_sampledFrame = frameCount;
			_pressedThisFrame = false;
			bool readable;
			bool flag = ReadA(out readable);
			if (!readable)
			{
				_phase = Phase.Unknown;
				return false;
			}
			if (!flag)
			{
				_phase = Phase.Released;
				return false;
			}
			_pressedThisFrame = _phase == Phase.Released;
			_phase = Phase.Held;
			return _pressedThisFrame;
		}

		private static bool ReadA(out bool readable)
		{
			readable = false;
			try
			{
				BaseController rightController = LocalRig.RightController;
				if ((Object)(object)rightController == (Object)null)
				{
					return false;
				}
				readable = true;
				return rightController.GetAButton();
			}
			catch
			{
				readable = false;
				return false;
			}
		}
	}
	internal static class LocalRig
	{
		private static RigManager _rig;

		private static int _resolvedFrame = -1;

		private static bool _warnedDisagreement;

		internal static RigManager Manager
		{
			get
			{
				int frameCount = Time.frameCount;
				if (_resolvedFrame == frameCount)
				{
					return _rig;
				}
				_resolvedFrame = frameCount;
				return _rig = Resolve();
			}
		}

		internal static PhysicsRig Physics
		{
			get
			{
				RigManager manager = Manager;
				if (!((Object)(object)manager != (Object)null))
				{
					return null;
				}
				return manager.physicsRig;
			}
		}

		internal static Transform Head
		{
			get
			{
				PhysicsRig physics = Physics;
				if (!((Object)(object)physics != (Object)null))
				{
					return null;
				}
				return ((Rig)physics).m_head;
			}
		}

		internal static Hand LeftHand
		{
			get
			{
				PhysicsRig physics = Physics;
				if (!((Object)(object)physics != (Object)null))
				{
					return null;
				}
				return physics.leftHand;
			}
		}

		internal static Hand RightHand
		{
			get
			{
				PhysicsRig physics = Physics;
				if (!((Object)(object)physics != (Object)null))
				{
					return null;
				}
				return physics.rightHand;
			}
		}

		internal static BaseController RightController => Controller((Handedness)2);

		internal static void Reset()
		{
			_rig = null;
			_resolvedFrame = -1;
			_warnedDisagreement = false;
		}

		private static RigManager Resolve()
		{
			RigManager val = null;
			try
			{
				PlayerRefs instance = PlayerRefs.Instance;
				if ((Object)(object)instance != (Object)null && instance.HasRefs)
				{
					val = instance.PlayerRigManager;
				}
			}
			catch (Exception ex)
			{
				if (!_warnedDisagreement)
				{
					_warnedDisagreement = true;
					Log.Warning("Could not read the game's own player reference (" + ex.GetType().Name + "); falling back to BoneLib for the local rig.");
				}
			}
			RigManager val2 = null;
			try
			{
				val2 = Player.RigManager;
			}
			catch
			{
			}
			if ((Object)(object)val == (Object)null)
			{
				return val2;
			}
			if (!_warnedDisagreement && (Object)(object)val2 != (Object)null && ((Il2CppObjectBase)val2).Pointer != ((Il2CppObjectBase)val).Pointer)
			{
				_warnedDisagreement = true;
				Log.Warning("BoneLib resolved a different rig than the game's own player reference " + $"(BoneLib: '{SafeName(val2)}', game: '{SafeName(val)}'). " + "Using the game's. This is what a networked player rig being mistaken for yours looks like.");
			}
			return val;
		}

		private static string SafeName(RigManager rig)
		{
			try
			{
				return ((Object)(object)rig != (Object)null) ? ((Object)rig).name : "null";
			}
			catch
			{
				return "?";
			}
		}

		internal static BaseController Controller(Handedness side)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			try
			{
				RigManager manager = Manager;
				if ((Object)(object)manager == (Object)null)
				{
					return null;
				}
				ControllerRig controllerRig = manager.ControllerRig;
				if ((Object)(object)controllerRig == (Object)null)
				{
					return null;
				}
				return ((int)side == 1) ? controllerRig.leftController : controllerRig.rightController;
			}
			catch
			{
				return null;
			}
		}

		internal static bool IsLocalHand(Hand hand)
		{
			if ((Object)(object)hand == (Object)null)
			{
				return false;
			}
			RigManager manager = Manager;
			if ((Object)(object)manager != (Object)null)
			{
				return (Object)(object)hand.manager == (Object)(object)manager;
			}
			return false;
		}
	}
	internal static class PlayerState
	{
		private static PhysicsRig _bodiesOwner;

		private static Rigidbody[] _bodies;

		internal static bool IsValid
		{
			get
			{
				if (HelperMethods.IsLoading())
				{
					return false;
				}
				if ((Object)(object)LocalRig.Manager != (Object)null)
				{
					return (Object)(object)LocalRig.Physics != (Object)null;
				}
				return false;
			}
		}

		internal static Transform Head => LocalRig.Head;

		internal static Rigidbody Pelvis
		{
			get
			{
				PhysicsRig physics = LocalRig.Physics;
				PhysTorso val = (((Object)(object)physics != (Object)null) ? physics.torso : null);
				if (!((Object)(object)val != (Object)null))
				{
					return null;
				}
				return val.rbPelvis;
			}
		}

		internal static Rigidbody Chest
		{
			get
			{
				PhysicsRig physics = LocalRig.Physics;
				PhysTorso val = (((Object)(object)physics != (Object)null) ? physics.torso : null);
				if (!((Object)(object)val != (Object)null))
				{
					return null;
				}
				return val.rbChest;
			}
		}

		internal static Vector3 BodyCentre
		{
			get
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				Rigidbody chest = Chest;
				if ((Object)(object)chest != (Object)null)
				{
					return chest.position;
				}
				Rigidbody pelvis = Pelvis;
				if ((Object)(object)pelvis != (Object)null)
				{
					return pelvis.position;
				}
				Transform head = Head;
				if (!((Object)(object)head != (Object)null))
				{
					return Vector3.zero;
				}
				return head.position;
			}
		}

		internal static Vector3 Velocity
		{
			get
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				Rigidbody pelvis = Pelvis;
				if (!((Object)(object)pelvis != (Object)null))
				{
					return Vector3.zero;
				}
				return pelvis.velocity;
			}
		}

		internal static Vector3 BodyVelocity
		{
			get
			{
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_009e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c7: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: 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_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				Rigidbody[] array = RigBodies();
				if (array == null || array.Length == 0)
				{
					return Velocity;
				}
				Vector3 val = Vector3.zero;
				float num = 0f;
				foreach (Rigidbody val2 in array)
				{
					if (!((Object)(object)val2 == (Object)null) && !val2.isKinematic)
					{
						float mass = val2.mass;
						if (!(mass <= 0f) && !float.IsNaN(mass) && !float.IsInfinity(mass))
						{
							val += val2.velocity * mass;
							num += mass;
						}
					}
				}
				if (num <= 0f)
				{
					return Velocity;
				}
				Vector3 val3 = val / num;
				if (!float.IsNaN(val3.x) && !float.IsNaN(val3.y) && !float.IsNaN(val3.z))
				{
					return val3;
				}
				return Velocity;
			}
		}

		internal static bool RigStillClimbing
		{
			get
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Invalid comparison between Unknown and I4
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Invalid comparison between Unknown and I4
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Invalid comparison between Unknown and I4
				try
				{
					PhysicsRig physics = LocalRig.Physics;
					if ((Object)(object)physics == (Object)null)
					{
						return false;
					}
					StepState stepState = physics._stepState;
					return (int)stepState == 4 || (int)stepState == 3 || (int)stepState == 5;
				}
				catch
				{
					return false;
				}
			}
		}

		internal static bool RigSettled
		{
			get
			{
				try
				{
					if (RigStillClimbing)
					{
						return true;
					}
					PhysicsRig physics = LocalRig.Physics;
					PhysGrounder val = (((Object)(object)physics != (Object)null) ? physics.physG : null);
					return (Object)(object)val != (Object)null && val.isGrounded;
				}
				catch
				{
					return false;
				}
			}
		}

		internal static bool IsLocalHand(Hand hand)
		{
			return LocalRig.IsLocalHand(hand);
		}

		internal static string StepStateName()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PhysicsRig physics = LocalRig.Physics;
				return ((Object)(object)physics != (Object)null) ? ((object)physics._stepState/*cast due to .constrained prefix*/).ToString() : "none";
			}
			catch
			{
				return "?";
			}
		}

		internal static bool TryGetMarrowClimbNormal(out Vector3 normal)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			normal = Vector3.zero;
			PhysicsRig physics = LocalRig.Physics;
			if ((Object)(object)physics == (Object)null)
			{
				return false;
			}
			StepState stepState = physics._stepState;
			if ((int)stepState != 4 && (int)stepState != 3 && (int)stepState != 5)
			{
				return false;
			}
			Vector3 climbingNormal = physics.climbingNormal;
			if (((Vector3)(ref climbingNormal)).sqrMagnitude < 0.25f)
			{
				return false;
			}
			normal = ((Vector3)(ref climbingNormal)).normalized;
			return true;
		}

		internal static Rigidbody[] RigBodies()
		{
			PhysicsRig physics = LocalRig.Physics;
			if ((Object)(object)physics == (Object)null)
			{
				_bodiesOwner = null;
				_bodies = null;
				return null;
			}
			if (_bodies != null && (Object)(object)_bodiesOwner == (Object)(object)physics)
			{
				return _bodies;
			}
			try
			{
				Il2CppArrayBase<Rigidbody> componentsInChildren = ((Component)physics).GetComponentsInChildren<Rigidbody>(true);
				if (componentsInChildren == null)
				{
					return null;
				}
				int num = 0;
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if ((Object)(object)componentsInChildren[i] != (Object)null)
					{
						num++;
					}
				}
				Rigidbody[] array = (Rigidbody[])(object)new Rigidbody[num];
				int num2 = 0;
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					if (num2 >= num)
					{
						break;
					}
					Rigidbody val = componentsInChildren[j];
					if ((Object)(object)val != (Object)null)
					{
						array[num2++] = val;
					}
				}
				_bodies = array;
				_bodiesOwner = physics;
				return _bodies;
			}
			catch (Exception ex)
			{
				Log.Debug("Could not gather rig rigidbodies (" + ex.GetType().Name + ")");
				return null;
			}
		}

		internal static void DropCaches()
		{
			_bodies = null;
			_bodiesOwner = null;
		}
	}
	internal static class Prefs
	{
		internal static MelonPreferences_Category Category;

		internal static MelonPreferences_Entry<bool> Enabled;

		internal static MelonPreferences_Entry<float> JumpStrength;

		internal static MelonPreferences_Entry<float> LookInfluence;

		internal static MelonPreferences_Entry<float> OutwardPush;

		internal static MelonPreferences_Entry<float> UpwardBoost;

		internal static MelonPreferences_Entry<float> OutwardFloor;

		internal static MelonPreferences_Entry<float> AimStrictness;

		internal static MelonPreferences_Entry<float> StaminaCost;

		internal static MelonPreferences_Entry<bool> AvatarStrengthScaling;

		internal static MelonPreferences_Entry<bool> SuppressVanillaJump;

		internal static MelonPreferences_Entry<bool> DebugLogging;

		internal const float DefaultJumpStrength = 1.8f;

		internal const float DefaultLookInfluence = 2f;

		internal const float DefaultOutwardPush = 0.9f;

		internal const float DefaultUpwardBoost = 1.65f;

		internal const float DefaultOutwardFloor = 0.35f;

		internal const float DefaultAimStrictness = 180f;

		internal const float DefaultStaminaCost = 10f;

		internal static bool EnabledValue
		{
			get
			{
				if (Enabled != null)
				{
					return Enabled.Value;
				}
				return true;
			}
		}

		internal static float JumpStrengthValue => Sane(JumpStrength, 1.8f);

		internal static float LookInfluenceValue => Sane(LookInfluence, 2f);

		internal static float OutwardPushValue => Sane(OutwardPush, 0.9f);

		internal static float UpwardBoostValue => Sane(UpwardBoost, 1.65f);

		internal static float OutwardFloorValue => Sane(OutwardFloor, 0.35f);

		internal static float AimStrictnessValue => Sane(AimStrictness, 180f);

		internal static float StaminaCostValue => Sane(StaminaCost, 10f);

		internal static bool AvatarStrengthScalingValue
		{
			get
			{
				if (AvatarStrengthScaling != null)
				{
					return AvatarStrengthScaling.Value;
				}
				return true;
			}
		}

		internal static bool SuppressVanillaJumpValue
		{
			get
			{
				if (SuppressVanillaJump != null)
				{
					return SuppressVanillaJump.Value;
				}
				return true;
			}
		}

		internal static bool DebugLoggingValue
		{
			get
			{
				if (DebugLogging != null)
				{
					return DebugLogging.Value;
				}
				return false;
			}
		}

		private static float Sane(MelonPreferences_Entry<float> entry, float fallback)
		{
			if (entry == null)
			{
				return fallback;
			}
			float value = entry.Value;
			if (!float.IsNaN(value) && !float.IsInfinity(value))
			{
				return value;
			}
			return fallback;
		}

		internal static void Setup()
		{
			Category = MelonPreferences.CreateCategory("WallGrabJump", "Wall Grab Jump");
			Enabled = Category.CreateEntry<bool>("Enabled", true, "Enabled", "Master switch for the wall jump.", false, false, (ValueValidator)null, (string)null);
			JumpStrength = Category.CreateEntry<float>("JumpStrength", 1.8f, "Jump Strength", "Multiplier on the push. 1.0 is a controlled shove off the wall.", false, false, (ValueValidator)null, (string)null);
			LookInfluence = Category.CreateEntry<float>("LookInfluence", 2f, "Look Influence", "How strongly your head direction steers the jump.", false, false, (ValueValidator)null, (string)null);
			OutwardPush = Category.CreateEntry<float>("OutwardPush", 0.9f, "Outward Push", "How hard the jump shoves away from the wall face. Lower this if jumps feel like being kicked off the wall.", false, false, (ValueValidator)null, (string)null);
			UpwardBoost = Category.CreateEntry<float>("UpwardBoost", 1.65f, "Upward Boost", "How much lift is mixed into every jump.", false, false, (ValueValidator)null, (string)null);
			OutwardFloor = Category.CreateEntry<float>("OutwardFloor", 0.35f, "Outward Floor", "How much separation from the wall a kick-off guarantees. 0 removes the guarantee; jumps still never aim into the surface.", false, false, (ValueValidator)null, (string)null);
			AimStrictness = Category.CreateEntry<float>("AimStrictness", 180f, "Aim Strictness", "Max degrees your look may differ from straight off the wall before the jump is refused. 180 = never refuse.", false, false, (ValueValidator)null, (string)null);
			StaminaCost = Category.CreateEntry<float>("StaminaCost", 10f, "Stamina Cost %", "Percent of max climbing stamina a wall jump costs. Only used when ClimbStamina is installed.", false, false, (ValueValidator)null, (string)null);
			SuppressVanillaJump = Category.CreateEntry<bool>("SuppressVanillaJump", true, "Suppress Vanilla Jump", "Stop a wall jump from also firing BONELAB's own jump. Set false to remove the patch entirely if it ever misbehaves.", false, false, (ValueValidator)null, (string)null);
			AvatarStrengthScaling = Category.CreateEntry<bool>("AvatarStrengthScaling", true, "Avatar Strength Scaling", "Stronger avatars wall jump farther, weaker ones shorter, using the same upper-body strength stat ClimbStamina reads. Off = every avatar jumps the same.", false, false, (ValueValidator)null, (string)null);
			DebugLogging = Category.CreateEntry<bool>("DebugLogging", false, "Debug Logging", "Verbose per-jump logging for troubleshooting.", false, false, (ValueValidator)null, (string)null);
		}
	}
	internal static class RegrabGuard
	{
		private const float GripHeldThreshold = 0.2f;

		private const float UnreadableGripGrace = 0.5f;

		private static float _blockUntil = float.NegativeInfinity;

		private static bool _installed;

		private static bool _leftHeld;

		private static bool _rightHeld;

		private static float _leftUnreadableSince = -1f;

		private static float _rightUnreadableSince = -1f;

		internal static void Suppress(float seconds)
		{
			float num = Time.time + seconds;
			if (num > _blockUntil)
			{
				_blockUntil = num;
			}
		}

		internal static void SuppressHand(Handedness side)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			if ((int)side == 1)
			{
				_leftHeld = true;
				_leftUnreadableSince = -1f;
			}
			else
			{
				_rightHeld = true;
				_rightUnreadableSince = -1f;
			}
		}

		internal static void Tick()
		{
			if (_leftHeld && GripReleased((Handedness)1, ref _leftUnreadableSince))
			{
				_leftHeld = false;
				Log.Debug("Left hand may climb again (grip released)");
			}
			if (_rightHeld && GripReleased((Handedness)2, ref _rightUnreadableSince))
			{
				_rightHeld = false;
				Log.Debug("Right hand may climb again (grip released)");
			}
		}

		private static bool GripReleased(Handedness side, ref float unreadableSince)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			float time = Time.time;
			try
			{
				BaseController val = LocalRig.Controller(side);
				if ((Object)(object)val == (Object)null)
				{
					if (unreadableSince < 0f)
					{
						unreadableSince = time;
					}
					return time - unreadableSince >= 0.5f;
				}
				unreadableSince = -1f;
				return val.GetGripForce() <= 0.2f;
			}
			catch
			{
				if (unreadableSince < 0f)
				{
					unreadableSince = time;
				}
				return time - unreadableSince >= 0.5f;
			}
		}

		internal static void Clear()
		{
			_blockUntil = float.NegativeInfinity;
			_leftHeld = false;
			_rightHeld = false;
			_leftUnreadableSince = -1f;
			_rightUnreadableSince = -1f;
		}

		internal static void ApplyPatches(Harmony harmony)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			if (_installed)
			{
				return;
			}
			MethodInfo method = typeof(Grip).GetMethod("OnGrabConfirm", AccessTools.all);
			MethodInfo method2 = typeof(RegrabGuard).GetMethod("OnGrabConfirmPrefix", AccessTools.all);
			if (method == null || method2 == null)
			{
				Log.Warning("Grip.OnGrabConfirm not found; the brief anti-regrab window after a vanilla wall jump is off.");
				return;
			}
			try
			{
				harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_installed = true;
			}
			catch (Exception ex)
			{
				Log.Warning("Could not patch Grip.OnGrabConfirm (" + ex.GetType().Name + "); the anti-regrab hold-off after a vanilla wall jump is off.");
			}
		}

		private static bool OnGrabConfirmPrefix(Grip __instance, Hand hand)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			try
			{
				if ((Object)(object)hand == (Object)null || !PlayerState.IsLocalHand(hand))
				{
					return true;
				}
				if (!(((int)hand.handedness == 1) ? _leftHeld : _rightHeld) && Time.time >= _blockUntil)
				{
					return true;
				}
				if ((Object)(object)__instance == (Object)null || !ClimbDetector.IsClimbingGrip(__instance))
				{
					return true;
				}
				return false;
			}
			catch
			{
				return true;
			}
		}
	}
	internal static class VanillaJumpGuard
	{
		private const float MaxSuppressSeconds = 6f;

		private const float AirborneSettleSeconds = 0.25f;

		private static bool _installed;

		private static bool _suppressing;

		private static float _hardStopAt;

		private static float _settledAt;

		private static float _lastWallJumpAt = float.NegativeInfinity;

		private static int _lastWallJumpFrame = -1;

		private static int _lastVanillaJumpFrame = -1;

		private static bool _saidSuppressed;

		internal static void ApplyPatches(Harmony harmony)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			if (_installed || !Prefs.SuppressVanillaJumpValue)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(typeof(RemapRig), "Jump", Type.EmptyTypes, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(VanillaJumpGuard), "JumpPrefix", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Log.Warning("RemapRig.Jump not found; the vanilla jump is not held off during a wall jump.");
				return;
			}
			try
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_installed = true;
			}
			catch (Exception ex)
			{
				Log.Warning("Could not patch the vanilla jump (" + ex.GetType().Name + "); an avatar that can jump in midair may add its own jump on top of a wall jump.");
			}
		}

		internal static void OnWallJump()
		{
			if (_lastVanillaJumpFrame == Time.frameCount)
			{
				Log.Debug("Vanilla jump already ran EARLIER THIS FRAME than the wall jump — the hold-off arms too late to stop it. Its lift is stacked on this jump.");
			}
			_suppressing = true;
			_hardStopAt = Time.time + 6f;
			_settledAt = Time.time + 0.25f;
			_lastWallJumpAt = Time.time;
			_lastWallJumpFrame = Time.frameCount;
			_saidSuppressed = false;
		}

		internal static void Tick()
		{
			if (_suppressing)
			{
				float time = Time.time;
				if (time >= _hardStopAt)
				{
					_suppressing = false;
					Log.Debug($"Wall jump hold-off ended on the {6f:0} s limit without the rig reporting a landing (step={PlayerState.StepStateName()}).");
				}
				else if (time >= _settledAt && PlayerState.RigSettled)
				{
					_suppressing = false;
					Log.Debug($"Wall jump hold-off ended after {time - _lastWallJumpAt:0.00}s (step={PlayerState.StepStateName()}).");
				}
			}
		}

		internal static void Clear()
		{
			_suppressing = false;
		}

		private static bool JumpPrefix(RemapRig __instance)
		{
			return Allow(__instance);
		}

		private static bool Allow(RemapRig instance)
		{
			try
			{
				bool flag = _lastWallJumpFrame >= 0 && Time.time - _lastWallJumpAt < 1.5f;
				if (!_suppressing && !flag)
				{
					return true;
				}
				bool flag2 = IsLocal(instance);
				if (flag2)
				{
					_lastVanillaJumpFrame = Time.frameCount;
				}
				if (!_suppressing)
				{
					if (flag2)
					{
						Log.Debug($"Vanilla jump executed {Time.time - _lastWallJumpAt:0.00}s ({Time.frameCount - _lastWallJumpFrame} frames) after a wall jump, not suppressed.");
					}
					return true;
				}
				if (!flag2)
				{
					return true;
				}
				if (!_saidSuppressed)
				{
					_saidSuppressed = true;
					Log.Debug("Vanilla jump held off for this wall-jump press.");
				}
				return false;
			}
			catch
			{
				return true;
			}
		}

		private static bool IsLocal(RemapRig instance)
		{
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			RigManager manager = LocalRig.Manager;
			RemapRig val = (((Object)(object)manager != (Object)null) ? manager.remapHeptaRig : null);
			if ((Object)(object)val != (Object)null)
			{
				return ((Il2CppObjectBase)instance).Pointer == ((Il2CppObjectBase)val).Pointer;
			}
			return false;
		}
	}
	public class WallGrabJumpMod : MelonMod
	{
		private static Instance _logger;

		private WallJumpController _controller;

		private bool _wasEnabled = true;

		private Action<LevelInfo> _onLevelLoaded;

		private Action _onLevelUnloaded;

		private Action<RigManager> _onPlayerDeath;

		public override void OnInitializeMelon()
		{
			_logger = ((MelonBase)this).LoggerInstance;
			try
			{
				Prefs.Setup();
			}
			catch (Exception ex)
			{
				Log.Warning("Could not create preferences (" + ex.GetType().Name + "); running on defaults.");
			}
			_controller = new WallJumpController();
			RegrabGuard.ApplyPatches(((MelonBase)this).HarmonyInstance);
			VanillaJumpGuard.ApplyPatches(((MelonBase)this).HarmonyInstance);
			ClimbAnythingCompatibility.Initialize(((MelonBase)this).HarmonyInstance);
			ClimbStaminaCompatibility.Initialize();
			_onLevelLoaded = delegate
			{
				ResetAll();
			};
			_onLevelUnloaded = ResetAll;
			_onPlayerDeath = delegate(RigManager rig)
			{
				RigManager manager = LocalRig.Manager;
				if ((Object)(object)rig != (Object)null && (Object)(object)manager != (Object)null && (Object)(object)rig == (Object)(object)manager)
				{
					ResetAll();
				}
			};
			Hooking.OnLevelLoaded += _onLevelLoaded;
			Hooking.OnLevelUnloaded += _onLevelUnloaded;
			Hooking.OnPlayerDeath += _onPlayerDeath;
			SetupMenu();
			Log.Msg("Initialized.");
		}

		public override void OnLateInitializeMelon()
		{
			ClimbAnythingCompatibility.Retry(((MelonBase)this).HarmonyInstance);
			ClimbStaminaCompatibility.Retry();
		}

		public override void OnDeinitializeMelon()
		{
			Hooking.OnLevelLoaded -= _onLevelLoaded;
			Hooking.OnLevelUnloaded -= _onLevelUnloaded;
			Hooking.OnPlayerDeath -= _onPlayerDeath;
		}

		public override void OnUpdate()
		{
			if (_controller == null)
			{
				return;
			}
			bool enabledValue = Prefs.EnabledValue;
			if (enabledValue != _wasEnabled)
			{
				_wasEnabled = enabledValue;
				if (!enabledValue)
				{
					ResetAll();
				}
			}
			if (enabledValue)
			{
				_controller.Tick();
			}
		}

		public override void OnFixedUpdate()
		{
			if (_controller != null && _wasEnabled)
			{
				_controller.FixedTick(Time.fixedDeltaTime);
			}
		}

		private void ResetAll()
		{
			_controller?.Reset();
			ClimbAnythingCompatibility.ClearSuppression();
			RegrabGuard.Clear();
			VanillaJumpGuard.Clear();
			PlayerState.DropCaches();
			LocalRig.Reset();
		}

		private static void SetupMenu()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (Prefs.Category == null)
				{
					Log.Warning("Preferences are unavailable, so there is no menu to build; the mod runs on defaults.");
					return;
				}
				Page obj = Page.Root.CreatePage("Wall Grab Jump", Color.cyan, 0, true);
				obj.CreateBool("Enabled", Color.cyan, Prefs.EnabledValue, (Action<bool>)delegate(bool value)
				{
					if (Prefs.Enabled != null)
					{
						Prefs.Enabled.Value = value;
					}
				});
				obj.CreateFloat("Jump Strength", Color.cyan, Prefs.JumpStrengthValue, 0.1f, 0.5f, 3f, (Action<float>)delegate(float value)
				{
					if (Prefs.JumpStrength != null)
					{
						Prefs.JumpStrength.Value = value;
					}
				});
				obj.CreateFloat("Upward Boost", Color.cyan, Prefs.UpwardBoostValue, 0.05f, 0f, 3f, (Action<float>)delegate(float value)
				{
					if (Prefs.UpwardBoost != null)
					{
						Prefs.UpwardBoost.Value = value;
					}
				});
				obj.CreateFloat("Stamina Cost %", Color.cyan, Prefs.StaminaCostValue, 5f, 0f, 50f, (Action<float>)delegate(float value)
				{
					if (Prefs.StaminaCost != null)
					{
						Prefs.StaminaCost.Value = value;
					}
				});
			}
			catch (Exception ex)
			{
				Log.Warning("Could not build the BoneMenu page (" + ex.GetType().Name + "); preferences still work from the config file.");
			}
		}

		internal static void LogMsg(string message)
		{
			Instance logger = _logger;
			if (logger != null)
			{
				logger.Msg(message);
			}
		}

		internal static void LogWarn(string message)
		{
			Instance logger = _logger;
			if (logger != null)
			{
				logger.Warning(message);
			}
		}
	}
	internal static class Log
	{
		internal static void Msg(string message)
		{
			WallGrabJumpMod.LogMsg(message);
		}

		internal static void Warning(string message)
		{
			WallGrabJumpMod.LogWarn(message);
		}

		internal static void Debug(string message)
		{
			if (Prefs.DebugLoggingValue)
			{
				WallGrabJumpMod.LogMsg("[debug] " + message);
			}
		}
	}
	internal sealed class WallJumpController
	{
		private const float BaseJumpSpeed = 3.5f;

		private const float DownwardStrength = 0.45f;

		private const float AbsoluteMaxDeltaV = 16f;

		private const float OutwardInfluence = 0.9f;

		private const float UpInfluence = 0.55f;

		private const float MinOutwardDot = 0.35f;

		private const float MinVerticalComponent = -0.3f;

		private const float AimedVerticalLimit = -1f;

		private const float MinOutwardVertical = -0.25f;

		private const float MinOutwardHorizontal = 0.2f;

		private const float WallTiltFadeStart = 0.3f;

		private const float WallTiltFadeEnd = 0.6f;

		private const float AwayAssistStart = 0.35f;

		private const float InwardAssistStart = 0.75f;

		private const float OverheadFadeStart = -0.2f;

		private const float OverheadFadeEnd = -0.65f;

		private const float WallProbeNear = 0.9f;

		private const float WallProbeFar = 1.6f;

		private const float MaxIntoWallCancel = 1.5f;

		private const float PushDuration = 0.09f;

		private const float MaxReleaseWaitSeconds = 0.03f;

		private const float OutwardClampSeconds = 0.25f;

		private const float OutwardClampTolerance = 0.4f;

		private const float OutwardClampTotal = 2f;

		private const float OutwardClampMaxAssist = 0.5f;

		private const float CooldownSeconds = 0.25f;

		private const float RegrabBlanketSeconds = 0.3f;

		private const float SuccessAmplitude = 0.55f;

		private const float SuccessSeconds = 0.09f;

		private const float SuccessFrequency = 150f;

		private const float DeniedAmplitude = 0.22f;

		private const float DeniedSeconds = 0.035f;

		private const float DeniedFrequency = 110f;

		private const float LateSampleDelay = 0.25f;

		private readonly InputController _input = new InputController();

		private float _readyAt = float.NegativeInfinity;

		private bool _pushing;

		private Vector3 _pushDirection;

		private float _pushBudget;

		private float _pushApplied;

		private float _pushElapsed;

		private bool _clamping;

		private Vector3 _clampOutward;

		private float _clampBaseline;

		private float _clampGravity;

		private float _clampDelivered;

		private float _clampSpent;

		private float _clampStart;

		private float _clampUntil;

		private float _pushHeldFor;

		private bool _saidWaited;

		private bool _diagPending;

		private bool _diagPrePush;

		private float _diagJumpTime;

		private float _diagSampleAt;

		private Vector3 _diagOutward;

		internal void Reset()
		{
			_input.Reset();
			_clamping = false;
			_clampSpent = 0f;
			_diagPending = false;
			_diagPrePush = false;
			_readyAt = float.NegativeInfinity;
			CancelPush();
		}

		private void CancelPush()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			_pushing = false;
			_pushHeldFor = 0f;
			_saidWaited = false;
			_pushDirection = Vector3.zero;
			_pushBudget = 0f;
			_pushApplied = 0f;
			_pushElapsed = 0f;
		}

		internal void Tick()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: 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)
			ClimbAnythingCompatibility.Tick();
			RegrabGuard.Tick();
			bool num = _input.PressedThisFrame();
			VanillaJumpGuard.Tick();
			if (_diagPending && Time.time >= _diagSampleAt)
			{
				_diagPending = false;
				if (PlayerState.IsValid)
				{
					Log.Debug($"Wall jump +{Time.time - _diagJumpTime:0.00}s: body[{Decompose(PlayerState.BodyVelocity, _diagOutward)}]");
				}
			}
			if (!num || !PlayerState.IsValid || Time.time < _readyAt)
			{
				return;
			}
			if (ClimbDetector.Snapshot(out var left, out var right) == 0)
			{
				Log.Debug("Wall jump: A pressed, but neither hand counts as climbing. " + ClimbDetector.DescribeRig());
				return;
			}
			if (ClimbStaminaCompatibility.ClimbingBlocked)
			{
				Deny(left, right);
				Log.Debug("Wall jump refused: ClimbStamina has climbing blocked");
				return;
			}
			if (!ClimbStaminaCompatibility.CanAfford())
			{
				Deny(left, right);
				Log.Debug("Wall jump refused: not enough stamina");
				return;
			}
			float num2 = Mathf.Clamp(Prefs.AimStrictnessValue, 0f, 180f);
			if (num2 < 179.5f)
			{
				float overhead;
				Vector3 val = FindOutward(left, right, out overhead);
				Vector3 val2 = LookDirection();
				if (val != Vector3.zero && val2 != Vector3.zero && Vector3.Angle(val2, val) > num2)
				{
					Deny(left, right);
					Log.Debug($"Wall jump refused: looking {Vector3.Angle(val2, val):0} deg off the wall (limit {num2:0})");
					return;
				}
			}
			Execute(left, right);
		}

		private void Deny(ClimbHold left, ClimbHold right)
		{
			_readyAt = Time.time + 0.25f;
			if (left.Valid)
			{
				Pulse((Handedness)1, 0.035f, 110f, 0.22f);
			}
			if (right.Valid)
			{
				Pulse((Handedness)2, 0.035f, 110f, 0.22f);
			}
		}

		private void Execute(ClimbHold left, ClimbHold right)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: 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_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: 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_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0412: Unknown result type (might be due to invalid IL or missing references)
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			//IL_047e: Unknown result type (might be due to invalid IL or missing references)
			//IL_049c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0564: Unknown result type (might be due to invalid IL or missing references)
			//IL_0569: Unknown result type (might be due to invalid IL or missing references)
			//IL_061a: Unknown result type (might be due to invalid IL or missing references)
			//IL_061c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0635: Unknown result type (might be due to invalid IL or missing references)
			//IL_063a: Unknown result type (might be due to invalid IL or missing references)
			float overhead;
			Vector3 val = FindOutward(left, right, out overhead);
			Vector3 val2 = LookDirection();
			float num = WallPresence(val2, val);
			float num2 = EffectiveAssist(val2, val, num, overhead);
			Vector3 val3 = Compose(val2, val, num2);
			float rawStrength;
			float num3 = AvatarJump.Multiplier(out rawStrength);
			float num4 = 3.5f * Mathf.Clamp(Prefs.JumpStrengthValue, 0.05f, 6f) * Mathf.Lerp(1f, 0.45f, Mathf.Max(0f, 0f - val3.y)) * num3;
			Vector3 val4 = val3 * num4;
			if (!(val == Vector3.zero))
			{
				Vector3.Dot(val4, val);
			}
			float num5 = 0f;
			if (val != Vector3.zero)
			{
				float num6 = Vector3.Dot(PlayerState.BodyVelocity, -val);
				if (num6 > 0f)
				{
					num5 = Mathf.Min(num6, 1.5f);
					val4 += val * num5;
				}
			}
			float num7 = ((Vector3)(ref val4)).magnitude;
			if (!IsFinite(num7) || !IsFinite(val4.x) || !IsFinite(val4.y) || !IsFinite(val4.z))
			{
				Log.Debug("Wall jump aborted: computed a non-finite velocity");
				return;
			}
			if (num7 > 16f)
			{
				Log.Debug($"Wall jump clipped by the {16f:0} m/s ceiling ({num7:0.00} asked for) — Jump Strength and avatar scaling together " + "exceed it, so further increases in either do nothing.");
				val4 = val4 / num7 * 16f;
				num7 = 16f;
			}
			if (num7 < 0.01f)
			{
				return;
			}
			Vector3 bodyVelocity = PlayerState.BodyVelocity;
			int num8 = Release(left) + Release(right);
			if (num8 == 0)
			{
				_readyAt = Time.time + 0.25f;
				Log.Debug("Wall jump aborted: nothing could be released");
				return;
			}
			ClimbStaminaCompatibility.Spend();
			ClimbAnythingCompatibility.SuppressAfterJump(left, right, 0.3f);
			RegrabGuard.Suppress(0.3f);
			VanillaJumpGuard.OnWallJump();
			if (left.Valid)
			{
				RegrabGuard.SuppressHand((Handedness)1);
			}
			if (right.Valid)
			{
				RegrabGuard.SuppressHand((Handedness)2);
			}
			_pushDirection = val4 / num7;
			_pushBudget = num7;
			_pushApplied = 0f;
			_pushElapsed = 0f;
			_pushing = true;
			_readyAt = Time.time + 0.25f;
			if (left.Valid)
			{
				Pulse((Handedness)1, 0.09f, 150f, 0.55f);
			}
			if (right.Valid)
			{
				Pulse((Handedness)2, 0.09f, 150f, 0.55f);
			}
			_clamping = val != Vector3.zero && num2 <= 0.5f;
			if (_clamping)
			{
				_clampOutward = val;
				_clampBaseline = Vector3.Dot(bodyVelocity, val);
				_clampGravity = Vector3.Dot(Physics.gravity, val);
				_clampDelivered = 0f;
				_clampSpent = 0f;
				_clampStart = Time.time;
				_clampUntil = Time.time + 0.25f;
			}
			Log.Debug("Wall jump: rig step at release = " + PlayerState.StepStateName() + ".");
			_diagOutward = val;
			_diagJumpTime = Time.time;
			_diagSampleAt = Time.time + 0.25f;
			_diagPending = Prefs.DebugLoggingValue;
			_diagPrePush = _diagPending;
			Log.Debug($"Wall jump: {num8} hand(s), look=({val2.x:0.00},{val2.y:0.00},{val2.z:0.00}) outward={((val == Vector3.zero) ? "none" : $"({val.x:0.00},{val.y:0.00},{val.z:0.00})")} dot={((val == Vector3.zero) ? 0f : Vector3.Dot(val2, val)):+0.00;-0.00} wall={num:0.00} assist={num2:0.00} | dir[{Decompose(_pushDirection, val)}] dV={num7:0.00} cancel={num5:0.00} avatar[strUpper={rawStrength:0.00} scale={num3:0.00} {AvatarJump.Describe()}] | vel pre-detach body[{Decompose(bodyVelocity, val)}] pelvis[{Decompose(PlayerState.Velocity, val)}]");
		}

		private static int Release(ClimbHold hold)
		{
			if (!hold.Valid)
			{
				return 0;
			}
			try
			{
				switch (hold.Source)
				{
				case ClimbSource.Vanilla:
					if ((Object)(object)hold.Grip == (Object)null || (Object)(object)hold.Hand == (Object)null)
					{
						return 0;
					}
					hold.Grip.ForceDetach(hold.Hand);
					return 1;
				case ClimbSource.ClimbAnything:
					return ClimbAnythingCompatibility.Release(hold) ? 1 : 0;
				}
			}
			catch (Exception ex)
			{
				Log.Debug("Release failed (" + ex.GetType().Name + ")");
			}
			return 0;
		}

		private static bool IsFinite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}

		private static Vector3 LookDirection()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			Transform head = PlayerState.Head;
			if ((Object)(object)head == (Object)null)
			{
				return Vector3.zero;
			}
			Vector3 forward = head.forward;
			if (!(((Vector3)(ref forward)).sqrMagnitude < 1E-06f))
			{
				return ((Vector3)(ref forward)).normalized;
			}
			return Vector3.zero;
		}

		internal static Vector3 Compose(Vector3 look, Vector3 outward)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			return Compose(look, outward, EffectiveAssist(look, outward, 1f, 0f));
		}

		internal static Vector3 Compose(Vector3 look, Vector3 outward, float assist)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_008a: 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)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp(Prefs.LookInfluenceValue, 0f, 5f);
			float num2 = Mathf.Clamp(Prefs.OutwardPushValue, 0f, 5f);
			float num3 = Mathf.Clamp(Prefs.UpwardBoostValue, 0f, 5f);
			Vector3 val = look * num + outward * (num2 * assist) + Vector3.up * (num3 * assist);
			if (((Vector3)(ref val)).sqrMagnitude < 1E-06f)
			{
				val = ((outward != Vector3.zero) ? (outward + Vector3.up * 0.5f) : Vector3.up);
			}
			float floor = Mathf.Clamp(Prefs.OutwardFloorValue, 0f, 0.95f) * assist;
			float lowest = Mathf.Lerp(-1f, -0.3f, assist);
			return ApplyLimits(((Vector3)(ref val)).normalized, outward, floor, lowest);
		}

		private static float EffectiveAssist(Vector3 look, Vector3 outward, float wallPresence, float overhead)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp(Prefs.LookInfluenceValue, 0f, 5f);
			float num2 = WallAssist(look, outward);
			if (Vector3.Dot(look, outward) < 0f)
			{
				num2 *= Mathf.Clamp01(wallPresence);
			}
			num2 *= 1f - Mathf.Clamp01(overhead);
			return Mathf.Lerp(1f, num2, Mathf.Clamp01(num));
		}

		private static float WallPresence(Vector3 look, Vector3 outward)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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_00d1: 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)
			if (look == Vector3.zero || outward == Vector3.zero)
			{
				return 1f;
			}
			if (Vector3.Dot(look, outward) >= 0f)
			{
				return 1f;
			}
			try
			{
				Vector3 bodyCentre = PlayerState.BodyCentre;
				Transform val = null;
				PhysicsRig physics = LocalRig.Physics;
				if ((Object)(object)physics != (Object)null)
				{
					val = ((Component)physics).transform.root;
				}
				Il2CppStructArray<RaycastHit> val2 = Physics.RaycastAll(bodyCentre, look, 1.6f, -5, (QueryTriggerInteraction)1);
				if (val2 == null)
				{
					return 0f;
				}
				float num = float.MaxValue;
				for (int i = 0; i < ((Il2CppArrayBase<RaycastHit>)(object)val2).Length; i++)
				{
					RaycastHit val3 = ((Il2CppArrayBase<RaycastHit>)(object)val2)[i];
					Collider collider = ((RaycastHit)(ref val3)).collider;
					if (!((Object)(object)collider == (Object)null) && (!((Object)(object)val != (Object)null) || !((Object)(object)((Component)collider).transform.root == (Object)(object)val)))
					{
						val3 = ((Il2CppArrayBase<RaycastHit>)(object)val2)[i];
						if (((RaycastHit)(ref val3)).distance < num)
						{
							val3 = ((Il2CppArrayBase<RaycastHit>)(object)val2)[i];
							num = ((RaycastHit)(ref val3)).distance;
						}
					}
				}
				if (num == float.MaxValue)
				{
					return 0f;
				}
				return 1f - Mathf.Clamp01(Mathf.InverseLerp(0.9f, 1.6f, num));
			}
			catch (Exception ex)
			{
				Log.Debug("Wall presence probe failed (" + ex.GetType().Name + ")");
				return 1f;
			}
		}

		private static float WallAssist(Vector3 look, Vector3 outward)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			if (look == Vector3.zero)
			{
				return 1f;
			}
			if (outward == Vector3.zero)
			{
				return 0f;
			}
			float num = Vector3.Dot(look, outward);
			float num2 = ((num >= 0f) ? Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(0.35f, 1f, num)) : Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(0.75f, 1f, 0f - num)));
			float num3 = Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(0.3f, 0.6f, Mathf.Abs(outward.y)));
			return Mathf.Lerp(num2, 1f, num3);
		}

		private static Vector3 ApplyLimits(Vector3 direction, Vector3 outward, float floor, float lowest)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_00a7: 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_00c9: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: 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_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			if (outward == Vector3.zero)
			{
				return RaiseAbove(direction, outward, lowest);
			}
			float num = Mathf.Clamp(outward.y, -1f, 1f);
			Vector3 val = Vector3.up - outward * num;
			if (((Vector3)(ref val)).sqrMagnitude < 1E-08f)
			{
				float minY = ((num > 0f) ? Mathf.Max(floor, lowest) : lowest);
				return RaiseAbove(direction, outward, minY);
			}
			val = ((Vector3)(ref val)).normalized;
			float num2 = Vector3.Dot(direction, outward);
			if (num2 < floor)
			{
				Vector3 val2 = direction - outward * num2;
				if (((Vector3)(ref val2)).sqrMagnitude < 1E-06f)
				{
					val2 = val;
				}
				Vector3 val3 = outward * floor + ((Vector3)(ref val2)).normalized * Mathf.Sqrt(Mathf.Max(0f, 1f - floor * floor));
				direction = ((Vector3)(ref val3)).normalized;
			}
			if (direction.y >= lowest)
			{
				return direction;
			}
			float num3 = 1f;
			for (int i = 0; i < 20; i++)
			{
				if (!(LeanHeight(direction, outward, num3) < lowest))
				{
					break;
				}
				num3 *= 2f;
			}
			float num4 = 0f;
			for (int j = 0; j < 32; j++)
			{
				float num5 = (num4 + num3) * 0.5f;
				if (LeanHeight(direction, outward, num5) < lowest)
				{
					num4 = num5;
				}
				else
				{
					num3 = num5;
				}
			}
			Vector3 val4 = direction + outward * num3;
			if (!(((Vector3)(ref val4)).sqrMagnitude < 1E-06f))
			{
				return ((Vector3)(ref val4)).normalized;
			}
			return direction;
		}

		private static float LeanHeight(Vector3 direction, Vector3 outward, float lean)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = direction + outward * lean;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (!(magnitude < 1E-06f))
			{
				return val.y / magnitude;
			}
			return direction.y;
		}

		private static Vector3 RaiseAbove(Vector3 direction, Vector3 outward, float minY)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			minY = Mathf.Clamp(minY, -1f, 1f);
			if (direction.y >= minY)
			{
				return direction;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(direction.x, 0f, direction.z);
			if (((Vector3)(ref val)).sqrMagnitude < 1E-06f)
			{
				((Vector3)(ref val))..ctor(outward.x, 0f, outward.z);
			}
			if (((Vector3)(ref val)).sqrMagnitude < 1E-06f)
			{
				return direction;
			}
			val = ((Vector3)(ref val)).normalized * Mathf.Sqrt(Mathf.Max(0f, 1f - minY * minY));
			return new Vector3(val.x, minY, val.z);
		}

		private static Vector3 FindOutward(ClimbHold left, ClimbHold right, out float overhead)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00b5: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			overhead = 0f;
			Vector3 val;
			if (left.Valid && right.Valid)
			{
				val = (left.Anchor + right.Anchor) * 0.5f;
			}
			else if (left.Valid)
			{
				val = left.Anchor;
			}
			else
			{
				if (!right.Valid)
				{
					return Vector3.zero;
				}
				val = right.Anchor;
			}
			Vector3 bodyCentre = PlayerState.BodyCentre;
			if (TryCastToSurface(bodyCentre, val, out var normal) || TryClosestPoint(left, right, bodyCentre, out normal) || PlayerState.TryGetMarrowClimbNormal(out normal))
			{
				overhead = Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(-0.2f, -0.65f, normal.y));
				Vector3 val2 = LimitDownward(normal);
				if (val2 != Vector3.zero)
				{
					return val2;
				}
			}
			Vector3 val3 = bodyCentre - val;
			val3.y = 0f;
			if (((Vector3)(ref val3)).sqrMagnitude > 0.0025f)
			{
				return ((Vector3)(ref val3)).normalized;
			}
			overhead = 1f;
			return Vector3.zero;
		}

		private static bool TryCastToSurface(Vector3 body, Vector3 anchor, out Vector3 normal)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			normal = Vector3.zero;
			Vector3 val = anchor - body;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.05f)
			{
				return false;
			}
			try
			{
				Transform val2 = null;
				PhysicsRig physics = LocalRig.Physics;
				if ((Object)(object)physics != (Object)null)
				{
					val2 = ((Component)physics).transform.root;
				}
				Il2CppStructArray<RaycastHit> val3 = Physics.RaycastAll(body, val / magnitude, magnitude + 0.4f, -5, (QueryTriggerInteraction)1);
				if (val3 == null)
				{
					return false;
				}
				float num = float.MaxValue;
				float num2 = magnitude * 0.5f;
				for (int i = 0; i < ((Il2CppArrayBase<RaycastHit>)(object)val3).Length; i++)
				{
					RaycastHit val4 = ((Il2CppArrayBase<RaycastHit>)(object)val3)[i];
					if (((RaycastHit)(ref val4)).distance < num2 || ((RaycastHit)(ref val4)).distance >= num)
					{
						continue;
					}
					Collider collider = ((RaycastHit)(ref val4)).collider;
					if (!((Object)(object)collider == (Object)null) && (!((Object)(object)val2 != (Object)null) || !((Object)(object)((Component)collider).transform.root == (Object)(object)val2)))
					{
						Vector3 normal2 = ((RaycastHit)(ref val4)).normal;
						if (!(((Vector3)(ref normal2)).sqrMagnitude < 0.25f))
						{
							num = ((RaycastHit)(ref val4)).distance;
							normal2 = ((RaycastHit)(ref val4)).normal;
							normal = ((Vector3)(ref normal2)).normalized;
						}
					}
				}
				return num < float.MaxValue;
			}
			catch (Exception ex)
			{
				Log.Debug("Surface cast failed (" + ex.GetType().Name + ")");
				return false;
			}
		}

		private static bool TryClosestPoint(ClimbHold left, ClimbHold right, Vector3 body, out Vector3 normal)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			normal = Vector3.zero;
			Vector3 val = Vector3.zero;
			int num = 0;
			for (int i = 0; i < 2; i++)
			{
				ClimbHold climbHold = ((i == 0) ? left : right);
				if (!climbHold.Valid || (Object)(object)climbHold.Surface == (Object)null)
				{
					continue;
				}
				try
				{
					Vector3 val2 = body - climbHold.Surface.ClosestPoint(body);
					if (!(((Vector3)(ref val2)).sqrMagnitude < 0.0004f))
					{
						val += ((Vector3)(ref val2)).normalized;
						num++;
					}
				}
				catch
				{
				}
			}
			if (num == 0 || ((Vector3)(ref val)).sqrMagnitude < 1E-06f)
			{
				return false;
			}
			normal = ((Vector3)(ref val)).normalized;
			return true;
		}

		private static Vector3 LimitDownward(Vector3 normal)
		{
			//IL_0000: 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)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (normal.y >= -0.25f)
			{
				return normal;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(normal.x, 0f, normal.z);
			if (((Vector3)(ref val)).sqrMagnitude < 0.040000003f)
			{
				return Vector3.zero;
			}
			float num = -0.25f;
			val = ((Vector3)(ref val)).normalized * Mathf.Sqrt(1f - num * num);
			return new Vector3(val.x, num, val.z);
		}

		internal void FixedTick(float fixedDeltaTime)
		{
			ApplyPush(fixedDeltaTime);
			ApplyOutwardClamp();
		}

		private void ApplyPush(float fixedDeltaTime)
		{
			//IL_00b1: 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_00e0: 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_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: 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_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			if (!_pushing)
			{
				return;
			}
			if (fixedDeltaTime <= 0f || !PlayerState.IsValid)
			{
				CancelPush();
				return;
			}
			Rigidbody[] array = PlayerState.RigBodies();
			if (array == null || array.Length == 0)
			{
				CancelPush();
				return;
			}
			if (_diagPrePush)
			{
				_diagPrePush = false;
				Log.Debug($"Wall jump post-detach (+{Time.time - _diagJumpTime:0.00}s, before push): step={PlayerState.StepStateName()} body[{Decompose(PlayerState.BodyVelocity, _diagOutward)}] pelvis[{Decompose(PlayerState.Velocity, _diagOutward)}]");
			}
			if (_pushApplied <= 0f && _pushHeldFor < 0.03f && PlayerState.RigStillClimbing)
			{
				_pushHeldFor += fixedDeltaTime;
				if (!_saidWaited)
				{
					_saidWaited = true;
					Log.Debug("Wall jump: holding the push, the rig is still " + PlayerState.StepStateName() + ".");
				}
				return;
			}
			if (_saidWaited && _pushApplied <= 0f)
			{
				Log.Debug($"Wall jump: pushing after {_pushHeldFor * 1000f:0} ms, rig is now {PlayerState.StepStateName()}.");
			}
			_pushElapsed += fixedDeltaTime;
			float num = _pushBudget * (fixedDeltaTime / 0.09f);
			float num2 = _pushBudget - _pushApplied;
			if (num > num2)
			{
				num = num2;
			}
			if (num > 1E-05f)
			{
				_pushApplied += num;
				if (_clamping)
				{
					_clampDelivered += num * Vector3.Dot(_pushDirection, _clampOutward);
				}
				Vector3 val = _pushDirection * num;
				foreach (Rigidbody val2 in array)
				{
					if (!((Object)(object)val2 == (Object)null) && !val2.isKinematic)
					{
						val2.AddForce(val, (ForceMode)2);
					}
				}
			}
			if (_pushApplied >= _pushBudget - 1E-05f || _pushElapsed >= 0.09f)
			{
				if (_diagPending)
				{
					Log.Debug($"Wall jump push done (+{_pushElapsed:0.00}s): body[{Decompose(PlayerState.BodyVelocity, _diagOutward)}]");
				}
				CancelPush();
			}
		}

		private void ApplyOutwardClamp()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if (!_clamping)
			{
				return;
			}
			if (Time.time >= _clampUntil || !PlayerState.IsValid)
			{
				_clamping = false;
				return;
			}
			float num = _clampBaseline + _clampDelivered + _clampGravity * (Time.time - _clampStart);
			float num2 = Vector3.Dot(PlayerState.BodyVelocity, _clampOutward) - num - 0.4f;
			if (!IsFinite(num2))
			{
				_clamping = false;
			}
			else
			{
				if (num2 <= 0f)
				{
					return;
				}
				float num3 = 2f - _clampSpent;
				if (num3 <= 0f)
				{
					_clamping = false;
					return;
				}
				if (num2 > num3)
				{
					num2 = num3;
				}
				Rigidbody[] array = PlayerState.RigBodies();
				if (array == null || array.Length == 0)
				{
					_clamping = false;
					return;
				}
				_clampSpent += num2;
				Vector3 val = _clampOutward * (0f - num2);
				foreach (Rigidbody val2 in array)
				{
					if (!((Object)(object)val2 == (Object)null) && !val2.isKinematic)
					{
						val2.AddForce(val, (ForceMode)2);
					}
				}
				if (_diagPending)
				{
					Log.Debug($"Wall jump clamp (+{Time.time - _diagJumpTime:0.00}s): trimmed {num2:0.00} m/s unexplained outward ({_clampSpent:0.00} of {2f:0.0} total)");
				}
			}
		}

		private static string Decompose(Vector3 v, Vector3 outward)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_008c: 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_008f: 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)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_00d5: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			if (!(outward == Vector3.zero))
			{
				float num = Vector3.Dot(v, outward);
				Vector3 val = v - outward * num;
				Vector3 val2 = Vector3.up - outward * outward.y;
				float num2 = 0f;
				if (((Vector3)(ref val2)).sqrMagnitude > 1E-06f)
				{
					val2 = ((Vector3)(ref val2)).normalized;
					num2 = Vector3.Dot(val, val2);
					val -= val2 * num2;
				}
				return $"out {num:+0.00;-0.00} up {num2:+0.00;-0.00} side {((Vector3)(ref val)).magnitude:0.00}";
			}
			return $"({v.x:0.00}, {v.y:0.00}, {v.z:0.00})";
		}

		private static void Pulse(Handedness side, float seconds, float frequency, float amplitude)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				BaseController val = LocalRig.Controller(side);
				if (!((Object)(object)val == (Object)null))
				{
					Haptor haptor = val.haptor;
					if (!((Object)(object)haptor == (Object)null) && haptor.hapticsAllowed)
					{
						haptor.SENDHAPTIC(0f, seconds, frequency, Mathf.Clamp01(amplitude));
					}
				}
			}
			catch (Exception ex)
			{
				Log.Debug("Haptic pulse failed (" + ex.GetType().Name + ")");
			}
		}
	}
}
namespace WallGrabJump.Compatibility
{
	internal static class ClimbAnythingCompatibility
	{
		private const float GripHeldThreshold = 0.01f;

		private const float UnreadableGripGrace = 1.5f;

		private static bool _looked;

		private static Harmony _harmony;

		private static object _melon;

		private static FieldInfo _leftStateField;

		private static FieldInfo _rightStateField;

		private static FieldInfo _handField;

		private static FieldInfo _climbPointField;

		private static FieldInfo _isClimbingField;

		private static MethodInfo _stopClimbing;

		private static object _leftState;

		private static object _rightState;

		private static bool _leftSuppressed;

		private static bool _rightSuppressed;

		private static float _leftUnreadableSince = -1f;

		private static float _rightUnreadableSince = -1f;

		private static float _blockAllUntil = float.NegativeInfinity;

		private static int _faults;

		private static float _lastFaultAt = float.NegativeInfinity;

		private const int MaxFaults = 5;

		private const float FaultWindow = 10f;

		internal static bool Active { get; private set; }

		internal static void Initialize(Harmony harmony)
		{
			_harmony = harmony;
			if (!_looked)
			{
				MelonBase val = MelonBase.FindMelon("ClimbAnything", "Waspothegreat");
				if (val != null)
				{
					_looked = true;
					TryBind(val);
				}
			}
		}

		internal static void Retry(Harmony harmony)
		{
			if (_harmony == null)
			{
				_harmony = harmony;
			}
			if (!_looked && _harmony != null)
			{
				_looked = true;
				MelonBase val = MelonBase.FindMelon("ClimbAnything", "Waspothegreat");
				if (val != null)
				{
					TryBind(val);
				}
			}
		}

		private static void TryBind(MelonBase melon)
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			try
			{
				Type type = ((object)melon).GetType();
				_leftStateField = type.GetField("_leftHandState", BindingFlags.Instance | BindingFlags.NonPublic);
				_rightStateField = type.GetField("_rightHandState", BindingFlags.Instance | BindingFlags.NonPublic);
				Type nestedType = type.GetNestedType("HandState", BindingFlags.Public | BindingFlags.NonPublic);
				_handField = nestedType?.GetField("Hand", BindingFlags.Instance | BindingFlags.Public);
				_climbPointField = nestedType?.GetField("ClimbPoint", BindingFlags.Instance | BindingFlags.Public);
				_isClimbingField = nestedType?.GetField("IsClimbing", BindingFlags.Instance | BindingFlags.Public);
				MethodInfo method = type.GetMethod("StartClimbing", BindingFlags.Instance | BindingFlags.NonPublic);
				_stopClimbing = type.GetMethod("StopClimbing", BindingFlags.Instance | BindingFlags.NonPublic);
				if (!ShapeIsSupported(method, nestedType))
				{
					Log.Warning("ClimbAnything is installed but its internals don't match the supported layout (verified against 1.0.0 / package 1.0.1). Wall jumping from ClimbAnything holds is disabled; vanilla climbing still works and ClimbAnything itself is untouched.");
					return;
				}
				_melon = melon;
				_harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(ClimbAnythingCompatibility), "StartClimbingPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Active = true;
				MelonInfoAttribute info = melon.Info;
				Log.Msg("ClimbAnything " + (((info != null) ? info.Version : null) ?? "?") + " detected — wall jumping works from its holds, and a hand that jumps needs a fresh grip before it can climb again.");
			}
			catch (Exception ex)
			{
				Active = false;
				Log.Warning($"Could not set up ClimbAnything compatibility ({ex.GetType().Name}: {ex.Message}). " + "Vanilla wall jumping still works; ClimbAnything itself is untouched.");
			}
		}

		private static bool ShapeIsSupported(MethodInfo startClimbing, Type handStateType)
		{
			if (handStateType == null || startClimbing == null || _stopClimbing == null)
			{
				return false;
			}
			if (_leftStateField == null || _rightStateField == null)
			{
				return false;
			}
			if (_handField == null || _climbPointField == null || _isClimbingField == null)
			{
				return false;
			}
			if (_handField.FieldType != typeof(Hand))
			{
				return false;
			}
			if (_isClimbingField.FieldType != typeof(bool))
			{
				return false;
			}
			if (!typeof(Object).IsAssignableFrom(_climbPointField.FieldType))
			{
				return false;
			}
			ParameterInfo[] parameters = startClimbing.GetParameters();
			if (parameters.Length != 2 || parameters[0].ParameterType != handStateType)
			{
				return false;
			}
			ParameterInfo[] parameters2 = _stopClimbing.GetParameters();
			if (parameters2.Length != 1 || parameters2[0].ParameterType != handStateType)
			{
				return false;
			}
			return true;
		}

		internal static ClimbHold Evaluate(Hand hand, Handedness side)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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)
			if (!Active || (Object)(object)hand == (Object)null)
			{
				return default(ClimbHold);
			}
			try
			{
				object obj = StateFor(side);
				if (obj == null)
				{
					return default(ClimbHold);
				}
				if (!(bool)_isClimbingField.GetValue(obj))
				{
					return default(ClimbHold);
				}
				object? value = _climbPointField.GetValue(obj);
				Object val = (Object)((value is Object) ? value : null);
				if (val == (Object)null)
				{
					return default(ClimbHold);
				}
				object? value2 = _handField.GetValue(obj);
				Hand val2 = (Hand)((value2 is Hand) ? value2 : null);
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)hand)
				{
					return default(ClimbHold);
				}
				ClimbHold result = new ClimbHold
				{
					Source = ClimbSource.ClimbAnything,
					Side = side,
					Hand = hand,
					State = obj,
					Anchor = ((Component)hand).transform.position
				};
				GameObject val3 = ((Il2CppObjectBase)val).TryCast<GameObject>();
				if ((Object)(object)val3 != (Object)null)
				{
					result.Anchor = val3.transform.position;
					Transform parent = val3.transform.parent;
					if ((Object)(object)parent != (Object)null)
					{
						result.Surface = ((Component)parent).GetComponent<Collider>();
					}
				}
				return result;
			}
			catch (Exception e)
			{
				Fault(e);
				return default(ClimbHold);
			}
		}

		private static object StateFor(Handedness side)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			if (_melon == null)
			{
				return null;
			}
			if ((int)side == 1)
			{
				return _leftState ?? (_leftState = _leftStateField.GetValue(_melon));
			}
			if ((int)side == 2)
			{
				return _rightState ?? (_rightState = _rightStateField.GetValue(_melon));
			}
			return null;
		}

		internal static bool Release(ClimbHold hold)
		{
			if (!Active || hold.Source != ClimbSource.ClimbAnything || hold.State == null)
			{
				return false;
			}
			try
			{
				_stopClimbing.Invoke(_melon, new object[1] { hold.State });
				return true;
			}
			catch (Exception e)
			{
				Fault(e);
				return false;
			}
		}

		internal static void SuppressAfterJump(ClimbHold left, ClimbHold right, float blanketSeconds)
		{
			_blockAllUntil = Time.time + blanketSeconds;
			if (left.Valid)
			{
				_leftSuppressed = true;
				_leftUnreadableSince = -1f;
			}
			if (right.Valid)
			{
				_rightSuppressed = true;
				_rightUnreadableSince = -1f;
			}
		}

		internal static void Tick()
		{
			if (_leftSuppressed || _rightSuppressed)
			{
				if (_leftSuppressed && GripReleased((Handedness)1, ref _leftUnreadableSince))
				{
					_leftSuppressed = false;
					Log.Debug("Left hand may climb again (grip released)");
				}
				if (_rightSuppressed && GripReleased((Handedness)2, ref _rightUnreadableSince))
				{
					_rightSuppressed = false;
					Log.Debug("Right hand may climb again (grip released)");
				}
			}
		}

		private static bool GripReleased(Handedness side, ref float unreadableSince)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			float time = Time.time;
			try
			{
				BaseController val = null;
				val = LocalRig.Controller(side);
				if ((Object)(object)val == (Object)null)
				{
					if (unreadableSince < 0f)
					{
						unreadableSince = time;
					}
					return time - unreadableSince >= 1.5f;
				}
				unreadableSince = -1f;
				return val.GetGripForce() <= 0.01f;
			}
			catch
			{
				if (unreadableSince < 0f)
				{
					unreadableSince = time;
				}
				return time - unreadableSince >= 1.5f;
			}
		}

		internal static void ClearSuppression()
		{
			_leftSuppressed = false;
			_rightSuppressed = false;
			_leftUnreadableSince = -1f;
			_rightUnreadableSince = -1f;
			_blockAllUntil = float.NegativeInfinity;
		}

		private static bool StartClimbingPrefix(object __0)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Invalid comparison between Unknown and I4
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Invalid comparison between Unknown and I4
			if (!Active)
			{
				return true;
			}
			if (!_leftSuppressed && !_rightSuppressed && Time.time >= _blockAllUntil)
			{
				return true;
			}
			try
			{
				if (Time.time < _blockAllUntil)
				{
					return false;
				}
				if (__0 == _leftState)
				{
					return !_leftSuppressed;
				}
				if (__0 == _rightState)
				{
					return !_rightSuppressed;
				}
				object? value = _handField.GetValue(__0);
				Hand val = (Hand)((value is Hand) ? value : null);
				if ((Object)(object)val == (Object)null)
				{
					return true;
				}
				Handedness handedness = val.handedness;
				if ((int)handedness != 1)
				{
					if ((int)handedness == 2)
					{
						return !_rightSuppressed;
					}
					return true;
				}
				return !_leftSuppressed;
			}
			catch (Exception e)
			{
				Fault(e);
				return true;
			}
		}

		private static void Fault(Exception e)
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (realtimeSinceStartup - _lastFaultAt > 10f)
			{
				_faults = 0;
			}
			_lastFaultAt = realtimeSinceStartup;
			_faults++;
			if (_faults == 1)