Decompiled source of RealControl v1.0.1

plugins/RealControl.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("RealControl")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RealControl")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("486de57c-6d4c-406a-adf7-a4433b917004")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("Sapphire009.RealControl", "RealControl", "1.0.2")]
public sealed class RealControlPlugin : BaseUnityPlugin
{
	private enum ExpectedHand
	{
		Left,
		Right
	}

	private enum StepDirection
	{
		Up,
		Down,
		Left,
		Right
	}

	private sealed class InputState
	{
		public bool WasControlledWallClimbing;

		public float LastPrimaryPressedTime = float.NegativeInfinity;

		public ExpectedHand NextHand = ExpectedHand.Left;
	}

	[HarmonyPatch(typeof(CharacterInput), "Sample", new Type[] { typeof(bool) })]
	private static class CharacterInputSamplePatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		[HarmonyAfter(new string[] { "Sapphire009.WASDX", "Sapphire009.JumpingPEAK" })]
		private static void Postfix(CharacterInput __instance)
		{
			//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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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)
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			Character component = ((Component)__instance).GetComponent<Character>();
			if ((Object)(object)component == (Object)null || !component.IsLocal)
			{
				return;
			}
			InputState orCreateState = GetOrCreateState(__instance);
			Vector2 movementInput = __instance.movementInput;
			bool upHeld = ReadUpHeld(movementInput);
			bool leftHeld = ReadLeftHeld(movementInput);
			bool rightHeld = ReadRightHeld(movementInput);
			bool downHeld = ReadDownHeld(movementInput);
			if (!IsControlledWallClimbing(component))
			{
				if (__instance.usePrimaryWasPressed)
				{
					orCreateState.LastPrimaryPressedTime = Time.unscaledTime;
				}
				orCreateState.WasControlledWallClimbing = false;
			}
			else
			{
				if (!orCreateState.WasControlledWallClimbing)
				{
					BeginControlledClimb(component, orCreateState);
				}
				ProcessControlledClimbInput(__instance, component, orCreateState, upHeld, leftHeld, rightHeld, downHeld);
			}
		}
	}

	public const string PluginGUID = "Sapphire009.RealControl";

	public const string PluginName = "RealControl";

	public const string PluginVersion = "1.0.2";

	private const string BuildMarker = "DirectionalAlternatingInput-Stamina-R3";

	private const float NormalGrabDetectionWindow = 0.75f;

	private const float MinimumDirectionSqrMagnitude = 0.0001f;

	private const float StepStaminaCost = 0.05f;

	internal static ManualLogSource ModLogger;

	private static ConfigEntry<float> upStepDistance;

	private static ConfigEntry<float> sideStepDistance;

	private static ConfigEntry<float> downStepDistance;

	private static ConfigEntry<bool> logSuccessfulSteps;

	private static readonly Dictionary<int, InputState> InputStates = new Dictionary<int, InputState>();

	private Harmony harmony;

	private void Awake()
	{
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Expected O, but got Unknown
		ModLogger = ((BaseUnityPlugin)this).Logger;
		upStepDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Climb Step", "UpStepDistance", 1.5f, "W를 누른 상태에서 올바른 좌클릭/우클릭 교대 입력 1회당 위로 이동할 거리입니다.");
		sideStepDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Climb Step", "SideStepDistance", 1.5f, "A 또는 D를 누른 상태에서 올바른 좌클릭/우클릭 교대 입력 1회당 좌우로 이동할 거리입니다.");
		downStepDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Climb Step", "DownStepDistance", 1.5f, "S를 누른 상태에서 올바른 좌클릭/우클릭 교대 입력 1회당 아래로 이동할 거리입니다.");
		logSuccessfulSteps = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogSuccessfulSteps", false, "true이면 적용된 등반 스텝을 로그에 기록합니다.");
		harmony = new Harmony("Sapphire009.RealControl");
		harmony.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"RealControl 1.0.2 loaded. Developer=Sapphire009. Build=DirectionalAlternatingInput-Stamina-R3.");
	}

	private void OnDestroy()
	{
		InputStates.Clear();
		if (harmony != null)
		{
			harmony.UnpatchSelf();
			harmony = null;
		}
		ModLogger = null;
	}

	private static InputState GetOrCreateState(CharacterInput characterInput)
	{
		int instanceID = ((Object)characterInput).GetInstanceID();
		if (!InputStates.TryGetValue(instanceID, out var value))
		{
			value = new InputState();
			InputStates.Add(instanceID, value);
		}
		return value;
	}

	private static bool IsControlledWallClimbing(Character character)
	{
		if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || character.refs == null || (Object)(object)character.refs.climbing == (Object)null)
		{
			return false;
		}
		return character.data.isClimbing && !character.data.isRopeClimbing && !character.data.isVineClimbing && (Object)(object)character.data.currentClimbHandle == (Object)null;
	}

	private static bool ReadUpHeld(Vector2 sampledMovement)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		if (CharacterInput.action_moveForward != null)
		{
			return CharacterInput.action_moveForward.IsPressed();
		}
		return sampledMovement.y > 0.5f;
	}

	private static bool ReadLeftHeld(Vector2 sampledMovement)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		if (CharacterInput.action_moveLeft != null)
		{
			return CharacterInput.action_moveLeft.IsPressed();
		}
		return sampledMovement.x < -0.5f;
	}

	private static bool ReadRightHeld(Vector2 sampledMovement)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		if (CharacterInput.action_moveRight != null)
		{
			return CharacterInput.action_moveRight.IsPressed();
		}
		return sampledMovement.x > 0.5f;
	}

	private static bool ReadDownHeld(Vector2 sampledMovement)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		if (CharacterInput.action_moveBackward != null)
		{
			return CharacterInput.action_moveBackward.IsPressed();
		}
		return sampledMovement.y < -0.5f;
	}

	private static bool TryGetHeldDirection(bool upHeld, bool leftHeld, bool rightHeld, bool downHeld, out StepDirection stepDirection)
	{
		stepDirection = StepDirection.Up;
		int num = 0;
		if (upHeld)
		{
			stepDirection = StepDirection.Up;
			num++;
		}
		if (downHeld)
		{
			stepDirection = StepDirection.Down;
			num++;
		}
		if (leftHeld)
		{
			stepDirection = StepDirection.Left;
			num++;
		}
		if (rightHeld)
		{
			stepDirection = StepDirection.Right;
			num++;
		}
		return num == 1;
	}

	private static void BeginControlledClimb(Character character, InputState state)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		bool flag = Time.unscaledTime - state.LastPrimaryPressedTime <= 0.75f;
		state.NextHand = (flag ? ExpectedHand.Right : ExpectedHand.Left);
		character.refs.climbing.playerSlide = Vector2.zero;
		state.WasControlledWallClimbing = true;
	}

	private static bool HasEnoughStepStamina(Character character)
	{
		if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null)
		{
			return false;
		}
		float num = Mathf.Max(0f, character.data.currentStamina) + Mathf.Max(0f, character.data.extraStamina);
		return num + 0.0001f >= 0.05f;
	}

	private static bool ConsumeStepStamina(Character character)
	{
		if (!HasEnoughStepStamina(character))
		{
			return false;
		}
		float num = 0.05f;
		float num2 = Mathf.Min(Mathf.Max(0f, character.data.currentStamina), num);
		CharacterData data = character.data;
		data.currentStamina -= num2;
		num -= num2;
		if (num > 0f)
		{
			float num3 = Mathf.Min(Mathf.Max(0f, character.data.extraStamina), num);
			CharacterData data2 = character.data;
			data2.extraStamina -= num3;
			num -= num3;
		}
		character.ClampStamina();
		character.data.extraStamina = Mathf.Max(0f, character.data.extraStamina);
		character.data.sinceUseStamina = 0f;
		if ((Object)(object)GUIManager.instance != (Object)null && (Object)(object)GUIManager.instance.bar != (Object)null)
		{
			GUIManager.instance.bar.ChangeBar();
		}
		return num <= 0.0001f;
	}

	private static bool TryApplyStep(Character character, StepDirection stepDirection)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: 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_007d: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: 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_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: 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_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_026f: Unknown result type (might be due to invalid IL or missing references)
		if (!IsControlledWallClimbing(character))
		{
			return false;
		}
		Vector3 climbNormal = character.data.climbNormal;
		if (((Vector3)(ref climbNormal)).sqrMagnitude < 0.0001f)
		{
			return false;
		}
		((Vector3)(ref climbNormal)).Normalize();
		Vector3 val = Vector3.ProjectOnPlane(Vector3.up, climbNormal);
		if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
		{
			return false;
		}
		((Vector3)(ref val)).Normalize();
		Vector3 val2 = Vector3.Cross(climbNormal, val);
		if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
		{
			return false;
		}
		((Vector3)(ref val2)).Normalize();
		Vector3 val3 = Vector3.zero;
		switch (stepDirection)
		{
		case StepDirection.Up:
			val3 = val * Mathf.Max(0.01f, upStepDistance.Value);
			break;
		case StepDirection.Down:
			val3 = -val * Mathf.Max(0.01f, downStepDistance.Value);
			break;
		case StepDirection.Left:
			val3 = -val2 * Mathf.Max(0.01f, sideStepDistance.Value);
			break;
		case StepDirection.Right:
			val3 = val2 * Mathf.Max(0.01f, sideStepDistance.Value);
			break;
		}
		if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f)
		{
			return false;
		}
		if (!ConsumeStepStamina(character))
		{
			return false;
		}
		character.refs.climbing.playerSlide = Vector2.zero;
		CharacterData data = character.data;
		data.climbPos += val3;
		character.data.sinceGrounded = 0f;
		if (logSuccessfulSteps.Value)
		{
			ManualLogSource modLogger = ModLogger;
			if (modLogger != null)
			{
				modLogger.LogInfo((object)($"[RealControl] Step={stepDirection}, " + $"Distance={((Vector3)(ref val3)).magnitude:0.000}, " + $"StaminaCost={0.05f:0.00}, " + $"CurrentStamina={character.data.currentStamina:0.000}, " + $"ExtraStamina={character.data.extraStamina:0.000}, " + $"ClimbPos={character.data.climbPos}"));
			}
		}
		return true;
	}

	private static void ProcessControlledClimbInput(CharacterInput characterInput, Character character, InputState state, bool upHeld, bool leftHeld, bool rightHeld, bool downHeld)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		bool usePrimaryWasPressed = characterInput.usePrimaryWasPressed;
		bool useSecondaryWasPressed = characterInput.useSecondaryWasPressed;
		characterInput.movementInput = Vector2.zero;
		characterInput.usePrimaryWasReleased = false;
		if (((state.NextHand == ExpectedHand.Left) ? usePrimaryWasPressed : useSecondaryWasPressed) && TryGetHeldDirection(upHeld, leftHeld, rightHeld, downHeld, out var stepDirection) && TryApplyStep(character, stepDirection))
		{
			state.NextHand = ((state.NextHand == ExpectedHand.Left) ? ExpectedHand.Right : ExpectedHand.Left);
		}
		characterInput.usePrimaryWasPressed = false;
		characterInput.usePrimaryIsPressed = false;
		characterInput.useSecondaryWasPressed = false;
		characterInput.useSecondaryIsPressed = false;
		characterInput.useSecondaryWasReleased = false;
	}
}
namespace Sapphire009.RealControlMod;

