weight bump

This commit is contained in:
NotAKidoS 2023-03-30 23:34:18 -05:00
parent 7454efdb2f
commit 09cb3838a6
6 changed files with 134 additions and 58 deletions

View file

@ -123,19 +123,20 @@ internal class DesktopVRIKSystem : MonoBehaviour
// DesktopVRIK Settings // DesktopVRIK Settings
public bool Setting_Enabled = true; public bool Setting_Enabled = true;
public bool Setting_PlantFeet = true; public bool Setting_PlantFeet;
public bool Setting_ResetFootsteps; public bool Setting_ResetFootsteps;
public float Setting_BodyLeanWeight; public float Setting_BodyLeanWeight;
public float Setting_BodyHeadingLimit; public float Setting_BodyHeadingLimit;
public float Setting_PelvisHeadingWeight; public float Setting_PelvisHeadingWeight;
public float Setting_ChestHeadingWeight; public float Setting_ChestHeadingWeight;
public float Setting_IKLerpSpeed;
// Calibration Settings // Calibration Settings
public bool Setting_UseVRIKToes = true; public bool Setting_UseVRIKToes;
public bool Setting_FindUnmappedToes = true; public bool Setting_FindUnmappedToes;
// Integration Settings // Integration Settings
public bool Setting_IntegrationAMT = false; public bool Setting_IntegrationAMT;
// Avatar Components // Avatar Components
public CVRAvatar avatarDescriptor = null; public CVRAvatar avatarDescriptor = null;
@ -161,20 +162,21 @@ internal class DesktopVRIKSystem : MonoBehaviour
// VRIK Calibration Info // VRIK Calibration Info
Vector3 _vrikKneeNormalLeft; Vector3 _vrikKneeNormalLeft;
Vector3 _vrikKneeNormalRight; Vector3 _vrikKneeNormalRight;
Vector3 _vrikInitialFootStepLeft; Vector3 _vrikInitialFootPosLeft;
Vector3 _vrikInitialFootStepRight; Vector3 _vrikInitialFootPosRight;
Quaternion _vrikInitialFootRotLeft;
Quaternion _vrikInitialFootRotRight;
float _vrikInitialFootDistance; float _vrikInitialFootDistance;
float _vrikInitialStepThreshold; float _vrikInitialStepThreshold;
float _vrikInitialStepHeight; float _vrikInitialStepHeight;
bool _vrikFixTransformsRequired; bool _vrikFixTransformsRequired;
// Player Info // Player Info
Transform _cameraTransform = null; Transform _cameraTransform;
bool _ikEmotePlaying = false; bool _ikEmotePlaying;
float _ikWeightLerp = 1f;
float _ikSimulatedRootAngle = 0f; float _ikSimulatedRootAngle = 0f;
float _locomotionWeight = 1f; float _locomotionWeight = 1f;
float _locomotionWeightLerp = 1f;
float _locomotionLerpSpeed = 10f;
// Last Movement Parent Info // Last Movement Parent Info
Vector3 _movementPosition; Vector3 _movementPosition;
@ -202,32 +204,60 @@ internal class DesktopVRIKSystem : MonoBehaviour
if (avatarVRIK == null) return; if (avatarVRIK == null) return;
HandleLocomotionTracking(); HandleLocomotionTracking();
LerpLocomotionWeight(); UpdateLocomotionWeight();
ApplyBodySystemWeights(); ApplyBodySystemWeights();
} }
void HandleLocomotionTracking() void HandleLocomotionTracking()
{ {
bool isMoving = movementSystem.movementVector.magnitude > 0f; bool shouldTrackLocomotion = ShouldTrackLocomotion();
bool isGrounded = movementSystem._isGrounded;
bool isCrouching = movementSystem.crouching;
bool isProne = movementSystem.prone;
bool isFlying = movementSystem.flying;
bool shouldTrackLocomotion = !(isMoving || isCrouching || isProne || isFlying || !isGrounded);
if (shouldTrackLocomotion != BodySystem.TrackingLocomotionEnabled) if (shouldTrackLocomotion != BodySystem.TrackingLocomotionEnabled)
{ {
BodySystem.TrackingLocomotionEnabled = shouldTrackLocomotion; BodySystem.TrackingLocomotionEnabled = shouldTrackLocomotion;
avatarIKSolver.Reset(); avatarIKSolver.Reset();
ResetDesktopVRIK(); ResetDesktopVRIK();
if (shouldTrackLocomotion) IKResetFootsteps();
} }
} }
void LerpLocomotionWeight() bool ShouldTrackLocomotion()
{ {
_locomotionWeight = BodySystem.TrackingEnabled && BodySystem.TrackingLocomotionEnabled ? 1.0f : 0.0f; bool isMoving = movementSystem.movementVector.magnitude > 0f;
_locomotionWeightLerp = Mathf.Lerp(_locomotionWeightLerp, _locomotionWeight, Time.deltaTime * _locomotionLerpSpeed); bool isGrounded = movementSystem._isGrounded;
bool isCrouching = movementSystem.crouching;
bool isProne = movementSystem.prone;
bool isFlying = movementSystem.flying;
bool isStanding = IsStanding();
return !(isMoving || isCrouching || isProne || isFlying || !isGrounded || !isStanding);
}
bool IsStanding()
{
// Let AMT handle it if available
if (Setting_IntegrationAMT) return true;
// Get Upright value
Vector3 delta = avatarIKSolver.spine.headPosition - avatarTransform.position;
Vector3 deltaRotated = Quaternion.Euler(0, avatarTransform.rotation.eulerAngles.y, 0) * delta;
float upright = Mathf.InverseLerp(0f, avatarIKSolver.spine.headHeight, deltaRotated.y);
return upright > 0.85f;
}
void UpdateLocomotionWeight()
{
float targetWeight = BodySystem.TrackingEnabled && BodySystem.TrackingLocomotionEnabled ? 1.0f : 0.0f;
if (Setting_IKLerpSpeed > 0)
{
_ikWeightLerp = Mathf.Lerp(_ikWeightLerp, targetWeight, Time.deltaTime * Setting_IKLerpSpeed);
_locomotionWeight = Mathf.Lerp(_locomotionWeight, targetWeight, Time.deltaTime * Setting_IKLerpSpeed * 2f);
}
else
{
_ikWeightLerp = targetWeight;
_locomotionWeight = targetWeight;
}
} }
void ApplyBodySystemWeights() void ApplyBodySystemWeights()
@ -354,17 +384,11 @@ internal class DesktopVRIKSystem : MonoBehaviour
avatarIKSolver.plantFeet = Setting_PlantFeet; avatarIKSolver.plantFeet = Setting_PlantFeet;
// Apply custom VRIK solving effects // Apply custom VRIK solving effects
if (_locomotionWeightLerp > 0) if (_ikWeightLerp > 0)
{ {
IKBodyLeaningOffset(); IKBodyLeaningOffset();
IKBodyHeadingOffset(); IKBodyHeadingOffset();
} }
// Reset footsteps while transitioning
if (_locomotionWeightLerp < 0.99f)
{
IKResetFootsteps();
}
} }
void IKBodyLeaningOffset() void IKBodyLeaningOffset()
@ -372,7 +396,7 @@ internal class DesktopVRIKSystem : MonoBehaviour
// Emulate old VRChat hip movement // Emulate old VRChat hip movement
if (Setting_BodyLeanWeight <= 0) return; if (Setting_BodyLeanWeight <= 0) return;
float weightedAngle = Setting_BodyLeanWeight * _locomotionWeightLerp; float weightedAngle = Setting_BodyLeanWeight * _ikWeightLerp;
float angle = _cameraTransform.localEulerAngles.x; float angle = _cameraTransform.localEulerAngles.x;
angle = angle > 180 ? angle - 360 : angle; angle = angle > 180 ? angle - 360 : angle;
Quaternion rotation = Quaternion.AngleAxis(angle * weightedAngle, avatarTransform.right); Quaternion rotation = Quaternion.AngleAxis(angle * weightedAngle, avatarTransform.right);
@ -384,7 +408,7 @@ internal class DesktopVRIKSystem : MonoBehaviour
// Make root heading follow within a set limit // Make root heading follow within a set limit
if (Setting_BodyHeadingLimit <= 0) return; if (Setting_BodyHeadingLimit <= 0) return;
float weightedAngleLimit = Setting_BodyHeadingLimit * _locomotionWeightLerp; float weightedAngleLimit = Setting_BodyHeadingLimit * _ikWeightLerp;
float deltaAngleRoot = Mathf.DeltaAngle(transform.eulerAngles.y, _ikSimulatedRootAngle); float deltaAngleRoot = Mathf.DeltaAngle(transform.eulerAngles.y, _ikSimulatedRootAngle);
float absDeltaAngleRoot = Mathf.Abs(deltaAngleRoot); float absDeltaAngleRoot = Mathf.Abs(deltaAngleRoot);
@ -410,17 +434,17 @@ internal class DesktopVRIKSystem : MonoBehaviour
void IKResetFootsteps() void IKResetFootsteps()
{ {
// Attempt to skip footstep transition // Reset footsteps immediatly to initial
if (!Setting_ResetFootsteps) return; if (!Setting_ResetFootsteps) return;
IKSolverVR.Footstep footstepLeft = avatarIKSolver.locomotion.footsteps[0]; VRIKUtils.SetFootsteps
IKSolverVR.Footstep footstepRight = avatarIKSolver.locomotion.footsteps[1]; (
Vector3 globalLeft = movementSystem.transform.TransformPoint(_vrikInitialFootStepLeft); avatarVRIK,
Vector3 globalRight = movementSystem.transform.TransformPoint(_vrikInitialFootStepRight); _vrikInitialFootPosLeft,
footstepLeft.Reset(avatarTransform.rotation, globalLeft, footstepLeft.stepToRot); _vrikInitialFootPosRight,
footstepRight.Reset(avatarTransform.rotation, globalRight, footstepRight.stepToRot); _vrikInitialFootRotLeft,
//footstepRight.StepTo(globalRight, avatarTransform.rotation, 100f); _vrikInitialFootRotRight
//footstepLeft.StepTo(globalLeft, avatarTransform.rotation, 100f); );
} }
void ResetDesktopVRIK() void ResetDesktopVRIK()
@ -542,7 +566,7 @@ internal class DesktopVRIKSystem : MonoBehaviour
VRIKUtils.CalculateInitialIKScaling(avatarVRIK, out _vrikInitialFootDistance, out _vrikInitialStepThreshold, out _vrikInitialStepHeight); VRIKUtils.CalculateInitialIKScaling(avatarVRIK, out _vrikInitialFootDistance, out _vrikInitialStepThreshold, out _vrikInitialStepHeight);
// Calculate initial Footstep positions // Calculate initial Footstep positions
VRIKUtils.CalculateInitialFootsteps(avatarVRIK, out _vrikInitialFootStepLeft, out _vrikInitialFootStepRight); VRIKUtils.CalculateInitialFootsteps(avatarVRIK, out _vrikInitialFootPosLeft, out _vrikInitialFootPosRight, out _vrikInitialFootRotLeft, out _vrikInitialFootRotRight);
// Setup HeadIKTarget // Setup HeadIKTarget
VRIKUtils.SetupHeadIKTarget(avatarVRIK); VRIKUtils.SetupHeadIKTarget(avatarVRIK);

View file

@ -17,21 +17,20 @@ public static class BTKUIAddon
AddMelonToggle(ref miscCategory, DesktopVRIKMod.EntryEnabled); AddMelonToggle(ref miscCategory, DesktopVRIKMod.EntryEnabled);
//Add my own page to not clog up Misc Menu //Add my own page to not clog up Misc Menu
Page desktopVRIKPage = miscCategory.AddPage("DesktopVRIK Settings", "", "Configure the settings for DesktopVRIK.", "DesktopVRIK"); Page desktopVRIKPage = miscCategory.AddPage("DesktopVRIK Settings", "", "Configure the settings for DesktopVRIK.", "DesktopVRIK");
desktopVRIKPage.MenuTitle = "DesktopVRIK Settings"; desktopVRIKPage.MenuTitle = "DesktopVRIK Settings";
Category desktopVRIKCategory = desktopVRIKPage.AddCategory(DesktopVRIKMod.SettingsCategory); Category desktopVRIKCategory = desktopVRIKPage.AddCategory(DesktopVRIKMod.SettingsCategory);
// General Settings // General Settings
//AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.EntryEnabled);
AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.EntryPlantFeet); AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.EntryPlantFeet);
AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.EntryResetFootstepsOnIdle);
// Calibration Settings // Calibration Settings
AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.EntryUseVRIKToes); AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.EntryUseVRIKToes);
AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.EntryFindUnmappedToes); AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.EntryFindUnmappedToes);
// Fine-tuning Settings
AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.EntryResetFootstepsOnIdle);
// Body Leaning Weight // Body Leaning Weight
AddMelonSlider(ref desktopVRIKPage, DesktopVRIKMod.EntryBodyLeanWeight, 0, 1f, 1); AddMelonSlider(ref desktopVRIKPage, DesktopVRIKMod.EntryBodyLeanWeight, 0, 1f, 1);
@ -39,7 +38,11 @@ public static class BTKUIAddon
AddMelonSlider(ref desktopVRIKPage, DesktopVRIKMod.EntryBodyHeadingLimit, 0, 90f, 0); AddMelonSlider(ref desktopVRIKPage, DesktopVRIKMod.EntryBodyHeadingLimit, 0, 90f, 0);
AddMelonSlider(ref desktopVRIKPage, DesktopVRIKMod.EntryPelvisHeadingWeight, 0, 1f, 1); AddMelonSlider(ref desktopVRIKPage, DesktopVRIKMod.EntryPelvisHeadingWeight, 0, 1f, 1);
AddMelonSlider(ref desktopVRIKPage, DesktopVRIKMod.EntryChestHeadingWeight, 0, 1f, 1); AddMelonSlider(ref desktopVRIKPage, DesktopVRIKMod.EntryChestHeadingWeight, 0, 1f, 1);
// Lerp Speed
AddMelonSlider(ref desktopVRIKPage, DesktopVRIKMod.EntryIKLerpSpeed, 0, 20f, 0);
} }
private static void AddMelonToggle(ref Category category, MelonLoader.MelonPreferences_Entry<bool> entry) private static void AddMelonToggle(ref Category category, MelonLoader.MelonPreferences_Entry<bool> entry)
{ {
category.AddToggle(entry.DisplayName, entry.Description, entry.Value).OnValueUpdated += b => entry.Value = b; category.AddToggle(entry.DisplayName, entry.Description, entry.Value).OnValueUpdated += b => entry.Value = b;

View file

@ -15,12 +15,12 @@ public class DesktopVRIKMod : MelonMod
public static readonly MelonPreferences_Entry<bool> EntryPlantFeet = public static readonly MelonPreferences_Entry<bool> EntryPlantFeet =
CategoryDesktopVRIK.CreateEntry("Enforce Plant Feet", true, description: "Forces VRIK Plant Feet enabled to prevent hovering when stopping movement."); CategoryDesktopVRIK.CreateEntry("Enforce Plant Feet", true, description: "Forces VRIK Plant Feet enabled to prevent hovering when stopping movement.");
public static readonly MelonPreferences_Entry<bool> EntryResetFootstepsOnIdle =
CategoryDesktopVRIK.CreateEntry("Reset Footsteps on Idle", true, description: "Determins if the Locomotion Footsteps will be reset to their calibration position when entering idle.");
public static readonly MelonPreferences_Entry<bool> EntryUseVRIKToes = public static readonly MelonPreferences_Entry<bool> EntryUseVRIKToes =
CategoryDesktopVRIK.CreateEntry("Use VRIK Toes", false, description: "Determines if VRIK uses humanoid toes for IK solving, which can cause feet to idle behind the avatar."); CategoryDesktopVRIK.CreateEntry("Use VRIK Toes", false, description: "Determines if VRIK uses humanoid toes for IK solving, which can cause feet to idle behind the avatar.");
public static readonly MelonPreferences_Entry<bool> EntryResetFootstepsOnIdle =
CategoryDesktopVRIK.CreateEntry("Reset Footsteps on Idle", false, description: "Forces Locomotion Footsteps to reset to their initial position on return to idle. This is a bit aggressive.");
public static readonly MelonPreferences_Entry<bool> EntryFindUnmappedToes = public static readonly MelonPreferences_Entry<bool> EntryFindUnmappedToes =
CategoryDesktopVRIK.CreateEntry("Find Unmapped Toes", false, description: "Determines if DesktopVRIK should look for unmapped toe bones if the humanoid rig does not have any."); CategoryDesktopVRIK.CreateEntry("Find Unmapped Toes", false, description: "Determines if DesktopVRIK should look for unmapped toe bones if the humanoid rig does not have any.");
@ -36,6 +36,14 @@ public class DesktopVRIKMod : MelonMod
public static readonly MelonPreferences_Entry<float> EntryChestHeadingWeight = public static readonly MelonPreferences_Entry<float> EntryChestHeadingWeight =
CategoryDesktopVRIK.CreateEntry("Chest Heading Weight", 0.75f, description: "Determines how much the chest will face the Body Heading Limit. Set to 0 to align with head."); CategoryDesktopVRIK.CreateEntry("Chest Heading Weight", 0.75f, description: "Determines how much the chest will face the Body Heading Limit. Set to 0 to align with head.");
public static readonly MelonPreferences_Entry<float> EntryIKLerpSpeed =
CategoryDesktopVRIK.CreateEntry("IK Lerp Speed", 10f, description: "Determines fast the IK & Locomotion weights blend after entering idle. Set to 0 to disable.");
public static readonly MelonPreferences_Entry<bool> EntryIntegrationAMT =
CategoryDesktopVRIK.CreateEntry("AMT Integration", true, description: "Relies on AvatarMotionTweaker to handle VRIK Locomotion weights if available.");
public static bool integration_AMT = false;
public override void OnInitializeMelon() public override void OnInitializeMelon()
{ {
Logger = LoggerInstance; Logger = LoggerInstance;
@ -50,6 +58,16 @@ public class DesktopVRIKMod : MelonMod
Logger.Msg("Initializing BTKUILib support."); Logger.Msg("Initializing BTKUILib support.");
BTKUIAddon.Init(); BTKUIAddon.Init();
} }
//AvatarMotionTweaker Handling
if (MelonMod.RegisteredMelons.Any(it => it.Info.Name == "AvatarMotionTweaker"))
{
Logger.Msg("AvatarMotionTweaker was found. Relying on it to handle VRIK locomotion.");
integration_AMT = true;
}
else
{
Logger.Msg("AvatarMotionTweaker was not found. Using built-in VRIK locomotion handling.");
}
} }
internal static void UpdateAllSettings() internal static void UpdateAllSettings()
@ -64,10 +82,18 @@ public class DesktopVRIKMod : MelonMod
DesktopVRIKSystem.Instance.Setting_BodyHeadingLimit = Mathf.Clamp(EntryBodyHeadingLimit.Value, 0f, 90f); DesktopVRIKSystem.Instance.Setting_BodyHeadingLimit = Mathf.Clamp(EntryBodyHeadingLimit.Value, 0f, 90f);
DesktopVRIKSystem.Instance.Setting_PelvisHeadingWeight = (1f - Mathf.Clamp01(EntryPelvisHeadingWeight.Value)); DesktopVRIKSystem.Instance.Setting_PelvisHeadingWeight = (1f - Mathf.Clamp01(EntryPelvisHeadingWeight.Value));
DesktopVRIKSystem.Instance.Setting_ChestHeadingWeight = (1f - Mathf.Clamp01(EntryChestHeadingWeight.Value)); DesktopVRIKSystem.Instance.Setting_ChestHeadingWeight = (1f - Mathf.Clamp01(EntryChestHeadingWeight.Value));
DesktopVRIKSystem.Instance.Setting_ChestHeadingWeight = (1f - Mathf.Clamp01(EntryChestHeadingWeight.Value));
DesktopVRIKSystem.Instance.Setting_IKLerpSpeed = Mathf.Clamp(EntryIKLerpSpeed.Value, 0f, 20f);
// Calibration Settings // Calibration Settings
DesktopVRIKSystem.Instance.Setting_UseVRIKToes = EntryUseVRIKToes.Value; DesktopVRIKSystem.Instance.Setting_UseVRIKToes = EntryUseVRIKToes.Value;
DesktopVRIKSystem.Instance.Setting_FindUnmappedToes = EntryFindUnmappedToes.Value; DesktopVRIKSystem.Instance.Setting_FindUnmappedToes = EntryFindUnmappedToes.Value;
// Fine-tuning Settings
DesktopVRIKSystem.Instance.Setting_ResetFootsteps = EntryResetFootstepsOnIdle.Value;
// Integration Settings
DesktopVRIKSystem.Instance.Setting_IntegrationAMT = EntryIntegrationAMT.Value && integration_AMT;
} }
void OnUpdateSettings(object arg1, object arg2) => UpdateAllSettings(); void OnUpdateSettings(object arg1, object arg2) => UpdateAllSettings();

