Decompiled source of WallGrabJump v1.1.1
Mods/WallGrabJump.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
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)