internal static class AnimationFlow
{
	private sealed class AnimationFlowState
	{
		public bool HasPositionSample;

		public bool HasDirectionalPose;

		public bool StepActive;

		public bool IsFrozen;

		public bool HasInputSampleSnapshot;

		public float StepStartedTime;

		public float TimeWithoutMovement;

		public Vector2 LastDirection = Vector2.zero;

		public Vector3 InputSampleStartClimbPosition = Vector3.zero;

		public Vector3 LastCharacterCenter = Vector3.zero;
	}

	[HarmonyPatch(typeof(CharacterInput), "Sample", new Type[] { typeof(bool) })]
	private static class CharacterInputStepDetectionPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static void Prefix(CharacterInput __instance)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Character val = ResolveCharacter((Component)(object)__instance);
			if (IsLocalNormalWallClimbing(val))
			{
				AnimationFlowState orCreateState = GetOrCreateState(val);
				orCreateState.InputSampleStartClimbPosition = val.data.climbPos;
				orCreateState.HasInputSampleSnapshot = true;
			}
		}

		[HarmonyPostfix]
		[HarmonyPriority(-200)]
		private static void Postfix(CharacterInput __instance)
		{
			//IL_0040: 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_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_006c: 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)
			Character val = ResolveCharacter((Component)(object)__instance);
			if (!IsLocalNormalWallClimbing(val))
			{
				return;
			}
			AnimationFlowState orCreateState = GetOrCreateState(val);
			if (orCreateState.HasInputSampleSnapshot)
			{
				orCreateState.HasInputSampleSnapshot = false;
				Vector3 worldMovement = val.data.climbPos - orCreateState.InputSampleStartClimbPosition;
				if (!(((Vector3)(ref worldMovement)).sqrMagnitude <= 1E-06f) && TryConvertWorldMovementToInput(val, worldMovement, out var inputDirection))
				{
					BeginStepAnimation(val, orCreateState, inputDirection);
				}
			}
		}
	}

	[HarmonyPatch(typeof(CharacterAnimations), "Update")]
	private static class CharacterAnimationsFlowPatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(-200)]
		private static void Postfix(CharacterAnimations __instance)
		{
			Character val = ResolveCharacter((Component)(object)__instance);
			if (!((Object)(object)val == (Object)null) && val.IsLocal)
			{
				if (!IsLocalNormalWallClimbing(val))
				{
					RestoreAndRemoveState(val);
				}
				else
				{
					UpdateAnimationFlow(val);
				}
			}
		}
	}

	[HarmonyPatch(typeof(CharacterClimbing), "StartClimbRpc", new Type[]
	{
		typeof(Vector3),
		typeof(Vector3)
	})]
	private static class StartClimbAnimationFlowPatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(-200)]
		private static void Postfix(CharacterClimbing __instance)
		{
			Character val = ResolveCharacter((Component)(object)__instance);
			if (!((Object)(object)val == (Object)null) && val.IsLocal)
			{
				RestoreAndRemoveState(val);
			}
		}
	}

	[HarmonyPatch(typeof(CharacterClimbing), "StopClimbingRpc", new Type[] { typeof(float) })]
	private static class StopClimbAnimationFlowPatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(-200)]
		private static void Postfix(CharacterClimbing __instance)
		{
			Character val = ResolveCharacter((Component)(object)__instance);
			if (!((Object)(object)val == (Object)null) && val.IsLocal)
			{
				RestoreAndRemoveState(val);
			}
		}
	}

	private const float AppliedStepSqrMagnitude = 1E-06f;

	private const float MinimumDirectionalMovement = 0.0005f;

	private const float MinimumStepAnimationTime = 0.12f;

	private const float MovementStopGraceTime = 0.08f;

	private const float MinimumDirectionSqrMagnitude = 0.0001f;

	private const float MinimumAnimationSpeed = 0.01f;

	private static readonly int ClimbJumpAnimationHash = Animator.StringToHash("Climb Jump");

	private static readonly int InputXAnimationHash = Animator.StringToHash("Input X");

	private static readonly int InputYAnimationHash = Animator.StringToHash("Input Y");

	private static readonly Dictionary<int, AnimationFlowState> FlowStates = new Dictionary<int, AnimationFlowState>();

	private static Character ResolveCharacter(Component component)
	{
		if ((Object)(object)component == (Object)null)
		{
			return null;
		}
		Character val = component.GetComponent<Character>();
		if ((Object)(object)val == (Object)null)
		{
			val = component.GetComponentInParent<Character>();
		}
		return val;
	}

	private static bool IsLocalNormalWallClimbing(Character character)
	{
		if ((Object)(object)character == (Object)null || !character.IsLocal || (Object)(object)character.data == (Object)null || character.refs == null || (Object)(object)character.refs.climbing == (Object)null || (Object)(object)character.refs.animator == (Object)null)
		{
			return false;
		}
		return character.data.isClimbing && !character.data.isRopeClimbing && !character.data.isVineClimbing && (Object)(object)character.data.currentClimbHandle == (Object)null;
	}

	private static AnimationFlowState GetOrCreateState(Character character)
	{
		//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)
		int instanceID = ((Object)character).GetInstanceID();
		if (!FlowStates.TryGetValue(instanceID, out var value))
		{
			value = new AnimationFlowState();
			value.HasPositionSample = true;
			value.LastCharacterCenter = character.Center;
			FlowStates.Add(instanceID, value);
		}
		return value;
	}

	private static float GetClimbAnimationSpeed(Character character)
	{
		if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null)
		{
			return 1f;
		}
		return Mathf.Max(0.01f, character.data.staminaMod);
	}

	private static bool TryGetWallAxes(Character character, out Vector3 wallUp, out Vector3 wallRight)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_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_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		wallUp = Vector3.zero;
		wallRight = Vector3.zero;
		if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null)
		{
			return false;
		}
		Vector3 climbNormal = character.data.climbNormal;
		if (((Vector3)(ref climbNormal)).sqrMagnitude <= 0.0001f)
		{
			return false;
		}
		((Vector3)(ref climbNormal)).Normalize();
		wallUp = Vector3.ProjectOnPlane(Vector3.up, climbNormal);
		if (((Vector3)(ref wallUp)).sqrMagnitude <= 0.0001f)
		{
			return false;
		}
		((Vector3)(ref wallUp)).Normalize();
		wallRight = Vector3.Cross(climbNormal, wallUp);
		if (((Vector3)(ref wallRight)).sqrMagnitude <= 0.0001f)
		{
			return false;
		}
		((Vector3)(ref wallRight)).Normalize();
		return true;
	}

	private static bool TryConvertWorldMovementToInput(Character character, Vector3 worldMovement, out Vector2 inputDirection)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		inputDirection = Vector2.zero;
		if (!TryGetWallAxes(character, out var wallUp, out var wallRight))
		{
			return false;
		}
		inputDirection = new Vector2(Vector3.Dot(worldMovement, wallRight), Vector3.Dot(worldMovement, wallUp));
		if (((Vector2)(ref inputDirection)).sqrMagnitude <= 0.0001f)
		{
			inputDirection = Vector2.zero;
			return false;
		}
		((Vector2)(ref inputDirection)).Normalize();
		return true;
	}

	private static bool TryConvertInputToWorldDirection(Character character, Vector2 inputDirection, out Vector3 worldDirection)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		worldDirection = Vector3.zero;
		if (((Vector2)(ref inputDirection)).sqrMagnitude <= 0.0001f)
		{
			return false;
		}
		if (!TryGetWallAxes(character, out var wallUp, out var wallRight))
		{
			return false;
		}
		worldDirection = wallRight * inputDirection.x + wallUp * inputDirection.y;
		if (((Vector3)(ref worldDirection)).sqrMagnitude <= 0.0001f)
		{
			worldDirection = Vector3.zero;
			return false;
		}
		((Vector3)(ref worldDirection)).Normalize();
		return true;
	}

	private static Vector3 GetWallSurfaceMovement(Character character, Vector3 worldMovement)
	{
		//IL_001b: 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_001d: 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_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_003d: Unknown result type (might be due to invalid IL or missing references)
		if (!TryGetWallAxes(character, out var wallUp, out var wallRight))
		{
			return Vector3.zero;
		}
		return wallRight * Vector3.Dot(worldMovement, wallRight) + wallUp * Vector3.Dot(worldMovement, wallUp);
	}

	private static void BeginStepAnimation(Character character, AnimationFlowState state, Vector2 direction)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)character == (Object)null) && state != null && !(((Vector2)(ref direction)).sqrMagnitude <= 0.0001f))
		{
			((Vector2)(ref direction)).Normalize();
			state.LastDirection = direction;
			state.HasDirectionalPose = true;
			state.StepActive = true;
			state.IsFrozen = false;
			state.StepStartedTime = Time.unscaledTime;
			state.TimeWithoutMovement = 0f;
			ResumeAnimation(character, state);
		}
	}

	private static void ApplyDirectionalAnimation(Animator animator, Vector2 direction)
	{
		//IL_0007: 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)
		animator.SetFloat(InputXAnimationHash, direction.x);
		animator.SetFloat(InputYAnimationHash, direction.y);
	}

	private static void ResumeAnimation(Character character, AnimationFlowState state)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		Animator animator = character.refs.animator;
		animator.SetBool(ClimbJumpAnimationHash, false);
		ApplyDirectionalAnimation(animator, state.LastDirection);
		animator.speed = GetClimbAnimationSpeed(character);
		state.IsFrozen = false;
	}

	private static void FreezeAnimation(Character character, AnimationFlowState state)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		Animator animator = character.refs.animator;
		animator.SetBool(ClimbJumpAnimationHash, false);
		ApplyDirectionalAnimation(animator, state.LastDirection);
		animator.speed = 0f;
		state.IsFrozen = true;
		state.StepActive = false;
	}

	private static void RestoreAndRemoveState(Character character)
	{
		if ((Object)(object)character == (Object)null)
		{
			return;
		}
		int instanceID = ((Object)character).GetInstanceID();
		if (FlowStates.TryGetValue(instanceID, out var _))
		{
			if (character.refs != null && (Object)(object)character.refs.animator != (Object)null)
			{
				character.refs.animator.speed = 1f;
			}
			FlowStates.Remove(instanceID);
		}
	}

	private static void UpdateAnimationFlow(Character character)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: 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_0071: 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: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		Animator animator = character.refs.animator;
		AnimationFlowState orCreateState = GetOrCreateState(character);
		Vector3 center = character.Center;
		if (!orCreateState.HasPositionSample)
		{
			orCreateState.HasPositionSample = true;
			orCreateState.LastCharacterCenter = center;
			return;
		}
		Vector3 worldMovement = center - orCreateState.LastCharacterCenter;
		Vector3 wallSurfaceMovement = GetWallSurfaceMovement(character, worldMovement);
		bool flag = false;
		if (orCreateState.StepActive && orCreateState.HasDirectionalPose && TryConvertInputToWorldDirection(character, orCreateState.LastDirection, out var worldDirection))
		{
			float num = Vector3.Dot(wallSurfaceMovement, worldDirection);
			flag = num > 0.0005f;
		}
		if (orCreateState.StepActive && orCreateState.HasDirectionalPose)
		{
			float num2 = Time.unscaledTime - orCreateState.StepStartedTime;
			if (flag || num2 < 0.12f)
			{
				orCreateState.TimeWithoutMovement = 0f;
				ResumeAnimation(character, orCreateState);
			}
			else
			{
				orCreateState.TimeWithoutMovement += Time.unscaledDeltaTime;
				if (orCreateState.TimeWithoutMovement >= 0.08f)
				{
					FreezeAnimation(character, orCreateState);
				}
				else
				{
					ResumeAnimation(character, orCreateState);
				}
			}
		}
		else if (orCreateState.HasDirectionalPose)
		{
			FreezeAnimation(character, orCreateState);
		}
		else
		{
			animator.SetBool(ClimbJumpAnimationHash, false);
		}
		orCreateState.LastCharacterCenter = center;
	}
}
internal static class NoDelay
{
	private enum MouseHand
	{
		None,
		Left,
		Right
	}