View file

@ -26,6 +26,6 @@ using System.Reflection;
namespace NAK.Melons.DesktopVRIK.Properties; namespace NAK.Melons.DesktopVRIK.Properties;
internal static class AssemblyInfoParams internal static class AssemblyInfoParams
{ {
public const string Version = "4.1.2"; public const string Version = "4.1.3";
public const string Author = "NotAKidoS"; public const string Author = "NotAKidoS";
} }

View file

@ -154,10 +154,33 @@ public static class VRIKUtils
initialStepHeight = Vector3.Distance(vrik.references.leftFoot.position, vrik.references.leftCalf.position) * 0.2f; initialStepHeight = Vector3.Distance(vrik.references.leftFoot.position, vrik.references.leftCalf.position) * 0.2f;
} }
public static void CalculateInitialFootsteps(VRIK vrik, out Vector3 initialFootstepLeft, out Vector3 initialFootstepRight) public static void CalculateInitialFootsteps(VRIK vrik, out Vector3 initialFootPosLeft, out Vector3 initialFootPosRight, out Quaternion initialFootRotLeft, out Quaternion initialFootRotRight)
{ {
initialFootstepLeft = vrik.references.root.InverseTransformPoint(vrik.references.leftFoot.position); Transform root = vrik.references.root;
initialFootstepRight = vrik.references.root.InverseTransformPoint(vrik.references.rightFoot.position); Transform leftFoot = vrik.references.leftFoot;
Transform rightFoot = vrik.references.rightFoot;
// Calculate the world rotation of the root bone at the current frame
Quaternion rootWorldRot = root.rotation;
// Calculate the world rotation of the left and right feet relative to the root bone
initialFootPosLeft = root.InverseTransformPoint(leftFoot.position);
initialFootPosRight = root.InverseTransformPoint(rightFoot.position);
initialFootRotLeft = Quaternion.Inverse(rootWorldRot) * leftFoot.rotation;
initialFootRotRight = Quaternion.Inverse(rootWorldRot) * rightFoot.rotation;
}
public static void SetFootsteps(VRIK vrik, Vector3 footPosLeft, Vector3 footPosRight, Quaternion footRotLeft, Quaternion footRotRight)
{
var locomotionSolver = vrik.solver.locomotion;
var footsteps = locomotionSolver.footsteps;
var footstepLeft = footsteps[0];
var footstepRight = footsteps[1];
var rootWorldRot = vrik.references.root.rotation;
footstepLeft.Reset(rootWorldRot, vrik.transform.TransformPoint(footPosLeft), rootWorldRot * footRotLeft);
footstepRight.Reset(rootWorldRot, vrik.transform.TransformPoint(footPosRight), rootWorldRot * footRotRight);
} }
public static void SetupHeadIKTarget(VRIK vrik) public static void SetupHeadIKTarget(VRIK vrik)

