Decompiled source of NexusLocomotion v1.0.1

Mods/NexusLocomotion.dll

Decompiled 2 months ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using GamepadLocomotion;
using HarmonyLib;
using MelonLoader;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Main), "GamepadLocomotion", "1.4.0", "Jake", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("GamepadLocomotion")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GamepadLocomotion")]
[assembly: AssemblyTitle("GamepadLocomotion")]
[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 GamepadLocomotion
{
	public class Main : MelonMod
	{
		private struct XInputGamepad
		{
			public ushort Buttons;

			public byte LeftTrigger;

			public byte RightTrigger;

			public short LeftStickX;

			public short LeftStickY;

			public short RightStickX;

			public short RightStickY;
		}

		private struct XInputState
		{
			public uint PacketNumber;

			public XInputGamepad Gamepad;
		}

		private const uint ERROR_SUCCESS = 0u;

		private const ushort DPAD_UP = 1;

		private const ushort DPAD_DOWN = 2;

		private const ushort DPAD_LEFT = 4;

		private const ushort DPAD_RIGHT = 8;

		private const ushort BUTTON_A = 4096;

		private const ushort BUTTON_START = 16;

		private bool controllerConnected;

		private bool playerReady;

		private bool setupComplete;

		private object openControllerRig;

		private object physicsRig;

		private object leftController;

		private static Type vector2Type;

		private static ConstructorInfo vector2Constructor;

		private MethodInfo secondaryThumbstickMethod;

		private static Type vector3Type;

		private static ConstructorInfo vector3Constructor;

		private PropertyInfo groundVelocityProperty;

		private const float MOVE_SPEED = 3f;

		private FieldInfo thumbstickAxisField;

		private PropertyInfo thumbstickAxisProperty;

		private object torso;

		private object rbChest;

		private object directionMasterTransform;

		private MethodInfo addForceMethod;

		private MethodInfo isSleepingMethod;

		private MethodInfo quaternionVector3MultiplyMethod;

		private Type forceModeType;

		private object forceModeAcceleration;

		private const float FORCE_MULTIPLIER = 12f;

		private PropertyInfo axisPrimaryProperty;

		private PropertyInfo axisPrimaryDirtyProperty;

		private PropertyInfo primaryStickProperty;

		private PropertyInfo primaryStickTouchProperty;

		private Harmony harmony;

		private bool patchApplied;

		private bool onMarrowReadyPatchApplied;

		private static Main instance;

		private object xrControllerLeft;

		private PropertyInfo joystick2DAxisProperty;

		private bool xrControllerFound;

		private readonly Stopwatch deltaClock = new Stopwatch();

		private bool scannedOnce;

		private bool aButtonWasDown;

		private bool startButtonWasDown;

		private PropertyInfo quickmenuEnabledProperty;

		private PropertyInfo bButtonProperty;

		private PropertyInfo bButtonDownProperty;

		private PropertyInfo bButtonUpProperty;

		private object xrControllerRight;

		private PropertyInfo aButtonProperty;

		private PropertyInfo aButtonDownProperty;

		private PropertyInfo aButtonUpProperty;

		private int velocityLogCounter;

		private static float currentX;

		private static float currentY;

		private static float currentRightX;

		private static float currentRightY;

		private static bool loggedFirstCall;

		[DllImport("XInput1_4.dll", CallingConvention = CallingConvention.StdCall)]
		private static extern uint XInputGetState(uint userIndex, out XInputState state);

		public override void OnInitializeMelon()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			MelonLogger.Msg("");
			MelonLogger.Msg("======================================");
			MelonLogger.Msg(" GamepadLocomotion 1.4.0");
			MelonLogger.Msg(" BoneLib.Player based rig access");
			MelonLogger.Msg("======================================");
			MelonLogger.Msg("[Gamepad] Waiting for XInput controller...");
			instance = this;
			harmony = new Harmony("com.jake.gamepadlocomotion");
			try
			{
				Type type = FindType("Il2CppSLZ.Marrow.OpenControllerRig");
				if (type == null)
				{
					MelonLogger.Error("[Setup] OpenControllerRig type not found for OnMarrowReady patch.");
					return;
				}
				MethodInfo method = type.GetMethod("OnMarrowReady", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method == null)
				{
					MelonLogger.Error("[Setup] OnMarrowReady method not found.");
					return;
				}
				MethodInfo method2 = typeof(Main).GetMethod("OnMarrowReadyPostfix", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				onMarrowReadyPatchApplied = true;
				MelonLogger.Msg("[Setup] OnMarrowReady patched - will re-sync on every level load.");
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[Setup] OnMarrowReady patch error: " + ex.Message);
			}
		}

		private static void OnMarrowReadyPostfix()
		{
			try
			{
				instance?.TriggerRefresh("OnMarrowReady");
			}
			catch
			{
			}
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			TriggerRefresh("Scene loaded: " + sceneName);
		}

		private void TriggerRefresh(string reason)
		{
			MelonLogger.Msg("[Player] " + reason + " - re-acquiring rig references.");
			playerReady = false;
			setupComplete = false;
			openControllerRig = null;
			physicsRig = null;
			leftController = null;
			torso = null;
			rbChest = null;
			directionMasterTransform = null;
			xrControllerLeft = null;
			xrControllerRight = null;
			xrControllerFound = false;
		}

		public override void OnUpdate()
		{
			CheckController();
			if (!playerReady)
			{
				FindPlayer();
			}
			else if (!setupComplete)
			{
				SetupMovement();
			}
			else if (!controllerConnected)
			{
				currentX = 0f;
				currentY = 0f;
			}
			else
			{
				UpdateStickValues();
			}
		}

		private bool GetControllerState(out XInputState state)
		{
			return XInputGetState(0u, out state) == 0;
		}

		private void CheckController()
		{
			XInputState state;
			bool controllerState = GetControllerState(out state);
			if (controllerState && !controllerConnected)
			{
				controllerConnected = true;
				MelonLogger.Msg("[Gamepad] XInput controller detected.");
			}
			if (!controllerState && controllerConnected)
			{
				controllerConnected = false;
				MelonLogger.Msg("[Gamepad] Controller disconnected.");
			}
		}

		private void FindPlayer()
		{
			try
			{
				Type type = FindType("BoneLib.Player");
				if (type == null)
				{
					MelonLogger.Error("[Player] BoneLib.Player type was not found. Is BoneLib loaded?");
					return;
				}
				object staticPropertyValue = GetStaticPropertyValue(type, "ControllerRig");
				if (staticPropertyValue != null)
				{
					openControllerRig = staticPropertyValue;
					object staticPropertyValue2 = GetStaticPropertyValue(type, "PhysicsRig");
					physicsRig = staticPropertyValue2;
					object obj = GetStaticPropertyValue(type, "LeftController");
					if (obj == null)
					{
						obj = GetInstancePropertyValue(staticPropertyValue, "leftController") ?? GetInstanceFieldValue(staticPropertyValue, "leftController");
					}
					leftController = obj;
					playerReady = true;
					MelonLogger.Msg("");
					MelonLogger.Msg("[Player] ControllerRig found via BoneLib.Player.");
					MelonLogger.Msg("[Player] PhysicsRig: " + ((physicsRig != null) ? "found" : "NOT found"));
					MelonLogger.Msg("[Player] leftController: " + ((leftController != null) ? "found" : "NOT found"));
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[Player] " + ex.Message);
			}
		}

		private void SetupMovement()
		{
			//IL_07bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d0: Expected O, but got Unknown
			//IL_07d0: Expected O, but got Unknown
			try
			{
				Type type = openControllerRig.GetType();
				MelonLogger.Msg("[Movement] Rig = " + type.FullName);
				vector2Type = FindType("UnityEngine.Vector2");
				if (vector2Type == null)
				{
					MelonLogger.Error("[Movement] UnityEngine.Vector2 was not found.");
					return;
				}
				vector2Constructor = vector2Type.GetConstructor(new Type[2]
				{
					typeof(float),
					typeof(float)
				});
				if (vector2Constructor == null)
				{
					MelonLogger.Error("[Movement] Vector2 constructor not found.");
					return;
				}
				MelonLogger.Msg("[Movement] Vector2 interface ready.");
				vector3Type = FindType("UnityEngine.Vector3");
				if (vector3Type != null)
				{
					vector3Constructor = vector3Type.GetConstructor(new Type[3]
					{
						typeof(float),
						typeof(float),
						typeof(float)
					});
				}
				if (physicsRig != null)
				{
					groundVelocityProperty = FindProperty(physicsRig.GetType(), "groundVelocity");
					MelonLogger.Msg("[Movement] groundVelocity: " + ((groundVelocityProperty != null) ? "found" : "not found"));
				}
				if (leftController != null)
				{
					Type type2 = leftController.GetType();
					thumbstickAxisField = type2.GetField("_thumbstickAxis", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					thumbstickAxisProperty = FindProperty(type2, "_thumbstickAxis") ?? FindProperty(type2, "thumbstickAxis");
					MelonLogger.Msg("[Movement] leftController type: " + type2.FullName);
					MelonLogger.Msg("[Movement] _thumbstickAxis field: " + ((thumbstickAxisField != null) ? "found" : "not found"));
					MelonLogger.Msg("[Movement] _thumbstickAxis property: " + ((thumbstickAxisProperty != null) ? "found" : "not found"));
					if (!scannedOnce)
					{
						ScanForKeywordMethods(type2, "thumbstick");
						ScanForKeywordMethods(type2, "axis");
						ScanForKeywordMethods(type2, "Menu");
					}
				}
				else
				{
					MelonLogger.Msg("[Movement] leftController not available - cannot set _thumbstickAxis.");
				}
				if (physicsRig != null)
				{
					torso = GetInstancePropertyValue(physicsRig, "torso") ?? GetInstanceFieldValue(physicsRig, "torso");
					MelonLogger.Msg("[Movement] torso: " + ((torso != null) ? "found" : "not found"));
					if (torso != null)
					{
						rbChest = GetInstancePropertyValue(torso, "rbChest") ?? GetInstanceFieldValue(torso, "rbChest");
						MelonLogger.Msg("[Movement] rbChest: " + ((rbChest != null) ? "found" : "not found"));
					}
				}
				directionMasterTransform = GetInstancePropertyValue(openControllerRig, "directionMasterTransform") ?? GetInstanceFieldValue(openControllerRig, "directionMasterTransform");
				MelonLogger.Msg("[Movement] directionMasterTransform: " + ((directionMasterTransform != null) ? "found" : "not found"));
				if (rbChest != null)
				{
					Type type3 = rbChest.GetType();
					Type type4 = FindType("UnityEngine.Quaternion");
					forceModeType = FindType("UnityEngine.ForceMode");
					if (type4 != null && vector3Type != null)
					{
						quaternionVector3MultiplyMethod = type4.GetMethod("op_Multiply", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { type4, vector3Type }, null);
					}
					if (forceModeType != null)
					{
						addForceMethod = type3.GetMethod("AddForce", BindingFlags.Instance | BindingFlags.Public, null, new Type[2] { vector3Type, forceModeType }, null);
						forceModeAcceleration = Enum.ToObject(forceModeType, 5);
					}
					isSleepingMethod = type3.GetMethod("IsSleeping", BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null);
					MelonLogger.Msg("[Movement] AddForce method: " + ((addForceMethod != null) ? "found" : "not found"));
					MelonLogger.Msg("[Movement] Quaternion*Vector3 operator: " + ((quaternionVector3MultiplyMethod != null) ? "found" : "not found"));
					object instancePropertyValue = GetInstancePropertyValue(rbChest, "isKinematic");
					object instancePropertyValue2 = GetInstancePropertyValue(rbChest, "mass");
					MelonLogger.Msg("[Movement] rbChest.isKinematic: " + ((instancePropertyValue != null) ? instancePropertyValue.ToString() : "?"));
					MelonLogger.Msg("[Movement] rbChest.mass: " + ((instancePropertyValue2 != null) ? instancePropertyValue2.ToString() : "?"));
				}
				if (!scannedOnce)
				{
					scannedOnce = true;
					ScanForKeywordMethods(type, "Primary");
					ScanForKeywordMethods(type, "Jump");
					ScanForKeywordMethods(type, "Menu");
					Type type5 = FindType("BoneLib.Player");
					if (type5 != null)
					{
						object staticPropertyValue = GetStaticPropertyValue(type5, "RigManager");
						if (staticPropertyValue != null)
						{
							MelonLogger.Msg("[Scan] RigManager type: " + staticPropertyValue.GetType().FullName);
							ScanForKeywordMethods(staticPropertyValue.GetType(), "Menu");
						}
					}
					if (physicsRig != null)
					{
						Type type6 = physicsRig.GetType();
						MelonLogger.Msg("[Scan] PhysicsRig type: " + type6.FullName);
						ScanForKeywordMethods(type6, "Primary");
						ScanForKeywordMethods(type6, "Jump");
						ScanForKeywordMethods(type6, "Move");
						ScanForKeywordMethods(type6, "Velocity");
						ScanForKeywordMethods(type6, "Menu");
					}
					else
					{
						MelonLogger.Msg("[Scan] PhysicsRig was not available to scan.");
					}
				}
				axisPrimaryProperty = FindProperty(type, "_axisPrimary") ?? FindProperty(type, "axisPrimary");
				axisPrimaryDirtyProperty = FindProperty(type, "_axisPrimaryDirty") ?? FindProperty(type, "axisPrimaryDirty");
				primaryStickProperty = FindProperty(type, "_primaryStick") ?? FindProperty(type, "primaryStick");
				primaryStickTouchProperty = FindProperty(type, "_primaryStickTouch") ?? FindProperty(type, "primaryStickTouch");
				MelonLogger.Msg("[Movement] Direct axisPrimary: " + ((axisPrimaryProperty != null) ? "found" : "not found"));
				quickmenuEnabledProperty = FindProperty(type, "quickmenuEnabled");
				MelonLogger.Msg("[Movement] quickmenuEnabled: " + ((quickmenuEnabledProperty != null) ? "found - START button will toggle it" : "not found"));
				MethodInfo method = type.GetMethod("GetPrimaryAxis", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (method == null)
				{
					MelonLogger.Error("[Movement] GetPrimaryAxis() was not found on " + type.FullName);
				}
				else if (!patchApplied)
				{
					MethodInfo method2 = typeof(Main).GetMethod("PrimaryAxisPostfix", BindingFlags.Static | BindingFlags.NonPublic);
					MethodInfo method3 = typeof(Main).GetMethod("PrimaryAxisPrefix", BindingFlags.Static | BindingFlags.NonPublic);
					harmony.Patch((MethodBase)method, new HarmonyMethod(method3), new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					patchApplied = true;
					MelonLogger.Msg("[Movement] GetPrimaryAxis() patched.");
				}
				try
				{
					Type type7 = FindType("Il2CppSLZ.Marrow.Utilities.MarrowGame");
					if (type7 == null)
					{
						MelonLogger.Error("[XR2] Il2CppSLZ.Marrow.Utilities.MarrowGame not found.");
					}
					else
					{
						object staticPropertyValue2 = GetStaticPropertyValue(type7, "xr");
						if (staticPropertyValue2 == null)
						{
							MelonLogger.Error("[XR2] MarrowGame.xr returned null.");
						}
						else
						{
							xrControllerLeft = GetInstancePropertyValue(staticPropertyValue2, "LeftController");
							if (xrControllerLeft == null)
							{
								MelonLogger.Error("[XR2] XRApi.LeftController is null.");
							}
							else
							{
								joystick2DAxisProperty = FindProperty(xrControllerLeft.GetType(), "Joystick2DAxis");
								xrControllerFound = joystick2DAxisProperty != null;
								MelonLogger.Msg("[XR2] XRController type: " + xrControllerLeft.GetType().FullName);
								MelonLogger.Msg("[XR2] Joystick2DAxis property: " + (xrControllerFound ? "found" : "not found"));
								Type type8 = xrControllerLeft.GetType();
								bButtonProperty = FindProperty(type8, "BButton");
								bButtonDownProperty = FindProperty(type8, "BButtonDown");
								bButtonUpProperty = FindProperty(type8, "BButtonUp");
								MelonLogger.Msg("[XR2] BButton properties: " + ((bButtonProperty != null && bButtonDownProperty != null && bButtonUpProperty != null) ? "found - START opens radial menu" : "not found"));
								xrControllerRight = GetInstancePropertyValue(staticPropertyValue2, "RightController");
								if (xrControllerRight != null)
								{
									Type type9 = xrControllerRight.GetType();
									aButtonProperty = FindProperty(type9, "AButton");
									aButtonDownProperty = FindProperty(type9, "AButtonDown");
									aButtonUpProperty = FindProperty(type9, "AButtonUp");
									MelonLogger.Msg("[XR2] AButton properties: " + ((aButtonProperty != null && aButtonDownProperty != null && aButtonUpProperty != null) ? "found - A button jumps" : "not found"));
								}
								else
								{
									MelonLogger.Error("[XR2] XRApi.RightController is null.");
								}
							}
						}
					}
				}
				catch (Exception ex)
				{
					MelonLogger.Error("[XR2] Setup error: " + ex.Message);
				}
				secondaryThumbstickMethod = type.GetMethod("ProcessSecondaryThumbstick", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2]
				{
					vector2Type,
					typeof(float)
				}, null);
				if (secondaryThumbstickMethod == null)
				{
					MelonLogger.Error("[Movement] ProcessSecondaryThumbstick(Vector2, float) was not found.");
				}
				else
				{
					MelonLogger.Msg("[Movement] ProcessSecondaryThumbstick found.");
					MelonLogger.Msg("[Movement] RIGHT STICK -> rotation");
					if (!deltaClock.IsRunning)
					{
						deltaClock.Start();
					}
				}
				MelonLogger.Msg("[Movement] LEFT STICK -> primary axis");
				MelonLogger.Msg("[Movement] DPAD -> primary axis backup");
				setupComplete = true;
				MelonLogger.Msg("[Movement] Setup complete.");
			}
			catch (Exception ex2)
			{
				MelonLogger.Error("[Movement] Setup error: " + ex2.Message);
			}
		}

		private static void ScanForKeywordMethods(Type startType, string keyword)
		{
			try
			{
				MelonLogger.Msg("[Scan] Searching " + startType.FullName + " and base classes for \"" + keyword + "\" methods...");
				Type type = startType;
				int num = 0;
				while (type != null && type != typeof(object))
				{
					MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					MethodInfo[] array = methods;
					foreach (MethodInfo methodInfo in array)
					{
						if (methodInfo.Name.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) < 0)
						{
							continue;
						}
						ParameterInfo[] parameters = methodInfo.GetParameters();
						string text = "";
						for (int j = 0; j < parameters.Length; j++)
						{
							if (j > 0)
							{
								text += ", ";
							}
							text += parameters[j].ParameterType.Name;
						}
						MelonLogger.Msg("[Scan] " + type.Name + "." + methodInfo.Name + "(" + text + ") -> " + methodInfo.ReturnType.Name);
						num++;
					}
					type = type.BaseType;
				}
				MelonLogger.Msg("[Scan] Done. " + num + " match(es).");
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[Scan] " + ex.Message);
			}
		}

		private static void PrimaryAxisPrefix()
		{
			if (!loggedFirstCall)
			{
				loggedFirstCall = true;
				MelonLogger.Msg("[Movement] CONFIRMED: GetPrimaryAxis() was called by the game.");
			}
		}

		private static void PrimaryAxisPostfix(ref object __result)
		{
			try
			{
				if (!(vector2Constructor == null))
				{
					__result = vector2Constructor.Invoke(new object[2] { currentX, currentY });
				}
			}
			catch
			{
			}
		}

		private void UpdateStickValues()
		{
			try
			{
				if (!GetControllerState(out var state))
				{
					currentX = 0f;
					currentY = 0f;
					return;
				}
				float num = NormalizeStick(state.Gamepad.LeftStickX);
				float num2 = NormalizeStick(state.Gamepad.LeftStickY);
				ushort buttons = state.Gamepad.Buttons;
				if ((buttons & 4) != 0)
				{
					num = -1f;
				}
				if ((buttons & 8) != 0)
				{
					num = 1f;
				}
				if ((buttons & 2) != 0)
				{
					num2 = -1f;
				}
				if ((buttons & 1) != 0)
				{
					num2 = 1f;
				}
				if (Math.Abs(num) < 0.12f)
				{
					num = 0f;
				}
				if (Math.Abs(num2) < 0.12f)
				{
					num2 = 0f;
				}
				currentX = num;
				currentY = num2;
				if (groundVelocityProperty != null && vector3Constructor != null && physicsRig != null)
				{
					object value = vector3Constructor.Invoke(new object[3]
					{
						num * 3f,
						0f,
						num2 * 3f
					});
					groundVelocityProperty.SetValue(physicsRig, value);
				}
				if (leftController != null && vector2Constructor != null && (thumbstickAxisField != null || thumbstickAxisProperty != null))
				{
					object value2 = vector2Constructor.Invoke(new object[2] { num, num2 });
					if (thumbstickAxisField != null)
					{
						thumbstickAxisField.SetValue(leftController, value2);
					}
					else
					{
						thumbstickAxisProperty.SetValue(leftController, value2);
					}
				}
				if (xrControllerFound && xrControllerLeft != null && vector2Constructor != null)
				{
					object value3 = vector2Constructor.Invoke(new object[2] { num, num2 });
					joystick2DAxisProperty.SetValue(xrControllerLeft, value3);
				}
				if (addForceMethod != null && rbChest != null && directionMasterTransform != null && vector3Constructor != null)
				{
					object obj = vector3Constructor.Invoke(new object[3] { num, 0f, num2 });
					object instancePropertyValue = GetInstancePropertyValue(directionMasterTransform, "rotation");
					object obj2 = obj;
					if (instancePropertyValue != null && quaternionVector3MultiplyMethod != null)
					{
						obj2 = quaternionVector3MultiplyMethod.Invoke(null, new object[2] { instancePropertyValue, obj });
					}
					Type type = obj2.GetType();
					float num3 = (float)type.GetField("x").GetValue(obj2);
					float num4 = (float)type.GetField("y").GetValue(obj2);
					float num5 = (float)type.GetField("z").GetValue(obj2);
					object obj3 = vector3Constructor.Invoke(new object[3]
					{
						num3 * 12f,
						num4 * 12f,
						num5 * 12f
					});
					addForceMethod.Invoke(rbChest, new object[2] { obj3, forceModeAcceleration });
					velocityLogCounter++;
					if (velocityLogCounter >= 60)
					{
						velocityLogCounter = 0;
						object instancePropertyValue2 = GetInstancePropertyValue(rbChest, "velocity");
						object instancePropertyValue3 = GetInstancePropertyValue(rbChest, "isKinematic");
						object obj4 = null;
						if (isSleepingMethod != null)
						{
							try
							{
								obj4 = isSleepingMethod.Invoke(rbChest, null);
							}
							catch
							{
							}
						}
						MelonLogger.Msg("[Movement] rbChest.velocity: " + ((instancePropertyValue2 != null) ? instancePropertyValue2.ToString() : "?") + " | kinematic: " + ((instancePropertyValue3 != null) ? instancePropertyValue3.ToString() : "?") + " | sleeping: " + ((obj4 != null) ? obj4.ToString() : "?") + " | input: " + num.ToString("F2") + "," + num2.ToString("F2"));
					}
				}
				if (axisPrimaryProperty != null && vector2Constructor != null)
				{
					object value4 = vector2Constructor.Invoke(new object[2] { num, num2 });
					axisPrimaryProperty.SetValue(openControllerRig, value4);
				}
				bool flag = num != 0f || num2 != 0f;
				if (axisPrimaryDirtyProperty != null)
				{
					axisPrimaryDirtyProperty.SetValue(openControllerRig, true);
				}
				if (primaryStickProperty != null)
				{
					primaryStickProperty.SetValue(openControllerRig, flag);
				}
				if (primaryStickTouchProperty != null)
				{
					primaryStickTouchProperty.SetValue(openControllerRig, flag);
				}
				float value5 = NormalizeStick(state.Gamepad.RightStickX);
				float value6 = NormalizeStick(state.Gamepad.RightStickY);
				if (Math.Abs(value5) < 0.15f)
				{
					value5 = 0f;
				}
				if (Math.Abs(value6) < 0.15f)
				{
					value6 = 0f;
				}
				currentRightX = value5;
				currentRightY = value6;
				bool flag2 = (buttons & 0x1000) != 0;
				bool flag3 = flag2 && !aButtonWasDown;
				bool flag4 = !flag2 && aButtonWasDown;
				if (aButtonProperty != null && aButtonDownProperty != null && aButtonUpProperty != null && xrControllerRight != null)
				{
					aButtonProperty.SetValue(xrControllerRight, flag2);
					aButtonDownProperty.SetValue(xrControllerRight, flag3);
					aButtonUpProperty.SetValue(xrControllerRight, flag4);
					if (flag3)
					{
						MelonLogger.Msg("[Movement] A pressed -> jump.");
					}
				}
				aButtonWasDown = flag2;
				bool flag5 = (buttons & 0x10) != 0;
				bool flag6 = flag5 && !startButtonWasDown;
				bool flag7 = !flag5 && startButtonWasDown;
				if (bButtonProperty != null && bButtonDownProperty != null && bButtonUpProperty != null && xrControllerRight != null)
				{
					bButtonProperty.SetValue(xrControllerRight, flag5);
					bButtonDownProperty.SetValue(xrControllerRight, flag6);
					bButtonUpProperty.SetValue(xrControllerRight, flag7);
					if (flag6)
					{
						MelonLogger.Msg("[Movement] START pressed -> radial menu.");
					}
				}
				startButtonWasDown = flag5;
				if (secondaryThumbstickMethod != null && vector2Constructor != null && openControllerRig != null)
				{
					float num6 = (float)deltaClock.Elapsed.TotalSeconds;
					deltaClock.Restart();
					object obj6 = vector2Constructor.Invoke(new object[2] { currentRightX, currentRightY });
					secondaryThumbstickMethod.Invoke(openControllerRig, new object[2] { obj6, num6 });
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[Movement] " + ex.Message);
				torso = null;
				rbChest = null;
				directionMasterTransform = null;
				leftController = null;
				thumbstickAxisField = null;
				thumbstickAxisProperty = null;
				secondaryThumbstickMethod = null;
				xrControllerLeft = null;
				xrControllerRight = null;
				xrControllerFound = false;
			}
		}

		private float NormalizeStick(short value)
		{
			if (value >= 0)
			{
				return (float)value / 32767f;
			}
			return (float)value / 32768f;
		}

		private static PropertyInfo FindProperty(Type type, string name)
		{
			return type.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		private static object GetStaticPropertyValue(Type type, string name)
		{
			try
			{
				PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (property == null)
				{
					return null;
				}
				return property.GetValue(null);
			}
			catch
			{
				return null;
			}
		}

		private static object GetInstancePropertyValue(object instance, string name)
		{
			if (instance == null)
			{
				return null;
			}
			try
			{
				PropertyInfo propertyInfo = FindProperty(instance.GetType(), name);
				if (propertyInfo == null)
				{
					return null;
				}
				return propertyInfo.GetValue(instance);
			}
			catch
			{
				return null;
			}
		}

		private static object GetInstanceFieldValue(object instance, string name)
		{
			if (instance == null)
			{
				return null;
			}
			try
			{
				FieldInfo field = instance.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null)
				{
					return null;
				}
				return field.GetValue(instance);
			}
			catch
			{
				return null;
			}
		}

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