	private sealed class MouseDelayState
	{
		public bool WasNormalWallClimbing;

		public MouseHand LastAcceptedHand = MouseHand.None;

		public float LastAcceptedClickTime = float.NegativeInfinity;

		public float LastPrimaryPressedTime = float.NegativeInfinity;
	}

	[HarmonyPatch(typeof(CharacterInput), "Sample", new Type[] { typeof(bool) })]
	private static class CharacterInputSampleShortDelayPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static void Prefix(CharacterInput __instance)
		{
			Character character = ResolveCharacter((Component)(object)__instance);
			UpdateShortDelay(character);
		}

		[HarmonyPostfix]
		[HarmonyPriority(800)]
		private static void Postfix(CharacterInput __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				Character character = ResolveCharacter((Component)(object)__instance);
				ApplyMouseAlternationDelay(__instance, character);
			}
		}
	}

	[HarmonyPatch(typeof(CharacterClimbing), "RPCA_ClimbJump")]
	private static class ClimbJumpShortDelayPatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(CharacterClimbing __instance)
		{
			Character val = ResolveCharacter((Component)(object)__instance);
			if (IsLocalNormalWallClimbing(val))
			{
				val.data.sinceClimbJump = 0f;
			}
		}
	}

	[HarmonyPatch(typeof(CharacterClimbing), "StartClimbRpc", new Type[]
	{
		typeof(Vector3),
		typeof(Vector3)
	})]
	private static class StartClimbShortDelayPatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(CharacterClimbing __instance)
		{
			Character val = ResolveCharacter((Component)(object)__instance);
			if (IsLocalNormalWallClimbing(val))
			{
				val.data.sinceClimbJump = 0f;
				MouseDelayState orCreateMouseDelayState = GetOrCreateMouseDelayState(val);
				BeginMouseAlternationForClimb(orCreateMouseDelayState);
			}
		}
	}

	private const float ShortClimbDelay = 0.5f;

	private const float ReadyClimbJumpTime = 2f;

	private const float MouseAlternationDelay = 0.5f;

	private const float NormalGrabDetectionWindow = 0.75f;

	private static readonly Dictionary<int, MouseDelayState> MouseDelayStates = new Dictionary<int, MouseDelayState>();

	private static Character ResolveCharacter(Component component)
	{
		if ((Object)(object)component == (Object)null)
		{
			return null;
		}
		Character val = component.GetComponent<Character>();
		if ((Object)(object)val == (Object)null)
		{
			val = component.GetComponentInParent<Character>();
		}
		return val;
	}

	private static MouseDelayState GetOrCreateMouseDelayState(Character character)
	{
		int instanceID = ((Object)character).GetInstanceID();
		if (!MouseDelayStates.TryGetValue(instanceID, out var value))
		{
			value = new MouseDelayState();
			MouseDelayStates.Add(instanceID, value);
		}
		return value;
	}

	private static bool IsLocalCharacter(Character character)
	{
		return (Object)(object)character != (Object)null && character.IsLocal && (Object)(object)character.data != (Object)null;
	}

	private static bool IsLocalNormalWallClimbing(Character character)
	{
		if (!IsLocalCharacter(character))
		{
			return false;
		}
		return character.data.isClimbing && !character.data.isRopeClimbing && !character.data.isVineClimbing && (Object)(object)character.data.currentClimbHandle == (Object)null;
	}

	private static void UpdateShortDelay(Character character)
	{
		if (IsLocalNormalWallClimbing(character) && character.data.sinceClimbJump >= 0.5f && character.data.sinceClimbJump < 2f)
		{
			character.data.sinceClimbJump = 2f;
		}
	}

	private static void ResetMouseAlternation(MouseDelayState state)
	{
		state.LastAcceptedHand = MouseHand.None;
		state.LastAcceptedClickTime = float.NegativeInfinity;
	}

	private static void BeginMouseAlternationForClimb(MouseDelayState state)
	{
		if (Time.unscaledTime - state.LastPrimaryPressedTime <= 0.75f)
		{
			state.LastAcceptedHand = MouseHand.Left;
			state.LastAcceptedClickTime = state.LastPrimaryPressedTime;
		}
		else
		{
			ResetMouseAlternation(state);
		}
		state.WasNormalWallClimbing = true;
	}

	private static bool CanAcceptOppositeClick(MouseDelayState state, MouseHand pressedHand)
	{
		if (state.LastAcceptedHand == MouseHand.None)
		{
			return true;
		}
		if (state.LastAcceptedHand == pressedHand)
		{
			return false;
		}
		float num = Time.unscaledTime - state.LastAcceptedClickTime;
		return num >= 0.5f;
	}

	private static void AcceptClick(MouseDelayState state, MouseHand pressedHand)
	{
		state.LastAcceptedHand = pressedHand;
		state.LastAcceptedClickTime = Time.unscaledTime;
	}

	private static void SuppressPrimaryClick(CharacterInput characterInput)
	{
		characterInput.usePrimaryWasPressed = false;
		characterInput.usePrimaryIsPressed = false;
	}

	private static void SuppressSecondaryClick(CharacterInput characterInput)
	{
		characterInput.useSecondaryWasPressed = false;
		characterInput.useSecondaryIsPressed = false;
	}

	private static void ProcessPrimaryClick(CharacterInput characterInput, MouseDelayState state)
	{
		if (characterInput.usePrimaryWasPressed)
		{
			if (!CanAcceptOppositeClick(state, MouseHand.Left))
			{
				SuppressPrimaryClick(characterInput);
			}
			else
			{
				AcceptClick(state, MouseHand.Left);
			}
		}
	}

	private static void ProcessSecondaryClick(CharacterInput characterInput, MouseDelayState state)
	{
		if (characterInput.useSecondaryWasPressed)
		{
			if (!CanAcceptOppositeClick(state, MouseHand.Right))
			{
				SuppressSecondaryClick(characterInput);
			}
			else
			{
				AcceptClick(state, MouseHand.Right);
			}
		}
	}

	private static void ApplyMouseAlternationDelay(CharacterInput characterInput, Character character)
	{
		if (!IsLocalCharacter(character))
		{
			return;
		}
		MouseDelayState orCreateMouseDelayState = GetOrCreateMouseDelayState(character);
		if (!IsLocalNormalWallClimbing(character))
		{
			if (characterInput.usePrimaryWasPressed)
			{
				orCreateMouseDelayState.LastPrimaryPressedTime = Time.unscaledTime;
			}
			orCreateMouseDelayState.WasNormalWallClimbing = false;
			ResetMouseAlternation(orCreateMouseDelayState);
			return;
		}
		if (!orCreateMouseDelayState.WasNormalWallClimbing)
		{
			if (characterInput.usePrimaryWasPressed)
			{
				orCreateMouseDelayState.LastPrimaryPressedTime = Time.unscaledTime;
			}
			BeginMouseAlternationForClimb(orCreateMouseDelayState);
		}
		bool usePrimaryWasPressed = characterInput.usePrimaryWasPressed;
		bool useSecondaryWasPressed = characterInput.useSecondaryWasPressed;
		if (usePrimaryWasPressed && useSecondaryWasPressed)
		{
			if (orCreateMouseDelayState.LastAcceptedHand == MouseHand.Left)
			{
				SuppressPrimaryClick(characterInput);
				ProcessSecondaryClick(characterInput, orCreateMouseDelayState);
			}
			else if (orCreateMouseDelayState.LastAcceptedHand == MouseHand.Right)
			{
				SuppressSecondaryClick(characterInput);
				ProcessPrimaryClick(characterInput, orCreateMouseDelayState);
			}
			else
			{
				SuppressSecondaryClick(characterInput);
				ProcessPrimaryClick(characterInput, orCreateMouseDelayState);
			}
		}
		else
		{
			ProcessPrimaryClick(characterInput, orCreateMouseDelayState);
			ProcessSecondaryClick(characterInput, orCreateMouseDelayState);
		}
	}
}
internal static class NoWall
{
	[HarmonyPatch(typeof(CharacterClimbing), "Update")]
	private static class CharacterClimbingUpdatePatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(CharacterClimbing __instance)
		{
			Character val = ResolveCharacter((Component)(object)__instance);
			if (!IsLocalCharacter(val))
			{
				return true;
			}
			KeepOrClearReleaseLock(val);
			if (!IsLocalNormalWallClimbing(val))
			{
				return true;
			}
			if ((Object)(object)val.input != (Object)null)
			{
				val.input.jumpWasPressed = false;
			}
			if (!IsAtReleaseThreshold(val))
			{
				return true;
			}
			StopClimbingImmediately(__instance, val);
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(CharacterClimbing __instance)
		{
			Character character = ResolveCharacter((Component)(object)__instance);
			if (IsLocalNormalWallClimbing(character) && IsAtReleaseThreshold(character))
			{
				StopClimbingImmediately(__instance, character);
			}
		}
	}

