using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.InputSystem;
using Zorro.ControllerSupport;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("PEAK Auto Grab Climb")]
[assembly: AssemblyDescription("Automatic grab-release climbing with terrain-aware vanilla fallback for PEAK.")]
[assembly: AssemblyCompany("TaXueXuex")]
[assembly: AssemblyProduct("PEAK Auto Grab Climb")]
[assembly: AssemblyCopyright("Copyright © 2026 TaXueXuex")]
[assembly: AssemblyFileVersion("1.0.4.0")]
[assembly: AssemblyInformationalVersion("1.0.4 (2026-09-13)")]
[assembly: AssemblyMetadata("Author", "TaXueXuex")]
[assembly: AssemblyMetadata("ReleaseDate", "2026-09-13")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("1.0.4.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace TaXueXuex.AutoGrabClimb
{
[BepInPlugin("TaXueXuex.AutoGrabClimb", "Auto Grab Climb", "1.0.4")]
public sealed class Plugin : BaseUnityPlugin
{
private enum CyclePhase
{
Idle,
Grab,
Release
}
public const string PluginGuid = "TaXueXuex.AutoGrabClimb";
public const string PluginName = "Auto Grab Climb";
public const string PluginVersion = "1.0.4";
public const string AuthorName = "TaXueXuex";
public const string ReleaseDate = "2026-09-13";
private const KeyCode ToggleKey = (KeyCode)291;
private const int GrabPhysicsTicks = 7;
private const int ReleasePhysicsTicks = 12;
private const int ConfirmationTimeoutTicks = 4;
private const float PeakWallRegrabCooldownSeconds = 0.2f;
private const float RegrabPitchDegrees = 1f;
private const float FavorableSlopeAimCompensation = 1f;
private const float WallAngleDeadZoneDegrees = 1f;
private const float OverhangFallbackDegrees = 1f;
private const float AutoResumeDegrees = 0.25f;
private const float AutoResumeConfirmationSeconds = 0.05f;
private const float InitialHoldConfirmationSeconds = 0.14f;
internal static Plugin Instance;
internal static bool ModeEnabled;
private Harmony _harmony;
private CharacterClimbing _activeClimbing;
private bool _overridingInput;
private CyclePhase _phase;
private int _phaseFixedSteps;
private int _effectiveGrabTicks;
private int _effectiveReleaseTicks;
private bool _grabConfirmed;
private bool _releaseRequested;
private bool _grabRequested;
private bool _retryGrabRequested;
private bool _retryReleaseRequested;
private bool _regrabTimingReady;
private bool _restoreLookDirection;
private CharacterData _lookDirectionOwner;
private Vector3 _savedLookDirection;
private bool _releaseSurfaceValid;
private float _releaseWallDegrees;
private bool _surfaceBypassActive;
private float _normalSurfaceCandidateSince = -1f;
private float _physicalGrabHeldSince = -1f;
private float _initialPhysicalGrabObservedAt = -1f;
private bool _automationHoldCommitted;
private static bool _controllerForwardHeld;
private float _controllerToggleSince = -1f;
private bool _controllerToggleConsumed;
private CharacterClimbing _temporaryToggleOwner;
private bool _savedClimbToggle;
private static readonly FieldInfo ClimbToggledOnField = AccessTools.Field(typeof(CharacterClimbing), "climbToggledOn");
private bool _lastGamepadScheme;
private bool _loggedRuntimeFailure;
private string _noticeText;
private float _noticeUntil;
private GUIStyle _noticeTitleStyle;
private GUIStyle _noticeBodyStyle;
private static readonly FieldInfo ClimbingCharacterField = AccessTools.Field(typeof(CharacterClimbing), "character");
private static readonly MethodInfo CanDoInputMethod = AccessTools.Method(typeof(Character), "CanDoInput", (Type[])null, (Type[])null);
private void Awake()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
Instance = this;
ModeEnabled = false;
_harmony = new Harmony("TaXueXuex.AutoGrabClimb");
_harmony.PatchAll();
((BaseUnityPlugin)this).Logger.LogInfo((object)"Auto Grab Climb 1.0.4 loaded. Author=TaXueXuex, ReleaseDate=2026-09-13, Toggle=F10, default=OFF, G7/R12, Aim=+1deg, SlopeK=1, dynamic terrain routing=ON, keyboard/mouse and native gamepad support=ON");
}
private void OnDestroy()
{
RestoreControllerClimbToggle();
RestoreOriginalLookDirection();
if (_harmony != null)
{
_harmony.UnpatchSelf();
}
if ((Object)(object)Instance == (Object)(object)this)
{
Instance = null;
}
}
private void Update()
{
bool flag = IsGamepadInput();
if (flag != _lastGamepadScheme)
{
StopOverriding();
ResetActivationHold();
ResetSurfaceRouting();
_controllerForwardHeld = false;
_lastGamepadScheme = flag;
}
if (!IsMovementChordHeld())
{
ResetSurfaceRouting();
ResetActivationHold();
}
else if (!IsPhysicalGrabHeld())
{
FinishPhysicalGrabPress();
}
bool flag2 = CheckControllerToggle();
if (Input.GetKeyDown((KeyCode)291) || flag2)
{
ModeEnabled = !ModeEnabled;
StopOverriding();
ResetActivationHold();
if (!ModeEnabled)
{
ResetSurfaceRouting();
}
ShowToggleNotice();
((BaseUnityPlugin)this).Logger.LogInfo((object)("Auto Grab Climb mode = " + ModeEnabled));
}
}
private void ShowToggleNotice()
{
_noticeText = (ModeEnabled ? "Auto Grab Climb: ON\nHold Sprint first, then hold Forward + Grab (keep Sprint held)" : "Auto Grab Climb: OFF");
_noticeUntil = Time.unscaledTime + 3.5f;
}
private void OnGUI()
{
//IL_0068: 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_008b: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
if (!string.IsNullOrEmpty(_noticeText) && !(Time.unscaledTime > _noticeUntil))
{
EnsureNoticeStyles();
float num = Mathf.Min(680f, (float)Screen.width - 32f);
float num2 = (ModeEnabled ? 72f : 48f);
Rect val = default(Rect);
((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, 30f, num, num2);
Color color = GUI.color;
GUI.color = new Color(0.06f, 0.06f, 0.06f, 0.92f);
GUI.Box(val, GUIContent.none);
GUI.color = color;
if (ModeEnabled)
{
GUI.Label(new Rect(((Rect)(ref val)).x + 14f, ((Rect)(ref val)).y + 7f, ((Rect)(ref val)).width - 28f, 26f), "Auto Grab Climb: ON", _noticeTitleStyle);
GUI.Label(new Rect(((Rect)(ref val)).x + 14f, ((Rect)(ref val)).y + 35f, ((Rect)(ref val)).width - 28f, 25f), "Hold Sprint first, then hold Forward + Grab (keep Sprint held)", _noticeBodyStyle);
}
else
{
GUI.Label(new Rect(((Rect)(ref val)).x + 14f, ((Rect)(ref val)).y + 8f, ((Rect)(ref val)).width - 28f, 27f), "Auto Grab Climb: OFF", _noticeTitleStyle);
}
}
}
private void EnsureNoticeStyles()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected O, but got Unknown
//IL_006a: 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_0089: Expected O, but got Unknown
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
if (_noticeTitleStyle == null || _noticeBodyStyle == null)
{
_noticeTitleStyle = new GUIStyle(GUI.skin.label);
_noticeTitleStyle.fontSize = 20;
_noticeTitleStyle.fontStyle = (FontStyle)1;
_noticeTitleStyle.alignment = (TextAnchor)4;
_noticeTitleStyle.normal.textColor = new Color(0.45f, 1f, 0.45f, 1f);
_noticeBodyStyle = new GUIStyle(GUI.skin.label);
_noticeBodyStyle.fontSize = 17;
_noticeBodyStyle.fontStyle = (FontStyle)1;
_noticeBodyStyle.alignment = (TextAnchor)4;
_noticeBodyStyle.normal.textColor = Color.white;
}
}
internal void BeforeClimbingUpdate(CharacterClimbing climbing)
{
try
{
Character localCharacter = Character.localCharacter;
Character ownerCharacter = GetOwnerCharacter(climbing);
if ((Object)(object)localCharacter == (Object)null || (Object)(object)ownerCharacter == (Object)null || (Object)(object)ownerCharacter != (Object)(object)localCharacter)
{
return;
}
if ((Object)(object)_activeClimbing != (Object)(object)climbing)
{
_activeClimbing = climbing;
StopOverriding();
ResetSurfaceRouting();
ResetActivationHold();
}
CharacterInput input = localCharacter.input;
if ((Object)(object)input == (Object)null)
{
return;
}
if (ShouldPreserveOriginalTap(localCharacter))
{
StopOverriding();
return;
}
if (ShouldUseVanillaClimbing(localCharacter))
{
StopOverriding();
return;
}
if (!IsEligible(localCharacter))
{
StopOverriding();
return;
}
PrepareContinuousClimbInput(input);
if (!_overridingInput || _phase == CyclePhase.Idle)
{
if (_automationHoldCommitted && (Object)(object)localCharacter.data != (Object)null && localCharacter.data.isClimbing)
{
BeginRelease(localCharacter, input);
}
else
{
BeginGrab(localCharacter, input);
}
}
else if (_phase == CyclePhase.Grab)
{
if (_releaseRequested)
{
BeginRelease(localCharacter, input);
}
else if (_retryGrabRequested)
{
RetryGrab(localCharacter, input);
}
else
{
ApplyGrabInput(input, pressedEdge: false);
}
}
else if (_grabRequested)
{
BeginGrab(localCharacter, input);
}
else if (_retryReleaseRequested)
{
RetryRelease(input);
}
else
{
ApplyReleaseInput(input, releasedEdge: false);
}
_overridingInput = true;
PrepareControllerRelease(climbing);
}
catch (Exception ex)
{
LogRuntimeFailure("update", ex);
}
}
internal void BeforeClimbingFixedUpdate(CharacterClimbing climbing)
{
try
{
if (!_overridingInput || (Object)(object)climbing != (Object)(object)_activeClimbing)
{
return;
}
Character localCharacter = Character.localCharacter;
Character ownerCharacter = GetOwnerCharacter(climbing);
if (!((Object)(object)localCharacter == (Object)null) && !((Object)(object)ownerCharacter == (Object)null) && !((Object)(object)ownerCharacter != (Object)(object)localCharacter) && !((Object)(object)localCharacter.input == (Object)null) && IsActivationChordHeld())
{
if (ShouldPreserveOriginalTap(localCharacter) || ShouldUseVanillaClimbing(localCharacter))
{
StopOverriding();
}
else
{
PrepareContinuousClimbInput(localCharacter.input);
}
}
}
catch (Exception ex)
{
LogRuntimeFailure("physics input", ex);
}
}
internal void AfterClimbingUpdate(CharacterClimbing climbing)
{
if ((Object)(object)climbing == (Object)(object)_temporaryToggleOwner)
{
RestoreControllerClimbToggle();
}
if ((Object)(object)climbing == (Object)(object)_activeClimbing)
{
RestoreOriginalLookDirection();
}
}
internal void AfterClimbingFixedUpdate(CharacterClimbing climbing)
{
try
{
if (!_overridingInput || (Object)(object)climbing != (Object)(object)_activeClimbing)
{
return;
}
Character localCharacter = Character.localCharacter;
Character ownerCharacter = GetOwnerCharacter(climbing);
if ((Object)(object)localCharacter == (Object)null || (Object)(object)ownerCharacter == (Object)null || (Object)(object)ownerCharacter != (Object)(object)localCharacter || (Object)(object)localCharacter.data == (Object)null)
{
return;
}
_phaseFixedSteps++;
if (_phase == CyclePhase.Grab)
{
if (localCharacter.data.isClimbing)
{
_grabConfirmed = true;
_effectiveGrabTicks++;
if (_effectiveGrabTicks >= 7)
{
_releaseRequested = true;
}
}
else if (_grabConfirmed || _phaseFixedSteps >= 4)
{
_retryGrabRequested = true;
}
}
else if (_phase == CyclePhase.Release)
{
if (!localCharacter.data.isClimbing)
{
_effectiveReleaseTicks++;
UpdateExactRelease(localCharacter);
}
else if (_phaseFixedSteps >= 4)
{
_retryReleaseRequested = true;
}
}
}
catch (Exception ex)
{
LogRuntimeFailure("physics state", ex);
}
}
private void BeginGrab(Character local, CharacterInput input)
{
_phase = CyclePhase.Grab;
_phaseFixedSteps = 0;
_effectiveGrabTicks = 0;
_effectiveReleaseTicks = 0;
_grabConfirmed = (Object)(object)local.data != (Object)null && local.data.isClimbing;
_releaseRequested = false;
_grabRequested = false;
_retryGrabRequested = false;
_retryReleaseRequested = false;
_regrabTimingReady = false;
PrimeOriginalGrab(local, input);
}
private void RetryGrab(Character local, CharacterInput input)
{
_phaseFixedSteps = 0;
_effectiveGrabTicks = 0;
_grabConfirmed = (Object)(object)local.data != (Object)null && local.data.isClimbing;
_retryGrabRequested = false;
PrimeOriginalGrab(local, input);
}
private void BeginRelease(Character local, CharacterInput input)
{
_phase = CyclePhase.Release;
_phaseFixedSteps = 0;
_effectiveReleaseTicks = 0;
_releaseRequested = false;
_grabRequested = false;
_retryGrabRequested = false;
_retryReleaseRequested = false;
_regrabTimingReady = false;
CaptureReleaseSurface(local);
ApplyReleaseInput(input, releasedEdge: true);
}
private void RetryRelease(CharacterInput input)
{
_phaseFixedSteps = 0;
_retryReleaseRequested = false;
ApplyReleaseInput(input, releasedEdge: true);
}
private static void PrepareContinuousClimbInput(CharacterInput input)
{
//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_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)
Vector2 movementInput = input.movementInput;
movementInput.x = 0f;
movementInput.y = 1f;
input.movementInput = movementInput;
}
private void PrimeOriginalGrab(Character local, CharacterInput input)
{
ApplyGrabInput(input, pressedEdge: true);
if ((Object)(object)local != (Object)null && (Object)(object)local.data != (Object)null)
{
ApplyTemporaryRegrabAim(local.data);
local.data.sincePressClimb = 0f;
}
}
private void UpdateExactRelease(Character local)
{
if (!_regrabTimingReady && _effectiveReleaseTicks >= 12)
{
_regrabTimingReady = true;
}
if (_regrabTimingReady && !_grabRequested && !(local.data.sinceClimb + 0.0001f < 0.2f))
{
_grabRequested = true;
}
}
private void ApplyTemporaryRegrabAim(CharacterData data)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: 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_0037: 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_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_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)data == (Object)null))
{
RestoreOriginalLookDirection();
Vector3 lookDirection = data.lookDirection;
Vector3 val = Vector3.ProjectOnPlane(lookDirection, Vector3.up);
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
{
val = data.lookDirection_Flat;
}
if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f))
{
float num = ((_releaseSurfaceValid && _releaseWallDegrees < -1f) ? (1f * _releaseWallDegrees) : 0f);
float num2 = Mathf.Clamp(1f + num, -30f, 10f) * (MathF.PI / 180f);
Vector3 val2 = ((Vector3)(ref val)).normalized * Mathf.Cos(num2) + Vector3.up * Mathf.Sin(num2);
_savedLookDirection = lookDirection;
_lookDirectionOwner = data;
_restoreLookDirection = true;
data.lookDirection = ((Vector3)(ref val2)).normalized;
}
}
}
private void RestoreOriginalLookDirection()
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
if (_restoreLookDirection)
{
if ((Object)(object)_lookDirectionOwner != (Object)null)
{
_lookDirectionOwner.lookDirection = _savedLookDirection;
}
_restoreLookDirection = false;
_lookDirectionOwner = null;
}
}
private void CaptureReleaseSurface(Character local)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
_releaseSurfaceValid = false;
if (!((Object)(object)local == (Object)null) && !((Object)(object)local.data == (Object)null))
{
Vector3 normalized = ((Vector3)(ref local.data.climbNormal)).normalized;
if (!(((Vector3)(ref normalized)).sqrMagnitude <= 0.25f))
{
_releaseSurfaceValid = true;
_releaseWallDegrees = GetWallDegrees(normalized);
}
}
}
private bool ShouldUseVanillaClimbing(Character local)
{
//IL_0051: 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_0077: Unknown result type (might be due to invalid IL or missing references)
if (!ModeEnabled || (Object)(object)local == (Object)null || (Object)(object)local.data == (Object)null || !IsActivationChordHeld())
{
return false;
}
if (!local.data.isClimbing)
{
_normalSurfaceCandidateSince = -1f;
return _surfaceBypassActive;
}
Vector3 normalized = ((Vector3)(ref local.data.climbNormal)).normalized;
if (((Vector3)(ref normalized)).sqrMagnitude <= 0.25f)
{
_normalSurfaceCandidateSince = -1f;
return _surfaceBypassActive;
}
float wallDegrees = GetWallDegrees(normalized);
if (!_surfaceBypassActive)
{
if (wallDegrees <= 1f)
{
return false;
}
_surfaceBypassActive = true;
_normalSurfaceCandidateSince = -1f;
return true;
}
if (wallDegrees > 0.25f)
{
_normalSurfaceCandidateSince = -1f;
return true;
}
if (_normalSurfaceCandidateSince < 0f)
{
_normalSurfaceCandidateSince = Time.unscaledTime;
return true;
}
if (Time.unscaledTime - _normalSurfaceCandidateSince < 0.05f)
{
return true;
}
_surfaceBypassActive = false;
_normalSurfaceCandidateSince = -1f;
return false;
}
private static float GetWallDegrees(Vector3 normal)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
return Mathf.Asin(Mathf.Clamp(0f - normal.y, -1f, 1f)) * 57.29578f;
}
private void ResetSurfaceRouting()
{
_surfaceBypassActive = false;
_normalSurfaceCandidateSince = -1f;
}
private bool ShouldPreserveOriginalTap(Character local)
{
if (!ModeEnabled || (Object)(object)local == (Object)null || (Object)(object)local.data == (Object)null || !IsActivationChordHeld())
{
return false;
}
bool num = IsAutomationHoldConfirmed();
if (!_overridingInput && local.data.isClimbing && _initialPhysicalGrabObservedAt < 0f)
{
_initialPhysicalGrabObservedAt = Time.unscaledTime;
}
if (!num)
{
return true;
}
if (_overridingInput)
{
return false;
}
if (!local.data.isClimbing || _initialPhysicalGrabObservedAt < 0f)
{
return true;
}
return Time.unscaledTime - _initialPhysicalGrabObservedAt < 0.14f;
}
private bool IsAutomationHoldConfirmed()
{
if (!IsActivationChordHeld())
{
ResetActivationHold();
return false;
}
if (_automationHoldCommitted)
{
return true;
}
if (_physicalGrabHeldSince < 0f)
{
_physicalGrabHeldSince = Time.unscaledTime;
return false;
}
if (Time.unscaledTime - _physicalGrabHeldSince < 0.14f)
{
return false;
}
_automationHoldCommitted = true;
return true;
}
private void FinishPhysicalGrabPress()
{
ResetActivationHold();
}
private void ResetActivationHold()
{
_physicalGrabHeldSince = -1f;
_initialPhysicalGrabObservedAt = -1f;
_automationHoldCommitted = false;
}
private void PrepareControllerRelease(CharacterClimbing climbing)
{
if (_phase == CyclePhase.Release && IsGamepadInput() && !((Object)(object)climbing == (Object)null) && !(ClimbToggledOnField == null))
{
Character localCharacter = Character.localCharacter;
if (!((Object)(object)localCharacter == (Object)null) && !((Object)(object)localCharacter.data == (Object)null) && localCharacter.data.isClimbing)
{
_savedClimbToggle = (bool)ClimbToggledOnField.GetValue(climbing);
_temporaryToggleOwner = climbing;
ClimbToggledOnField.SetValue(climbing, false);
}
}
}
private void RestoreControllerClimbToggle()
{
CharacterClimbing temporaryToggleOwner = _temporaryToggleOwner;
_temporaryToggleOwner = null;
if (!((Object)(object)temporaryToggleOwner == (Object)null) && !(ClimbToggledOnField == null))
{
Character ownerCharacter = GetOwnerCharacter(temporaryToggleOwner);
if ((Object)(object)ownerCharacter != (Object)null && (Object)(object)ownerCharacter.data != (Object)null && ownerCharacter.data.isClimbing)
{
ClimbToggledOnField.SetValue(temporaryToggleOwner, _savedClimbToggle);
}
}
}
private static bool IsGamepadInput()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Invalid comparison between Unknown and I4
return (int)InputHandler.GetCurrentUsedInputScheme() == 1;
}
private static bool IsPhysicalGrabHeld()
{
if (!IsGamepadInput())
{
return Input.GetMouseButton(0);
}
if (CharacterInput.action_usePrimary != null)
{
return CharacterInput.action_usePrimary.IsPressed();
}
return false;
}
private static bool IsMovementChordHeld()
{
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: 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)
if (!IsGamepadInput())
{
_controllerForwardHeld = false;
bool flag = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
return Input.GetKey((KeyCode)119) && flag;
}
bool num = (CharacterInput.action_sprint != null && CharacterInput.action_sprint.IsPressed()) || (CharacterInput.action_sprintToggle != null && CharacterInput.action_sprintToggle.IsPressed());
Vector2 val = ((CharacterInput.action_move != null) ? CharacterInput.action_move.ReadValue<Vector2>() : Vector2.zero);
_controllerForwardHeld = num && val.y >= (_controllerForwardHeld ? 0.35f : 0.55f);
return _controllerForwardHeld;
}
private static bool IsActivationChordHeld()
{
if (IsMovementChordHeld())
{
return IsPhysicalGrabHeld();
}
return false;
}
internal bool ShouldBridgeMovementSprint(Character local)
{
if (ModeEnabled && _overridingInput && !_surfaceBypassActive && (Object)(object)local != (Object)null && (Object)(object)local == (Object)(object)Character.localCharacter && (Object)(object)local.data != (Object)null && !local.data.isGrounded && IsGamepadInput())
{
return IsEligible(local);
}
return false;
}
private bool CheckControllerToggle()
{
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
Gamepad current = Gamepad.current;
if (current == null || !((InputDevice)current).added || !current.leftStickButton.isPressed || !current.rightStickButton.isPressed)
{
_controllerToggleSince = -1f;
_controllerToggleConsumed = false;
return false;
}
if (_controllerToggleConsumed)
{
return false;
}
Character localCharacter = Character.localCharacter;
if ((Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter.data != (Object)null && localCharacter.data.isGrounded && !localCharacter.data.isClimbing && !localCharacter.data.isRopeClimbing && !localCharacter.data.isVineClimbing && !localCharacter.data.passedOut && CanAcceptInput(localCharacter))
{
Vector2 val = ((InputControl<Vector2>)(object)current.leftStick).ReadValue();
if (((Vector2)(ref val)).sqrMagnitude < 0.04f)
{
val = ((InputControl<Vector2>)(object)current.rightStick).ReadValue();
if (((Vector2)(ref val)).sqrMagnitude < 0.04f)
{
if (_controllerToggleSince < 0f)
{
_controllerToggleSince = Time.unscaledTime;
}
if (Time.unscaledTime - _controllerToggleSince < 1f)
{
return false;
}
_controllerToggleConsumed = true;
return true;
}
}
}
_controllerToggleSince = -1f;
return false;
}
private bool IsEligible(Character local)
{
if (!ModeEnabled || (Object)(object)local == (Object)null || (Object)(object)local.data == (Object)null || !IsActivationChordHeld())
{
return false;
}
if (local.inAirport || !CanAcceptInput(local))
{
return false;
}
if (local.data.passedOut || local.data.isRopeClimbing || local.data.isVineClimbing || local.data.usingEmoteWheel || local.data.usingBackpackWheel || (Object)(object)local.data.currentItem != (Object)null)
{
return false;
}
return true;
}
private bool CanAcceptInput(Character local)
{
if (CanDoInputMethod == null)
{
return true;
}
try
{
return (bool)CanDoInputMethod.Invoke(local, null);
}
catch (Exception ex)
{
LogRuntimeFailure("input availability", ex);
return true;
}
}
private Character GetOwnerCharacter(CharacterClimbing climbing)
{
if ((Object)(object)climbing == (Object)null)
{
return null;
}
if (ClimbingCharacterField != null)
{
object? value = ClimbingCharacterField.GetValue(climbing);
Character val = (Character)((value is Character) ? value : null);
if ((Object)(object)val != (Object)null)
{
return val;
}
}
return ((Component)climbing).GetComponentInParent<Character>();
}
private void StopOverriding()
{
RestoreControllerClimbToggle();
RestoreOriginalLookDirection();
_overridingInput = false;
_phase = CyclePhase.Idle;
_phaseFixedSteps = 0;
_effectiveGrabTicks = 0;
_effectiveReleaseTicks = 0;
_grabConfirmed = false;
_releaseRequested = false;
_grabRequested = false;
_retryGrabRequested = false;
_retryReleaseRequested = false;
_regrabTimingReady = false;
}
private static void ApplyGrabInput(CharacterInput input, bool pressedEdge)
{
input.usePrimaryWasPressed = pressedEdge;
input.usePrimaryIsPressed = true;
input.usePrimaryWasReleased = false;
}
private static void ApplyReleaseInput(CharacterInput input, bool releasedEdge)
{
input.usePrimaryWasPressed = false;
input.usePrimaryIsPressed = false;
input.usePrimaryWasReleased = releasedEdge;
}
private void LogRuntimeFailure(string stage, Exception ex)
{
if (!_loggedRuntimeFailure)
{
_loggedRuntimeFailure = true;
((BaseUnityPlugin)this).Logger.LogError((object)("Auto Grab Climb " + stage + " error: " + UnwrapException(ex).Message));
}
}
private static Exception UnwrapException(Exception ex)
{
if (!(ex is TargetInvocationException { InnerException: not null } ex2))
{
return ex;
}
return ex2.InnerException;
}
}
[HarmonyPatch(typeof(Character), "CalculateWorldMovementDir")]
internal static class ControllerWorldMovementPatch
{
internal struct SavedMovement
{
public CharacterInput Input;
public Vector2 Movement;
}
[HarmonyPrefix]
private static void Prefix(Character __instance, out SavedMovement __state)
{
//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_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
__state = default(SavedMovement);
Plugin instance = Plugin.Instance;
if (!((Object)(object)instance == (Object)null) && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.input == (Object)null) && instance.ShouldBridgeMovementSprint(__instance))
{
__state.Input = __instance.input;
__state.Movement = __state.Input.movementInput;
__state.Input.movementInput = Vector2.up;
}
}
[HarmonyFinalizer]
private static void Finalizer(SavedMovement __state)
{
//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)
if ((Object)(object)__state.Input != (Object)null)
{
__state.Input.movementInput = __state.Movement;
}
}
}
[HarmonyPatch(typeof(CharacterMovement), "SetMovementState")]
internal static class ControllerSprintMovementPatch
{
internal struct SavedInput
{
public CharacterInput Input;
public bool SprintHeld;
}
[HarmonyPrefix]
private static void Prefix(Character ___character, out SavedInput __state)
{
__state = default(SavedInput);
Plugin instance = Plugin.Instance;
if (!((Object)(object)instance == (Object)null) && !((Object)(object)___character == (Object)null) && !((Object)(object)___character.input == (Object)null) && instance.ShouldBridgeMovementSprint(___character))
{
__state.Input = ___character.input;
__state.SprintHeld = __state.Input.sprintIsPressed;
__state.Input.sprintIsPressed = true;
}
}
[HarmonyFinalizer]
private static void Finalizer(SavedInput __state)
{
if ((Object)(object)__state.Input != (Object)null)
{
__state.Input.sprintIsPressed = __state.SprintHeld;
}
}
}
[HarmonyPatch(typeof(CharacterClimbing), "Update")]
internal static class CharacterClimbingUpdatePatch
{
[HarmonyPrefix]
private static void Prefix(CharacterClimbing __instance)
{
Plugin instance = Plugin.Instance;
if ((Object)(object)instance != (Object)null)
{
instance.BeforeClimbingUpdate(__instance);
}
}
[HarmonyPostfix]
private static void Postfix(CharacterClimbing __instance)
{
Plugin instance = Plugin.Instance;
if ((Object)(object)instance != (Object)null)
{
instance.AfterClimbingUpdate(__instance);
}
}
}
[HarmonyPatch(typeof(CharacterClimbing), "FixedUpdate")]
internal static class CharacterClimbingFixedUpdatePatch
{
[HarmonyPrefix]
private static void Prefix(CharacterClimbing __instance)
{
Plugin instance = Plugin.Instance;
if ((Object)(object)instance != (Object)null)
{
instance.BeforeClimbingFixedUpdate(__instance);
}
}
[HarmonyPostfix]
private static void Postfix(CharacterClimbing __instance)
{
Plugin instance = Plugin.Instance;
if ((Object)(object)instance != (Object)null)
{
instance.AfterClimbingFixedUpdate(__instance);
}
}
}
}