From d1abb3b4ef0ca61a582135b69abf89398217278f Mon Sep 17 00:00:00 2001 From: NotAKidoS <37721153+NotAKidOnSteam@users.noreply.github.com> Date: Mon, 10 Apr 2023 03:01:26 -0500 Subject: [PATCH] add faked root angle fix from DesktopVRIK --- IKFixes/HarmonyPatches.cs | 32 +++++++++++++++++++++++++++----- IKFixes/Main.cs | 10 ++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/IKFixes/HarmonyPatches.cs b/IKFixes/HarmonyPatches.cs index 592b86e..33b697a 100644 --- a/IKFixes/HarmonyPatches.cs +++ b/IKFixes/HarmonyPatches.cs @@ -11,6 +11,8 @@ namespace NAK.Melons.IKFixes.HarmonyPatches; internal static class BodySystemPatches { + static float _ikSimulatedRootAngle = 0f; + [HarmonyPostfix] [HarmonyPatch(typeof(BodySystem), "SetupOffsets")] private static void Postfix_BodySystem_SetupOffsets(List trackingPoints) @@ -51,11 +53,6 @@ internal static class BodySystemPatches { IKSolverVR solver = IKSystem.vrik.solver; - // Allow avatar to rotate seperatly from Player (Desktop&VR) - // FBT needs avatar root to follow head - // VR default is 25 degrees - solver.spine.maxRootAngle = BodySystem.isCalibratedAsFullBody ? 0f : 25f; - if (BodySystem.TrackingEnabled) { IKSystem.vrik.enabled = true; @@ -89,6 +86,31 @@ internal static class BodySystemPatches SetLegWeight(solver.rightLeg, 0f); SetPelvisWeight(solver.spine, 0f); } + + if (IKFixesMod.EntryUseFakeRootAngle.Value) + { + // Emulate maxRootAngle because CVR doesn't have the player controller set up ideally for VRIK. + // This is a small small fix, but makes it so the feet dont point in the direction of the head + // when turning. It also means turning with joystick & turning IRL make feet behave the same and follow behind. + float weightedAngleLimit = IKFixesMod.EntryFakeRootAngleLimit.Value * solver.locomotion.weight; + float pivotAngle = MovementSystem.Instance.rotationPivot.eulerAngles.y; + float deltaAngleRoot = Mathf.DeltaAngle(pivotAngle, _ikSimulatedRootAngle); + float absDeltaAngleRoot = Mathf.Abs(deltaAngleRoot); + if (absDeltaAngleRoot > weightedAngleLimit) + { + deltaAngleRoot = Mathf.Sign(deltaAngleRoot) * weightedAngleLimit; + _ikSimulatedRootAngle = Mathf.MoveTowardsAngle(_ikSimulatedRootAngle, pivotAngle, absDeltaAngleRoot - weightedAngleLimit); + } + solver.spine.maxRootAngle = 0f; + solver.spine.rootHeadingOffset = deltaAngleRoot; + } + else + { + // Allow avatar to rotate seperatly from Player (Desktop&VR) + // FBT needs avatar root to follow head + // VR default is 25 degrees + solver.spine.maxRootAngle = BodySystem.isCalibratedAsFullBody ? 0f : 25f; + } } int num = 0; diff --git a/IKFixes/Main.cs b/IKFixes/Main.cs index 1e0da50..1d1f076 100644 --- a/IKFixes/Main.cs +++ b/IKFixes/Main.cs @@ -4,6 +4,16 @@ namespace NAK.Melons.IKFixes; public class IKFixesMod : MelonMod { + internal static MelonLogger.Instance Logger; + public const string SettingsCategory = "IKFixes"; + public static readonly MelonPreferences_Category CategoryIKFixes = MelonPreferences.CreateCategory(SettingsCategory); + + public static readonly MelonPreferences_Entry EntryUseFakeRootAngle = + CategoryIKFixes.CreateEntry("Use Fake Root Angle", false, description: "Emulates maxRootAngle. This fixes feet pointing in direction of head when looking around."); + + public static readonly MelonPreferences_Entry EntryFakeRootAngleLimit = + CategoryIKFixes.CreateEntry("Fake Root Angle Limit", 25f, description: "Specifies the maximum angle the lower body can have relative to the head when rotating."); + public override void OnInitializeMelon() { ApplyPatches(typeof(HarmonyPatches.VRIKPatches));