View file

@ -1,7 +1,7 @@
{ {
"_id": 117, "_id": 117,
"name": "DesktopVRIK", "name": "DesktopVRIK",
"modversion": "4.1.2", "modversion": "4.1.3",
"gameversion": "2022r170", "gameversion": "2022r170",
"loaderversion": "0.5.7", "loaderversion": "0.5.7",
"modtype": "Mod", "modtype": "Mod",
@ -17,8 +17,8 @@
"requirements": [ "requirements": [
"BTKUILib" "BTKUILib"
], ],
"downloadlink": "https://github.com/NotAKidOnSteam/DesktopVRIK/releases/download/v4.1.2/DesktopVRIK.dll", "downloadlink": "https://github.com/NotAKidOnSteam/DesktopVRIK/releases/download/v4.1.3/DesktopVRIK.dll",
"sourcelink": "https://github.com/NotAKidOnSteam/DesktopVRIK/", "sourcelink": "https://github.com/NotAKidOnSteam/DesktopVRIK/",
"changelog": "- No longer requires AvatarMotionTweaker.\n- No longer piggybacks on IKSystem/PlayerSetup.\n\n DesktopVRIK will now handle VRIK Locomotion weight instead of relying on CVR & AMT to handle it. This means LeapMotionExtension, PickupArmMovement, and CVRLimbGrabber will now work while in crouch/prone.", "changelog": "- No longer requires AvatarMotionTweaker.\n- No longer piggybacks on IKSystem/PlayerSetup.\n- Tweaks to Locomotion & IKSolver weight blending.\n\n DesktopVRIK will now handle VRIK Locomotion weight instead of relying on CVR & AMT to handle it. This means LeapMotionExtension, PickupArmMovement, and CVRLimbGrabber will now work while in crouch/prone.",
"embedcolor": "9b59b6" "embedcolor": "9b59b6"
} }