using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using TheLabModdingLib;
using UnityEngine;
using UnityEngine.SceneManagement;
using Valve.VR.InteractionSystem;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace SmoothLocomotion;
[BepInPlugin("com.thelab.smoothlocomotion", "SmoothLocomotion", "1.0.0")]
public class SmoothLocomotionMod : BaseUnityPlugin
{
private ConfigEntry<bool> configEnabled;
private ConfigEntry<float> configMoveSpeed;
private ConfigEntry<bool> configSnapTurn;
private ConfigEntry<float> configSnapTurnAngle;
private ConfigEntry<float> configDeadzone;
private ConfigEntry<bool> configNoClip;
private ConfigEntry<float> configGravityScale;
private float moveSpeed = 2f;
private float snapTurnAngle = 45f;
private float deadzone = 0.2f;
private bool smoothLocomotionEnabled = true;
private bool snapTurningEnabled = true;
private bool noClip = false;
private float gravityScale = 1f;
private Vector2 lastRightStick;
private CharacterController _cc;
private int _lastIgnoreFrame = -1;
private float _verticalVelocity = 0f;
private float _maxHeadHeight = 0f;
private void Awake()
{
configEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable smooth locomotion");
configMoveSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MoveSpeed", 2f, "Movement speed (units/sec)");
configSnapTurn = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SnapTurnEnabled", true, "Enable snap turning");
configSnapTurnAngle = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SnapTurnAngle", 45f, "Snap turn angle (degrees)");
configDeadzone = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Deadzone", 0.2f, "Thumbstick deadzone");
configNoClip = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "NoClip", false, "Disable collision when moving");
configGravityScale = ((BaseUnityPlugin)this).Config.Bind<float>("General", "GravityScale", 1f, "Gravity multiplier (1 = normal)");
smoothLocomotionEnabled = configEnabled.Value;
moveSpeed = configMoveSpeed.Value;
snapTurningEnabled = configSnapTurn.Value;
snapTurnAngle = configSnapTurnAngle.Value;
deadzone = configDeadzone.Value;
noClip = configNoClip.Value;
gravityScale = configGravityScale.Value;
configEnabled.SettingChanged += delegate
{
smoothLocomotionEnabled = configEnabled.Value;
};
configMoveSpeed.SettingChanged += delegate
{
moveSpeed = configMoveSpeed.Value;
};
configSnapTurn.SettingChanged += delegate
{
snapTurningEnabled = configSnapTurn.Value;
};
configSnapTurnAngle.SettingChanged += delegate
{
snapTurnAngle = configSnapTurnAngle.Value;
};
configDeadzone.SettingChanged += delegate
{
deadzone = configDeadzone.Value;
};
configGravityScale.SettingChanged += delegate
{
gravityScale = configGravityScale.Value;
};
configNoClip.SettingChanged += delegate
{
noClip = configNoClip.Value;
if (noClip && (Object)(object)_cc != (Object)null)
{
Object.Destroy((Object)(object)_cc);
_cc = null;
}
if (!noClip)
{
_cc = null;
}
};
InputAPI.Initialize();
SceneManager.sceneLoaded += OnSceneLoaded;
((BaseUnityPlugin)this).Logger.LogInfo((object)"[SmoothLocomotion] Initialized.");
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
_cc = null;
_maxHeadHeight = 0f;
_verticalVelocity = 0f;
if (smoothLocomotionEnabled)
{
try
{
PlayerAPI.SetTeleportEnabled(false);
}
catch
{
}
}
}
private void Update()
{
if (!smoothLocomotionEnabled)
{
return;
}
try
{
if (!((Object)(object)PlayerAPI.VRPlayerInstance == (Object)null))
{
EnsureCC();
ProcessSmoothMovement();
ProcessSnapTurning();
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("[SmoothLocomotion] Update error: " + ex.Message));
}
}
private void EnsureCC()
{
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
if (!noClip && !((Object)(object)_cc != (Object)null))
{
Transform trackingOrigin = PlayerAPI.TrackingOrigin;
if (!((Object)(object)trackingOrigin == (Object)null))
{
_cc = ((Component)trackingOrigin).gameObject.AddComponent<CharacterController>();
_cc.height = 1.5f;
_cc.center = new Vector3(0f, 0.75f, 0f);
_cc.radius = 0.2f;
_cc.skinWidth = 0.01f;
_cc.minMoveDistance = 0.001f;
}
}
}
private void IgnoreHandColliders()
{
if ((Object)(object)_cc == (Object)null || Time.frameCount == _lastIgnoreFrame)
{
return;
}
_lastIgnoreFrame = Time.frameCount;
foreach (VRHand allHand in PlayerAPI.GetAllHands())
{
if ((Object)(object)allHand == (Object)null)
{
continue;
}
Collider[] componentsInChildren = ((Component)allHand).GetComponentsInChildren<Collider>(true);
foreach (Collider val in componentsInChildren)
{
if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)_cc)
{
Physics.IgnoreCollision((Collider)(object)_cc, val, true);
}
}
}
}
private void SyncCCUnderCamera()
{
//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_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_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_006e: 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_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: 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)
if (!((Object)(object)_cc == (Object)null))
{
Transform trackingOrigin = PlayerAPI.TrackingOrigin;
Transform hMDTransform = PlayerAPI.HMDTransform;
if (!((Object)(object)trackingOrigin == (Object)null) && !((Object)(object)hMDTransform == (Object)null))
{
Vector3 val = trackingOrigin.InverseTransformPoint(hMDTransform.position);
Vector3 val2 = trackingOrigin.InverseTransformDirection(hMDTransform.forward);
_maxHeadHeight = Mathf.Max(new float[3] { _maxHeadHeight, val.y, 0.3f });
_cc.center = new Vector3(val.x, _maxHeadHeight * 0.5f, val.z) - val2 * 0.1f;
_cc.height = _maxHeadHeight;
}
}
}
private void ProcessSmoothMovement()
{
//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
//IL_01f6: 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_01fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0203: Unknown result type (might be due to invalid IL or missing references)
//IL_0208: Unknown result type (might be due to invalid IL or missing references)
//IL_020d: Unknown result type (might be due to invalid IL or missing references)
//IL_0211: Unknown result type (might be due to invalid IL or missing references)
//IL_0216: Unknown result type (might be due to invalid IL or missing references)
//IL_0218: Unknown result type (might be due to invalid IL or missing references)
//IL_021a: Unknown result type (might be due to invalid IL or missing references)
//IL_0221: Unknown result type (might be due to invalid IL or missing references)
//IL_0226: Unknown result type (might be due to invalid IL or missing references)
//IL_0228: 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_0234: Unknown result type (might be due to invalid IL or missing references)
//IL_0239: 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_025b: Unknown result type (might be due to invalid IL or missing references)
//IL_0260: 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_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_00c2: 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_01af: Unknown result type (might be due to invalid IL or missing references)
//IL_01b4: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: 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_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)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: 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_0128: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: 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_015f: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_0182: Unknown result type (might be due to invalid IL or missing references)
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
//IL_018c: Unknown result type (might be due to invalid IL or missing references)
IgnoreHandColliders();
SyncCCUnderCamera();
Transform trackingOrigin = PlayerAPI.TrackingOrigin;
Transform hMDTransform = PlayerAPI.HMDTransform;
if ((Object)(object)trackingOrigin == (Object)null || (Object)(object)hMDTransform == (Object)null)
{
return;
}
Vector3 val;
if ((Object)(object)_cc != (Object)null)
{
float num = Physics.gravity.y * gravityScale;
float deltaTime = Time.deltaTime;
if (_cc.isGrounded && _verticalVelocity < 0f)
{
_verticalVelocity = -2f * gravityScale;
}
else if (!_cc.isGrounded)
{
_verticalVelocity += num * deltaTime;
}
Vector2 leftThumbstickAxisNormalized = InputAPI.GetLeftThumbstickAxisNormalized();
if (((Vector2)(ref leftThumbstickAxisNormalized)).magnitude > deadzone)
{
val = Vector3.ProjectOnPlane(hMDTransform.forward, Vector3.up);
Vector3 normalized = ((Vector3)(ref val)).normalized;
val = Vector3.ProjectOnPlane(hMDTransform.right, Vector3.up);
Vector3 normalized2 = ((Vector3)(ref val)).normalized;
val = normalized * leftThumbstickAxisNormalized.y + normalized2 * leftThumbstickAxisNormalized.x;
Vector3 normalized3 = ((Vector3)(ref val)).normalized;
float num2 = moveSpeed * Mathf.Clamp01(((Vector2)(ref leftThumbstickAxisNormalized)).magnitude);
_cc.Move(normalized3 * num2 * deltaTime + new Vector3(0f, _verticalVelocity * deltaTime, 0f));
}
else
{
_cc.Move(new Vector3(0f, _verticalVelocity * deltaTime, 0f));
}
}
else
{
Vector2 leftThumbstickAxisNormalized2 = InputAPI.GetLeftThumbstickAxisNormalized();
if (((Vector2)(ref leftThumbstickAxisNormalized2)).magnitude > deadzone)
{
val = Vector3.ProjectOnPlane(hMDTransform.forward, Vector3.up);
Vector3 normalized4 = ((Vector3)(ref val)).normalized;
val = Vector3.ProjectOnPlane(hMDTransform.right, Vector3.up);
Vector3 normalized5 = ((Vector3)(ref val)).normalized;
val = normalized4 * leftThumbstickAxisNormalized2.y + normalized5 * leftThumbstickAxisNormalized2.x;
Vector3 normalized6 = ((Vector3)(ref val)).normalized;
float num3 = moveSpeed * Mathf.Clamp01(((Vector2)(ref leftThumbstickAxisNormalized2)).magnitude);
trackingOrigin.position += normalized6 * num3 * Time.deltaTime;
}
}
}
private void ProcessSnapTurning()
{
//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_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: 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_00f3: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
if (!snapTurningEnabled)
{
return;
}
Vector2 rightThumbstickAxisNormalized = InputAPI.GetRightThumbstickAxisNormalized();
if (((Vector2)(ref rightThumbstickAxisNormalized)).magnitude < deadzone)
{
lastRightStick = Vector2.zero;
return;
}
Transform trackingOrigin = PlayerAPI.TrackingOrigin;
Transform hMDTransform = PlayerAPI.HMDTransform;
if (!((Object)(object)trackingOrigin == (Object)null) && !((Object)(object)hMDTransform == (Object)null))
{
if (rightThumbstickAxisNormalized.x < -0.5f && lastRightStick.x >= -0.5f)
{
trackingOrigin.RotateAround(hMDTransform.position, Vector3.up, 0f - snapTurnAngle);
}
else if (rightThumbstickAxisNormalized.x > 0.5f && lastRightStick.x <= 0.5f)
{
trackingOrigin.RotateAround(hMDTransform.position, Vector3.up, snapTurnAngle);
}
lastRightStick = rightThumbstickAxisNormalized;
}
}
}