	[HarmonyPatch(typeof(CharacterClimbing), "TryToStartWallClimb")]
	private static class TryToStartWallClimbPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(CharacterClimbing __instance)
		{
			Character character = ResolveCharacter((Component)(object)__instance);
			if (!IsLocalCharacter(character))
			{
				return true;
			}
			return !KeepOrClearReleaseLock(character);
		}
	}

	[HarmonyPatch(typeof(CharacterClimbing), "StartClimbRpc", new Type[]
	{
		typeof(Vector3),
		typeof(Vector3)
	})]
	private static class StartClimbRpcPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(CharacterClimbing __instance)
		{
			Character character = ResolveCharacter((Component)(object)__instance);
			if (!IsLocalCharacter(character))
			{
				return true;
			}
			return !KeepOrClearReleaseLock(character);
		}
	}

	[HarmonyPatch(typeof(Character), "OnDestroy")]
	private static class CharacterOnDestroyPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Character __instance)
		{
			RemoveReleaseLock(__instance);
		}
	}

	private const float ReleaseStaminaThreshold = 0.049f;

	private const float ComparisonEpsilon = 0.0005f;

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

	private static Character ResolveCharacter(Component component)
	{
		if ((Object)(object)component == (Object)null)
		{
			return null;
		}
		Character val = component.GetComponent<Character>();
		if ((Object)(object)val == (Object)null)
		{
			val = component.GetComponentInParent<Character>();
		}
		return val;
	}

	private static bool IsLocalCharacter(Character character)
	{
		return (Object)(object)character != (Object)null && character.refs != null && (Object)(object)character.refs.view != (Object)null && character.refs.view.IsMine;
	}

	private static bool IsNormalWallClimbing(Character character)
	{
		return (Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null && character.refs != null && (Object)(object)character.refs.climbing != (Object)null && character.data.isClimbing && !character.data.isRopeClimbing && !character.data.isVineClimbing && (Object)(object)character.data.currentClimbHandle == (Object)null;
	}

	private static bool IsLocalNormalWallClimbing(Character character)
	{
		return IsLocalCharacter(character) && IsNormalWallClimbing(character);
	}

	private static float GetRemainingStamina(Character character)
	{
		if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null)
		{
			return float.MaxValue;
		}
		return Mathf.Max(0f, character.data.currentStamina) + Mathf.Max(0f, character.data.extraStamina);
	}

	private static bool IsAtReleaseThreshold(Character character)
	{
		return GetRemainingStamina(character) <= 0.0495f;
	}

	private static bool IsPrimaryActuallyHeld(Character character)
	{
		if (CharacterInput.action_usePrimary != null)
		{
			return CharacterInput.action_usePrimary.IsPressed();
		}
		return (Object)(object)character != (Object)null && (Object)(object)character.input != (Object)null && character.input.usePrimaryIsPressed;
	}

	private static bool HasReleaseLock(Character character)
	{
		return (Object)(object)character != (Object)null && ForcedReleaseLocks.Contains(((Object)character).GetInstanceID());
	}

	private static void AddReleaseLock(Character character)
	{
		if (!((Object)(object)character == (Object)null))
		{
			ForcedReleaseLocks.Add(((Object)character).GetInstanceID());
		}
	}

	private static void RemoveReleaseLock(Character character)
	{
		if (!((Object)(object)character == (Object)null))
		{
			ForcedReleaseLocks.Remove(((Object)character).GetInstanceID());
		}
	}

	private static bool KeepOrClearReleaseLock(Character character)
	{
		if (!HasReleaseLock(character))
		{
			return false;
		}
		bool flag = !IsAtReleaseThreshold(character);
		bool flag2 = !IsPrimaryActuallyHeld(character);
		if (flag && flag2)
		{
			RemoveReleaseLock(character);
			return false;
		}
		if ((Object)(object)character.data != (Object)null)
		{
			character.data.sincePressClimb = 10f;
		}
		return true;
	}

	private static void StopClimbingImmediately(CharacterClimbing climbing, Character character)
	{
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)climbing == (Object)null) && !((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null))
		{
			AddReleaseLock(character);
			if ((Object)(object)character.input != (Object)null)
			{
				character.input.jumpWasPressed = false;
			}
			character.data.sincePressClimb = 10f;
			climbing.playerSlide = Vector2.zero;
			if (character.data.isClimbing)
			{
				climbing.StopClimbingRpc(0f);
			}
			if (PhotonNetwork.InRoom && character.refs != null && (Object)(object)character.refs.view != (Object)null)
			{
				character.refs.view.RPC("StopClimbingRpc", (RpcTarget)1, new object[1] { 0f });
			}
		}
	}
}
internal static class StopStamina
{
	[HarmonyPatch(typeof(Character), "UseStamina", new Type[]
	{
		typeof(float),
		typeof(bool)
	})]
	private static class CharacterUseStaminaPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(Character __instance, float __0, ref bool __result)
		{
			if (!IsNormalWallClimbing(__instance))
			{
				return true;
			}
			if (__0 <= 0f)
			{
				return true;
			}
			if (__0 >= 0.099f)
			{
				return true;
			}
			__instance.data.sinceUseStamina = 0f;
			__result = true;
			return false;
		}
	}

	private const float DashStaminaCost = 0.1f;

	private const float ComparisonEpsilon = 0.001f;

	private static bool IsNormalWallClimbing(Character character)
	{
		if ((Object)(object)character == (Object)null || !character.IsLocal || (Object)(object)character.data == (Object)null)
		{
			return false;
		}
		return character.data.isClimbing && !character.data.isRopeClimbing && !character.data.isVineClimbing && (Object)(object)character.data.currentClimbHandle == (Object)null;
	}
}