Decompiled source of GorillaMovement v0.4.0

Mods/GorillaMovement.dll

Decompiled 7 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib.BoneMenu;
using GorillaMovement;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MelonLoader;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(GorillaMovementMod), "Gorilla Movement", "0.4.0", "GorillaMovement", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("GorillaMovement")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GorillaMovement")]
[assembly: AssemblyTitle("GorillaMovement")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GorillaMovement
{
	public static class GorillaLocomotion
	{
		private sealed class HandState
		{
			public Transform Controller;

			public Vector3 PreviousPosition;

			public Vector3 ContactNormal;

			public bool HasPreviousPosition;

			public bool Touching;
		}

		private static readonly HandState left = new HandState();

		private static readonly HandState right = new HandState();

		private static Transform physicsRigRoot;

		private static Transform controllerRigRoot;

		private static Transform headTransform;

		private static Rigidbody chestBody;

		private static Vector3[] velocityHistory;

		private static int velocityIndex;

		private static Vector3 velocityAverage;

		private static bool enabled;

		private static bool referencesWarningLogged;

		private static bool leftWasTouching;

		private static bool rightWasTouching;

		public static void Enable()
		{
			enabled = true;
			ResetTracking();
			RefreshPlayerReferences();
			PlayerRigCollision.Enable(physicsRigRoot, controllerRigRoot, chestBody);
		}

		public static void Disable()
		{
			enabled = false;
			PlayerRigCollision.Disable();
			RecoverRigFromFloor();
			ResetTracking();
		}

		public static void UpdateMovement()
		{
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: 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)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: 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_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_0475: Unknown result type (might be due to invalid IL or missing references)
			//IL_0476: Unknown result type (might be due to invalid IL or missing references)
			//IL_0480: Unknown result type (might be due to invalid IL or missing references)
			//IL_0481: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_042e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			if (!MovementSettings.Enabled || !enabled || !RefreshPlayerReferences())
			{
				return;
			}
			PlayerRigCollision.Enable(physicsRigRoot, controllerRigRoot, chestBody);
			if ((Object)(object)left.Controller == (Object)null || (Object)(object)right.Controller == (Object)null || (Object)(object)physicsRigRoot == (Object)null || (Object)(object)chestBody == (Object)null)
			{
				return;
			}
			float fixedDeltaTime = Time.fixedDeltaTime;
			if (fixedDeltaTime <= 0f)
			{
				return;
			}
			int num = Mathf.Clamp(MovementSettings.VelocityHistorySize, 2, 32);
			if (velocityHistory == null || velocityHistory.Length != num)
			{
				velocityHistory = (Vector3[])(object)new Vector3[num];
				velocityIndex = 0;
				velocityAverage = Vector3.zero;
				left.HasPreviousPosition = false;
				right.HasPreviousPosition = false;
			}
			Vector3 val = LimitArmReach(left.Controller.position);
			Vector3 val2 = LimitArmReach(right.Controller.position);
			if (!left.HasPreviousPosition || !right.HasPreviousPosition)
			{
				left.PreviousPosition = val;
				right.PreviousPosition = val2;
				left.HasPreviousPosition = true;
				right.HasPreviousPosition = true;
				return;
			}
			Vector3 val3 = val - left.PreviousPosition;
			Vector3 val4 = val2 - right.PreviousPosition;
			UpdateHandContact(left, left.PreviousPosition, val);
			UpdateHandContact(right, right.PreviousPosition, val2);
			Vector3 val5 = Vector3.zero;
			int num2 = 0;
			if (left.Touching)
			{
				Vector3 val6 = Vector3.Project(val3, -left.ContactNormal);
				if (Vector3.Dot(val3, -left.ContactNormal) > 0f)
				{
					val5 -= val6 * MovementSettings.PushStrength;
					num2++;
				}
			}
			if (right.Touching)
			{
				Vector3 val7 = Vector3.Project(val4, -right.ContactNormal);
				if (Vector3.Dot(val4, -right.ContactNormal) > 0f)
				{
					val5 -= val7 * MovementSettings.PushStrength;
					num2++;
				}
			}
			if (num2 > 1)
			{
				val5 /= Mathf.Sqrt((float)num2);
			}
			float num3 = Mathf.Max(0.015f, MovementSettings.MaxSpeed * fixedDeltaTime);
			val5 = Vector3.ClampMagnitude(val5, num3);
			if (((Vector3)(ref val5)).sqrMagnitude > 1E-07f)
			{
				Transform obj = physicsRigRoot;
				obj.position += val5;
				Vector3 velocity = chestBody.velocity;
				Vector3 val8 = val5 / fixedDeltaTime;
				chestBody.velocity = Vector3.ClampMagnitude(velocity + val8, MovementSettings.MaxSpeed);
			}
			Vector3 val9 = val5 / fixedDeltaTime;
			velocityIndex = (velocityIndex + 1) % velocityHistory.Length;
			Vector3 val10 = velocityHistory[velocityIndex];
			velocityAverage += (val9 - val10) / (float)velocityHistory.Length;
			velocityHistory[velocityIndex] = val9;
			if ((leftWasTouching && !left.Touching) || (rightWasTouching && !right.Touching))
			{
				Vector3 velocity2 = Vector3.ClampMagnitude(velocityAverage * MovementSettings.JumpMultiplier, MovementSettings.MaxSpeed);
				if (((Vector3)(ref velocity2)).magnitude >= MovementSettings.VelocityLimit)
				{
					chestBody.velocity = velocity2;
				}
				velocityAverage = Vector3.zero;
				Array.Clear(velocityHistory, 0, velocityHistory.Length);
				velocityIndex = 0;
			}
			leftWasTouching = left.Touching;
			rightWasTouching = right.Touching;
			left.PreviousPosition = val;
			right.PreviousPosition = val2;
		}

		private static void UpdateHandContact(HandState hand, Vector3 previous, Vector3 current)
		{
			//IL_0009: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: 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_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			hand.Touching = false;
			hand.ContactNormal = Vector3.zero;
			float num = Mathf.Clamp(MovementSettings.HandRadius, 0.02f, 0.15f);
			Vector3 val = current - previous;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude > 0.0001f)
			{
				RaycastHit[] array = Il2CppArrayBase<RaycastHit>.op_Implicit((Il2CppArrayBase<RaycastHit>)(object)Physics.SphereCastAll(previous, num, val / magnitude, magnitude + num, -1, (QueryTriggerInteraction)1));
				float num2 = float.PositiveInfinity;
				RaycastHit[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					RaycastHit val2 = array2[i];
					if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && !PlayerRigCollision.IsPlayerCollider(((RaycastHit)(ref val2)).collider) && ((RaycastHit)(ref val2)).distance < num2)
					{
						num2 = ((RaycastHit)(ref val2)).distance;
						hand.ContactNormal = ((RaycastHit)(ref val2)).normal;
						hand.Touching = true;
					}
				}
			}
			if (hand.Touching)
			{
				return;
			}
			Collider[] array3 = Il2CppArrayBase<Collider>.op_Implicit((Il2CppArrayBase<Collider>)(object)Physics.OverlapSphere(current, num, -1, (QueryTriggerInteraction)1));
			float num3 = float.PositiveInfinity;
			Collider[] array4 = array3;
			foreach (Collider val3 in array4)
			{
				if ((Object)(object)val3 == (Object)null || PlayerRigCollision.IsPlayerCollider(val3))
				{
					continue;
				}
				Vector3 val4 = val3.ClosestPoint(current);
				Vector3 val5 = current - val4;
				float sqrMagnitude = ((Vector3)(ref val5)).sqrMagnitude;
				if (sqrMagnitude < num3)
				{
					num3 = sqrMagnitude;
					if (((Vector3)(ref val5)).sqrMagnitude > 1E-05f)
					{
						hand.ContactNormal = ((Vector3)(ref val5)).normalized;
					}
					else
					{
						hand.ContactNormal = Vector3.up;
					}
					hand.Touching = true;
				}
			}
		}

		private static bool RefreshPlayerReferences()
		{
			try
			{
				Type type = FindType("BoneLib.Player");
				if (type == null)
				{
					return Warn("Couldn't find BoneLib.Player.");
				}
				object staticMember = GetStaticMember(type, "PhysicsRig");
				object staticMember2 = GetStaticMember(type, "ControllerRig");
				if (staticMember == null || staticMember2 == null)
				{
					return Warn("Player rigs aren't ready yet.");
				}
				Transform transform = GetTransform(staticMember);
				Transform transform2 = GetTransform(staticMember2);
				object obj = GetStaticMember(type, "LeftController");
				object obj2 = GetStaticMember(type, "RightController");
				if (obj == null)
				{
					obj = FindNamedMember(staticMember2, "leftController", "leftHand", "leftHandTransform", "leftHandAnchor");
				}
				if (obj2 == null)
				{
					obj2 = FindNamedMember(staticMember2, "rightController", "rightHand", "rightHandTransform", "rightHandAnchor");
				}
				Transform transform3 = GetTransform(obj);
				Transform transform4 = GetTransform(obj2);
				object instance = FindNamedMember(staticMember, "torso", "Torso");
				object obj3 = FindNamedMember(instance, "rbChest", "chestRigidbody", "chest");
				Rigidbody val = (Rigidbody)((obj3 is Rigidbody) ? obj3 : null);
				if ((Object)(object)val == (Object)null)
				{
					val = GetComponentMember<Rigidbody>(instance);
				}
				if ((Object)(object)transform == (Object)null || (Object)(object)transform2 == (Object)null || (Object)(object)transform3 == (Object)null || (Object)(object)transform4 == (Object)null || (Object)(object)val == (Object)null)
				{
					return Warn("Could not identify live hand transforms and chest Rigidbody. The current BONELAB/FlatPlayer rig may use different member names.");
				}
				bool flag = (Object)(object)physicsRigRoot != (Object)(object)transform || (Object)(object)controllerRigRoot != (Object)(object)transform2 || (Object)(object)left.Controller != (Object)(object)transform3 || (Object)(object)right.Controller != (Object)(object)transform4 || (Object)(object)chestBody != (Object)(object)val;
				physicsRigRoot = transform;
				controllerRigRoot = transform2;
				left.Controller = transform3;
				right.Controller = transform4;
				chestBody = val;
				headTransform = FindTransformByName(staticMember2, "head", "headtransform", "headfollower", "headanchor");
				if (flag)
				{
					ResetTracking();
					PlayerRigCollision.Enable(physicsRigRoot, controllerRigRoot, chestBody);
				}
				referencesWarningLogged = false;
				return true;
			}
			catch (Exception ex)
			{
				return Warn("Rig discovery error: " + ex.Message);
			}
		}

		private static Vector3 LimitArmReach(Vector3 handPosition)
		{
			//IL_0014: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_0059: 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_0061: 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)
			if ((Object)(object)headTransform == (Object)null)
			{
				return handPosition;
			}
			Vector3 val = handPosition - headTransform.position;
			float num = Mathf.Max(0.5f, MovementSettings.MaxArmLength);
			return (((Vector3)(ref val)).magnitude > num) ? (headTransform.position + ((Vector3)(ref val)).normalized * num) : handPosition;
		}

		private static void RecoverRigFromFloor()
		{
			//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_00cc: 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)
			//IL_00d7: 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_0066: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: 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_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)physicsRigRoot == (Object)null)
			{
				return;
			}
			try
			{
				Collider[] array = Il2CppArrayBase<Collider>.op_Implicit(((Component)physicsRigRoot).GetComponentsInChildren<Collider>(true));
				float num = float.PositiveInfinity;
				Collider[] array2 = array;
				foreach (Collider val in array2)
				{
					if (!((Object)(object)val == (Object)null) && val.enabled && !val.isTrigger)
					{
						Bounds bounds = val.bounds;
						if (((Bounds)(ref bounds)).min.y < num)
						{
							bounds = val.bounds;
							num = ((Bounds)(ref bounds)).min.y;
						}
					}
				}
				if (float.IsInfinity(num))
				{
					return;
				}
				Vector3 val2 = physicsRigRoot.position + Vector3.up * 10f;
				RaycastHit[] array3 = Il2CppArrayBase<RaycastHit>.op_Implicit((Il2CppArrayBase<RaycastHit>)(object)Physics.RaycastAll(val2, Vector3.down, 25f, -1, (QueryTriggerInteraction)1));
				float num2 = float.NegativeInfinity;
				float num3 = float.PositiveInfinity;
				RaycastHit[] array4 = array3;
				for (int j = 0; j < array4.Length; j++)
				{
					RaycastHit val3 = array4[j];
					if (!((Object)(object)((RaycastHit)(ref val3)).collider == (Object)null) && !PlayerRigCollision.IsPlayerCollider(((RaycastHit)(ref val3)).collider) && ((RaycastHit)(ref val3)).distance < num3)
					{
						num3 = ((RaycastHit)(ref val3)).distance;
						num2 = ((RaycastHit)(ref val3)).point.y;
					}
				}
				if (float.IsNegativeInfinity(num2) || !(num < num2 + 0.08f))
				{
					return;
				}
				float num4 = Mathf.Clamp(num2 + 0.12f - num, 0f, 3f);
				if (!(num4 > 0f))
				{
					return;
				}
				Transform obj = physicsRigRoot;
				obj.position += Vector3.up * num4;
				if ((Object)(object)chestBody != (Object)null)
				{
					Vector3 velocity = chestBody.velocity;
					if (velocity.y < 0f)
					{
						velocity.y = 0f;
					}
					chestBody.velocity = velocity;
				}
				MelonLogger.Msg("[Gorilla Movement] Lifted player rig out of the floor by " + num4.ToString("F2") + "m.");
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[Gorilla Movement] Rig floor recovery failed: " + ex.Message);
			}
		}

		private static void ResetTracking()
		{
			//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)
			left.HasPreviousPosition = false;
			right.HasPreviousPosition = false;
			left.Touching = false;
			right.Touching = false;
			leftWasTouching = false;
			rightWasTouching = false;
			velocityHistory = null;
			velocityAverage = Vector3.zero;
			velocityIndex = 0;
		}

		private static Transform FindTransformByName(object rootObject, params string[] names)
		{
			Transform transform = GetTransform(rootObject);
			if ((Object)(object)transform == (Object)null)
			{
				return null;
			}
			foreach (Transform componentsInChild in ((Component)transform).GetComponentsInChildren<Transform>(true))
			{
				string text = ((Object)componentsInChild).name.ToLowerInvariant();
				foreach (string text2 in names)
				{
					if (text.Contains(text2.ToLowerInvariant()))
					{
						return componentsInChild;
					}
				}
			}
			return null;
		}

		private static object FindNamedMember(object instance, params string[] names)
		{
			if (instance == null)
			{
				return null;
			}
			foreach (string name in names)
			{
				object member = GetMember(instance, name);
				if (member != null)
				{
					return member;
				}
			}
			return null;
		}

		private static T GetComponentMember<T>(object instance) where T : Component
		{
			Transform transform = GetTransform(instance);
			return ((Object)(object)transform != (Object)null) ? ((Component)transform).GetComponentInChildren<T>(true) : default(T);
		}

		private static Transform GetTransform(object instance)
		{
			if (instance == null)
			{
				return null;
			}
			Transform val = (Transform)((instance is Transform) ? instance : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Component val2 = (Component)((instance is Component) ? instance : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2.transform;
			}
			GameObject val3 = (GameObject)((instance is GameObject) ? instance : null);
			if ((Object)(object)val3 != (Object)null)
			{
				return val3.transform;
			}
			object member = GetMember(instance, "transform");
			return (Transform)((member is Transform) ? member : null);
		}

		private static Type FindType(string fullName)
		{
			Type type = Type.GetType(fullName + ", BoneLib");
			if (type != null)
			{
				return type;
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				type = assembly.GetType(fullName);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}

		private static object GetStaticMember(Type type, string name)
		{
			Type type2 = type;
			while (type2 != null)
			{
				PropertyInfo property = type2.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null)
				{
					try
					{
						return property.GetValue(null, null);
					}
					catch
					{
					}
				}
				FieldInfo field = type2.GetField(name, BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					try
					{
						return field.GetValue(null);
					}
					catch
					{
					}
				}
				type2 = type2.BaseType;
			}
			return null;
		}

		private static object GetMember(object instance, string name)
		{
			if (instance == null)
			{
				return null;
			}
			Type type = instance.GetType();
			while (type != null)
			{
				PropertyInfo property = type.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null)
				{
					try
					{
						return property.GetValue(instance, null);
					}
					catch
					{
					}
				}
				FieldInfo field = type.GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					try
					{
						return field.GetValue(instance);
					}
					catch
					{
					}
				}
				type = type.BaseType;
			}
			return null;
		}

		private static bool Warn(string message)
		{
			if (!referencesWarningLogged)
			{
				MelonLogger.Warning("[Gorilla Movement] " + message);
				referencesWarningLogged = true;
			}
			return false;
		}
	}
	public static class GorillaMovementMenu
	{
		public static void Initialize()
		{
			//IL_000b: 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)
			//IL_0053: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			Page val = Page.Root.CreatePage("Gorilla Movement", Color.green, 0, true);
			val.CreateBool("Enable Movement", Color.white, MovementSettings.Enabled, (Action<bool>)delegate(bool value)
			{
				MovementSettings.Enabled = value;
				if (value)
				{
					GorillaLocomotion.Enable();
				}
				else
				{
					GorillaLocomotion.Disable();
				}
				MovementSettings.Save();
			});
			val.CreateFloat("Push Strength", Color.white, MovementSettings.PushStrength, 0.1f, 0.1f, 5f, (Action<float>)delegate(float value)
			{
				MovementSettings.PushStrength = value;
				MovementSettings.Save();
			});
			val.CreateFloat("Maximum Speed", Color.white, MovementSettings.MaxSpeed, 0.5f, 1f, 15f, (Action<float>)delegate(float value)
			{
				MovementSettings.MaxSpeed = value;
				MovementSettings.Save();
			});
			val.CreateFloat("Maximum Arm Reach", Color.white, MovementSettings.MaxArmLength, 0.05f, 0.75f, 2.5f, (Action<float>)delegate(float value)
			{
				MovementSettings.MaxArmLength = value;
				MovementSettings.Save();
			});
			val.CreateFloat("Hand Contact Radius", Color.white, MovementSettings.HandRadius, 0.005f, 0.02f, 0.12f, (Action<float>)delegate(float value)
			{
				MovementSettings.HandRadius = value;
				MovementSettings.Save();
			});
		}
	}
	public class GorillaMovementMod : MelonMod
	{
		public override void OnInitializeMelon()
		{
			((MelonBase)this).LoggerInstance.Msg("Gorilla Movement 0.4.0 loading...");
			MovementSettings.Initialize();
			GorillaMovementMenu.Initialize();
			if (MovementSettings.Enabled)
			{
				GorillaLocomotion.Enable();
			}
			((MelonBase)this).LoggerInstance.Msg("Gorilla Movement initialized.");
		}

		public override void OnFixedUpdate()
		{
			if (MovementSettings.Enabled)
			{
				GorillaLocomotion.UpdateMovement();
			}
		}

		public override void OnDeinitializeMelon()
		{
			GorillaLocomotion.Disable();
			MovementSettings.Save();
			((MelonBase)this).LoggerInstance.Msg("Gorilla Movement disabled and settings saved.");
		}
	}
	public static class MovementSettings
	{
		private static string configPath;

		public static bool Enabled = false;

		public static float PushStrength = 1.8f;

		public static float MaxSpeed = 7f;

		public static float HandRadius = 0.055f;

		public static float MaxArmLength = 1.5f;

		public static float VelocityLimit = 0.4f;

		public static float JumpMultiplier = 1.2f;

		public static int VelocityHistorySize = 8;

		public static void Initialize()
		{
			string text = Path.Combine(MelonEnvironment.UserDataDirectory, "GorillaMovement");
			Directory.CreateDirectory(text);
			configPath = Path.Combine(text, "Preferences.cfg");
			if (File.Exists(configPath))
			{
				Load();
			}
			Save();
		}

		public static void Save()
		{
			if (string.IsNullOrEmpty(configPath))
			{
				return;
			}
			try
			{
				Directory.CreateDirectory(Path.GetDirectoryName(configPath));
				string contents = "# Gorilla Movement settings" + Environment.NewLine + "Enabled=" + Enabled + Environment.NewLine + "PushStrength=" + PushStrength.ToString(CultureInfo.InvariantCulture) + Environment.NewLine + "MaxSpeed=" + MaxSpeed.ToString(CultureInfo.InvariantCulture) + Environment.NewLine + "HandRadius=" + HandRadius.ToString(CultureInfo.InvariantCulture) + Environment.NewLine + "MaxArmLength=" + MaxArmLength.ToString(CultureInfo.InvariantCulture) + Environment.NewLine + "VelocityLimit=" + VelocityLimit.ToString(CultureInfo.InvariantCulture) + Environment.NewLine + "JumpMultiplier=" + JumpMultiplier.ToString(CultureInfo.InvariantCulture) + Environment.NewLine + "VelocityHistorySize=" + VelocityHistorySize + Environment.NewLine;
				File.WriteAllText(configPath, contents);
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[Gorilla Movement] Could not save Preferences.cfg: " + ex.Message);
			}
		}

		private static void Load()
		{
			try
			{
				string[] array = File.ReadAllLines(configPath);
				foreach (string text in array)
				{
					string text2 = text.Trim();
					if (text2.Length == 0 || text2.StartsWith("#"))
					{
						continue;
					}
					int num = text2.IndexOf('=');
					if (num < 1)
					{
						continue;
					}
					string text3 = text2.Substring(0, num).Trim();
					string text4 = text2.Substring(num + 1).Trim();
					float result2;
					switch (text3.ToLowerInvariant())
					{
					case "enabled":
					{
						if (bool.TryParse(text4, out var result3))
						{
							Enabled = result3;
						}
						break;
					}
					case "pushstrength":
						if (float.TryParse(text4, NumberStyles.Float, CultureInfo.InvariantCulture, out result2))
						{
							PushStrength = result2;
						}
						break;
					case "maxspeed":
						if (float.TryParse(text4, NumberStyles.Float, CultureInfo.InvariantCulture, out result2))
						{
							MaxSpeed = result2;
						}
						break;
					case "handradius":
						if (float.TryParse(text4, NumberStyles.Float, CultureInfo.InvariantCulture, out result2))
						{
							HandRadius = result2;
						}
						break;
					case "maxarmlength":
						if (float.TryParse(text4, NumberStyles.Float, CultureInfo.InvariantCulture, out result2))
						{
							MaxArmLength = result2;
						}
						break;
					case "velocitylimit":
						if (float.TryParse(text4, NumberStyles.Float, CultureInfo.InvariantCulture, out result2))
						{
							VelocityLimit = result2;
						}
						break;
					case "jumpmultiplier":
						if (float.TryParse(text4, NumberStyles.Float, CultureInfo.InvariantCulture, out result2))
						{
							JumpMultiplier = result2;
						}
						break;
					case "velocityhistorysize":
					{
						if (int.TryParse(text4, out var result))
						{
							VelocityHistorySize = result;
						}
						break;
					}
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[Gorilla Movement] Could not read Preferences.cfg: " + ex.Message);
			}
		}
	}
	public static class PlayerRigCollision
	{
		private static readonly Dictionary<Collider, bool> originalStates = new Dictionary<Collider, bool>();

		private static Transform physicsRoot;

		private static Transform controllerRoot;

		private static Rigidbody chestBody;

		private static readonly string[] legTerms = new string[11]
		{
			"leg", "foot", "feet", "calf", "thigh", "shin", "knee", "ankle", "toe", "lowerleg",
			"upperleg"
		};

		public static void Enable(Transform newPhysicsRoot, Transform newControllerRoot, Rigidbody newChestBody)
		{
			physicsRoot = newPhysicsRoot;
			controllerRoot = newControllerRoot;
			chestBody = newChestBody;
			ScanRoot(physicsRoot);
			if ((Object)(object)controllerRoot != (Object)(object)physicsRoot)
			{
				ScanRoot(controllerRoot);
			}
		}

		public static void Disable()
		{
			foreach (KeyValuePair<Collider, bool> originalState in originalStates)
			{
				if ((Object)(object)originalState.Key != (Object)null)
				{
					originalState.Key.enabled = originalState.Value;
				}
			}
			originalStates.Clear();
			physicsRoot = null;
			controllerRoot = null;
			chestBody = null;
		}

		public static bool IsPlayerCollider(Collider collider)
		{
			if ((Object)(object)collider == (Object)null)
			{
				return true;
			}
			Transform transform = ((Component)collider).transform;
			return IsInside(transform, physicsRoot) || IsInside(transform, controllerRoot);
		}

		private static bool IsInside(Transform child, Transform root)
		{
			return (Object)(object)child != (Object)null && (Object)(object)root != (Object)null && ((Object)(object)child == (Object)(object)root || child.IsChildOf(root));
		}

		private static void ScanRoot(Transform root)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Collider[] array = Il2CppArrayBase<Collider>.op_Implicit(((Component)root).GetComponentsInChildren<Collider>(true));
			float chestY = (((Object)(object)chestBody != (Object)null) ? chestBody.worldCenterOfMass.y : float.PositiveInfinity);
			Collider[] array2 = array;
			foreach (Collider val in array2)
			{
				if (!((Object)(object)val == (Object)null) && BelongsToLowerBody(val, chestY))
				{
					if (!originalStates.ContainsKey(val))
					{
						originalStates.Add(val, val.enabled);
					}
					val.enabled = false;
				}
			}
		}

		private static bool BelongsToLowerBody(Collider collider, float chestY)
		{
			//IL_008b: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)collider).transform;
			while ((Object)(object)val != (Object)null)
			{
				string[] array = legTerms;
				foreach (string value in array)
				{
					if (((Object)val).name.ToLowerInvariant().Contains(value))
					{
						return true;
					}
				}
				if ((Object)(object)val == (Object)(object)physicsRoot || (Object)(object)val == (Object)(object)controllerRoot)
				{
					break;
				}
				val = val.parent;
			}
			if ((Object)(object)chestBody != (Object)null)
			{
				Bounds bounds = collider.bounds;
				if (((Bounds)(ref bounds)).center.y < chestY - 0.3f)
				{
					return true;
				}
			}
			return false;
		}
	}
}