From 971466da249ce1e66801a5be9900a43880836010 Mon Sep 17 00:00:00 2001 From: SDraw Date: Thu, 16 Mar 2023 09:20:45 +0300 Subject: [PATCH 01/63] Features merge from experimental: Settings rework Finger tracking networks sync only if hands are tracked Working fix for animator override controller Mass center offset calculations Steps scaling --- ml_amt/Main.cs | 67 +++++++++--- ml_amt/MotionTweaker.cs | 138 +++++++++++++++++------- ml_amt/Settings.cs | 207 +++++++++++++++--------------------- ml_amt/Utils.cs | 9 +- ml_amt/resources/menu.js | 11 +- ml_dht/HeadTracked.cs | 18 ++-- ml_dht/Settings.cs | 99 ++++++----------- ml_lme/LeapInput.cs | 28 +++-- ml_lme/LeapTracked.cs | 88 ++++++++------- ml_lme/Settings.cs | 223 +++++++++++++++++---------------------- ml_lme/Utils.cs | 6 +- ml_pam/ArmMover.cs | 2 + ml_pam/Settings.cs | 29 ++--- 13 files changed, 474 insertions(+), 451 deletions(-) diff --git a/ml_amt/Main.cs b/ml_amt/Main.cs index c6aeae2..05ecf6b 100644 --- a/ml_amt/Main.cs +++ b/ml_amt/Main.cs @@ -47,6 +47,11 @@ namespace ml_amt null, new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnCalibrate_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) ); + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod("SetPlaySpaceScale", BindingFlags.NonPublic | BindingFlags.Instance), + null, + new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnPlayspaceScale_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); // FBT detour HarmonyInstance.Patch( @@ -70,16 +75,16 @@ namespace ml_amt null ); - // AAS overriding "fix" + // AAS overriding fix HarmonyInstance.Patch( - typeof(CVRAnimatorManager).GetMethod(nameof(CVRAnimatorManager.SetOverrideAnimation), BindingFlags.Instance), - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnAnimationOverride_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), - null + typeof(CVRAnimatorManager).GetMethod(nameof(CVRAnimatorManager.SetOverrideAnimation)), + new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnOverride_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnOverride_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) ); HarmonyInstance.Patch( typeof(CVRAnimatorManager).GetMethod(nameof(CVRAnimatorManager.RestoreOverrideAnimation)), - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnAnimationOverrideRestore_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), - null + new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnOverride_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnOverride_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) ); MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); @@ -93,7 +98,7 @@ namespace ml_amt m_localTweaker = PlayerSetup.Instance.gameObject.AddComponent(); m_localTweaker.SetIKOverrideCrouch(Settings.IKOverrideCrouch); m_localTweaker.SetCrouchLimit(Settings.CrouchLimit); - m_localTweaker.SetIKOverrideCrouch(Settings.IKOverrideProne); + m_localTweaker.SetIKOverrideProne(Settings.IKOverrideProne); m_localTweaker.SetProneLimit(Settings.ProneLimit); m_localTweaker.SetPoseTransitions(Settings.PoseTransitions); m_localTweaker.SetAdjustedMovement(Settings.AdjustedMovement); @@ -153,6 +158,20 @@ namespace ml_amt } } + static void OnPlayspaceScale_Postfix() => ms_instance?.OnPlayspaceScale(); + void OnPlayspaceScale() + { + try + { + if(m_localTweaker != null) + m_localTweaker.OnPlayspaceScale(); + } + catch(System.Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } + } + // FBT detection override static void FBTDetour_Prefix() { @@ -237,14 +256,38 @@ namespace ml_amt return false; } - static bool OnAnimationOverride_Prefix() + static void OnOverride_Prefix(ref CVRAnimatorManager __instance, ref bool __state) { - return !Settings.OverrideFix; + try + { + if(Settings.OverrideFix && (__instance.animator != null)) + { + __state = __instance.animator.enabled; + if(__state) + __instance.animator.enabled = false; + __instance.animator.WriteDefaultValues(); + } + } + catch(System.Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } } - - static bool OnAnimationOverrideRestore_Prefix() + static void OnOverride_Postfix(ref CVRAnimatorManager __instance, bool __state) { - return !Settings.OverrideFix; + try + { + if(Settings.OverrideFix && (__instance.animator != null)) + { + __instance.animator.enabled = __state; + if(__state) + __instance.animator.Update(0f); + } + } + catch(System.Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } } } } diff --git a/ml_amt/MotionTweaker.cs b/ml_amt/MotionTweaker.cs index 6d45664..95527c1 100644 --- a/ml_amt/MotionTweaker.cs +++ b/ml_amt/MotionTweaker.cs @@ -1,4 +1,5 @@ using ABI_RC.Core.Player; +using ABI_RC.Systems.IK; using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.MovementSystem; using RootMotion.FinalIK; @@ -44,6 +45,7 @@ namespace ml_amt bool m_grounded = false; bool m_groundedRaw = false; bool m_moving = false; + bool m_locomotionOverride = false; bool m_ikOverrideCrouch = true; float m_crouchLimit = 0.65f; @@ -64,6 +66,7 @@ namespace ml_amt bool m_followHips = true; Vector3 m_hipsToPlayer = Vector3.zero; + Vector2 m_stepDistance = Vector2.zero; Vector3 m_massCenter = Vector3.zero; readonly List m_parameters = null; @@ -73,6 +76,7 @@ namespace ml_amt m_parameters = new List(); } + // Unity events void Start() { m_inVR = Utils.IsInVR(); @@ -87,7 +91,8 @@ namespace ml_amt Settings.IKOverrideJumpChange += this.SetIKOverrideJump; Settings.DetectEmotesChange += this.SetDetectEmotes; Settings.FollowHipsChange += this.SetFollowHips; - Settings.MassCenterChange += this.SetMassCenter; + Settings.MassCenterChange += this.OnMassCenterChange; + Settings.ScaledStepsChange += this.OnScaledStepsChange; } void OnDestroy() @@ -102,7 +107,7 @@ namespace ml_amt Settings.IKOverrideJumpChange -= this.SetIKOverrideJump; Settings.DetectEmotesChange -= this.SetDetectEmotes; Settings.FollowHipsChange -= this.SetFollowHips; - Settings.MassCenterChange -= this.SetMassCenter; + Settings.MassCenterChange -= this.OnMassCenterChange; } void Update() @@ -116,8 +121,7 @@ namespace ml_amt // Update upright Matrix4x4 l_hmdMatrix = PlayerSetup.Instance.transform.GetMatrix().inverse * (m_inVR ? PlayerSetup.Instance.vrHeadTracker.transform.GetMatrix() : PlayerSetup.Instance.desktopCameraRig.transform.GetMatrix()); float l_currentHeight = Mathf.Clamp((l_hmdMatrix * ms_pointVector).y, 0f, float.MaxValue); - float l_avatarScale = (m_avatarScale > 0f) ? (PlayerSetup.Instance._avatar.transform.localScale.y / m_avatarScale) : 0f; - float l_avatarViewHeight = Mathf.Clamp(m_viewPointHeight * l_avatarScale, 0f, float.MaxValue); + float l_avatarViewHeight = Mathf.Clamp(m_viewPointHeight * GetRelativeScale(), 0f, float.MaxValue); m_upright = Mathf.Clamp01((l_avatarViewHeight > 0f) ? (l_currentHeight / l_avatarViewHeight) : 0f); m_poseState = (m_upright <= Mathf.Min(m_proneLimit, m_crouchLimit)) ? PoseState.Proning : ((m_upright <= Mathf.Max(m_proneLimit, m_crouchLimit)) ? PoseState.Crouching : PoseState.Standing); @@ -163,6 +167,7 @@ namespace ml_amt } } + // Game events internal void OnAvatarClear() { m_vrIk = null; @@ -178,10 +183,12 @@ namespace ml_amt m_locomotionOffset = Vector3.zero; m_emoteActive = false; m_moving = false; + m_locomotionOverride = false; m_hipsToPlayer = Vector3.zero; m_avatarHips = null; m_viewPointHeight = 1f; m_massCenter = Vector3.zero; + m_stepDistance = Vector2.zero; m_parameters.Clear(); } @@ -252,6 +259,8 @@ namespace ml_amt m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? m_massCenter : m_locomotionOffset); + m_stepDistance.Set(m_vrIk.solver.locomotion.stepThreshold, m_vrIk.solver.locomotion.footDistance); + m_vrIk.onPreSolverUpdate.AddListener(this.OnIKPreUpdate); m_vrIk.onPostSolverUpdate.AddListener(this.OnIKPostUpdate); } @@ -273,9 +282,28 @@ namespace ml_amt } } + internal void OnPlayspaceScale() + { + if(m_vrIk != null) + { + if(Settings.MassCenter) + m_vrIk.solver.locomotion.offset = m_massCenter * GetRelativeScale(); + + if(Settings.ScaledSteps) + { + m_vrIk.solver.locomotion.stepThreshold = m_stepDistance.x * GetRelativeScale(); + m_vrIk.solver.locomotion.footDistance = m_stepDistance.y * GetRelativeScale(); + + m_vrIk.solver.locomotion.stepHeight.keys = Utils.GetSineKeyframes(Mathf.Clamp01(PlayerSetup.Instance.GetAvatarHeight()) * 0.03f); + m_vrIk.solver.locomotion.heelHeight.keys = Utils.GetSineKeyframes(Mathf.Clamp01(PlayerSetup.Instance.GetAvatarHeight()) * 0.03f); + } + } + } + + // IK events void OnIKPreUpdate() { - bool l_legsOverride = false; + bool l_locomotionOverride = false; m_ikWeight = m_vrIk.solver.IKPositionWeight; m_locomotionWeight = m_vrIk.solver.locomotion.weight; @@ -286,35 +314,42 @@ namespace ml_amt if(m_detectEmotes && m_emoteActive) m_vrIk.solver.IKPositionWeight = 0f; - if((m_ikOverrideCrouch && (m_poseState != PoseState.Standing)) || (m_ikOverrideProne && (m_poseState == PoseState.Proning))) + if(!BodySystem.isCalibratedAsFullBody) { - m_vrIk.solver.locomotion.weight = 0f; - l_legsOverride = true; - } - if(m_ikOverrideFly && MovementSystem.Instance.flying) - { - m_vrIk.solver.locomotion.weight = 0f; - m_vrIk.solver.leftLeg.useAnimatedBendNormal = true; - m_vrIk.solver.rightLeg.useAnimatedBendNormal = true; - l_legsOverride = true; - } - - if(m_ikOverrideJump && !m_grounded && !MovementSystem.Instance.flying) - { - m_vrIk.solver.locomotion.weight = 0f; - m_vrIk.solver.leftLeg.useAnimatedBendNormal = true; - m_vrIk.solver.rightLeg.useAnimatedBendNormal = true; - l_legsOverride = true; + if((m_ikOverrideCrouch && (m_poseState != PoseState.Standing)) || (m_ikOverrideProne && (m_poseState == PoseState.Proning))) + { + m_vrIk.solver.locomotion.weight = 0f; + m_vrIk.solver.leftLeg.useAnimatedBendNormal = true; + m_vrIk.solver.rightLeg.useAnimatedBendNormal = true; + l_locomotionOverride = true; + } + if(m_ikOverrideFly && MovementSystem.Instance.flying) + { + m_vrIk.solver.locomotion.weight = 0f; + m_vrIk.solver.leftLeg.useAnimatedBendNormal = true; + m_vrIk.solver.rightLeg.useAnimatedBendNormal = true; + l_locomotionOverride = true; + } + if(m_ikOverrideJump && !m_grounded && !MovementSystem.Instance.flying) + { + m_vrIk.solver.locomotion.weight = 0f; + m_vrIk.solver.leftLeg.useAnimatedBendNormal = true; + m_vrIk.solver.rightLeg.useAnimatedBendNormal = true; + l_locomotionOverride = true; + } } bool l_solverActive = !Mathf.Approximately(m_vrIk.solver.IKPositionWeight, 0f); - - if(l_legsOverride && l_solverActive && m_followHips && (!m_moving || (m_poseState == PoseState.Proning)) && m_inVR && !BodySystem.isCalibratedAsFullBody) + if(l_locomotionOverride && l_solverActive && m_followHips && (!m_moving || (m_poseState == PoseState.Proning)) && m_inVR && !BodySystem.isCalibratedAsFullBody) { m_vrIk.solver.plantFeet = false; - ABI_RC.Systems.IK.IKSystem.VrikRootController.enabled = false; + IKSystem.VrikRootController.enabled = false; PlayerSetup.Instance._avatar.transform.localPosition = m_hipsToPlayer; } + + if(m_locomotionOverride && !l_locomotionOverride) + m_vrIk.solver.Reset(); + m_locomotionOverride = l_locomotionOverride; } void OnIKPostUpdate() @@ -326,25 +361,26 @@ namespace ml_amt m_vrIk.solver.rightLeg.useAnimatedBendNormal = m_bendNormalRight; } - public void SetIKOverrideCrouch(bool p_state) + // Settings + internal void SetIKOverrideCrouch(bool p_state) { m_ikOverrideCrouch = p_state; } - public void SetCrouchLimit(float p_value) + internal void SetCrouchLimit(float p_value) { if(!m_customCrouchLimit) m_crouchLimit = Mathf.Clamp01(p_value); } - public void SetIKOverrideProne(bool p_state) + internal void SetIKOverrideProne(bool p_state) { m_ikOverrideProne = p_state; } - public void SetProneLimit(float p_value) + internal void SetProneLimit(float p_value) { if(!m_customProneLimit) m_proneLimit = Mathf.Clamp01(p_value); } - public void SetPoseTransitions(bool p_state) + internal void SetPoseTransitions(bool p_state) { m_poseTransitions = p_state; @@ -354,7 +390,7 @@ namespace ml_amt PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Prone", false); } } - public void SetAdjustedMovement(bool p_state) + internal void SetAdjustedMovement(bool p_state) { m_adjustedMovement = p_state; @@ -364,28 +400,54 @@ namespace ml_amt MovementSystem.Instance.ChangeProne(false); } } - public void SetIKOverrideFly(bool p_state) + internal void SetIKOverrideFly(bool p_state) { m_ikOverrideFly = p_state; } - public void SetIKOverrideJump(bool p_state) + internal void SetIKOverrideJump(bool p_state) { m_ikOverrideJump = p_state; } - public void SetDetectEmotes(bool p_state) + internal void SetDetectEmotes(bool p_state) { m_detectEmotes = p_state; } - public void SetFollowHips(bool p_state) + internal void SetFollowHips(bool p_state) { m_followHips = p_state; } - public void SetMassCenter(bool p_state) + void OnMassCenterChange(bool p_state) { if(m_vrIk != null) - m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? m_massCenter : m_locomotionOffset); + m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? (m_massCenter * GetRelativeScale()) : m_locomotionOffset); + } + void OnScaledStepsChange(bool p_state) + { + if(m_vrIk != null) + { + if(p_state) + { + m_vrIk.solver.locomotion.stepThreshold = m_stepDistance.x * GetRelativeScale(); + m_vrIk.solver.locomotion.footDistance = m_stepDistance.y * GetRelativeScale(); + m_vrIk.solver.locomotion.stepHeight.keys = Utils.GetSineKeyframes(Mathf.Clamp01(PlayerSetup.Instance.GetAvatarHeight()) * 0.03f); + m_vrIk.solver.locomotion.heelHeight.keys = Utils.GetSineKeyframes(Mathf.Clamp01(PlayerSetup.Instance.GetAvatarHeight()) * 0.03f); + } + else + { + IKSystem.Instance.ApplyAvatarScaleToIk(PlayerSetup.Instance.GetAvatarHeight()); + m_vrIk.solver.locomotion.stepHeight.keys = Utils.GetSineKeyframes(0.03f); + m_vrIk.solver.locomotion.heelHeight.keys = Utils.GetSineKeyframes(0.03f); + } + } } + // Arbitrary + float GetRelativeScale() + { + return ((m_avatarScale > 0f) ? (PlayerSetup.Instance._avatar.transform.localScale.y / m_avatarScale) : 0f); + } + + // Parameters access public float GetUpright() => m_upright; public bool GetGroundedRaw() => m_groundedRaw; public bool GetMoving() => m_moving; diff --git a/ml_amt/Settings.cs b/ml_amt/Settings.cs index c01f273..930a83d 100644 --- a/ml_amt/Settings.cs +++ b/ml_amt/Settings.cs @@ -20,23 +20,25 @@ namespace ml_amt DetectEmotes, FollowHips, CollisionScale, + ScaledSteps, MassCenter, OverrideFix }; - static bool ms_ikOverrideCrouch = true; - static float ms_crouchLimit = 0.65f; - static bool ms_ikOverrideProne = true; - static float ms_proneLimit = 0.3f; - static bool ms_poseTransitions = true; - static bool ms_adjustedMovement = true; - static bool ms_ikOverrideFly = true; - static bool ms_ikOverrideJump = true; - static bool ms_detectEmotes = true; - static bool ms_followHips = true; - static bool ms_collisionScale = true; - static bool ms_massCenter = true; - static bool ms_overrideFix = false; + public static bool IKOverrideCrouch { get; private set; } = true; + public static float CrouchLimit { get; private set; } = 0.65f; + public static bool IKOverrideProne { get; private set; } = true; + public static float ProneLimit { get; private set; } = 0.3f; + public static bool PoseTransitions { get; private set; } = true; + public static bool AdjustedMovement { get; private set; } = true; + public static bool IKOverrideFly { get; private set; } = true; + public static bool IKOverrideJump { get; private set; } = true; + public static bool DetectEmotes { get; private set; } = true; + public static bool FollowHips { get; private set; } = true; + public static bool MassCenter { get; private set; } = true; + public static bool ScaledSteps { get; private set; } = true; + public static bool CollisionScale { get; private set; } = true; + public static bool OverrideFix { get; private set; } = true; static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; @@ -51,8 +53,9 @@ namespace ml_amt static public event Action IKOverrideJumpChange; static public event Action DetectEmotesChange; static public event Action FollowHipsChange; - static public event Action CollisionScaleChange; static public event Action MassCenterChange; + static public event Action ScaledStepsChange; + static public event Action CollisionScaleChange; static public event Action OverrideFixChange; internal static void Init() @@ -61,19 +64,20 @@ namespace ml_amt ms_entries = new List() { - ms_category.CreateEntry(ModSetting.IKOverrideCrouch.ToString(), true), - ms_category.CreateEntry(ModSetting.CrouchLimit.ToString(), 65), - ms_category.CreateEntry(ModSetting.IKOverrideProne.ToString(), true), - ms_category.CreateEntry(ModSetting.ProneLimit.ToString(), 30), - ms_category.CreateEntry(ModSetting.PoseTransitions.ToString(), true), - ms_category.CreateEntry(ModSetting.AdjustedMovement.ToString(), true), - ms_category.CreateEntry(ModSetting.IKOverrideFly.ToString(), true), - ms_category.CreateEntry(ModSetting.IKOverrideJump.ToString(), true), - ms_category.CreateEntry(ModSetting.DetectEmotes.ToString(), true), - ms_category.CreateEntry(ModSetting.FollowHips.ToString(), true), - ms_category.CreateEntry(ModSetting.CollisionScale.ToString(), true), - ms_category.CreateEntry(ModSetting.MassCenter.ToString(), true), - ms_category.CreateEntry(ModSetting.OverrideFix.ToString(), false) + ms_category.CreateEntry(ModSetting.IKOverrideCrouch.ToString(), IKOverrideCrouch), + ms_category.CreateEntry(ModSetting.CrouchLimit.ToString(), (int)(CrouchLimit * 100f)), + ms_category.CreateEntry(ModSetting.IKOverrideProne.ToString(), IKOverrideProne), + ms_category.CreateEntry(ModSetting.ProneLimit.ToString(), (int)(ProneLimit * 100f)), + ms_category.CreateEntry(ModSetting.PoseTransitions.ToString(), PoseTransitions), + ms_category.CreateEntry(ModSetting.AdjustedMovement.ToString(), AdjustedMovement), + ms_category.CreateEntry(ModSetting.IKOverrideFly.ToString(), IKOverrideFly), + ms_category.CreateEntry(ModSetting.IKOverrideJump.ToString(), IKOverrideJump), + ms_category.CreateEntry(ModSetting.DetectEmotes.ToString(), DetectEmotes), + ms_category.CreateEntry(ModSetting.FollowHips.ToString(), FollowHips), + ms_category.CreateEntry(ModSetting.MassCenter.ToString(), MassCenter), + ms_category.CreateEntry(ModSetting.ScaledSteps.ToString(), ScaledSteps), + ms_category.CreateEntry(ModSetting.CollisionScale.ToString(), CollisionScale), + ms_category.CreateEntry(ModSetting.OverrideFix.ToString(), OverrideFix) }; Load(); @@ -105,19 +109,20 @@ namespace ml_amt static void Load() { - ms_ikOverrideCrouch = (bool)ms_entries[(int)ModSetting.IKOverrideCrouch].BoxedValue; - ms_crouchLimit = ((int)ms_entries[(int)ModSetting.CrouchLimit].BoxedValue) * 0.01f; - ms_ikOverrideProne = (bool)ms_entries[(int)ModSetting.IKOverrideProne].BoxedValue; - ms_proneLimit = ((int)ms_entries[(int)ModSetting.ProneLimit].BoxedValue) * 0.01f; - ms_poseTransitions = (bool)ms_entries[(int)ModSetting.PoseTransitions].BoxedValue; - ms_adjustedMovement = (bool)ms_entries[(int)ModSetting.AdjustedMovement].BoxedValue; - ms_ikOverrideFly = (bool)ms_entries[(int)ModSetting.IKOverrideFly].BoxedValue; - ms_ikOverrideJump = (bool)ms_entries[(int)ModSetting.IKOverrideJump].BoxedValue; - ms_detectEmotes = (bool)ms_entries[(int)ModSetting.DetectEmotes].BoxedValue; - ms_followHips = (bool)ms_entries[(int)ModSetting.FollowHips].BoxedValue; - ms_collisionScale = (bool)ms_entries[(int)ModSetting.CollisionScale].BoxedValue; - ms_massCenter = (bool)ms_entries[(int)ModSetting.MassCenter].BoxedValue; - ms_overrideFix = (bool)ms_entries[(int)ModSetting.OverrideFix].BoxedValue; + IKOverrideCrouch = (bool)ms_entries[(int)ModSetting.IKOverrideCrouch].BoxedValue; + CrouchLimit = ((int)ms_entries[(int)ModSetting.CrouchLimit].BoxedValue) * 0.01f; + IKOverrideProne = (bool)ms_entries[(int)ModSetting.IKOverrideProne].BoxedValue; + ProneLimit = ((int)ms_entries[(int)ModSetting.ProneLimit].BoxedValue) * 0.01f; + PoseTransitions = (bool)ms_entries[(int)ModSetting.PoseTransitions].BoxedValue; + AdjustedMovement = (bool)ms_entries[(int)ModSetting.AdjustedMovement].BoxedValue; + IKOverrideFly = (bool)ms_entries[(int)ModSetting.IKOverrideFly].BoxedValue; + IKOverrideJump = (bool)ms_entries[(int)ModSetting.IKOverrideJump].BoxedValue; + DetectEmotes = (bool)ms_entries[(int)ModSetting.DetectEmotes].BoxedValue; + FollowHips = (bool)ms_entries[(int)ModSetting.FollowHips].BoxedValue; + MassCenter = (bool)ms_entries[(int)ModSetting.MassCenter].BoxedValue; + ScaledSteps = (bool)ms_entries[(int)ModSetting.ScaledSteps].BoxedValue; + CollisionScale = (bool)ms_entries[(int)ModSetting.CollisionScale].BoxedValue; + OverrideFix = (bool)ms_entries[(int)ModSetting.OverrideFix].BoxedValue; } static void OnSliderUpdate(string p_name, string p_value) @@ -128,15 +133,15 @@ namespace ml_amt { case ModSetting.CrouchLimit: { - ms_crouchLimit = int.Parse(p_value) * 0.01f; - CrouchLimitChange?.Invoke(ms_crouchLimit); + CrouchLimit = int.Parse(p_value) * 0.01f; + CrouchLimitChange?.Invoke(CrouchLimit); } break; case ModSetting.ProneLimit: { - ms_proneLimit = int.Parse(p_value) * 0.01f; - ProneLimitChange?.Invoke(ms_proneLimit); + ProneLimit = int.Parse(p_value) * 0.01f; + ProneLimitChange?.Invoke(ProneLimit); } break; } @@ -153,78 +158,85 @@ namespace ml_amt { case ModSetting.IKOverrideCrouch: { - ms_ikOverrideCrouch = bool.Parse(p_value); - IKOverrideCrouchChange?.Invoke(ms_ikOverrideCrouch); + IKOverrideCrouch = bool.Parse(p_value); + IKOverrideCrouchChange?.Invoke(IKOverrideCrouch); } break; case ModSetting.IKOverrideProne: { - ms_ikOverrideProne = bool.Parse(p_value); - IKOverrideProneChange?.Invoke(ms_ikOverrideProne); + IKOverrideProne = bool.Parse(p_value); + IKOverrideProneChange?.Invoke(IKOverrideProne); } break; case ModSetting.PoseTransitions: { - ms_poseTransitions = bool.Parse(p_value); - PoseTransitionsChange?.Invoke(ms_poseTransitions); + PoseTransitions = bool.Parse(p_value); + PoseTransitionsChange?.Invoke(PoseTransitions); } break; case ModSetting.AdjustedMovement: { - ms_adjustedMovement = bool.Parse(p_value); - AdjustedMovementChange?.Invoke(ms_adjustedMovement); + AdjustedMovement = bool.Parse(p_value); + AdjustedMovementChange?.Invoke(AdjustedMovement); } break; case ModSetting.IKOverrideFly: { - ms_ikOverrideFly = bool.Parse(p_value); - IKOverrideFlyChange?.Invoke(ms_ikOverrideFly); + IKOverrideFly = bool.Parse(p_value); + IKOverrideFlyChange?.Invoke(IKOverrideFly); } break; case ModSetting.IKOverrideJump: { - ms_ikOverrideJump = bool.Parse(p_value); - IKOverrideJumpChange?.Invoke(ms_ikOverrideJump); + IKOverrideJump = bool.Parse(p_value); + IKOverrideJumpChange?.Invoke(IKOverrideJump); } break; case ModSetting.DetectEmotes: { - ms_detectEmotes = bool.Parse(p_value); - DetectEmotesChange?.Invoke(ms_detectEmotes); + DetectEmotes = bool.Parse(p_value); + DetectEmotesChange?.Invoke(DetectEmotes); } break; case ModSetting.FollowHips: { - ms_followHips = bool.Parse(p_value); - FollowHipsChange?.Invoke(ms_followHips); - } - break; - - case ModSetting.CollisionScale: - { - ms_collisionScale = bool.Parse(p_value); - CollisionScaleChange?.Invoke(ms_collisionScale); + FollowHips = bool.Parse(p_value); + FollowHipsChange?.Invoke(FollowHips); } break; case ModSetting.MassCenter: { - ms_massCenter = bool.Parse(p_value); - MassCenterChange?.Invoke(ms_massCenter); + MassCenter = bool.Parse(p_value); + MassCenterChange?.Invoke(MassCenter); + } + break; + + case ModSetting.ScaledSteps: + { + ScaledSteps = bool.Parse(p_value); + ScaledStepsChange?.Invoke(ScaledSteps); + } + break; + + case ModSetting.CollisionScale: + { + CollisionScale = bool.Parse(p_value); + CollisionScaleChange?.Invoke(CollisionScale); } break; case ModSetting.OverrideFix: { - ms_overrideFix = bool.Parse(p_value); - OverrideFixChange?.Invoke(ms_overrideFix); + OverrideFix = bool.Parse(p_value); + OverrideFixChange?.Invoke(OverrideFix); } break; } @@ -232,58 +244,5 @@ namespace ml_amt ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value); } } - - public static bool IKOverrideCrouch - { - get => ms_ikOverrideCrouch; - } - public static float CrouchLimit - { - get => ms_crouchLimit; - } - public static bool IKOverrideProne - { - get => ms_ikOverrideProne; - } - public static float ProneLimit - { - get => ms_proneLimit; - } - public static bool PoseTransitions - { - get => ms_poseTransitions; - } - public static bool AdjustedMovement - { - get => ms_adjustedMovement; - } - public static bool IKOverrideFly - { - get => ms_ikOverrideFly; - } - public static bool IKOverrideJump - { - get => ms_ikOverrideJump; - } - public static bool DetectEmotes - { - get => ms_detectEmotes; - } - public static bool FollowHips - { - get => ms_followHips; - } - public static bool CollisionScale - { - get => ms_collisionScale; - } - public static bool MassCenter - { - get => ms_massCenter; - } - public static bool OverrideFix - { - get => ms_overrideFix; - } } } diff --git a/ml_amt/Utils.cs b/ml_amt/Utils.cs index 31b75d8..140cadc 100644 --- a/ml_amt/Utils.cs +++ b/ml_amt/Utils.cs @@ -1,10 +1,12 @@ using UnityEngine; -using ABI_RC.Systems.IK; +using System.Reflection; namespace ml_amt { static class Utils { + static MethodInfo ms_getSineKeyframes = typeof(RootMotion.FinalIK.IKSolverVR).GetMethod("GetSineKeyframes", BindingFlags.NonPublic | BindingFlags.Static); + public static bool IsInVR() => ((ABI_RC.Core.Savior.CheckVR.Instance != null) && ABI_RC.Core.Savior.CheckVR.Instance.hasVrDeviceLoaded); // Extensions @@ -12,5 +14,10 @@ namespace ml_amt { return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.localScale : Vector3.one); } + + public static Keyframe[] GetSineKeyframes(float p_mag) + { + return (Keyframe[])ms_getSineKeyframes.Invoke(null, new object[] { p_mag }); + } } } diff --git a/ml_amt/resources/menu.js b/ml_amt/resources/menu.js index 8e1e71c..152a75c 100644 --- a/ml_amt/resources/menu.js +++ b/ml_amt/resources/menu.js @@ -256,6 +256,13 @@ function inp_toggle_mod_amt(_obj, _callbackName) {
+ +
+
Scaled locomotion steps:
+
+
+
+
Alternative avatar collider scale:
@@ -265,9 +272,9 @@ function inp_toggle_mod_amt(_obj, _callbackName) {
-
Prevent Unity animation override (chairs, etc.):
+
Fix animation overrides (chairs, etc.):
-
+
`; diff --git a/ml_dht/HeadTracked.cs b/ml_dht/HeadTracked.cs index a7ac529..00b116d 100644 --- a/ml_dht/HeadTracked.cs +++ b/ml_dht/HeadTracked.cs @@ -34,6 +34,7 @@ namespace ml_dht Quaternion m_bindRotation; Quaternion m_lastHeadRotation; + // Unity events void Start() { Settings.EnabledChange += this.SetEnabled; @@ -56,6 +57,7 @@ namespace ml_dht Settings.FaceOverrideChange -= this.SetFaceOverride; } + // Tracking updates public void UpdateTrackingData(ref TrackingData p_data) { m_headPosition.Set(p_data.m_headPositionX * (m_mirrored ? -1f : 1f), p_data.m_headPositionY, p_data.m_headPositionZ); @@ -77,6 +79,7 @@ namespace ml_dht } } + // Game events internal void OnEyeControllerUpdate(CVREyeController p_component) { if(m_enabled) @@ -139,7 +142,8 @@ namespace ml_dht m_bindRotation = Quaternion.identity; } - public void SetEnabled(bool p_state) + // Settings + internal void SetEnabled(bool p_state) { if(m_enabled != p_state) { @@ -148,7 +152,7 @@ namespace ml_dht m_lastHeadRotation = ((m_headBone != null) ? m_headBone.rotation : m_bindRotation); } } - public void SetHeadTracking(bool p_state) + internal void SetHeadTracking(bool p_state) { if(m_headTracking != p_state) { @@ -157,23 +161,23 @@ namespace ml_dht m_lastHeadRotation = ((m_headBone != null) ? m_headBone.rotation : m_bindRotation); } } - public void SetEyeTracking(bool p_state) + internal void SetEyeTracking(bool p_state) { m_eyeTracking = p_state; } - public void SetBlinking(bool p_state) + internal void SetBlinking(bool p_state) { m_blinking = p_state; } - public void SetSmoothing(float p_value) + internal void SetSmoothing(float p_value) { m_smoothing = 1f - Mathf.Clamp(p_value, 0f, 0.99f); } - public void SetMirrored(bool p_state) + internal void SetMirrored(bool p_state) { m_mirrored = p_state; } - public void SetFaceOverride(bool p_state) + internal void SetFaceOverride(bool p_state) { m_faceOverride = p_state; } diff --git a/ml_dht/Settings.cs b/ml_dht/Settings.cs index 12057f2..7251fed 100644 --- a/ml_dht/Settings.cs +++ b/ml_dht/Settings.cs @@ -18,13 +18,13 @@ namespace ml_dht FaceOverride } - static bool ms_enabled = false; - static bool ms_headTracking = true; - static bool ms_eyeTracking = true; - static bool ms_blinking = true; - static bool ms_mirrored = false; - static float ms_smoothing = 0.5f; - static bool ms_faceOverride = true; + public static bool Enabled { get; private set; } = false; + public static bool HeadTracking { get; private set; } = true; + public static bool EyeTracking { get; private set; } = true; + public static bool Blinking { get; private set; } = true; + public static bool Mirrored { get; private set; } = false; + public static float Smoothing { get; private set; } = 0.5f; + public static bool FaceOverride { get; private set; } = true; static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; @@ -43,13 +43,13 @@ namespace ml_dht ms_entries = new List() { - ms_category.CreateEntry(ModSetting.Enabled.ToString(), false), - ms_category.CreateEntry(ModSetting.HeadTracking.ToString(), false), - ms_category.CreateEntry(ModSetting.EyeTracking.ToString(), true), - ms_category.CreateEntry(ModSetting.Blinking.ToString(), true), - ms_category.CreateEntry(ModSetting.Mirrored.ToString(), false), - ms_category.CreateEntry(ModSetting.Smoothing.ToString(), 50), - ms_category.CreateEntry(ModSetting.FaceOverride.ToString(), true) + ms_category.CreateEntry(ModSetting.Enabled.ToString(), Enabled), + ms_category.CreateEntry(ModSetting.HeadTracking.ToString(), HeadTracking), + ms_category.CreateEntry(ModSetting.EyeTracking.ToString(), EyeTracking), + ms_category.CreateEntry(ModSetting.Blinking.ToString(), Blinking), + ms_category.CreateEntry(ModSetting.Mirrored.ToString(), Mirrored), + ms_category.CreateEntry(ModSetting.Smoothing.ToString(), (int)(Smoothing * 50f)), + ms_category.CreateEntry(ModSetting.FaceOverride.ToString(), FaceOverride) }; Load(); @@ -81,13 +81,13 @@ namespace ml_dht static void Load() { - ms_enabled = (bool)ms_entries[(int)ModSetting.Enabled].BoxedValue; - ms_headTracking = (bool)ms_entries[(int)ModSetting.HeadTracking].BoxedValue; - ms_eyeTracking = (bool)ms_entries[(int)ModSetting.EyeTracking].BoxedValue; - ms_blinking = (bool)ms_entries[(int)ModSetting.Blinking].BoxedValue; - ms_mirrored = (bool)ms_entries[(int)ModSetting.Mirrored].BoxedValue; - ms_smoothing = ((int)ms_entries[(int)ModSetting.Smoothing].BoxedValue) * 0.01f; - ms_faceOverride = (bool)ms_entries[(int)ModSetting.FaceOverride].BoxedValue; + Enabled = (bool)ms_entries[(int)ModSetting.Enabled].BoxedValue; + HeadTracking = (bool)ms_entries[(int)ModSetting.HeadTracking].BoxedValue; + EyeTracking = (bool)ms_entries[(int)ModSetting.EyeTracking].BoxedValue; + Blinking = (bool)ms_entries[(int)ModSetting.Blinking].BoxedValue; + Mirrored = (bool)ms_entries[(int)ModSetting.Mirrored].BoxedValue; + Smoothing = ((int)ms_entries[(int)ModSetting.Smoothing].BoxedValue) * 0.01f; + FaceOverride = (bool)ms_entries[(int)ModSetting.FaceOverride].BoxedValue; } static void OnSliderUpdate(string p_name, string p_value) @@ -98,8 +98,8 @@ namespace ml_dht { case ModSetting.Smoothing: { - ms_smoothing = int.Parse(p_value) * 0.01f; - SmoothingChange?.Invoke(ms_smoothing); + Smoothing = int.Parse(p_value) * 0.01f; + SmoothingChange?.Invoke(Smoothing); } break; } @@ -116,43 +116,43 @@ namespace ml_dht { case ModSetting.Enabled: { - ms_enabled = bool.Parse(p_value); - EnabledChange?.Invoke(ms_enabled); + Enabled = bool.Parse(p_value); + EnabledChange?.Invoke(Enabled); } break; case ModSetting.HeadTracking: { - ms_headTracking = bool.Parse(p_value); - HeadTrackingChange?.Invoke(ms_headTracking); + HeadTracking = bool.Parse(p_value); + HeadTrackingChange?.Invoke(HeadTracking); } break; case ModSetting.EyeTracking: { - ms_eyeTracking = bool.Parse(p_value); - EyeTrackingChange?.Invoke(ms_eyeTracking); + EyeTracking = bool.Parse(p_value); + EyeTrackingChange?.Invoke(EyeTracking); } break; case ModSetting.Blinking: { - ms_blinking = bool.Parse(p_value); - BlinkingChange?.Invoke(ms_blinking); + Blinking = bool.Parse(p_value); + BlinkingChange?.Invoke(Blinking); } break; case ModSetting.Mirrored: { - ms_mirrored = bool.Parse(p_value); - MirroredChange?.Invoke(ms_mirrored); + Mirrored = bool.Parse(p_value); + MirroredChange?.Invoke(Mirrored); } break; case ModSetting.FaceOverride: { - ms_faceOverride = bool.Parse(p_value); - FaceOverrideChange?.Invoke(ms_faceOverride); + FaceOverride = bool.Parse(p_value); + FaceOverrideChange?.Invoke(FaceOverride); } break; } @@ -160,34 +160,5 @@ namespace ml_dht ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value); } } - - public static bool Enabled - { - get => ms_enabled; - } - public static bool HeadTracking - { - get => ms_headTracking; - } - public static bool EyeTracking - { - get => ms_eyeTracking; - } - public static bool Blinking - { - get => ms_blinking; - } - public static bool Mirrored - { - get => ms_mirrored; - } - public static float Smoothing - { - get => ms_smoothing; - } - public static bool FaceOverride - { - get => ms_faceOverride; - } } } diff --git a/ml_lme/LeapInput.cs b/ml_lme/LeapInput.cs index 697d95e..6365a67 100644 --- a/ml_lme/LeapInput.cs +++ b/ml_lme/LeapInput.cs @@ -11,8 +11,6 @@ namespace ml_lme [DisallowMultipleComponent] class LeapInput : CVRInputModule { - static readonly FieldInfo ms_indexGestureToggle = typeof(InputModuleSteamVR).GetField("_steamVrIndexGestureToggleValue", BindingFlags.Instance | BindingFlags.NonPublic); - CVRInputManager m_inputManager = null; InputModuleSteamVR m_steamVrModule = null; bool m_inVR = false; @@ -123,8 +121,18 @@ namespace ml_lme { if(l_data.m_leftHand.m_present) SetFingersInput(l_data.m_leftHand, true); + if(l_data.m_rightHand.m_present) SetFingersInput(l_data.m_rightHand, false); + + if(m_inVR) + { + m_inputManager.individualFingerTracking = !m_steamVrModule.GetIndexGestureToggle(); + m_inputManager.individualFingerTracking |= (l_data.m_leftHand.m_present || l_data.m_rightHand.m_present); + } + else + m_inputManager.individualFingerTracking = (l_data.m_leftHand.m_present || l_data.m_rightHand.m_present); + IKSystem.Instance.FingerSystem.controlActive = m_inputManager.individualFingerTracking; } m_handRayLeft.enabled = (l_data.m_leftHand.m_present && (!m_inVR || !Utils.IsLeftHandTracked() || !Settings.FingersOnly)); @@ -240,15 +248,12 @@ namespace ml_lme // Arbitrary void UpdateFingerTracking() { - m_inputManager.individualFingerTracking = (Settings.Enabled || (m_inVR && Utils.AreKnucklesInUse() && !(bool)ms_indexGestureToggle.GetValue(m_steamVrModule))); + m_inputManager.individualFingerTracking = (Settings.Enabled || (m_inVR && Utils.AreKnucklesInUse() && !m_steamVrModule.GetIndexGestureToggle())); IKSystem.Instance.FingerSystem.controlActive = m_inputManager.individualFingerTracking; } void SetFingersInput(GestureMatcher.HandData p_hand, bool p_left) { - m_inputManager.individualFingerTracking = true; - IKSystem.Instance.FingerSystem.controlActive = true; - if(p_left) { m_inputManager.fingerCurlLeftThumb = p_hand.m_bends[0]; @@ -256,11 +261,6 @@ namespace ml_lme m_inputManager.fingerCurlLeftMiddle = p_hand.m_bends[2]; m_inputManager.fingerCurlLeftRing = p_hand.m_bends[3]; m_inputManager.fingerCurlLeftPinky = p_hand.m_bends[4]; - IKSystem.Instance.FingerSystem.leftThumbCurl = p_hand.m_bends[0]; - IKSystem.Instance.FingerSystem.leftIndexCurl = p_hand.m_bends[1]; - IKSystem.Instance.FingerSystem.leftMiddleCurl = p_hand.m_bends[2]; - IKSystem.Instance.FingerSystem.leftRingCurl = p_hand.m_bends[3]; - IKSystem.Instance.FingerSystem.leftPinkyCurl = p_hand.m_bends[4]; } else { @@ -269,14 +269,10 @@ namespace ml_lme m_inputManager.fingerCurlRightMiddle = p_hand.m_bends[2]; m_inputManager.fingerCurlRightRing = p_hand.m_bends[3]; m_inputManager.fingerCurlRightPinky = p_hand.m_bends[4]; - IKSystem.Instance.FingerSystem.rightThumbCurl = p_hand.m_bends[0]; - IKSystem.Instance.FingerSystem.rightIndexCurl = p_hand.m_bends[1]; - IKSystem.Instance.FingerSystem.rightMiddleCurl = p_hand.m_bends[2]; - IKSystem.Instance.FingerSystem.rightRingCurl = p_hand.m_bends[3]; - IKSystem.Instance.FingerSystem.rightPinkyCurl = p_hand.m_bends[4]; } } + // Game settings void OnGameSettingBoolChange(string p_name, bool p_state) { if(p_name == "ControlUseGripToGrab") diff --git a/ml_lme/LeapTracked.cs b/ml_lme/LeapTracked.cs index 4725404..7c8cfea 100644 --- a/ml_lme/LeapTracked.cs +++ b/ml_lme/LeapTracked.cs @@ -37,6 +37,7 @@ namespace ml_lme bool m_leftTargetActive = false; bool m_rightTargetActive = false; + // Unity events void Start() { m_inVR = Utils.IsInVR(); @@ -51,51 +52,20 @@ namespace ml_lme m_rightHandTarget.localPosition = Vector3.zero; m_rightHandTarget.localRotation = Quaternion.identity; - Settings.EnabledChange += this.SetEnabled; - Settings.FingersOnlyChange += this.SetFingersOnly; - Settings.TrackElbowsChange += this.SetTrackElbows; + Settings.EnabledChange += this.OnEnabledChange; + Settings.FingersOnlyChange += this.OnFingersOnlyChange; + Settings.TrackElbowsChange += this.OnTrackElbowsChange; - SetEnabled(Settings.Enabled); - SetFingersOnly(Settings.FingersOnly); - SetTrackElbows(Settings.TrackElbows); + OnEnabledChange(Settings.Enabled); + OnFingersOnlyChange(Settings.FingersOnly); + OnTrackElbowsChange(Settings.TrackElbows); } void OnDestroy() { - Settings.EnabledChange -= this.SetEnabled; - Settings.FingersOnlyChange -= this.SetFingersOnly; - Settings.TrackElbowsChange -= this.SetTrackElbows; - } - - void SetEnabled(bool p_state) - { - m_enabled = p_state; - - RefreshArmIK(); - if(!m_enabled || m_fingersOnly) - RestoreVRIK(); - } - - void SetFingersOnly(bool p_state) - { - m_fingersOnly = p_state; - - RefreshArmIK(); - if(!m_enabled || m_fingersOnly) - RestoreVRIK(); - } - - void SetTrackElbows(bool p_state) - { - m_trackElbows = p_state; - - if((m_leftArmIK != null) && (m_rightArmIK != null)) - { - m_leftArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f); - m_rightArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f); - } - - RestoreVRIK(); + Settings.EnabledChange -= this.OnEnabledChange; + Settings.FingersOnlyChange -= this.OnFingersOnlyChange; + Settings.TrackElbowsChange -= this.OnTrackElbowsChange; } void Update() @@ -159,15 +129,18 @@ namespace ml_lme GestureMatcher.LeapData l_data = LeapManager.GetInstance().GetLatestData(); Vector3 l_hipsLocalPos = m_hips.localPosition; + Quaternion l_hipsLocalRot = m_hips.localRotation; m_poseHandler.GetHumanPose(ref m_pose); UpdateFingers(l_data); m_poseHandler.SetHumanPose(ref m_pose); m_hips.localPosition = l_hipsLocalPos; + m_hips.localRotation = l_hipsLocalRot; } } + // Tracking update void UpdateFingers(GestureMatcher.LeapData p_data) { if(p_data.m_leftHand.m_present) @@ -227,6 +200,7 @@ namespace ml_lme } } + // Game events internal void OnAvatarClear() { m_vrIK = null; @@ -348,6 +322,7 @@ namespace ml_lme } } + // IK updates void OnIKPreUpdate() { m_armsWeights.Set( @@ -376,6 +351,39 @@ namespace ml_lme m_vrIK.solver.rightArm.rotationWeight = m_armsWeights.w; } + // Settings + void OnEnabledChange(bool p_state) + { + m_enabled = p_state; + + RefreshArmIK(); + if(!m_enabled || m_fingersOnly) + RestoreVRIK(); + } + + void OnFingersOnlyChange(bool p_state) + { + m_fingersOnly = p_state; + + RefreshArmIK(); + if(!m_enabled || m_fingersOnly) + RestoreVRIK(); + } + + void OnTrackElbowsChange(bool p_state) + { + m_trackElbows = p_state; + + if((m_leftArmIK != null) && (m_rightArmIK != null)) + { + m_leftArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f); + m_rightArmIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f); + } + + RestoreVRIK(); + } + + // Arbitrary void RestoreVRIK() { if(m_vrIK != null) diff --git a/ml_lme/Settings.cs b/ml_lme/Settings.cs index 0015b43..a28ee48 100644 --- a/ml_lme/Settings.cs +++ b/ml_lme/Settings.cs @@ -37,18 +37,18 @@ namespace ml_lme GripThreadhold }; - static bool ms_enabled = false; - static Vector3 ms_desktopOffset = new Vector3(0f, -0.45f, 0.3f); - static bool ms_fingersOnly = false; - static bool ms_modelVisibility = false; - static LeapTrackingMode ms_trackingMode = LeapTrackingMode.Desktop; - static Vector3 ms_rootAngle = Vector3.zero; - static bool ms_headAttach = false; - static Vector3 ms_headOffset = new Vector3(0f, -0.3f, 0.15f); - static bool ms_trackElbows = true; - static bool ms_input = true; - static float ms_interactThreadhold = 0.8f; - static float ms_gripThreadhold = 0.4f; + public static bool Enabled { get; private set; } = false; + public static Vector3 DesktopOffset { get; private set; } = new Vector3(0f, -0.45f, 0.3f); + public static bool FingersOnly { get; private set; } = false; + public static bool ModelVisibility { get; private set; } = false; + public static LeapTrackingMode TrackingMode { get; private set; } = LeapTrackingMode.Desktop; + public static Vector3 RootAngle { get; private set; } = Vector3.zero; + public static bool HeadAttach { get; private set; } = false; + public static Vector3 HeadOffset { get; private set; } = new Vector3(0f, -0.3f, 0.15f); + public static bool TrackElbows { get; private set; } = true; + public static bool Input { get; private set; } = true; + public static float InteractThreadhold { get; private set; } = 0.8f; + public static float GripThreadhold { get; private set; } = 0.4f; static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; @@ -72,24 +72,24 @@ namespace ml_lme ms_entries = new List() { - ms_category.CreateEntry(ModSetting.Enabled.ToString(), ms_enabled), - ms_category.CreateEntry(ModSetting.DesktopX.ToString(), 0), - ms_category.CreateEntry(ModSetting.DesktopY.ToString(), -45), - ms_category.CreateEntry(ModSetting.DesktopZ.ToString(), 30), - ms_category.CreateEntry(ModSetting.FingersOnly.ToString(), ms_modelVisibility), - ms_category.CreateEntry(ModSetting.Model.ToString(), ms_modelVisibility), - ms_category.CreateEntry(ModSetting.Mode.ToString(), (int)ms_trackingMode), - ms_category.CreateEntry(ModSetting.AngleX.ToString(), 0), - ms_category.CreateEntry(ModSetting.AngleY.ToString(), 0), - ms_category.CreateEntry(ModSetting.AngleZ.ToString(), 0), - ms_category.CreateEntry(ModSetting.Head.ToString(), ms_headAttach), - ms_category.CreateEntry(ModSetting.HeadX.ToString(), 0), - ms_category.CreateEntry(ModSetting.HeadY.ToString(), -30), - ms_category.CreateEntry(ModSetting.HeadZ.ToString(), 15), - ms_category.CreateEntry(ModSetting.TrackElbows.ToString(), true), - ms_category.CreateEntry(ModSetting.Input.ToString(), true), - ms_category.CreateEntry(ModSetting.InteractThreadhold.ToString(), 80), - ms_category.CreateEntry(ModSetting.GripThreadhold.ToString(), 40), + ms_category.CreateEntry(ModSetting.Enabled.ToString(), Enabled), + ms_category.CreateEntry(ModSetting.DesktopX.ToString(), (int)(DesktopOffset.x * 100f)), + ms_category.CreateEntry(ModSetting.DesktopY.ToString(), (int)(DesktopOffset.y * 100f)), + ms_category.CreateEntry(ModSetting.DesktopZ.ToString(), (int)(DesktopOffset.z * 100f)), + ms_category.CreateEntry(ModSetting.FingersOnly.ToString(), FingersOnly), + ms_category.CreateEntry(ModSetting.Model.ToString(), ModelVisibility), + ms_category.CreateEntry(ModSetting.Mode.ToString(), (int)TrackingMode), + ms_category.CreateEntry(ModSetting.AngleX.ToString(), (int)(RootAngle.x * 100f)), + ms_category.CreateEntry(ModSetting.AngleY.ToString(), (int)(RootAngle.y * 100f)), + ms_category.CreateEntry(ModSetting.AngleZ.ToString(), (int)(RootAngle.z * 100f)), + ms_category.CreateEntry(ModSetting.Head.ToString(), HeadAttach), + ms_category.CreateEntry(ModSetting.HeadX.ToString(), (int)(HeadOffset.x * 100f)), + ms_category.CreateEntry(ModSetting.HeadY.ToString(), (int)(HeadOffset.y * 100f)), + ms_category.CreateEntry(ModSetting.HeadZ.ToString(), (int)(HeadOffset.z * 100f)), + ms_category.CreateEntry(ModSetting.TrackElbows.ToString(), TrackElbows), + ms_category.CreateEntry(ModSetting.Input.ToString(), Input), + ms_category.CreateEntry(ModSetting.InteractThreadhold.ToString(), (int)(InteractThreadhold * 100f)), + ms_category.CreateEntry(ModSetting.GripThreadhold.ToString(), (int)(GripThreadhold * 100f)), }; Load(); @@ -122,30 +122,30 @@ namespace ml_lme static void Load() { - ms_enabled = (bool)ms_entries[(int)ModSetting.Enabled].BoxedValue; - ms_desktopOffset = new Vector3( + Enabled = (bool)ms_entries[(int)ModSetting.Enabled].BoxedValue; + DesktopOffset = new Vector3( (int)ms_entries[(int)ModSetting.DesktopX].BoxedValue, (int)ms_entries[(int)ModSetting.DesktopY].BoxedValue, (int)ms_entries[(int)ModSetting.DesktopZ].BoxedValue ) * 0.01f; - ms_fingersOnly = (bool)ms_entries[(int)ModSetting.FingersOnly].BoxedValue; - ms_modelVisibility = (bool)ms_entries[(int)ModSetting.Model].BoxedValue; - ms_trackingMode = (LeapTrackingMode)(int)ms_entries[(int)ModSetting.Mode].BoxedValue; - ms_rootAngle = new Vector3( + FingersOnly = (bool)ms_entries[(int)ModSetting.FingersOnly].BoxedValue; + ModelVisibility = (bool)ms_entries[(int)ModSetting.Model].BoxedValue; + TrackingMode = (LeapTrackingMode)(int)ms_entries[(int)ModSetting.Mode].BoxedValue; + RootAngle = new Vector3( (int)ms_entries[(int)ModSetting.AngleX].BoxedValue, (int)ms_entries[(int)ModSetting.AngleY].BoxedValue, (int)ms_entries[(int)ModSetting.AngleZ].BoxedValue ); - ms_headAttach = (bool)ms_entries[(int)ModSetting.Head].BoxedValue; - ms_headOffset = new Vector3( + HeadAttach = (bool)ms_entries[(int)ModSetting.Head].BoxedValue; + HeadOffset = new Vector3( (int)ms_entries[(int)ModSetting.HeadX].BoxedValue, (int)ms_entries[(int)ModSetting.HeadY].BoxedValue, (int)ms_entries[(int)ModSetting.HeadZ].BoxedValue ) * 0.01f; - ms_trackElbows = (bool)ms_entries[(int)ModSetting.TrackElbows].BoxedValue; - ms_input = (bool)ms_entries[(int)ModSetting.Input].BoxedValue; - ms_interactThreadhold = (int)ms_entries[(int)ModSetting.InteractThreadhold].BoxedValue * 0.01f; - ms_gripThreadhold = (int)ms_entries[(int)ModSetting.GripThreadhold].BoxedValue * 0.01f; + TrackElbows = (bool)ms_entries[(int)ModSetting.TrackElbows].BoxedValue; + Input = (bool)ms_entries[(int)ModSetting.Input].BoxedValue; + InteractThreadhold = (int)ms_entries[(int)ModSetting.InteractThreadhold].BoxedValue * 0.01f; + GripThreadhold = (int)ms_entries[(int)ModSetting.GripThreadhold].BoxedValue * 0.01f; } static void OnToggleUpdate(string p_name, string p_value) @@ -156,43 +156,43 @@ namespace ml_lme { case ModSetting.Enabled: { - ms_enabled = bool.Parse(p_value); - EnabledChange?.Invoke(ms_enabled); + Enabled = bool.Parse(p_value); + EnabledChange?.Invoke(Enabled); } break; case ModSetting.FingersOnly: { - ms_fingersOnly = bool.Parse(p_value); - FingersOnlyChange?.Invoke(ms_fingersOnly); + FingersOnly = bool.Parse(p_value); + FingersOnlyChange?.Invoke(FingersOnly); } break; case ModSetting.Model: { - ms_modelVisibility = bool.Parse(p_value); - ModelVisibilityChange?.Invoke(ms_modelVisibility); + ModelVisibility = bool.Parse(p_value); + ModelVisibilityChange?.Invoke(ModelVisibility); } break; case ModSetting.Head: { - ms_headAttach = bool.Parse(p_value); - HeadAttachChange?.Invoke(ms_headAttach); + HeadAttach = bool.Parse(p_value); + HeadAttachChange?.Invoke(HeadAttach); } break; case ModSetting.TrackElbows: { - ms_trackElbows = bool.Parse(p_value); - TrackElbowsChange?.Invoke(ms_trackElbows); + TrackElbows = bool.Parse(p_value); + TrackElbowsChange?.Invoke(TrackElbows); } break; case ModSetting.Input: { - ms_input = bool.Parse(p_value); - InputChange?.Invoke(ms_input); + Input = bool.Parse(p_value); + InputChange?.Invoke(Input); } break; } @@ -209,72 +209,90 @@ namespace ml_lme { case ModSetting.DesktopX: { - ms_desktopOffset.x = int.Parse(p_value) * 0.01f; - DesktopOffsetChange?.Invoke(ms_desktopOffset); + Vector3 l_current = DesktopOffset; + l_current.x = int.Parse(p_value) * 0.01f; + DesktopOffset = l_current; + DesktopOffsetChange?.Invoke(l_current); } break; case ModSetting.DesktopY: { - ms_desktopOffset.y = int.Parse(p_value) * 0.01f; - DesktopOffsetChange?.Invoke(ms_desktopOffset); + Vector3 l_current = DesktopOffset; + l_current.y = int.Parse(p_value) * 0.01f; + DesktopOffset = l_current; + DesktopOffsetChange?.Invoke(l_current); } break; case ModSetting.DesktopZ: { - ms_desktopOffset.z = int.Parse(p_value) * 0.01f; - DesktopOffsetChange?.Invoke(ms_desktopOffset); + Vector3 l_current = DesktopOffset; + l_current.z = int.Parse(p_value) * 0.01f; + DesktopOffset = l_current; + DesktopOffsetChange?.Invoke(l_current); } break; case ModSetting.AngleX: { - ms_rootAngle.x = int.Parse(p_value); - RootAngleChange?.Invoke(ms_rootAngle); + Vector3 l_current = RootAngle; + l_current.x = int.Parse(p_value); + RootAngle = l_current; + RootAngleChange?.Invoke(l_current); } break; case ModSetting.AngleY: { - ms_rootAngle.y = int.Parse(p_value); - RootAngleChange?.Invoke(ms_rootAngle); + Vector3 l_current = RootAngle; + l_current.y = int.Parse(p_value); + RootAngle = l_current; + RootAngleChange?.Invoke(l_current); } break; case ModSetting.AngleZ: { - ms_rootAngle.z = int.Parse(p_value); - RootAngleChange?.Invoke(ms_rootAngle); + Vector3 l_current = RootAngle; + l_current.z = int.Parse(p_value); + RootAngle = l_current; + RootAngleChange?.Invoke(l_current); } break; case ModSetting.HeadX: { - ms_headOffset.x = int.Parse(p_value) * 0.01f; - HeadOffsetChange?.Invoke(ms_headOffset); + Vector3 l_current = HeadOffset; + l_current.x = int.Parse(p_value) * 0.01f; + HeadOffset = l_current; + HeadOffsetChange?.Invoke(l_current); } break; case ModSetting.HeadY: { - ms_headOffset.y = int.Parse(p_value) * 0.01f; - HeadOffsetChange?.Invoke(ms_headOffset); + Vector3 l_current = HeadOffset; + l_current.y = int.Parse(p_value) * 0.01f; + HeadOffset = l_current; + HeadOffsetChange?.Invoke(l_current); } break; case ModSetting.HeadZ: { - ms_headOffset.z = int.Parse(p_value) * 0.01f; - HeadOffsetChange?.Invoke(ms_headOffset); + Vector3 l_current = HeadOffset; + l_current.z = int.Parse(p_value) * 0.01f; + HeadOffset = l_current; + HeadOffsetChange?.Invoke(l_current); } break; case ModSetting.InteractThreadhold: { - ms_interactThreadhold = int.Parse(p_value) * 0.01f; - InteractThreadholdChange?.Invoke(ms_interactThreadhold); + InteractThreadhold = int.Parse(p_value) * 0.01f; + InteractThreadholdChange?.Invoke(InteractThreadhold); } break; case ModSetting.GripThreadhold: { - ms_gripThreadhold = int.Parse(p_value) * 0.01f; - GripThreadholdChange?.Invoke(ms_gripThreadhold); + GripThreadhold = int.Parse(p_value) * 0.01f; + GripThreadholdChange?.Invoke(GripThreadhold); } break; } @@ -291,8 +309,8 @@ namespace ml_lme { case ModSetting.Mode: { - ms_trackingMode = (LeapTrackingMode)int.Parse(p_value); - TrackingModeChange?.Invoke(ms_trackingMode); + TrackingMode = (LeapTrackingMode)int.Parse(p_value); + TrackingModeChange?.Invoke(TrackingMode); } break; } @@ -300,54 +318,5 @@ namespace ml_lme ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value); } } - - public static bool Enabled - { - get => ms_enabled; - } - public static Vector3 DesktopOffset - { - get => ms_desktopOffset; - } - public static bool FingersOnly - { - get => ms_fingersOnly; - } - public static bool ModelVisibility - { - get => ms_modelVisibility; - } - public static LeapTrackingMode TrackingMode - { - get => ms_trackingMode; - } - public static Vector3 RootAngle - { - get => ms_rootAngle; - } - public static bool HeadAttach - { - get => ms_headAttach; - } - public static Vector3 HeadOffset - { - get => ms_headOffset; - } - public static bool TrackElbows - { - get => ms_trackElbows; - } - public static bool Input - { - get => ms_input; - } - public static float InteractThreadhold - { - get => ms_interactThreadhold; - } - public static float GripThreadhold - { - get => ms_gripThreadhold; - } } } diff --git a/ml_lme/Utils.cs b/ml_lme/Utils.cs index a113e64..c41511e 100644 --- a/ml_lme/Utils.cs +++ b/ml_lme/Utils.cs @@ -1,6 +1,8 @@ using ABI_RC.Core.Player; +using ABI_RC.Core.Savior; using ABI_RC.Core.UI; using System.Linq; +using System.Reflection; using UnityEngine; namespace ml_lme @@ -9,9 +11,11 @@ namespace ml_lme { static readonly Quaternion ms_hmdRotationFix = new Quaternion(0f, 0.7071068f, 0.7071068f, 0f); static readonly Quaternion ms_screentopRotationFix = new Quaternion(0f, 0f, -1f, 0f); + static readonly FieldInfo ms_indexGestureToggle = typeof(InputModuleSteamVR).GetField("_steamVrIndexGestureToggleValue", BindingFlags.Instance | BindingFlags.NonPublic); - public static bool IsInVR() => ((ABI_RC.Core.Savior.CheckVR.Instance != null) && ABI_RC.Core.Savior.CheckVR.Instance.hasVrDeviceLoaded); + public static bool IsInVR() => ((CheckVR.Instance != null) && CheckVR.Instance.hasVrDeviceLoaded); public static bool AreKnucklesInUse() => PlayerSetup.Instance._trackerManager.trackerNames.Contains("knuckles"); + public static bool GetIndexGestureToggle(this InputModuleSteamVR p_module) => (bool)ms_indexGestureToggle.GetValue(p_module); public static bool IsLeftHandTracked() => ((VRTrackerManager.Instance.leftHand != null) && VRTrackerManager.Instance.leftHand.active); public static bool IsRightHandTracked() => ((VRTrackerManager.Instance.rightHand != null) && VRTrackerManager.Instance.rightHand.active); diff --git a/ml_pam/ArmMover.cs b/ml_pam/ArmMover.cs index 01db46d..d9c5f7f 100644 --- a/ml_pam/ArmMover.cs +++ b/ml_pam/ArmMover.cs @@ -32,6 +32,7 @@ namespace ml_pam Matrix4x4 m_offset = Matrix4x4.identity; bool m_targetActive = false; + // Unity events void Start() { m_inVR = Utils.IsInVR(); @@ -67,6 +68,7 @@ namespace ml_pam } } + // IK updates void OnIKPreUpdate() { m_armWeight.Set(m_vrIK.solver.rightArm.positionWeight, m_vrIK.solver.rightArm.rotationWeight); diff --git a/ml_pam/Settings.cs b/ml_pam/Settings.cs index c3fc659..488f2df 100644 --- a/ml_pam/Settings.cs +++ b/ml_pam/Settings.cs @@ -13,8 +13,8 @@ namespace ml_pam GrabOffset } - static bool ms_enabled = true; - static float ms_grabOffset = 0.25f; + public static bool Enabled { get; private set; } = true; + public static float GrabOffset { get; private set; } = 0.25f; static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; @@ -28,8 +28,8 @@ namespace ml_pam ms_entries = new List() { - ms_category.CreateEntry(ModSetting.Enabled.ToString(), ms_enabled), - ms_category.CreateEntry(ModSetting.GrabOffset.ToString(), 25), + ms_category.CreateEntry(ModSetting.Enabled.ToString(), Enabled), + ms_category.CreateEntry(ModSetting.GrabOffset.ToString(), (int)(GrabOffset * 100f)), }; Load(); @@ -61,8 +61,8 @@ namespace ml_pam static void Load() { - ms_enabled = (bool)ms_entries[(int)ModSetting.Enabled].BoxedValue; - ms_grabOffset = (int)ms_entries[(int)ModSetting.GrabOffset].BoxedValue * 0.01f; + Enabled = (bool)ms_entries[(int)ModSetting.Enabled].BoxedValue; + GrabOffset = (int)ms_entries[(int)ModSetting.GrabOffset].BoxedValue * 0.01f; } static void OnToggleUpdate(string p_name, string p_value) @@ -73,8 +73,8 @@ namespace ml_pam { case ModSetting.Enabled: { - ms_enabled = bool.Parse(p_value); - EnabledChange?.Invoke(ms_enabled); + Enabled = bool.Parse(p_value); + EnabledChange?.Invoke(Enabled); } break; } @@ -91,8 +91,8 @@ namespace ml_pam { case ModSetting.GrabOffset: { - ms_grabOffset = int.Parse(p_value) * 0.01f; - GrabOffsetChange?.Invoke(ms_grabOffset); + GrabOffset = int.Parse(p_value) * 0.01f; + GrabOffsetChange?.Invoke(GrabOffset); } break; } @@ -100,14 +100,5 @@ namespace ml_pam ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value); } } - - public static bool Enabled - { - get => ms_enabled; - } - public static float GrabOffset - { - get => ms_grabOffset; - } } } From ee8047ac3ed84f230c43f16ab5b8faef830fffb0 Mon Sep 17 00:00:00 2001 From: SDraw Date: Thu, 16 Mar 2023 10:00:01 +0300 Subject: [PATCH 02/63] Version bump --- README.md | 6 +++--- ml_dht/Properties/AssemblyInfo.cs | 6 +++--- ml_lme/Properties/AssemblyInfo.cs | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 9e1ab38..97400a0 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ Merged set of MelonLoader mods for ChilloutVR. -**State table for game build 2022r170:** +**State table for game build 2022r170p1:** | Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes | |-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------| | Avatar Change Info | ml_aci | 1.0.3 | Retired | Retired | Superseded by `Extended Game Notifications` | Avatar Motion Tweaker | ml_amt | 1.2.3 | Yes, update review | Working | -| Desktop Head Tracking | ml_dht | 1.1.1 | Yes | Working | +| Desktop Head Tracking | ml_dht | 1.1.2 | Yes | Working | | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | | Extended Game Notifications | ml_egn | 1.0.1 | Yes | Working | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update | Leap Motion Extension | ml_lme | 1.3.1 | Yes, update review | Working | -| Pickup Arm Movement | ml_pam | 1.0.1 | Retired, update review | Working | +| Pickup Arm Movement | ml_pam | 1.0.2 | Retired, update review | Working | | Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` diff --git a/ml_dht/Properties/AssemblyInfo.cs b/ml_dht/Properties/AssemblyInfo.cs index 8ec9bbb..6ccf6ab 100644 --- a/ml_dht/Properties/AssemblyInfo.cs +++ b/ml_dht/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("DesktopHeadTracking")] -[assembly: AssemblyVersion("1.1.1")] -[assembly: AssemblyFileVersion("1.1.1")] +[assembly: AssemblyVersion("1.1.2")] +[assembly: AssemblyFileVersion("1.1.2")] -[assembly: MelonLoader.MelonInfo(typeof(ml_dht.DesktopHeadTracking), "DesktopHeadTracking", "1.1.1", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_dht.DesktopHeadTracking), "DesktopHeadTracking", "1.1.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] \ No newline at end of file diff --git a/ml_lme/Properties/AssemblyInfo.cs b/ml_lme/Properties/AssemblyInfo.cs index c404034..a71b2c1 100644 --- a/ml_lme/Properties/AssemblyInfo.cs +++ b/ml_lme/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("LeapMotionExtension")] -[assembly: AssemblyVersion("1.3.1")] -[assembly: AssemblyFileVersion("1.3.1")] +[assembly: AssemblyVersion("1.3.2")] +[assembly: AssemblyFileVersion("1.3.2")] -[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.3.1", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.3.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] From da201e213511b8d06caf173fae98ea83be797221 Mon Sep 17 00:00:00 2001 From: SDraw Date: Fri, 17 Mar 2023 16:24:21 +0000 Subject: [PATCH 03/63] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 97400a0..1b5be58 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@ Merged set of MelonLoader mods for ChilloutVR. | Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes | |-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------| | Avatar Change Info | ml_aci | 1.0.3 | Retired | Retired | Superseded by `Extended Game Notifications` -| Avatar Motion Tweaker | ml_amt | 1.2.3 | Yes, update review | Working | +| Avatar Motion Tweaker | ml_amt | 1.2.3 | Yes | Working | | Desktop Head Tracking | ml_dht | 1.1.2 | Yes | Working | | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | | Extended Game Notifications | ml_egn | 1.0.1 | Yes | Working | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update -| Leap Motion Extension | ml_lme | 1.3.1 | Yes, update review | Working | -| Pickup Arm Movement | ml_pam | 1.0.2 | Retired, update review | Working | +| Leap Motion Extension | ml_lme | 1.3.2 | Yes | Working | +| Pickup Arm Movement | ml_pam | 1.0.1 | Yes | Working | | Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` From 2c67f02f7e7648132312edbc3c7f89e1d9a0b572 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 18 Mar 2023 01:35:14 +0300 Subject: [PATCH 04/63] Animator parameters save and restore --- ml_amt/AnimatorAnalyzer.cs | 71 +++++++++++++++++++++++++++++++ ml_amt/Main.cs | 13 +++--- ml_amt/Properties/AssemblyInfo.cs | 6 +-- ml_amt/ml_amt.csproj | 1 + 4 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 ml_amt/AnimatorAnalyzer.cs diff --git a/ml_amt/AnimatorAnalyzer.cs b/ml_amt/AnimatorAnalyzer.cs new file mode 100644 index 0000000..80c4531 --- /dev/null +++ b/ml_amt/AnimatorAnalyzer.cs @@ -0,0 +1,71 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace ml_amt +{ + class AnimatorAnalyzer + { + bool m_enabled = true; + List m_parameters = null; + + public void AnalyzeFrom(Animator p_animator) + { + m_enabled = p_animator.enabled; + m_parameters = p_animator.parameters?.ToList(); + + if(m_parameters != null) + { + foreach(var l_param in m_parameters) + { + switch(l_param.type) + { + case AnimatorControllerParameterType.Bool: + case AnimatorControllerParameterType.Trigger: + l_param.defaultBool = p_animator.GetBool(l_param.nameHash); + break; + case AnimatorControllerParameterType.Float: + l_param.defaultFloat = p_animator.GetFloat(l_param.nameHash); + break; + case AnimatorControllerParameterType.Int: + l_param.defaultInt = p_animator.GetInteger(l_param.nameHash); + break; + + } + } + } + } + + public void ApplyTo(Animator p_animator) + { + p_animator.enabled = m_enabled; + + if(m_parameters != null) + { + foreach(var l_param in m_parameters) + { + switch(l_param.type) + { + case AnimatorControllerParameterType.Bool: + p_animator.SetBool(l_param.nameHash, l_param.defaultBool); + break; + case AnimatorControllerParameterType.Float: + p_animator.SetFloat(l_param.nameHash, l_param.defaultFloat); + break; + case AnimatorControllerParameterType.Int: + p_animator.SetInteger(l_param.nameHash, l_param.defaultInt); + break; + case AnimatorControllerParameterType.Trigger: + { + if(l_param.defaultBool) + p_animator.SetTrigger(l_param.nameHash); + } + break; + } + } + } + } + + public bool IsEnabled() => m_enabled; + } +} diff --git a/ml_amt/Main.cs b/ml_amt/Main.cs index 05ecf6b..c913150 100644 --- a/ml_amt/Main.cs +++ b/ml_amt/Main.cs @@ -256,14 +256,15 @@ namespace ml_amt return false; } - static void OnOverride_Prefix(ref CVRAnimatorManager __instance, ref bool __state) + static void OnOverride_Prefix(ref CVRAnimatorManager __instance, out AnimatorAnalyzer __state) { + __state = new AnimatorAnalyzer(); try { if(Settings.OverrideFix && (__instance.animator != null)) { - __state = __instance.animator.enabled; - if(__state) + __state.AnalyzeFrom(__instance.animator); + if(__state.IsEnabled()) __instance.animator.enabled = false; __instance.animator.WriteDefaultValues(); } @@ -273,14 +274,14 @@ namespace ml_amt MelonLoader.MelonLogger.Error(l_exception); } } - static void OnOverride_Postfix(ref CVRAnimatorManager __instance, bool __state) + static void OnOverride_Postfix(ref CVRAnimatorManager __instance, AnimatorAnalyzer __state) { try { if(Settings.OverrideFix && (__instance.animator != null)) { - __instance.animator.enabled = __state; - if(__state) + __state.ApplyTo(__instance.animator); + if(__state.IsEnabled()) __instance.animator.Update(0f); } } diff --git a/ml_amt/Properties/AssemblyInfo.cs b/ml_amt/Properties/AssemblyInfo.cs index 1bbc069..9a84e96 100644 --- a/ml_amt/Properties/AssemblyInfo.cs +++ b/ml_amt/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("AvatarMotionTweaker")] -[assembly: AssemblyVersion("1.2.3")] -[assembly: AssemblyFileVersion("1.2.3")] +[assembly: AssemblyVersion("1.2.4")] +[assembly: AssemblyFileVersion("1.2.4")] -[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.2.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.2.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] \ No newline at end of file diff --git a/ml_amt/ml_amt.csproj b/ml_amt/ml_amt.csproj index bea6a67..cd4e2bc 100644 --- a/ml_amt/ml_amt.csproj +++ b/ml_amt/ml_amt.csproj @@ -75,6 +75,7 @@ + From 4112e6dab94d1a17a43729048c1803c2d7cb5a6e Mon Sep 17 00:00:00 2001 From: SDraw Date: Fri, 17 Mar 2023 22:38:28 +0000 Subject: [PATCH 05/63] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1b5be58..fd89337 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Merged set of MelonLoader mods for ChilloutVR. | Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes | |-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------| | Avatar Change Info | ml_aci | 1.0.3 | Retired | Retired | Superseded by `Extended Game Notifications` -| Avatar Motion Tweaker | ml_amt | 1.2.3 | Yes | Working | +| Avatar Motion Tweaker | ml_amt | 1.2.4 | Yes, update review | Working | | Desktop Head Tracking | ml_dht | 1.1.2 | Yes | Working | | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | | Extended Game Notifications | ml_egn | 1.0.1 | Yes | Working From 4b171bbbad19e6e2ce53cf90a06d081742960d62 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 18 Mar 2023 12:48:10 +0300 Subject: [PATCH 06/63] Remove collider state change --- ml_amt/Main.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ml_amt/Main.cs b/ml_amt/Main.cs index c913150..2c0deab 100644 --- a/ml_amt/Main.cs +++ b/ml_amt/Main.cs @@ -222,8 +222,6 @@ namespace ml_amt if(__0 || (Mathf.Abs(l_currentHeight - l_newHeight) > (l_currentHeight * 0.05f)) || (Vector3.Distance(l_currentCenter, l_newCenter) > (l_currentHeight * 0.05f))) { - bool l_active = ___controller.enabled; - if(__0) ___controller.radius = l_newRadius; ___controller.height = l_newHeight; @@ -243,8 +241,6 @@ namespace ml_amt __instance.forceObject.transform.localScale = new Vector3(l_newRadius + 0.1f, l_newHeight, l_newRadius + 0.1f); if(__instance.groundCheck != null) __instance.groundCheck.localPosition = ____colliderCenter; - - ___controller.enabled = l_active; } } } From c28b1dc82665b9839b206f47cb6d18bc3525f08d Mon Sep 17 00:00:00 2001 From: SDraw Date: Sun, 19 Mar 2023 14:26:09 +0300 Subject: [PATCH 07/63] Detecting destroyed pickup --- README.md | 2 +- ml_pam/ArmMover.cs | 11 ++++++++--- ml_pam/Properties/AssemblyInfo.cs | 6 +++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index fd89337..9d574f3 100644 --- a/README.md +++ b/README.md @@ -10,5 +10,5 @@ Merged set of MelonLoader mods for ChilloutVR. | Extended Game Notifications | ml_egn | 1.0.1 | Yes | Working | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update | Leap Motion Extension | ml_lme | 1.3.2 | Yes | Working | -| Pickup Arm Movement | ml_pam | 1.0.1 | Yes | Working | +| Pickup Arm Movement | ml_pam | 1.0.2 | Yes, update review| Working | | Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` diff --git a/ml_pam/ArmMover.cs b/ml_pam/ArmMover.cs index d9c5f7f..c9940ae 100644 --- a/ml_pam/ArmMover.cs +++ b/ml_pam/ArmMover.cs @@ -61,10 +61,15 @@ namespace ml_pam void Update() { - if(m_enabled && (m_pickup != null)) + if(m_enabled && !ReferenceEquals(m_pickup, null)) { - Matrix4x4 l_result = m_pickup.transform.GetMatrix() * m_offset; - m_target.position = l_result * ms_pointVector; + if(m_pickup != null) + { + Matrix4x4 l_result = m_pickup.transform.GetMatrix() * m_offset; + m_target.position = l_result * ms_pointVector; + } + else + this.OnPickupDrop(m_pickup); } } diff --git a/ml_pam/Properties/AssemblyInfo.cs b/ml_pam/Properties/AssemblyInfo.cs index 9a229fb..54ba674 100644 --- a/ml_pam/Properties/AssemblyInfo.cs +++ b/ml_pam/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("PickupArmMovement")] -[assembly: AssemblyVersion("1.0.1")] -[assembly: AssemblyFileVersion("1.0.1")] +[assembly: AssemblyVersion("1.0.2")] +[assembly: AssemblyFileVersion("1.0.2")] -[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.0.1", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.0.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPriority(1)] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] From 26fc42c850b4e125645c2a8e6de7a93399f3cd55 Mon Sep 17 00:00:00 2001 From: SDraw Date: Wed, 29 Mar 2023 12:10:15 +0300 Subject: [PATCH 08/63] Fix of fingers curls network sync --- README.md | 2 +- ml_lme/LeapInput.cs | 10 ++++++++++ ml_lme/Properties/AssemblyInfo.cs | 6 +++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9d574f3..5b3f57d 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,6 @@ Merged set of MelonLoader mods for ChilloutVR. | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | | Extended Game Notifications | ml_egn | 1.0.1 | Yes | Working | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update -| Leap Motion Extension | ml_lme | 1.3.2 | Yes | Working | +| Leap Motion Extension | ml_lme | 1.3.3 | Yes, update review | Working | | Pickup Arm Movement | ml_pam | 1.0.2 | Yes, update review| Working | | Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` diff --git a/ml_lme/LeapInput.cs b/ml_lme/LeapInput.cs index 6365a67..aa0cef4 100644 --- a/ml_lme/LeapInput.cs +++ b/ml_lme/LeapInput.cs @@ -261,6 +261,11 @@ namespace ml_lme m_inputManager.fingerCurlLeftMiddle = p_hand.m_bends[2]; m_inputManager.fingerCurlLeftRing = p_hand.m_bends[3]; m_inputManager.fingerCurlLeftPinky = p_hand.m_bends[4]; + IKSystem.Instance.FingerSystem.leftThumbCurl = p_hand.m_bends[0]; + IKSystem.Instance.FingerSystem.leftIndexCurl = p_hand.m_bends[1]; + IKSystem.Instance.FingerSystem.leftMiddleCurl = p_hand.m_bends[2]; + IKSystem.Instance.FingerSystem.leftRingCurl = p_hand.m_bends[3]; + IKSystem.Instance.FingerSystem.leftPinkyCurl = p_hand.m_bends[4]; } else { @@ -269,6 +274,11 @@ namespace ml_lme m_inputManager.fingerCurlRightMiddle = p_hand.m_bends[2]; m_inputManager.fingerCurlRightRing = p_hand.m_bends[3]; m_inputManager.fingerCurlRightPinky = p_hand.m_bends[4]; + IKSystem.Instance.FingerSystem.rightThumbCurl = p_hand.m_bends[0]; + IKSystem.Instance.FingerSystem.rightIndexCurl = p_hand.m_bends[1]; + IKSystem.Instance.FingerSystem.rightMiddleCurl = p_hand.m_bends[2]; + IKSystem.Instance.FingerSystem.rightRingCurl = p_hand.m_bends[3]; + IKSystem.Instance.FingerSystem.rightPinkyCurl = p_hand.m_bends[4]; } } diff --git a/ml_lme/Properties/AssemblyInfo.cs b/ml_lme/Properties/AssemblyInfo.cs index a71b2c1..2f6a005 100644 --- a/ml_lme/Properties/AssemblyInfo.cs +++ b/ml_lme/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("LeapMotionExtension")] -[assembly: AssemblyVersion("1.3.2")] -[assembly: AssemblyFileVersion("1.3.2")] +[assembly: AssemblyVersion("1.3.3")] +[assembly: AssemblyFileVersion("1.3.3")] -[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.3.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.3.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] From bc6e2894956e7dee9b878098738bd2da40b24010 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 8 Apr 2023 02:51:46 +0300 Subject: [PATCH 09/63] New mod - PlayerRagdollMod Update to MelonLoader 0.6.1 --- README.md | 1 + ml_amt/ml_amt.csproj.user | 2 +- ml_dht/ml_dht.csproj.user | 2 +- ml_drs/ml_drs.csproj | 8 +- ml_drs/ml_drs.csproj.user | 2 +- ml_egn/ml_egn.csproj.user | 2 +- ml_lme/ml_lme.csproj.user | 2 +- ml_mods_cvr.sln | 6 + ml_pam/ml_pam.csproj.user | 2 +- ml_prm/Main.cs | 98 ++++++++++++ ml_prm/Properties/AssemblyInfo.cs | 12 ++ ml_prm/README.md | 21 +++ ml_prm/RagdollController.cs | 246 +++++++++++++++++++++++++++++ ml_prm/Settings.cs | 79 +++++++++ ml_prm/Utils.cs | 18 +++ ml_prm/ml_prm.csproj | 140 ++++++++++++++++ ml_prm/ml_prm.csproj.user | 6 + ml_prm/vendor/RootMotion/ReadMe.md | 2 + 18 files changed, 640 insertions(+), 9 deletions(-) create mode 100644 ml_prm/Main.cs create mode 100644 ml_prm/Properties/AssemblyInfo.cs create mode 100644 ml_prm/README.md create mode 100644 ml_prm/RagdollController.cs create mode 100644 ml_prm/Settings.cs create mode 100644 ml_prm/Utils.cs create mode 100644 ml_prm/ml_prm.csproj create mode 100644 ml_prm/ml_prm.csproj.user create mode 100644 ml_prm/vendor/RootMotion/ReadMe.md diff --git a/README.md b/README.md index 5b3f57d..230bde6 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,5 @@ Merged set of MelonLoader mods for ChilloutVR. | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update | Leap Motion Extension | ml_lme | 1.3.3 | Yes, update review | Working | | Pickup Arm Movement | ml_pam | 1.0.2 | Yes, update review| Working | +| Player Ragdoll Mod | ml_prm | 1.0.0 | Yes, publish review | Working | | Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` diff --git a/ml_amt/ml_amt.csproj.user b/ml_amt/ml_amt.csproj.user index 04df561..d2e6c0a 100644 --- a/ml_amt/ml_amt.csproj.user +++ b/ml_amt/ml_amt.csproj.user @@ -1,6 +1,6 @@  - D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\;D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\ + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\;D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\ \ No newline at end of file diff --git a/ml_dht/ml_dht.csproj.user b/ml_dht/ml_dht.csproj.user index 04df561..d2e6c0a 100644 --- a/ml_dht/ml_dht.csproj.user +++ b/ml_dht/ml_dht.csproj.user @@ -1,6 +1,6 @@  - D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\;D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\ + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\;D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\ \ No newline at end of file diff --git a/ml_drs/ml_drs.csproj b/ml_drs/ml_drs.csproj index 41b71ab..3809559 100644 --- a/ml_drs/ml_drs.csproj +++ b/ml_drs/ml_drs.csproj @@ -35,6 +35,7 @@ False False + D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll C:\Games\Steam\common\ChilloutVR\ChilloutVR_Data\Managed\cohtml.Net.dll @@ -44,8 +45,9 @@ C:\Games\Steam\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll False - - C:\Games\Steam\common\ChilloutVR\MelonLoader\MelonLoader.dll + + False + D:\games\Steam\steamapps\common\ChilloutVR\MelonLoader\MelonLoader.dll False @@ -69,6 +71,6 @@ - copy /y "$(TargetPath)" "C:\Games\Steam\common\ChilloutVR\Mods\" + copy /y "$(TargetPath)" "D:\Games\Steam\steamapps\common\ChilloutVR\Mods\" \ No newline at end of file diff --git a/ml_drs/ml_drs.csproj.user b/ml_drs/ml_drs.csproj.user index 2539084..5c67b34 100644 --- a/ml_drs/ml_drs.csproj.user +++ b/ml_drs/ml_drs.csproj.user @@ -1,6 +1,6 @@  - C:\Games\Steam\common\ChilloutVR\MelonLoader\;C:\Games\Steam\common\ChilloutVR\ChilloutVR_Data\Managed\ + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\;D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\ \ No newline at end of file diff --git a/ml_egn/ml_egn.csproj.user b/ml_egn/ml_egn.csproj.user index 04df561..d2e6c0a 100644 --- a/ml_egn/ml_egn.csproj.user +++ b/ml_egn/ml_egn.csproj.user @@ -1,6 +1,6 @@  - D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\;D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\ + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\;D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\ \ No newline at end of file diff --git a/ml_lme/ml_lme.csproj.user b/ml_lme/ml_lme.csproj.user index 04df561..d2e6c0a 100644 --- a/ml_lme/ml_lme.csproj.user +++ b/ml_lme/ml_lme.csproj.user @@ -1,6 +1,6 @@  - D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\;D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\ + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\;D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\ \ No newline at end of file diff --git a/ml_mods_cvr.sln b/ml_mods_cvr.sln index d9193c5..19f4b60 100644 --- a/ml_mods_cvr.sln +++ b/ml_mods_cvr.sln @@ -15,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ml_egn", "ml_egn\ml_egn.csp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ml_pam", "ml_pam\ml_pam.csproj", "{3B5028DE-8C79-40DF-A1EF-BDB29D366125}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ml_prm", "ml_prm\ml_prm.csproj", "{ABD2A720-2DE8-4EB3-BFC2-8F1C3D2ADA15}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -45,6 +47,10 @@ Global {3B5028DE-8C79-40DF-A1EF-BDB29D366125}.Debug|x64.Build.0 = Debug|x64 {3B5028DE-8C79-40DF-A1EF-BDB29D366125}.Release|x64.ActiveCfg = Release|x64 {3B5028DE-8C79-40DF-A1EF-BDB29D366125}.Release|x64.Build.0 = Release|x64 + {ABD2A720-2DE8-4EB3-BFC2-8F1C3D2ADA15}.Debug|x64.ActiveCfg = Debug|x64 + {ABD2A720-2DE8-4EB3-BFC2-8F1C3D2ADA15}.Debug|x64.Build.0 = Debug|x64 + {ABD2A720-2DE8-4EB3-BFC2-8F1C3D2ADA15}.Release|x64.ActiveCfg = Release|x64 + {ABD2A720-2DE8-4EB3-BFC2-8F1C3D2ADA15}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ml_pam/ml_pam.csproj.user b/ml_pam/ml_pam.csproj.user index 04df561..d2e6c0a 100644 --- a/ml_pam/ml_pam.csproj.user +++ b/ml_pam/ml_pam.csproj.user @@ -1,6 +1,6 @@  - D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\;D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\ + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\;D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\ \ No newline at end of file diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs new file mode 100644 index 0000000..806d6e2 --- /dev/null +++ b/ml_prm/Main.cs @@ -0,0 +1,98 @@ +using ABI_RC.Core.Player; +using System; +using System.Reflection; +using ABI_RC.Core.InteractionSystem; +using UnityEngine; + +namespace ml_prm +{ + public class PlayerRagdollMod : MelonLoader.MelonMod + { + static PlayerRagdollMod ms_instance = null; + + RagdollController m_localController = null; + + public override void OnInitializeMelon() + { + if(ms_instance == null) + ms_instance = this; + + Settings.Init(); + + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)), + null, + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.NonPublic | BindingFlags.Static)) + ); + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)), + null, + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + HarmonyInstance.Patch( + typeof(CVRSeat).GetMethod(nameof(CVRSeat.SitDown)), + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnCVRSeatSitDown_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + null + ); + + MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); + } + + public override void OnDeinitializeMelon() + { + if(ms_instance == this) + ms_instance = null; + } + + System.Collections.IEnumerator WaitForLocalPlayer() + { + while(PlayerSetup.Instance == null) + yield return null; + + m_localController = PlayerSetup.Instance.gameObject.AddComponent(); + } + + static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear(); + void OnAvatarClear() + { + try + { + if(m_localController != null) + m_localController.OnAvatarClear(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnSetupAvatar_Postfix() => ms_instance?.OnSetupAvatar(); + void OnSetupAvatar() + { + try + { + if(m_localController != null) + m_localController.OnAvatarSetup(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnCVRSeatSitDown_Prefix(ref CVRSeat __instance) => ms_instance?.OnCVRSeatSitDown(__instance); + void OnCVRSeatSitDown(CVRSeat p_seat) + { + try + { + if(m_localController != null) + m_localController.OnSeatSitDown(p_seat); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + } +} diff --git a/ml_prm/Properties/AssemblyInfo.cs b/ml_prm/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9e478a5 --- /dev/null +++ b/ml_prm/Properties/AssemblyInfo.cs @@ -0,0 +1,12 @@ +using System.Reflection; + +[assembly: AssemblyTitle("PlayerRagdollMod")] +[assembly: AssemblyVersion("1.0.0")] +[assembly: AssemblyFileVersion("1.0.0")] + +[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.0.0", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonGame(null, "ChilloutVR")] +[assembly: MelonLoader.MelonPriority(2)] +[assembly: MelonLoader.MelonOptionalDependencies("BTKUILib")] +[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] \ No newline at end of file diff --git a/ml_prm/README.md b/ml_prm/README.md new file mode 100644 index 0000000..9958531 --- /dev/null +++ b/ml_prm/README.md @@ -0,0 +1,21 @@ +# Player Ragdoll Mod +This mod turns your player's avatar into ragdoll puppet. + +# Installation +* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader) +* Get [latest release DLL](../../../releases/latest): + * Put `ml_prm.dll` in `Mods` folder of game + +# Usage +* Press `R` to turn into ragdoll and back. + +Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUILib): +* **Switch ragdoll:** turns into ragdoll state and back, made for VR usage primarily. +* **Use hotkey:** enables/disables ragdoll state switch with `R` key; `true` by default. +* **Restore position:** returns to position of ragdoll state activation upon ragdoll state exit; `false` by default. +* **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. + +# Notes +* Incompatible with `Follow hips on IK override` option in AvatarMotionTweaker. +* Even if locally ragdoll state is activated in the middle of playing emote, remote players still see whole emote animation. +* Not suggested to activate fly mode with enabled ragdoll state. diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs new file mode 100644 index 0000000..4615da4 --- /dev/null +++ b/ml_prm/RagdollController.cs @@ -0,0 +1,246 @@ +using ABI_RC.Core.InteractionSystem; +using ABI_RC.Core.Player; +using ABI_RC.Systems.MovementSystem; +using RootMotion.Dynamics; +using RootMotion.FinalIK; +using System.Collections.Generic; +using UnityEngine; + +namespace ml_prm +{ + class RagdollController : MonoBehaviour + { + VRIK m_vrIK = null; + float m_vrIkWeight = 1f; + + bool m_enabled = false; + + readonly List m_rigidBodies = null; + readonly List m_colliders = null; + Transform m_puppetRoot = null; + Transform m_puppet = null; + BipedRagdollReferences m_puppetReferences; + BipedRagdollReferences m_avatarReferences; + readonly List> m_boneLinks = null; + + bool m_avatarReady = false; + Vector3 m_lastPosition = Vector3.zero; + Vector3 m_velocity = Vector3.zero; + + internal RagdollController() + { + m_rigidBodies = new List(); + m_colliders = new List(); + m_boneLinks = new List>(); + } + + // Unity events + void Start() + { + m_puppetRoot = new GameObject("[PlayerAvatarPuppet]").transform; + m_puppetRoot.parent = PlayerSetup.Instance.transform; + m_puppetRoot.localPosition = Vector3.zero; + m_puppetRoot.localRotation = Quaternion.identity; + + Settings.SwitchChange += this.SwitchRagdoll; + } + + void OnDestroy() + { + Settings.SwitchChange -= this.SwitchRagdoll; + } + + void Update() + { + Vector3 l_pos = PlayerSetup.Instance.transform.position; + m_velocity = (m_velocity + (l_pos - m_lastPosition) / Time.deltaTime) * 0.5f; + m_lastPosition = l_pos; + + if(Settings.Hotkey && Input.GetKeyDown(KeyCode.R) && !ViewManager.Instance.isGameMenuOpen()) + SwitchRagdoll(); + } + + void LateUpdate() + { + if(m_enabled && m_avatarReady) + { + foreach(var l_link in m_boneLinks) + l_link.Item1.CopyGlobal(l_link.Item2); + } + } + + // Game events + internal void OnAvatarClear() + { + if(m_enabled) + MovementSystem.Instance.SetImmobilized(false); + + if(m_puppet != null) + Object.Destroy(m_puppet.gameObject); + m_puppet = null; + + m_vrIK = null; + m_enabled = false; + m_avatarReady = false; + m_rigidBodies.Clear(); + m_colliders.Clear(); + m_avatarReferences = new BipedRagdollReferences(); + m_puppetReferences = new BipedRagdollReferences(); + m_boneLinks.Clear(); + } + + internal void OnAvatarSetup() + { + if(PlayerSetup.Instance._animator.isHuman) + { + m_avatarReferences = BipedRagdollReferences.FromAvatar(PlayerSetup.Instance._animator); + + m_puppet = new GameObject("Root").transform; + m_puppet.parent = m_puppetRoot; + m_puppet.localPosition = Vector3.zero; + m_puppet.localRotation = Quaternion.identity; + + m_puppetReferences.root = m_puppet; + m_puppetReferences.hips = CloneTransform(m_avatarReferences.hips, m_puppetReferences.root, "Hips"); + m_puppetReferences.spine = CloneTransform(m_avatarReferences.spine, m_puppetReferences.hips, "Spine"); + m_puppetReferences.chest = CloneTransform(m_avatarReferences.chest, m_puppetReferences.spine, "Chest"); + m_puppetReferences.head = CloneTransform(m_avatarReferences.head, m_puppetReferences.chest, "Head"); + + m_puppetReferences.leftUpperArm = CloneTransform(m_avatarReferences.leftUpperArm, m_puppetReferences.chest, "LeftUpperArm"); + m_puppetReferences.leftLowerArm = CloneTransform(m_avatarReferences.leftLowerArm, m_puppetReferences.leftUpperArm, "LeftLowerArm"); + m_puppetReferences.leftHand = CloneTransform(m_avatarReferences.leftHand, m_puppetReferences.leftLowerArm, "LeftHand"); + + m_puppetReferences.rightUpperArm = CloneTransform(m_avatarReferences.rightUpperArm, m_puppetReferences.chest, "RightUpperArm"); + m_puppetReferences.rightLowerArm = CloneTransform(m_avatarReferences.rightLowerArm, m_puppetReferences.rightUpperArm, "RightLowerArm"); + m_puppetReferences.rightHand = CloneTransform(m_avatarReferences.rightHand, m_puppetReferences.rightLowerArm, "RightHand"); + + m_puppetReferences.leftUpperLeg = CloneTransform(m_avatarReferences.leftUpperLeg, m_puppetReferences.hips, "LeftUpperLeg"); + m_puppetReferences.leftLowerLeg = CloneTransform(m_avatarReferences.leftLowerLeg, m_puppetReferences.leftUpperLeg, "LeftLowerLeg"); + m_puppetReferences.leftFoot = CloneTransform(m_avatarReferences.leftFoot, m_puppetReferences.leftLowerLeg, "LeftFoot"); + + m_puppetReferences.rightUpperLeg = CloneTransform(m_avatarReferences.rightUpperLeg, m_puppetReferences.hips, "RightUpperLeg"); + m_puppetReferences.rightLowerLeg = CloneTransform(m_avatarReferences.rightLowerLeg, m_puppetReferences.rightUpperLeg, "RightLowerLeg"); + m_puppetReferences.rightFoot = CloneTransform(m_avatarReferences.rightFoot, m_puppetReferences.rightLowerLeg, "RightFoot"); + + BipedRagdollCreator.Options l_options = BipedRagdollCreator.AutodetectOptions(m_puppetReferences); + l_options.joints = RagdollCreator.JointType.Character; + BipedRagdollCreator.Create(m_puppetReferences, l_options); + + Transform[] l_puppetTransforms = m_puppetReferences.GetRagdollTransforms(); + Transform[] l_avatarTransforms = m_avatarReferences.GetRagdollTransforms(); + for(int i = 0; i < l_puppetTransforms.Length; i++) + { + if(l_puppetTransforms[i] != null) + { + Rigidbody l_body = l_puppetTransforms[i].GetComponent(); + if(l_body != null) + { + m_rigidBodies.Add(l_body); + l_body.isKinematic = true; + l_body.angularDrag = 0.5f; + l_body.drag = 1.0f; + l_body.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; + } + + CharacterJoint l_joint = l_puppetTransforms[i].GetComponent(); + if(l_joint != null) + { + l_joint.enablePreprocessing = false; + l_joint.enableProjection = true; + } + + Collider l_collider = l_puppetTransforms[i].GetComponent(); + if(l_collider != null) + { + Physics.IgnoreCollision(MovementSystem.Instance.proxyCollider, l_collider, true); + l_collider.enabled = false; + m_colliders.Add(l_collider); + } + + if(l_avatarTransforms[i] != null) + m_boneLinks.Add(System.Tuple.Create(l_puppetTransforms[i], l_avatarTransforms[i])); + } + } + + m_vrIK = PlayerSetup.Instance._avatar.GetComponent(); + if(m_vrIK != null) + { + m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreUpdate); + m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostUpdate); + } + + m_avatarReady = true; + } + } + + internal void OnSeatSitDown(CVRSeat p_seat) + { + if(m_enabled && m_avatarReady && !p_seat.occupied) + SwitchRagdoll(); + } + + // IK updates + void OnIKPreUpdate() + { + if(m_enabled) + { + m_vrIkWeight = m_vrIK.solver.IKPositionWeight; + m_vrIK.solver.IKPositionWeight = 0f; + } + } + void OnIKPostUpdate() + { + if(m_enabled) + m_vrIK.solver.IKPositionWeight = m_vrIkWeight; + } + + // Arbitrary + public void SwitchRagdoll() + { + if(m_avatarReady && (MovementSystem.Instance.lastSeat == null)) + { + m_enabled = !m_enabled; + + MovementSystem.Instance.SetImmobilized(m_enabled); + + if(m_enabled) + { + foreach(var l_link in m_boneLinks) + l_link.Item2.CopyGlobal(l_link.Item1); + + foreach(Rigidbody l_body in m_rigidBodies) + l_body.isKinematic = false; + + Vector3 l_velocity = m_velocity * Settings.Multiplier; + foreach(Rigidbody l_body in m_rigidBodies) + { + l_body.velocity = l_velocity; + l_body.angularVelocity = Vector3.zero; + } + } + else + { + foreach(Rigidbody l_body in m_rigidBodies) + l_body.isKinematic = true; + + if(!Settings.RestorePosition && (m_puppetReferences.hips != null)) + { + Vector3 l_pos = m_puppetReferences.hips.position; + PlayerSetup.Instance.transform.position = l_pos; + } + } + + foreach(Collider l_collider in m_colliders) + l_collider.enabled = m_enabled; + } + } + + static Transform CloneTransform(Transform p_source, Transform p_parent, string p_name) + { + Transform l_target = new GameObject(p_name).transform; + l_target.parent = p_parent; + p_source.CopyGlobal(l_target); + return l_target; + } + } +} diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs new file mode 100644 index 0000000..ea68fa3 --- /dev/null +++ b/ml_prm/Settings.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ml_prm +{ + static class Settings + { + public enum ModSetting + { + Hotkey = 0, + Multiplier, + RestorePosition + } + + public static bool Hotkey { get; private set; } = true; + public static float Multiplier { get; private set; } = 2f; + public static bool RestorePosition { get; private set; } = false; + + static public event Action SwitchChange; + static public event Action HotkeyChange; + static public event Action RestorePositionChange; + static public event Action MultiplierChange; + + static MelonLoader.MelonPreferences_Category ms_category = null; + static List ms_entries = null; + + internal static void Init() + { + ms_category = MelonLoader.MelonPreferences.CreateCategory("PRM"); + ms_entries = new List() + { + ms_category.CreateEntry(ModSetting.Hotkey.ToString(), Hotkey), + ms_category.CreateEntry(ModSetting.Multiplier.ToString(), Multiplier), + ms_category.CreateEntry(ModSetting.RestorePosition.ToString(), RestorePosition), + }; + + Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; + Multiplier = (float)ms_entries[(int)ModSetting.Multiplier].BoxedValue; + RestorePosition = (bool)ms_entries[(int)ModSetting.RestorePosition].BoxedValue; + + if(MelonLoader.MelonMod.RegisteredMelons.First(m => m.Info.Name == "BTKUILib") != null) + { + CreateBtkUi(); + } + } + + static void CreateBtkUi() + { + var l_categoryMain = BTKUILib.QuickMenuAPI.MiscTabPage.AddCategory("PlayerRagdollMod"); + var l_page = l_categoryMain.AddPage("Player Ragdoll Settings", "", "PlayerRagdollMod settings", "PlayerRagdollMod"); + l_page.MenuTitle = "Ragdoll settings"; + var l_categoryMod = l_page.AddCategory("Settings"); + + l_categoryMod.AddButton("Switch ragdoll", "", "Switch between normal and ragdoll state").OnPress += () => + { + SwitchChange?.Invoke(); + }; + l_categoryMod.AddToggle("Use hotkey", "Switch ragdoll mode with 'R' key", Hotkey).OnValueUpdated += (state) => + { + Hotkey = state; + ms_entries[(int)ModSetting.Hotkey].BoxedValue = state; + HotkeyChange?.Invoke(Hotkey); + }; + l_categoryMod.AddToggle("Restore position", "Bring avatar back where ragdoll state was activated", RestorePosition).OnValueUpdated += (state) => + { + RestorePosition = state; + ms_entries[(int)ModSetting.RestorePosition].BoxedValue = state; + RestorePositionChange?.Invoke(Hotkey); + }; + l_page.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", Multiplier, 1f, 50f).OnValueUpdated += (value) => + { + Multiplier = value; + ms_entries[(int)ModSetting.Multiplier].BoxedValue = value; + MultiplierChange?.Invoke(value); + }; + } + } +} diff --git a/ml_prm/Utils.cs b/ml_prm/Utils.cs new file mode 100644 index 0000000..76fa779 --- /dev/null +++ b/ml_prm/Utils.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace ml_prm +{ + static class Utils + { + public static void CopyGlobal(this Transform p_source, Transform p_target) + { + p_target.position = p_source.position; + p_target.rotation = p_source.rotation; + } + } +} diff --git a/ml_prm/ml_prm.csproj b/ml_prm/ml_prm.csproj new file mode 100644 index 0000000..8c2917c --- /dev/null +++ b/ml_prm/ml_prm.csproj @@ -0,0 +1,140 @@ + + + + + Debug + AnyCPU + {ABD2A720-2DE8-4EB3-BFC2-8F1C3D2ADA15} + Library + Properties + ml_prm + ml_prm + v4.7.2 + 512 + true + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + + False + D:\games\Steam\steamapps\common\ChilloutVR\MelonLoader\0Harmony.dll + False + + + False + False + + + False + False + + + D:\games\Steam\steamapps\common\ChilloutVR\Mods\BTKUILib.dll + False + + + False + D:\games\Steam\steamapps\common\ChilloutVR\MelonLoader\MelonLoader.dll + False + + + + + + + + + + False + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AnimationModule.dll + False + + + False + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.ClothModule.dll + False + + + False + False + + + False + False + + + False + D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.PhysicsModule.dll + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + copy /y "$(TargetPath)" "D:\Games\Steam\steamapps\common\ChilloutVR\Mods\" + + \ No newline at end of file diff --git a/ml_prm/ml_prm.csproj.user b/ml_prm/ml_prm.csproj.user new file mode 100644 index 0000000..4d08fe9 --- /dev/null +++ b/ml_prm/ml_prm.csproj.user @@ -0,0 +1,6 @@ + + + + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\;D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\;D:\Games\Steam\steamapps\common\ChilloutVR\Mods\ + + \ No newline at end of file diff --git a/ml_prm/vendor/RootMotion/ReadMe.md b/ml_prm/vendor/RootMotion/ReadMe.md new file mode 100644 index 0000000..5455e7a --- /dev/null +++ b/ml_prm/vendor/RootMotion/ReadMe.md @@ -0,0 +1,2 @@ +* Buy https://assetstore.unity.com/packages/tools/physics/puppetmaster-48977 +* Put `PuppetMaster` and `RagdollManager` scripts in this folder From 78ca550e64f13f7ef778902fa3220dbb8d6f1cef Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 8 Apr 2023 03:20:14 +0300 Subject: [PATCH 10/63] Chest is optional bone --- ml_prm/README.md | 2 +- ml_prm/RagdollController.cs | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ml_prm/README.md b/ml_prm/README.md index 9958531..6c2ff7f 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -1,5 +1,5 @@ # Player Ragdoll Mod -This mod turns your player's avatar into ragdoll puppet. +This mod turns player's avatar into ragdoll puppet. # Installation * Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader) diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 4615da4..9a07436 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -103,14 +103,17 @@ namespace ml_prm m_puppetReferences.root = m_puppet; m_puppetReferences.hips = CloneTransform(m_avatarReferences.hips, m_puppetReferences.root, "Hips"); m_puppetReferences.spine = CloneTransform(m_avatarReferences.spine, m_puppetReferences.hips, "Spine"); - m_puppetReferences.chest = CloneTransform(m_avatarReferences.chest, m_puppetReferences.spine, "Chest"); - m_puppetReferences.head = CloneTransform(m_avatarReferences.head, m_puppetReferences.chest, "Head"); - m_puppetReferences.leftUpperArm = CloneTransform(m_avatarReferences.leftUpperArm, m_puppetReferences.chest, "LeftUpperArm"); + if(m_avatarReferences.chest != null) + m_puppetReferences.chest = CloneTransform(m_avatarReferences.chest, m_puppetReferences.spine, "Chest"); + + m_puppetReferences.head = CloneTransform(m_avatarReferences.head, (m_puppetReferences.chest != null) ? m_puppetReferences.chest : m_puppetReferences.spine, "Head"); + + m_puppetReferences.leftUpperArm = CloneTransform(m_avatarReferences.leftUpperArm, (m_puppetReferences.chest != null) ? m_puppetReferences.chest : m_puppetReferences.spine, "LeftUpperArm"); m_puppetReferences.leftLowerArm = CloneTransform(m_avatarReferences.leftLowerArm, m_puppetReferences.leftUpperArm, "LeftLowerArm"); m_puppetReferences.leftHand = CloneTransform(m_avatarReferences.leftHand, m_puppetReferences.leftLowerArm, "LeftHand"); - m_puppetReferences.rightUpperArm = CloneTransform(m_avatarReferences.rightUpperArm, m_puppetReferences.chest, "RightUpperArm"); + m_puppetReferences.rightUpperArm = CloneTransform(m_avatarReferences.rightUpperArm, (m_puppetReferences.chest != null) ? m_puppetReferences.chest : m_puppetReferences.spine, "RightUpperArm"); m_puppetReferences.rightLowerArm = CloneTransform(m_avatarReferences.rightLowerArm, m_puppetReferences.rightUpperArm, "RightLowerArm"); m_puppetReferences.rightHand = CloneTransform(m_avatarReferences.rightHand, m_puppetReferences.rightLowerArm, "RightHand"); From f08adb8f5361d46cd9dfc2fe8c146bf72515d758 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 8 Apr 2023 15:45:48 +0300 Subject: [PATCH 11/63] Drag, angular drag and gravity settings --- ml_prm/Main.cs | 27 ++++++++++++++++-- ml_prm/RagdollController.cs | 48 +++++++++++++++++++++++++++++--- ml_prm/Settings.cs | 55 +++++++++++++++++++++++++++++-------- ml_prm/Utils.cs | 7 +---- 4 files changed, 113 insertions(+), 24 deletions(-) diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs index 806d6e2..1734a54 100644 --- a/ml_prm/Main.cs +++ b/ml_prm/Main.cs @@ -1,8 +1,8 @@ -using ABI_RC.Core.Player; +using ABI_RC.Core.InteractionSystem; +using ABI_RC.Core.Player; +using ABI_RC.Systems.IK.SubSystems; using System; using System.Reflection; -using ABI_RC.Core.InteractionSystem; -using UnityEngine; namespace ml_prm { @@ -34,6 +34,11 @@ namespace ml_prm new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnCVRSeatSitDown_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), null ); + HarmonyInstance.Patch( + typeof(BodySystem).GetMethod(nameof(BodySystem.StartCalibration)), + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnStartCalibration_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + null + ); MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); } @@ -42,6 +47,8 @@ namespace ml_prm { if(ms_instance == this) ms_instance = null; + + m_localController = null; } System.Collections.IEnumerator WaitForLocalPlayer() @@ -94,5 +101,19 @@ namespace ml_prm } } + static void OnStartCalibration_Prefix() => ms_instance?.OnStartCalibration(); + void OnStartCalibration() + { + try + { + if(m_localController != null) + m_localController.OnStartCalibration(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + } } diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 9a07436..86fbba2 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -1,5 +1,6 @@ using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Player; +using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.MovementSystem; using RootMotion.Dynamics; using RootMotion.FinalIK; @@ -43,11 +44,17 @@ namespace ml_prm m_puppetRoot.localRotation = Quaternion.identity; Settings.SwitchChange += this.SwitchRagdoll; + Settings.MovementDragChange += this.OnMovementDragChange; + Settings.AngularDragChange += this.OnAngularDragChange; + Settings.GravityChange += this.OnGravityChange; } void OnDestroy() { Settings.SwitchChange -= this.SwitchRagdoll; + Settings.MovementDragChange -= this.OnMovementDragChange; + Settings.AngularDragChange -= this.OnAngularDragChange; + Settings.GravityChange -= this.OnGravityChange; } void Update() @@ -140,8 +147,9 @@ namespace ml_prm { m_rigidBodies.Add(l_body); l_body.isKinematic = true; - l_body.angularDrag = 0.5f; - l_body.drag = 1.0f; + l_body.angularDrag = Settings.AngularDrag; + l_body.drag = Settings.MovementDrag; + l_body.useGravity = Settings.Gravity; l_body.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; } @@ -182,6 +190,12 @@ namespace ml_prm SwitchRagdoll(); } + internal void OnStartCalibration() + { + if(m_enabled && m_avatarReady) + SwitchRagdoll(); + } + // IK updates void OnIKPreUpdate() { @@ -197,10 +211,36 @@ namespace ml_prm m_vrIK.solver.IKPositionWeight = m_vrIkWeight; } + // Settings + void OnMovementDragChange(float p_value) + { + if(m_avatarReady) + { + foreach(Rigidbody l_body in m_rigidBodies) + l_body.drag = p_value; + } + } + void OnAngularDragChange(float p_value) + { + if(m_avatarReady) + { + foreach(Rigidbody l_body in m_rigidBodies) + l_body.angularDrag = p_value; + } + } + void OnGravityChange(bool p_state) + { + if(m_avatarReady) + { + foreach(Rigidbody l_body in m_rigidBodies) + l_body.useGravity = p_state; + } + } + // Arbitrary public void SwitchRagdoll() { - if(m_avatarReady && (MovementSystem.Instance.lastSeat == null)) + if(m_avatarReady && (MovementSystem.Instance.lastSeat == null) && !BodySystem.isCalibrating) { m_enabled = !m_enabled; @@ -214,7 +254,7 @@ namespace ml_prm foreach(Rigidbody l_body in m_rigidBodies) l_body.isKinematic = false; - Vector3 l_velocity = m_velocity * Settings.Multiplier; + Vector3 l_velocity = m_velocity * Settings.VelocityMultiplier; foreach(Rigidbody l_body in m_rigidBodies) { l_body.velocity = l_velocity; diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index ea68fa3..438d6c9 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -9,18 +9,27 @@ namespace ml_prm public enum ModSetting { Hotkey = 0, - Multiplier, - RestorePosition + VelocityMultiplier, + RestorePosition, + MovementDrag, + AngularDrag, + Gravity } public static bool Hotkey { get; private set; } = true; - public static float Multiplier { get; private set; } = 2f; + public static float VelocityMultiplier { get; private set; } = 2f; public static bool RestorePosition { get; private set; } = false; + public static float MovementDrag { get; private set; } = 1f; + public static float AngularDrag { get; private set; } = 0.5f; + public static bool Gravity { get; private set; } = true; static public event Action SwitchChange; static public event Action HotkeyChange; static public event Action RestorePositionChange; - static public event Action MultiplierChange; + static public event Action VelocityMultiplierChange; + static public event Action MovementDragChange; + static public event Action AngularDragChange; + static public event Action GravityChange; static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; @@ -31,13 +40,19 @@ namespace ml_prm ms_entries = new List() { ms_category.CreateEntry(ModSetting.Hotkey.ToString(), Hotkey), - ms_category.CreateEntry(ModSetting.Multiplier.ToString(), Multiplier), + ms_category.CreateEntry(ModSetting.VelocityMultiplier.ToString(), VelocityMultiplier), ms_category.CreateEntry(ModSetting.RestorePosition.ToString(), RestorePosition), + ms_category.CreateEntry(ModSetting.MovementDrag.ToString(), MovementDrag), + ms_category.CreateEntry(ModSetting.AngularDrag.ToString(), AngularDrag), + ms_category.CreateEntry(ModSetting.Gravity.ToString(), Gravity), }; Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; - Multiplier = (float)ms_entries[(int)ModSetting.Multiplier].BoxedValue; + VelocityMultiplier = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue, 0f, 50f); RestorePosition = (bool)ms_entries[(int)ModSetting.RestorePosition].BoxedValue; + MovementDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 100f); + AngularDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0.5f, 50f); + Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue; if(MelonLoader.MelonMod.RegisteredMelons.First(m => m.Info.Name == "BTKUILib") != null) { @@ -66,13 +81,31 @@ namespace ml_prm { RestorePosition = state; ms_entries[(int)ModSetting.RestorePosition].BoxedValue = state; - RestorePositionChange?.Invoke(Hotkey); + RestorePositionChange?.Invoke(RestorePosition); }; - l_page.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", Multiplier, 1f, 50f).OnValueUpdated += (value) => + l_categoryMod.AddToggle("Use gravity", "Apply gravity to ragdoll", Gravity).OnValueUpdated += (state) => { - Multiplier = value; - ms_entries[(int)ModSetting.Multiplier].BoxedValue = value; - MultiplierChange?.Invoke(value); + Gravity = state; + ms_entries[(int)ModSetting.Gravity].BoxedValue = state; + GravityChange?.Invoke(Gravity); + }; + l_page.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", VelocityMultiplier, 1f, 50f).OnValueUpdated += (value) => + { + VelocityMultiplier = value; + ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue = value; + VelocityMultiplierChange?.Invoke(VelocityMultiplier); + }; + l_page.AddSlider("Movement drag", "Movement resistance", MovementDrag, 0f, 100f).OnValueUpdated += (value) => + { + MovementDrag = value; + ms_entries[(int)ModSetting.MovementDrag].BoxedValue = value; + MovementDragChange?.Invoke(MovementDrag); + }; + l_page.AddSlider("Angular movement drag", "Rotation movement resistance", AngularDrag, 0.5f, 50f).OnValueUpdated += (value) => + { + AngularDrag = value; + ms_entries[(int)ModSetting.AngularDrag].BoxedValue = value; + AngularDragChange?.Invoke(AngularDrag); }; } } diff --git a/ml_prm/Utils.cs b/ml_prm/Utils.cs index 76fa779..ccc657f 100644 --- a/ml_prm/Utils.cs +++ b/ml_prm/Utils.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; +using UnityEngine; namespace ml_prm { From 8ffc8763764ef760371f9180e45e490269b5ad48 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 8 Apr 2023 12:51:21 +0000 Subject: [PATCH 12/63] Update README.md --- README.md | 8 ++++---- ml_prm/README.md | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 230bde6..ecf23f1 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ Merged set of MelonLoader mods for ChilloutVR. | Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes | |-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------| | Avatar Change Info | ml_aci | 1.0.3 | Retired | Retired | Superseded by `Extended Game Notifications` -| Avatar Motion Tweaker | ml_amt | 1.2.4 | Yes, update review | Working | +| Avatar Motion Tweaker | ml_amt | 1.2.4 | Yes | Working | | Desktop Head Tracking | ml_dht | 1.1.2 | Yes | Working | | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | | Extended Game Notifications | ml_egn | 1.0.1 | Yes | Working | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update -| Leap Motion Extension | ml_lme | 1.3.3 | Yes, update review | Working | -| Pickup Arm Movement | ml_pam | 1.0.2 | Yes, update review| Working | -| Player Ragdoll Mod | ml_prm | 1.0.0 | Yes, publish review | Working | +| Leap Motion Extension | ml_lme | 1.3.3 | Yes | Working | +| Pickup Arm Movement | ml_pam | 1.0.2 | Yes| Working | +| Player Ragdoll Mod | ml_prm | 1.0.0 | No, publish review | Working | | Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` diff --git a/ml_prm/README.md b/ml_prm/README.md index 6c2ff7f..a8b53b8 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -13,7 +13,10 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * **Switch ragdoll:** turns into ragdoll state and back, made for VR usage primarily. * **Use hotkey:** enables/disables ragdoll state switch with `R` key; `true` by default. * **Restore position:** returns to position of ragdoll state activation upon ragdoll state exit; `false` by default. +* **Use gravity:** enables/disables gravity for ragdoll; `true` by default. * **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. +* **Movement drag:** movement resistance; `1.0` by default. +* **Angular movement drag:** angular movement resistance; `0.5` by default. # Notes * Incompatible with `Follow hips on IK override` option in AvatarMotionTweaker. From 8bee0d2adfe4d1f90f93867b1013e710bbe847c0 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 8 Apr 2023 17:12:54 +0300 Subject: [PATCH 13/63] Reset button, animation cancel, world check, VR offset fix --- ml_prm/Main.cs | 22 ++++++++++- ml_prm/README.md | 3 +- ml_prm/RagdollController.cs | 31 +++++++++++++-- ml_prm/Settings.cs | 79 +++++++++++++++++++++++++++++++------ ml_prm/Utils.cs | 11 +++++- 5 files changed, 128 insertions(+), 18 deletions(-) diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs index 1734a54..06479de 100644 --- a/ml_prm/Main.cs +++ b/ml_prm/Main.cs @@ -1,4 +1,5 @@ -using ABI_RC.Core.InteractionSystem; +using ABI_RC.Core; +using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Player; using ABI_RC.Systems.IK.SubSystems; using System; @@ -39,6 +40,11 @@ namespace ml_prm new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnStartCalibration_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), null ); + HarmonyInstance.Patch( + typeof(RootLogic).GetMethod(nameof(RootLogic.SpawnOnWorldInstance)), + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnWorldSpawn_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + null + ); MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); } @@ -115,5 +121,19 @@ namespace ml_prm } } + static void OnWorldSpawn_Prefix() => ms_instance?.OnWorldSpawn(); + void OnWorldSpawn() + { + try + { + if(m_localController != null) + m_localController.OnWorldSpawn(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + } } diff --git a/ml_prm/README.md b/ml_prm/README.md index a8b53b8..3bb96a7 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -17,8 +17,9 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. * **Movement drag:** movement resistance; `1.0` by default. * **Angular movement drag:** angular movement resistance; `0.5` by default. +* **Reset settings:** resets mod settings to default. # Notes * Incompatible with `Follow hips on IK override` option in AvatarMotionTweaker. -* Even if locally ragdoll state is activated in the middle of playing emote, remote players still see whole emote animation. * Not suggested to activate fly mode with enabled ragdoll state. +* Can't be activated in worlds that don't allow flying and spawnables. diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 86fbba2..6c7d2ab 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -11,6 +11,8 @@ namespace ml_prm { class RagdollController : MonoBehaviour { + static readonly Vector4 ms_pointVector = new Vector4(0f, 0f, 0f, 1f); + VRIK m_vrIK = null; float m_vrIkWeight = 1f; @@ -196,6 +198,12 @@ namespace ml_prm SwitchRagdoll(); } + internal void OnWorldSpawn() + { + if(m_enabled && m_avatarReady) + SwitchRagdoll(true); + } + // IK updates void OnIKPreUpdate() { @@ -238,13 +246,15 @@ namespace ml_prm } // Arbitrary - public void SwitchRagdoll() + void SwitchRagdoll() => SwitchRagdoll(false); + public void SwitchRagdoll(bool p_force = false) { - if(m_avatarReady && (MovementSystem.Instance.lastSeat == null) && !BodySystem.isCalibrating) + if(m_avatarReady && (MovementSystem.Instance.lastSeat == null) && !BodySystem.isCalibrating && (Utils.IsWorldSafe() || p_force)) { m_enabled = !m_enabled; MovementSystem.Instance.SetImmobilized(m_enabled); + PlayerSetup.Instance.animatorManager.SetAnimatorParameterTrigger("CancelEmote"); if(m_enabled) { @@ -268,8 +278,21 @@ namespace ml_prm if(!Settings.RestorePosition && (m_puppetReferences.hips != null)) { - Vector3 l_pos = m_puppetReferences.hips.position; - PlayerSetup.Instance.transform.position = l_pos; + if(Utils.IsInVR()) + { + Matrix4x4 l_playerMatrix = PlayerSetup.Instance.transform.GetMatrix(); + Matrix4x4 l_avatarMatrix = PlayerSetup.Instance._avatar.transform.GetMatrix(); + Matrix4x4 l_avatarToPlayer = l_avatarMatrix.inverse * l_playerMatrix; + + Vector3 l_pos = m_puppetReferences.hips.position; + Vector3 l_offset = l_avatarToPlayer * ms_pointVector; + PlayerSetup.Instance.transform.position = (l_pos + l_offset); + } + else + { + Vector3 l_pos = m_puppetReferences.hips.position; + PlayerSetup.Instance.transform.position = l_pos; + } } } diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index 438d6c9..d538eb3 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -16,6 +16,16 @@ namespace ml_prm Gravity } + enum UiElementIndex + { + Hotkey = 0, + RestorePosition, + Gravity, + VelocityMultiplier, + MovementDrag, + AngularDrag + } + public static bool Hotkey { get; private set; } = true; public static float VelocityMultiplier { get; private set; } = 2f; public static bool RestorePosition { get; private set; } = false; @@ -34,6 +44,8 @@ namespace ml_prm static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; + static List ms_uiElements = new List(); + internal static void Init() { ms_category = MelonLoader.MelonPreferences.CreateCategory("PRM"); @@ -71,42 +83,87 @@ namespace ml_prm { SwitchChange?.Invoke(); }; - l_categoryMod.AddToggle("Use hotkey", "Switch ragdoll mode with 'R' key", Hotkey).OnValueUpdated += (state) => + + ms_uiElements.Add(l_categoryMod.AddToggle("Use hotkey", "Switch ragdoll mode with 'R' key", Hotkey)); + (ms_uiElements[(int)UiElementIndex.Hotkey] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => { Hotkey = state; ms_entries[(int)ModSetting.Hotkey].BoxedValue = state; - HotkeyChange?.Invoke(Hotkey); + HotkeyChange?.Invoke(state); }; - l_categoryMod.AddToggle("Restore position", "Bring avatar back where ragdoll state was activated", RestorePosition).OnValueUpdated += (state) => + + ms_uiElements.Add(l_categoryMod.AddToggle("Restore position", "Bring avatar back where ragdoll state was activated", RestorePosition)); + (ms_uiElements[(int)UiElementIndex.RestorePosition] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => { RestorePosition = state; ms_entries[(int)ModSetting.RestorePosition].BoxedValue = state; - RestorePositionChange?.Invoke(RestorePosition); + RestorePositionChange?.Invoke(state); }; - l_categoryMod.AddToggle("Use gravity", "Apply gravity to ragdoll", Gravity).OnValueUpdated += (state) => + + ms_uiElements.Add(l_categoryMod.AddToggle("Use gravity", "Apply gravity to ragdoll", Gravity)); + (ms_uiElements[(int)UiElementIndex.Gravity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => { Gravity = state; ms_entries[(int)ModSetting.Gravity].BoxedValue = state; - GravityChange?.Invoke(Gravity); + GravityChange?.Invoke(state); }; - l_page.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", VelocityMultiplier, 1f, 50f).OnValueUpdated += (value) => + + ms_uiElements.Add(l_page.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", VelocityMultiplier, 1f, 50f)); + (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => { VelocityMultiplier = value; ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue = value; - VelocityMultiplierChange?.Invoke(VelocityMultiplier); + VelocityMultiplierChange?.Invoke(value); }; - l_page.AddSlider("Movement drag", "Movement resistance", MovementDrag, 0f, 100f).OnValueUpdated += (value) => + + ms_uiElements.Add(l_page.AddSlider("Movement drag", "Movement resistance", MovementDrag, 0f, 100f)); + (ms_uiElements[(int)UiElementIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => { MovementDrag = value; ms_entries[(int)ModSetting.MovementDrag].BoxedValue = value; - MovementDragChange?.Invoke(MovementDrag); + MovementDragChange?.Invoke(value); }; - l_page.AddSlider("Angular movement drag", "Rotation movement resistance", AngularDrag, 0.5f, 50f).OnValueUpdated += (value) => + + ms_uiElements.Add(l_page.AddSlider("Angular movement drag", "Rotation movement resistance", AngularDrag, 0.5f, 50f)); + (ms_uiElements[(int)UiElementIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => { AngularDrag = value; ms_entries[(int)ModSetting.AngularDrag].BoxedValue = value; AngularDragChange?.Invoke(AngularDrag); }; + + l_categoryMod.AddButton("Reset settings", "", "Reset mod settings to default").OnPress += () => + { + Hotkey = true; + (ms_uiElements[(int)UiElementIndex.Hotkey] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; + ms_entries[(int)ModSetting.Hotkey].BoxedValue = true; + HotkeyChange?.Invoke(true); + + RestorePosition = false; + ms_entries[(int)ModSetting.RestorePosition].BoxedValue = false; + (ms_uiElements[(int)UiElementIndex.RestorePosition] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = false; + RestorePositionChange?.Invoke(false); + + Gravity = true; + ms_entries[(int)ModSetting.Gravity].BoxedValue = true; + (ms_uiElements[(int)UiElementIndex.Gravity] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; + GravityChange?.Invoke(true); + + VelocityMultiplier = 2f; + ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue = 2f; + (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(2f); + VelocityMultiplierChange?.Invoke(2f); + + MovementDrag = 1f; + ms_entries[(int)ModSetting.MovementDrag].BoxedValue = 1f; + (ms_uiElements[(int)UiElementIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(1f); + MovementDragChange?.Invoke(1f); + + AngularDrag = 0.5f; + ms_entries[(int)ModSetting.MovementDrag].BoxedValue = 0.5f; + (ms_uiElements[(int)UiElementIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(0.5f); + AngularDragChange?.Invoke(0.5f); + }; } } } diff --git a/ml_prm/Utils.cs b/ml_prm/Utils.cs index ccc657f..7b8d73d 100644 --- a/ml_prm/Utils.cs +++ b/ml_prm/Utils.cs @@ -1,13 +1,22 @@ -using UnityEngine; +using ABI.CCK.Components; +using UnityEngine; namespace ml_prm { static class Utils { + public static bool IsInVR() => ((ABI_RC.Core.Savior.CheckVR.Instance != null) && ABI_RC.Core.Savior.CheckVR.Instance.hasVrDeviceLoaded); + public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying && CVRWorld.Instance.allowSpawnables); + public static void CopyGlobal(this Transform p_source, Transform p_target) { p_target.position = p_source.position; p_target.rotation = p_source.rotation; } + + public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) + { + return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.localScale : Vector3.one); + } } } From 76f9244d9cd519fad7a10a762f09330ce8d624ea Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 8 Apr 2023 17:19:14 +0300 Subject: [PATCH 14/63] Minor fix --- ml_prm/Settings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index d538eb3..cd2cb60 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -66,7 +66,7 @@ namespace ml_prm AngularDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0.5f, 50f); Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue; - if(MelonLoader.MelonMod.RegisteredMelons.First(m => m.Info.Name == "BTKUILib") != null) + if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null) { CreateBtkUi(); } From 835ce0aebb4c3c2a7e37591ed19c6338e5e07dfb Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 8 Apr 2023 17:49:46 +0000 Subject: [PATCH 15/63] Update README.md --- ml_prm/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ml_prm/README.md b/ml_prm/README.md index 3bb96a7..0adf8e9 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -23,3 +23,4 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * Incompatible with `Follow hips on IK override` option in AvatarMotionTweaker. * Not suggested to activate fly mode with enabled ragdoll state. * Can't be activated in worlds that don't allow flying and spawnables. +* If ragdoll state is enabled in during emote, remote players see whole emote playing while local player sees ragdolling. It's tied to how game handles remote players, currently can be prevented with renaming avatar emote animations to not have default name or containing `Emote` substring. From e4264188060ac5ed0f69b3656689323179a7aba0 Mon Sep 17 00:00:00 2001 From: kafeijao Date: Sat, 8 Apr 2023 19:31:57 +0100 Subject: [PATCH 16/63] Added a unity editor script to toggle ragdoll via animation on your avatar --- ml_prm/Main.cs | 6 ++++++ ml_prm/README.md | 12 ++++++++++++ ml_prm/RagdollController.cs | 9 +++++++++ ml_prm/RagdollToggle.cs | 12 ++++++++++++ ml_prm/ml_prm_editor_script.unitypackage | Bin 0 -> 862 bytes .../resources/ragdoll_toggle_editor_script.png | Bin 0 -> 6326 bytes 6 files changed, 39 insertions(+) create mode 100644 ml_prm/RagdollToggle.cs create mode 100644 ml_prm/ml_prm_editor_script.unitypackage create mode 100644 ml_prm/resources/ragdoll_toggle_editor_script.png diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs index 06479de..75852e7 100644 --- a/ml_prm/Main.cs +++ b/ml_prm/Main.cs @@ -3,7 +3,9 @@ using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Player; using ABI_RC.Systems.IK.SubSystems; using System; +using System.Collections.Generic; using System.Reflection; +using ABI_RC.Core.Util.AssetFiltering; namespace ml_prm { @@ -46,6 +48,10 @@ namespace ml_prm null ); + // Whitelist the toggle script + var l_localComponentWhitelist = typeof(SharedFilter).GetField("_localComponentWhitelist", BindingFlags.NonPublic | BindingFlags.Static)!.GetValue(null) as HashSet; + l_localComponentWhitelist!.Add(typeof(RagdollToggle)); + MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); } diff --git a/ml_prm/README.md b/ml_prm/README.md index 3bb96a7..cffb93c 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -23,3 +23,15 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * Incompatible with `Follow hips on IK override` option in AvatarMotionTweaker. * Not suggested to activate fly mode with enabled ragdoll state. * Can't be activated in worlds that don't allow flying and spawnables. + +# Unity Editor Script +You can also trigger the ragdoll via animations on your avatar. To do this you need to download and import the +`ml_prm_editor_script.unitypackage` into your unity project. Then add the component `Ragdoll Toggle` anywhere inside of +your avatar's hierarchy. Now you can animate both parameters available: + +- **Should Override:** Whether the animation should override the toggled state of the ragdoll. +- **Is On:** Whether the ragdoll state is On or Off (only works if `Should Override` is also On). + +![](resources/ragdoll_toggle_editor_script.png) + +**Note:** In order to work the game object needs to be active and the component enabled. diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 6c7d2ab..ecd7fdc 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -30,6 +30,8 @@ namespace ml_prm Vector3 m_lastPosition = Vector3.zero; Vector3 m_velocity = Vector3.zero; + RagdollToggle m_avatarRagdollToggle = null; + internal RagdollController() { m_rigidBodies = new List(); @@ -67,6 +69,11 @@ namespace ml_prm if(Settings.Hotkey && Input.GetKeyDown(KeyCode.R) && !ViewManager.Instance.isGameMenuOpen()) SwitchRagdoll(); + + if (m_avatarRagdollToggle != null && m_avatarRagdollToggle.isActiveAndEnabled && m_avatarRagdollToggle.shouldOverride) { + if (m_enabled != m_avatarRagdollToggle.isOn) + SwitchRagdoll(); + } } void LateUpdate() @@ -182,6 +189,8 @@ namespace ml_prm m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostUpdate); } + m_avatarRagdollToggle = PlayerSetup.Instance._avatar.GetComponentInChildren(true); + m_avatarReady = true; } } diff --git a/ml_prm/RagdollToggle.cs b/ml_prm/RagdollToggle.cs new file mode 100644 index 0000000..63343a2 --- /dev/null +++ b/ml_prm/RagdollToggle.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +namespace ml_prm +{ + public class RagdollToggle : MonoBehaviour + { + [Tooltip("Whether or not is should use the isOn property to override the current Ragdoll State of the Avatar.")] + [SerializeField] public bool shouldOverride; + [Tooltip("Whether Ragdoll State is active or not on the Avatar. Requires shouldOverride to be true to work.")] + [SerializeField] public bool isOn; + } +} diff --git a/ml_prm/ml_prm_editor_script.unitypackage b/ml_prm/ml_prm_editor_script.unitypackage new file mode 100644 index 0000000000000000000000000000000000000000..7efa88414692edbe958af130773feebf8f7203f6 GIT binary patch literal 862 zcmV-k1EKsMiwFpmqcLOz0AX@tXmn+5a4vLVascg_-EPw`6vuN*q`rgIE4bP6;W$aT z0u3ZCVAA-yKofG}lh%;N#dZc`+LLj?Bk>BHbS<*!;VwQ^$>+{(bE8Pgo&> ztjKwumsyfVG%jdRmKCRE!9j!cev#ff?t+1>~Y(O8eZ@@Y}UQuTJpwXwdc5U`b6Gda64;I7VqNp#eYDO+iR*+`4)fZ3kc?-zRRIc_tl2#TP{7|m0fLWW@|2GI{_`klX;s2d9I_LMl(I@gC{x3;4{a;K&7ym=h z>;G287B_PNmFKu!WLZWbV{shDoM$l=1xuIVkO_IN8ub`v{6MN!FMqM(-7BSPD;M|2Z)ad-$j6pCcf9@Trv=%tjC0?G*T_ z+vVYBr9b||XuE%AHOAwsGU(@v|LgUCF^hk{|BG3d|Anc0{yzw3_`klX;djyA@A%Am zMvLD)V6`}TSGWfiU_h6E&EM@WF9K!TC7`=n;AKgGb+YV!btD_q3Y$LL!D?qFuY?|v ohw*#u_GK zCQBH`o}FRFGGu!n-+u4={+Hie*UUW6nde;RoX`23`*Yv-MBX;N$#p{L1QQbzm!W~~ z9VVtDE5Nlq8w>E+blr>-_&S2Ta}&x`L=>I}ZjQTXn`kpJmBw=HIxqwG?4AY>kxWb{ zza74h5D@uJOiY4ChPv8!(RRz}^T@k;4TNph{7HosX?xfCiU3bNb4Bed@G@35wIrr8 zOvxpKxbs-UL8o^nH^|y#hF+s>Q%=Sw|H7TS8vQZ_9vZQh2ch)=Uq9tNH+^mjdz;)Y zyjQ<~HG3Fj`m317(BgddHzTAQ%vPmc>Ak?Hdr#^j0S?L&IMP zXoOy1jjRHi;;&p7J$$xVA_;9@_x#r`jc~3MPA^~U3yOeBOi%O0Xkh4<0B$H4jvoumWaH`DNXskZ4 z>!VJ%v~W1x3F|r;$Y`LZcyMGW9_%lV&BPC!lh-<+BU3c)>O%ytIYp=h?V?{FV?CJ^ z7RIvHVUUYlLNLE7FS&as~!{;8w=Rm7=V2Xc+ z$XH#j8XJ14y*>n=>&=Vh^AOVhem3+#ZOd)A3Q0fq;}pqS?jsl;htcZ(+E}D7SRioY)5X}Sx;=hVz~9pM{?|O z6-Mj!NnV6LOqR<5!d0BMrX9kPtl-}Nz}%+d$vvwFsPV>^u;rl&SZ}TgtQo`JUk_we z^kzPqR|r>FSmE5Tw>gaKzOOjBjNGO>Bk8}}`R9{6!fh6*!&%Qn@0eR!x~#1ATO)G( z$~A!C6c$lms0K$%QY21YZd5s?+iy15;NULvQQ1CR8923^`mrpC)EDNQbHu5 zOU18#hpL90?%7GB)p@~{bs_|zOksE>=xctqzSy+osQWl#-IZ&&h=N<#a_Ej0` zjB!e6%b6>y>Mv%eSUCD#&T)h=H^>5suB|nL;RABZaYy7hB`03o=c(+KF%vD|#Byw4 zGsA3{)$ikJld!Io#7mSk7x_}EF8S*7kq5}RKM?s~mx_mht|lD*`O(nv7VyhQvMJjj z%&Tq7r3fYLBwj<^oGx}&S6I0%UVp|DK&#oU8fHdm=!RkdVZ3Dr3Dq`UKtkE6i z9GWrQUua$UX5}&ibzsdF+I0k>e!3mNv?w6GG}6?3J*=#(Th-1*^#z=`H2Pw2d$P+< z!v3^)2bwH>Tg-TWHSNG)Pvk2M9sXKr6r8SlG&Bw*Nr;&xXo0=*bO@&V6W_vzZ+})p zO?wscRvV+lN6|s%wY(E?Y}1mXUei?-R0s{laL5=8{YbMJ^Ixg!t2n9d6p?%EBlTB- zr8Oz#nxJw`*%@`+weSq1xti@L(&}!qz3*&ti&{|z5d87*t|Jakpq0D|1vs^cn>=&^ zn_l3lQ!x1^scv(~{eJcKkH7Oh*xksSsXf5E>+Ot^7@hJ8q-6QbOofB3%wV5s z8kUV4+Ppp48dWG_-n8iGEIJz@WOtchk!xJ)$Ii^FiaJVAm)VTu6(2%o@IkD^M~TFM zYqO04FZGZRo{oF?sSZRTwUE50dNq$oTc7V;miMkc5=SDO3x>1aqNcT8P+w~bVa@BY z@uPeTWSJ=}HRo0jp#NPK57Ppvu`%7{6ry=8Gk|Uw1prIgBa>*}hyOw_X%)(F^eb=v zSiOv6cGtvQ=RpVzb+XteY3=P>^g6o9N&V*T^6T6E)6kGhh5+av@mlHCH(?qO`DK-i zu~@BrSLV3eDn|{2TEIsjE8AqiSZupaHKqEC;D-?mw70VCdCxhgfx zqsIT-L0nh(6vRFoivc3N+rKcHGE&UTXwpBMVPs?jkF)x=-$`bR)dJ5vw`=4=*bl@JoS-dr z0Edlp*dcGDc5s4M29`;_RkL}Ii=yKSWqyv;TtjwSe!qo(Io2E2BR|2hw&Aa2JQcZ< zz8ZYs^ggIWy=#Uo(VPuC$>q@`ly$BpZ5u@7Ieq-Kqkw6K3Nly3ndeTMns_mDc2@o9lF^d@g5z~gaWiqF8yQ0R{}ZfnK#lP8xki?b?i=+`q6aDn+~e* za>G>c-0pc98mR8?a`UGxIe=wfEBl}Q>b@O`_Ka3qF2>AmuLify^zb|eVC(NtELJLXjWzEj+tMof&mLEw?h64P$U;^y_jX8A&iDx&3xv3maP z$)H;|l|{^y27>QbVh+=Y9He;8H?vxRQteF@QK@0vy)yd!3kLuJ4vVr`sp|)2>DRaInpIVb^cW%T|B2Y>)P(*RD2bnmruB@J?3YG zRX};@oz@|$wB+(Yom3Ds;V3ijik1`_j%o8VWRvrD@K8x8KJ8XWHQa~a_<~X3*tOGg z5`ac%ahyT`WJlD&03Qm1Mqs+<5y3mDf638YU!A|N7{G)gexIlD1JveJSc^3q1Y;oh z|NDGDHuCkEe5}T1lHb-ucqm9z?q}Z5D$E~YfIBT?+BW90VpD*lqFya|myI^?8<&^y zM8HgQJA2t4dQ_Iik4?X#`reZRg2fzHu>^VkNpfuvJ8T7wo=~s>Xj5vOU={QKYt?Pt zi4@N;DA!_8kndeG1N+tY)_dLjLP5cHP$=h8?svs@fL>L48e2)ooz}zKqbHbaT_ksu z%WHe9y{6yzc~)}p%=Ks z>opw-F$%y7_B{@Azv_i!Ph0dEUVN^^q=qlmM&6I^RQut2?cMGYp0(Sf%Ann{va)~4 zbaW=mKXnl(V>frjPVOxf6sK^36(95$+arA4-0jBTv0yNGx$!;AqW!n`*-Ki){n-eq zn%8NRTI~I|B5~N?7b?AGhlOXXl7YH%miwz{Hq+L^cnf1KwR%C@^Zs z;2S@^kwbRW$G`_#pEpwLyK>#3wQVkVp$~^jpzW@a@`^;Xg76|EW|^8J&qsML85@+x zD>`?amiL;}9d>w>B{q4Cl%X;FewHexTN=T;5>~+l>+9^!t*q~te(<&NgvwD(pSho3 z+-+*TX3?`16%{z7ZuE-M*Z}}pd4AK&DJd_YF=mmcjTji}Xq_XE%Scb(9lBpp}iN5W11{YUE9G^_7K% zCyQ4>9Vf}`>^-aVc#x+$XAk*esQv;p3{722uJ@GHH+lI$%W*0{yHt^ z-kSJWMYH3LWQ>FYR~k3NJ5S01k|0iC-PA|b=G+(l3v=a4^>o+%725q>{}E&JJxuWIsbYg^yjJ5nJ${}gBV%`kT8SN$`D7<2m2IRMmqTju?>(HB&;OV?Aq=)V5o{}hk+`^}dGj(k z^EHnU!RV34YnFD>zW*gBFE#M_`mYKO6AR=!6OuljN1|uTkAGB=gXC%vp*R*OK6+zkyw8e5V=lbdJ~sBNr12CZ2}0$tv7RR7fhvj1kZgq_mOUCT*cba#Botl4=rMrPnUvAR=}bNLF-9A)LFh*UZy8i;Ps$uR3!MMmS@^dLp#yYK z^PBq^Zu~*k)_9hfUj7Pi!z&4NE(7`jKdm;g77A+7zl%N8wku*!yodpjfx?VUS6^*B zrX3#>;tq9Yhv+K)w#AbZ9(AQC%m64mGu{-kX<|rK$j6_0wzIh`Q{={7nAq+g=V$5t zz0GL6%46h7jEEWxMWwint)A}qV1_=j2arkmdR4`udhGRhz#(~UGTOS+`107HTHUN` z!C##Z;nuvu#l_X%#&Yq4oV|yaiN9;1aV0DbkmOP8hgJt5NFRbzajUY^@-D<|)D5ZA zc$p$BR@61bc!Mt|3g8juaJu9ue9w2Wzwiq~x!kgN_}ehMOf65LbrsR0XB=_vbxA4M z+|e;>GU)@%vad6fYpeDNI%9H4IgRy3Nhs&sIQ>H*~MqT5Z<9_f_jm@xyC6Z&^DR6pKV zm*As-2rC;JBX+mpX=z zOvbV4uB#9Kfqe~^kO3T~h{x}IX>Ia)X~i}*k2U|yi7l#pRY72uH&?9zRP+pt9iK1H5hK9U z#<^8rywvyet10B}X2pWC!-?fM1Vw{VBf<55hee$?z+`CcuIeo6z2iSM!7FY$Xu@zI zWsE$YNFL@^@v$|))8I79UI5_pz#*d%Gqfo}Z;!CFO~L2SUkE^Z5wo}BZ1+Xu-R>K_n??9F`SdL2bTwY>gB01DSI9zuyQt9JF;Lc_aIcd?k zLUr1%7A2Dyqx4z{%!h!|Fm<+?H==<;+<4T%Y2}etdg3D6??alV5**1gzFg)#Iz6T7 zzqwSpL1z!$`VXV&FD3PEGUJPih+!m^7+wU17pyfVntodqOPW+9^4#N3f>5MazanQ% zft{m(oCOwO9;ttHTfu^-g*5{PPs%Fir2&>5S1TOb3rzi`r>LR`vVT;Pp9kaM>8%4|yAZ<~WEyPn~Yx5Hu3@Ju5>dlT}XZ zD--Eg;;I_McWuJ!v50DH0V3Bwq6Z3KiG(6^@|wONt$Bp>$@^vNQycIJZpR;&;KmvI zdpoR8&GV)FE~`1ke*5)HM&Dh^YolvGLwDlmqB$_p+(#V!n5}}Jh1N<^ZRlR|jsF5E z|C#F_>I2CC5&}c)4a3x)oTzz94f1~6hks)b5DQoF=Y~-r?BG9_c=W{!JzkzB`O*-~ z_b_}E1Hhc6om!nrJ!Whzu zQ-YcS)woZet^uB(;c$X(#2x*=G2lZe4nLZe-JFIoKD*jIVqC5Kv)(%>^iJjmkRNUj zOCN`h_`w08l3QP|=|ZxLfQkakIGy?`QmOXQg!VvR-{2Kx2rd7GSP$H9K2K$HWekyP zn*Jm-Wmz>9@I?XD-vv0Doq$XGYJjbq=bw$veKe`zIew$o5|ybL2v_w-l<(zcR$;Nt z!pffKWeyMGCGf4Act8j~)$r^gi>@6)3gAJ?6!Boi4iW#giT1Y{07Pf#(?3u=LqPbf zBN+MSS)G4RmyN~4hi>OW&_wIn&GCS>YQ* zRxY80_c4}TX-d-ucs(4TqW)PRqr~Bxv7@77$FN@^4sq)!~ zjUwAxVkLqqu!EaPni*OwFe;XEmODn=!`A{TF5WKQb@ Date: Sat, 8 Apr 2023 23:19:51 +0300 Subject: [PATCH 17/63] Not harsh world restrictions --- ml_prm/Main.cs | 3 +-- ml_prm/RagdollController.cs | 28 +++++++++++++++++----------- ml_prm/Utils.cs | 9 ++++++++- ml_prm/ml_prm.csproj | 1 + 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs index 75852e7..8a53961 100644 --- a/ml_prm/Main.cs +++ b/ml_prm/Main.cs @@ -49,8 +49,7 @@ namespace ml_prm ); // Whitelist the toggle script - var l_localComponentWhitelist = typeof(SharedFilter).GetField("_localComponentWhitelist", BindingFlags.NonPublic | BindingFlags.Static)!.GetValue(null) as HashSet; - l_localComponentWhitelist!.Add(typeof(RagdollToggle)); + (typeof(SharedFilter).GetField("_localComponentWhitelist", BindingFlags.NonPublic | BindingFlags.Static)?.GetValue(null) as HashSet)?.Add(typeof(RagdollToggle)); MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); } diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index ecd7fdc..a088b66 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -70,10 +70,8 @@ namespace ml_prm if(Settings.Hotkey && Input.GetKeyDown(KeyCode.R) && !ViewManager.Instance.isGameMenuOpen()) SwitchRagdoll(); - if (m_avatarRagdollToggle != null && m_avatarRagdollToggle.isActiveAndEnabled && m_avatarRagdollToggle.shouldOverride) { - if (m_enabled != m_avatarRagdollToggle.isOn) - SwitchRagdoll(); - } + if((m_avatarRagdollToggle != null) && m_avatarRagdollToggle.isActiveAndEnabled && m_avatarRagdollToggle.shouldOverride && (m_enabled != m_avatarRagdollToggle.isOn)) + SwitchRagdoll(); } void LateUpdate() @@ -98,6 +96,7 @@ namespace ml_prm m_vrIK = null; m_enabled = false; m_avatarReady = false; + m_avatarRagdollToggle = null; m_rigidBodies.Clear(); m_colliders.Clear(); m_avatarReferences = new BipedRagdollReferences(); @@ -158,7 +157,7 @@ namespace ml_prm l_body.isKinematic = true; l_body.angularDrag = Settings.AngularDrag; l_body.drag = Settings.MovementDrag; - l_body.useGravity = Settings.Gravity; + l_body.useGravity = (!Utils.IsWorldSafe() || Settings.Gravity); l_body.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; } @@ -210,7 +209,15 @@ namespace ml_prm internal void OnWorldSpawn() { if(m_enabled && m_avatarReady) - SwitchRagdoll(true); + SwitchRagdoll(); + + if(m_avatarReady) + { + foreach(Rigidbody l_body in m_rigidBodies) + { + l_body.useGravity = (!Utils.IsWorldSafe() || Settings.Gravity); + } + } } // IK updates @@ -250,15 +257,14 @@ namespace ml_prm if(m_avatarReady) { foreach(Rigidbody l_body in m_rigidBodies) - l_body.useGravity = p_state; + l_body.useGravity = (!Utils.IsWorldSafe() || p_state); } } // Arbitrary - void SwitchRagdoll() => SwitchRagdoll(false); - public void SwitchRagdoll(bool p_force = false) + public void SwitchRagdoll() { - if(m_avatarReady && (MovementSystem.Instance.lastSeat == null) && !BodySystem.isCalibrating && (Utils.IsWorldSafe() || p_force)) + if(m_avatarReady && (MovementSystem.Instance.lastSeat == null) && !BodySystem.isCalibrating) { m_enabled = !m_enabled; @@ -273,7 +279,7 @@ namespace ml_prm foreach(Rigidbody l_body in m_rigidBodies) l_body.isKinematic = false; - Vector3 l_velocity = m_velocity * Settings.VelocityMultiplier; + Vector3 l_velocity = m_velocity * Mathf.Clamp(Settings.VelocityMultiplier, 1f, (Utils.IsWorldSafe() ? Utils.GetWorldFlyMultiplier() : 1f)); foreach(Rigidbody l_body in m_rigidBodies) { l_body.velocity = l_velocity; diff --git a/ml_prm/Utils.cs b/ml_prm/Utils.cs index 7b8d73d..359c3fb 100644 --- a/ml_prm/Utils.cs +++ b/ml_prm/Utils.cs @@ -6,7 +6,14 @@ namespace ml_prm static class Utils { public static bool IsInVR() => ((ABI_RC.Core.Savior.CheckVR.Instance != null) && ABI_RC.Core.Savior.CheckVR.Instance.hasVrDeviceLoaded); - public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying && CVRWorld.Instance.allowSpawnables); + public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying); + public static float GetWorldFlyMultiplier() + { + float l_result = 1f; + if(CVRWorld.Instance != null) + l_result = CVRWorld.Instance.flyMultiplier; + return l_result; + } public static void CopyGlobal(this Transform p_source, Transform p_target) { diff --git a/ml_prm/ml_prm.csproj b/ml_prm/ml_prm.csproj index 8c2917c..d2d89ba 100644 --- a/ml_prm/ml_prm.csproj +++ b/ml_prm/ml_prm.csproj @@ -89,6 +89,7 @@ + From 49d11056ecd07ac0436a3d68058af9af79a0368a Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 8 Apr 2023 20:23:31 +0000 Subject: [PATCH 18/63] Update README.md --- ml_prm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ml_prm/README.md b/ml_prm/README.md index c7a45f0..b93d250 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -22,7 +22,7 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI # Notes * Incompatible with `Follow hips on IK override` option in AvatarMotionTweaker. * Not suggested to activate fly mode with enabled ragdoll state. -* Can't be activated in worlds that don't allow flying and spawnables. +* In worlds that don't allow flying velocity multiplier is forced to 1 and gravity is forced on. * If ragdoll state is enabled in during emote, remote players see whole emote playing while local player sees ragdolling. It's tied to how game handles remote players, currently can be prevented with renaming avatar emote animations to not have default name or containing `Emote` substring. # Unity Editor Script From 327f5d6cddb6e782f36a33ecaf2c60df8d039a24 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sun, 9 Apr 2023 01:57:09 +0300 Subject: [PATCH 19/63] FBT flop fix, alignment fix --- ml_prm/RagdollController.cs | 92 +++++++++++++++++++++---------------- ml_prm/Utils.cs | 5 -- 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index a088b66..5d6f2aa 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -11,8 +11,6 @@ namespace ml_prm { class RagdollController : MonoBehaviour { - static readonly Vector4 ms_pointVector = new Vector4(0f, 0f, 0f, 1f); - VRIK m_vrIK = null; float m_vrIkWeight = 1f; @@ -23,7 +21,6 @@ namespace ml_prm Transform m_puppetRoot = null; Transform m_puppet = null; BipedRagdollReferences m_puppetReferences; - BipedRagdollReferences m_avatarReferences; readonly List> m_boneLinks = null; bool m_avatarReady = false; @@ -72,12 +69,18 @@ namespace ml_prm if((m_avatarRagdollToggle != null) && m_avatarRagdollToggle.isActiveAndEnabled && m_avatarRagdollToggle.shouldOverride && (m_enabled != m_avatarRagdollToggle.isOn)) SwitchRagdoll(); + + if(m_enabled && m_avatarReady && BodySystem.isCalibratedAsFullBody) + BodySystem.TrackingPositionWeight = 0f; } void LateUpdate() { if(m_enabled && m_avatarReady) { + if(BodySystem.isCalibratedAsFullBody) + BodySystem.TrackingPositionWeight = 0f; + foreach(var l_link in m_boneLinks) l_link.Item1.CopyGlobal(l_link.Item2); } @@ -99,7 +102,6 @@ namespace ml_prm m_avatarRagdollToggle = null; m_rigidBodies.Clear(); m_colliders.Clear(); - m_avatarReferences = new BipedRagdollReferences(); m_puppetReferences = new BipedRagdollReferences(); m_boneLinks.Clear(); } @@ -108,7 +110,7 @@ namespace ml_prm { if(PlayerSetup.Instance._animator.isHuman) { - m_avatarReferences = BipedRagdollReferences.FromAvatar(PlayerSetup.Instance._animator); + BipedRagdollReferences l_avatarReferences = BipedRagdollReferences.FromAvatar(PlayerSetup.Instance._animator); m_puppet = new GameObject("Root").transform; m_puppet.parent = m_puppetRoot; @@ -116,36 +118,36 @@ namespace ml_prm m_puppet.localRotation = Quaternion.identity; m_puppetReferences.root = m_puppet; - m_puppetReferences.hips = CloneTransform(m_avatarReferences.hips, m_puppetReferences.root, "Hips"); - m_puppetReferences.spine = CloneTransform(m_avatarReferences.spine, m_puppetReferences.hips, "Spine"); + m_puppetReferences.hips = CloneTransform(l_avatarReferences.hips, m_puppetReferences.root, "Hips"); + m_puppetReferences.spine = CloneTransform(l_avatarReferences.spine, m_puppetReferences.hips, "Spine"); - if(m_avatarReferences.chest != null) - m_puppetReferences.chest = CloneTransform(m_avatarReferences.chest, m_puppetReferences.spine, "Chest"); + if(l_avatarReferences.chest != null) + m_puppetReferences.chest = CloneTransform(l_avatarReferences.chest, m_puppetReferences.spine, "Chest"); - m_puppetReferences.head = CloneTransform(m_avatarReferences.head, (m_puppetReferences.chest != null) ? m_puppetReferences.chest : m_puppetReferences.spine, "Head"); + m_puppetReferences.head = CloneTransform(l_avatarReferences.head, (m_puppetReferences.chest != null) ? m_puppetReferences.chest : m_puppetReferences.spine, "Head"); - m_puppetReferences.leftUpperArm = CloneTransform(m_avatarReferences.leftUpperArm, (m_puppetReferences.chest != null) ? m_puppetReferences.chest : m_puppetReferences.spine, "LeftUpperArm"); - m_puppetReferences.leftLowerArm = CloneTransform(m_avatarReferences.leftLowerArm, m_puppetReferences.leftUpperArm, "LeftLowerArm"); - m_puppetReferences.leftHand = CloneTransform(m_avatarReferences.leftHand, m_puppetReferences.leftLowerArm, "LeftHand"); + m_puppetReferences.leftUpperArm = CloneTransform(l_avatarReferences.leftUpperArm, (m_puppetReferences.chest != null) ? m_puppetReferences.chest : m_puppetReferences.spine, "LeftUpperArm"); + m_puppetReferences.leftLowerArm = CloneTransform(l_avatarReferences.leftLowerArm, m_puppetReferences.leftUpperArm, "LeftLowerArm"); + m_puppetReferences.leftHand = CloneTransform(l_avatarReferences.leftHand, m_puppetReferences.leftLowerArm, "LeftHand"); - m_puppetReferences.rightUpperArm = CloneTransform(m_avatarReferences.rightUpperArm, (m_puppetReferences.chest != null) ? m_puppetReferences.chest : m_puppetReferences.spine, "RightUpperArm"); - m_puppetReferences.rightLowerArm = CloneTransform(m_avatarReferences.rightLowerArm, m_puppetReferences.rightUpperArm, "RightLowerArm"); - m_puppetReferences.rightHand = CloneTransform(m_avatarReferences.rightHand, m_puppetReferences.rightLowerArm, "RightHand"); + m_puppetReferences.rightUpperArm = CloneTransform(l_avatarReferences.rightUpperArm, (m_puppetReferences.chest != null) ? m_puppetReferences.chest : m_puppetReferences.spine, "RightUpperArm"); + m_puppetReferences.rightLowerArm = CloneTransform(l_avatarReferences.rightLowerArm, m_puppetReferences.rightUpperArm, "RightLowerArm"); + m_puppetReferences.rightHand = CloneTransform(l_avatarReferences.rightHand, m_puppetReferences.rightLowerArm, "RightHand"); - m_puppetReferences.leftUpperLeg = CloneTransform(m_avatarReferences.leftUpperLeg, m_puppetReferences.hips, "LeftUpperLeg"); - m_puppetReferences.leftLowerLeg = CloneTransform(m_avatarReferences.leftLowerLeg, m_puppetReferences.leftUpperLeg, "LeftLowerLeg"); - m_puppetReferences.leftFoot = CloneTransform(m_avatarReferences.leftFoot, m_puppetReferences.leftLowerLeg, "LeftFoot"); + m_puppetReferences.leftUpperLeg = CloneTransform(l_avatarReferences.leftUpperLeg, m_puppetReferences.hips, "LeftUpperLeg"); + m_puppetReferences.leftLowerLeg = CloneTransform(l_avatarReferences.leftLowerLeg, m_puppetReferences.leftUpperLeg, "LeftLowerLeg"); + m_puppetReferences.leftFoot = CloneTransform(l_avatarReferences.leftFoot, m_puppetReferences.leftLowerLeg, "LeftFoot"); - m_puppetReferences.rightUpperLeg = CloneTransform(m_avatarReferences.rightUpperLeg, m_puppetReferences.hips, "RightUpperLeg"); - m_puppetReferences.rightLowerLeg = CloneTransform(m_avatarReferences.rightLowerLeg, m_puppetReferences.rightUpperLeg, "RightLowerLeg"); - m_puppetReferences.rightFoot = CloneTransform(m_avatarReferences.rightFoot, m_puppetReferences.rightLowerLeg, "RightFoot"); + m_puppetReferences.rightUpperLeg = CloneTransform(l_avatarReferences.rightUpperLeg, m_puppetReferences.hips, "RightUpperLeg"); + m_puppetReferences.rightLowerLeg = CloneTransform(l_avatarReferences.rightLowerLeg, m_puppetReferences.rightUpperLeg, "RightLowerLeg"); + m_puppetReferences.rightFoot = CloneTransform(l_avatarReferences.rightFoot, m_puppetReferences.rightLowerLeg, "RightFoot"); BipedRagdollCreator.Options l_options = BipedRagdollCreator.AutodetectOptions(m_puppetReferences); l_options.joints = RagdollCreator.JointType.Character; BipedRagdollCreator.Create(m_puppetReferences, l_options); Transform[] l_puppetTransforms = m_puppetReferences.GetRagdollTransforms(); - Transform[] l_avatarTransforms = m_avatarReferences.GetRagdollTransforms(); + Transform[] l_avatarTransforms = l_avatarReferences.GetRagdollTransforms(); for(int i = 0; i < l_puppetTransforms.Length; i++) { if(l_puppetTransforms[i] != null) @@ -241,7 +243,10 @@ namespace ml_prm if(m_avatarReady) { foreach(Rigidbody l_body in m_rigidBodies) + { l_body.drag = p_value; + l_body.WakeUp(); + } } } void OnAngularDragChange(float p_value) @@ -249,7 +254,10 @@ namespace ml_prm if(m_avatarReady) { foreach(Rigidbody l_body in m_rigidBodies) + { l_body.angularDrag = p_value; + l_body.WakeUp(); + } } } void OnGravityChange(bool p_state) @@ -273,6 +281,9 @@ namespace ml_prm if(m_enabled) { + if(BodySystem.isCalibratedAsFullBody) + BodySystem.TrackingPositionWeight = 0f; + foreach(var l_link in m_boneLinks) l_link.Item2.CopyGlobal(l_link.Item1); @@ -288,34 +299,37 @@ namespace ml_prm } else { + if(BodySystem.isCalibratedAsFullBody) + BodySystem.TrackingPositionWeight = 1f; + foreach(Rigidbody l_body in m_rigidBodies) l_body.isKinematic = true; - if(!Settings.RestorePosition && (m_puppetReferences.hips != null)) + if((m_puppetReferences.hips != null)) { - if(Utils.IsInVR()) - { - Matrix4x4 l_playerMatrix = PlayerSetup.Instance.transform.GetMatrix(); - Matrix4x4 l_avatarMatrix = PlayerSetup.Instance._avatar.transform.GetMatrix(); - Matrix4x4 l_avatarToPlayer = l_avatarMatrix.inverse * l_playerMatrix; + Vector3 l_hipsPos = m_puppetReferences.hips.position; - Vector3 l_pos = m_puppetReferences.hips.position; - Vector3 l_offset = l_avatarToPlayer * ms_pointVector; - PlayerSetup.Instance.transform.position = (l_pos + l_offset); - } - else + if(!Settings.RestorePosition) { - Vector3 l_pos = m_puppetReferences.hips.position; - PlayerSetup.Instance.transform.position = l_pos; + if(Utils.IsInVR()) + { + Vector3 l_diff = l_hipsPos - PlayerSetup.Instance._avatar.transform.position; + Vector3 l_playerPos = PlayerSetup.Instance.transform.position; + PlayerSetup.Instance.transform.position = l_playerPos + l_diff; + } + else + PlayerSetup.Instance.transform.position = l_hipsPos; } } } - - foreach(Collider l_collider in m_colliders) - l_collider.enabled = m_enabled; } + + foreach(Collider l_collider in m_colliders) + l_collider.enabled = m_enabled; } + public bool IsRagdolled() => (m_enabled && m_avatarReady); + static Transform CloneTransform(Transform p_source, Transform p_parent, string p_name) { Transform l_target = new GameObject(p_name).transform; diff --git a/ml_prm/Utils.cs b/ml_prm/Utils.cs index 359c3fb..36a8c74 100644 --- a/ml_prm/Utils.cs +++ b/ml_prm/Utils.cs @@ -20,10 +20,5 @@ namespace ml_prm p_target.position = p_source.position; p_target.rotation = p_source.rotation; } - - public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) - { - return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.localScale : Vector3.one); - } } } From fe5e1dfd3c65766811f9c79d7c6c180d5d9f2de1 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sun, 9 Apr 2023 13:59:53 +0000 Subject: [PATCH 20/63] Pose transitions in FBT with enabled game's option for running FBT animations Limit movement drag to 50 Settings listener on destroy --- README.md | 2 +- ml_amt/MotionTweaker.cs | 18 ++++++++++++++++-- ml_amt/Properties/AssemblyInfo.cs | 6 +++--- ml_lme/LeapInput.cs | 2 ++ ml_prm/RagdollController.cs | 7 ++++--- ml_prm/Settings.cs | 4 ++-- 6 files changed, 28 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ecf23f1..07df240 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Merged set of MelonLoader mods for ChilloutVR. | Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes | |-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------| | Avatar Change Info | ml_aci | 1.0.3 | Retired | Retired | Superseded by `Extended Game Notifications` -| Avatar Motion Tweaker | ml_amt | 1.2.4 | Yes | Working | +| Avatar Motion Tweaker | ml_amt | 1.2.5 | Yes, update review | Working | | Desktop Head Tracking | ml_dht | 1.1.2 | Yes | Working | | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | | Extended Game Notifications | ml_egn | 1.0.1 | Yes | Working diff --git a/ml_amt/MotionTweaker.cs b/ml_amt/MotionTweaker.cs index 95527c1..98ace85 100644 --- a/ml_amt/MotionTweaker.cs +++ b/ml_amt/MotionTweaker.cs @@ -1,4 +1,5 @@ using ABI_RC.Core.Player; +using ABI_RC.Core.Savior; using ABI_RC.Systems.IK; using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.MovementSystem; @@ -37,6 +38,7 @@ namespace ml_amt Transform m_avatarHips = null; float m_viewPointHeight = 1f; bool m_inVR = false; + bool m_fbtAnimations = true; bool m_avatarReady = false; bool m_compatibleAvatar = false; @@ -93,6 +95,9 @@ namespace ml_amt Settings.FollowHipsChange += this.SetFollowHips; Settings.MassCenterChange += this.OnMassCenterChange; Settings.ScaledStepsChange += this.OnScaledStepsChange; + + m_fbtAnimations = MetaPort.Instance.settings.GetSettingsBool("GeneralEnableRunningAnimationFullBody"); + MetaPort.Instance.settings.settingBoolChanged.AddListener(this.OnGameSettingBoolChange); } void OnDestroy() @@ -108,6 +113,8 @@ namespace ml_amt Settings.DetectEmotesChange -= this.SetDetectEmotes; Settings.FollowHipsChange -= this.SetFollowHips; Settings.MassCenterChange -= this.OnMassCenterChange; + + MetaPort.Instance.settings.settingBoolChanged.RemoveListener(this.OnGameSettingBoolChange); } void Update() @@ -147,8 +154,8 @@ namespace ml_amt if(m_poseTransitions) { - PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Crouching", (m_poseState == PoseState.Crouching) && !m_compatibleAvatar && !BodySystem.isCalibratedAsFullBody); - PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Prone", (m_poseState == PoseState.Proning) && !m_compatibleAvatar && !BodySystem.isCalibratedAsFullBody); + PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Crouching", (m_poseState == PoseState.Crouching) && !m_compatibleAvatar && (!BodySystem.isCalibratedAsFullBody || m_fbtAnimations)); + PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool("Prone", (m_poseState == PoseState.Proning) && !m_compatibleAvatar && (!BodySystem.isCalibratedAsFullBody || m_fbtAnimations)); } } @@ -441,6 +448,13 @@ namespace ml_amt } } + // Game settings + void OnGameSettingBoolChange(string p_name, bool p_state) + { + if(p_name == "GeneralEnableRunningAnimationFullBody") + m_fbtAnimations = p_state; + } + // Arbitrary float GetRelativeScale() { diff --git a/ml_amt/Properties/AssemblyInfo.cs b/ml_amt/Properties/AssemblyInfo.cs index 9a84e96..ba6d274 100644 --- a/ml_amt/Properties/AssemblyInfo.cs +++ b/ml_amt/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("AvatarMotionTweaker")] -[assembly: AssemblyVersion("1.2.4")] -[assembly: AssemblyFileVersion("1.2.4")] +[assembly: AssemblyVersion("1.2.5")] +[assembly: AssemblyFileVersion("1.2.5")] -[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.2.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.2.5", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] \ No newline at end of file diff --git a/ml_lme/LeapInput.cs b/ml_lme/LeapInput.cs index aa0cef4..585fbf1 100644 --- a/ml_lme/LeapInput.cs +++ b/ml_lme/LeapInput.cs @@ -111,6 +111,8 @@ namespace ml_lme { Settings.EnabledChange -= this.OnEnableChange; Settings.InputChange -= this.OnInputChange; + + MetaPort.Instance.settings.settingBoolChanged.RemoveListener(this.OnGameSettingBoolChange); } void Update() diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 5d6f2aa..47c28e4 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -284,6 +284,7 @@ namespace ml_prm if(BodySystem.isCalibratedAsFullBody) BodySystem.TrackingPositionWeight = 0f; + // Copy before set to non-kinematic to reduce stacked forces foreach(var l_link in m_boneLinks) l_link.Item2.CopyGlobal(l_link.Item1); @@ -322,10 +323,10 @@ namespace ml_prm } } } - } - foreach(Collider l_collider in m_colliders) - l_collider.enabled = m_enabled; + foreach(Collider l_collider in m_colliders) + l_collider.enabled = m_enabled; + } } public bool IsRagdolled() => (m_enabled && m_avatarReady); diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index cd2cb60..e1fef82 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -62,7 +62,7 @@ namespace ml_prm Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; VelocityMultiplier = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue, 0f, 50f); RestorePosition = (bool)ms_entries[(int)ModSetting.RestorePosition].BoxedValue; - MovementDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 100f); + MovementDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); AngularDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0.5f, 50f); Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue; @@ -116,7 +116,7 @@ namespace ml_prm VelocityMultiplierChange?.Invoke(value); }; - ms_uiElements.Add(l_page.AddSlider("Movement drag", "Movement resistance", MovementDrag, 0f, 100f)); + ms_uiElements.Add(l_page.AddSlider("Movement drag", "Movement resistance", MovementDrag, 0f, 50f)); (ms_uiElements[(int)UiElementIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => { MovementDrag = value; From 17b1d1d9cf1bfe096ef8391fe1080e314a501e48 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sun, 9 Apr 2023 14:14:31 +0000 Subject: [PATCH 21/63] Update README.md --- ml_prm/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ml_prm/README.md b/ml_prm/README.md index b93d250..81a3f7f 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -14,16 +14,20 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * **Use hotkey:** enables/disables ragdoll state switch with `R` key; `true` by default. * **Restore position:** returns to position of ragdoll state activation upon ragdoll state exit; `false` by default. * **Use gravity:** enables/disables gravity for ragdoll; `true` by default. + * Note: Forcibly enabled in worlds that don't allow flight. * **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. + * Note: Limited according to world's fly multiplier. + * Note: Forcibly set to `1.0` in worlds that don't allow flight. * **Movement drag:** movement resistance; `1.0` by default. * **Angular movement drag:** angular movement resistance; `0.5` by default. * **Reset settings:** resets mod settings to default. # Notes -* Incompatible with `Follow hips on IK override` option in AvatarMotionTweaker. +* Slightly incompatible with `Follow hips on IK override` option in AvatarMotionTweaker. * Not suggested to activate fly mode with enabled ragdoll state. -* In worlds that don't allow flying velocity multiplier is forced to 1 and gravity is forced on. -* If ragdoll state is enabled in during emote, remote players see whole emote playing while local player sees ragdolling. It's tied to how game handles remote players, currently can be prevented with renaming avatar emote animations to not have default name or containing `Emote` substring. +* If ragdoll state is enabled during emote, remote players see whole emote playing while local player sees ragdolling. It's tied to how game handles remote players, currently can be prevented with (choose one): + * Renaming avatar emote animations to not have default name or containing `Emote` substring. + * Holding any movement key when activating ragdoll state. # Unity Editor Script You can also trigger the ragdoll via animations on your avatar. To do this you need to download and import the From 96ab14c698f63877a398388138d2aa403fa30742 Mon Sep 17 00:00:00 2001 From: SDraw Date: Mon, 10 Apr 2023 00:28:41 +0300 Subject: [PATCH 22/63] Actual camera point instead of offset for eyes --- ml_amt/MotionTweaker.cs | 2 +- ml_amt/Utils.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ml_amt/MotionTweaker.cs b/ml_amt/MotionTweaker.cs index 98ace85..ec6e487 100644 --- a/ml_amt/MotionTweaker.cs +++ b/ml_amt/MotionTweaker.cs @@ -126,7 +126,7 @@ namespace ml_amt m_moving = !Mathf.Approximately(MovementSystem.Instance.movementVector.magnitude, 0f); // Update upright - Matrix4x4 l_hmdMatrix = PlayerSetup.Instance.transform.GetMatrix().inverse * (m_inVR ? PlayerSetup.Instance.vrHeadTracker.transform.GetMatrix() : PlayerSetup.Instance.desktopCameraRig.transform.GetMatrix()); + Matrix4x4 l_hmdMatrix = PlayerSetup.Instance.transform.GetMatrix().inverse * PlayerSetup.Instance.GetActiveCamera().transform.GetMatrix(); float l_currentHeight = Mathf.Clamp((l_hmdMatrix * ms_pointVector).y, 0f, float.MaxValue); float l_avatarViewHeight = Mathf.Clamp(m_viewPointHeight * GetRelativeScale(), 0f, float.MaxValue); m_upright = Mathf.Clamp01((l_avatarViewHeight > 0f) ? (l_currentHeight / l_avatarViewHeight) : 0f); diff --git a/ml_amt/Utils.cs b/ml_amt/Utils.cs index 140cadc..02eaf7a 100644 --- a/ml_amt/Utils.cs +++ b/ml_amt/Utils.cs @@ -1,5 +1,5 @@ -using UnityEngine; -using System.Reflection; +using System.Reflection; +using UnityEngine; namespace ml_amt { From 6a73e7f2ce438511c642b426973e59d4af6873ea Mon Sep 17 00:00:00 2001 From: SDraw Date: Mon, 10 Apr 2023 09:32:50 +0300 Subject: [PATCH 23/63] More stable ragdoll upon activation --- ml_prm/RagdollController.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 47c28e4..3ff666f 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -142,10 +142,18 @@ namespace ml_prm m_puppetReferences.rightLowerLeg = CloneTransform(l_avatarReferences.rightLowerLeg, m_puppetReferences.rightUpperLeg, "RightLowerLeg"); m_puppetReferences.rightFoot = CloneTransform(l_avatarReferences.rightFoot, m_puppetReferences.rightLowerLeg, "RightFoot"); + // Move to world origin to overcome possible issues, maybe? + m_puppetRoot.position = Vector3.zero; + m_puppetRoot.rotation = Quaternion.identity; + BipedRagdollCreator.Options l_options = BipedRagdollCreator.AutodetectOptions(m_puppetReferences); l_options.joints = RagdollCreator.JointType.Character; BipedRagdollCreator.Create(m_puppetReferences, l_options); + // And return back + m_puppetRoot.localPosition = Vector3.zero; + m_puppetRoot.localRotation = Quaternion.identity; + Transform[] l_puppetTransforms = m_puppetReferences.GetRagdollTransforms(); Transform[] l_avatarTransforms = l_avatarReferences.GetRagdollTransforms(); for(int i = 0; i < l_puppetTransforms.Length; i++) @@ -173,7 +181,10 @@ namespace ml_prm Collider l_collider = l_puppetTransforms[i].GetComponent(); if(l_collider != null) { - Physics.IgnoreCollision(MovementSystem.Instance.proxyCollider, l_collider, true); + l_collider.gameObject.layer = LayerMask.NameToLayer("PlayerLocal"); + Physics.IgnoreCollision(l_collider, MovementSystem.Instance.proxyCollider, true); + Physics.IgnoreCollision(l_collider, MovementSystem.Instance.controller, true); + Physics.IgnoreCollision(l_collider, MovementSystem.Instance.forceCollider, true); l_collider.enabled = false; m_colliders.Add(l_collider); } From dfa7da50d65f4b8470adb92ca82afa0961256c0f Mon Sep 17 00:00:00 2001 From: SDraw Date: Mon, 10 Apr 2023 15:36:37 +0300 Subject: [PATCH 24/63] Ragdoll controller public instance access Settings fix --- .../img_01.png} | Bin ml_prm/README.md | 12 ++++++-- ml_prm/RagdollController.cs | 17 ++++++++--- ml_prm/Settings.cs | 28 +++++++++--------- 4 files changed, 37 insertions(+), 20 deletions(-) rename ml_prm/{resources/ragdoll_toggle_editor_script.png => .github/img_01.png} (100%) diff --git a/ml_prm/resources/ragdoll_toggle_editor_script.png b/ml_prm/.github/img_01.png similarity index 100% rename from ml_prm/resources/ragdoll_toggle_editor_script.png rename to ml_prm/.github/img_01.png diff --git a/ml_prm/README.md b/ml_prm/README.md index 81a3f7f..f1a6571 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -27,7 +27,7 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * Not suggested to activate fly mode with enabled ragdoll state. * If ragdoll state is enabled during emote, remote players see whole emote playing while local player sees ragdolling. It's tied to how game handles remote players, currently can be prevented with (choose one): * Renaming avatar emote animations to not have default name or containing `Emote` substring. - * Holding any movement key when activating ragdoll state. + * Holding any movement key right after activating ragdoll state. # Unity Editor Script You can also trigger the ragdoll via animations on your avatar. To do this you need to download and import the @@ -37,6 +37,14 @@ your avatar's hierarchy. Now you can animate both parameters available: - **Should Override:** Whether the animation should override the toggled state of the ragdoll. - **Is On:** Whether the ragdoll state is On or Off (only works if `Should Override` is also On). -![](resources/ragdoll_toggle_editor_script.png) +![](.github/img_01.png) **Note:** In order to work the game object needs to be active and the component enabled. + +# Mods Integration +* Add mod's dll as reference in your project +* Access ragdoll controller with `ml_prm.RagdollController.Instance`. + +Available methods: +* ```bool IsRagdolled()``` +* ```void SwitchRagdoll()``` diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 3ff666f..00b5543 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -9,8 +9,11 @@ using UnityEngine; namespace ml_prm { - class RagdollController : MonoBehaviour + [DisallowMultipleComponent] + public class RagdollController : MonoBehaviour { + public static RagdollController Instance { get; private set; } = null; + VRIK m_vrIK = null; float m_vrIkWeight = 1f; @@ -31,10 +34,18 @@ namespace ml_prm internal RagdollController() { + if(Instance == null) + Instance = this; + m_rigidBodies = new List(); m_colliders = new List(); m_boneLinks = new List>(); } + ~RagdollController() + { + if(Instance == this) + Instance = null; + } // Unity events void Start() @@ -227,9 +238,7 @@ namespace ml_prm if(m_avatarReady) { foreach(Rigidbody l_body in m_rigidBodies) - { l_body.useGravity = (!Utils.IsWorldSafe() || Settings.Gravity); - } } } @@ -317,7 +326,7 @@ namespace ml_prm foreach(Rigidbody l_body in m_rigidBodies) l_body.isKinematic = true; - if((m_puppetReferences.hips != null)) + if(m_puppetReferences.hips != null) { Vector3 l_hipsPos = m_puppetReferences.hips.position; diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index e1fef82..7171f5e 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -6,7 +6,7 @@ namespace ml_prm { static class Settings { - public enum ModSetting + enum ModSetting { Hotkey = 0, VelocityMultiplier, @@ -29,8 +29,8 @@ namespace ml_prm public static bool Hotkey { get; private set; } = true; public static float VelocityMultiplier { get; private set; } = 2f; public static bool RestorePosition { get; private set; } = false; - public static float MovementDrag { get; private set; } = 1f; - public static float AngularDrag { get; private set; } = 0.5f; + public static float MovementDrag { get; private set; } = 2f; + public static float AngularDrag { get; private set; } = 2f; public static bool Gravity { get; private set; } = true; static public event Action SwitchChange; @@ -60,10 +60,10 @@ namespace ml_prm }; Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; - VelocityMultiplier = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue, 0f, 50f); + VelocityMultiplier = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue, 1f, 50f); RestorePosition = (bool)ms_entries[(int)ModSetting.RestorePosition].BoxedValue; MovementDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); - AngularDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0.5f, 50f); + AngularDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue; if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null) @@ -124,7 +124,7 @@ namespace ml_prm MovementDragChange?.Invoke(value); }; - ms_uiElements.Add(l_page.AddSlider("Angular movement drag", "Rotation movement resistance", AngularDrag, 0.5f, 50f)); + ms_uiElements.Add(l_page.AddSlider("Angular movement drag", "Rotation movement resistance", AngularDrag, 0f, 50f)); (ms_uiElements[(int)UiElementIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => { AngularDrag = value; @@ -154,15 +154,15 @@ namespace ml_prm (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(2f); VelocityMultiplierChange?.Invoke(2f); - MovementDrag = 1f; - ms_entries[(int)ModSetting.MovementDrag].BoxedValue = 1f; - (ms_uiElements[(int)UiElementIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(1f); - MovementDragChange?.Invoke(1f); + MovementDrag = 2f; + ms_entries[(int)ModSetting.MovementDrag].BoxedValue = 2f; + (ms_uiElements[(int)UiElementIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(2f); + MovementDragChange?.Invoke(2f); - AngularDrag = 0.5f; - ms_entries[(int)ModSetting.MovementDrag].BoxedValue = 0.5f; - (ms_uiElements[(int)UiElementIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(0.5f); - AngularDragChange?.Invoke(0.5f); + AngularDrag = 2f; + ms_entries[(int)ModSetting.MovementDrag].BoxedValue = 2f; + (ms_uiElements[(int)UiElementIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(2f); + AngularDragChange?.Invoke(2f); }; } } From faac28fb887dd1baa3595c0804a0eb6d4d26960b Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 11 Apr 2023 00:18:41 +0300 Subject: [PATCH 25/63] Reaction to CVRPointer component with `ragdoll` type --- ml_prm/RagdollController.cs | 12 +++++++++++ ml_prm/RagdollTrigger.cs | 42 +++++++++++++++++++++++++++++++++++++ ml_prm/Settings.cs | 21 ++++++++++++++++++- ml_prm/ml_prm.csproj | 1 + 4 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 ml_prm/RagdollTrigger.cs diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 00b5543..db0e46c 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -31,6 +31,7 @@ namespace ml_prm Vector3 m_velocity = Vector3.zero; RagdollToggle m_avatarRagdollToggle = null; + RagdollTrigger m_customTrigger = null; internal RagdollController() { @@ -55,6 +56,8 @@ namespace ml_prm m_puppetRoot.localPosition = Vector3.zero; m_puppetRoot.localRotation = Quaternion.identity; + m_customTrigger = MovementSystem.Instance.proxyCollider.gameObject.AddComponent(); + Settings.SwitchChange += this.SwitchRagdoll; Settings.MovementDragChange += this.OnMovementDragChange; Settings.AngularDragChange += this.OnAngularDragChange; @@ -63,6 +66,12 @@ namespace ml_prm void OnDestroy() { + if(m_customTrigger != null) + { + Object.Destroy(m_customTrigger); + m_customTrigger = null; + } + Settings.SwitchChange -= this.SwitchRagdoll; Settings.MovementDragChange -= this.OnMovementDragChange; Settings.AngularDragChange -= this.OnAngularDragChange; @@ -83,6 +92,9 @@ namespace ml_prm if(m_enabled && m_avatarReady && BodySystem.isCalibratedAsFullBody) BodySystem.TrackingPositionWeight = 0f; + + if(!m_enabled && m_avatarReady && (m_customTrigger != null) && m_customTrigger.GetStateWithReset() && Settings.PointersReaction) + SwitchRagdoll(); } void LateUpdate() diff --git a/ml_prm/RagdollTrigger.cs b/ml_prm/RagdollTrigger.cs new file mode 100644 index 0000000..4b05c67 --- /dev/null +++ b/ml_prm/RagdollTrigger.cs @@ -0,0 +1,42 @@ +using ABI.CCK.Components; +using UnityEngine; + +namespace ml_prm +{ + [DisallowMultipleComponent] + class RagdollTrigger : MonoBehaviour + { + static int ms_localPlayerLayer = 0; + + Collider m_lastCollider = null; + bool m_triggered = false; + + void Start() + { + ms_localPlayerLayer = LayerMask.NameToLayer("PlayerLocal"); + } + + void OnTriggerEnter(Collider p_other) + { + CVRPointer l_pointer = p_other.gameObject.GetComponent(); + if((l_pointer != null) && l_pointer.type == "ragdoll" && p_other.gameObject.layer == ms_localPlayerLayer && (m_lastCollider != p_other)) + { + m_lastCollider = p_other; + m_triggered = true; + } + } + + void OnTriggerExit(Collider p_other) + { + if(m_lastCollider == p_other) + m_lastCollider = null; + } + + public bool GetStateWithReset() + { + bool l_state = m_triggered; + m_triggered = false; + return l_state; + } + } +} diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index 7171f5e..bd44fd3 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -13,7 +13,8 @@ namespace ml_prm RestorePosition, MovementDrag, AngularDrag, - Gravity + Gravity, + PointersReaction } enum UiElementIndex @@ -21,6 +22,7 @@ namespace ml_prm Hotkey = 0, RestorePosition, Gravity, + PointersReaction, VelocityMultiplier, MovementDrag, AngularDrag @@ -32,6 +34,7 @@ namespace ml_prm public static float MovementDrag { get; private set; } = 2f; public static float AngularDrag { get; private set; } = 2f; public static bool Gravity { get; private set; } = true; + public static bool PointersReaction { get; private set; } = true; static public event Action SwitchChange; static public event Action HotkeyChange; @@ -40,6 +43,7 @@ namespace ml_prm static public event Action MovementDragChange; static public event Action AngularDragChange; static public event Action GravityChange; + static public event Action PointersReactionChange; static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; @@ -57,6 +61,7 @@ namespace ml_prm ms_category.CreateEntry(ModSetting.MovementDrag.ToString(), MovementDrag), ms_category.CreateEntry(ModSetting.AngularDrag.ToString(), AngularDrag), ms_category.CreateEntry(ModSetting.Gravity.ToString(), Gravity), + ms_category.CreateEntry(ModSetting.PointersReaction.ToString(), PointersReaction) }; Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; @@ -65,6 +70,7 @@ namespace ml_prm MovementDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); AngularDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue; + PointersReaction = (bool)ms_entries[(int)ModSetting.PointersReaction].BoxedValue; if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null) { @@ -108,6 +114,14 @@ namespace ml_prm GravityChange?.Invoke(state); }; + ms_uiElements.Add(l_categoryMod.AddToggle("Pointers reaction", "React to CVRPointer components with 'ragdoll' type", PointersReaction)); + (ms_uiElements[(int)UiElementIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => + { + PointersReaction = state; + ms_entries[(int)ModSetting.PointersReaction].BoxedValue = state; + PointersReactionChange?.Invoke(state); + }; + ms_uiElements.Add(l_page.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", VelocityMultiplier, 1f, 50f)); (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => { @@ -149,6 +163,11 @@ namespace ml_prm (ms_uiElements[(int)UiElementIndex.Gravity] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; GravityChange?.Invoke(true); + PointersReaction = true; + ms_entries[(int)ModSetting.PointersReaction].BoxedValue = true; + (ms_uiElements[(int)UiElementIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; + PointersReactionChange?.Invoke(true); + VelocityMultiplier = 2f; ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue = 2f; (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(2f); diff --git a/ml_prm/ml_prm.csproj b/ml_prm/ml_prm.csproj index d2d89ba..4a041d1 100644 --- a/ml_prm/ml_prm.csproj +++ b/ml_prm/ml_prm.csproj @@ -86,6 +86,7 @@ + From 73b09dd5fb9a3dcf40d960d8c767d349dee0718d Mon Sep 17 00:00:00 2001 From: SDraw Date: Mon, 10 Apr 2023 22:29:27 +0000 Subject: [PATCH 26/63] Update README.md --- ml_prm/README.md | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/ml_prm/README.md b/ml_prm/README.md index f1a6571..07a3039 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -15,36 +15,38 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * **Restore position:** returns to position of ragdoll state activation upon ragdoll state exit; `false` by default. * **Use gravity:** enables/disables gravity for ragdoll; `true` by default. * Note: Forcibly enabled in worlds that don't allow flight. +* **Pointers reaction:** enables ragdoll state when player collides with CVRPointer colliders of `ragdoll` type (avatars, props and world included) on `PlayerLocal` layer; `true` by default. * **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. * Note: Limited according to world's fly multiplier. * Note: Forcibly set to `1.0` in worlds that don't allow flight. -* **Movement drag:** movement resistance; `1.0` by default. -* **Angular movement drag:** angular movement resistance; `0.5` by default. +* **Movement drag:** movement resistance; `2.0` by default. +* **Angular movement drag:** angular movement resistance; `2.0` by default. * **Reset settings:** resets mod settings to default. +# Unity Editor Script +You can also trigger the ragdoll via animations on your avatar. To do this you need: +* Download and import the `ml_prm_editor_script.unitypackage` into your unity project +* Add the component `Ragdoll Toggle` anywhere inside of your avatar's hierarchy. + +Now you can animate both parameters available: +- **Should Override:** whether the animation should override the toggled state of the ragdoll. +- **Is On:** whether the ragdoll state is On or Off (only works if `Should Override` is also On). + +![](.github/img_01.png) +Note: In order to work the game object needs to be active and the component enabled. + +# Mods Integration +You can use this mod's functions within your mod. To do this you need: +* Add mod's dll as reference in your project +* Access ragdoll controller with `ml_prm.RagdollController.Instance` + +Available methods: +* ```bool IsRagdolled()``` +* ```void SwitchRagdoll()``` + # Notes * Slightly incompatible with `Follow hips on IK override` option in AvatarMotionTweaker. * Not suggested to activate fly mode with enabled ragdoll state. * If ragdoll state is enabled during emote, remote players see whole emote playing while local player sees ragdolling. It's tied to how game handles remote players, currently can be prevented with (choose one): * Renaming avatar emote animations to not have default name or containing `Emote` substring. * Holding any movement key right after activating ragdoll state. - -# Unity Editor Script -You can also trigger the ragdoll via animations on your avatar. To do this you need to download and import the -`ml_prm_editor_script.unitypackage` into your unity project. Then add the component `Ragdoll Toggle` anywhere inside of -your avatar's hierarchy. Now you can animate both parameters available: - -- **Should Override:** Whether the animation should override the toggled state of the ragdoll. -- **Is On:** Whether the ragdoll state is On or Off (only works if `Should Override` is also On). - -![](.github/img_01.png) - -**Note:** In order to work the game object needs to be active and the component enabled. - -# Mods Integration -* Add mod's dll as reference in your project -* Access ragdoll controller with `ml_prm.RagdollController.Instance`. - -Available methods: -* ```bool IsRagdolled()``` -* ```void SwitchRagdoll()``` From 9a262b2ded5c52083a3cc964091543510cd2442b Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 11 Apr 2023 09:46:27 +0300 Subject: [PATCH 27/63] Minor fixes --- ml_prm/RagdollController.cs | 10 ++++++---- ml_prm/RagdollTrigger.cs | 9 ++------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index db0e46c..de063e5 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -93,7 +93,7 @@ namespace ml_prm if(m_enabled && m_avatarReady && BodySystem.isCalibratedAsFullBody) BodySystem.TrackingPositionWeight = 0f; - if(!m_enabled && m_avatarReady && (m_customTrigger != null) && m_customTrigger.GetStateWithReset() && Settings.PointersReaction) + if((m_customTrigger != null) && m_customTrigger.GetStateWithReset() && !m_enabled && m_avatarReady && Settings.PointersReaction) SwitchRagdoll(); } @@ -277,7 +277,8 @@ namespace ml_prm foreach(Rigidbody l_body in m_rigidBodies) { l_body.drag = p_value; - l_body.WakeUp(); + if(m_enabled) + l_body.WakeUp(); } } } @@ -288,7 +289,8 @@ namespace ml_prm foreach(Rigidbody l_body in m_rigidBodies) { l_body.angularDrag = p_value; - l_body.WakeUp(); + if(m_enabled) + l_body.WakeUp(); } } } @@ -309,10 +311,10 @@ namespace ml_prm m_enabled = !m_enabled; MovementSystem.Instance.SetImmobilized(m_enabled); - PlayerSetup.Instance.animatorManager.SetAnimatorParameterTrigger("CancelEmote"); if(m_enabled) { + PlayerSetup.Instance.animatorManager.SetAnimatorParameterTrigger("CancelEmote"); if(BodySystem.isCalibratedAsFullBody) BodySystem.TrackingPositionWeight = 0f; diff --git a/ml_prm/RagdollTrigger.cs b/ml_prm/RagdollTrigger.cs index 4b05c67..83f987f 100644 --- a/ml_prm/RagdollTrigger.cs +++ b/ml_prm/RagdollTrigger.cs @@ -6,20 +6,15 @@ namespace ml_prm [DisallowMultipleComponent] class RagdollTrigger : MonoBehaviour { - static int ms_localPlayerLayer = 0; + static readonly int ms_localPlayerLayer = LayerMask.NameToLayer("PlayerLocal"); Collider m_lastCollider = null; bool m_triggered = false; - void Start() - { - ms_localPlayerLayer = LayerMask.NameToLayer("PlayerLocal"); - } - void OnTriggerEnter(Collider p_other) { CVRPointer l_pointer = p_other.gameObject.GetComponent(); - if((l_pointer != null) && l_pointer.type == "ragdoll" && p_other.gameObject.layer == ms_localPlayerLayer && (m_lastCollider != p_other)) + if((l_pointer != null) && (l_pointer.type == "ragdoll") && (p_other.gameObject.layer == ms_localPlayerLayer) && (m_lastCollider != p_other)) { m_lastCollider = p_other; m_triggered = true; From 92a058a0acba32356438b6f204c4157671f1e42d Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 11 Apr 2023 10:17:32 +0300 Subject: [PATCH 28/63] Removed `PlayerLocal` layer usage to avoid possible world maps problems --- ml_prm/RagdollController.cs | 1 - ml_prm/RagdollTrigger.cs | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index de063e5..4b91dca 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -204,7 +204,6 @@ namespace ml_prm Collider l_collider = l_puppetTransforms[i].GetComponent(); if(l_collider != null) { - l_collider.gameObject.layer = LayerMask.NameToLayer("PlayerLocal"); Physics.IgnoreCollision(l_collider, MovementSystem.Instance.proxyCollider, true); Physics.IgnoreCollision(l_collider, MovementSystem.Instance.controller, true); Physics.IgnoreCollision(l_collider, MovementSystem.Instance.forceCollider, true); diff --git a/ml_prm/RagdollTrigger.cs b/ml_prm/RagdollTrigger.cs index 83f987f..fb0ee93 100644 --- a/ml_prm/RagdollTrigger.cs +++ b/ml_prm/RagdollTrigger.cs @@ -6,15 +6,13 @@ namespace ml_prm [DisallowMultipleComponent] class RagdollTrigger : MonoBehaviour { - static readonly int ms_localPlayerLayer = LayerMask.NameToLayer("PlayerLocal"); - Collider m_lastCollider = null; bool m_triggered = false; void OnTriggerEnter(Collider p_other) { CVRPointer l_pointer = p_other.gameObject.GetComponent(); - if((l_pointer != null) && (l_pointer.type == "ragdoll") && (p_other.gameObject.layer == ms_localPlayerLayer) && (m_lastCollider != p_other)) + if((l_pointer != null) && (l_pointer.type == "ragdoll") && (m_lastCollider != p_other)) { m_lastCollider = p_other; m_triggered = true; From 5185c00fb12d86645dbcfaf7debfc068402c4dce Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 11 Apr 2023 10:44:06 +0300 Subject: [PATCH 29/63] Update README.md --- ml_prm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ml_prm/README.md b/ml_prm/README.md index 07a3039..b233754 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -15,7 +15,7 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * **Restore position:** returns to position of ragdoll state activation upon ragdoll state exit; `false` by default. * **Use gravity:** enables/disables gravity for ragdoll; `true` by default. * Note: Forcibly enabled in worlds that don't allow flight. -* **Pointers reaction:** enables ragdoll state when player collides with CVRPointer colliders of `ragdoll` type (avatars, props and world included) on `PlayerLocal` layer; `true` by default. +* **Pointers reaction:** enables ragdoll state when player collides with CVRPointer colliders of `ragdoll` type (avatars, props and world included); `true` by default. * **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. * Note: Limited according to world's fly multiplier. * Note: Forcibly set to `1.0` in worlds that don't allow flight. From 912b37c87f46c9875506b2172ba983e9f731bd4f Mon Sep 17 00:00:00 2001 From: SDraw Date: Wed, 12 Apr 2023 21:33:25 +0300 Subject: [PATCH 30/63] Check for props game settings and world restrictions Combat system integration Additional measure for unsafe worlds --- README.md | 2 +- ml_egn/Main.cs | 32 +++++-- ml_egn/Properties/AssemblyInfo.cs | 6 +- ml_egn/Utils.cs | 4 + ml_prm/Main.cs | 24 +++++ ml_prm/README.md | 1 + ml_prm/RagdollController.cs | 142 +++++++++++++++++++++--------- ml_prm/Settings.cs | 23 ++++- ml_prm/Utils.cs | 9 +- 9 files changed, 186 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 07df240..0152fa5 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Merged set of MelonLoader mods for ChilloutVR. | Avatar Motion Tweaker | ml_amt | 1.2.5 | Yes, update review | Working | | Desktop Head Tracking | ml_dht | 1.1.2 | Yes | Working | | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | -| Extended Game Notifications | ml_egn | 1.0.1 | Yes | Working +| Extended Game Notifications | ml_egn | 1.0.2 | Yes, update review | Working | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update | Leap Motion Extension | ml_lme | 1.3.3 | Yes | Working | | Pickup Arm Movement | ml_pam | 1.0.2 | Yes| Working | diff --git a/ml_egn/Main.cs b/ml_egn/Main.cs index c77bf82..90d54a2 100644 --- a/ml_egn/Main.cs +++ b/ml_egn/Main.cs @@ -1,5 +1,4 @@ using ABI_RC.Core.EventSystem; -using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.IO; using ABI_RC.Core.Networking; using ABI_RC.Core.Util; @@ -57,6 +56,7 @@ namespace ml_egn Utils.ShowMenuNotification("Avatar changed", 1f); else Utils.ShowHUDNotification("(Synced) Client", "Avatar changed"); + } catch(System.Exception e) { @@ -68,19 +68,37 @@ namespace ml_egn { try { - if(Utils.IsConnected()) + if(Utils.ArePropsEnabled()) { - if(Utils.IsMenuOpened()) - Utils.ShowMenuNotification("Prop spawned", 1f); + if(Utils.ArePropsAllowed()) + { + if(Utils.IsConnected()) + { + if(Utils.IsMenuOpened()) + Utils.ShowMenuNotification("Prop spawned", 1f); + else + Utils.ShowHUDNotification("(Synced) Client", "Prop spawned"); + } + else + { + if(Utils.IsMenuOpened()) + Utils.ShowMenuAlert("Prop Error", "Not connected to live instance"); + else + Utils.ShowHUDNotification("(Local) Client", "Unable to spawn prop", "Not connected to live instance"); + } + } else - Utils.ShowHUDNotification("(Synced) Client", "Prop spawned"); + { + if(Utils.IsMenuOpened()) + Utils.ShowMenuAlert("Prop Error", "Props are not allowed in this world"); + } } else { if(Utils.IsMenuOpened()) - Utils.ShowMenuAlert("Prop Error", "Not connected to live instance"); + Utils.ShowMenuAlert("Prop Error", "Props are disabled in game settings"); else - Utils.ShowHUDNotification("(Local) Client", "Unable to spawn prop", "Not connected to live instance"); + Utils.ShowHUDNotification("(Local) Client", "Unable to spawn prop", "Props are disabled in game settings"); } } catch(System.Exception e) diff --git a/ml_egn/Properties/AssemblyInfo.cs b/ml_egn/Properties/AssemblyInfo.cs index f1610b5..2bd2627 100644 --- a/ml_egn/Properties/AssemblyInfo.cs +++ b/ml_egn/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("ExtendedGameNotifications")] -[assembly: AssemblyVersion("1.0.1")] -[assembly: AssemblyFileVersion("1.0.1")] +[assembly: AssemblyVersion("1.0.2")] +[assembly: AssemblyFileVersion("1.0.2")] -[assembly: MelonLoader.MelonInfo(typeof(ml_egn.ExtendedGameNotifications), "ExtendedGameNotifications", "1.0.1", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_egn.ExtendedGameNotifications), "ExtendedGameNotifications", "1.0.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] \ No newline at end of file diff --git a/ml_egn/Utils.cs b/ml_egn/Utils.cs index f4935b9..319e7ac 100644 --- a/ml_egn/Utils.cs +++ b/ml_egn/Utils.cs @@ -1,5 +1,6 @@ using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Networking; +using ABI_RC.Core.Savior; using ABI_RC.Core.UI; using DarkRift; @@ -42,5 +43,8 @@ namespace ml_egn l_result = (NetworkManager.Instance.GameNetwork.ConnectionState == ConnectionState.Connected); return l_result; } + + public static bool ArePropsAllowed() => ((MetaPort.Instance != null) && MetaPort.Instance.worldAllowProps); + public static bool ArePropsEnabled() => ((MetaPort.Instance != null) && MetaPort.Instance.settings.GetSettingsBool("ContentFilterPropsEnabled")); } } diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs index 8a53961..a8abb8f 100644 --- a/ml_prm/Main.cs +++ b/ml_prm/Main.cs @@ -6,6 +6,8 @@ using System; using System.Collections.Generic; using System.Reflection; using ABI_RC.Core.Util.AssetFiltering; +using ABI.CCK.Components; +using System.Linq; namespace ml_prm { @@ -47,6 +49,11 @@ namespace ml_prm new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnWorldSpawn_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), null ); + HarmonyInstance.Patch( + typeof(CombatSystem).GetMethods().First(m => (!m.IsGenericMethod && m.Name == nameof(CombatSystem.Down))), + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnCombatDown_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + null + ); // Whitelist the toggle script (typeof(SharedFilter).GetField("_localComponentWhitelist", BindingFlags.NonPublic | BindingFlags.Static)?.GetValue(null) as HashSet)?.Add(typeof(RagdollToggle)); @@ -140,5 +147,22 @@ namespace ml_prm } } + static void OnCombatDown_Prefix(ref CombatSystem __instance) + { + if((__instance == CombatSystem.Instance) && !__instance.isDown) + ms_instance?.OnCombatDown(); + } + void OnCombatDown() + { + try + { + if(m_localController != null) + m_localController.OnCombatDown(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } } } diff --git a/ml_prm/README.md b/ml_prm/README.md index b233754..fb8142a 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -16,6 +16,7 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * **Use gravity:** enables/disables gravity for ragdoll; `true` by default. * Note: Forcibly enabled in worlds that don't allow flight. * **Pointers reaction:** enables ragdoll state when player collides with CVRPointer colliders of `ragdoll` type (avatars, props and world included); `true` by default. +* **Combat reaction:** enables ragdoll state upon death in worlds with combat system; `true` by default. * **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. * Note: Limited according to world's fly multiplier. * Note: Forcibly set to `1.0` in worlds that don't allow flight. diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 4b91dca..c66e8bd 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -1,4 +1,5 @@ -using ABI_RC.Core.InteractionSystem; +using ABI.CCK.Components; +using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Player; using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.MovementSystem; @@ -33,6 +34,8 @@ namespace ml_prm RagdollToggle m_avatarRagdollToggle = null; RagdollTrigger m_customTrigger = null; + bool m_reachedGround = true; + internal RagdollController() { if(Instance == null) @@ -84,15 +87,18 @@ namespace ml_prm m_velocity = (m_velocity + (l_pos - m_lastPosition) / Time.deltaTime) * 0.5f; m_lastPosition = l_pos; + if(m_avatarReady && !m_reachedGround && MovementSystem.Instance.IsGrounded()) + m_reachedGround = true; + + if(m_enabled && m_avatarReady && BodySystem.isCalibratedAsFullBody) + BodySystem.TrackingPositionWeight = 0f; + if(Settings.Hotkey && Input.GetKeyDown(KeyCode.R) && !ViewManager.Instance.isGameMenuOpen()) SwitchRagdoll(); if((m_avatarRagdollToggle != null) && m_avatarRagdollToggle.isActiveAndEnabled && m_avatarRagdollToggle.shouldOverride && (m_enabled != m_avatarRagdollToggle.isOn)) SwitchRagdoll(); - if(m_enabled && m_avatarReady && BodySystem.isCalibratedAsFullBody) - BodySystem.TrackingPositionWeight = 0f; - if((m_customTrigger != null) && m_customTrigger.GetStateWithReset() && !m_enabled && m_avatarReady && Settings.PointersReaction) SwitchRagdoll(); } @@ -127,6 +133,7 @@ namespace ml_prm m_colliders.Clear(); m_puppetReferences = new BipedRagdollReferences(); m_boneLinks.Clear(); + m_reachedGround = true; } internal void OnAvatarSetup() @@ -253,6 +260,12 @@ namespace ml_prm } } + internal void OnCombatDown() + { + if(!m_enabled && m_avatarReady && Settings.CombatReaction) + SwitchRagdoll(); + } + // IK updates void OnIKPreUpdate() { @@ -305,60 +318,88 @@ namespace ml_prm // Arbitrary public void SwitchRagdoll() { - if(m_avatarReady && (MovementSystem.Instance.lastSeat == null) && !BodySystem.isCalibrating) + if(m_avatarReady) { - m_enabled = !m_enabled; - - MovementSystem.Instance.SetImmobilized(m_enabled); - - if(m_enabled) + if(!m_enabled) { - PlayerSetup.Instance.animatorManager.SetAnimatorParameterTrigger("CancelEmote"); - if(BodySystem.isCalibratedAsFullBody) - BodySystem.TrackingPositionWeight = 0f; - - // Copy before set to non-kinematic to reduce stacked forces - foreach(var l_link in m_boneLinks) - l_link.Item2.CopyGlobal(l_link.Item1); - - foreach(Rigidbody l_body in m_rigidBodies) - l_body.isKinematic = false; - - Vector3 l_velocity = m_velocity * Mathf.Clamp(Settings.VelocityMultiplier, 1f, (Utils.IsWorldSafe() ? Utils.GetWorldFlyMultiplier() : 1f)); - foreach(Rigidbody l_body in m_rigidBodies) + if(IsSafeToRagdoll() && m_reachedGround) { - l_body.velocity = l_velocity; - l_body.angularVelocity = Vector3.zero; + // Eject player from seat + if(MovementSystem.Instance.lastSeat != null) + { + Vector3 l_pos = PlayerSetup.Instance.transform.position; + Quaternion l_rot = PlayerSetup.Instance.transform.rotation; + MovementSystem.Instance.lastSeat.ExitSeat(); + PlayerSetup.Instance.transform.position = l_pos; + PlayerSetup.Instance.transform.rotation = Quaternion.Euler(0f, l_rot.eulerAngles.y, 0f); + } + + MovementSystem.Instance.SetImmobilized(true); + PlayerSetup.Instance.animatorManager.SetAnimatorParameterTrigger("CancelEmote"); + if(BodySystem.isCalibratedAsFullBody) + BodySystem.TrackingPositionWeight = 0f; + + if(!Utils.IsWorldSafe()) + m_reachedGround = false; // Force player to unragdoll and reach ground first + + // Copy before set to non-kinematic to reduce stacked forces + foreach(var l_link in m_boneLinks) + l_link.Item2.CopyGlobal(l_link.Item1); + + foreach(Rigidbody l_body in m_rigidBodies) + l_body.isKinematic = false; + + Vector3 l_velocity = m_velocity * Mathf.Clamp(Settings.VelocityMultiplier, 1f, (Utils.IsWorldSafe() ? Utils.GetWorldFlyMultiplier() : 1f)); + + foreach(Rigidbody l_body in m_rigidBodies) + { + l_body.velocity = l_velocity; + l_body.angularVelocity = Vector3.zero; + } + + foreach(Collider l_collider in m_colliders) + l_collider.enabled = true; + + m_enabled = true; } } else { - if(BodySystem.isCalibratedAsFullBody) - BodySystem.TrackingPositionWeight = 1f; - - foreach(Rigidbody l_body in m_rigidBodies) - l_body.isKinematic = true; - - if(m_puppetReferences.hips != null) + if(IsSafeToUnragdoll()) { - Vector3 l_hipsPos = m_puppetReferences.hips.position; + MovementSystem.Instance.SetImmobilized(false); + if(BodySystem.isCalibratedAsFullBody) + BodySystem.TrackingPositionWeight = 1f; - if(!Settings.RestorePosition) + foreach(Rigidbody l_body in m_rigidBodies) + l_body.isKinematic = true; + + if(m_puppetReferences.hips != null) { - if(Utils.IsInVR()) + Vector3 l_hipsPos = m_puppetReferences.hips.position; + + if(!Settings.RestorePosition) { - Vector3 l_diff = l_hipsPos - PlayerSetup.Instance._avatar.transform.position; - Vector3 l_playerPos = PlayerSetup.Instance.transform.position; - PlayerSetup.Instance.transform.position = l_playerPos + l_diff; + if(Utils.IsInVR()) + { + Vector3 l_diff = l_hipsPos - PlayerSetup.Instance._avatar.transform.position; + Vector3 l_playerPos = PlayerSetup.Instance.transform.position; + PlayerSetup.Instance.transform.position = l_playerPos + l_diff; + } + else + PlayerSetup.Instance.transform.position = l_hipsPos; } - else - PlayerSetup.Instance.transform.position = l_hipsPos; } + + foreach(Collider l_collider in m_colliders) + l_collider.enabled = false; + + m_lastPosition = PlayerSetup.Instance.transform.position; + m_velocity = Vector3.zero; + + m_enabled = false; } } - - foreach(Collider l_collider in m_colliders) - l_collider.enabled = m_enabled; } } @@ -371,5 +412,20 @@ namespace ml_prm p_source.CopyGlobal(l_target); return l_target; } + + static bool IsSafeToRagdoll() + { + bool l_result = true; + l_result &= !BodySystem.isCalibrating; // Not calibrating + l_result &= ((CombatSystem.Instance == null) || !CombatSystem.Instance.isDown); // Non-combat world or not dead + return l_result; + } + + static bool IsSafeToUnragdoll() + { + bool l_result = true; + l_result &= ((CombatSystem.Instance == null) || !CombatSystem.Instance.isDown); // Non-combat world or not dead + return l_result; + } } } diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index bd44fd3..79e2187 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -14,7 +14,8 @@ namespace ml_prm MovementDrag, AngularDrag, Gravity, - PointersReaction + PointersReaction, + CombatReaction } enum UiElementIndex @@ -23,6 +24,7 @@ namespace ml_prm RestorePosition, Gravity, PointersReaction, + CombatReaction, VelocityMultiplier, MovementDrag, AngularDrag @@ -35,6 +37,7 @@ namespace ml_prm public static float AngularDrag { get; private set; } = 2f; public static bool Gravity { get; private set; } = true; public static bool PointersReaction { get; private set; } = true; + public static bool CombatReaction { get; private set; } = true; static public event Action SwitchChange; static public event Action HotkeyChange; @@ -44,6 +47,7 @@ namespace ml_prm static public event Action AngularDragChange; static public event Action GravityChange; static public event Action PointersReactionChange; + static public event Action CombatReactionChange; static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; @@ -61,7 +65,8 @@ namespace ml_prm ms_category.CreateEntry(ModSetting.MovementDrag.ToString(), MovementDrag), ms_category.CreateEntry(ModSetting.AngularDrag.ToString(), AngularDrag), ms_category.CreateEntry(ModSetting.Gravity.ToString(), Gravity), - ms_category.CreateEntry(ModSetting.PointersReaction.ToString(), PointersReaction) + ms_category.CreateEntry(ModSetting.PointersReaction.ToString(), PointersReaction), + ms_category.CreateEntry(ModSetting.CombatReaction.ToString(), CombatReaction) }; Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; @@ -71,6 +76,7 @@ namespace ml_prm AngularDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue; PointersReaction = (bool)ms_entries[(int)ModSetting.PointersReaction].BoxedValue; + CombatReaction = (bool)ms_entries[(int)ModSetting.CombatReaction].BoxedValue; if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null) { @@ -122,6 +128,14 @@ namespace ml_prm PointersReactionChange?.Invoke(state); }; + ms_uiElements.Add(l_categoryMod.AddToggle("Combat reaction", "Ragdoll upon combat system death", CombatReaction)); + (ms_uiElements[(int)UiElementIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => + { + CombatReaction = state; + ms_entries[(int)ModSetting.CombatReaction].BoxedValue = state; + CombatReactionChange?.Invoke(state); + }; + ms_uiElements.Add(l_page.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", VelocityMultiplier, 1f, 50f)); (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => { @@ -168,6 +182,11 @@ namespace ml_prm (ms_uiElements[(int)UiElementIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; PointersReactionChange?.Invoke(true); + CombatReaction = true; + ms_entries[(int)ModSetting.CombatReaction].BoxedValue = true; + (ms_uiElements[(int)UiElementIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; + CombatReactionChange?.Invoke(true); + VelocityMultiplier = 2f; ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue = 2f; (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(2f); diff --git a/ml_prm/Utils.cs b/ml_prm/Utils.cs index 36a8c74..c6eb321 100644 --- a/ml_prm/Utils.cs +++ b/ml_prm/Utils.cs @@ -1,11 +1,16 @@ using ABI.CCK.Components; +using ABI_RC.Core.Savior; +using ABI_RC.Systems.MovementSystem; +using System.Reflection; using UnityEngine; namespace ml_prm { static class Utils { - public static bool IsInVR() => ((ABI_RC.Core.Savior.CheckVR.Instance != null) && ABI_RC.Core.Savior.CheckVR.Instance.hasVrDeviceLoaded); + static readonly FieldInfo ms_grounded = typeof(MovementSystem).GetField("_isGrounded", BindingFlags.NonPublic | BindingFlags.Instance); + + public static bool IsInVR() => ((CheckVR.Instance != null) && CheckVR.Instance.hasVrDeviceLoaded); public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying); public static float GetWorldFlyMultiplier() { @@ -15,6 +20,8 @@ namespace ml_prm return l_result; } + public static bool IsGrounded(this MovementSystem p_instance) => (bool)ms_grounded.GetValue(p_instance); + public static void CopyGlobal(this Transform p_source, Transform p_target) { p_target.position = p_source.position; From 2c7c90c7928afa12c89907462587bb5106ed77ea Mon Sep 17 00:00:00 2001 From: SDraw Date: Thu, 13 Apr 2023 15:59:40 +0300 Subject: [PATCH 31/63] `Ragdolled` avatar's animator boolean parameter Simplified additional parameters parsing --- ml_amt/AvatarParameter.cs | 67 +++++++++++++++++++---------------- ml_amt/MotionTweaker.cs | 26 +++----------- ml_amt/README.md | 4 +-- ml_prm/AvatarBoolParameter.cs | 43 ++++++++++++++++++++++ ml_prm/README.md | 4 +++ ml_prm/RagdollController.cs | 5 +++ ml_prm/ml_prm.csproj | 1 + 7 files changed, 97 insertions(+), 53 deletions(-) create mode 100644 ml_prm/AvatarBoolParameter.cs diff --git a/ml_amt/AvatarParameter.cs b/ml_amt/AvatarParameter.cs index 3349104..7bec1d3 100644 --- a/ml_amt/AvatarParameter.cs +++ b/ml_amt/AvatarParameter.cs @@ -1,4 +1,6 @@ -using ABI_RC.Core.Player; +using ABI_RC.Core; +using System.Text.RegularExpressions; +using UnityEngine; namespace ml_amt { @@ -11,24 +13,30 @@ namespace ml_amt Moving } - public enum ParameterSyncType - { - Synced, - Local - } + readonly ParameterType m_type; + readonly string m_name; + readonly int m_hash = 0; + readonly bool m_sync; + readonly AnimatorControllerParameterType m_innerType; + readonly CVRAnimatorManager m_manager = null; - public readonly ParameterType m_type; - public readonly ParameterSyncType m_sync; - public readonly string m_name; - public readonly int m_hash; // For local only - - - public AvatarParameter(ParameterType p_type, string p_name, ParameterSyncType p_sync = ParameterSyncType.Synced, int p_hash = 0) + public AvatarParameter(ParameterType p_type, CVRAnimatorManager p_manager) { m_type = p_type; - m_sync = p_sync; - m_name = p_name; - m_hash = p_hash; + m_name = p_type.ToString(); + m_manager = p_manager; + + Regex l_regex = new Regex("^#?" + m_name + '$'); + foreach(var l_param in m_manager.animator.parameters) + { + if(l_regex.IsMatch(l_param.name)) + { + m_hash = l_param.nameHash; + m_sync = (l_param.name[0] != '#'); + m_innerType = l_param.type; + break; + } + } } public void Update(MotionTweaker p_tweaker) @@ -49,29 +57,28 @@ namespace ml_amt } } + public bool IsValid() => (m_hash != 0); + public ParameterType GetParameterType() => m_type; + void SetFloat(float p_value) { - switch(m_sync) + if(m_innerType == AnimatorControllerParameterType.Float) { - case ParameterSyncType.Local: - PlayerSetup.Instance._animator.SetFloat(m_hash, p_value); - break; - case ParameterSyncType.Synced: - PlayerSetup.Instance.animatorManager.SetAnimatorParameterFloat(m_name, p_value); - break; + if(m_sync) + m_manager.SetAnimatorParameterFloat(m_name, p_value); + else + m_manager.animator.SetFloat(m_hash, p_value); } } void SetBoolean(bool p_value) { - switch(m_sync) + if(m_innerType == AnimatorControllerParameterType.Bool) { - case ParameterSyncType.Local: - PlayerSetup.Instance._animator.SetBool(m_hash, p_value); - break; - case ParameterSyncType.Synced: - PlayerSetup.Instance.animatorManager.SetAnimatorParameterBool(m_name, p_value); - break; + if(m_sync) + m_manager.SetAnimatorParameterBool(m_name, p_value); + else + m_manager.animator.SetBool(m_hash, p_value); } } } diff --git a/ml_amt/MotionTweaker.cs b/ml_amt/MotionTweaker.cs index ec6e487..11e9ffb 100644 --- a/ml_amt/MotionTweaker.cs +++ b/ml_amt/MotionTweaker.cs @@ -208,28 +208,12 @@ namespace ml_amt m_viewPointHeight = PlayerSetup.Instance._avatar.GetComponent().viewPosition.y; // Parse animator parameters - AnimatorControllerParameter[] l_params = PlayerSetup.Instance._animator.parameters; - foreach(var l_param in l_params) - { - foreach(AvatarParameter.ParameterType l_enumParam in System.Enum.GetValues(typeof(AvatarParameter.ParameterType))) - { - if(l_param.name.Contains(l_enumParam.ToString()) && (m_parameters.FindIndex(p => p.m_type == l_enumParam) == -1)) - { - bool l_local = (l_param.name[0] == '#'); + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Upright, PlayerSetup.Instance.animatorManager)); + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.GroundedRaw, PlayerSetup.Instance.animatorManager)); + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Moving, PlayerSetup.Instance.animatorManager)); + m_parameters.RemoveAll(p => !p.IsValid()); - m_parameters.Add(new AvatarParameter( - l_enumParam, - l_param.name, - (l_local ? AvatarParameter.ParameterSyncType.Local : AvatarParameter.ParameterSyncType.Synced), - (l_local ? l_param.nameHash : 0) - )); - - break; - } - } - } - - m_compatibleAvatar = m_parameters.Exists(p => p.m_type == AvatarParameter.ParameterType.Upright); + m_compatibleAvatar = m_parameters.Exists(p => (p.GetParameterType() == AvatarParameter.ParameterType.Upright)); m_avatarScale = Mathf.Abs(PlayerSetup.Instance._avatar.transform.localScale.y); Transform l_customTransform = PlayerSetup.Instance._avatar.transform.Find("CrouchLimit"); diff --git a/ml_amt/README.md b/ml_amt/README.md index b717c77..86c02a4 100644 --- a/ml_amt/README.md +++ b/ml_amt/README.md @@ -38,9 +38,9 @@ Available additional parameters for AAS animator: * Note: Can be set as local-only (not synced) if starts with `#` character. * Note: Defining this parameter in AAS animator will consider avatar as compatible with mod. * Note: Can't be used for transitions between poses in desktop mode. In desktop mode its value is driven by avatar animations. Use `CVR Parameter Stream` for detecting desktop/VR modes and change AAS animator transitions accordingly. -* **`GroundedRaw`:** defines instant grounding state of player instead of delayed default parameter `Grounded`. +* **`GroundedRaw`:** defines instant grounding state of player instead of delayed default parameter `Grounded`; boolean. * Note: Can be set as local-only (not synced) if starts with `#` character. -* **`Moving`:** defines movement state of player +* **`Moving`:** defines movement state of player; boolean. * Note: Can be set as local-only (not synced) if starts with `#` character. Additional mod's behaviour: diff --git a/ml_prm/AvatarBoolParameter.cs b/ml_prm/AvatarBoolParameter.cs new file mode 100644 index 0000000..b7a9535 --- /dev/null +++ b/ml_prm/AvatarBoolParameter.cs @@ -0,0 +1,43 @@ +using ABI_RC.Core; +using System.Text.RegularExpressions; +using UnityEngine; + +namespace ml_prm +{ + class AvatarBoolParameter + { + public readonly string m_name; + public readonly int m_hash = 0; + public readonly bool m_sync; + readonly CVRAnimatorManager m_manager = null; + + public AvatarBoolParameter(string p_name, CVRAnimatorManager p_manager) + { + m_name = p_name; + m_manager = p_manager; + + Regex l_regex = new Regex("^#?" + p_name + '$'); + foreach(var l_param in m_manager.animator.parameters) + { + if(l_regex.IsMatch(l_param.name) && (l_param.type == AnimatorControllerParameterType.Bool)) + { + m_name = l_param.name; + m_hash = l_param.nameHash; + m_sync = (l_param.name[0] != '#'); + break; + } + } + } + + public void SetValue(bool p_value) + { + if(m_hash != 0) + { + if(m_sync) + m_manager.SetAnimatorParameterBool(m_name, p_value); + else + m_manager.animator.SetBool(m_hash, p_value); + } + } + } +} diff --git a/ml_prm/README.md b/ml_prm/README.md index fb8142a..d0773bf 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -24,6 +24,10 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * **Angular movement drag:** angular movement resistance; `2.0` by default. * **Reset settings:** resets mod settings to default. +Available additional parameters for AAS animator: +* **`Ragdolled`:** defines current ragdoll state; boolean. + * Note: Can be set as local-only (not synced) if starts with `#` character. + # Unity Editor Script You can also trigger the ragdoll via animations on your avatar. To do this you need: * Download and import the `ml_prm_editor_script.unitypackage` into your unity project diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index c66e8bd..e4e2d87 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -33,6 +33,7 @@ namespace ml_prm RagdollToggle m_avatarRagdollToggle = null; RagdollTrigger m_customTrigger = null; + AvatarBoolParameter m_ragdolledParameter = null; bool m_reachedGround = true; @@ -129,6 +130,7 @@ namespace ml_prm m_enabled = false; m_avatarReady = false; m_avatarRagdollToggle = null; + m_ragdolledParameter = null; m_rigidBodies.Clear(); m_colliders.Clear(); m_puppetReferences = new BipedRagdollReferences(); @@ -231,6 +233,7 @@ namespace ml_prm } m_avatarRagdollToggle = PlayerSetup.Instance._avatar.GetComponentInChildren(true); + m_ragdolledParameter = new AvatarBoolParameter("Ragdolled", PlayerSetup.Instance.animatorManager); m_avatarReady = true; } @@ -336,6 +339,7 @@ namespace ml_prm MovementSystem.Instance.SetImmobilized(true); PlayerSetup.Instance.animatorManager.SetAnimatorParameterTrigger("CancelEmote"); + m_ragdolledParameter.SetValue(true); if(BodySystem.isCalibratedAsFullBody) BodySystem.TrackingPositionWeight = 0f; @@ -368,6 +372,7 @@ namespace ml_prm if(IsSafeToUnragdoll()) { MovementSystem.Instance.SetImmobilized(false); + m_ragdolledParameter.SetValue(false); if(BodySystem.isCalibratedAsFullBody) BodySystem.TrackingPositionWeight = 1f; diff --git a/ml_prm/ml_prm.csproj b/ml_prm/ml_prm.csproj index 4a041d1..33450f6 100644 --- a/ml_prm/ml_prm.csproj +++ b/ml_prm/ml_prm.csproj @@ -86,6 +86,7 @@ + From f06cd955e98edba77de1bfe3f57e78775fee0275 Mon Sep 17 00:00:00 2001 From: SDraw Date: Thu, 13 Apr 2023 23:03:43 +0300 Subject: [PATCH 32/63] Automatic recovery feature --- ml_prm/RagdollController.cs | 24 ++++++++++++++++ ml_prm/Settings.cs | 55 +++++++++++++++++++++++++++++++------ 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index e4e2d87..0160dbe 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -5,6 +5,7 @@ using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.MovementSystem; using RootMotion.Dynamics; using RootMotion.FinalIK; +using System.Collections; using System.Collections.Generic; using UnityEngine; @@ -34,6 +35,7 @@ namespace ml_prm RagdollToggle m_avatarRagdollToggle = null; RagdollTrigger m_customTrigger = null; AvatarBoolParameter m_ragdolledParameter = null; + Coroutine m_recoverTask = null; bool m_reachedGround = true; @@ -119,6 +121,12 @@ namespace ml_prm // Game events internal void OnAvatarClear() { + if(m_recoverTask != null) + { + StopCoroutine(m_recoverTask); + m_recoverTask = null; + } + if(m_enabled) MovementSystem.Instance.SetImmobilized(false); @@ -364,6 +372,9 @@ namespace ml_prm foreach(Collider l_collider in m_colliders) l_collider.enabled = true; + if(Settings.AutoRecover) + m_recoverTask = StartCoroutine(AutoRecover()); + m_enabled = true; } } @@ -371,6 +382,12 @@ namespace ml_prm { if(IsSafeToUnragdoll()) { + if(m_recoverTask != null) + { + StopCoroutine(m_recoverTask); + m_recoverTask = null; + } + MovementSystem.Instance.SetImmobilized(false); m_ragdolledParameter.SetValue(false); if(BodySystem.isCalibratedAsFullBody) @@ -410,6 +427,13 @@ namespace ml_prm public bool IsRagdolled() => (m_enabled && m_avatarReady); + IEnumerator AutoRecover() + { + yield return new WaitForSeconds(Settings.RecoverDelay); + m_recoverTask = null; + SwitchRagdoll(); + } + static Transform CloneTransform(Transform p_source, Transform p_parent, string p_name) { Transform l_target = new GameObject(p_name).transform; diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index 79e2187..13a92a8 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using UnityEngine; namespace ml_prm { @@ -15,7 +16,9 @@ namespace ml_prm AngularDrag, Gravity, PointersReaction, - CombatReaction + CombatReaction, + AutoRecover, + RecoverDelay } enum UiElementIndex @@ -25,9 +28,11 @@ namespace ml_prm Gravity, PointersReaction, CombatReaction, + AutoRecover, VelocityMultiplier, MovementDrag, - AngularDrag + AngularDrag, + RecoverDelay } public static bool Hotkey { get; private set; } = true; @@ -38,6 +43,8 @@ namespace ml_prm public static bool Gravity { get; private set; } = true; public static bool PointersReaction { get; private set; } = true; public static bool CombatReaction { get; private set; } = true; + public static bool AutoRecover { get; private set; } = false; + public static float RecoverDelay { get; private set; } = 3f; static public event Action SwitchChange; static public event Action HotkeyChange; @@ -48,6 +55,8 @@ namespace ml_prm static public event Action GravityChange; static public event Action PointersReactionChange; static public event Action CombatReactionChange; + static public event Action AutoRecoverChange; + static public event Action RecoverDelayChange; static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; @@ -66,17 +75,21 @@ namespace ml_prm ms_category.CreateEntry(ModSetting.AngularDrag.ToString(), AngularDrag), ms_category.CreateEntry(ModSetting.Gravity.ToString(), Gravity), ms_category.CreateEntry(ModSetting.PointersReaction.ToString(), PointersReaction), - ms_category.CreateEntry(ModSetting.CombatReaction.ToString(), CombatReaction) + ms_category.CreateEntry(ModSetting.CombatReaction.ToString(), CombatReaction), + ms_category.CreateEntry(ModSetting.AutoRecover.ToString(), AutoRecover), + ms_category.CreateEntry(ModSetting.RecoverDelay.ToString(), RecoverDelay) }; Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; - VelocityMultiplier = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue, 1f, 50f); + VelocityMultiplier = Mathf.Clamp((float)ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue, 1f, 50f); RestorePosition = (bool)ms_entries[(int)ModSetting.RestorePosition].BoxedValue; - MovementDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); - AngularDrag = UnityEngine.Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); + MovementDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); + AngularDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue; PointersReaction = (bool)ms_entries[(int)ModSetting.PointersReaction].BoxedValue; CombatReaction = (bool)ms_entries[(int)ModSetting.CombatReaction].BoxedValue; + AutoRecover = (bool)ms_entries[(int)ModSetting.AutoRecover].BoxedValue; + RecoverDelay = Mathf.Clamp((float)ms_entries[(int)ModSetting.RecoverDelay].BoxedValue, 1f, 10f); if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null) { @@ -136,6 +149,14 @@ namespace ml_prm CombatReactionChange?.Invoke(state); }; + ms_uiElements.Add(l_categoryMod.AddToggle("Auto recover", "Automatically unragdoll after set recover delay", AutoRecover)); + (ms_uiElements[(int)UiElementIndex.AutoRecover] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => + { + AutoRecover = state; + ms_entries[(int)ModSetting.AutoRecover].BoxedValue = state; + AutoRecoverChange?.Invoke(state); + }; + ms_uiElements.Add(l_page.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", VelocityMultiplier, 1f, 50f)); (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => { @@ -157,7 +178,15 @@ namespace ml_prm { AngularDrag = value; ms_entries[(int)ModSetting.AngularDrag].BoxedValue = value; - AngularDragChange?.Invoke(AngularDrag); + AngularDragChange?.Invoke(value); + }; + + ms_uiElements.Add(l_page.AddSlider("Recover delay (seconds)", "Recover delay for automatic recover", RecoverDelay, 1f, 10f)); + (ms_uiElements[(int)UiElementIndex.RecoverDelay] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => + { + RecoverDelay = value; + ms_entries[(int)ModSetting.RecoverDelay].BoxedValue = value; + RecoverDelayChange?.Invoke(value); }; l_categoryMod.AddButton("Reset settings", "", "Reset mod settings to default").OnPress += () => @@ -187,6 +216,11 @@ namespace ml_prm (ms_uiElements[(int)UiElementIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; CombatReactionChange?.Invoke(true); + AutoRecover = false; + ms_entries[(int)ModSetting.AutoRecover].BoxedValue = false; + (ms_uiElements[(int)UiElementIndex.AutoRecover] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = false; + AutoRecoverChange?.Invoke(false); + VelocityMultiplier = 2f; ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue = 2f; (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(2f); @@ -198,9 +232,14 @@ namespace ml_prm MovementDragChange?.Invoke(2f); AngularDrag = 2f; - ms_entries[(int)ModSetting.MovementDrag].BoxedValue = 2f; + ms_entries[(int)ModSetting.AngularDrag].BoxedValue = 2f; (ms_uiElements[(int)UiElementIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(2f); AngularDragChange?.Invoke(2f); + + RecoverDelay = 3f; + ms_entries[(int)ModSetting.RecoverDelay].BoxedValue = 3f; + (ms_uiElements[(int)UiElementIndex.RecoverDelay] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(3f); + RecoverDelayChange?.Invoke(3f); }; } } From 8d337635b8943da92aa036945b6ecf5054746d22 Mon Sep 17 00:00:00 2001 From: SDraw Date: Thu, 13 Apr 2023 20:07:55 +0000 Subject: [PATCH 33/63] Update README.md --- ml_prm/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ml_prm/README.md b/ml_prm/README.md index d0773bf..e671301 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -17,11 +17,13 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * Note: Forcibly enabled in worlds that don't allow flight. * **Pointers reaction:** enables ragdoll state when player collides with CVRPointer colliders of `ragdoll` type (avatars, props and world included); `true` by default. * **Combat reaction:** enables ragdoll state upon death in worlds with combat system; `true` by default. +* **Auto recover:** enables automatic recovering after specific time delay; `false` by default. * **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. * Note: Limited according to world's fly multiplier. * Note: Forcibly set to `1.0` in worlds that don't allow flight. * **Movement drag:** movement resistance; `2.0` by default. * **Angular movement drag:** angular movement resistance; `2.0` by default. +* **Recover delay:** time delay for enabled `Auto recover` in seconds; `3.0` by default. * **Reset settings:** resets mod settings to default. Available additional parameters for AAS animator: From fa5a0334b93cd1d05d0d52cb78c24b7f86785c98 Mon Sep 17 00:00:00 2001 From: SDraw Date: Fri, 14 Apr 2023 11:00:20 +0300 Subject: [PATCH 34/63] More effective recovery Fix of trigger detection --- ml_prm/README.md | 2 +- ml_prm/RagdollController.cs | 36 ++++++++++++++---------------------- ml_prm/RagdollTrigger.cs | 32 ++++++++++++++++++++++++++------ ml_prm/Settings.cs | 2 +- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/ml_prm/README.md b/ml_prm/README.md index e671301..369a331 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -15,7 +15,7 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * **Restore position:** returns to position of ragdoll state activation upon ragdoll state exit; `false` by default. * **Use gravity:** enables/disables gravity for ragdoll; `true` by default. * Note: Forcibly enabled in worlds that don't allow flight. -* **Pointers reaction:** enables ragdoll state when player collides with CVRPointer colliders of `ragdoll` type (avatars, props and world included); `true` by default. +* **Pointers reaction:** enables ragdoll state when player collides with trigger colliders with CVRPointer component of `ragdoll` type (avatars, props and world included); `true` by default. * **Combat reaction:** enables ragdoll state upon death in worlds with combat system; `true` by default. * **Auto recover:** enables automatic recovering after specific time delay; `false` by default. * **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 0160dbe..14251ed 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -35,9 +35,9 @@ namespace ml_prm RagdollToggle m_avatarRagdollToggle = null; RagdollTrigger m_customTrigger = null; AvatarBoolParameter m_ragdolledParameter = null; - Coroutine m_recoverTask = null; bool m_reachedGround = true; + float m_downTime = float.MinValue; internal RagdollController() { @@ -96,6 +96,16 @@ namespace ml_prm if(m_enabled && m_avatarReady && BodySystem.isCalibratedAsFullBody) BodySystem.TrackingPositionWeight = 0f; + if(m_avatarReady && m_enabled && Settings.AutoRecover) + { + m_downTime += Time.deltaTime; + if(m_downTime >= Settings.RecoverDelay) + { + SwitchRagdoll(); + m_downTime = float.MinValue; // One attepmt to recover + } + } + if(Settings.Hotkey && Input.GetKeyDown(KeyCode.R) && !ViewManager.Instance.isGameMenuOpen()) SwitchRagdoll(); @@ -121,12 +131,6 @@ namespace ml_prm // Game events internal void OnAvatarClear() { - if(m_recoverTask != null) - { - StopCoroutine(m_recoverTask); - m_recoverTask = null; - } - if(m_enabled) MovementSystem.Instance.SetImmobilized(false); @@ -144,6 +148,7 @@ namespace ml_prm m_puppetReferences = new BipedRagdollReferences(); m_boneLinks.Clear(); m_reachedGround = true; + m_downTime = float.MinValue; } internal void OnAvatarSetup() @@ -372,8 +377,7 @@ namespace ml_prm foreach(Collider l_collider in m_colliders) l_collider.enabled = true; - if(Settings.AutoRecover) - m_recoverTask = StartCoroutine(AutoRecover()); + m_downTime = 0f; m_enabled = true; } @@ -382,12 +386,6 @@ namespace ml_prm { if(IsSafeToUnragdoll()) { - if(m_recoverTask != null) - { - StopCoroutine(m_recoverTask); - m_recoverTask = null; - } - MovementSystem.Instance.SetImmobilized(false); m_ragdolledParameter.SetValue(false); if(BodySystem.isCalibratedAsFullBody) @@ -418,6 +416,7 @@ namespace ml_prm m_lastPosition = PlayerSetup.Instance.transform.position; m_velocity = Vector3.zero; + m_downTime = float.MinValue; m_enabled = false; } @@ -427,13 +426,6 @@ namespace ml_prm public bool IsRagdolled() => (m_enabled && m_avatarReady); - IEnumerator AutoRecover() - { - yield return new WaitForSeconds(Settings.RecoverDelay); - m_recoverTask = null; - SwitchRagdoll(); - } - static Transform CloneTransform(Transform p_source, Transform p_parent, string p_name) { Transform l_target = new GameObject(p_name).transform; diff --git a/ml_prm/RagdollTrigger.cs b/ml_prm/RagdollTrigger.cs index fb0ee93..451da15 100644 --- a/ml_prm/RagdollTrigger.cs +++ b/ml_prm/RagdollTrigger.cs @@ -6,23 +6,43 @@ namespace ml_prm [DisallowMultipleComponent] class RagdollTrigger : MonoBehaviour { - Collider m_lastCollider = null; + Collider m_collider = null; + Collider m_lastTrigger = null; bool m_triggered = false; + void Start() + { + m_collider = this.GetComponent(); + } + + void Update() + { + if(!ReferenceEquals(m_lastTrigger, null)) + { + if(m_lastTrigger != null) + { + if(!m_collider.bounds.Intersects(m_lastTrigger.bounds)) + m_lastTrigger = null; + } + else + m_lastTrigger = null; + } + } + void OnTriggerEnter(Collider p_other) { - CVRPointer l_pointer = p_other.gameObject.GetComponent(); - if((l_pointer != null) && (l_pointer.type == "ragdoll") && (m_lastCollider != p_other)) + CVRPointer l_pointer = p_other.GetComponent(); + if((l_pointer != null) && (l_pointer.type == "ragdoll") && (m_lastTrigger != p_other)) { - m_lastCollider = p_other; + m_lastTrigger = p_other; m_triggered = true; } } void OnTriggerExit(Collider p_other) { - if(m_lastCollider == p_other) - m_lastCollider = null; + if(m_lastTrigger == p_other) + m_lastTrigger = null; } public bool GetStateWithReset() diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index 13a92a8..58f5de0 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -133,7 +133,7 @@ namespace ml_prm GravityChange?.Invoke(state); }; - ms_uiElements.Add(l_categoryMod.AddToggle("Pointers reaction", "React to CVRPointer components with 'ragdoll' type", PointersReaction)); + ms_uiElements.Add(l_categoryMod.AddToggle("Pointers reaction", "React to trigger colliders with CVRPointer component of 'ragdoll' type", PointersReaction)); (ms_uiElements[(int)UiElementIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => { PointersReaction = state; From f983f2909c9310cbd90bb92d1ea7c99b62be3b8a Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 15 Apr 2023 13:51:12 +0300 Subject: [PATCH 35/63] Ignoring local player's pointers option Settings hide --- ml_prm/README.md | 1 + ml_prm/RagdollTrigger.cs | 8 +++++++- ml_prm/Settings.cs | 21 ++++++++++++++++++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/ml_prm/README.md b/ml_prm/README.md index 369a331..515a371 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -16,6 +16,7 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * **Use gravity:** enables/disables gravity for ragdoll; `true` by default. * Note: Forcibly enabled in worlds that don't allow flight. * **Pointers reaction:** enables ragdoll state when player collides with trigger colliders with CVRPointer component of `ragdoll` type (avatars, props and world included); `true` by default. +* **Ignore local pointers:** enables/disables ignoring of CVRPointer components of `ragdoll` type on local player's avatar; `true` by default. * **Combat reaction:** enables ragdoll state upon death in worlds with combat system; `true` by default. * **Auto recover:** enables automatic recovering after specific time delay; `false` by default. * **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. diff --git a/ml_prm/RagdollTrigger.cs b/ml_prm/RagdollTrigger.cs index 451da15..d5996bd 100644 --- a/ml_prm/RagdollTrigger.cs +++ b/ml_prm/RagdollTrigger.cs @@ -1,4 +1,5 @@ using ABI.CCK.Components; +using ABI_RC.Core.Player; using UnityEngine; namespace ml_prm @@ -32,7 +33,7 @@ namespace ml_prm void OnTriggerEnter(Collider p_other) { CVRPointer l_pointer = p_other.GetComponent(); - if((l_pointer != null) && (l_pointer.type == "ragdoll") && (m_lastTrigger != p_other)) + if((l_pointer != null) && (l_pointer.type == "ragdoll") && !IsIgnored(l_pointer.transform) && (m_lastTrigger != p_other)) { m_lastTrigger = p_other; m_triggered = true; @@ -51,5 +52,10 @@ namespace ml_prm m_triggered = false; return l_state; } + + static bool IsIgnored(Transform p_transform) + { + return (Settings.IgnoreLocal && (p_transform.root == PlayerSetup.Instance.transform)); + } } } diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index 58f5de0..591c3f6 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -16,6 +16,7 @@ namespace ml_prm AngularDrag, Gravity, PointersReaction, + IgnoreLocal, CombatReaction, AutoRecover, RecoverDelay @@ -27,6 +28,7 @@ namespace ml_prm RestorePosition, Gravity, PointersReaction, + IgnoreLocal, CombatReaction, AutoRecover, VelocityMultiplier, @@ -42,6 +44,7 @@ namespace ml_prm public static float AngularDrag { get; private set; } = 2f; public static bool Gravity { get; private set; } = true; public static bool PointersReaction { get; private set; } = true; + public static bool IgnoreLocal { get; private set; } = true; public static bool CombatReaction { get; private set; } = true; public static bool AutoRecover { get; private set; } = false; public static float RecoverDelay { get; private set; } = 3f; @@ -54,6 +57,7 @@ namespace ml_prm static public event Action AngularDragChange; static public event Action GravityChange; static public event Action PointersReactionChange; + static public event Action IgnoreLocalChange; static public event Action CombatReactionChange; static public event Action AutoRecoverChange; static public event Action RecoverDelayChange; @@ -65,7 +69,7 @@ namespace ml_prm internal static void Init() { - ms_category = MelonLoader.MelonPreferences.CreateCategory("PRM"); + ms_category = MelonLoader.MelonPreferences.CreateCategory("PRM", null, true); ms_entries = new List() { ms_category.CreateEntry(ModSetting.Hotkey.ToString(), Hotkey), @@ -75,6 +79,7 @@ namespace ml_prm ms_category.CreateEntry(ModSetting.AngularDrag.ToString(), AngularDrag), ms_category.CreateEntry(ModSetting.Gravity.ToString(), Gravity), ms_category.CreateEntry(ModSetting.PointersReaction.ToString(), PointersReaction), + ms_category.CreateEntry(ModSetting.IgnoreLocal.ToString(), IgnoreLocal), ms_category.CreateEntry(ModSetting.CombatReaction.ToString(), CombatReaction), ms_category.CreateEntry(ModSetting.AutoRecover.ToString(), AutoRecover), ms_category.CreateEntry(ModSetting.RecoverDelay.ToString(), RecoverDelay) @@ -87,6 +92,7 @@ namespace ml_prm AngularDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue; PointersReaction = (bool)ms_entries[(int)ModSetting.PointersReaction].BoxedValue; + IgnoreLocal = (bool)ms_entries[(int)ModSetting.IgnoreLocal].BoxedValue; CombatReaction = (bool)ms_entries[(int)ModSetting.CombatReaction].BoxedValue; AutoRecover = (bool)ms_entries[(int)ModSetting.AutoRecover].BoxedValue; RecoverDelay = Mathf.Clamp((float)ms_entries[(int)ModSetting.RecoverDelay].BoxedValue, 1f, 10f); @@ -141,6 +147,14 @@ namespace ml_prm PointersReactionChange?.Invoke(state); }; + ms_uiElements.Add(l_categoryMod.AddToggle("Ignore local pointers", "Ignore local avatar's CVRPointer components of 'ragdoll' type", IgnoreLocal)); + (ms_uiElements[(int)UiElementIndex.IgnoreLocal] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => + { + IgnoreLocal = state; + ms_entries[(int)ModSetting.IgnoreLocal].BoxedValue = state; + IgnoreLocalChange?.Invoke(state); + }; + ms_uiElements.Add(l_categoryMod.AddToggle("Combat reaction", "Ragdoll upon combat system death", CombatReaction)); (ms_uiElements[(int)UiElementIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => { @@ -211,6 +225,11 @@ namespace ml_prm (ms_uiElements[(int)UiElementIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; PointersReactionChange?.Invoke(true); + IgnoreLocal = true; + ms_entries[(int)ModSetting.IgnoreLocal].BoxedValue = true; + (ms_uiElements[(int)UiElementIndex.IgnoreLocal] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; + IgnoreLocalChange?.Invoke(true); + CombatReaction = true; ms_entries[(int)ModSetting.CombatReaction].BoxedValue = true; (ms_uiElements[(int)UiElementIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; From b36f1009d988670bd6c14d560eaa39004a6d1e9b Mon Sep 17 00:00:00 2001 From: SDraw Date: Sun, 16 Apr 2023 11:47:36 +0300 Subject: [PATCH 36/63] Fix of ragdolling with hips IK override option enabled Hiding settings from UIExpansionKit --- README.md | 10 +++++----- ml_amt/Main.cs | 1 + ml_amt/ModSupporter.cs | 32 +++++++++++++++++++++++++++++++ ml_amt/MotionTweaker.cs | 2 +- ml_amt/Properties/AssemblyInfo.cs | 7 ++++--- ml_amt/Settings.cs | 2 +- ml_amt/ml_amt.csproj | 5 +++++ ml_dht/Properties/AssemblyInfo.cs | 6 +++--- ml_dht/Settings.cs | 2 +- ml_lme/Properties/AssemblyInfo.cs | 6 +++--- ml_lme/Settings.cs | 2 +- ml_pam/Properties/AssemblyInfo.cs | 6 +++--- ml_pam/Settings.cs | 2 +- ml_prm/README.md | 1 - 14 files changed, 61 insertions(+), 23 deletions(-) create mode 100644 ml_amt/ModSupporter.cs diff --git a/README.md b/README.md index 0152fa5..8709f71 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ Merged set of MelonLoader mods for ChilloutVR. | Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes | |-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------| | Avatar Change Info | ml_aci | 1.0.3 | Retired | Retired | Superseded by `Extended Game Notifications` -| Avatar Motion Tweaker | ml_amt | 1.2.5 | Yes, update review | Working | -| Desktop Head Tracking | ml_dht | 1.1.2 | Yes | Working | +| Avatar Motion Tweaker | ml_amt | 1.2.6 | Yes, update review | Working | +| Desktop Head Tracking | ml_dht | 1.1.3 | Yes, update review | Working | | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | | Extended Game Notifications | ml_egn | 1.0.2 | Yes, update review | Working | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update -| Leap Motion Extension | ml_lme | 1.3.3 | Yes | Working | -| Pickup Arm Movement | ml_pam | 1.0.2 | Yes| Working | -| Player Ragdoll Mod | ml_prm | 1.0.0 | No, publish review | Working | +| Leap Motion Extension | ml_lme | 1.3.4 | Yes, update review | Working | +| Pickup Arm Movement | ml_pam | 1.0.3 | Yes, update review| Working | +| Player Ragdoll Mod | ml_prm | 1.0.0 | Yes | Working | | Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` diff --git a/ml_amt/Main.cs b/ml_amt/Main.cs index 2c0deab..c6ccd70 100644 --- a/ml_amt/Main.cs +++ b/ml_amt/Main.cs @@ -87,6 +87,7 @@ namespace ml_amt new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnOverride_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) ); + ModSupporter.Init(); MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); } diff --git a/ml_amt/ModSupporter.cs b/ml_amt/ModSupporter.cs new file mode 100644 index 0000000..c5c2ed5 --- /dev/null +++ b/ml_amt/ModSupporter.cs @@ -0,0 +1,32 @@ +using System.Collections; +using System.Linq; + +namespace ml_amt +{ + static class ModSupporter + { + static bool ms_ragdollMod = false; + + public static void Init() + { + if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "PlayerRagdollMod") != null) + MelonLoader.MelonCoroutines.Start(WaitForRagdollInstance()); + } + + // PlayerRagdollMod support + static IEnumerator WaitForRagdollInstance() + { + while(ml_prm.RagdollController.Instance == null) + yield return null; + + ms_ragdollMod = true; + } + static bool IsRagdolled() => ml_prm.RagdollController.Instance.IsRagdolled(); + public static bool SkipHipsOverride() + { + bool l_result = false; + l_result |= (ms_ragdollMod && IsRagdolled()); + return l_result; + } + } +} diff --git a/ml_amt/MotionTweaker.cs b/ml_amt/MotionTweaker.cs index 11e9ffb..f205fd2 100644 --- a/ml_amt/MotionTweaker.cs +++ b/ml_amt/MotionTweaker.cs @@ -331,7 +331,7 @@ namespace ml_amt } bool l_solverActive = !Mathf.Approximately(m_vrIk.solver.IKPositionWeight, 0f); - if(l_locomotionOverride && l_solverActive && m_followHips && (!m_moving || (m_poseState == PoseState.Proning)) && m_inVR && !BodySystem.isCalibratedAsFullBody) + if(l_locomotionOverride && l_solverActive && m_followHips && (!m_moving || (m_poseState == PoseState.Proning)) && m_inVR && !BodySystem.isCalibratedAsFullBody && !ModSupporter.SkipHipsOverride()) { m_vrIk.solver.plantFeet = false; IKSystem.VrikRootController.enabled = false; diff --git a/ml_amt/Properties/AssemblyInfo.cs b/ml_amt/Properties/AssemblyInfo.cs index ba6d274..e187bdd 100644 --- a/ml_amt/Properties/AssemblyInfo.cs +++ b/ml_amt/Properties/AssemblyInfo.cs @@ -1,10 +1,11 @@ using System.Reflection; [assembly: AssemblyTitle("AvatarMotionTweaker")] -[assembly: AssemblyVersion("1.2.5")] -[assembly: AssemblyFileVersion("1.2.5")] +[assembly: AssemblyVersion("1.2.6")] +[assembly: AssemblyFileVersion("1.2.6")] -[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.2.5", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.2.6", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] +[assembly: MelonLoader.MelonOptionalDependencies("ml_prm")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] \ No newline at end of file diff --git a/ml_amt/Settings.cs b/ml_amt/Settings.cs index 930a83d..6f60289 100644 --- a/ml_amt/Settings.cs +++ b/ml_amt/Settings.cs @@ -60,7 +60,7 @@ namespace ml_amt internal static void Init() { - ms_category = MelonLoader.MelonPreferences.CreateCategory("AMT"); + ms_category = MelonLoader.MelonPreferences.CreateCategory("AMT", null, true); ms_entries = new List() { diff --git a/ml_amt/ml_amt.csproj b/ml_amt/ml_amt.csproj index cd4e2bc..17bb8f2 100644 --- a/ml_amt/ml_amt.csproj +++ b/ml_amt/ml_amt.csproj @@ -54,6 +54,10 @@ False False + + D:\Games\Steam\steamapps\common\ChilloutVR\Mods\ml_prm.dll + False + @@ -77,6 +81,7 @@ + diff --git a/ml_dht/Properties/AssemblyInfo.cs b/ml_dht/Properties/AssemblyInfo.cs index 6ccf6ab..a434039 100644 --- a/ml_dht/Properties/AssemblyInfo.cs +++ b/ml_dht/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("DesktopHeadTracking")] -[assembly: AssemblyVersion("1.1.2")] -[assembly: AssemblyFileVersion("1.1.2")] +[assembly: AssemblyVersion("1.1.3")] +[assembly: AssemblyFileVersion("1.1.3")] -[assembly: MelonLoader.MelonInfo(typeof(ml_dht.DesktopHeadTracking), "DesktopHeadTracking", "1.1.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_dht.DesktopHeadTracking), "DesktopHeadTracking", "1.1.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] \ No newline at end of file diff --git a/ml_dht/Settings.cs b/ml_dht/Settings.cs index 7251fed..dfaa33f 100644 --- a/ml_dht/Settings.cs +++ b/ml_dht/Settings.cs @@ -39,7 +39,7 @@ namespace ml_dht internal static void Init() { - ms_category = MelonLoader.MelonPreferences.CreateCategory("DHT"); + ms_category = MelonLoader.MelonPreferences.CreateCategory("DHT", null, true); ms_entries = new List() { diff --git a/ml_lme/Properties/AssemblyInfo.cs b/ml_lme/Properties/AssemblyInfo.cs index 2f6a005..892c296 100644 --- a/ml_lme/Properties/AssemblyInfo.cs +++ b/ml_lme/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("LeapMotionExtension")] -[assembly: AssemblyVersion("1.3.3")] -[assembly: AssemblyFileVersion("1.3.3")] +[assembly: AssemblyVersion("1.3.4")] +[assembly: AssemblyFileVersion("1.3.4")] -[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.3.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.3.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] diff --git a/ml_lme/Settings.cs b/ml_lme/Settings.cs index a28ee48..56ff521 100644 --- a/ml_lme/Settings.cs +++ b/ml_lme/Settings.cs @@ -68,7 +68,7 @@ namespace ml_lme internal static void Init() { - ms_category = MelonLoader.MelonPreferences.CreateCategory("LME"); + ms_category = MelonLoader.MelonPreferences.CreateCategory("LME", null, true); ms_entries = new List() { diff --git a/ml_pam/Properties/AssemblyInfo.cs b/ml_pam/Properties/AssemblyInfo.cs index 54ba674..e7bee17 100644 --- a/ml_pam/Properties/AssemblyInfo.cs +++ b/ml_pam/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("PickupArmMovement")] -[assembly: AssemblyVersion("1.0.2")] -[assembly: AssemblyFileVersion("1.0.2")] +[assembly: AssemblyVersion("1.0.3")] +[assembly: AssemblyFileVersion("1.0.3")] -[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.0.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.0.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPriority(1)] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] diff --git a/ml_pam/Settings.cs b/ml_pam/Settings.cs index 488f2df..433cdab 100644 --- a/ml_pam/Settings.cs +++ b/ml_pam/Settings.cs @@ -24,7 +24,7 @@ namespace ml_pam internal static void Init() { - ms_category = MelonLoader.MelonPreferences.CreateCategory("PAM"); + ms_category = MelonLoader.MelonPreferences.CreateCategory("PAM", null, true); ms_entries = new List() { diff --git a/ml_prm/README.md b/ml_prm/README.md index 515a371..4596181 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -53,7 +53,6 @@ Available methods: * ```void SwitchRagdoll()``` # Notes -* Slightly incompatible with `Follow hips on IK override` option in AvatarMotionTweaker. * Not suggested to activate fly mode with enabled ragdoll state. * If ragdoll state is enabled during emote, remote players see whole emote playing while local player sees ragdolling. It's tied to how game handles remote players, currently can be prevented with (choose one): * Renaming avatar emote animations to not have default name or containing `Emote` substring. From 7e9224c3d63180f33e1deefb3374a6b5fec86b07 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sun, 16 Apr 2023 18:03:34 +0000 Subject: [PATCH 37/63] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8709f71..1a5c4f8 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Merged set of MelonLoader mods for ChilloutVR. | Avatar Motion Tweaker | ml_amt | 1.2.6 | Yes, update review | Working | | Desktop Head Tracking | ml_dht | 1.1.3 | Yes, update review | Working | | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | -| Extended Game Notifications | ml_egn | 1.0.2 | Yes, update review | Working +| Extended Game Notifications | ml_egn | 1.0.2 | Yes | Working | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update | Leap Motion Extension | ml_lme | 1.3.4 | Yes, update review | Working | | Pickup Arm Movement | ml_pam | 1.0.3 | Yes, update review| Working | From 2540a4fca2111fac3e302dc1e6d5eb5776d9e74c Mon Sep 17 00:00:00 2001 From: SDraw Date: Sun, 16 Apr 2023 22:17:10 +0300 Subject: [PATCH 38/63] Slipperiness and bounciness options --- README.md | 2 +- ml_prm/Properties/AssemblyInfo.cs | 6 ++--- ml_prm/README.md | 4 +++ ml_prm/RagdollController.cs | 30 +++++++++++++++++++++- ml_prm/Settings.cs | 42 +++++++++++++++++++++++++++++-- 5 files changed, 77 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 1a5c4f8..894a20f 100644 --- a/README.md +++ b/README.md @@ -11,5 +11,5 @@ Merged set of MelonLoader mods for ChilloutVR. | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update | Leap Motion Extension | ml_lme | 1.3.4 | Yes, update review | Working | | Pickup Arm Movement | ml_pam | 1.0.3 | Yes, update review| Working | -| Player Ragdoll Mod | ml_prm | 1.0.0 | Yes | Working | +| Player Ragdoll Mod | ml_prm | 1.0.1 | Yes, update review | Working | | Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` diff --git a/ml_prm/Properties/AssemblyInfo.cs b/ml_prm/Properties/AssemblyInfo.cs index 9e478a5..dca7ef0 100644 --- a/ml_prm/Properties/AssemblyInfo.cs +++ b/ml_prm/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("PlayerRagdollMod")] -[assembly: AssemblyVersion("1.0.0")] -[assembly: AssemblyFileVersion("1.0.0")] +[assembly: AssemblyVersion("1.0.1")] +[assembly: AssemblyFileVersion("1.0.1")] -[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.0.0", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.0.1", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPriority(2)] [assembly: MelonLoader.MelonOptionalDependencies("BTKUILib")] diff --git a/ml_prm/README.md b/ml_prm/README.md index 4596181..ccd275c 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -19,6 +19,10 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * **Ignore local pointers:** enables/disables ignoring of CVRPointer components of `ragdoll` type on local player's avatar; `true` by default. * **Combat reaction:** enables ragdoll state upon death in worlds with combat system; `true` by default. * **Auto recover:** enables automatic recovering after specific time delay; `false` by default. +* **Slipperiness:** enables/disable low friction of ragdoll; `false` by default. + * Note: Forcibly disabled in worlds that don't allow flight. +* **Bounciness:** enables/disable bounce force of ragdoll; `false` by default. + * Note: Forcibly disabled in worlds that don't allow flight. * **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. * Note: Limited according to world's fly multiplier. * Note: Forcibly set to `1.0` in worlds that don't allow flight. diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 14251ed..c626c12 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -5,7 +5,6 @@ using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.MovementSystem; using RootMotion.Dynamics; using RootMotion.FinalIK; -using System.Collections; using System.Collections.Generic; using UnityEngine; @@ -35,6 +34,7 @@ namespace ml_prm RagdollToggle m_avatarRagdollToggle = null; RagdollTrigger m_customTrigger = null; AvatarBoolParameter m_ragdolledParameter = null; + readonly PhysicMaterial m_physicsMaterial = null; bool m_reachedGround = true; float m_downTime = float.MinValue; @@ -47,6 +47,13 @@ namespace ml_prm m_rigidBodies = new List(); m_colliders = new List(); m_boneLinks = new List>(); + + m_physicsMaterial = new PhysicMaterial("Ragdoll"); + m_physicsMaterial.dynamicFriction = 0.5f; + m_physicsMaterial.staticFriction = 0.5f; + m_physicsMaterial.frictionCombine = PhysicMaterialCombine.Average; + m_physicsMaterial.bounciness = 0f; + m_physicsMaterial.bounceCombine = PhysicMaterialCombine.Average; } ~RagdollController() { @@ -68,6 +75,8 @@ namespace ml_prm Settings.MovementDragChange += this.OnMovementDragChange; Settings.AngularDragChange += this.OnAngularDragChange; Settings.GravityChange += this.OnGravityChange; + Settings.SlipperinessChange += this.OnPhysicsMaterialChange; + Settings.BouncinessChange += this.OnPhysicsMaterialChange; } void OnDestroy() @@ -82,6 +91,8 @@ namespace ml_prm Settings.MovementDragChange -= this.OnMovementDragChange; Settings.AngularDragChange -= this.OnAngularDragChange; Settings.GravityChange -= this.OnGravityChange; + Settings.SlipperinessChange -= this.OnPhysicsMaterialChange; + Settings.BouncinessChange -= this.OnPhysicsMaterialChange; } void Update() @@ -230,6 +241,8 @@ namespace ml_prm Physics.IgnoreCollision(l_collider, MovementSystem.Instance.controller, true); Physics.IgnoreCollision(l_collider, MovementSystem.Instance.forceCollider, true); l_collider.enabled = false; + l_collider.sharedMaterial = m_physicsMaterial; + l_collider.material = m_physicsMaterial; m_colliders.Add(l_collider); } @@ -274,6 +287,8 @@ namespace ml_prm foreach(Rigidbody l_body in m_rigidBodies) l_body.useGravity = (!Utils.IsWorldSafe() || Settings.Gravity); } + + OnPhysicsMaterialChange(true); } internal void OnCombatDown() @@ -330,6 +345,19 @@ namespace ml_prm l_body.useGravity = (!Utils.IsWorldSafe() || p_state); } } + void OnPhysicsMaterialChange(bool p_state) + { + if(m_physicsMaterial != null) + { + bool l_slipperiness = (Settings.Slipperiness && Utils.IsWorldSafe()); + bool l_bounciness = (Settings.Bounciness && Utils.IsWorldSafe()); + m_physicsMaterial.dynamicFriction = (l_slipperiness ? 0f : 0.5f); + m_physicsMaterial.staticFriction = (l_slipperiness ? 0f : 0.5f); + m_physicsMaterial.frictionCombine = (l_slipperiness ? PhysicMaterialCombine.Minimum : PhysicMaterialCombine.Average); + m_physicsMaterial.bounciness = (l_bounciness ? 1f : 0f); + m_physicsMaterial.bounceCombine = (l_bounciness ? PhysicMaterialCombine.Maximum : PhysicMaterialCombine.Average); + } + } // Arbitrary public void SwitchRagdoll() diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index 591c3f6..8dc8577 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -19,7 +19,9 @@ namespace ml_prm IgnoreLocal, CombatReaction, AutoRecover, - RecoverDelay + RecoverDelay, + Slipperiness, + Bounciness } enum UiElementIndex @@ -31,6 +33,8 @@ namespace ml_prm IgnoreLocal, CombatReaction, AutoRecover, + Slipperiness, + Bounciness, VelocityMultiplier, MovementDrag, AngularDrag, @@ -48,6 +52,8 @@ namespace ml_prm public static bool CombatReaction { get; private set; } = true; public static bool AutoRecover { get; private set; } = false; public static float RecoverDelay { get; private set; } = 3f; + public static bool Slipperiness { get; private set; } = false; + public static bool Bounciness { get; private set; } = false; static public event Action SwitchChange; static public event Action HotkeyChange; @@ -61,6 +67,8 @@ namespace ml_prm static public event Action CombatReactionChange; static public event Action AutoRecoverChange; static public event Action RecoverDelayChange; + static public event Action SlipperinessChange; + static public event Action BouncinessChange; static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; @@ -82,7 +90,9 @@ namespace ml_prm ms_category.CreateEntry(ModSetting.IgnoreLocal.ToString(), IgnoreLocal), ms_category.CreateEntry(ModSetting.CombatReaction.ToString(), CombatReaction), ms_category.CreateEntry(ModSetting.AutoRecover.ToString(), AutoRecover), - ms_category.CreateEntry(ModSetting.RecoverDelay.ToString(), RecoverDelay) + ms_category.CreateEntry(ModSetting.RecoverDelay.ToString(), RecoverDelay), + ms_category.CreateEntry(ModSetting.Slipperiness.ToString(), Slipperiness), + ms_category.CreateEntry(ModSetting.Bounciness.ToString(), Bounciness) }; Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; @@ -96,6 +106,8 @@ namespace ml_prm CombatReaction = (bool)ms_entries[(int)ModSetting.CombatReaction].BoxedValue; AutoRecover = (bool)ms_entries[(int)ModSetting.AutoRecover].BoxedValue; RecoverDelay = Mathf.Clamp((float)ms_entries[(int)ModSetting.RecoverDelay].BoxedValue, 1f, 10f); + Slipperiness = (bool)ms_entries[(int)ModSetting.Slipperiness].BoxedValue; + Bounciness = (bool)ms_entries[(int)ModSetting.Bounciness].BoxedValue; if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null) { @@ -171,6 +183,22 @@ namespace ml_prm AutoRecoverChange?.Invoke(state); }; + ms_uiElements.Add(l_categoryMod.AddToggle("Slipperiness", "Enables/disables friction of ragdoll", Slipperiness)); + (ms_uiElements[(int)UiElementIndex.Slipperiness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => + { + Slipperiness = state; + ms_entries[(int)ModSetting.Slipperiness].BoxedValue = state; + SlipperinessChange?.Invoke(state); + }; + + ms_uiElements.Add(l_categoryMod.AddToggle("Bounciness", "Enables/disables bounciness of ragdoll", Bounciness)); + (ms_uiElements[(int)UiElementIndex.Bounciness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => + { + Bounciness = state; + ms_entries[(int)ModSetting.Bounciness].BoxedValue = state; + BouncinessChange?.Invoke(state); + }; + ms_uiElements.Add(l_page.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", VelocityMultiplier, 1f, 50f)); (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => { @@ -240,6 +268,16 @@ namespace ml_prm (ms_uiElements[(int)UiElementIndex.AutoRecover] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = false; AutoRecoverChange?.Invoke(false); + Slipperiness = false; + ms_entries[(int)ModSetting.Slipperiness].BoxedValue = false; + (ms_uiElements[(int)UiElementIndex.Slipperiness] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = false; + SlipperinessChange?.Invoke(false); + + Bounciness = false; + ms_entries[(int)ModSetting.Bounciness].BoxedValue = false; + (ms_uiElements[(int)UiElementIndex.Bounciness] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = false; + BouncinessChange?.Invoke(false); + VelocityMultiplier = 2f; ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue = 2f; (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(2f); From 4501e858c7acdb4c79a29ddfbfbd1f6562dc1700 Mon Sep 17 00:00:00 2001 From: SDraw Date: Mon, 17 Apr 2023 14:41:03 +0300 Subject: [PATCH 39/63] Settings rework Velocity limit rework View direction and VR camera ragdoll following --- ml_prm/RagdollController.cs | 30 +++- ml_prm/Settings.cs | 308 +++++++++++++++++++----------------- ml_prm/Utils.cs | 9 +- 3 files changed, 192 insertions(+), 155 deletions(-) diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index c626c12..9e3b001 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -1,6 +1,7 @@ using ABI.CCK.Components; using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Player; +using ABI_RC.Core.Player.AvatarTracking.Local; using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.MovementSystem; using RootMotion.Dynamics; @@ -17,6 +18,8 @@ namespace ml_prm VRIK m_vrIK = null; float m_vrIkWeight = 1f; + LocalHeadPoint m_headPoint = null; + bool m_inVr = false; bool m_enabled = false; @@ -64,6 +67,9 @@ namespace ml_prm // Unity events void Start() { + m_inVr = Utils.IsInVR(); + m_headPoint = this.GetComponent(); + m_puppetRoot = new GameObject("[PlayerAvatarPuppet]").transform; m_puppetRoot.parent = PlayerSetup.Instance.transform; m_puppetRoot.localPosition = Vector3.zero; @@ -136,6 +142,12 @@ namespace ml_prm foreach(var l_link in m_boneLinks) l_link.Item1.CopyGlobal(l_link.Item2); + + if(m_inVr && Settings.VrFollow) + { + Transform l_camera = PlayerSetup.Instance.GetActiveCamera().transform; + l_camera.position = m_headPoint.GetPointPosition(); + } } } @@ -164,6 +176,8 @@ namespace ml_prm internal void OnAvatarSetup() { + m_inVr = Utils.IsInVR(); + if(PlayerSetup.Instance._animator.isHuman) { BipedRagdollReferences l_avatarReferences = BipedRagdollReferences.FromAvatar(PlayerSetup.Instance._animator); @@ -282,12 +296,7 @@ namespace ml_prm if(m_enabled && m_avatarReady) SwitchRagdoll(); - if(m_avatarReady) - { - foreach(Rigidbody l_body in m_rigidBodies) - l_body.useGravity = (!Utils.IsWorldSafe() || Settings.Gravity); - } - + OnGravityChange(Settings.Gravity); OnPhysicsMaterialChange(true); } @@ -394,7 +403,12 @@ namespace ml_prm foreach(Rigidbody l_body in m_rigidBodies) l_body.isKinematic = false; - Vector3 l_velocity = m_velocity * Mathf.Clamp(Settings.VelocityMultiplier, 1f, (Utils.IsWorldSafe() ? Utils.GetWorldFlyMultiplier() : 1f)); + Vector3 l_velocity = Vector3.ClampMagnitude(m_velocity * (Utils.IsWorldSafe() ? Settings.VelocityMultiplier : 1f), Utils.GetWorldMovementLimit()); + if(Settings.ViewVelocity && Utils.IsWorldSafe()) + { + float l_mag = l_velocity.magnitude; + l_velocity = PlayerSetup.Instance.GetActiveCamera().transform.forward * l_mag; + } foreach(Rigidbody l_body in m_rigidBodies) { @@ -428,7 +442,7 @@ namespace ml_prm if(!Settings.RestorePosition) { - if(Utils.IsInVR()) + if(m_inVr) { Vector3 l_diff = l_hipsPos - PlayerSetup.Instance._avatar.transform.position; Vector3 l_playerPos = PlayerSetup.Instance.transform.position; diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index 8dc8577..90bc936 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -21,7 +21,9 @@ namespace ml_prm AutoRecover, RecoverDelay, Slipperiness, - Bounciness + Bounciness, + ViewVelocity, + VrFollow, } enum UiElementIndex @@ -35,10 +37,14 @@ namespace ml_prm AutoRecover, Slipperiness, Bounciness, + ViewVelocity, + VrFollow, VelocityMultiplier, MovementDrag, AngularDrag, - RecoverDelay + RecoverDelay, + + Count } public static bool Hotkey { get; private set; } = true; @@ -54,6 +60,8 @@ namespace ml_prm public static float RecoverDelay { get; private set; } = 3f; public static bool Slipperiness { get; private set; } = false; public static bool Bounciness { get; private set; } = false; + public static bool ViewVelocity { get; private set; } = false; + public static bool VrFollow { get; private set; } = true; static public event Action SwitchChange; static public event Action HotkeyChange; @@ -69,6 +77,8 @@ namespace ml_prm static public event Action RecoverDelayChange; static public event Action SlipperinessChange; static public event Action BouncinessChange; + static public event Action ViewVelocityChange; + static public event Action VrFollowChange; static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; @@ -92,7 +102,9 @@ namespace ml_prm ms_category.CreateEntry(ModSetting.AutoRecover.ToString(), AutoRecover), ms_category.CreateEntry(ModSetting.RecoverDelay.ToString(), RecoverDelay), ms_category.CreateEntry(ModSetting.Slipperiness.ToString(), Slipperiness), - ms_category.CreateEntry(ModSetting.Bounciness.ToString(), Bounciness) + ms_category.CreateEntry(ModSetting.Bounciness.ToString(), Bounciness), + ms_category.CreateEntry(ModSetting.ViewVelocity.ToString(), ViewVelocity), + ms_category.CreateEntry(ModSetting.VrFollow.ToString(), VrFollow) }; Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; @@ -108,6 +120,8 @@ namespace ml_prm RecoverDelay = Mathf.Clamp((float)ms_entries[(int)ModSetting.RecoverDelay].BoxedValue, 1f, 10f); Slipperiness = (bool)ms_entries[(int)ModSetting.Slipperiness].BoxedValue; Bounciness = (bool)ms_entries[(int)ModSetting.Bounciness].BoxedValue; + ViewVelocity = (bool)ms_entries[(int)ModSetting.ViewVelocity].BoxedValue; + VrFollow = (bool)ms_entries[(int)ModSetting.VrFollow].BoxedValue; if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null) { @@ -122,182 +136,186 @@ namespace ml_prm l_page.MenuTitle = "Ragdoll settings"; var l_categoryMod = l_page.AddCategory("Settings"); - l_categoryMod.AddButton("Switch ragdoll", "", "Switch between normal and ragdoll state").OnPress += () => - { - SwitchChange?.Invoke(); - }; + l_categoryMod.AddButton("Switch ragdoll", "", "Switch between normal and ragdoll state").OnPress += () => SwitchChange?.Invoke(); ms_uiElements.Add(l_categoryMod.AddToggle("Use hotkey", "Switch ragdoll mode with 'R' key", Hotkey)); - (ms_uiElements[(int)UiElementIndex.Hotkey] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => - { - Hotkey = state; - ms_entries[(int)ModSetting.Hotkey].BoxedValue = state; - HotkeyChange?.Invoke(state); - }; + (ms_uiElements[(int)UiElementIndex.Hotkey] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Hotkey, state); ms_uiElements.Add(l_categoryMod.AddToggle("Restore position", "Bring avatar back where ragdoll state was activated", RestorePosition)); - (ms_uiElements[(int)UiElementIndex.RestorePosition] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => - { - RestorePosition = state; - ms_entries[(int)ModSetting.RestorePosition].BoxedValue = state; - RestorePositionChange?.Invoke(state); - }; + (ms_uiElements[(int)UiElementIndex.RestorePosition] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.RestorePosition, state); ms_uiElements.Add(l_categoryMod.AddToggle("Use gravity", "Apply gravity to ragdoll", Gravity)); - (ms_uiElements[(int)UiElementIndex.Gravity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => - { - Gravity = state; - ms_entries[(int)ModSetting.Gravity].BoxedValue = state; - GravityChange?.Invoke(state); - }; + (ms_uiElements[(int)UiElementIndex.Gravity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Gravity, state); ms_uiElements.Add(l_categoryMod.AddToggle("Pointers reaction", "React to trigger colliders with CVRPointer component of 'ragdoll' type", PointersReaction)); - (ms_uiElements[(int)UiElementIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => - { - PointersReaction = state; - ms_entries[(int)ModSetting.PointersReaction].BoxedValue = state; - PointersReactionChange?.Invoke(state); - }; + (ms_uiElements[(int)UiElementIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.PointersReaction, state); ms_uiElements.Add(l_categoryMod.AddToggle("Ignore local pointers", "Ignore local avatar's CVRPointer components of 'ragdoll' type", IgnoreLocal)); - (ms_uiElements[(int)UiElementIndex.IgnoreLocal] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => - { - IgnoreLocal = state; - ms_entries[(int)ModSetting.IgnoreLocal].BoxedValue = state; - IgnoreLocalChange?.Invoke(state); - }; + (ms_uiElements[(int)UiElementIndex.IgnoreLocal] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.IgnoreLocal, state); ms_uiElements.Add(l_categoryMod.AddToggle("Combat reaction", "Ragdoll upon combat system death", CombatReaction)); - (ms_uiElements[(int)UiElementIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => - { - CombatReaction = state; - ms_entries[(int)ModSetting.CombatReaction].BoxedValue = state; - CombatReactionChange?.Invoke(state); - }; + (ms_uiElements[(int)UiElementIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.CombatReaction, state); ms_uiElements.Add(l_categoryMod.AddToggle("Auto recover", "Automatically unragdoll after set recover delay", AutoRecover)); - (ms_uiElements[(int)UiElementIndex.AutoRecover] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => - { - AutoRecover = state; - ms_entries[(int)ModSetting.AutoRecover].BoxedValue = state; - AutoRecoverChange?.Invoke(state); - }; + (ms_uiElements[(int)UiElementIndex.AutoRecover] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.AutoRecover, state); ms_uiElements.Add(l_categoryMod.AddToggle("Slipperiness", "Enables/disables friction of ragdoll", Slipperiness)); - (ms_uiElements[(int)UiElementIndex.Slipperiness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => - { - Slipperiness = state; - ms_entries[(int)ModSetting.Slipperiness].BoxedValue = state; - SlipperinessChange?.Invoke(state); - }; + (ms_uiElements[(int)UiElementIndex.Slipperiness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Slipperiness, state); ms_uiElements.Add(l_categoryMod.AddToggle("Bounciness", "Enables/disables bounciness of ragdoll", Bounciness)); - (ms_uiElements[(int)UiElementIndex.Bounciness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => - { - Bounciness = state; - ms_entries[(int)ModSetting.Bounciness].BoxedValue = state; - BouncinessChange?.Invoke(state); - }; + (ms_uiElements[(int)UiElementIndex.Bounciness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Bounciness, state); + + ms_uiElements.Add(l_categoryMod.AddToggle("View direction velocity", "Apply velocity to camera view direction", ViewVelocity)); + (ms_uiElements[(int)UiElementIndex.ViewVelocity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.ViewVelocity, state); + + ms_uiElements.Add(l_categoryMod.AddToggle("VR camera follow", "Forces VR camera to follow ragdoll", VrFollow)); + (ms_uiElements[(int)UiElementIndex.VrFollow] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate( ModSetting.VrFollow, state); ms_uiElements.Add(l_page.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", VelocityMultiplier, 1f, 50f)); - (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => - { - VelocityMultiplier = value; - ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue = value; - VelocityMultiplierChange?.Invoke(value); - }; + (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(ModSetting.VelocityMultiplier, value); ms_uiElements.Add(l_page.AddSlider("Movement drag", "Movement resistance", MovementDrag, 0f, 50f)); - (ms_uiElements[(int)UiElementIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => - { - MovementDrag = value; - ms_entries[(int)ModSetting.MovementDrag].BoxedValue = value; - MovementDragChange?.Invoke(value); - }; + (ms_uiElements[(int)UiElementIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(ModSetting.MovementDrag, value); ms_uiElements.Add(l_page.AddSlider("Angular movement drag", "Rotation movement resistance", AngularDrag, 0f, 50f)); - (ms_uiElements[(int)UiElementIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => - { - AngularDrag = value; - ms_entries[(int)ModSetting.AngularDrag].BoxedValue = value; - AngularDragChange?.Invoke(value); - }; + (ms_uiElements[(int)UiElementIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(ModSetting.AngularDrag, value); ms_uiElements.Add(l_page.AddSlider("Recover delay (seconds)", "Recover delay for automatic recover", RecoverDelay, 1f, 10f)); - (ms_uiElements[(int)UiElementIndex.RecoverDelay] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => + (ms_uiElements[(int)UiElementIndex.RecoverDelay] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(ModSetting.RecoverDelay, value); + + l_categoryMod.AddButton("Reset settings", "", "Reset mod settings to default").OnPress += Reset; + } + + static void OnToggleUpdate(ModSetting p_setting, bool p_state, UiElementIndex p_uiIndex = UiElementIndex.Count) + { + switch(p_setting) { - RecoverDelay = value; - ms_entries[(int)ModSetting.RecoverDelay].BoxedValue = value; - RecoverDelayChange?.Invoke(value); - }; + case ModSetting.Hotkey: + { + Hotkey = p_state; + HotkeyChange?.Invoke(p_state); + } + break; - l_categoryMod.AddButton("Reset settings", "", "Reset mod settings to default").OnPress += () => + case ModSetting.RestorePosition: + { + RestorePosition = p_state; + RestorePositionChange?.Invoke(p_state); + } + break; + + case ModSetting.Gravity: + { + Gravity = p_state; + GravityChange?.Invoke(p_state); + } + break; + + case ModSetting.PointersReaction: + { + PointersReaction = p_state; + PointersReactionChange?.Invoke(p_state); + } break; + + case ModSetting.IgnoreLocal: + { + IgnoreLocal = p_state; + IgnoreLocalChange?.Invoke(p_state); + } break; + + case ModSetting.CombatReaction: + { + CombatReaction = p_state; + CombatReactionChange?.Invoke(p_state); + } break; + + case ModSetting.AutoRecover: + { + AutoRecover = p_state; + AutoRecoverChange?.Invoke(p_state); + } break; + + case ModSetting.Slipperiness: + { + Slipperiness = p_state; + SlipperinessChange?.Invoke(p_state); + } break; + + case ModSetting.Bounciness: + { + Bounciness = p_state; + BouncinessChange?.Invoke(p_state); + } break; + + case ModSetting.ViewVelocity: + { + ViewVelocity = p_state; + ViewVelocityChange?.Invoke(p_state); + } break; + + case ModSetting.VrFollow: + { + VrFollow = p_state; + VrFollowChange?.Invoke(p_state); + } break; + } + + ms_entries[(int)p_setting].BoxedValue = p_state; + if(p_uiIndex != UiElementIndex.Count) + (ms_uiElements[(int)p_uiIndex] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = p_state; + } + + static void OnSliderUpdate(ModSetting p_setting, float p_value, UiElementIndex p_uiIndex = UiElementIndex.Count) + { + switch(p_setting) { - Hotkey = true; - (ms_uiElements[(int)UiElementIndex.Hotkey] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; - ms_entries[(int)ModSetting.Hotkey].BoxedValue = true; - HotkeyChange?.Invoke(true); + case ModSetting.VelocityMultiplier: + { + VelocityMultiplier = p_value; + VelocityMultiplierChange?.Invoke(p_value); + } break; - RestorePosition = false; - ms_entries[(int)ModSetting.RestorePosition].BoxedValue = false; - (ms_uiElements[(int)UiElementIndex.RestorePosition] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = false; - RestorePositionChange?.Invoke(false); + case ModSetting.MovementDrag: + { + MovementDrag = p_value; + MovementDragChange?.Invoke(p_value); + } break; - Gravity = true; - ms_entries[(int)ModSetting.Gravity].BoxedValue = true; - (ms_uiElements[(int)UiElementIndex.Gravity] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; - GravityChange?.Invoke(true); + case ModSetting.AngularDrag: + { + AngularDrag = p_value; + AngularDragChange?.Invoke(p_value); + } break; - PointersReaction = true; - ms_entries[(int)ModSetting.PointersReaction].BoxedValue = true; - (ms_uiElements[(int)UiElementIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; - PointersReactionChange?.Invoke(true); + case ModSetting.RecoverDelay: + { + RecoverDelay = p_value; + RecoverDelayChange?.Invoke(p_value); + } break; + } - IgnoreLocal = true; - ms_entries[(int)ModSetting.IgnoreLocal].BoxedValue = true; - (ms_uiElements[(int)UiElementIndex.IgnoreLocal] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; - IgnoreLocalChange?.Invoke(true); + ms_entries[(int)p_setting].BoxedValue = p_value; + if(p_uiIndex != UiElementIndex.Count) + (ms_uiElements[(int)p_uiIndex] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(p_value); + } - CombatReaction = true; - ms_entries[(int)ModSetting.CombatReaction].BoxedValue = true; - (ms_uiElements[(int)UiElementIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = true; - CombatReactionChange?.Invoke(true); - - AutoRecover = false; - ms_entries[(int)ModSetting.AutoRecover].BoxedValue = false; - (ms_uiElements[(int)UiElementIndex.AutoRecover] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = false; - AutoRecoverChange?.Invoke(false); - - Slipperiness = false; - ms_entries[(int)ModSetting.Slipperiness].BoxedValue = false; - (ms_uiElements[(int)UiElementIndex.Slipperiness] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = false; - SlipperinessChange?.Invoke(false); - - Bounciness = false; - ms_entries[(int)ModSetting.Bounciness].BoxedValue = false; - (ms_uiElements[(int)UiElementIndex.Bounciness] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = false; - BouncinessChange?.Invoke(false); - - VelocityMultiplier = 2f; - ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue = 2f; - (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(2f); - VelocityMultiplierChange?.Invoke(2f); - - MovementDrag = 2f; - ms_entries[(int)ModSetting.MovementDrag].BoxedValue = 2f; - (ms_uiElements[(int)UiElementIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(2f); - MovementDragChange?.Invoke(2f); - - AngularDrag = 2f; - ms_entries[(int)ModSetting.AngularDrag].BoxedValue = 2f; - (ms_uiElements[(int)UiElementIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(2f); - AngularDragChange?.Invoke(2f); - - RecoverDelay = 3f; - ms_entries[(int)ModSetting.RecoverDelay].BoxedValue = 3f; - (ms_uiElements[(int)UiElementIndex.RecoverDelay] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(3f); - RecoverDelayChange?.Invoke(3f); - }; + static void Reset() + { + OnToggleUpdate(ModSetting.Hotkey, true, UiElementIndex.Hotkey); + OnToggleUpdate(ModSetting.RestorePosition, false, UiElementIndex.RestorePosition); + OnToggleUpdate(ModSetting.Gravity, true, UiElementIndex.Gravity); + OnToggleUpdate(ModSetting.PointersReaction, true, UiElementIndex.PointersReaction); + OnToggleUpdate(ModSetting.IgnoreLocal, true, UiElementIndex.IgnoreLocal); + OnToggleUpdate(ModSetting.CombatReaction, true, UiElementIndex.CombatReaction); + OnToggleUpdate(ModSetting.AutoRecover, false, UiElementIndex.AutoRecover); + OnToggleUpdate(ModSetting.Slipperiness, false, UiElementIndex.Slipperiness); + OnToggleUpdate(ModSetting.Bounciness, false, UiElementIndex.Bounciness); + OnToggleUpdate(ModSetting.ViewVelocity, false, UiElementIndex.ViewVelocity); + OnToggleUpdate(ModSetting.VrFollow, true, UiElementIndex.VrFollow); + OnSliderUpdate(ModSetting.VelocityMultiplier, 2f, UiElementIndex.VelocityMultiplier); + OnSliderUpdate(ModSetting.MovementDrag, 2f, UiElementIndex.MovementDrag); + OnSliderUpdate(ModSetting.AngularDrag, 2f, UiElementIndex.AngularDrag); + OnSliderUpdate(ModSetting.RecoverDelay, 3f, UiElementIndex.RecoverDelay); } } } diff --git a/ml_prm/Utils.cs b/ml_prm/Utils.cs index c6eb321..d4aa8f0 100644 --- a/ml_prm/Utils.cs +++ b/ml_prm/Utils.cs @@ -12,11 +12,16 @@ namespace ml_prm public static bool IsInVR() => ((CheckVR.Instance != null) && CheckVR.Instance.hasVrDeviceLoaded); public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying); - public static float GetWorldFlyMultiplier() + public static float GetWorldMovementLimit() { float l_result = 1f; if(CVRWorld.Instance != null) - l_result = CVRWorld.Instance.flyMultiplier; + { + l_result = CVRWorld.Instance.baseMovementSpeed; + l_result *= CVRWorld.Instance.sprintMultiplier; + l_result *= CVRWorld.Instance.inAirMovementMultiplier; + l_result *= CVRWorld.Instance.flyMultiplier; + } return l_result; } From 5e463ec0a9eabc42171453910346b2459f498df2 Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 18 Apr 2023 01:04:04 +0300 Subject: [PATCH 40/63] Constant ragdoll following in desktop and VR Removed `Restore position` option --- ml_prm/RagdollController.cs | 58 ++++++++++++++++++------------------- ml_prm/Settings.cs | 37 ++--------------------- 2 files changed, 31 insertions(+), 64 deletions(-) diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 9e3b001..602e56e 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -1,7 +1,7 @@ using ABI.CCK.Components; using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Player; -using ABI_RC.Core.Player.AvatarTracking.Local; +using ABI_RC.Core.Savior; using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.MovementSystem; using RootMotion.Dynamics; @@ -18,7 +18,6 @@ namespace ml_prm VRIK m_vrIK = null; float m_vrIkWeight = 1f; - LocalHeadPoint m_headPoint = null; bool m_inVr = false; bool m_enabled = false; @@ -33,6 +32,7 @@ namespace ml_prm bool m_avatarReady = false; Vector3 m_lastPosition = Vector3.zero; Vector3 m_velocity = Vector3.zero; + Vector3 m_ragdollLastPos = Vector3.zero; RagdollToggle m_avatarRagdollToggle = null; RagdollTrigger m_customTrigger = null; @@ -68,7 +68,6 @@ namespace ml_prm void Start() { m_inVr = Utils.IsInVR(); - m_headPoint = this.GetComponent(); m_puppetRoot = new GameObject("[PlayerAvatarPuppet]").transform; m_puppetRoot.parent = PlayerSetup.Instance.transform; @@ -103,9 +102,20 @@ namespace ml_prm void Update() { - Vector3 l_pos = PlayerSetup.Instance.transform.position; - m_velocity = (m_velocity + (l_pos - m_lastPosition) / Time.deltaTime) * 0.5f; - m_lastPosition = l_pos; + if(m_enabled && m_avatarReady) + { + Vector3 l_dif = m_puppetReferences.hips.position - m_ragdollLastPos; + PlayerSetup.Instance.transform.position += l_dif; + m_puppetReferences.hips.position -= l_dif; + m_ragdollLastPos = m_puppetReferences.hips.position; + } + + if(!m_enabled && m_avatarReady) + { + Vector3 l_pos = PlayerSetup.Instance.transform.position; + m_velocity = (m_velocity + (l_pos - m_lastPosition) / Time.deltaTime) * 0.5f; + m_lastPosition = l_pos; + } if(m_avatarReady && !m_reachedGround && MovementSystem.Instance.IsGrounded()) m_reachedGround = true; @@ -142,12 +152,6 @@ namespace ml_prm foreach(var l_link in m_boneLinks) l_link.Item1.CopyGlobal(l_link.Item2); - - if(m_inVr && Settings.VrFollow) - { - Transform l_camera = PlayerSetup.Instance.GetActiveCamera().transform; - l_camera.position = m_headPoint.GetPointPosition(); - } } } @@ -382,7 +386,16 @@ namespace ml_prm { Vector3 l_pos = PlayerSetup.Instance.transform.position; Quaternion l_rot = PlayerSetup.Instance.transform.rotation; - MovementSystem.Instance.lastSeat.ExitSeat(); + + if(MetaPort.Instance.isUsingVr) + { + MetaPort.Instance.isUsingVr = false; + MovementSystem.Instance.lastSeat.ExitSeat(); + MetaPort.Instance.isUsingVr = true; + } + else + MovementSystem.Instance.lastSeat.ExitSeat(); + PlayerSetup.Instance.transform.position = l_pos; PlayerSetup.Instance.transform.rotation = Quaternion.Euler(0f, l_rot.eulerAngles.y, 0f); } @@ -419,6 +432,7 @@ namespace ml_prm foreach(Collider l_collider in m_colliders) l_collider.enabled = true; + m_ragdollLastPos = m_puppetReferences.hips.position; m_downTime = 0f; m_enabled = true; @@ -436,22 +450,8 @@ namespace ml_prm foreach(Rigidbody l_body in m_rigidBodies) l_body.isKinematic = true; - if(m_puppetReferences.hips != null) - { - Vector3 l_hipsPos = m_puppetReferences.hips.position; - - if(!Settings.RestorePosition) - { - if(m_inVr) - { - Vector3 l_diff = l_hipsPos - PlayerSetup.Instance._avatar.transform.position; - Vector3 l_playerPos = PlayerSetup.Instance.transform.position; - PlayerSetup.Instance.transform.position = l_playerPos + l_diff; - } - else - PlayerSetup.Instance.transform.position = l_hipsPos; - } - } + PlayerSetup.Instance.transform.position = m_puppetReferences.hips.position; + PlayerSetup.Instance.transform.position -= (PlayerSetup.Instance.transform.rotation * PlayerSetup.Instance._avatar.transform.localPosition); foreach(Collider l_collider in m_colliders) l_collider.enabled = false; diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index 90bc936..86f05e6 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -11,7 +11,6 @@ namespace ml_prm { Hotkey = 0, VelocityMultiplier, - RestorePosition, MovementDrag, AngularDrag, Gravity, @@ -22,14 +21,12 @@ namespace ml_prm RecoverDelay, Slipperiness, Bounciness, - ViewVelocity, - VrFollow, + ViewVelocity } enum UiElementIndex { Hotkey = 0, - RestorePosition, Gravity, PointersReaction, IgnoreLocal, @@ -38,7 +35,6 @@ namespace ml_prm Slipperiness, Bounciness, ViewVelocity, - VrFollow, VelocityMultiplier, MovementDrag, AngularDrag, @@ -49,7 +45,6 @@ namespace ml_prm public static bool Hotkey { get; private set; } = true; public static float VelocityMultiplier { get; private set; } = 2f; - public static bool RestorePosition { get; private set; } = false; public static float MovementDrag { get; private set; } = 2f; public static float AngularDrag { get; private set; } = 2f; public static bool Gravity { get; private set; } = true; @@ -61,11 +56,9 @@ namespace ml_prm public static bool Slipperiness { get; private set; } = false; public static bool Bounciness { get; private set; } = false; public static bool ViewVelocity { get; private set; } = false; - public static bool VrFollow { get; private set; } = true; static public event Action SwitchChange; static public event Action HotkeyChange; - static public event Action RestorePositionChange; static public event Action VelocityMultiplierChange; static public event Action MovementDragChange; static public event Action AngularDragChange; @@ -78,7 +71,6 @@ namespace ml_prm static public event Action SlipperinessChange; static public event Action BouncinessChange; static public event Action ViewVelocityChange; - static public event Action VrFollowChange; static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; @@ -92,7 +84,6 @@ namespace ml_prm { ms_category.CreateEntry(ModSetting.Hotkey.ToString(), Hotkey), ms_category.CreateEntry(ModSetting.VelocityMultiplier.ToString(), VelocityMultiplier), - ms_category.CreateEntry(ModSetting.RestorePosition.ToString(), RestorePosition), ms_category.CreateEntry(ModSetting.MovementDrag.ToString(), MovementDrag), ms_category.CreateEntry(ModSetting.AngularDrag.ToString(), AngularDrag), ms_category.CreateEntry(ModSetting.Gravity.ToString(), Gravity), @@ -103,13 +94,11 @@ namespace ml_prm ms_category.CreateEntry(ModSetting.RecoverDelay.ToString(), RecoverDelay), ms_category.CreateEntry(ModSetting.Slipperiness.ToString(), Slipperiness), ms_category.CreateEntry(ModSetting.Bounciness.ToString(), Bounciness), - ms_category.CreateEntry(ModSetting.ViewVelocity.ToString(), ViewVelocity), - ms_category.CreateEntry(ModSetting.VrFollow.ToString(), VrFollow) + ms_category.CreateEntry(ModSetting.ViewVelocity.ToString(), ViewVelocity) }; Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; VelocityMultiplier = Mathf.Clamp((float)ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue, 1f, 50f); - RestorePosition = (bool)ms_entries[(int)ModSetting.RestorePosition].BoxedValue; MovementDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); AngularDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue; @@ -121,7 +110,6 @@ namespace ml_prm Slipperiness = (bool)ms_entries[(int)ModSetting.Slipperiness].BoxedValue; Bounciness = (bool)ms_entries[(int)ModSetting.Bounciness].BoxedValue; ViewVelocity = (bool)ms_entries[(int)ModSetting.ViewVelocity].BoxedValue; - VrFollow = (bool)ms_entries[(int)ModSetting.VrFollow].BoxedValue; if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null) { @@ -141,9 +129,6 @@ namespace ml_prm ms_uiElements.Add(l_categoryMod.AddToggle("Use hotkey", "Switch ragdoll mode with 'R' key", Hotkey)); (ms_uiElements[(int)UiElementIndex.Hotkey] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Hotkey, state); - ms_uiElements.Add(l_categoryMod.AddToggle("Restore position", "Bring avatar back where ragdoll state was activated", RestorePosition)); - (ms_uiElements[(int)UiElementIndex.RestorePosition] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.RestorePosition, state); - ms_uiElements.Add(l_categoryMod.AddToggle("Use gravity", "Apply gravity to ragdoll", Gravity)); (ms_uiElements[(int)UiElementIndex.Gravity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Gravity, state); @@ -168,9 +153,6 @@ namespace ml_prm ms_uiElements.Add(l_categoryMod.AddToggle("View direction velocity", "Apply velocity to camera view direction", ViewVelocity)); (ms_uiElements[(int)UiElementIndex.ViewVelocity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.ViewVelocity, state); - ms_uiElements.Add(l_categoryMod.AddToggle("VR camera follow", "Forces VR camera to follow ragdoll", VrFollow)); - (ms_uiElements[(int)UiElementIndex.VrFollow] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate( ModSetting.VrFollow, state); - ms_uiElements.Add(l_page.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", VelocityMultiplier, 1f, 50f)); (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(ModSetting.VelocityMultiplier, value); @@ -197,13 +179,6 @@ namespace ml_prm } break; - case ModSetting.RestorePosition: - { - RestorePosition = p_state; - RestorePositionChange?.Invoke(p_state); - } - break; - case ModSetting.Gravity: { Gravity = p_state; @@ -252,12 +227,6 @@ namespace ml_prm ViewVelocity = p_state; ViewVelocityChange?.Invoke(p_state); } break; - - case ModSetting.VrFollow: - { - VrFollow = p_state; - VrFollowChange?.Invoke(p_state); - } break; } ms_entries[(int)p_setting].BoxedValue = p_state; @@ -302,7 +271,6 @@ namespace ml_prm static void Reset() { OnToggleUpdate(ModSetting.Hotkey, true, UiElementIndex.Hotkey); - OnToggleUpdate(ModSetting.RestorePosition, false, UiElementIndex.RestorePosition); OnToggleUpdate(ModSetting.Gravity, true, UiElementIndex.Gravity); OnToggleUpdate(ModSetting.PointersReaction, true, UiElementIndex.PointersReaction); OnToggleUpdate(ModSetting.IgnoreLocal, true, UiElementIndex.IgnoreLocal); @@ -311,7 +279,6 @@ namespace ml_prm OnToggleUpdate(ModSetting.Slipperiness, false, UiElementIndex.Slipperiness); OnToggleUpdate(ModSetting.Bounciness, false, UiElementIndex.Bounciness); OnToggleUpdate(ModSetting.ViewVelocity, false, UiElementIndex.ViewVelocity); - OnToggleUpdate(ModSetting.VrFollow, true, UiElementIndex.VrFollow); OnSliderUpdate(ModSetting.VelocityMultiplier, 2f, UiElementIndex.VelocityMultiplier); OnSliderUpdate(ModSetting.MovementDrag, 2f, UiElementIndex.MovementDrag); OnSliderUpdate(ModSetting.AngularDrag, 2f, UiElementIndex.AngularDrag); From fb2a7ed119b304c6f628dfb2599c39bac8275c95 Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 18 Apr 2023 08:40:46 +0300 Subject: [PATCH 41/63] Update README.md --- ml_prm/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ml_prm/README.md b/ml_prm/README.md index ccd275c..992788b 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -12,7 +12,6 @@ This mod turns player's avatar into ragdoll puppet. Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUILib): * **Switch ragdoll:** turns into ragdoll state and back, made for VR usage primarily. * **Use hotkey:** enables/disables ragdoll state switch with `R` key; `true` by default. -* **Restore position:** returns to position of ragdoll state activation upon ragdoll state exit; `false` by default. * **Use gravity:** enables/disables gravity for ragdoll; `true` by default. * Note: Forcibly enabled in worlds that don't allow flight. * **Pointers reaction:** enables ragdoll state when player collides with trigger colliders with CVRPointer component of `ragdoll` type (avatars, props and world included); `true` by default. @@ -23,6 +22,8 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * Note: Forcibly disabled in worlds that don't allow flight. * **Bounciness:** enables/disable bounce force of ragdoll; `false` by default. * Note: Forcibly disabled in worlds that don't allow flight. +* **View direction velocity:** apply velocity to camera view direction instead of player movement direction; `false` by default. + * Note: Forcibly disabled in worlds that don't allow flight. * **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. * Note: Limited according to world's fly multiplier. * Note: Forcibly set to `1.0` in worlds that don't allow flight. From 823a76d95a7c2d99699fb73e8d5b6ddc4cb9b393 Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 18 Apr 2023 12:08:49 +0300 Subject: [PATCH 42/63] Flight mode consideration Possible IK pose consideration Minor fixes --- ml_prm/Main.cs | 29 +++++++++++++++++--- ml_prm/README.md | 1 - ml_prm/RagdollController.cs | 54 +++++++++++++++++++++++++------------ 3 files changed, 62 insertions(+), 22 deletions(-) diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs index a8abb8f..cb01968 100644 --- a/ml_prm/Main.cs +++ b/ml_prm/Main.cs @@ -1,13 +1,14 @@ -using ABI_RC.Core; +using ABI.CCK.Components; +using ABI_RC.Core; using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Player; +using ABI_RC.Core.Util.AssetFiltering; using ABI_RC.Systems.IK.SubSystems; +using ABI_RC.Systems.MovementSystem; using System; using System.Collections.Generic; -using System.Reflection; -using ABI_RC.Core.Util.AssetFiltering; -using ABI.CCK.Components; using System.Linq; +using System.Reflection; namespace ml_prm { @@ -54,6 +55,11 @@ namespace ml_prm new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnCombatDown_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), null ); + HarmonyInstance.Patch( + typeof(MovementSystem).GetMethod(nameof(MovementSystem.ToggleFlight)), + null, + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnToggleFlight_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); // Whitelist the toggle script (typeof(SharedFilter).GetField("_localComponentWhitelist", BindingFlags.NonPublic | BindingFlags.Static)?.GetValue(null) as HashSet)?.Add(typeof(RagdollToggle)); @@ -77,6 +83,7 @@ namespace ml_prm m_localController = PlayerSetup.Instance.gameObject.AddComponent(); } + // Patches static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear(); void OnAvatarClear() { @@ -164,5 +171,19 @@ namespace ml_prm MelonLoader.MelonLogger.Error(e); } } + + static void OnToggleFlight_Postfix() => ms_instance?.OnToggleFlight(); + void OnToggleFlight() + { + try + { + if(m_localController != null) + m_localController.OnToggleFlight(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } } } diff --git a/ml_prm/README.md b/ml_prm/README.md index 992788b..c81013e 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -58,7 +58,6 @@ Available methods: * ```void SwitchRagdoll()``` # Notes -* Not suggested to activate fly mode with enabled ragdoll state. * If ragdoll state is enabled during emote, remote players see whole emote playing while local player sees ragdolling. It's tied to how game handles remote players, currently can be prevented with (choose one): * Renaming avatar emote animations to not have default name or containing `Emote` substring. * Holding any movement key right after activating ragdoll state. diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 602e56e..52231d3 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -102,7 +102,7 @@ namespace ml_prm void Update() { - if(m_enabled && m_avatarReady) + if(m_avatarReady && m_enabled) { Vector3 l_dif = m_puppetReferences.hips.position - m_ragdollLastPos; PlayerSetup.Instance.transform.position += l_dif; @@ -110,17 +110,17 @@ namespace ml_prm m_ragdollLastPos = m_puppetReferences.hips.position; } - if(!m_enabled && m_avatarReady) + if(m_avatarReady && !m_enabled) { Vector3 l_pos = PlayerSetup.Instance.transform.position; m_velocity = (m_velocity + (l_pos - m_lastPosition) / Time.deltaTime) * 0.5f; m_lastPosition = l_pos; } - if(m_avatarReady && !m_reachedGround && MovementSystem.Instance.IsGrounded()) - m_reachedGround = true; + if(m_avatarReady && !m_reachedGround) + m_reachedGround = MovementSystem.Instance.IsGrounded(); - if(m_enabled && m_avatarReady && BodySystem.isCalibratedAsFullBody) + if(m_avatarReady && m_enabled && BodySystem.isCalibratedAsFullBody && !BodySystem.isCalibrating) BodySystem.TrackingPositionWeight = 0f; if(m_avatarReady && m_enabled && Settings.AutoRecover) @@ -139,20 +139,26 @@ namespace ml_prm if((m_avatarRagdollToggle != null) && m_avatarRagdollToggle.isActiveAndEnabled && m_avatarRagdollToggle.shouldOverride && (m_enabled != m_avatarRagdollToggle.isOn)) SwitchRagdoll(); - if((m_customTrigger != null) && m_customTrigger.GetStateWithReset() && !m_enabled && m_avatarReady && Settings.PointersReaction) + if((m_customTrigger != null) && m_customTrigger.GetStateWithReset() && m_avatarReady && !m_enabled && Settings.PointersReaction) SwitchRagdoll(); } void LateUpdate() { - if(m_enabled && m_avatarReady) + if(m_avatarReady && m_enabled) { - if(BodySystem.isCalibratedAsFullBody) + if(BodySystem.isCalibratedAsFullBody && !BodySystem.isCalibrating) BodySystem.TrackingPositionWeight = 0f; foreach(var l_link in m_boneLinks) l_link.Item1.CopyGlobal(l_link.Item2); } + + if(m_avatarReady && !m_enabled && (m_vrIK != null)) + { + foreach(var l_link in m_boneLinks) + l_link.Item2.CopyGlobal(l_link.Item1); + } } // Game events @@ -285,19 +291,19 @@ namespace ml_prm internal void OnSeatSitDown(CVRSeat p_seat) { - if(m_enabled && m_avatarReady && !p_seat.occupied) + if(m_avatarReady && m_enabled && !p_seat.occupied) SwitchRagdoll(); } internal void OnStartCalibration() { - if(m_enabled && m_avatarReady) + if(m_avatarReady && m_enabled) SwitchRagdoll(); } internal void OnWorldSpawn() { - if(m_enabled && m_avatarReady) + if(m_avatarReady && m_enabled) SwitchRagdoll(); OnGravityChange(Settings.Gravity); @@ -306,7 +312,13 @@ namespace ml_prm internal void OnCombatDown() { - if(!m_enabled && m_avatarReady && Settings.CombatReaction) + if(m_avatarReady && !m_enabled && Settings.CombatReaction) + SwitchRagdoll(); + } + + internal void OnToggleFlight() + { + if(m_avatarReady && m_enabled && MovementSystem.Instance.flying) SwitchRagdoll(); } @@ -354,8 +366,9 @@ namespace ml_prm { if(m_avatarReady) { + bool l_gravity = (!Utils.IsWorldSafe() || p_state); foreach(Rigidbody l_body in m_rigidBodies) - l_body.useGravity = (!Utils.IsWorldSafe() || p_state); + l_body.useGravity = l_gravity; } } void OnPhysicsMaterialChange(bool p_state) @@ -400,6 +413,9 @@ namespace ml_prm PlayerSetup.Instance.transform.rotation = Quaternion.Euler(0f, l_rot.eulerAngles.y, 0f); } + if(MovementSystem.Instance.flying) + MovementSystem.Instance.ChangeFlight(false); + MovementSystem.Instance.SetImmobilized(true); PlayerSetup.Instance.animatorManager.SetAnimatorParameterTrigger("CancelEmote"); m_ragdolledParameter.SetValue(true); @@ -410,8 +426,11 @@ namespace ml_prm m_reachedGround = false; // Force player to unragdoll and reach ground first // Copy before set to non-kinematic to reduce stacked forces - foreach(var l_link in m_boneLinks) - l_link.Item2.CopyGlobal(l_link.Item1); + if(m_vrIK == null) + { + foreach(var l_link in m_boneLinks) + l_link.Item2.CopyGlobal(l_link.Item1); + } foreach(Rigidbody l_body in m_rigidBodies) l_body.isKinematic = false; @@ -451,7 +470,8 @@ namespace ml_prm l_body.isKinematic = true; PlayerSetup.Instance.transform.position = m_puppetReferences.hips.position; - PlayerSetup.Instance.transform.position -= (PlayerSetup.Instance.transform.rotation * PlayerSetup.Instance._avatar.transform.localPosition); + if(m_inVr) + PlayerSetup.Instance.transform.position -= (PlayerSetup.Instance.transform.rotation * PlayerSetup.Instance._avatar.transform.localPosition); foreach(Collider l_collider in m_colliders) l_collider.enabled = false; @@ -466,7 +486,7 @@ namespace ml_prm } } - public bool IsRagdolled() => (m_enabled && m_avatarReady); + public bool IsRagdolled() => (m_avatarReady && m_enabled); static Transform CloneTransform(Transform p_source, Transform p_parent, string p_name) { From 9839169cc176f39dadd9425fe8e40523ea5f7708 Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 18 Apr 2023 13:50:08 +0300 Subject: [PATCH 43/63] Revert IK pose consideration --- ml_prm/RagdollController.cs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 52231d3..29e378c 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -145,20 +145,14 @@ namespace ml_prm void LateUpdate() { - if(m_avatarReady && m_enabled) + if(m_avatarReady && m_enabled && !BodySystem.isCalibrating) { - if(BodySystem.isCalibratedAsFullBody && !BodySystem.isCalibrating) + if(BodySystem.isCalibratedAsFullBody) BodySystem.TrackingPositionWeight = 0f; foreach(var l_link in m_boneLinks) l_link.Item1.CopyGlobal(l_link.Item2); } - - if(m_avatarReady && !m_enabled && (m_vrIK != null)) - { - foreach(var l_link in m_boneLinks) - l_link.Item2.CopyGlobal(l_link.Item1); - } } // Game events @@ -426,11 +420,8 @@ namespace ml_prm m_reachedGround = false; // Force player to unragdoll and reach ground first // Copy before set to non-kinematic to reduce stacked forces - if(m_vrIK == null) - { - foreach(var l_link in m_boneLinks) - l_link.Item2.CopyGlobal(l_link.Item1); - } + foreach(var l_link in m_boneLinks) + l_link.Item2.CopyGlobal(l_link.Item1); foreach(Rigidbody l_body in m_rigidBodies) l_body.isKinematic = false; From 427c346ba2518d36d06b283e3749326e870297c8 Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 18 Apr 2023 20:32:28 +0300 Subject: [PATCH 44/63] Drag limitation --- ml_prm/README.md | 1 + ml_prm/RagdollController.cs | 4 +++- ml_prm/Settings.cs | 33 ++++++++++++++++++++++----------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/ml_prm/README.md b/ml_prm/README.md index c81013e..6cea7e2 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -28,6 +28,7 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * Note: Limited according to world's fly multiplier. * Note: Forcibly set to `1.0` in worlds that don't allow flight. * **Movement drag:** movement resistance; `2.0` by default. + * Note: Forcibly set to `0.0` in worlds that don't allow flight. * **Angular movement drag:** angular movement resistance; `2.0` by default. * **Recover delay:** time delay for enabled `Auto recover` in seconds; `3.0` by default. * **Reset settings:** resets mod settings to default. diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 29e378c..f5037dc 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -302,6 +302,7 @@ namespace ml_prm OnGravityChange(Settings.Gravity); OnPhysicsMaterialChange(true); + OnMovementDragChange(Settings.MovementDrag); } internal void OnCombatDown() @@ -336,9 +337,10 @@ namespace ml_prm { if(m_avatarReady) { + float l_drag = (Utils.IsWorldSafe() ? p_value : 0f); foreach(Rigidbody l_body in m_rigidBodies) { - l_body.drag = p_value; + l_body.drag = l_drag; if(m_enabled) l_body.WakeUp(); } diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index 86f05e6..502af1d 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -190,43 +190,50 @@ namespace ml_prm { PointersReaction = p_state; PointersReactionChange?.Invoke(p_state); - } break; + } + break; case ModSetting.IgnoreLocal: { IgnoreLocal = p_state; IgnoreLocalChange?.Invoke(p_state); - } break; + } + break; case ModSetting.CombatReaction: { CombatReaction = p_state; CombatReactionChange?.Invoke(p_state); - } break; + } + break; case ModSetting.AutoRecover: { AutoRecover = p_state; AutoRecoverChange?.Invoke(p_state); - } break; + } + break; case ModSetting.Slipperiness: { Slipperiness = p_state; SlipperinessChange?.Invoke(p_state); - } break; + } + break; case ModSetting.Bounciness: { Bounciness = p_state; BouncinessChange?.Invoke(p_state); - } break; + } + break; case ModSetting.ViewVelocity: { ViewVelocity = p_state; ViewVelocityChange?.Invoke(p_state); - } break; + } + break; } ms_entries[(int)p_setting].BoxedValue = p_state; @@ -242,25 +249,29 @@ namespace ml_prm { VelocityMultiplier = p_value; VelocityMultiplierChange?.Invoke(p_value); - } break; + } + break; case ModSetting.MovementDrag: { MovementDrag = p_value; MovementDragChange?.Invoke(p_value); - } break; + } + break; case ModSetting.AngularDrag: { AngularDrag = p_value; AngularDragChange?.Invoke(p_value); - } break; + } + break; case ModSetting.RecoverDelay: { RecoverDelay = p_value; RecoverDelayChange?.Invoke(p_value); - } break; + } + break; } ms_entries[(int)p_setting].BoxedValue = p_value; From 1ef839af3f80566c89f74d7a7a980e3ffbeae85c Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 18 Apr 2023 23:25:35 +0300 Subject: [PATCH 45/63] Restricted drag fix --- ml_prm/README.md | 2 +- ml_prm/RagdollController.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ml_prm/README.md b/ml_prm/README.md index 6cea7e2..ba900d3 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -28,7 +28,7 @@ Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUI * Note: Limited according to world's fly multiplier. * Note: Forcibly set to `1.0` in worlds that don't allow flight. * **Movement drag:** movement resistance; `2.0` by default. - * Note: Forcibly set to `0.0` in worlds that don't allow flight. + * Note: Forcibly set to `1.0` in worlds that don't allow flight. * **Angular movement drag:** angular movement resistance; `2.0` by default. * **Recover delay:** time delay for enabled `Auto recover` in seconds; `3.0` by default. * **Reset settings:** resets mod settings to default. diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index f5037dc..35f56cd 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -240,7 +240,7 @@ namespace ml_prm m_rigidBodies.Add(l_body); l_body.isKinematic = true; l_body.angularDrag = Settings.AngularDrag; - l_body.drag = Settings.MovementDrag; + l_body.drag = (Utils.IsWorldSafe() ? Settings.MovementDrag : 1f); l_body.useGravity = (!Utils.IsWorldSafe() || Settings.Gravity); l_body.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; } @@ -337,7 +337,7 @@ namespace ml_prm { if(m_avatarReady) { - float l_drag = (Utils.IsWorldSafe() ? p_value : 0f); + float l_drag = (Utils.IsWorldSafe() ? p_value : 1f); foreach(Rigidbody l_body in m_rigidBodies) { l_body.drag = l_drag; From ac5820d1887be25d0c07b18d78e1603487b26928 Mon Sep 17 00:00:00 2001 From: SDraw Date: Wed, 19 Apr 2023 15:00:37 +0300 Subject: [PATCH 46/63] Minor changes and fixes --- ml_amt/MotionTweaker.cs | 10 +++------- ml_amt/Utils.cs | 23 ++++++++++++++++------- ml_dht/HeadTracked.cs | 5 +---- ml_dht/Utils.cs | 8 +++++++- ml_lme/LeapInput.cs | 1 - ml_prm/Settings.cs | 2 +- 6 files changed, 28 insertions(+), 21 deletions(-) diff --git a/ml_amt/MotionTweaker.cs b/ml_amt/MotionTweaker.cs index f205fd2..a02bf7c 100644 --- a/ml_amt/MotionTweaker.cs +++ b/ml_amt/MotionTweaker.cs @@ -5,7 +5,6 @@ using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.MovementSystem; using RootMotion.FinalIK; using System.Collections.Generic; -using System.Reflection; using UnityEngine; namespace ml_amt @@ -14,9 +13,6 @@ namespace ml_amt class MotionTweaker : MonoBehaviour { static readonly Vector4 ms_pointVector = new Vector4(0f, 0f, 0f, 1f); - static readonly FieldInfo ms_grounded = typeof(MovementSystem).GetField("_isGrounded", BindingFlags.NonPublic | BindingFlags.Instance); - static readonly FieldInfo ms_groundedRaw = typeof(MovementSystem).GetField("_isGroundedRaw", BindingFlags.NonPublic | BindingFlags.Instance); - static readonly FieldInfo ms_hasToes = typeof(IKSolverVR).GetField("hasToes", BindingFlags.NonPublic | BindingFlags.Instance); static readonly int ms_emoteHash = Animator.StringToHash("Emote"); enum PoseState @@ -121,8 +117,8 @@ namespace ml_amt { if(m_avatarReady) { - m_grounded = (bool)ms_grounded.GetValue(MovementSystem.Instance); - m_groundedRaw = (bool)ms_groundedRaw.GetValue(MovementSystem.Instance); + m_grounded = MovementSystem.Instance.IsGrounded(); + m_groundedRaw = MovementSystem.Instance.IsGroundedRaw(); m_moving = !Mathf.Approximately(MovementSystem.Instance.movementVector.magnitude, 0f); // Update upright @@ -230,7 +226,7 @@ namespace ml_amt m_locomotionOffset = m_vrIk.solver.locomotion.offset; m_massCenter = m_locomotionOffset; - if((bool)ms_hasToes.GetValue(m_vrIk.solver)) + if(m_vrIk.solver.HasToes()) { Transform l_foot = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftFoot); if(l_foot == null) diff --git a/ml_amt/Utils.cs b/ml_amt/Utils.cs index 02eaf7a..0024fe9 100644 --- a/ml_amt/Utils.cs +++ b/ml_amt/Utils.cs @@ -1,23 +1,32 @@ -using System.Reflection; +using ABI_RC.Systems.MovementSystem; +using RootMotion.FinalIK; +using System.Reflection; using UnityEngine; namespace ml_amt { static class Utils { - static MethodInfo ms_getSineKeyframes = typeof(RootMotion.FinalIK.IKSolverVR).GetMethod("GetSineKeyframes", BindingFlags.NonPublic | BindingFlags.Static); + static readonly FieldInfo ms_grounded = typeof(MovementSystem).GetField("_isGrounded", BindingFlags.NonPublic | BindingFlags.Instance); + static readonly FieldInfo ms_groundedRaw = typeof(MovementSystem).GetField("_isGroundedRaw", BindingFlags.NonPublic | BindingFlags.Instance); + static readonly FieldInfo ms_hasToes = typeof(IKSolverVR).GetField("hasToes", BindingFlags.NonPublic | BindingFlags.Instance); + static MethodInfo ms_getSineKeyframes = typeof(IKSolverVR).GetMethod("GetSineKeyframes", BindingFlags.NonPublic | BindingFlags.Static); public static bool IsInVR() => ((ABI_RC.Core.Savior.CheckVR.Instance != null) && ABI_RC.Core.Savior.CheckVR.Instance.hasVrDeviceLoaded); - // Extensions - public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) - { - return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.localScale : Vector3.one); - } + public static bool IsGrounded(this MovementSystem p_instance) => (bool)ms_grounded.GetValue(MovementSystem.Instance); + public static bool IsGroundedRaw(this MovementSystem p_instance) => (bool)ms_groundedRaw.GetValue(MovementSystem.Instance); + public static bool HasToes(this IKSolverVR p_instance) => (bool)ms_hasToes.GetValue(p_instance); public static Keyframe[] GetSineKeyframes(float p_mag) { return (Keyframe[])ms_getSineKeyframes.Invoke(null, new object[] { p_mag }); } + + // Engine extensions + public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) + { + return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.localScale : Vector3.one); + } } } diff --git a/ml_dht/HeadTracked.cs b/ml_dht/HeadTracked.cs index 00b116d..35c28a0 100644 --- a/ml_dht/HeadTracked.cs +++ b/ml_dht/HeadTracked.cs @@ -1,7 +1,6 @@ using ABI.CCK.Components; using ABI_RC.Core.Player; using RootMotion.FinalIK; -using System.Reflection; using UnityEngine; using ViveSR.anipal.Lip; @@ -10,8 +9,6 @@ namespace ml_dht [DisallowMultipleComponent] class HeadTracked : MonoBehaviour { - static FieldInfo ms_emotePlaying = typeof(PlayerSetup).GetField("_emotePlaying", BindingFlags.NonPublic | BindingFlags.Instance); - bool m_enabled = false; bool m_headTracking = true; bool m_blinking = true; @@ -74,7 +71,7 @@ namespace ml_dht { m_lastHeadRotation = Quaternion.Slerp(m_lastHeadRotation, m_avatarDescriptor.transform.rotation * (m_headRotation * m_bindRotation), m_smoothing); - if(!(bool)ms_emotePlaying.GetValue(PlayerSetup.Instance)) + if(!PlayerSetup.Instance.IsEmotePlaying()) m_headBone.rotation = m_lastHeadRotation; } } diff --git a/ml_dht/Utils.cs b/ml_dht/Utils.cs index 7d2651c..c830b43 100644 --- a/ml_dht/Utils.cs +++ b/ml_dht/Utils.cs @@ -1,9 +1,15 @@ -using UnityEngine; +using ABI_RC.Core.Player; +using System.Reflection; +using UnityEngine; namespace ml_dht { static class Utils { + static FieldInfo ms_emotePlaying = typeof(PlayerSetup).GetField("_emotePlaying", BindingFlags.NonPublic | BindingFlags.Instance); + + public static bool IsEmotePlaying(this PlayerSetup p_instance) => (bool)ms_emotePlaying.GetValue(p_instance); + public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) { return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.localScale : Vector3.one); diff --git a/ml_lme/LeapInput.cs b/ml_lme/LeapInput.cs index 585fbf1..9cf5545 100644 --- a/ml_lme/LeapInput.cs +++ b/ml_lme/LeapInput.cs @@ -3,7 +3,6 @@ using ABI_RC.Core.Player; using ABI_RC.Core.Savior; using ABI_RC.Systems.IK; using System.Collections; -using System.Reflection; using UnityEngine; namespace ml_lme diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index 502af1d..dcbed8b 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -100,7 +100,7 @@ namespace ml_prm Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; VelocityMultiplier = Mathf.Clamp((float)ms_entries[(int)ModSetting.VelocityMultiplier].BoxedValue, 1f, 50f); MovementDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); - AngularDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.MovementDrag].BoxedValue, 0f, 50f); + AngularDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.AngularDrag].BoxedValue, 0f, 50f); Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue; PointersReaction = (bool)ms_entries[(int)ModSetting.PointersReaction].BoxedValue; IgnoreLocal = (bool)ms_entries[(int)ModSetting.IgnoreLocal].BoxedValue; From 7ef112d02c33a33d1190972e8324e30657a3a00a Mon Sep 17 00:00:00 2001 From: SDraw Date: Fri, 21 Apr 2023 14:42:44 +0000 Subject: [PATCH 47/63] Update README.md --- README.md | 10 +++++----- ml_amt/README.md | 8 ++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 894a20f..d266da0 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ Merged set of MelonLoader mods for ChilloutVR. | Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes | |-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------| | Avatar Change Info | ml_aci | 1.0.3 | Retired | Retired | Superseded by `Extended Game Notifications` -| Avatar Motion Tweaker | ml_amt | 1.2.6 | Yes, update review | Working | -| Desktop Head Tracking | ml_dht | 1.1.3 | Yes, update review | Working | +| Avatar Motion Tweaker | ml_amt | 1.2.6 | Yes | Working | +| Desktop Head Tracking | ml_dht | 1.1.3 | Yes | Working | | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | | Extended Game Notifications | ml_egn | 1.0.2 | Yes | Working | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update -| Leap Motion Extension | ml_lme | 1.3.4 | Yes, update review | Working | -| Pickup Arm Movement | ml_pam | 1.0.3 | Yes, update review| Working | -| Player Ragdoll Mod | ml_prm | 1.0.1 | Yes, update review | Working | +| Leap Motion Extension | ml_lme | 1.3.4 | Yes | Working | +| Pickup Arm Movement | ml_pam | 1.0.3 | Yes | Working | +| Player Ragdoll Mod | ml_prm | 1.0.1 | Yes | Working | | Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` diff --git a/ml_amt/README.md b/ml_amt/README.md index 86c02a4..e9a2eee 100644 --- a/ml_amt/README.md +++ b/ml_amt/README.md @@ -31,7 +31,7 @@ Available mod's settings in `Settings - IK - Avatar Motion Tweaker`: * **Scaled locomotion steps:** scales VRIK locomotion steps according to avatar height and scale; default value - `true`. * **Alternative avatar collider scale:** applies slightly different approach to avatar collider size change; default value - `true`. * **Fix animation overrides (chairs, etc.):** fixes animations overriding for avatars with AAS; default value - `true`. - * Note: This options is made to address [broken animator in chairs and combat worlds issue](https://feedback.abinteractive.net/p/gestures-getting-stuck-locally-upon-entering-vehicles-chairs). + * Note: This option is made to address [broken animator in chairs and combat worlds issue](https://feedback.abinteractive.net/p/gestures-getting-stuck-locally-upon-entering-vehicles-chairs). Available additional parameters for AAS animator: * **`Upright`:** defines linear coefficient between current viewpoint height and avatar's viewpoint height; float, range - [0.0, 1.0]. @@ -44,4 +44,8 @@ Available additional parameters for AAS animator: * Note: Can be set as local-only (not synced) if starts with `#` character. Additional mod's behaviour: -* Overrides FBT behaviour in 4PT mode (head, hands, hips). Be sure to disable legs and knees tracking in `Settings - IK tab`. +* Overrides and fixes IK behaviour in 4PT mode (head, hands, hips). Be sure to disable legs and knees tracking in `Settings - IK tab`. + +https://user-images.githubusercontent.com/4295751/233663668-adf5eaa6-8195-4fd2-90d5-78d61fe3fe58.mp4 + +https://user-images.githubusercontent.com/4295751/233663726-80a05323-aed2-41fb-9b00-7d5024ebf247.mp4 From 0440baa84fdae7586ea7565e122bde2078567024 Mon Sep 17 00:00:00 2001 From: SDraw Date: Mon, 24 Apr 2023 22:18:30 +0300 Subject: [PATCH 48/63] Fingers values reset Hips transform restore after pose modification --- ml_lme/LeapInput.cs | 62 +++++++++++++++++++++++++++++++ ml_lme/LeapTracked.cs | 13 +++++++ ml_lme/Properties/AssemblyInfo.cs | 6 +-- ml_pam/ArmMover.cs | 15 ++++++++ ml_pam/Properties/AssemblyInfo.cs | 6 +-- 5 files changed, 96 insertions(+), 6 deletions(-) diff --git a/ml_lme/LeapInput.cs b/ml_lme/LeapInput.cs index 9cf5545..03b3762 100644 --- a/ml_lme/LeapInput.cs +++ b/ml_lme/LeapInput.cs @@ -15,6 +15,8 @@ namespace ml_lme bool m_inVR = false; bool m_gripToGrab = true; + bool m_handVisibleLeft = false; + bool m_handVisibleRight = false; ControllerRay m_handRayLeft = null; ControllerRay m_handRayRight = null; LineRenderer m_lineLeft = null; @@ -121,10 +123,32 @@ namespace ml_lme if(Settings.Enabled) { if(l_data.m_leftHand.m_present) + { SetFingersInput(l_data.m_leftHand, true); + m_handVisibleLeft = true; + } + else + { + if(m_handVisibleLeft) + { + ResetFingers(true); + m_handVisibleLeft = false; + } + } if(l_data.m_rightHand.m_present) + { SetFingersInput(l_data.m_rightHand, false); + m_handVisibleRight = true; + } + else + { + if(m_handVisibleRight) + { + ResetFingers(false); + m_handVisibleRight = false; + } + } if(m_inVR) { @@ -209,6 +233,8 @@ namespace ml_lme { OnInputChange(p_state && Settings.Input); UpdateFingerTracking(); + m_handVisibleLeft &= p_state; + m_handVisibleRight &= p_state; } void OnInputChange(bool p_state) @@ -251,6 +277,12 @@ namespace ml_lme { m_inputManager.individualFingerTracking = (Settings.Enabled || (m_inVR && Utils.AreKnucklesInUse() && !m_steamVrModule.GetIndexGestureToggle())); IKSystem.Instance.FingerSystem.controlActive = m_inputManager.individualFingerTracking; + + if(!Settings.Enabled) + { + ResetFingers(true); + ResetFingers(false); + } } void SetFingersInput(GestureMatcher.HandData p_hand, bool p_left) @@ -283,6 +315,36 @@ namespace ml_lme } } + void ResetFingers(bool p_left) + { + if(p_left) + { + m_inputManager.fingerCurlLeftThumb = 0f; + m_inputManager.fingerCurlLeftIndex = 0f; + m_inputManager.fingerCurlLeftMiddle = 0f; + m_inputManager.fingerCurlLeftRing = 0f; + m_inputManager.fingerCurlLeftPinky = 0f; + IKSystem.Instance.FingerSystem.leftThumbCurl = 0f; + IKSystem.Instance.FingerSystem.leftIndexCurl = 0f; + IKSystem.Instance.FingerSystem.leftMiddleCurl = 0f; + IKSystem.Instance.FingerSystem.leftRingCurl = 0f; + IKSystem.Instance.FingerSystem.leftPinkyCurl = 0f; + } + else + { + m_inputManager.fingerCurlRightThumb = 0f; + m_inputManager.fingerCurlRightIndex = 0f; + m_inputManager.fingerCurlRightMiddle = 0f; + m_inputManager.fingerCurlRightRing = 0f; + m_inputManager.fingerCurlRightPinky = 0f; + IKSystem.Instance.FingerSystem.rightThumbCurl = 0f; + IKSystem.Instance.FingerSystem.rightIndexCurl = 0f; + IKSystem.Instance.FingerSystem.rightMiddleCurl = 0f; + IKSystem.Instance.FingerSystem.rightRingCurl = 0f; + IKSystem.Instance.FingerSystem.rightPinkyCurl = 0f; + } + } + // Game settings void OnGameSettingBoolChange(string p_name, bool p_state) { diff --git a/ml_lme/LeapTracked.cs b/ml_lme/LeapTracked.cs index 7c8cfea..21ce9cb 100644 --- a/ml_lme/LeapTracked.cs +++ b/ml_lme/LeapTracked.cs @@ -232,7 +232,14 @@ namespace ml_lme if(PlayerSetup.Instance._animator.isHuman) { + Vector3 l_hipsPos = Vector3.zero; + Quaternion l_hipsRot = Quaternion.identity; m_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips); + if(m_hips != null) + { + l_hipsPos = m_hips.localPosition; + l_hipsRot = m_hips.localRotation; + } if(!m_inVR) { @@ -308,6 +315,12 @@ namespace ml_lme m_vrIK.solver.OnPreUpdate += this.OnIKPreUpdate; m_vrIK.solver.OnPostUpdate += this.OnIKPostUpdate; } + + if(m_hips != null) + { + m_hips.localPosition = l_hipsPos; + m_hips.localRotation = l_hipsRot; + } } } diff --git a/ml_lme/Properties/AssemblyInfo.cs b/ml_lme/Properties/AssemblyInfo.cs index 892c296..ed513a5 100644 --- a/ml_lme/Properties/AssemblyInfo.cs +++ b/ml_lme/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("LeapMotionExtension")] -[assembly: AssemblyVersion("1.3.4")] -[assembly: AssemblyFileVersion("1.3.4")] +[assembly: AssemblyVersion("1.3.5")] +[assembly: AssemblyFileVersion("1.3.5")] -[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.3.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.3.5", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] diff --git a/ml_pam/ArmMover.cs b/ml_pam/ArmMover.cs index c9940ae..68d0fe4 100644 --- a/ml_pam/ArmMover.cs +++ b/ml_pam/ArmMover.cs @@ -132,6 +132,15 @@ namespace ml_pam if(PlayerSetup.Instance._animator.isHuman) { + Vector3 l_hipsPos = Vector3.zero; + Quaternion l_hipsRot = Quaternion.identity; + Transform l_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips); + if(l_hips != null) + { + l_hipsPos = l_hips.localPosition; + l_hipsRot = l_hips.localRotation; + } + HumanPose l_currentPose = new HumanPose(); HumanPoseHandler l_poseHandler = null; @@ -190,6 +199,12 @@ namespace ml_pam l_poseHandler?.SetHumanPose(ref l_currentPose); l_poseHandler?.Dispose(); + + if(l_hips != null) + { + l_hips.localPosition = l_hipsPos; + l_hips.localRotation = l_hipsRot; + } } if(m_enabled) diff --git a/ml_pam/Properties/AssemblyInfo.cs b/ml_pam/Properties/AssemblyInfo.cs index e7bee17..2bdb677 100644 --- a/ml_pam/Properties/AssemblyInfo.cs +++ b/ml_pam/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("PickupArmMovement")] -[assembly: AssemblyVersion("1.0.3")] -[assembly: AssemblyFileVersion("1.0.3")] +[assembly: AssemblyVersion("1.0.4")] +[assembly: AssemblyFileVersion("1.0.4")] -[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.0.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.0.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPriority(1)] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] From 6d13ff18947e79f00881ada3bf052fc92503beb4 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 29 Apr 2023 03:18:45 +0300 Subject: [PATCH 49/63] Dedicated BTKUILib page Internal settings and UI rework Upcoming mod support --- README.md | 4 +- ml_amt/ModSupporter.cs | 17 +++ ml_amt/Properties/AssemblyInfo.cs | 8 +- ml_amt/ml_amt.csproj | 4 + ml_prm/Main.cs | 8 ++ ml_prm/ModUi.cs | 189 ++++++++++++++++++++++++++++++ ml_prm/Properties/AssemblyInfo.cs | 6 +- ml_prm/README.md | 2 +- ml_prm/RagdollController.cs | 10 +- ml_prm/Settings.cs | 170 ++++++--------------------- ml_prm/ml_prm.csproj | 5 +- ml_prm/resources/person.png | Bin 0 -> 5017 bytes 12 files changed, 269 insertions(+), 154 deletions(-) create mode 100644 ml_prm/ModUi.cs create mode 100644 ml_prm/resources/person.png diff --git a/README.md b/README.md index d266da0..d0fbc08 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ Merged set of MelonLoader mods for ChilloutVR. | Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes | |-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------| | Avatar Change Info | ml_aci | 1.0.3 | Retired | Retired | Superseded by `Extended Game Notifications` -| Avatar Motion Tweaker | ml_amt | 1.2.6 | Yes | Working | +| Avatar Motion Tweaker | ml_amt | 1.2.7 | Yes, update review | Working | | Desktop Head Tracking | ml_dht | 1.1.3 | Yes | Working | | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | | Extended Game Notifications | ml_egn | 1.0.2 | Yes | Working | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update | Leap Motion Extension | ml_lme | 1.3.4 | Yes | Working | | Pickup Arm Movement | ml_pam | 1.0.3 | Yes | Working | -| Player Ragdoll Mod | ml_prm | 1.0.1 | Yes | Working | +| Player Ragdoll Mod | ml_prm | 1.0.2 | Yes, update review | Working | | Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` diff --git a/ml_amt/ModSupporter.cs b/ml_amt/ModSupporter.cs index c5c2ed5..a453e86 100644 --- a/ml_amt/ModSupporter.cs +++ b/ml_amt/ModSupporter.cs @@ -6,11 +6,14 @@ namespace ml_amt static class ModSupporter { static bool ms_ragdollMod = false; + static bool ms_copycatMod = false; public static void Init() { if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "PlayerRagdollMod") != null) MelonLoader.MelonCoroutines.Start(WaitForRagdollInstance()); + if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "PlayerMovementCopycat") != null) + MelonLoader.MelonCoroutines.Start(WaitForCopycatInstance()); } // PlayerRagdollMod support @@ -22,11 +25,25 @@ namespace ml_amt ms_ragdollMod = true; } static bool IsRagdolled() => ml_prm.RagdollController.Instance.IsRagdolled(); + + // PlayerMovementCopycat support + static IEnumerator WaitForCopycatInstance() + { + while(ml_pmc.PoseCopycat.Instance == null) + yield return null; + + ms_copycatMod = true; + } + static bool IsCopycating() => ml_pmc.PoseCopycat.Instance.IsActive(); + public static bool SkipHipsOverride() { bool l_result = false; l_result |= (ms_ragdollMod && IsRagdolled()); + l_result |= (ms_copycatMod && IsCopycating()); return l_result; } + + } } diff --git a/ml_amt/Properties/AssemblyInfo.cs b/ml_amt/Properties/AssemblyInfo.cs index e187bdd..2a256a4 100644 --- a/ml_amt/Properties/AssemblyInfo.cs +++ b/ml_amt/Properties/AssemblyInfo.cs @@ -1,11 +1,11 @@ using System.Reflection; [assembly: AssemblyTitle("AvatarMotionTweaker")] -[assembly: AssemblyVersion("1.2.6")] -[assembly: AssemblyFileVersion("1.2.6")] +[assembly: AssemblyVersion("1.2.7")] +[assembly: AssemblyFileVersion("1.2.7")] -[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.2.6", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.2.7", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] -[assembly: MelonLoader.MelonOptionalDependencies("ml_prm")] +[assembly: MelonLoader.MelonOptionalDependencies("ml_prm", "ml_pmc")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] \ No newline at end of file diff --git a/ml_amt/ml_amt.csproj b/ml_amt/ml_amt.csproj index 17bb8f2..58d618a 100644 --- a/ml_amt/ml_amt.csproj +++ b/ml_amt/ml_amt.csproj @@ -54,6 +54,10 @@ False False + + D:\Games\Steam\steamapps\common\ChilloutVR\Mods\ml_pmc.dll + False + D:\Games\Steam\steamapps\common\ChilloutVR\Mods\ml_prm.dll False diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs index cb01968..0ab7447 100644 --- a/ml_prm/Main.cs +++ b/ml_prm/Main.cs @@ -24,6 +24,7 @@ namespace ml_prm ms_instance = this; Settings.Init(); + ModUi.Init(); HarmonyInstance.Patch( typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)), @@ -81,6 +82,13 @@ namespace ml_prm yield return null; m_localController = PlayerSetup.Instance.gameObject.AddComponent(); + ModUi.SwitchChange += this.OnSwitchActivation; + } + + void OnSwitchActivation() + { + if(m_localController != null) + m_localController.SwitchRagdoll(); } // Patches diff --git a/ml_prm/ModUi.cs b/ml_prm/ModUi.cs new file mode 100644 index 0000000..1c50179 --- /dev/null +++ b/ml_prm/ModUi.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace ml_prm +{ + static class ModUi + { + enum UiIndex + { + Hotkey = 0, + Gravity, + PointersReaction, + IgnoreLocal, + CombatReaction, + AutoRecover, + Slipperiness, + Bounciness, + ViewVelocity, + VelocityMultiplier, + MovementDrag, + AngularDrag, + RecoverDelay + } + + static public event Action SwitchChange; + + static List ms_uiElements = null; + + internal static void Init() + { + ms_uiElements = new List(); + + if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null) + CreateUi(); + } + + // Separated method, otherwise exception is thrown, funny CSharp and optional references, smh + static void CreateUi() + { + BTKUILib.QuickMenuAPI.PrepareIcon("PlayerRagdollMod", "PRM-Person", GetIconStream("person.png")); + + var l_modRoot = new BTKUILib.UIObjects.Page("PlayerRagdollMod", "MainPage", true, "PRM-Person"); + l_modRoot.MenuTitle = "Player Ragdoll Mod"; + l_modRoot.MenuSubtitle = "Become a ragdoll and change various settings for people amusement"; + + var l_modCategory = l_modRoot.AddCategory("Settings"); + + l_modCategory.AddButton("Switch ragdoll", "PRM-Person", "Switch between normal and ragdoll state").OnPress += () => SwitchChange?.Invoke(); + + ms_uiElements.Add(l_modCategory.AddToggle("Use hotkey", "Switch ragdoll mode with 'R' key", Settings.Hotkey)); + (ms_uiElements[(int)UiIndex.Hotkey] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Hotkey, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Use gravity", "Apply gravity to ragdoll", Settings.Gravity)); + (ms_uiElements[(int)UiIndex.Gravity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Gravity, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Pointers reaction", "React to trigger colliders with CVRPointer component of 'ragdoll' type", Settings.PointersReaction)); + (ms_uiElements[(int)UiIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.PointersReaction, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Ignore local pointers", "Ignore local avatar's CVRPointer components of 'ragdoll' type", Settings.IgnoreLocal)); + (ms_uiElements[(int)UiIndex.IgnoreLocal] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.IgnoreLocal, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Combat reaction", "Ragdoll upon combat system death", Settings.CombatReaction)); + (ms_uiElements[(int)UiIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.CombatReaction, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Auto recover", "Automatically unragdoll after set recover delay", Settings.AutoRecover)); + (ms_uiElements[(int)UiIndex.AutoRecover] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.AutoRecover, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Slipperiness", "Enables/disables friction of ragdoll", Settings.Slipperiness)); + (ms_uiElements[(int)UiIndex.Slipperiness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Slipperiness, state); + + ms_uiElements.Add(l_modCategory.AddToggle("Bounciness", "Enables/disables bounciness of ragdoll", Settings.Bounciness)); + (ms_uiElements[(int)UiIndex.Bounciness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Bounciness, state); + + ms_uiElements.Add(l_modCategory.AddToggle("View direction velocity", "Apply velocity to camera view direction", Settings.ViewVelocity)); + (ms_uiElements[(int)UiIndex.ViewVelocity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.ViewVelocity, state); + + ms_uiElements.Add(l_modRoot.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", Settings.VelocityMultiplier, 1f, 50f)); + (ms_uiElements[(int)UiIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.VelocityMultiplier, value); + + ms_uiElements.Add(l_modRoot.AddSlider("Movement drag", "Movement resistance", Settings.MovementDrag, 0f, 50f)); + (ms_uiElements[(int)UiIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.MovementDrag, value); + + ms_uiElements.Add(l_modRoot.AddSlider("Angular movement drag", "Rotation movement resistance", Settings.AngularDrag, 0f, 50f)); + (ms_uiElements[(int)UiIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.AngularDrag, value); + + ms_uiElements.Add(l_modRoot.AddSlider("Recover delay (seconds)", "Recover delay for automatic recover", Settings.RecoverDelay, 1f, 10f)); + (ms_uiElements[(int)UiIndex.RecoverDelay] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.RecoverDelay, value); + + l_modCategory.AddButton("Reset settings", "", "Reset mod settings to default").OnPress += Reset; + } + + static void OnToggleUpdate(UiIndex p_index, bool p_state, bool p_force = false) + { + switch(p_index) + { + case UiIndex.Hotkey: + Settings.SetSetting(Settings.ModSetting.Hotkey, p_state); + break; + + case UiIndex.Gravity: + Settings.SetSetting(Settings.ModSetting.Gravity, p_state); + break; + + case UiIndex.PointersReaction: + Settings.SetSetting(Settings.ModSetting.PointersReaction, p_state); + break; + + case UiIndex.IgnoreLocal: + Settings.SetSetting(Settings.ModSetting.IgnoreLocal, p_state); + break; + + case UiIndex.CombatReaction: + Settings.SetSetting(Settings.ModSetting.CombatReaction, p_state); + break; + + case UiIndex.AutoRecover: + Settings.SetSetting(Settings.ModSetting.AutoRecover, p_state); + break; + + case UiIndex.Slipperiness: + Settings.SetSetting(Settings.ModSetting.Slipperiness, p_state); + break; + + case UiIndex.Bounciness: + Settings.SetSetting(Settings.ModSetting.Bounciness, p_state); + break; + + case UiIndex.ViewVelocity: + Settings.SetSetting(Settings.ModSetting.ViewVelocity, p_state); + break; + } + + if(p_force) + (ms_uiElements[(int)p_index] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = p_state; + } + + static void OnSliderUpdate(UiIndex p_index, float p_value, bool p_force = false) + { + switch(p_index) + { + case UiIndex.VelocityMultiplier: + Settings.SetSetting(Settings.ModSetting.VelocityMultiplier, p_value); + break; + + case UiIndex.MovementDrag: + Settings.SetSetting(Settings.ModSetting.MovementDrag, p_value); + break; + + case UiIndex.AngularDrag: + Settings.SetSetting(Settings.ModSetting.AngularDrag, p_value); + break; + + case UiIndex.RecoverDelay: + Settings.SetSetting(Settings.ModSetting.RecoverDelay, p_value); + break; + } + + if(p_force) + (ms_uiElements[(int)p_index] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(p_value); + } + + static void Reset() + { + OnToggleUpdate(UiIndex.Hotkey, true, true); + OnToggleUpdate(UiIndex.Gravity, true, true); + OnToggleUpdate(UiIndex.PointersReaction, true, true); + OnToggleUpdate(UiIndex.IgnoreLocal, true, true); + OnToggleUpdate(UiIndex.CombatReaction, true, true); + OnToggleUpdate(UiIndex.AutoRecover, false, true); + OnToggleUpdate(UiIndex.Slipperiness, false, true); + OnToggleUpdate(UiIndex.Bounciness, false, true); + OnToggleUpdate(UiIndex.ViewVelocity, false, true); + OnSliderUpdate(UiIndex.VelocityMultiplier, 2f, true); + OnSliderUpdate(UiIndex.MovementDrag, 2f, true); + OnSliderUpdate(UiIndex.AngularDrag, 2f, true); + OnSliderUpdate(UiIndex.RecoverDelay, 3f, true); + } + + static Stream GetIconStream(string p_name) + { + Assembly l_assembly = Assembly.GetExecutingAssembly(); + string l_assemblyName = l_assembly.GetName().Name; + return l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + p_name); + } + } +} diff --git a/ml_prm/Properties/AssemblyInfo.cs b/ml_prm/Properties/AssemblyInfo.cs index dca7ef0..511e79b 100644 --- a/ml_prm/Properties/AssemblyInfo.cs +++ b/ml_prm/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("PlayerRagdollMod")] -[assembly: AssemblyVersion("1.0.1")] -[assembly: AssemblyFileVersion("1.0.1")] +[assembly: AssemblyVersion("1.0.2")] +[assembly: AssemblyFileVersion("1.0.2")] -[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.0.1", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.0.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPriority(2)] [assembly: MelonLoader.MelonOptionalDependencies("BTKUILib")] diff --git a/ml_prm/README.md b/ml_prm/README.md index ba900d3..df89e18 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -9,7 +9,7 @@ This mod turns player's avatar into ragdoll puppet. # Usage * Press `R` to turn into ragdoll and back. -Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUILib): +Optional mod's settings page with [BTKUILib](https://github.com/BTK-Development/BTKUILib): * **Switch ragdoll:** turns into ragdoll state and back, made for VR usage primarily. * **Use hotkey:** enables/disables ragdoll state switch with `R` key; `true` by default. * **Use gravity:** enables/disables gravity for ragdoll; `true` by default. diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 35f56cd..51cc3c0 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -76,7 +76,6 @@ namespace ml_prm m_customTrigger = MovementSystem.Instance.proxyCollider.gameObject.AddComponent(); - Settings.SwitchChange += this.SwitchRagdoll; Settings.MovementDragChange += this.OnMovementDragChange; Settings.AngularDragChange += this.OnAngularDragChange; Settings.GravityChange += this.OnGravityChange; @@ -92,7 +91,6 @@ namespace ml_prm m_customTrigger = null; } - Settings.SwitchChange -= this.SwitchRagdoll; Settings.MovementDragChange -= this.OnMovementDragChange; Settings.AngularDragChange -= this.OnAngularDragChange; Settings.GravityChange -= this.OnGravityChange; @@ -224,10 +222,6 @@ namespace ml_prm l_options.joints = RagdollCreator.JointType.Character; BipedRagdollCreator.Create(m_puppetReferences, l_options); - // And return back - m_puppetRoot.localPosition = Vector3.zero; - m_puppetRoot.localRotation = Quaternion.identity; - Transform[] l_puppetTransforms = m_puppetReferences.GetRagdollTransforms(); Transform[] l_avatarTransforms = l_avatarReferences.GetRagdollTransforms(); for(int i = 0; i < l_puppetTransforms.Length; i++) @@ -269,6 +263,10 @@ namespace ml_prm } } + // And return back + m_puppetRoot.localPosition = Vector3.zero; + m_puppetRoot.localRotation = Quaternion.identity; + m_vrIK = PlayerSetup.Instance._avatar.GetComponent(); if(m_vrIK != null) { diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index dcbed8b..5f6d824 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -7,7 +7,7 @@ namespace ml_prm { static class Settings { - enum ModSetting + public enum ModSetting { Hotkey = 0, VelocityMultiplier, @@ -24,25 +24,6 @@ namespace ml_prm ViewVelocity } - enum UiElementIndex - { - Hotkey = 0, - Gravity, - PointersReaction, - IgnoreLocal, - CombatReaction, - AutoRecover, - Slipperiness, - Bounciness, - ViewVelocity, - VelocityMultiplier, - MovementDrag, - AngularDrag, - RecoverDelay, - - Count - } - public static bool Hotkey { get; private set; } = true; public static float VelocityMultiplier { get; private set; } = 2f; public static float MovementDrag { get; private set; } = 2f; @@ -57,7 +38,6 @@ namespace ml_prm public static bool Bounciness { get; private set; } = false; public static bool ViewVelocity { get; private set; } = false; - static public event Action SwitchChange; static public event Action HotkeyChange; static public event Action VelocityMultiplierChange; static public event Action MovementDragChange; @@ -75,8 +55,6 @@ namespace ml_prm static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; - static List ms_uiElements = new List(); - internal static void Init() { ms_category = MelonLoader.MelonPreferences.CreateCategory("PRM", null, true); @@ -110,190 +88,108 @@ namespace ml_prm Slipperiness = (bool)ms_entries[(int)ModSetting.Slipperiness].BoxedValue; Bounciness = (bool)ms_entries[(int)ModSetting.Bounciness].BoxedValue; ViewVelocity = (bool)ms_entries[(int)ModSetting.ViewVelocity].BoxedValue; - - if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null) - { - CreateBtkUi(); - } } - static void CreateBtkUi() + public static void SetSetting(ModSetting p_settings, object p_value) { - var l_categoryMain = BTKUILib.QuickMenuAPI.MiscTabPage.AddCategory("PlayerRagdollMod"); - var l_page = l_categoryMain.AddPage("Player Ragdoll Settings", "", "PlayerRagdollMod settings", "PlayerRagdollMod"); - l_page.MenuTitle = "Ragdoll settings"; - var l_categoryMod = l_page.AddCategory("Settings"); - - l_categoryMod.AddButton("Switch ragdoll", "", "Switch between normal and ragdoll state").OnPress += () => SwitchChange?.Invoke(); - - ms_uiElements.Add(l_categoryMod.AddToggle("Use hotkey", "Switch ragdoll mode with 'R' key", Hotkey)); - (ms_uiElements[(int)UiElementIndex.Hotkey] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Hotkey, state); - - ms_uiElements.Add(l_categoryMod.AddToggle("Use gravity", "Apply gravity to ragdoll", Gravity)); - (ms_uiElements[(int)UiElementIndex.Gravity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Gravity, state); - - ms_uiElements.Add(l_categoryMod.AddToggle("Pointers reaction", "React to trigger colliders with CVRPointer component of 'ragdoll' type", PointersReaction)); - (ms_uiElements[(int)UiElementIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.PointersReaction, state); - - ms_uiElements.Add(l_categoryMod.AddToggle("Ignore local pointers", "Ignore local avatar's CVRPointer components of 'ragdoll' type", IgnoreLocal)); - (ms_uiElements[(int)UiElementIndex.IgnoreLocal] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.IgnoreLocal, state); - - ms_uiElements.Add(l_categoryMod.AddToggle("Combat reaction", "Ragdoll upon combat system death", CombatReaction)); - (ms_uiElements[(int)UiElementIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.CombatReaction, state); - - ms_uiElements.Add(l_categoryMod.AddToggle("Auto recover", "Automatically unragdoll after set recover delay", AutoRecover)); - (ms_uiElements[(int)UiElementIndex.AutoRecover] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.AutoRecover, state); - - ms_uiElements.Add(l_categoryMod.AddToggle("Slipperiness", "Enables/disables friction of ragdoll", Slipperiness)); - (ms_uiElements[(int)UiElementIndex.Slipperiness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Slipperiness, state); - - ms_uiElements.Add(l_categoryMod.AddToggle("Bounciness", "Enables/disables bounciness of ragdoll", Bounciness)); - (ms_uiElements[(int)UiElementIndex.Bounciness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Bounciness, state); - - ms_uiElements.Add(l_categoryMod.AddToggle("View direction velocity", "Apply velocity to camera view direction", ViewVelocity)); - (ms_uiElements[(int)UiElementIndex.ViewVelocity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.ViewVelocity, state); - - ms_uiElements.Add(l_page.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", VelocityMultiplier, 1f, 50f)); - (ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(ModSetting.VelocityMultiplier, value); - - ms_uiElements.Add(l_page.AddSlider("Movement drag", "Movement resistance", MovementDrag, 0f, 50f)); - (ms_uiElements[(int)UiElementIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(ModSetting.MovementDrag, value); - - ms_uiElements.Add(l_page.AddSlider("Angular movement drag", "Rotation movement resistance", AngularDrag, 0f, 50f)); - (ms_uiElements[(int)UiElementIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(ModSetting.AngularDrag, value); - - ms_uiElements.Add(l_page.AddSlider("Recover delay (seconds)", "Recover delay for automatic recover", RecoverDelay, 1f, 10f)); - (ms_uiElements[(int)UiElementIndex.RecoverDelay] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(ModSetting.RecoverDelay, value); - - l_categoryMod.AddButton("Reset settings", "", "Reset mod settings to default").OnPress += Reset; - } - - static void OnToggleUpdate(ModSetting p_setting, bool p_state, UiElementIndex p_uiIndex = UiElementIndex.Count) - { - switch(p_setting) + switch(p_settings) { + // Booleans case ModSetting.Hotkey: { - Hotkey = p_state; - HotkeyChange?.Invoke(p_state); + Hotkey = (bool)p_value; + HotkeyChange?.Invoke((bool)p_value); } break; case ModSetting.Gravity: { - Gravity = p_state; - GravityChange?.Invoke(p_state); + Gravity = (bool)p_value; + GravityChange?.Invoke((bool)p_value); } break; case ModSetting.PointersReaction: { - PointersReaction = p_state; - PointersReactionChange?.Invoke(p_state); + PointersReaction = (bool)p_value; + PointersReactionChange?.Invoke((bool)p_value); } break; case ModSetting.IgnoreLocal: { - IgnoreLocal = p_state; - IgnoreLocalChange?.Invoke(p_state); + IgnoreLocal = (bool)p_value; + IgnoreLocalChange?.Invoke((bool)p_value); } break; case ModSetting.CombatReaction: { - CombatReaction = p_state; - CombatReactionChange?.Invoke(p_state); + CombatReaction = (bool)p_value; + CombatReactionChange?.Invoke((bool)p_value); } break; case ModSetting.AutoRecover: { - AutoRecover = p_state; - AutoRecoverChange?.Invoke(p_state); + AutoRecover = (bool)p_value; + AutoRecoverChange?.Invoke((bool)p_value); } break; case ModSetting.Slipperiness: { - Slipperiness = p_state; - SlipperinessChange?.Invoke(p_state); + Slipperiness = (bool)p_value; + SlipperinessChange?.Invoke((bool)p_value); } break; case ModSetting.Bounciness: { - Bounciness = p_state; - BouncinessChange?.Invoke(p_state); + Bounciness = (bool)p_value; + BouncinessChange?.Invoke((bool)p_value); } break; case ModSetting.ViewVelocity: { - ViewVelocity = p_state; - ViewVelocityChange?.Invoke(p_state); + ViewVelocity = (bool)p_value; + ViewVelocityChange?.Invoke((bool)p_value); } break; - } - ms_entries[(int)p_setting].BoxedValue = p_state; - if(p_uiIndex != UiElementIndex.Count) - (ms_uiElements[(int)p_uiIndex] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = p_state; - } - - static void OnSliderUpdate(ModSetting p_setting, float p_value, UiElementIndex p_uiIndex = UiElementIndex.Count) - { - switch(p_setting) - { + // Floats case ModSetting.VelocityMultiplier: { - VelocityMultiplier = p_value; - VelocityMultiplierChange?.Invoke(p_value); + VelocityMultiplier = (float)p_value; + VelocityMultiplierChange?.Invoke((float)p_value); } break; case ModSetting.MovementDrag: { - MovementDrag = p_value; - MovementDragChange?.Invoke(p_value); + MovementDrag = (float)p_value; + MovementDragChange?.Invoke((float)p_value); } break; case ModSetting.AngularDrag: { - AngularDrag = p_value; - AngularDragChange?.Invoke(p_value); + AngularDrag = (float)p_value; + AngularDragChange?.Invoke((float)p_value); } break; case ModSetting.RecoverDelay: { - RecoverDelay = p_value; - RecoverDelayChange?.Invoke(p_value); + RecoverDelay = (float)p_value; + RecoverDelayChange?.Invoke((float)p_value); } break; } - ms_entries[(int)p_setting].BoxedValue = p_value; - if(p_uiIndex != UiElementIndex.Count) - (ms_uiElements[(int)p_uiIndex] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(p_value); - } - - static void Reset() - { - OnToggleUpdate(ModSetting.Hotkey, true, UiElementIndex.Hotkey); - OnToggleUpdate(ModSetting.Gravity, true, UiElementIndex.Gravity); - OnToggleUpdate(ModSetting.PointersReaction, true, UiElementIndex.PointersReaction); - OnToggleUpdate(ModSetting.IgnoreLocal, true, UiElementIndex.IgnoreLocal); - OnToggleUpdate(ModSetting.CombatReaction, true, UiElementIndex.CombatReaction); - OnToggleUpdate(ModSetting.AutoRecover, false, UiElementIndex.AutoRecover); - OnToggleUpdate(ModSetting.Slipperiness, false, UiElementIndex.Slipperiness); - OnToggleUpdate(ModSetting.Bounciness, false, UiElementIndex.Bounciness); - OnToggleUpdate(ModSetting.ViewVelocity, false, UiElementIndex.ViewVelocity); - OnSliderUpdate(ModSetting.VelocityMultiplier, 2f, UiElementIndex.VelocityMultiplier); - OnSliderUpdate(ModSetting.MovementDrag, 2f, UiElementIndex.MovementDrag); - OnSliderUpdate(ModSetting.AngularDrag, 2f, UiElementIndex.AngularDrag); - OnSliderUpdate(ModSetting.RecoverDelay, 3f, UiElementIndex.RecoverDelay); + if(ms_entries != null) + ms_entries[(int)p_settings].BoxedValue = p_value; } } } diff --git a/ml_prm/ml_prm.csproj b/ml_prm/ml_prm.csproj index 33450f6..c7743ae 100644 --- a/ml_prm/ml_prm.csproj +++ b/ml_prm/ml_prm.csproj @@ -87,6 +87,7 @@ + @@ -135,7 +136,9 @@ - + + + copy /y "$(TargetPath)" "D:\Games\Steam\steamapps\common\ChilloutVR\Mods\" diff --git a/ml_prm/resources/person.png b/ml_prm/resources/person.png new file mode 100644 index 0000000000000000000000000000000000000000..578c19777cfb21a7109615266570ea456989ee7a GIT binary patch literal 5017 zcmbVQi8~a||DQeBC6;xDm8(P{iCkf^>t44?&Kx0<)?LYx`)ng;i*lxNB;<%yDo3tV zLhk!0S0Z-p&*%Fm{N{P)nVDx^@7MEwX6F5#c}={zsXjZaAS(cX-OvDM2>|4<3js*x z!^WOicI|L*!%J7!+{@J!04Z`HS=|_>%@eIP!<~HD^NC9}o+lBG)0R0AdHyekd!ZRE=kyEomRmkp;Rrm7?mJS`U+r?wKOllnvwC?P&jXnASIv#W(MJulL@ zkMW@9UOcr`O>H!kf0Un}HgdX#BlD;gZa`k@RU|$l?rXE#-};+ntGVtr7fNV1zTavm zi=7^?D#I`3Jj~(KIFbLMv5Ov@=X=}j$J((Zotc`2w>!F9a_K=A*7kpF8J#p|z%&1q zhuaVZ_j$rf%cD_GT)BHI%X6v`{C53x&y^I%jAeJ`FJ2+)_y58J#&uR6=G(Ya1`%;L zJGjTF2N1T7gOoWDsh6I@#Uo_t!}VwJGqCjs0QK&_3gMM9A_0K@Vu;hW4jK7HVR>*2 z&r768%y&R*~=`5K#i^E(DrSMa!_ZUf?~eDmh=?*Fe?Wd{ZaH1jp}D_4erVxAtGs;i zY$53nBn}j?f2>shqj?cGq0ouIfvKzBG^YX<2!eBdF+A6ucMF$Sa3X?7^umnOrys4$ zO-A_-p#Y6lk*SplKTbgYhsv2d$1qd)iz>K!hyyc2_ZI73Tni-6(bckefB~f0quTx7 z>6#=F(LH2=UY5Frn*{l)x2p-}x$}P2126f_kF!SwjIJqk zS-%i$hhSezlaBTUaQM3VlgUh~Ttdg>{~E_Y-o=C4G~2F{w4nR4;=mz;7Ma*04kbxR zfU}QJYcx{&;$FC0jDO#4jVad|wj`~E25HsL%LKoi3*=9@5LK?@WeEi6Ll06pBs|Zo zthHTnl5&NwcN<_zew|~86h1ZAL-<9O?re`q9{fct{nU1BbX#xbaz>BJZMwcILe7bXtQ z2z;eZT(};Z{L)vyE*p`2z1t2D+8P7Jt-{XU7+2|*~w3A>4LCqWF zY^8&>8{Lf@y222|1HXvUoj}(|6O67Ogfh9zfpE2DOqoFZla*YfeoP5&Nm{k0W-@8- z=}qL=)_dBnl}rOiZT3TgTw{%f)D3~wJMFJ}!xNopSomZp&pO8-Lzu))pyRdKYc-zV zi$E5fml(NAf5A`kNe;hh&EW@3v)tlgsk_)UszZq3XWIG zeX-fN6V|y<5m{MGrZ$;Cp=hlCg?zP&(jyf+GHI(*m%M22g^#wrvUXEAg)~12Efdql z&+q)WMWA@UndkVk+0}AP@)b%J5{hZ>6c!N(fQgtSWn6?ZTXWbaf&KfIK3THF zHytz+m{h}k=S!1}t@zj-MN_siyQ23)w(Dv&w80S{T34^6?YC#iwFa}I))Zuc0yIQt zb}Mh9+%!aX{RaHBUq-9&3lrXQL4#Q|6iqt20C%RnWezj|I}P`)o4Z2a3|X0MhFGla z97}#<01?Mbd3W#+qD6Ts&<$-f`|5_XFR?c63yKaF9#wB-p6TcdV6eP*$8I;H`HG|? z%%rIpG7Guf;+wVDAD$#J$u$u9g0_wS9YU&ecNwMAUnb%9Ww)g1EHM{LSddZJKK&o4JG~#) z@GYq@&wQBFjQ7>t_|MW*$f8_Fz93)nF!8bB`Hbx@Nct12%yjE1$1cIZR~R?;;kM(s zWzMv}_P(q2>7O8q&!|n=ZdQG-i1Dx6##BYDdbs|n2iZxDQ9Uo*i1uFi`_DF0Z@)^7$Y1?$IB;*r zPW)1qyrXij4o8#llrbx34a`};W8{JiF{rtQ)`%43~r>S$^l zct!Z#xa2UtQ@O$!MGa%c?yhOwX5AtVUG*y$5z2K_{q3kZjFATEEU?&KVKi5pzbiW01YF<`(#y*iu z`SorzzQxJ!x&gC!5Hr5y?)ke}YEZg8?3-r}!Q>TQ6^=78gWP*q^K+Y5%lr8H(eeTL zwc-@+nNJXSXS_h`Xo*64v`L9^T&w9z{vhg2mu%Q>N=G1S1e?kp4pr)OJ3{u5Ct^q( zD6F#WUjx&WIcH~0dy9L|h+1Rs zR1gCxn_1#Sphpj2ZxL|;SC18embBpN-X!Rnw%J(x98a#06@|KM2#GX+Y_`x#*8L;oKE}@*Cbd+Iimg~%f)QKRWr`;_{ro&ILFYdyPD^;>8?JHn2hS9h%Diez;$ZYOT z>+WS2*EepJDU|jD-`Gs_*F*7lJz`PVfn?DgTn}-hx?|*v7S0OAvMr4rpLx`n*g{tG z7+Nw^^ij&-2wNzy!mL&-yFF(~AB3!C)Yz-{W)BUee=5A*(9k{W^os>u0?zk6Ls<6; zzh3lF8{Lm_yY(gE1(L0c7xE)%`d5-blT~aJXKnWfmmGj7FzK=VebMZ9c#>hASnPa1 zZzjx(8G{|qT2o1Fc`qh8{E;okRgGZ&TNP;Jd0it<)JFS*Z%-qXE#A}U9T;o_hAJfP z>Tg}s<)x%4{otQb`!XJxeQE}2H9)#{39J$tzCAEc?47~&?f1gHrs77k`UhZQ%b$n&9 zpa0Q!eI@T#+ywIq9_-q=HMN6?+O9o}PFL{IU_$KE5_*>R!?*kf5F;+gW8bq+gJN$7 zQGQP3Y*xdrkEF6FY9D&*rP|$-P>_1eL_*X7R*ih*z~W^YZ%JzA4xMr5N#5JIGNQQ` zg)=i4v3IlFyZNZcWRr`Kw8&h7NQ1Vofq>1mzch=02Hv7xqjvT^l|&-}?#P2_FdYmk zyFb0b;J1HOTS&!mBNU2^+6S(GihxN)K~d+J|E5SsPQTaJ`^YVULZF{?=f`tmv)$KQ6dlZ zISexNt>!+ao zCz|~+_Ie^3a>t=@-H=&!{_PXw1}Rb|>X6E>rsF_`WPl+_C8taV^KDSf!5W5Y_pwLq z0ENL`@CTU-GWAh%+j-pGd_B`3$0P0WTuPzw+lAZu+or`{66-l!3Mumc%p#UV;eRxl z{FFHQ)07GZ7*lwVIUqaWe@q%!3!U90%AIbbB>{!@Z{<{tMaH@nsrl{4rRu37Q1Jz5 zxO>UaMLbzWyNC(+4c-6`^Up!%3(Sh%R5VG2WIDLeA1nFB%#AqD?*?C2g7$CkZ(-~$ zl~c3L7_m!-@fFRDcYFtd&jI^lNPYY&fq|F@I15R;sAz2rJsP$cTQMOrXIZ(#@S6vl z6$f@k%FNv??r}c1Kyr1qhY=iq*(F)m7UxS07#{TcN4iiP75|>l8%XmxB6K%lGQdW3 z8LbDGPp*)XU3dVMXO-z}*jx#I?YJJMMI9)ohFxYkYRbBva+j^!BA_ZNgc2a(g=KD} z&^#?k@|GlZV#fR3nMqSbV9Hb5_W}^TdE|z#cza?ALpdOw*~essS;1DEQfsffcWsTr znW|X8T!Yj4TM$S$JG|)$v|l`pa%y~PW&XiAN}LGMyekv)b~O=N8kc9)4kuCqd2HDx zXA9QfwcW>Ew4U`3e+rv1gJJymP@*JN0M2&!>Z^5jyFflez+*%1L$Mty0lt0mMc9al zD%?i`1b}>osgzwblMsxDi8293!X&p z-^R&wg$sf`YC&C*93C5LXyJx{-A~mi%fbeO(}2oQoV=M*u9^G&1QSXA3n}9T>v1Nq z&K>mk1eC<34=OG)`JUdCLjNa&H8>`hZ8ZKOsSvE_=K%AQcbKMuC})bl`NG|tN2&nn zAy=?y?QBdg&4wL9j-s4X?wa@&Zyi3ucYB78yzmz5F@%Gwc(At--*KJEy1uSs|9=vk z@BNXonHZxP1PO?ftn2E32!v=hL19t9fVJeD{DJ-tK8z>|(SO?PyeG}BKN4)Hk{ngd vXK#@!zE1Kd(yq8kNnH4U{Ez_f`T+xSRDSn Date: Tue, 2 May 2023 01:29:31 +0300 Subject: [PATCH 50/63] More stable ragdoll --- ml_prm/RagdollController.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 51cc3c0..3dfa59f 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -266,6 +266,7 @@ namespace ml_prm // And return back m_puppetRoot.localPosition = Vector3.zero; m_puppetRoot.localRotation = Quaternion.identity; + m_puppetRoot.gameObject.SetActive(false); m_vrIK = PlayerSetup.Instance._avatar.GetComponent(); if(m_vrIK != null) @@ -423,6 +424,8 @@ namespace ml_prm foreach(var l_link in m_boneLinks) l_link.Item2.CopyGlobal(l_link.Item1); + m_puppetRoot.gameObject.SetActive(true); + foreach(Rigidbody l_body in m_rigidBodies) l_body.isKinematic = false; @@ -457,6 +460,8 @@ namespace ml_prm if(BodySystem.isCalibratedAsFullBody) BodySystem.TrackingPositionWeight = 1f; + m_puppetRoot.gameObject.SetActive(false); + foreach(Rigidbody l_body in m_rigidBodies) l_body.isKinematic = true; From 699d7bdd5fc8032af37a505f979bfeab8139a0ef Mon Sep 17 00:00:00 2001 From: NotAKidoS <37721153+NotAKidOnSteam@users.noreply.github.com> Date: Mon, 1 May 2023 23:24:13 -0500 Subject: [PATCH 51/63] [PRM] Avatar Scaling Support --- ml_prm/Main.cs | 19 +++++++++++++++++++ ml_prm/RagdollController.cs | 17 +++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs index 0ab7447..24cb968 100644 --- a/ml_prm/Main.cs +++ b/ml_prm/Main.cs @@ -36,6 +36,11 @@ namespace ml_prm null, new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) ); + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod("SetupIKScaling", BindingFlags.NonPublic | BindingFlags.Instance), + null, + new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnSetupIKScaling_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); HarmonyInstance.Patch( typeof(CVRSeat).GetMethod(nameof(CVRSeat.SitDown)), new HarmonyLib.HarmonyMethod(typeof(PlayerRagdollMod).GetMethod(nameof(OnCVRSeatSitDown_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), @@ -120,6 +125,20 @@ namespace ml_prm } } + static void OnSetupIKScaling_Postfix(ref UnityEngine.Vector3 ___scaleDifference) => ms_instance?.OnSetupIKScaling(___scaleDifference.y); + void OnSetupIKScaling(float scaleDifference) + { + try + { + if (m_localController != null) + m_localController.OnAvatarScaling(1f + scaleDifference); + } + catch (Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + static void OnCVRSeatSitDown_Prefix(ref CVRSeat __instance) => ms_instance?.OnCVRSeatSitDown(__instance); void OnCVRSeatSitDown(CVRSeat p_seat) { diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 3dfa59f..7091657 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -28,6 +28,7 @@ namespace ml_prm Transform m_puppet = null; BipedRagdollReferences m_puppetReferences; readonly List> m_boneLinks = null; + readonly List> m_jointAnchors = null; bool m_avatarReady = false; Vector3 m_lastPosition = Vector3.zero; @@ -50,6 +51,7 @@ namespace ml_prm m_rigidBodies = new List(); m_colliders = new List(); m_boneLinks = new List>(); + m_jointAnchors = new List>(); m_physicsMaterial = new PhysicMaterial("Ragdoll"); m_physicsMaterial.dynamicFriction = 0.5f; @@ -172,8 +174,10 @@ namespace ml_prm m_colliders.Clear(); m_puppetReferences = new BipedRagdollReferences(); m_boneLinks.Clear(); + m_jointAnchors.Clear(); m_reachedGround = true; m_downTime = float.MinValue; + m_puppetRoot.localScale = Vector3.one; } internal void OnAvatarSetup() @@ -244,6 +248,7 @@ namespace ml_prm { l_joint.enablePreprocessing = false; l_joint.enableProjection = true; + m_jointAnchors.Add(System.Tuple.Create(l_joint, l_joint.connectedAnchor)); } Collider l_collider = l_puppetTransforms[i].GetComponent(); @@ -282,6 +287,18 @@ namespace ml_prm } } + internal void OnAvatarScaling(float scaleDifference) + { + if(m_avatarReady) + { + m_puppetRoot.localScale = Vector3.one * scaleDifference; + for(int i = 0; i < m_jointAnchors.Count; i++) + { + m_jointAnchors[i].Item1.connectedAnchor = m_jointAnchors[i].Item2 * scaleDifference; + } + } + } + internal void OnSeatSitDown(CVRSeat p_seat) { if(m_avatarReady && m_enabled && !p_seat.occupied) From 4e0ddaadd488d4bc9be1a276ced883e28bcb871d Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 2 May 2023 11:22:17 +0300 Subject: [PATCH 52/63] Jump recover option Preserve late update pose Upcoming mod support --- ml_lme/LeapInput.cs | 15 ++++++++----- ml_lme/ModSupporter.cs | 37 +++++++++++++++++++++++++++++++ ml_lme/ml_lme.csproj | 5 +++++ ml_prm/Main.cs | 4 ++-- ml_prm/ModUi.cs | 9 ++++++++ ml_prm/RagdollController.cs | 44 ++++++++++++++++++++++--------------- ml_prm/Settings.cs | 16 ++++++++++++-- 7 files changed, 102 insertions(+), 28 deletions(-) create mode 100644 ml_lme/ModSupporter.cs diff --git a/ml_lme/LeapInput.cs b/ml_lme/LeapInput.cs index 03b3762..fddc1fd 100644 --- a/ml_lme/LeapInput.cs +++ b/ml_lme/LeapInput.cs @@ -150,14 +150,17 @@ namespace ml_lme } } - if(m_inVR) + if(!ModSupporter.SkipFingersOverride()) { - m_inputManager.individualFingerTracking = !m_steamVrModule.GetIndexGestureToggle(); - m_inputManager.individualFingerTracking |= (l_data.m_leftHand.m_present || l_data.m_rightHand.m_present); + if(m_inVR) + { + m_inputManager.individualFingerTracking = !m_steamVrModule.GetIndexGestureToggle(); + m_inputManager.individualFingerTracking |= (l_data.m_leftHand.m_present || l_data.m_rightHand.m_present); + } + else + m_inputManager.individualFingerTracking = (l_data.m_leftHand.m_present || l_data.m_rightHand.m_present); + IKSystem.Instance.FingerSystem.controlActive = m_inputManager.individualFingerTracking; } - else - m_inputManager.individualFingerTracking = (l_data.m_leftHand.m_present || l_data.m_rightHand.m_present); - IKSystem.Instance.FingerSystem.controlActive = m_inputManager.individualFingerTracking; } m_handRayLeft.enabled = (l_data.m_leftHand.m_present && (!m_inVR || !Utils.IsLeftHandTracked() || !Settings.FingersOnly)); diff --git a/ml_lme/ModSupporter.cs b/ml_lme/ModSupporter.cs new file mode 100644 index 0000000..9747c8d --- /dev/null +++ b/ml_lme/ModSupporter.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ml_lme +{ + static class ModSupporter + { + static bool ms_copycatMod = false; + + public static void Init() + { + if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "PlayerMovementCopycat") != null) + MelonLoader.MelonCoroutines.Start(WaitForCopycatInstance()); + } + + // PlayerMovementCopycat support + static IEnumerator WaitForCopycatInstance() + { + while(ml_pmc.PoseCopycat.Instance == null) + yield return null; + + ms_copycatMod = true; + } + static bool IsCopycating() => (ml_pmc.PoseCopycat.Instance.IsActive() && ml_pmc.PoseCopycat.Instance.IsFingerTrackingActive()); + + public static bool SkipFingersOverride() + { + bool l_result = false; + l_result |= (ms_copycatMod && IsCopycating()); + return l_result; + } + } +} diff --git a/ml_lme/ml_lme.csproj b/ml_lme/ml_lme.csproj index 25fb3c8..62a7c85 100644 --- a/ml_lme/ml_lme.csproj +++ b/ml_lme/ml_lme.csproj @@ -55,6 +55,10 @@ C:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\MelonLoader.dll False + + D:\Games\Steam\steamapps\common\ChilloutVR\Mods\ml_pmc.dll + False + @@ -89,6 +93,7 @@ + diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs index 24cb968..d997fb6 100644 --- a/ml_prm/Main.cs +++ b/ml_prm/Main.cs @@ -126,12 +126,12 @@ namespace ml_prm } static void OnSetupIKScaling_Postfix(ref UnityEngine.Vector3 ___scaleDifference) => ms_instance?.OnSetupIKScaling(___scaleDifference.y); - void OnSetupIKScaling(float scaleDifference) + void OnSetupIKScaling(float p_scaleDifference) { try { if (m_localController != null) - m_localController.OnAvatarScaling(1f + scaleDifference); + m_localController.OnAvatarScaling(1f + p_scaleDifference); } catch (Exception e) { diff --git a/ml_prm/ModUi.cs b/ml_prm/ModUi.cs index 1c50179..2a77f31 100644 --- a/ml_prm/ModUi.cs +++ b/ml_prm/ModUi.cs @@ -19,6 +19,7 @@ namespace ml_prm Slipperiness, Bounciness, ViewVelocity, + JumpRecover, VelocityMultiplier, MovementDrag, AngularDrag, @@ -77,6 +78,9 @@ namespace ml_prm ms_uiElements.Add(l_modCategory.AddToggle("View direction velocity", "Apply velocity to camera view direction", Settings.ViewVelocity)); (ms_uiElements[(int)UiIndex.ViewVelocity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.ViewVelocity, state); + ms_uiElements.Add(l_modCategory.AddToggle("Jump recover", "Recover from ragdoll state by jumping", Settings.JumpRecover)); + (ms_uiElements[(int)UiIndex.JumpRecover] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.JumpRecover, state); + ms_uiElements.Add(l_modRoot.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", Settings.VelocityMultiplier, 1f, 50f)); (ms_uiElements[(int)UiIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.VelocityMultiplier, value); @@ -131,6 +135,10 @@ namespace ml_prm case UiIndex.ViewVelocity: Settings.SetSetting(Settings.ModSetting.ViewVelocity, p_state); break; + + case UiIndex.JumpRecover: + Settings.SetSetting(Settings.ModSetting.JumpRecover, p_state); + break; } if(p_force) @@ -173,6 +181,7 @@ namespace ml_prm OnToggleUpdate(UiIndex.Slipperiness, false, true); OnToggleUpdate(UiIndex.Bounciness, false, true); OnToggleUpdate(UiIndex.ViewVelocity, false, true); + OnToggleUpdate(UiIndex.JumpRecover, false, true); OnSliderUpdate(UiIndex.VelocityMultiplier, 2f, true); OnSliderUpdate(UiIndex.MovementDrag, 2f, true); OnSliderUpdate(UiIndex.AngularDrag, 2f, true); diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 7091657..d78601c 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -133,25 +133,39 @@ namespace ml_prm } } - if(Settings.Hotkey && Input.GetKeyDown(KeyCode.R) && !ViewManager.Instance.isGameMenuOpen()) - SwitchRagdoll(); - if((m_avatarRagdollToggle != null) && m_avatarRagdollToggle.isActiveAndEnabled && m_avatarRagdollToggle.shouldOverride && (m_enabled != m_avatarRagdollToggle.isOn)) SwitchRagdoll(); if((m_customTrigger != null) && m_customTrigger.GetStateWithReset() && m_avatarReady && !m_enabled && Settings.PointersReaction) SwitchRagdoll(); + + if(Settings.Hotkey && Input.GetKeyDown(KeyCode.R) && !ViewManager.Instance.isGameMenuOpen()) + SwitchRagdoll(); + + if(m_avatarReady && m_enabled && CVRInputManager.Instance.jump && Settings.JumpRecover) + SwitchRagdoll(); } void LateUpdate() { - if(m_avatarReady && m_enabled && !BodySystem.isCalibrating) + if(m_avatarReady) { - if(BodySystem.isCalibratedAsFullBody) - BodySystem.TrackingPositionWeight = 0f; + if(m_enabled) + { + if(!BodySystem.isCalibrating) + { + if(BodySystem.isCalibratedAsFullBody) + BodySystem.TrackingPositionWeight = 0f; - foreach(var l_link in m_boneLinks) - l_link.Item1.CopyGlobal(l_link.Item2); + foreach(var l_link in m_boneLinks) + l_link.Item1.CopyGlobal(l_link.Item2); + } + } + else + { + foreach(var l_link in m_boneLinks) + l_link.Item2.CopyGlobal(l_link.Item1); + } } } @@ -287,15 +301,13 @@ namespace ml_prm } } - internal void OnAvatarScaling(float scaleDifference) + internal void OnAvatarScaling(float p_scaleDifference) { if(m_avatarReady) { - m_puppetRoot.localScale = Vector3.one * scaleDifference; - for(int i = 0; i < m_jointAnchors.Count; i++) - { - m_jointAnchors[i].Item1.connectedAnchor = m_jointAnchors[i].Item2 * scaleDifference; - } + m_puppetRoot.localScale = Vector3.one * p_scaleDifference; + foreach(var l_pair in m_jointAnchors) + l_pair.Item1.connectedAnchor = l_pair.Item2 * p_scaleDifference; } } @@ -437,10 +449,6 @@ namespace ml_prm if(!Utils.IsWorldSafe()) m_reachedGround = false; // Force player to unragdoll and reach ground first - // Copy before set to non-kinematic to reduce stacked forces - foreach(var l_link in m_boneLinks) - l_link.Item2.CopyGlobal(l_link.Item1); - m_puppetRoot.gameObject.SetActive(true); foreach(Rigidbody l_body in m_rigidBodies) diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index 5f6d824..e5d92f7 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -21,7 +21,8 @@ namespace ml_prm RecoverDelay, Slipperiness, Bounciness, - ViewVelocity + ViewVelocity, + JumpRecover } public static bool Hotkey { get; private set; } = true; @@ -37,6 +38,7 @@ namespace ml_prm public static bool Slipperiness { get; private set; } = false; public static bool Bounciness { get; private set; } = false; public static bool ViewVelocity { get; private set; } = false; + public static bool JumpRecover { get; private set; } = false; static public event Action HotkeyChange; static public event Action VelocityMultiplierChange; @@ -51,6 +53,7 @@ namespace ml_prm static public event Action SlipperinessChange; static public event Action BouncinessChange; static public event Action ViewVelocityChange; + static public event Action JumpRecoverChange; static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; @@ -72,7 +75,8 @@ namespace ml_prm ms_category.CreateEntry(ModSetting.RecoverDelay.ToString(), RecoverDelay), ms_category.CreateEntry(ModSetting.Slipperiness.ToString(), Slipperiness), ms_category.CreateEntry(ModSetting.Bounciness.ToString(), Bounciness), - ms_category.CreateEntry(ModSetting.ViewVelocity.ToString(), ViewVelocity) + ms_category.CreateEntry(ModSetting.ViewVelocity.ToString(), ViewVelocity), + ms_category.CreateEntry(ModSetting.JumpRecover.ToString(), JumpRecover) }; Hotkey = (bool)ms_entries[(int)ModSetting.Hotkey].BoxedValue; @@ -88,6 +92,7 @@ namespace ml_prm Slipperiness = (bool)ms_entries[(int)ModSetting.Slipperiness].BoxedValue; Bounciness = (bool)ms_entries[(int)ModSetting.Bounciness].BoxedValue; ViewVelocity = (bool)ms_entries[(int)ModSetting.ViewVelocity].BoxedValue; + JumpRecover = (bool)ms_entries[(int)ModSetting.JumpRecover].BoxedValue; } public static void SetSetting(ModSetting p_settings, object p_value) @@ -158,6 +163,13 @@ namespace ml_prm } break; + case ModSetting.JumpRecover: + { + JumpRecover = (bool)p_value; + JumpRecoverChange?.Invoke((bool)p_value); + } + break; + // Floats case ModSetting.VelocityMultiplier: { From 61b7e599525e15f32e1c0d1c6be384494a66fcbe Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 2 May 2023 14:26:27 +0300 Subject: [PATCH 53/63] Version bump --- README.md | 8 ++++---- ml_lme/Properties/AssemblyInfo.cs | 7 ++++--- ml_prm/Properties/AssemblyInfo.cs | 6 +++--- ml_prm/README.md | 1 + 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d0fbc08..2b3f8e8 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ Merged set of MelonLoader mods for ChilloutVR. | Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes | |-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------| | Avatar Change Info | ml_aci | 1.0.3 | Retired | Retired | Superseded by `Extended Game Notifications` -| Avatar Motion Tweaker | ml_amt | 1.2.7 | Yes, update review | Working | +| Avatar Motion Tweaker | ml_amt | 1.2.7 | Yes | Working | | Desktop Head Tracking | ml_dht | 1.1.3 | Yes | Working | | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | | Extended Game Notifications | ml_egn | 1.0.2 | Yes | Working | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update -| Leap Motion Extension | ml_lme | 1.3.4 | Yes | Working | -| Pickup Arm Movement | ml_pam | 1.0.3 | Yes | Working | -| Player Ragdoll Mod | ml_prm | 1.0.2 | Yes, update review | Working | +| Leap Motion Extension | ml_lme | 1.3.6 | Yes, update review | Working | +| Pickup Arm Movement | ml_pam | 1.0.4 | Yes | Working | +| Player Ragdoll Mod | ml_prm | 1.0.3 | Yes, update review | Working | | Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` diff --git a/ml_lme/Properties/AssemblyInfo.cs b/ml_lme/Properties/AssemblyInfo.cs index ed513a5..8fdeb25 100644 --- a/ml_lme/Properties/AssemblyInfo.cs +++ b/ml_lme/Properties/AssemblyInfo.cs @@ -1,10 +1,11 @@ using System.Reflection; [assembly: AssemblyTitle("LeapMotionExtension")] -[assembly: AssemblyVersion("1.3.5")] -[assembly: AssemblyFileVersion("1.3.5")] +[assembly: AssemblyVersion("1.3.6")] +[assembly: AssemblyFileVersion("1.3.6")] -[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.3.5", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.3.6", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] +[assembly: MelonLoader.MelonOptionalDependencies("ml_pmc")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] diff --git a/ml_prm/Properties/AssemblyInfo.cs b/ml_prm/Properties/AssemblyInfo.cs index 511e79b..8726bc2 100644 --- a/ml_prm/Properties/AssemblyInfo.cs +++ b/ml_prm/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("PlayerRagdollMod")] -[assembly: AssemblyVersion("1.0.2")] -[assembly: AssemblyFileVersion("1.0.2")] +[assembly: AssemblyVersion("1.0.3")] +[assembly: AssemblyFileVersion("1.0.3")] -[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.0.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.0.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPriority(2)] [assembly: MelonLoader.MelonOptionalDependencies("BTKUILib")] diff --git a/ml_prm/README.md b/ml_prm/README.md index df89e18..d9c649f 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -24,6 +24,7 @@ Optional mod's settings page with [BTKUILib](https://github.com/BTK-Development/ * Note: Forcibly disabled in worlds that don't allow flight. * **View direction velocity:** apply velocity to camera view direction instead of player movement direction; `false` by default. * Note: Forcibly disabled in worlds that don't allow flight. +* **Jump recover:** enables recovering from ragdoll state by jumping; `false` by default. * **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. * Note: Limited according to world's fly multiplier. * Note: Forcibly set to `1.0` in worlds that don't allow flight. From 3f6a72898c9e7e94c53da8963570b14f5c0efdb7 Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 2 May 2023 15:10:41 +0300 Subject: [PATCH 54/63] Forgotten mod supporter initialization --- ml_lme/Main.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/ml_lme/Main.cs b/ml_lme/Main.cs index 2bfb331..a2c9635 100644 --- a/ml_lme/Main.cs +++ b/ml_lme/Main.cs @@ -49,6 +49,7 @@ namespace ml_lme new HarmonyLib.HarmonyMethod(typeof(LeapMotionExtension).GetMethod(nameof(OnPlayspaceScale_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) ); + ModSupporter.Init(); MelonLoader.MelonCoroutines.Start(WaitForRootLogic()); } From 6c83ea69301f9667ed8c3e47067e3598e8f616d7 Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 2 May 2023 23:03:26 +0300 Subject: [PATCH 55/63] VRIK post-update pose --- ml_prm/RagdollController.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index d78601c..0a0e3ca 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -358,6 +358,11 @@ namespace ml_prm { if(m_enabled) m_vrIK.solver.IKPositionWeight = m_vrIkWeight; + else + { + foreach(var l_link in m_boneLinks) + l_link.Item2.CopyGlobal(l_link.Item1); + } } // Settings From 3dceb850375253ed47f6f48b762c2bb0d2a98ee3 Mon Sep 17 00:00:00 2001 From: SDraw Date: Wed, 3 May 2023 21:37:16 +0300 Subject: [PATCH 56/63] VRIK locomotion fix upon unragdoll --- ml_prm/Properties/AssemblyInfo.cs | 6 +++--- ml_prm/RagdollController.cs | 12 +++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ml_prm/Properties/AssemblyInfo.cs b/ml_prm/Properties/AssemblyInfo.cs index 8726bc2..64fe343 100644 --- a/ml_prm/Properties/AssemblyInfo.cs +++ b/ml_prm/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("PlayerRagdollMod")] -[assembly: AssemblyVersion("1.0.3")] -[assembly: AssemblyFileVersion("1.0.3")] +[assembly: AssemblyVersion("1.0.4")] +[assembly: AssemblyFileVersion("1.0.4")] -[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.0.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.0.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPriority(2)] [assembly: MelonLoader.MelonOptionalDependencies("BTKUILib")] diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 0a0e3ca..5324aa6 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -120,7 +120,7 @@ namespace ml_prm if(m_avatarReady && !m_reachedGround) m_reachedGround = MovementSystem.Instance.IsGrounded(); - if(m_avatarReady && m_enabled && BodySystem.isCalibratedAsFullBody && !BodySystem.isCalibrating) + if(m_avatarReady && m_enabled && !BodySystem.isCalibrating) BodySystem.TrackingPositionWeight = 0f; if(m_avatarReady && m_enabled && Settings.AutoRecover) @@ -154,8 +154,7 @@ namespace ml_prm { if(!BodySystem.isCalibrating) { - if(BodySystem.isCalibratedAsFullBody) - BodySystem.TrackingPositionWeight = 0f; + BodySystem.TrackingPositionWeight = 0f; foreach(var l_link in m_boneLinks) l_link.Item1.CopyGlobal(l_link.Item2); @@ -448,7 +447,7 @@ namespace ml_prm MovementSystem.Instance.SetImmobilized(true); PlayerSetup.Instance.animatorManager.SetAnimatorParameterTrigger("CancelEmote"); m_ragdolledParameter.SetValue(true); - if(BodySystem.isCalibratedAsFullBody) + if(!BodySystem.isCalibrating) BodySystem.TrackingPositionWeight = 0f; if(!Utils.IsWorldSafe()) @@ -487,7 +486,7 @@ namespace ml_prm { MovementSystem.Instance.SetImmobilized(false); m_ragdolledParameter.SetValue(false); - if(BodySystem.isCalibratedAsFullBody) + if(!BodySystem.isCalibrating) BodySystem.TrackingPositionWeight = 1f; m_puppetRoot.gameObject.SetActive(false); @@ -502,6 +501,9 @@ namespace ml_prm foreach(Collider l_collider in m_colliders) l_collider.enabled = false; + if(m_vrIK != null) + m_vrIK.solver.Reset(); + m_lastPosition = PlayerSetup.Instance.transform.position; m_velocity = Vector3.zero; m_downTime = float.MinValue; From 0f5e1484d1645e2959e004a481339f101c091da7 Mon Sep 17 00:00:00 2001 From: SDraw Date: Thu, 4 May 2023 11:40:47 +0300 Subject: [PATCH 57/63] New mod: PlayerMovementCopycat Collider radius upon avatar scaling --- README.md | 7 +- ml_amt/Main.cs | 25 ++- ml_amt/Properties/AssemblyInfo.cs | 6 +- ml_mods_cvr.sln | 6 + ml_pmc/Main.cs | 130 ++++++++++++ ml_pmc/ModUi.cs | 136 +++++++++++++ ml_pmc/PoseCopycat.cs | 322 ++++++++++++++++++++++++++++++ ml_pmc/Properties/AssemblyInfo.cs | 12 ++ ml_pmc/PuppetParser.cs | 156 +++++++++++++++ ml_pmc/README.md | 21 ++ ml_pmc/Settings.cs | 120 +++++++++++ ml_pmc/Utils.cs | 81 ++++++++ ml_pmc/ml_pmc.csproj | 101 ++++++++++ ml_pmc/ml_pmc.csproj.user | 6 + ml_pmc/resources/dancing.png | Bin 0 -> 4168 bytes ml_pmc/resources/dancing_on.png | Bin 0 -> 4604 bytes 16 files changed, 1122 insertions(+), 7 deletions(-) create mode 100644 ml_pmc/Main.cs create mode 100644 ml_pmc/ModUi.cs create mode 100644 ml_pmc/PoseCopycat.cs create mode 100644 ml_pmc/Properties/AssemblyInfo.cs create mode 100644 ml_pmc/PuppetParser.cs create mode 100644 ml_pmc/README.md create mode 100644 ml_pmc/Settings.cs create mode 100644 ml_pmc/Utils.cs create mode 100644 ml_pmc/ml_pmc.csproj create mode 100644 ml_pmc/ml_pmc.csproj.user create mode 100644 ml_pmc/resources/dancing.png create mode 100644 ml_pmc/resources/dancing_on.png diff --git a/README.md b/README.md index 2b3f8e8..f8586f3 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,13 @@ Merged set of MelonLoader mods for ChilloutVR. | Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes | |-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------| | Avatar Change Info | ml_aci | 1.0.3 | Retired | Retired | Superseded by `Extended Game Notifications` -| Avatar Motion Tweaker | ml_amt | 1.2.7 | Yes | Working | +| Avatar Motion Tweaker | ml_amt | 1.2.8 | Yes, update review | Working | | Desktop Head Tracking | ml_dht | 1.1.3 | Yes | Working | | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | | Extended Game Notifications | ml_egn | 1.0.2 | Yes | Working | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update -| Leap Motion Extension | ml_lme | 1.3.6 | Yes, update review | Working | +| Leap Motion Extension | ml_lme | 1.3.6 | Yes | Working | | Pickup Arm Movement | ml_pam | 1.0.4 | Yes | Working | -| Player Ragdoll Mod | ml_prm | 1.0.3 | Yes, update review | Working | +| Player Movement Copycat | ml_pmc | 1.0.0 | On review | Working | +| Player Ragdoll Mod | ml_prm | 1.0.4 | Yes, update review | Working | | Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` diff --git a/ml_amt/Main.cs b/ml_amt/Main.cs index c6ccd70..6db0fdd 100644 --- a/ml_amt/Main.cs +++ b/ml_amt/Main.cs @@ -68,12 +68,17 @@ namespace ml_amt ); } - // Alternative collider height + // Alternative collider height and radius HarmonyInstance.Patch( typeof(MovementSystem).GetMethod("UpdateCollider", BindingFlags.NonPublic | BindingFlags.Instance), new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnUpdateCollider_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), null ); + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod("SetupIKScaling", BindingFlags.NonPublic | BindingFlags.Instance), + null, + new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnSetupIKScaling_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); // AAS overriding fix HarmonyInstance.Patch( @@ -252,7 +257,25 @@ namespace ml_amt return false; } + static void OnSetupIKScaling_Postfix( + ref PlayerSetup __instance, + float ____avatarHeight + ) + { + if(!Settings.CollisionScale) + return; + try + { + __instance._movementSystem.UpdateAvatarHeight(Mathf.Clamp(____avatarHeight, 0.05f, float.MaxValue), true); + } + catch(System.Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } + } + + // AnimatorOverrideController runtime animation replacement fix static void OnOverride_Prefix(ref CVRAnimatorManager __instance, out AnimatorAnalyzer __state) { __state = new AnimatorAnalyzer(); diff --git a/ml_amt/Properties/AssemblyInfo.cs b/ml_amt/Properties/AssemblyInfo.cs index 2a256a4..7100101 100644 --- a/ml_amt/Properties/AssemblyInfo.cs +++ b/ml_amt/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("AvatarMotionTweaker")] -[assembly: AssemblyVersion("1.2.7")] -[assembly: AssemblyFileVersion("1.2.7")] +[assembly: AssemblyVersion("1.2.8")] +[assembly: AssemblyFileVersion("1.2.8")] -[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.2.7", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.2.8", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonOptionalDependencies("ml_prm", "ml_pmc")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] diff --git a/ml_mods_cvr.sln b/ml_mods_cvr.sln index 19f4b60..94d3cbf 100644 --- a/ml_mods_cvr.sln +++ b/ml_mods_cvr.sln @@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ml_pam", "ml_pam\ml_pam.csp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ml_prm", "ml_prm\ml_prm.csproj", "{ABD2A720-2DE8-4EB3-BFC2-8F1C3D2ADA15}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ml_pmc", "ml_pmc\ml_pmc.csproj", "{758514D3-6E1A-4E05-A156-B4E5C74AB5C4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -51,6 +53,10 @@ Global {ABD2A720-2DE8-4EB3-BFC2-8F1C3D2ADA15}.Debug|x64.Build.0 = Debug|x64 {ABD2A720-2DE8-4EB3-BFC2-8F1C3D2ADA15}.Release|x64.ActiveCfg = Release|x64 {ABD2A720-2DE8-4EB3-BFC2-8F1C3D2ADA15}.Release|x64.Build.0 = Release|x64 + {758514D3-6E1A-4E05-A156-B4E5C74AB5C4}.Debug|x64.ActiveCfg = Debug|x64 + {758514D3-6E1A-4E05-A156-B4E5C74AB5C4}.Debug|x64.Build.0 = Debug|x64 + {758514D3-6E1A-4E05-A156-B4E5C74AB5C4}.Release|x64.ActiveCfg = Release|x64 + {758514D3-6E1A-4E05-A156-B4E5C74AB5C4}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ml_pmc/Main.cs b/ml_pmc/Main.cs new file mode 100644 index 0000000..bb3a3ea --- /dev/null +++ b/ml_pmc/Main.cs @@ -0,0 +1,130 @@ +using ABI_RC.Core.Networking.IO.Social; +using ABI_RC.Core.Player; +using ABI_RC.Systems.MovementSystem; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; + +namespace ml_pmc +{ + public class PlayerMovementCopycat : MelonLoader.MelonMod + { + static PlayerMovementCopycat ms_instance = null; + + PoseCopycat m_localCopycat = null; + + public override void OnInitializeMelon() + { + if(ms_instance == null) + ms_instance = this; + + Settings.Init(); + ModUi.Init(); + + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)), + null, + new HarmonyLib.HarmonyMethod(typeof(PlayerMovementCopycat).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.NonPublic | BindingFlags.Static)) + ); + HarmonyInstance.Patch( + typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)), + null, + new HarmonyLib.HarmonyMethod(typeof(PlayerMovementCopycat).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + + MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); + } + + public override void OnDeinitializeMelon() + { + if(ms_instance == this) + ms_instance = null; + + m_localCopycat = null; + } + + System.Collections.IEnumerator WaitForLocalPlayer() + { + while(PlayerSetup.Instance == null) + yield return null; + + m_localCopycat = PlayerSetup.Instance.gameObject.AddComponent(); + ModUi.CopySwitch += this.OnTargetSelect; + } + + void OnTargetSelect(string p_id) + { + if(m_localCopycat != null) + { + if(m_localCopycat.IsActive()) + m_localCopycat.SetTarget(null); + else + { + if(Friends.FriendsWith(p_id)) + { + if(CVRPlayerManager.Instance.GetPlayerPuppetMaster(p_id, out PuppetMaster l_puppetMaster)) + { + if(IsInSight(MovementSystem.Instance.proxyCollider, l_puppetMaster.GetComponent(), Utils.GetWorldMovementLimit())) + m_localCopycat.SetTarget(l_puppetMaster.gameObject); + else + ModUi.ShowAlert("Selected player is too far away or obstructed"); + } + else + ModUi.ShowAlert("Selected player isn't connected or ready yet"); + } + else + ModUi.ShowAlert("Selected player isn't your friend"); + } + } + } + + static bool IsInSight(CapsuleCollider p_source, CapsuleCollider p_target, float p_limit) + { + bool l_result = false; + if((p_source != null) && (p_target != null)) + { + Ray l_ray = new Ray(); + l_ray.origin = (p_source.transform.position + p_source.transform.rotation * p_source.center); + l_ray.direction = (p_target.transform.position + p_target.transform.rotation * p_target.center) - l_ray.origin; + List l_hits = Physics.RaycastAll(l_ray, p_limit, LayerMask.NameToLayer("UI Internal")).ToList(); + if(l_hits.Count > 0) + { + l_hits.Sort((a, b) => ((a.distance < b.distance) ? -1 : 1)); + l_result = (l_hits.First().collider.gameObject.transform.root == p_target.transform.root); + } + } + return l_result; + } + + // Patches + static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear(); + void OnAvatarClear() + { + try + { + if(m_localCopycat != null) + m_localCopycat.OnAvatarClear(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnSetupAvatar_Postfix() => ms_instance?.OnSetupAvatar(); + void OnSetupAvatar() + { + try + { + if(m_localCopycat != null) + m_localCopycat.OnAvatarSetup(); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + } +} diff --git a/ml_pmc/ModUi.cs b/ml_pmc/ModUi.cs new file mode 100644 index 0000000..c537cd2 --- /dev/null +++ b/ml_pmc/ModUi.cs @@ -0,0 +1,136 @@ +using BTKUILib.UIObjects; +using BTKUILib.UIObjects.Components; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +namespace ml_pmc +{ + static class ModUi + { + enum UiIndex + { + Toggle, + Position, + Rotation, + Gestures, + LookAtMix, + MirrorPose, + MirrorPosition, + MirrorRotation, + Reset + } + + internal static Action CopySwitch; + + static List ms_uiElements = null; + static string ms_selectedPlayer; + + internal static void Init() + { + ms_uiElements = new List(); + + BTKUILib.QuickMenuAPI.PrepareIcon("PlayerMovementCopycat", "PMC-Dancing", GetIconStream("dancing.png")); + BTKUILib.QuickMenuAPI.PrepareIcon("PlayerMovementCopycat", "PMC-Dancing-On", GetIconStream("dancing_on.png")); + + var l_category = BTKUILib.QuickMenuAPI.PlayerSelectPage.AddCategory("Player Movement Copycat", "PlayerMovementCopycat"); + + ms_uiElements.Add(l_category.AddButton("Copy movement", "PMC-Dancing", "Start/stop copy of player's movement")); + (ms_uiElements[(int)UiIndex.Toggle] as Button).OnPress += OnCopySwitch; + + ms_uiElements.Add(l_category.AddToggle("Apply position", "Apply local position change of target player", Settings.Position)); + (ms_uiElements[(int)UiIndex.Position] as ToggleButton).OnValueUpdated += (value) => OnToggleUpdate(UiIndex.Position, value); + + ms_uiElements.Add(l_category.AddToggle("Apply rotation", "Apply local rotation change of target player", Settings.Rotation)); + (ms_uiElements[(int)UiIndex.Rotation] as ToggleButton).OnValueUpdated += (value) => OnToggleUpdate(UiIndex.Rotation, value); + + ms_uiElements.Add(l_category.AddToggle("Copy gestures", "Copy gestures of target player", Settings.Gestures)); + (ms_uiElements[(int)UiIndex.Gestures] as ToggleButton).OnValueUpdated += (value) => OnToggleUpdate(UiIndex.Gestures, value); + + ms_uiElements.Add(l_category.AddToggle("Apply LookAtIK", "Mix target player pose and camera view direction (desktop only)", Settings.LookAtMix)); + (ms_uiElements[(int)UiIndex.LookAtMix] as ToggleButton).OnValueUpdated += (value) => OnToggleUpdate(UiIndex.LookAtMix, value); + + ms_uiElements.Add(l_category.AddToggle("Mirror pose", "Mirror target player pose", Settings.MirrorPose)); + (ms_uiElements[(int)UiIndex.MirrorPose] as ToggleButton).OnValueUpdated += (value) => OnToggleUpdate(UiIndex.MirrorPose, value); + + ms_uiElements.Add(l_category.AddToggle("Mirror position", "Mirror target player movement against 0YZ plane", Settings.MirrorPosition)); + (ms_uiElements[(int)UiIndex.MirrorPosition] as ToggleButton).OnValueUpdated += (value) => OnToggleUpdate(UiIndex.MirrorPosition, value); + + ms_uiElements.Add(l_category.AddToggle("Mirror rotation", "Mirror target player rotation against 0YZ plane", Settings.MirrorRotation)); + (ms_uiElements[(int)UiIndex.MirrorRotation] as ToggleButton).OnValueUpdated += (value) => OnToggleUpdate(UiIndex.MirrorRotation, value); + + ms_uiElements.Add(l_category.AddButton("Reset settings", "", "Reset mod's settings to default")); + (ms_uiElements[(int)UiIndex.Reset] as Button).OnPress += Reset; + + BTKUILib.QuickMenuAPI.OnPlayerSelected += (_, id) => ms_selectedPlayer = id; + PoseCopycat.OnActivityChange += UpdateToggleColor; + } + + static void OnCopySwitch() => CopySwitch?.Invoke(ms_selectedPlayer); + + static void OnToggleUpdate(UiIndex p_index, bool p_value, bool p_force = false) + { + switch(p_index) + { + case UiIndex.Position: + Settings.SetSetting(Settings.ModSetting.Position, p_value); + break; + + case UiIndex.Rotation: + Settings.SetSetting(Settings.ModSetting.Rotation, p_value); + break; + + case UiIndex.Gestures: + Settings.SetSetting(Settings.ModSetting.Gestures, p_value); + break; + + case UiIndex.LookAtMix: + Settings.SetSetting(Settings.ModSetting.LookAtMix, p_value); + break; + + case UiIndex.MirrorPose: + Settings.SetSetting(Settings.ModSetting.MirrorPose, p_value); + break; + + case UiIndex.MirrorPosition: + Settings.SetSetting(Settings.ModSetting.MirrorPosition, p_value); + break; + + case UiIndex.MirrorRotation: + Settings.SetSetting(Settings.ModSetting.MirrorRotation, p_value); + break; + } + + if(p_force) + (ms_uiElements[(int)p_index] as ToggleButton).ToggleValue = p_value; + } + + static void Reset() + { + OnToggleUpdate(UiIndex.Position, true, true); + OnToggleUpdate(UiIndex.Rotation, true, true); + OnToggleUpdate(UiIndex.Gestures, true, true); + OnToggleUpdate(UiIndex.LookAtMix, true, true); + OnToggleUpdate(UiIndex.MirrorPose, false, true); + OnToggleUpdate(UiIndex.MirrorPosition, false, true); + OnToggleUpdate(UiIndex.MirrorRotation, false, true); + } + + internal static void ShowAlert(string p_text) => BTKUILib.QuickMenuAPI.ShowAlertToast(p_text, 2); + + // Currently broken in BTKUILib, waiting for fix + static void UpdateToggleColor(bool p_state) + { + //(ms_uiElements[(int)UiIndex.Toggle] as Button).ButtonIcon = (p_state ? "PMC-Dancing-On" : "PMC-Dancing"); + //(ms_uiElements[(int)UiIndex.Toggle] as Button).ButtonText = (p_state ? "PMC-Dancing-On" : "PMC-Dancing"); + } + + static Stream GetIconStream(string p_name) + { + Assembly l_assembly = Assembly.GetExecutingAssembly(); + string l_assemblyName = l_assembly.GetName().Name; + return l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + p_name); + } + } +} diff --git a/ml_pmc/PoseCopycat.cs b/ml_pmc/PoseCopycat.cs new file mode 100644 index 0000000..a331c89 --- /dev/null +++ b/ml_pmc/PoseCopycat.cs @@ -0,0 +1,322 @@ +using ABI_RC.Core.Player; +using ABI_RC.Core.Savior; +using ABI_RC.Systems.IK; +using ABI_RC.Systems.IK.SubSystems; +using ABI_RC.Systems.MovementSystem; +using RootMotion.FinalIK; +using UnityEngine; + +namespace ml_pmc +{ + [DisallowMultipleComponent] + public class PoseCopycat : MonoBehaviour + { + static readonly Vector4 ms_pointVector = new Vector4(0f, 0f, 0f, 1f); + + static public PoseCopycat Instance { get; private set; } = null; + static internal System.Action OnActivityChange; + + Animator m_animator = null; + VRIK m_vrIk = null; + float m_ikWeight = 1f; + LookAtIK m_lookAtIk = null; + float m_lookIkWeight = 1f; + bool m_sitting = false; + bool m_inVr = false; + + bool m_active = false; + float m_distanceLimit = float.MaxValue; + bool m_fingerTracking = false; + + HumanPoseHandler m_poseHandler = null; + HumanPose m_pose; + PuppetParser m_puppetParser = null; + + internal PoseCopycat() + { + if(Instance == null) + Instance = this; + } + ~PoseCopycat() + { + if(Instance == this) + Instance = null; + } + + // Unity events + void Update() + { + m_sitting = (MovementSystem.Instance.lastSeat != null); + + if(m_active && (m_puppetParser != null)) + { + OverrideIK(); + + if(m_puppetParser.HasAnimator()) + { + bool l_mirror = Settings.MirrorPose; + + if(Settings.Gestures) + { + CVRInputManager.Instance.gestureLeft = (l_mirror ? m_puppetParser.GetRightGesture() : m_puppetParser.GetLeftGesture()); + CVRInputManager.Instance.gestureRight = (l_mirror ? m_puppetParser.GetLeftGesture() : m_puppetParser.GetRightGesture()); + } + + if(m_puppetParser.HasFingerTracking()) + { + m_fingerTracking = true; + + CVRInputManager.Instance.individualFingerTracking = true; + IKSystem.Instance.FingerSystem.controlActive = true; + + ref float[] l_curls = ref m_puppetParser.GetFingerCurls(); + + CVRInputManager.Instance.fingerCurlLeftThumb = l_curls[l_mirror ? 5 : 0]; + CVRInputManager.Instance.fingerCurlLeftIndex = l_curls[l_mirror ? 6 : 1]; + CVRInputManager.Instance.fingerCurlLeftMiddle = l_curls[l_mirror ? 7 : 2]; + CVRInputManager.Instance.fingerCurlLeftRing = l_curls[l_mirror ? 8 : 3]; + CVRInputManager.Instance.fingerCurlLeftPinky = l_curls[l_mirror ? 9 : 4]; + CVRInputManager.Instance.fingerCurlRightThumb = l_curls[l_mirror ? 0 : 5]; + CVRInputManager.Instance.fingerCurlRightIndex = l_curls[l_mirror ? 1 : 6]; + CVRInputManager.Instance.fingerCurlRightMiddle = l_curls[l_mirror ? 2 : 7]; + CVRInputManager.Instance.fingerCurlRightRing = l_curls[l_mirror ? 3 : 8]; + CVRInputManager.Instance.fingerCurlRightPinky = l_curls[l_mirror ? 4 : 9]; + + IKSystem.Instance.FingerSystem.leftThumbCurl = l_curls[l_mirror ? 5 : 0]; + IKSystem.Instance.FingerSystem.leftIndexCurl = l_curls[l_mirror ? 6 : 1]; + IKSystem.Instance.FingerSystem.leftMiddleCurl = l_curls[l_mirror ? 7 : 2]; + IKSystem.Instance.FingerSystem.leftRingCurl = l_curls[l_mirror ? 8 : 3]; + IKSystem.Instance.FingerSystem.leftPinkyCurl = l_curls[l_mirror ? 9 : 4]; + IKSystem.Instance.FingerSystem.rightThumbCurl = l_curls[l_mirror ? 0 : 5]; + IKSystem.Instance.FingerSystem.rightIndexCurl = l_curls[l_mirror ? 1 : 6]; + IKSystem.Instance.FingerSystem.rightMiddleCurl = l_curls[l_mirror ? 2 : 7]; + IKSystem.Instance.FingerSystem.rightRingCurl = l_curls[l_mirror ? 3 : 8]; + IKSystem.Instance.FingerSystem.rightPinkyCurl = l_curls[l_mirror ? 4 : 9]; + } + else + { + if(m_fingerTracking) + { + RestoreFingerTracking(); + m_fingerTracking = false; + } + } + + Matrix4x4 l_offset = m_puppetParser.GetOffset(); + Vector3 l_pos = l_offset * ms_pointVector; + Quaternion l_rot = l_offset.rotation; + + l_pos.y = 0f; + if(Settings.MirrorPosition) + l_pos.x *= -1f; + l_pos = Vector3.ClampMagnitude(l_pos, m_distanceLimit); + + l_rot = Quaternion.Euler(0f, l_rot.eulerAngles.y * (Settings.MirrorRotation ? -1f : 1f), 0f); + + Matrix4x4 l_result = PlayerSetup.Instance.transform.GetMatrix() * Matrix4x4.TRS(l_pos, l_rot, Vector3.one); + + if(Settings.Position && !m_sitting && !m_puppetParser.IsSitting() && Utils.IsWorldSafe() && Utils.IsCombatSafe()) + PlayerSetup.Instance.transform.position = l_result * ms_pointVector; + + if(Settings.Rotation && !m_sitting && !m_puppetParser.IsSitting() && Utils.IsCombatSafe()) + { + if(m_inVr) + { + Vector3 l_avatarPos = PlayerSetup.Instance._avatar.transform.position; + PlayerSetup.Instance.transform.rotation = l_result.rotation; + Vector3 l_dif = l_avatarPos - PlayerSetup.Instance._avatar.transform.position; + PlayerSetup.Instance.transform.position += l_dif; + } + else + PlayerSetup.Instance.transform.rotation = l_result.rotation; + } + } + else + { + if(!m_puppetParser.IsWaitingAnimator()) + SetTarget(null); + } + + if(Vector3.Distance(this.transform.position, m_puppetParser.transform.position) > m_distanceLimit) + SetTarget(null); + } + } + + void LateUpdate() + { + if(m_active && (m_animator != null) && (m_puppetParser != null) && m_puppetParser.IsPoseParsed()) + { + OverrideIK(); + + m_puppetParser.GetPose().CopyTo(ref m_pose); + if(Settings.MirrorPose) + Utils.MirrorPose(ref m_pose); + m_poseHandler.SetHumanPose(ref m_pose); + } + } + + // Patches + internal void OnAvatarClear() + { + m_inVr = Utils.IsInVR(); + + if(m_puppetParser != null) + Object.Destroy(m_puppetParser); + m_puppetParser = null; + + m_animator = null; + m_vrIk = null; + m_lookAtIk = null; + + m_poseHandler?.Dispose(); + m_poseHandler = null; + m_active = false; + m_distanceLimit = float.MaxValue; + m_fingerTracking = false; + m_pose = new HumanPose(); + } + internal void OnAvatarSetup() + { + m_animator = PlayerSetup.Instance._animator; + m_vrIk = PlayerSetup.Instance._avatar.GetComponent(); + m_lookAtIk = PlayerSetup.Instance._avatar.GetComponent(); + + if((m_animator != null) && m_animator.isHuman) + { + m_poseHandler = new HumanPoseHandler(m_animator.avatar, m_animator.transform); + m_poseHandler.GetHumanPose(ref m_pose); + + if(m_vrIk != null) + { + m_vrIk.onPreSolverUpdate.AddListener(this.OnVRIKPreUpdate); + m_vrIk.onPostSolverUpdate.AddListener(this.OnVRIKPostUpdate); + } + + if(m_lookAtIk != null) + { + m_lookAtIk.onPreSolverUpdate.AddListener(this.OnLookAtIKPreUpdate); + m_lookAtIk.onPostSolverUpdate.AddListener(this.OnLookAtIKPostUpdate); + } + } + else + m_animator = null; + } + + // IK updates + void OnVRIKPreUpdate() + { + if(m_active) + { + m_ikWeight = m_vrIk.solver.IKPositionWeight; + m_vrIk.solver.IKPositionWeight = 0f; + } + } + void OnVRIKPostUpdate() + { + if(m_active) + m_vrIk.solver.IKPositionWeight = m_ikWeight; + } + + void OnLookAtIKPreUpdate() + { + if(m_active && !Settings.LookAtMix) + { + m_lookIkWeight = m_lookAtIk.solver.IKPositionWeight; + m_lookAtIk.solver.IKPositionWeight = 0f; + } + } + void OnLookAtIKPostUpdate() + { + if(m_active && !Settings.LookAtMix) + m_lookAtIk.solver.IKPositionWeight = m_lookIkWeight; + } + + // Arbitrary + public void SetTarget(GameObject p_target) + { + if(m_animator != null) + { + if(!m_active) + { + if(p_target != null) + { + m_puppetParser = p_target.AddComponent(); + m_distanceLimit = Utils.GetWorldMovementLimit(); + + m_active = true; + OnActivityChange?.Invoke(m_active); + } + } + else + { + if(p_target == null) + { + if(m_puppetParser != null) + Object.Destroy(m_puppetParser); + m_puppetParser = null; + + if(!m_sitting) + { + Quaternion l_rot = PlayerSetup.Instance.transform.rotation; + PlayerSetup.Instance.transform.rotation = Quaternion.Euler(0f, l_rot.eulerAngles.y, 0f); + } + + RestoreIK(); + RestoreFingerTracking(); + m_fingerTracking = false; + + m_active = false; + OnActivityChange?.Invoke(m_active); + } + } + } + } + + public bool IsActive() => m_active; + public bool IsFingerTrackingActive() => m_fingerTracking; + + void OverrideIK() + { + if((m_vrIk != null) && !BodySystem.isCalibrating) + BodySystem.TrackingPositionWeight = 0f; + } + void RestoreIK() + { + if((m_vrIk != null) && !BodySystem.isCalibrating) + { + BodySystem.TrackingPositionWeight = 1f; + m_vrIk.solver.Reset(); + } + } + void RestoreFingerTracking() + { + CVRInputManager.Instance.individualFingerTracking = (m_inVr && Utils.AreKnucklesInUse() && !Utils.GetIndexGestureToggle()); + IKSystem.Instance.FingerSystem.controlActive = CVRInputManager.Instance.individualFingerTracking; + + if(!CVRInputManager.Instance.individualFingerTracking) + { + CVRInputManager.Instance.fingerCurlLeftThumb = 0f; + CVRInputManager.Instance.fingerCurlLeftIndex = 0f; + CVRInputManager.Instance.fingerCurlLeftMiddle = 0f; + CVRInputManager.Instance.fingerCurlLeftRing = 0f; + CVRInputManager.Instance.fingerCurlLeftPinky = 0f; + CVRInputManager.Instance.fingerCurlRightThumb = 0f; + CVRInputManager.Instance.fingerCurlRightIndex = 0f; + CVRInputManager.Instance.fingerCurlRightMiddle = 0f; + CVRInputManager.Instance.fingerCurlRightRing = 0f; + CVRInputManager.Instance.fingerCurlRightPinky = 0f; + + IKSystem.Instance.FingerSystem.leftThumbCurl = 0f; + IKSystem.Instance.FingerSystem.leftIndexCurl = 0f; + IKSystem.Instance.FingerSystem.leftMiddleCurl = 0f; + IKSystem.Instance.FingerSystem.leftRingCurl = 0f; + IKSystem.Instance.FingerSystem.leftPinkyCurl = 0f; + IKSystem.Instance.FingerSystem.rightThumbCurl = 0f; + IKSystem.Instance.FingerSystem.rightIndexCurl = 0f; + IKSystem.Instance.FingerSystem.rightMiddleCurl = 0f; + IKSystem.Instance.FingerSystem.rightRingCurl = 0f; + IKSystem.Instance.FingerSystem.rightPinkyCurl = 0f; + } + } + } +} diff --git a/ml_pmc/Properties/AssemblyInfo.cs b/ml_pmc/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..84f0e07 --- /dev/null +++ b/ml_pmc/Properties/AssemblyInfo.cs @@ -0,0 +1,12 @@ +using System.Reflection; + +[assembly: AssemblyTitle("PlayerMovementCopycat")] +[assembly: AssemblyVersion("1.0.0")] +[assembly: AssemblyFileVersion("1.0.0")] + +[assembly: MelonLoader.MelonInfo(typeof(ml_pmc.PlayerMovementCopycat), "PlayerMovementCopycat", "1.0.0", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonGame(null, "ChilloutVR")] +[assembly: MelonLoader.MelonPriority(3)] +[assembly: MelonLoader.MelonAdditionalDependencies("BTKUILib")] +[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] \ No newline at end of file diff --git a/ml_pmc/PuppetParser.cs b/ml_pmc/PuppetParser.cs new file mode 100644 index 0000000..531795a --- /dev/null +++ b/ml_pmc/PuppetParser.cs @@ -0,0 +1,156 @@ +using ABI_RC.Core.Player; +using UnityEngine; + +namespace ml_pmc +{ + [DisallowMultipleComponent] + class PuppetParser : MonoBehaviour + { + static readonly Vector4 ms_pointVector = new Vector4(0f, 0f, 0f, 1f); + + PuppetMaster m_puppetMaster = null; + Animator m_animator = null; + AnimatorCullingMode m_cullMode; + float m_armatureScale = 1f; + float m_armatureHeight = 0f; + + bool m_waitAnimator = true; + HumanPoseHandler m_poseHandler = null; + HumanPose m_pose; + bool m_poseParsed = false; + + Matrix4x4 m_matrix = Matrix4x4.identity; + Matrix4x4 m_offset = Matrix4x4.identity; + + bool m_sitting = false; + float m_leftGesture = 0f; + float m_rightGesture = 0f; + bool m_fingerTracking = false; + float[] m_fingerCurls = null; + + internal PuppetParser() + { + m_fingerCurls = new float[10]; + } + + // Unity events + void Start() + { + m_puppetMaster = this.GetComponent(); + m_matrix = this.transform.GetMatrix(); + StartCoroutine(WaitForAnimator()); + } + + void OnDestroy() + { + if(m_animator != null) + m_animator.cullingMode = m_cullMode; + + m_poseHandler?.Dispose(); + } + + void Update() + { + if(m_puppetMaster != null) + { + m_sitting = m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorSitting; + m_leftGesture = m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorGestureLeft; + m_rightGesture = m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorGestureRight; + m_fingerTracking = m_puppetMaster.PlayerAvatarMovementDataInput.IndexUseIndividualFingers; + if(m_fingerTracking) + { + m_fingerCurls[0] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftThumbCurl; + m_fingerCurls[1] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftIndexCurl; + m_fingerCurls[2] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftMiddleCurl; + m_fingerCurls[3] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftRingCurl; + m_fingerCurls[4] = m_puppetMaster.PlayerAvatarMovementDataInput.LeftPinkyCurl; + m_fingerCurls[5] = m_puppetMaster.PlayerAvatarMovementDataInput.RightThumbCurl; + m_fingerCurls[6] = m_puppetMaster.PlayerAvatarMovementDataInput.RightIndexCurl; + m_fingerCurls[7] = m_puppetMaster.PlayerAvatarMovementDataInput.RightMiddleCurl; + m_fingerCurls[8] = m_puppetMaster.PlayerAvatarMovementDataInput.RightRingCurl; + m_fingerCurls[9] = m_puppetMaster.PlayerAvatarMovementDataInput.RightPinkyCurl; + } + } + + if(!ReferenceEquals(m_animator, null)) + { + if(m_animator != null) + { + Matrix4x4 l_current = this.transform.GetMatrix(); + m_offset = m_matrix.inverse * l_current; + m_matrix = l_current; + } + else + Reset(); + } + } + + void LateUpdate() + { + if(m_animator != null) + { + m_poseHandler.GetHumanPose(ref m_pose); + m_pose.bodyPosition *= m_armatureScale; + m_pose.bodyPosition.y += m_armatureHeight; + m_poseParsed = true; + } + } + + // Arbitrary + System.Collections.IEnumerator WaitForAnimator() + { + while(m_puppetMaster.avatarObject == null) + yield return null; + + while(m_animator == null) + { + m_animator = m_puppetMaster.avatarObject.GetComponent(); + yield return null; + } + + if(m_animator.isHuman) + { + m_cullMode = m_animator.cullingMode; + m_animator.cullingMode = AnimatorCullingMode.AlwaysAnimate; + + Transform l_hips = m_animator.GetBoneTransform(HumanBodyBones.Hips); + if((l_hips != null) && (l_hips.parent != null)) + { + m_armatureScale = l_hips.parent.localScale.y; + m_armatureHeight = ((m_puppetMaster.transform.GetMatrix().inverse * l_hips.parent.GetMatrix()) * ms_pointVector).y; + } + + m_poseHandler = new HumanPoseHandler(m_animator.avatar, m_animator.transform); + m_matrix = this.transform.GetMatrix(); + } + else + Reset(); + + m_waitAnimator = false; + } + + void Reset() + { + m_animator = null; + m_poseHandler?.Dispose(); + m_poseHandler = null; + m_pose = new HumanPose(); + m_poseParsed = false; + m_offset = Matrix4x4.identity; + m_sitting = false; + m_leftGesture = 0f; + m_rightGesture = 0f; + } + + public bool IsWaitingAnimator() => m_waitAnimator; + public bool HasAnimator() => !ReferenceEquals(m_animator, null); + public ref HumanPose GetPose() => ref m_pose; + public bool IsPoseParsed() => m_poseParsed; + public ref Matrix4x4 GetOffset() => ref m_offset; + public bool IsSitting() => m_sitting; + public float GetLeftGesture() => m_leftGesture; + public float GetRightGesture() => m_rightGesture; + public bool HasFingerTracking() => m_fingerTracking; + public ref float[] GetFingerCurls() => ref m_fingerCurls; + } +} diff --git a/ml_pmc/README.md b/ml_pmc/README.md new file mode 100644 index 0000000..1f02e47 --- /dev/null +++ b/ml_pmc/README.md @@ -0,0 +1,21 @@ +# Player Movement Copycat +Allows to copy pose, gestures and movement of your friends. + +# Installation +* Install [BTKUILib](https://github.com/BTK-Development/BTKUILib) +* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader) +* Get [latest release DLL](../../../releases/latest): + * Put `ml_pmc.dll` in `Mods` folder of game + +# Usage +Available options in BTKUILib players list upon player selection: +* **Copy movement:** starts/stops copycating of selected player. + * Note: Selected player should be your friend, be in your view range and not obstructed by other players/world objects/props. +* **Apply position:** enables/disables position changes of selected player; `true` by default. + * Note: Forcibly disabled in worlds that don't allow flight. +* **Apply rotation:** enables/disables rotation changes of selected player; `true` by default. +* **Copy gestures:** enables/disables gestures copy of selected player; `true` by default. +* **Apply LookAtIK:** enables/disables additional head rotation based on camera view in desktop mode; `true` by default. +* **Mirror pose:** enables/disables pose and gestures mirroring; `false` by default. +* **Mirror position:** enables/disables mirroring of position changes of selected player along 0XZ plane; `false` by default. +* **Mirror rotation:** enables/disables mirroring of rotation changes of selected player along 0XZ plane; `false` by default. diff --git a/ml_pmc/Settings.cs b/ml_pmc/Settings.cs new file mode 100644 index 0000000..d412dc2 --- /dev/null +++ b/ml_pmc/Settings.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; + +namespace ml_pmc +{ + static class Settings + { + public enum ModSetting + { + Position, + Rotation, + Gestures, + LookAtMix, + MirrorPose, + MirrorPosition, + MirrorRotation + } + + public static bool Position { get; private set; } = true; + public static bool Rotation { get; private set; } = true; + public static bool Gestures { get; private set; } = true; + public static bool LookAtMix { get; private set; } = true; + public static bool MirrorPose { get; private set; } = false; + public static bool MirrorPosition { get; private set; } = false; + public static bool MirrorRotation { get; private set; } = false; + + public static Action PositionChange; + public static Action RotationChange; + public static Action GesturesChange; + public static Action LookAtMixChange; + public static Action MirrorPoseChange; + public static Action MirrorPositionChange; + public static Action MirrorRotationChange; + + static MelonLoader.MelonPreferences_Category ms_category = null; + static List ms_entries = null; + + internal static void Init() + { + ms_category = MelonLoader.MelonPreferences.CreateCategory("PMC", null, true); + ms_entries = new List() + { + ms_category.CreateEntry(ModSetting.Position.ToString(), Position), + ms_category.CreateEntry(ModSetting.Rotation.ToString(), Rotation), + ms_category.CreateEntry(ModSetting.Gestures.ToString(), Gestures), + ms_category.CreateEntry(ModSetting.LookAtMix.ToString(), LookAtMix), + ms_category.CreateEntry(ModSetting.MirrorPose.ToString(), MirrorPose), + ms_category.CreateEntry(ModSetting.MirrorPosition.ToString(), MirrorPosition), + ms_category.CreateEntry(ModSetting.MirrorRotation.ToString(), MirrorRotation), + }; + + Position = (bool)ms_entries[(int)ModSetting.Position].BoxedValue; + Rotation = (bool)ms_entries[(int)ModSetting.Rotation].BoxedValue; + Gestures = (bool)ms_entries[(int)ModSetting.Gestures].BoxedValue; + LookAtMix = (bool)ms_entries[(int)ModSetting.LookAtMix].BoxedValue; + MirrorPose = (bool)ms_entries[(int)ModSetting.MirrorPose].BoxedValue; + MirrorPosition = (bool)ms_entries[(int)ModSetting.MirrorPosition].BoxedValue; + MirrorRotation = (bool)ms_entries[(int)ModSetting.MirrorRotation].BoxedValue; + } + + public static void SetSetting(ModSetting p_setting, object p_value) + { + switch(p_setting) + { + case ModSetting.Position: + { + Position = (bool)p_value; + PositionChange?.Invoke((bool)p_value); + } + break; + + case ModSetting.Rotation: + { + Rotation = (bool)p_value; + RotationChange?.Invoke((bool)p_value); + break; + } + + case ModSetting.Gestures: + { + Gestures = (bool)p_value; + GesturesChange?.Invoke((bool)p_value); + } + break; + + case ModSetting.LookAtMix: + { + LookAtMix = (bool)p_value; + LookAtMixChange?.Invoke((bool)p_value); + } + break; + + // + case ModSetting.MirrorPose: + { + MirrorPose = (bool)p_value; + MirrorPoseChange?.Invoke((bool)p_value); + } + break; + + case ModSetting.MirrorPosition: + { + MirrorPosition = (bool)p_value; + MirrorPositionChange?.Invoke((bool)p_value); + } + break; + + case ModSetting.MirrorRotation: + { + MirrorRotation = (bool)p_value; + MirrorRotationChange?.Invoke((bool)p_value); + } + break; + } + + if(ms_entries != null) + ms_entries[(int)p_setting].BoxedValue = p_value; + } + } +} diff --git a/ml_pmc/Utils.cs b/ml_pmc/Utils.cs new file mode 100644 index 0000000..fbc462a --- /dev/null +++ b/ml_pmc/Utils.cs @@ -0,0 +1,81 @@ +using ABI.CCK.Components; +using ABI_RC.Core.Player; +using ABI_RC.Core.Savior; +using System.Linq; +using System.Reflection; +using UnityEngine; + +namespace ml_pmc +{ + static class Utils + { + static readonly FieldInfo ms_indexGestureToggle = typeof(InputModuleSteamVR).GetField("_steamVrIndexGestureToggleValue", BindingFlags.Instance | BindingFlags.NonPublic); + + static readonly (int, int)[] ms_sideMuscles = new (int, int)[] + { + (29,21), (30,22), (31,23), (32,24), (33,25), (34,26), (35,27), (36,28), + (46,37), (47,38), (48,39), (49,40), (50,41), (51,42), (52,43), (53,44), (54,45), + (75,55), (76,56), (77,57), (78,58), (79,59), (80,60), (81,61), (82,62), (83,63), (84,64), + (85,65), (86,66), (87,67), (88,68), (89, 69), (90,70), (91,71), (92,72), (93,73), (94,74) + }; + static readonly int[] ms_centralMuscles = new int[] { 1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 18, 20 }; + + public static bool IsInVR() => ((CheckVR.Instance != null) && CheckVR.Instance.hasVrDeviceLoaded); + public static bool AreKnucklesInUse() => PlayerSetup.Instance._trackerManager.trackerNames.Contains("knuckles"); + public static bool GetIndexGestureToggle() => (bool)ms_indexGestureToggle.GetValue(CVRInputManager.Instance.GetComponent()); + + public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying); + public static bool IsCombatSafe() => ((CombatSystem.Instance == null) || !CombatSystem.Instance.isDown); + + public static float GetWorldMovementLimit() + { + float l_result = 1f; + if(CVRWorld.Instance != null) + { + l_result = CVRWorld.Instance.baseMovementSpeed; + l_result *= CVRWorld.Instance.sprintMultiplier; + l_result *= CVRWorld.Instance.inAirMovementMultiplier; + l_result *= CVRWorld.Instance.flyMultiplier; + } + return l_result; + } + + public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) + { + return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.lossyScale : Vector3.one); + } + + public static void CopyTo(this HumanPose p_source, ref HumanPose p_target) + { + p_target.bodyPosition = p_source.bodyPosition; + p_target.bodyRotation = p_source.bodyRotation; + + int l_count = Mathf.Min(p_source.muscles.Length, p_target.muscles.Length); + for(int i = 0; i < l_count; i++) + p_target.muscles[i] = p_source.muscles[i]; + } + + public static void MirrorPose(ref HumanPose p_pose) + { + int l_count = p_pose.muscles.Length; + foreach(var l_pair in ms_sideMuscles) + { + if((l_count > l_pair.Item1) && (l_count > l_pair.Item2)) + { + float l_temp = p_pose.muscles[l_pair.Item1]; + p_pose.muscles[l_pair.Item1] = p_pose.muscles[l_pair.Item2]; + p_pose.muscles[l_pair.Item2] = l_temp; + } + } + foreach(int l_index in ms_centralMuscles) + { + if(l_count > l_index) + p_pose.muscles[l_index] *= -1f; + } + + p_pose.bodyRotation.x *= -1f; + p_pose.bodyRotation.w *= -1f; + p_pose.bodyPosition.x *= -1f; + } + } +} diff --git a/ml_pmc/ml_pmc.csproj b/ml_pmc/ml_pmc.csproj new file mode 100644 index 0000000..4679faa --- /dev/null +++ b/ml_pmc/ml_pmc.csproj @@ -0,0 +1,101 @@ + + + + + Debug + AnyCPU + {758514D3-6E1A-4E05-A156-B4E5C74AB5C4} + Library + Properties + ml_pmc + ml_pmc + v4.7.2 + 512 + true + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\0Harmony.dll + False + False + + + False + D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll + False + + + False + D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll + False + + + D:\Games\Steam\steamapps\common\ChilloutVR\Mods\BTKUILib.dll + False + False + + + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\MelonLoader.dll + False + False + + + + + + + + + + D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AnimationModule.dll + False + False + + + D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll + False + False + + + False + D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.PhysicsModule.dll + + + + + + + + + + + + + + + + + + + + copy /y "$(TargetPath)" "D:\Games\Steam\steamapps\common\ChilloutVR\Mods\" + + \ No newline at end of file diff --git a/ml_pmc/ml_pmc.csproj.user b/ml_pmc/ml_pmc.csproj.user new file mode 100644 index 0000000..4d08fe9 --- /dev/null +++ b/ml_pmc/ml_pmc.csproj.user @@ -0,0 +1,6 @@ + + + + D:\Games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\;D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\;D:\Games\Steam\steamapps\common\ChilloutVR\Mods\ + + \ No newline at end of file diff --git a/ml_pmc/resources/dancing.png b/ml_pmc/resources/dancing.png new file mode 100644 index 0000000000000000000000000000000000000000..d54c17c730829147bd61f5da4199790614913204 GIT binary patch literal 4168 zcmb_gc|276-~XO7#xh8lL9$)MD2d$c%P0y{wun+p8>xvY$`a;G-0aJ}RJzuZxRr~k zM7A?sU4&2yk(pbzgc(bgi0A13UeD|GJpVq=ALsS`ob!Hvw(t3#^F8mA;NrATlAuTc z07yF6+qwY&VI~Abg|Xr2#S%Yk5M$UM4hF!ucKv{2zVGkBE~=fhcRK(;#1;UM7yy>m zuyG6kH&FnQyZ|t}34nZ1&k@yh0Hj_y*xI;aDuE@(qV$)z9a^C9*xZAYn1y2w`UJAkTtVv0-LKm1mBoCIoNZ zklf<$zN(Z3?HB%2C>3W^u|}l4P43_h?`xcsnH|(+Mo%AQMS6m@OseM2rySJ7vWopX zZl&6?1l%9WDTqTr5@N0M)9B=^@0$`Y(TPo&{hce7g~ih+>ZhLjxP$8qO+iutYwk$2 zYTiz+G@8-al(@pKwGZ5U>2T{VM+)TrLWGqKi@eT?t)8-}6xH!~h)>;~&iw_STBo4k zXT23+Z-S3*G>Km|b^#m$#r zY40H=6p5+WC&FRQmy2qyBTU`Fmpk5S%$n!Sd}>u538Qyj=%`dBQTpauxheZz_+OpP zc4Yy%u0BGOVNB|B`gg25-XO{`w9+s8b;-kyH2rqNjFRl4)@kOlE0o#(f`uDpCiJWF zeE-m!8dvK`I~eKk_1of~nBU70gvXifLvoDpDi2)%b;eWIcKg9XmEG?%2nBPd zUpw#{@*Hg3j_i5T)iRsh$7-^Co#zft%P!qNZ%}@T6Pa4{&7?3UvI(!Up#CFY04HYj z;nk(cdSQ6+P+SLeNA6HNuJW-qiE>McXc6WomqVQUswm3)eZ!10uuut`h?#J}yJ%$( z^KWYuHV=HuIH!hGD37dsAf#<4sGW*QZ(cO$3;7gy(G-g~7UJhKPR{xzK0=qr)o&i$wh`Te z|6-g-PpXLb+FjXK67>ggJSoKs6%#&W%-uMU*&9C3Cv~_+GV4hn2yfd~ys(~M@WLGr>yJ;$AIA2Hih6+~r zYWF(&CZGO*@7^^z@2RTZ&)#-|-4P%AHR)(axzM8F6>Kir{bjhJ`9}q&FWk+zCLu4~{Pxl`FNGs6;_E&qrU zVr?CxqDoGct$|#h5Io6LXH4^oE9B1ksc|xD&1c#|KZRb{{${3i{($1qnr2B)=H5{8 z2SkK8qIf@nJNi^?0o)vR?g<6LMt1`>aOWznO+1>KFNDdtw>f-XQe!q+xU{FTY}k`* z-aXfI!G2Y7$JSSDc@ib)h>k+|7lssr)VK9{+S{Rb$4~O+(T3URWf#cZPWAPKe7d@i zcK=8EOn;#AHSH=#h4hA~UP%)@=9X~0zCnJlK&X7DfFH4`_l*zM^K^oYs_4D+=aD?_ zjCUNa<;GgzSm_>L+BTX$yKF&4YGr%he1LUJke$z~AnMD+p!acv0>@Xk7aG}-cRER@ zk^=X_#p&lIE=H|#<-mipnX~R!usYgH6+Eu_O1XjS4WzL57rYLe=-5NX!#=rlAHG0_~aR!TzE*~(1IPy*!$87U?raQbB~Oa^$h?Id(}K12oq zWgyQ55GX`s)Cs~iWxU#X8T2GNl4p!pTfh2vKM-Gcn2f-LU- z>l}>5{%_bqls^6+xZq#-(f{yvs?y_d7C}OQCDnPw;9-+Uq?j)e+LN@A?H1TsqG2fu+xaKPu0rv`AKbj=g+AHp^ewKbdQsH{^;+aEyp)8 z5@a)ol#Hsou?c3a2$xRd**2!hygMUKixjE05K}r6q=RTNg6=>|x(pS8G>yvUFGQIz zd5in6erm@HZz;jPf3E7ygqyB0*VnqYk%*7Iz5?Ixuj~*yVL&0W?IvP*^-J*OX#ByU z$wvL<{ZRMP>RLOGWg;2IluG>|Qf0W<+k}66T2$YFTbVA^^5t=zQ4UMYJ*3o+TtftA$Ca>aJ?#$=+V*cmLyXtn_z}55x5efornP4t}-4|ka(X8;M zaF zJySDj3Z^P7Qd|5~=PR^{lnBgR~e~qdt)61m$#lxASz3+bOJ@JdlMlmaJ6eh|Vb75= zjfEL`U&wx`hF>d64?J%Nb>|cLecTzFY)r!F@9Z+4=X-m*g0KEp*isR;O&WvDB>0T* zL78KCrJx^d_Zt36(i0NC^VKd0q)9)u!8Dk|qE%G5x>)k#`a58}1D7BqIH@X}2$xuU zYRjNUXx3l05ef#A)sGFFjlvRUPa>l-Vze#gHM`{SE?28x#C6j*)lnDOccDqm6+Ahu zFF18VEXOYw%X2eGQx2um(l22g?k$$MER`1Y1q)rDbIS{8A3lk7S+pa-N{MZySN=Cv zczc2vo^k6d39IQFZb4H9?R)1*qoI@xX78PogmP26nGv|8)uP<;hmy7ZnB*6sa!H}8(v zNGS;#X);5*y;GErn6w6`?R!;RbMU5pa%Gch$DT@sI(czf=R-PHBk5b-{+OPd93L+^ z{&wMb!esN*@x{;c*CxgnXX^T=9KH`mmOh*KN?LO%chEso7>H}YmWaS+BCOmD%#{R4 zS_zs-0BinFM4HC~$2EB}fuvt}J6ZkdjAFFBgR+U^+tx$lklOWnbRqDW;74HYdiQwU zJvuxSiavnt1Y@z79N&9##Mk@)myNmcedyvR`XA-(Bjue{b{sVZb^y!>A-?0uk2eF73e1r{jgdt38U=fi0SmAt?Z`k3qgJPgM;1vl-F3_<%P^ z=8XA>L478}xC=X7S3|g&F(xDi+Xd?(L%x!(IP4m7Ac*2Ck;K&IkQ=QNN^U-X|LKhT>14p!{fq^IX0RV zNHXF*BY!e-KY%T|k0>eBzmEfBljfEwxqjcrG?V_Lf%Cz(4Q(?)R?6$u@cH!}J61paiQ>or&@!AuRTZLiEowhvmY-zV#46dmPntB8;9dGg3=sEK1t8wN_>dNK`+74z` zEkE*a#%)+OR3-7Yr7m~0wHwe5g!#((W|;M}v05y$(!~feRP!fmTSqihCx0Ec8lKf_ zv3mTO*6|HH?ma?b#Q{Tt7vTxa--dex(X7eC{`pku`m&JWh-Gw21Fx;csFbCvWSatQ zh-|)e@q9{jVnyuL7c@s~0*ZL(zpv_jZ`zG8k$st{O)F)3W58cS(ccLGZ6xH$_Tb1s z&vm-6@cuQX-G$+QUt6s_?x%0^G2K@#3lCHffS;%LRw%~cdafalgu@~jb8BJ?QLA4* z3}eDpz3)0P|9jIGAAn>FtC7wC@4R_o=6Va_=O8wm}X0 zpX4aK9ae;}eVbuJ=S+%zAs&z7wpaM#Mo*l~QlmP?Oa_El^;z#ETD}$*X_e71&z#88 zqC6w8=5-Eo0wQ6cBs=Rua*{#I{pUI}C5DJ54dy#$!joFIMI;Yg?VkR)`+V%W-lFm| zQk#7vRe7%Ca&T*_U(_X0s^O+B@xGkzri8|cKX3m=O&ilYgvmtx(uaaS-ioCTw&aP? zxq^nM*N+3Yk9KW~bIpNtGlGoWp(+MBn#SF!k6m6`!9B89U+lFz&1Fs)G-kZE`D-=t zE8B&*`1uCt-amHs)sD6IC_ZYVdy=5qds6wSZq_ve8|gNodLJDFa3F%6?5~z zg>}4pKX<3$aC~y(2Kz**%&}r&mD4U6W9gFJCfBm+yiEq1;Qtf9WQS54kr zv}TRq70Ozzc<`~z4otm1ramOto|tVSRJI-3Y~;Ox)UaY?lbZb_a6s<6412D#_rATOPOu z0_nhT{N~%WqjH!}JHR$zkef%jLEBGWkbw?STZ163Rgq}Op%+E5WE+K%-QMeYXJ?1S zfG)ybeg3J-#hRs}%g7`Brot17r=8Jn8D&MNin+OIu_(ee0}O@%OZ}!}VuBv;q_NRE zCss)2*bA~$7GpPSzOAQDcY)-V2wYDnZKqTzn9a$t`ib|(k9I~CprfZESCO3iH+~A; zDutz&;iazlOf;bBxxaprk?M~vSq^UsE|7$=9B33t@1;C(wlCX+rAxt=Tj(1sqX0V> z9!pafv6Wyeg2ag6V^@C=aRLe=eygW&=Bh*^4X6LJx$45+bVl@lhf0;e6fdLLwP1}s za{$jo+3Rq+Q=X}eQ&%4-6vCP1##}+*Uq`XLxr_l7!zgo{z?WPWF8|xPlF1<7z)LcC zCftYQ`Am4=Ek1~WSp2UFP!Jw) zVr{@-+hQtkRk#WroR%7bJbnD9C-6Qf2n~ee6ce1qSNv?uEy>xEOb5E>vesh}G3^k8 zxf?(b;f1k|9BI6hzOjxzuY_|~#T&zQ4=>iDM(sUP_`uWA3^@Y-9ICRsk=h^~UXvWb zHHV>r3mtPJxAkK0RW~kVM%9!*gcRI1b9hXj_fAg87%O`KGDoZAEE0S;HRK!Oc)#mP zA}YU4x>29}X?gQqSGJ4mFCFtq>na`W>#TCF?hj*aZHuZ$f6He0jLTxzx3TaBdv1d4 zQ?O}TCUa~rt9~}wXUv?j}>?nVS!shsJMa_Id~K`cuL%Svy~Hdpm+orFLvO3K&eWiB?pMIo4qCQW ze+}ggD}@}rzu2~_!M?9T-Jg-| zQ~XOYa6{qpjEXFjmM;E(msa!3nbE%+ z$7CnNGWQeAR)D>bpW>)i0*%w<=JKG9bM7OpB4~9-mF}{raRIoyn}cd8kpHwJcPXBA zfuZ3l(NJZAr(}9<?T0S(xSGfD!m|vQx5c8Ihad(YL;fjfQ8>qg@Ol{c7nV^q%zhVNH1pNNAzCh1M z;>;~8o(sy`s$@%nw ziKPi;k(AMDhv68*{FD4o#)7{^A9+eNIY}|rqBH6mnvgR#&bNxlyRbBbJpkEiOpkx2 z)~7SRUMH2W#UH>FcsSd=NPqYpPhJmYnGZ7RE0@H92&*)hUz<*-_k(rb`)Rxa1|6e* z@r+3VmQ)GwNKEtjB(*_onH^|!g!=>4oA88vM!2zdP`FQtC@G4|MA@s&XHt;Hg5P76 z9Wj(Fq+0LYbI(2m5T?J7vCg|>m3xF`p6kwu%>WM_-Y&2Ob~RQll;nCGMVb*N*j6Gh z*J;7ufxQGAm?G2j()$Og0%g3T!t}N8KXFtaG{Myy{&3isyRhje@2{#-e=H5bQHc0q zHALazRI2EX<){3EA+Iw-))M>b0ITGgx#$5qQNO=XAKa7)@VZO8Kr7SZ871jb*bvU%os@!4P=zN(5Za@)ink4J1AivpPlK}69u!?Pj zT*oSzD-W Date: Sat, 6 May 2023 00:05:23 +0000 Subject: [PATCH 58/63] Update README.md --- README.md | 26 +++++++++++++------------- ml_pmc/README.md | 4 ++++ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index f8586f3..ce2828b 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ Merged set of MelonLoader mods for ChilloutVR. **State table for game build 2022r170p1:** -| Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes | -|-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------| -| Avatar Change Info | ml_aci | 1.0.3 | Retired | Retired | Superseded by `Extended Game Notifications` -| Avatar Motion Tweaker | ml_amt | 1.2.8 | Yes, update review | Working | -| Desktop Head Tracking | ml_dht | 1.1.3 | Yes | Working | -| Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | -| Extended Game Notifications | ml_egn | 1.0.2 | Yes | Working -| Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update -| Leap Motion Extension | ml_lme | 1.3.6 | Yes | Working | -| Pickup Arm Movement | ml_pam | 1.0.4 | Yes | Working | -| Player Movement Copycat | ml_pmc | 1.0.0 | On review | Working | -| Player Ragdoll Mod | ml_prm | 1.0.4 | Yes, update review | Working | -| Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` +| Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Notes | +|:---------:|:----------:|:--------------:| :----------------------------------------------------------------|-------| +| Avatar Change Info | ml_aci | 1.0.3 | ✔ Yes
⭕ **Retired** | Superseded by `Extended Game Notifications` +| Avatar Motion Tweaker | ml_amt | 1.2.8 | ✔ Yes
⏱ Update review | +| Desktop Head Tracking | ml_dht | 1.1.3 | ✔ Yes | +| Desktop Reticle Switch | ml_drs | 1.0.0 | ✔ Yes | +| Extended Game Notifications | ml_egn | 1.0.2 | ✔ Yes | +| Four Point Tracking | ml_fpt | 1.0.9 | ✔ Yes
⭕ **Retired** | In-game feature since 2022r170 update +| Leap Motion Extension | ml_lme | 1.3.6 | ✔ Yes | +| Pickup Arm Movement | ml_pam | 1.0.4 | ✔ Yes | +| Player Movement Copycat | ml_pmc | 1.0.0 | ⏱ On review | +| Player Ragdoll Mod | ml_prm | 1.0.4 | ✔ Yes
⏱ Update review | +| Server Connection Info | ml_sci | 1.0.2 | ✔ Yes
⭕ **Retired** | Superseded by `Extended Game Notifications` diff --git a/ml_pmc/README.md b/ml_pmc/README.md index 1f02e47..920db7a 100644 --- a/ml_pmc/README.md +++ b/ml_pmc/README.md @@ -19,3 +19,7 @@ Available options in BTKUILib players list upon player selection: * **Mirror pose:** enables/disables pose and gestures mirroring; `false` by default. * **Mirror position:** enables/disables mirroring of position changes of selected player along 0XZ plane; `false` by default. * **Mirror rotation:** enables/disables mirroring of rotation changes of selected player along 0XZ plane; `false` by default. + +# Notes +* Some avatars can have unordinary avatar hierarchy (scaled, rotated or with offset armature/parent objects). Possible fixes are being made upon reports or own findings. +* Currently misbehaves with FBT, fix in progress. From e73dd54e7b983eeba6dfbc38b3836e889e9c07f2 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sun, 7 May 2023 20:42:52 +0300 Subject: [PATCH 59/63] Scaled jump Minor changes --- ml_amt/{ => Fixes}/AnimatorAnalyzer.cs | 2 +- ml_amt/Fixes/AnimatorOverrideControllerFix.cs | 60 ++++++ ml_amt/Fixes/FBTDetectionFix.cs | 57 +++++ ml_amt/Fixes/MovementJumpFix.cs | 114 ++++++++++ ml_amt/Fixes/PlayerColliderFix.cs | 123 +++++++++++ ml_amt/Main.cs | 199 +----------------- ml_amt/MotionTweaker.cs | 8 +- ml_amt/Settings.cs | 45 ++-- ml_amt/Utils.cs | 24 ++- ml_amt/ml_amt.csproj | 6 +- ml_amt/resources/menu.js | 13 +- 11 files changed, 435 insertions(+), 216 deletions(-) rename ml_amt/{ => Fixes}/AnimatorAnalyzer.cs (99%) create mode 100644 ml_amt/Fixes/AnimatorOverrideControllerFix.cs create mode 100644 ml_amt/Fixes/FBTDetectionFix.cs create mode 100644 ml_amt/Fixes/MovementJumpFix.cs create mode 100644 ml_amt/Fixes/PlayerColliderFix.cs diff --git a/ml_amt/AnimatorAnalyzer.cs b/ml_amt/Fixes/AnimatorAnalyzer.cs similarity index 99% rename from ml_amt/AnimatorAnalyzer.cs rename to ml_amt/Fixes/AnimatorAnalyzer.cs index 80c4531..36900f8 100644 --- a/ml_amt/AnimatorAnalyzer.cs +++ b/ml_amt/Fixes/AnimatorAnalyzer.cs @@ -2,7 +2,7 @@ using System.Linq; using UnityEngine; -namespace ml_amt +namespace ml_amt.Fixes { class AnimatorAnalyzer { diff --git a/ml_amt/Fixes/AnimatorOverrideControllerFix.cs b/ml_amt/Fixes/AnimatorOverrideControllerFix.cs new file mode 100644 index 0000000..d375d51 --- /dev/null +++ b/ml_amt/Fixes/AnimatorOverrideControllerFix.cs @@ -0,0 +1,60 @@ +using ABI_RC.Core; +using System; +using System.Reflection; + +namespace ml_amt.Fixes +{ + static class AnimatorOverrideControllerFix + { + internal static void Init(HarmonyLib.Harmony p_instance) + { + // AAS overriding fix + p_instance.Patch( + typeof(CVRAnimatorManager).GetMethod(nameof(CVRAnimatorManager.SetOverrideAnimation)), + new HarmonyLib.HarmonyMethod(typeof(AnimatorOverrideControllerFix).GetMethod(nameof(OnOverride_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + new HarmonyLib.HarmonyMethod(typeof(AnimatorOverrideControllerFix).GetMethod(nameof(OnOverride_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + p_instance.Patch( + typeof(CVRAnimatorManager).GetMethod(nameof(CVRAnimatorManager.RestoreOverrideAnimation)), + new HarmonyLib.HarmonyMethod(typeof(AnimatorOverrideControllerFix).GetMethod(nameof(OnOverride_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + new HarmonyLib.HarmonyMethod(typeof(AnimatorOverrideControllerFix).GetMethod(nameof(OnOverride_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + } + + // AnimatorOverrideController runtime animation replacement fix + static void OnOverride_Prefix(ref CVRAnimatorManager __instance, out AnimatorAnalyzer __state) + { + __state = new AnimatorAnalyzer(); + try + { + if(Settings.OverrideFix && (__instance.animator != null)) + { + __state.AnalyzeFrom(__instance.animator); + if(__state.IsEnabled()) + __instance.animator.enabled = false; + __instance.animator.WriteDefaultValues(); + } + } + catch(Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } + } + static void OnOverride_Postfix(ref CVRAnimatorManager __instance, AnimatorAnalyzer __state) + { + try + { + if(Settings.OverrideFix && (__instance.animator != null)) + { + __state.ApplyTo(__instance.animator); + if(__state.IsEnabled()) + __instance.animator.Update(0f); + } + } + catch(Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } + } + } +} diff --git a/ml_amt/Fixes/FBTDetectionFix.cs b/ml_amt/Fixes/FBTDetectionFix.cs new file mode 100644 index 0000000..0dbb6e4 --- /dev/null +++ b/ml_amt/Fixes/FBTDetectionFix.cs @@ -0,0 +1,57 @@ +using ABI.CCK.Components; +using ABI_RC.Core.Player; +using ABI_RC.Systems.IK.SubSystems; +using System.Reflection; + +namespace ml_amt.Fixes +{ + static class FBTDetectionFix + { + static readonly MethodInfo[] ms_fbtDetouredMethods = + { + typeof(PlayerSetup).GetMethod("Update", BindingFlags.NonPublic | BindingFlags.Instance), + typeof(PlayerSetup).GetMethod("FixedUpdate", BindingFlags.NonPublic | BindingFlags.Instance), + typeof(PlayerSetup).GetMethod("UpdatePlayerAvatarMovementData", BindingFlags.NonPublic | BindingFlags.Instance), + typeof(CVRParameterStreamEntry).GetMethod(nameof(CVRParameterStreamEntry.CheckUpdate)) + }; + + static bool ms_fbtDetour = false; + + internal static void Init(HarmonyLib.Harmony p_instance) + { + // FBT detour + p_instance.Patch( + typeof(BodySystem).GetMethod(nameof(BodySystem.FBTAvailable)), + new HarmonyLib.HarmonyMethod(typeof(FBTDetectionFix).GetMethod(nameof(OnFBTAvailable_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + null + ); + foreach(MethodInfo l_detoured in ms_fbtDetouredMethods) + { + p_instance.Patch( + l_detoured, + new HarmonyLib.HarmonyMethod(typeof(FBTDetectionFix).GetMethod(nameof(FBTDetour_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + new HarmonyLib.HarmonyMethod(typeof(FBTDetectionFix).GetMethod(nameof(FBTDetour_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + } + } + + // FBT detection override + static void FBTDetour_Prefix() + { + ms_fbtDetour = true; + } + static void FBTDetour_Postfix() + { + ms_fbtDetour = false; + } + static bool OnFBTAvailable_Prefix(ref bool __result) + { + if(ms_fbtDetour && !BodySystem.isCalibratedAsFullBody) + { + __result = false; + return false; + } + return true; + } + } +} diff --git a/ml_amt/Fixes/MovementJumpFix.cs b/ml_amt/Fixes/MovementJumpFix.cs new file mode 100644 index 0000000..df18bc5 --- /dev/null +++ b/ml_amt/Fixes/MovementJumpFix.cs @@ -0,0 +1,114 @@ +using ABI.CCK.Components; +using ABI_RC.Core.Player; +using ABI_RC.Core.Savior; +using ABI_RC.Systems.MovementSystem; +using System; +using System.Collections; +using System.Reflection; +using UnityEngine; + +namespace ml_amt.Fixes +{ + static class MovementJumpFix + { + static FieldInfo ms_avatarHeight = typeof(PlayerSetup).GetField("_avatarHeight", BindingFlags.NonPublic | BindingFlags.Instance); + + static float ms_playerHeight = 1f; + + internal static void Init(HarmonyLib.Harmony p_instance) + { + p_instance.Patch( + typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)), + null, + new HarmonyLib.HarmonyMethod(typeof(MovementJumpFix).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + p_instance.Patch( + typeof(CVRWorld).GetMethod("SetupWorldRules", BindingFlags.NonPublic | BindingFlags.Instance), + null, + new HarmonyLib.HarmonyMethod(typeof(MovementJumpFix).GetMethod(nameof(OnWorldRulesSetup_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + p_instance.Patch( + typeof(PlayerSetup).GetMethod("SetupIKScaling", BindingFlags.NonPublic | BindingFlags.Instance), + null, + new HarmonyLib.HarmonyMethod(typeof(MovementJumpFix).GetMethod(nameof(OnSetupIKScaling_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + + Settings.ScaledJumpChange += OnScaledJumpChange; + MelonLoader.MelonCoroutines.Start(WaitForGameSettings()); + } + + static IEnumerator WaitForGameSettings() + { + while(MetaPort.Instance == null) + yield return null; + while(MetaPort.Instance.settings == null) + yield return null; + + ms_playerHeight = MetaPort.Instance.settings.GetSettingInt("GeneralPlayerHeight") * 0.01f; + MetaPort.Instance.settings.settingIntChanged.AddListener(OnGameSettingIntChange); + } + + // Patches + static void OnSetupAvatar_Postfix() + { + try + { + SetScaledJump(Settings.ScaledJump); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + static void OnWorldRulesSetup_Postfix() + { + try + { + SetScaledJump(Settings.ScaledJump); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + static void OnSetupIKScaling_Postfix() + { + try + { + SetScaledJump(Settings.ScaledJump); + } + catch(Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } + } + + // Mod settings + static void OnScaledJumpChange(bool p_state) + { + SetScaledJump(p_state); + } + + // Game settings + static void OnGameSettingIntChange(string p_name, int p_value) + { + if(p_name == "GeneralPlayerHeight") + { + ms_playerHeight = p_value * 0.01f; + } + } + + // Arbitrary + static void SetScaledJump(bool p_state) + { + if(Utils.IsWorldSafe()) + { + if(p_state) + MovementSystem.Instance.jumpHeight = Mathf.Clamp(Utils.GetWorldJumpHeight() * ((float)ms_avatarHeight.GetValue(PlayerSetup.Instance) / ms_playerHeight), float.MinValue, Utils.GetWorldMovementLimit()); + else + MovementSystem.Instance.jumpHeight = Utils.GetWorldJumpHeight(); + } + } + } +} diff --git a/ml_amt/Fixes/PlayerColliderFix.cs b/ml_amt/Fixes/PlayerColliderFix.cs new file mode 100644 index 0000000..64eb722 --- /dev/null +++ b/ml_amt/Fixes/PlayerColliderFix.cs @@ -0,0 +1,123 @@ +using ABI_RC.Core.Player; +using ABI_RC.Systems.MovementSystem; +using System; +using System.Reflection; +using UnityEngine; + +namespace ml_amt.Fixes +{ + static class PlayerColliderFix + { + static FieldInfo ms_initialAvatarHeight = typeof(PlayerSetup).GetField("_initialAvatarHeight", BindingFlags.NonPublic | BindingFlags.Instance); + static FieldInfo ms_avatarHeight = typeof(PlayerSetup).GetField("_avatarHeight", BindingFlags.NonPublic | BindingFlags.Instance); + + internal static void Init(HarmonyLib.Harmony p_instance) + { + // Alternative collider height and radius + p_instance.Patch( + typeof(MovementSystem).GetMethod("UpdateCollider", BindingFlags.NonPublic | BindingFlags.Instance), + new HarmonyLib.HarmonyMethod(typeof(PlayerColliderFix).GetMethod(nameof(OnUpdateCollider_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), + null + ); + p_instance.Patch( + typeof(PlayerSetup).GetMethod("SetupIKScaling", BindingFlags.NonPublic | BindingFlags.Instance), + null, + new HarmonyLib.HarmonyMethod(typeof(PlayerColliderFix).GetMethod(nameof(OnSetupIKScaling_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) + ); + + Settings.CollisionScaleChange += OnCollisionScaleChange; + } + + // Alternative collider size + static bool OnUpdateCollider_Prefix( + ref MovementSystem __instance, + bool __0, // updateRadius + CharacterController ___controller, + float ____avatarHeight, + float ____avatarHeightFactor, + float ____minimumColliderRadius, + Vector3 ____colliderCenter + ) + { + if(!Settings.CollisionScale) + return true; + + try + { + if(___controller != null) + { + float l_scaledHeight = ____avatarHeight * ____avatarHeightFactor; + float l_newRadius = (__0 ? Mathf.Max(____minimumColliderRadius, l_scaledHeight / 6f) : ___controller.radius); + + float l_newHeight = Mathf.Max(l_scaledHeight, l_newRadius * 2f); + float l_currentHeight = ___controller.height; + + Vector3 l_newCenter = ____colliderCenter; + l_newCenter.y = (l_newHeight + 0.075f) * 0.5f; // Idk where 0.075f has come from + Vector3 l_currentCenter = ___controller.center; + + if(__0 || (Mathf.Abs(l_currentHeight - l_newHeight) > (l_currentHeight * 0.05f)) || (Vector3.Distance(l_currentCenter, l_newCenter) > (l_currentHeight * 0.05f))) + { + if(__0) + ___controller.radius = l_newRadius; + ___controller.height = l_newHeight; + ___controller.center = l_newCenter; + + __instance.groundDistance = l_newRadius; + + if(__instance.proxyCollider != null) + { + if(__0) + __instance.proxyCollider.radius = l_newRadius; + __instance.proxyCollider.height = l_newHeight; + __instance.proxyCollider.center = new Vector3(0f, l_newCenter.y, 0f); + } + + if(__instance.forceObject != null) + __instance.forceObject.transform.localScale = new Vector3(l_newRadius + 0.1f, l_newHeight, l_newRadius + 0.1f); + if(__instance.groundCheck != null) + __instance.groundCheck.localPosition = ____colliderCenter; + } + } + } + catch(Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } + + return false; + } + static void OnSetupIKScaling_Postfix( + ref PlayerSetup __instance, + float ____avatarHeight + ) + { + if(!Settings.CollisionScale) + return; + + try + { + __instance._movementSystem.UpdateAvatarHeight(Mathf.Clamp(____avatarHeight, 0.05f, float.MaxValue), true); + } + catch(Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } + } + + static void OnCollisionScaleChange(bool p_state) + { + try + { + if(p_state) + MovementSystem.Instance.UpdateAvatarHeight((float)ms_avatarHeight.GetValue(PlayerSetup.Instance), true); + else + MovementSystem.Instance.UpdateAvatarHeight((float)ms_initialAvatarHeight.GetValue(PlayerSetup.Instance), true); + } + catch(Exception l_exception) + { + MelonLoader.MelonLogger.Error(l_exception); + } + } + } +} diff --git a/ml_amt/Main.cs b/ml_amt/Main.cs index 6db0fdd..cafb02a 100644 --- a/ml_amt/Main.cs +++ b/ml_amt/Main.cs @@ -1,30 +1,18 @@ using ABI.CCK.Components; -using ABI_RC.Core; using ABI_RC.Core.Player; using ABI_RC.Systems.IK.SubSystems; -using ABI_RC.Systems.MovementSystem; +using System; using System.Collections; using System.Reflection; -using UnityEngine; namespace ml_amt { public class AvatarMotionTweaker : MelonLoader.MelonMod { - static readonly MethodInfo[] ms_fbtDetouredMethods = - { - typeof(PlayerSetup).GetMethod("Update", BindingFlags.NonPublic | BindingFlags.Instance), - typeof(PlayerSetup).GetMethod("FixedUpdate", BindingFlags.NonPublic | BindingFlags.Instance), - typeof(PlayerSetup).GetMethod("UpdatePlayerAvatarMovementData", BindingFlags.NonPublic | BindingFlags.Instance), - typeof(CVRParameterStreamEntry).GetMethod(nameof(CVRParameterStreamEntry.CheckUpdate)) - }; - static AvatarMotionTweaker ms_instance = null; MotionTweaker m_localTweaker = null; - static bool ms_fbtDetour = false; - public override void OnInitializeMelon() { if(ms_instance == null) @@ -52,45 +40,13 @@ namespace ml_amt null, new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnPlayspaceScale_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) ); + - // FBT detour - HarmonyInstance.Patch( - typeof(BodySystem).GetMethod(nameof(BodySystem.FBTAvailable)), - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnFBTAvailable_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), - null - ); - foreach(MethodInfo l_detoured in ms_fbtDetouredMethods) - { - HarmonyInstance.Patch( - l_detoured, - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(FBTDetour_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(FBTDetour_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - } - - // Alternative collider height and radius - HarmonyInstance.Patch( - typeof(MovementSystem).GetMethod("UpdateCollider", BindingFlags.NonPublic | BindingFlags.Instance), - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnUpdateCollider_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), - null - ); - HarmonyInstance.Patch( - typeof(PlayerSetup).GetMethod("SetupIKScaling", BindingFlags.NonPublic | BindingFlags.Instance), - null, - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnSetupIKScaling_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - // AAS overriding fix - HarmonyInstance.Patch( - typeof(CVRAnimatorManager).GetMethod(nameof(CVRAnimatorManager.SetOverrideAnimation)), - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnOverride_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnOverride_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - HarmonyInstance.Patch( - typeof(CVRAnimatorManager).GetMethod(nameof(CVRAnimatorManager.RestoreOverrideAnimation)), - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnOverride_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), - new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnOverride_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); + // Fixes + Fixes.AnimatorOverrideControllerFix.Init(HarmonyInstance); + Fixes.FBTDetectionFix.Init(HarmonyInstance); + Fixes.PlayerColliderFix.Init(HarmonyInstance); + Fixes.MovementJumpFix.Init(HarmonyInstance); ModSupporter.Init(); MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); @@ -130,7 +86,7 @@ namespace ml_amt if(m_localTweaker != null) m_localTweaker.OnAvatarClear(); } - catch(System.Exception l_exception) + catch(Exception l_exception) { MelonLoader.MelonLogger.Error(l_exception); } @@ -144,7 +100,7 @@ namespace ml_amt if(m_localTweaker != null) m_localTweaker.OnSetupAvatar(); } - catch(System.Exception l_exception) + catch(Exception l_exception) { MelonLoader.MelonLogger.Error(l_exception); } @@ -158,7 +114,7 @@ namespace ml_amt if(m_localTweaker != null) m_localTweaker.OnCalibrate(); } - catch(System.Exception l_exception) + catch(Exception l_exception) { MelonLoader.MelonLogger.Error(l_exception); } @@ -172,140 +128,7 @@ namespace ml_amt if(m_localTweaker != null) m_localTweaker.OnPlayspaceScale(); } - catch(System.Exception l_exception) - { - MelonLoader.MelonLogger.Error(l_exception); - } - } - - // FBT detection override - static void FBTDetour_Prefix() - { - ms_fbtDetour = true; - } - static void FBTDetour_Postfix() - { - ms_fbtDetour = false; - } - static bool OnFBTAvailable_Prefix(ref bool __result) - { - if(ms_fbtDetour && !BodySystem.isCalibratedAsFullBody) - { - __result = false; - return false; - } - - return true; - } - - // Alternative collider size - static bool OnUpdateCollider_Prefix( - ref MovementSystem __instance, - bool __0, // updateRadius - CharacterController ___controller, - float ____avatarHeight, - float ____avatarHeightFactor, - float ____minimumColliderRadius, - Vector3 ____colliderCenter - ) - { - if(!Settings.CollisionScale) - return true; - - try - { - if(___controller != null) - { - float l_scaledHeight = ____avatarHeight * ____avatarHeightFactor; - float l_newRadius = (__0 ? Mathf.Max(____minimumColliderRadius, l_scaledHeight / 6f) : ___controller.radius); - - float l_newHeight = Mathf.Max(l_scaledHeight, l_newRadius * 2f); - float l_currentHeight = ___controller.height; - - Vector3 l_newCenter = ____colliderCenter; - l_newCenter.y = (l_newHeight + 0.075f) * 0.5f; // Idk where 0.075f has come from - Vector3 l_currentCenter = ___controller.center; - - if(__0 || (Mathf.Abs(l_currentHeight - l_newHeight) > (l_currentHeight * 0.05f)) || (Vector3.Distance(l_currentCenter, l_newCenter) > (l_currentHeight * 0.05f))) - { - if(__0) - ___controller.radius = l_newRadius; - ___controller.height = l_newHeight; - ___controller.center = l_newCenter; - - __instance.groundDistance = l_newRadius; - - if(__instance.proxyCollider != null) - { - if(__0) - __instance.proxyCollider.radius = l_newRadius; - __instance.proxyCollider.height = l_newHeight; - __instance.proxyCollider.center = new Vector3(0f, l_newCenter.y, 0f); - } - - if(__instance.forceObject != null) - __instance.forceObject.transform.localScale = new Vector3(l_newRadius + 0.1f, l_newHeight, l_newRadius + 0.1f); - if(__instance.groundCheck != null) - __instance.groundCheck.localPosition = ____colliderCenter; - } - } - } - catch(System.Exception l_exception) - { - MelonLoader.MelonLogger.Error(l_exception); - } - - return false; - } - static void OnSetupIKScaling_Postfix( - ref PlayerSetup __instance, - float ____avatarHeight - ) - { - if(!Settings.CollisionScale) - return; - - try - { - __instance._movementSystem.UpdateAvatarHeight(Mathf.Clamp(____avatarHeight, 0.05f, float.MaxValue), true); - } - catch(System.Exception l_exception) - { - MelonLoader.MelonLogger.Error(l_exception); - } - } - - // AnimatorOverrideController runtime animation replacement fix - static void OnOverride_Prefix(ref CVRAnimatorManager __instance, out AnimatorAnalyzer __state) - { - __state = new AnimatorAnalyzer(); - try - { - if(Settings.OverrideFix && (__instance.animator != null)) - { - __state.AnalyzeFrom(__instance.animator); - if(__state.IsEnabled()) - __instance.animator.enabled = false; - __instance.animator.WriteDefaultValues(); - } - } - catch(System.Exception l_exception) - { - MelonLoader.MelonLogger.Error(l_exception); - } - } - static void OnOverride_Postfix(ref CVRAnimatorManager __instance, AnimatorAnalyzer __state) - { - try - { - if(Settings.OverrideFix && (__instance.animator != null)) - { - __state.ApplyTo(__instance.animator); - if(__state.IsEnabled()) - __instance.animator.Update(0f); - } - } - catch(System.Exception l_exception) + catch(Exception l_exception) { MelonLoader.MelonLogger.Error(l_exception); } diff --git a/ml_amt/MotionTweaker.cs b/ml_amt/MotionTweaker.cs index a02bf7c..7fabdcb 100644 --- a/ml_amt/MotionTweaker.cs +++ b/ml_amt/MotionTweaker.cs @@ -32,7 +32,7 @@ namespace ml_amt bool m_bendNormalLeft = false; bool m_bendNormalRight = false; Transform m_avatarHips = null; - float m_viewPointHeight = 1f; + float m_avatarHeight = 1f; // Initial avatar view height bool m_inVR = false; bool m_fbtAnimations = true; @@ -124,7 +124,7 @@ namespace ml_amt // Update upright Matrix4x4 l_hmdMatrix = PlayerSetup.Instance.transform.GetMatrix().inverse * PlayerSetup.Instance.GetActiveCamera().transform.GetMatrix(); float l_currentHeight = Mathf.Clamp((l_hmdMatrix * ms_pointVector).y, 0f, float.MaxValue); - float l_avatarViewHeight = Mathf.Clamp(m_viewPointHeight * GetRelativeScale(), 0f, float.MaxValue); + float l_avatarViewHeight = Mathf.Clamp(m_avatarHeight * GetRelativeScale(), 0f, float.MaxValue); m_upright = Mathf.Clamp01((l_avatarViewHeight > 0f) ? (l_currentHeight / l_avatarViewHeight) : 0f); m_poseState = (m_upright <= Mathf.Min(m_proneLimit, m_crouchLimit)) ? PoseState.Proning : ((m_upright <= Mathf.Max(m_proneLimit, m_crouchLimit)) ? PoseState.Crouching : PoseState.Standing); @@ -189,7 +189,7 @@ namespace ml_amt m_locomotionOverride = false; m_hipsToPlayer = Vector3.zero; m_avatarHips = null; - m_viewPointHeight = 1f; + m_avatarHeight = 1f; m_massCenter = Vector3.zero; m_stepDistance = Vector2.zero; m_parameters.Clear(); @@ -201,7 +201,7 @@ namespace ml_amt m_vrIk = PlayerSetup.Instance._avatar.GetComponent(); m_locomotionLayer = PlayerSetup.Instance._animator.GetLayerIndex("Locomotion/Emotes"); m_avatarHips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips); - m_viewPointHeight = PlayerSetup.Instance._avatar.GetComponent().viewPosition.y; + m_avatarHeight = PlayerSetup.Instance._avatar.GetComponent().viewPosition.y; // Parse animator parameters m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Upright, PlayerSetup.Instance.animatorManager)); diff --git a/ml_amt/Settings.cs b/ml_amt/Settings.cs index 6f60289..0f54401 100644 --- a/ml_amt/Settings.cs +++ b/ml_amt/Settings.cs @@ -21,6 +21,7 @@ namespace ml_amt FollowHips, CollisionScale, ScaledSteps, + ScaledJump, MassCenter, OverrideFix }; @@ -37,6 +38,7 @@ namespace ml_amt public static bool FollowHips { get; private set; } = true; public static bool MassCenter { get; private set; } = true; public static bool ScaledSteps { get; private set; } = true; + public static bool ScaledJump { get; private set; } = false; public static bool CollisionScale { get; private set; } = true; public static bool OverrideFix { get; private set; } = true; @@ -55,6 +57,7 @@ namespace ml_amt static public event Action FollowHipsChange; static public event Action MassCenterChange; static public event Action ScaledStepsChange; + static public event Action ScaledJumpChange; static public event Action CollisionScaleChange; static public event Action OverrideFixChange; @@ -76,11 +79,26 @@ namespace ml_amt ms_category.CreateEntry(ModSetting.FollowHips.ToString(), FollowHips), ms_category.CreateEntry(ModSetting.MassCenter.ToString(), MassCenter), ms_category.CreateEntry(ModSetting.ScaledSteps.ToString(), ScaledSteps), + ms_category.CreateEntry(ModSetting.ScaledJump.ToString(), ScaledJump), ms_category.CreateEntry(ModSetting.CollisionScale.ToString(), CollisionScale), ms_category.CreateEntry(ModSetting.OverrideFix.ToString(), OverrideFix) }; - Load(); + IKOverrideCrouch = (bool)ms_entries[(int)ModSetting.IKOverrideCrouch].BoxedValue; + CrouchLimit = ((int)ms_entries[(int)ModSetting.CrouchLimit].BoxedValue) * 0.01f; + IKOverrideProne = (bool)ms_entries[(int)ModSetting.IKOverrideProne].BoxedValue; + ProneLimit = ((int)ms_entries[(int)ModSetting.ProneLimit].BoxedValue) * 0.01f; + PoseTransitions = (bool)ms_entries[(int)ModSetting.PoseTransitions].BoxedValue; + AdjustedMovement = (bool)ms_entries[(int)ModSetting.AdjustedMovement].BoxedValue; + IKOverrideFly = (bool)ms_entries[(int)ModSetting.IKOverrideFly].BoxedValue; + IKOverrideJump = (bool)ms_entries[(int)ModSetting.IKOverrideJump].BoxedValue; + DetectEmotes = (bool)ms_entries[(int)ModSetting.DetectEmotes].BoxedValue; + FollowHips = (bool)ms_entries[(int)ModSetting.FollowHips].BoxedValue; + MassCenter = (bool)ms_entries[(int)ModSetting.MassCenter].BoxedValue; + ScaledSteps = (bool)ms_entries[(int)ModSetting.ScaledSteps].BoxedValue; + ScaledJump = (bool)ms_entries[(int)ModSetting.ScaledJump].BoxedValue; + CollisionScale = (bool)ms_entries[(int)ModSetting.CollisionScale].BoxedValue; + OverrideFix = (bool)ms_entries[(int)ModSetting.OverrideFix].BoxedValue; MelonLoader.MelonCoroutines.Start(WaitMainMenuUi()); } @@ -107,24 +125,6 @@ namespace ml_amt }; } - static void Load() - { - IKOverrideCrouch = (bool)ms_entries[(int)ModSetting.IKOverrideCrouch].BoxedValue; - CrouchLimit = ((int)ms_entries[(int)ModSetting.CrouchLimit].BoxedValue) * 0.01f; - IKOverrideProne = (bool)ms_entries[(int)ModSetting.IKOverrideProne].BoxedValue; - ProneLimit = ((int)ms_entries[(int)ModSetting.ProneLimit].BoxedValue) * 0.01f; - PoseTransitions = (bool)ms_entries[(int)ModSetting.PoseTransitions].BoxedValue; - AdjustedMovement = (bool)ms_entries[(int)ModSetting.AdjustedMovement].BoxedValue; - IKOverrideFly = (bool)ms_entries[(int)ModSetting.IKOverrideFly].BoxedValue; - IKOverrideJump = (bool)ms_entries[(int)ModSetting.IKOverrideJump].BoxedValue; - DetectEmotes = (bool)ms_entries[(int)ModSetting.DetectEmotes].BoxedValue; - FollowHips = (bool)ms_entries[(int)ModSetting.FollowHips].BoxedValue; - MassCenter = (bool)ms_entries[(int)ModSetting.MassCenter].BoxedValue; - ScaledSteps = (bool)ms_entries[(int)ModSetting.ScaledSteps].BoxedValue; - CollisionScale = (bool)ms_entries[(int)ModSetting.CollisionScale].BoxedValue; - OverrideFix = (bool)ms_entries[(int)ModSetting.OverrideFix].BoxedValue; - } - static void OnSliderUpdate(string p_name, string p_value) { if(Enum.TryParse(p_name, out ModSetting l_setting)) @@ -226,6 +226,13 @@ namespace ml_amt } break; + case ModSetting.ScaledJump: + { + ScaledJump = bool.Parse(p_value); + ScaledJumpChange?.Invoke(ScaledJump); + } + break; + case ModSetting.CollisionScale: { CollisionScale = bool.Parse(p_value); diff --git a/ml_amt/Utils.cs b/ml_amt/Utils.cs index 0024fe9..5af342a 100644 --- a/ml_amt/Utils.cs +++ b/ml_amt/Utils.cs @@ -1,4 +1,5 @@ -using ABI_RC.Systems.MovementSystem; +using ABI.CCK.Components; +using ABI_RC.Systems.MovementSystem; using RootMotion.FinalIK; using System.Reflection; using UnityEngine; @@ -23,6 +24,27 @@ namespace ml_amt return (Keyframe[])ms_getSineKeyframes.Invoke(null, new object[] { p_mag }); } + public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying); + public static float GetWorldJumpHeight() + { + float l_result = 1f; + if(CVRWorld.Instance != null) + l_result = CVRWorld.Instance.jumpHeight; + return l_result; + } + public static float GetWorldMovementLimit() + { + float l_result = 1f; + if(CVRWorld.Instance != null) + { + l_result = CVRWorld.Instance.baseMovementSpeed; + l_result *= CVRWorld.Instance.sprintMultiplier; + l_result *= CVRWorld.Instance.inAirMovementMultiplier; + l_result *= CVRWorld.Instance.flyMultiplier; + } + return l_result; + } + // Engine extensions public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) { diff --git a/ml_amt/ml_amt.csproj b/ml_amt/ml_amt.csproj index 58d618a..19a3543 100644 --- a/ml_amt/ml_amt.csproj +++ b/ml_amt/ml_amt.csproj @@ -83,8 +83,12 @@
- + + + + + diff --git a/ml_amt/resources/menu.js b/ml_amt/resources/menu.js index 152a75c..e8fb5b3 100644 --- a/ml_amt/resources/menu.js +++ b/ml_amt/resources/menu.js @@ -263,16 +263,25 @@ function inp_toggle_mod_amt(_obj, _callbackName) {
+ +

Avatar independent game fixes/overhauls


+ +
+
Scaled locomotion jump:
+
+
+
+
-
Alternative avatar collider scale:
+
Alternative avatar collider:
-
Fix animation overrides (chairs, etc.):
+
Fix animator overrides (chairs, etc.):
From cc8f711d09759f721340c36b66390c645e0521e4 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sun, 7 May 2023 18:04:00 +0000 Subject: [PATCH 60/63] Update README.md --- ml_amt/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ml_amt/README.md b/ml_amt/README.md index e9a2eee..c3aab7b 100644 --- a/ml_amt/README.md +++ b/ml_amt/README.md @@ -29,6 +29,9 @@ Available mod's settings in `Settings - IK - Avatar Motion Tweaker`: * **Adjusted locomotion mass center:** automatically changes IK locomotion center if avatar has toe bones; default value - `true`. * Note: Compatible with [DesktopVRIK](https://github.com/NotAKidOnSteam/DesktopVRIK) and [FuckToes](https://github.com/NotAKidOnSteam/FuckToes). * **Scaled locomotion steps:** scales VRIK locomotion steps according to avatar height and scale; default value - `true`. +#### Fixes/overhauls options +* **Scaled locomotion jump:** scales locomotion jump according to relation between your player settings height and current avatar height (includes avatar scale); default value - `false`. + * Note: Disabled in worlds that don't allow flight. * **Alternative avatar collider scale:** applies slightly different approach to avatar collider size change; default value - `true`. * **Fix animation overrides (chairs, etc.):** fixes animations overriding for avatars with AAS; default value - `true`. * Note: This option is made to address [broken animator in chairs and combat worlds issue](https://feedback.abinteractive.net/p/gestures-getting-stuck-locally-upon-entering-vehicles-chairs). From 9159946de64549f2a8f8bacb4987449a3a6316b6 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sun, 7 May 2023 21:13:47 +0300 Subject: [PATCH 61/63] Exception on exit fix --- ml_prm/RagdollController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 5324aa6..77998c1 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -171,7 +171,7 @@ namespace ml_prm // Game events internal void OnAvatarClear() { - if(m_enabled) + if(m_enabled && (MovementSystem.Instance != null)) MovementSystem.Instance.SetImmobilized(false); if(m_puppet != null) From 732b15a6a9759080cc9bc4b19fa1998353888392 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sun, 28 May 2023 16:47:04 +0300 Subject: [PATCH 62/63] Transformation fixes More checks for non-flying worlds --- README.md | 10 +++++----- ml_lme/LeapTracked.cs | 7 ------- ml_lme/Properties/AssemblyInfo.cs | 6 +++--- ml_pam/ArmMover.cs | 7 ------- ml_pam/Properties/AssemblyInfo.cs | 6 +++--- ml_prm/Main.cs | 4 ++-- ml_prm/Properties/AssemblyInfo.cs | 6 +++--- ml_prm/RagdollController.cs | 25 ++++++++++++++++++++++--- ml_prm/Utils.cs | 7 +++++-- 9 files changed, 43 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index ce2828b..667a2bb 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,13 @@ Merged set of MelonLoader mods for ChilloutVR. | Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Notes | |:---------:|:----------:|:--------------:| :----------------------------------------------------------------|-------| | Avatar Change Info | ml_aci | 1.0.3 | ✔ Yes
⭕ **Retired** | Superseded by `Extended Game Notifications` -| Avatar Motion Tweaker | ml_amt | 1.2.8 | ✔ Yes
⏱ Update review | +| Avatar Motion Tweaker | ml_amt | 1.2.8 | ✔ Yes | | Desktop Head Tracking | ml_dht | 1.1.3 | ✔ Yes | | Desktop Reticle Switch | ml_drs | 1.0.0 | ✔ Yes | | Extended Game Notifications | ml_egn | 1.0.2 | ✔ Yes | | Four Point Tracking | ml_fpt | 1.0.9 | ✔ Yes
⭕ **Retired** | In-game feature since 2022r170 update -| Leap Motion Extension | ml_lme | 1.3.6 | ✔ Yes | -| Pickup Arm Movement | ml_pam | 1.0.4 | ✔ Yes | -| Player Movement Copycat | ml_pmc | 1.0.0 | ⏱ On review | -| Player Ragdoll Mod | ml_prm | 1.0.4 | ✔ Yes
⏱ Update review | +| Leap Motion Extension | ml_lme | 1.3.7 | ✔ Yes
⏱ Update review | +| Pickup Arm Movement | ml_pam | 1.0.5 | ✔ Yes
⏱ Update review | +| Player Movement Copycat | ml_pmc | 1.0.0 | ✔ Yes | +| Player Ragdoll Mod | ml_prm | 1.0.5 | ✔ Yes
⏱ Update review | | Server Connection Info | ml_sci | 1.0.2 | ✔ Yes
⭕ **Retired** | Superseded by `Extended Game Notifications` diff --git a/ml_lme/LeapTracked.cs b/ml_lme/LeapTracked.cs index 21ce9cb..10c720d 100644 --- a/ml_lme/LeapTracked.cs +++ b/ml_lme/LeapTracked.cs @@ -233,13 +233,9 @@ namespace ml_lme if(PlayerSetup.Instance._animator.isHuman) { Vector3 l_hipsPos = Vector3.zero; - Quaternion l_hipsRot = Quaternion.identity; m_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips); if(m_hips != null) - { l_hipsPos = m_hips.localPosition; - l_hipsRot = m_hips.localRotation; - } if(!m_inVR) { @@ -317,10 +313,7 @@ namespace ml_lme } if(m_hips != null) - { m_hips.localPosition = l_hipsPos; - m_hips.localRotation = l_hipsRot; - } } } diff --git a/ml_lme/Properties/AssemblyInfo.cs b/ml_lme/Properties/AssemblyInfo.cs index 8fdeb25..48dc288 100644 --- a/ml_lme/Properties/AssemblyInfo.cs +++ b/ml_lme/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("LeapMotionExtension")] -[assembly: AssemblyVersion("1.3.6")] -[assembly: AssemblyFileVersion("1.3.6")] +[assembly: AssemblyVersion("1.3.7")] +[assembly: AssemblyFileVersion("1.3.7")] -[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.3.6", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_lme.LeapMotionExtension), "LeapMotionExtension", "1.3.7", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonOptionalDependencies("ml_pmc")] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] diff --git a/ml_pam/ArmMover.cs b/ml_pam/ArmMover.cs index 68d0fe4..6091e3b 100644 --- a/ml_pam/ArmMover.cs +++ b/ml_pam/ArmMover.cs @@ -133,13 +133,9 @@ namespace ml_pam if(PlayerSetup.Instance._animator.isHuman) { Vector3 l_hipsPos = Vector3.zero; - Quaternion l_hipsRot = Quaternion.identity; Transform l_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips); if(l_hips != null) - { l_hipsPos = l_hips.localPosition; - l_hipsRot = l_hips.localRotation; - } HumanPose l_currentPose = new HumanPose(); HumanPoseHandler l_poseHandler = null; @@ -201,10 +197,7 @@ namespace ml_pam l_poseHandler?.Dispose(); if(l_hips != null) - { l_hips.localPosition = l_hipsPos; - l_hips.localRotation = l_hipsRot; - } } if(m_enabled) diff --git a/ml_pam/Properties/AssemblyInfo.cs b/ml_pam/Properties/AssemblyInfo.cs index 2bdb677..9ed68ec 100644 --- a/ml_pam/Properties/AssemblyInfo.cs +++ b/ml_pam/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("PickupArmMovement")] -[assembly: AssemblyVersion("1.0.4")] -[assembly: AssemblyFileVersion("1.0.4")] +[assembly: AssemblyVersion("1.0.5")] +[assembly: AssemblyFileVersion("1.0.5")] -[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.0.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.0.5", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPriority(1)] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs index d997fb6..0cd764d 100644 --- a/ml_prm/Main.cs +++ b/ml_prm/Main.cs @@ -130,10 +130,10 @@ namespace ml_prm { try { - if (m_localController != null) + if(m_localController != null) m_localController.OnAvatarScaling(1f + p_scaleDifference); } - catch (Exception e) + catch(Exception e) { MelonLoader.MelonLogger.Error(e); } diff --git a/ml_prm/Properties/AssemblyInfo.cs b/ml_prm/Properties/AssemblyInfo.cs index 64fe343..4f1e779 100644 --- a/ml_prm/Properties/AssemblyInfo.cs +++ b/ml_prm/Properties/AssemblyInfo.cs @@ -1,10 +1,10 @@ using System.Reflection; [assembly: AssemblyTitle("PlayerRagdollMod")] -[assembly: AssemblyVersion("1.0.4")] -[assembly: AssemblyFileVersion("1.0.4")] +[assembly: AssemblyVersion("1.0.5")] +[assembly: AssemblyFileVersion("1.0.5")] -[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.0.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.0.5", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPriority(2)] [assembly: MelonLoader.MelonOptionalDependencies("BTKUILib")] diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 77998c1..f51625b 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -41,6 +41,7 @@ namespace ml_prm readonly PhysicMaterial m_physicsMaterial = null; bool m_reachedGround = true; + float m_groundedTime = 0f; float m_downTime = float.MinValue; internal RagdollController() @@ -115,10 +116,14 @@ namespace ml_prm Vector3 l_pos = PlayerSetup.Instance.transform.position; m_velocity = (m_velocity + (l_pos - m_lastPosition) / Time.deltaTime) * 0.5f; m_lastPosition = l_pos; - } - if(m_avatarReady && !m_reachedGround) - m_reachedGround = MovementSystem.Instance.IsGrounded(); + if(!m_reachedGround && MovementSystem.Instance.IsGrounded()) + { + m_groundedTime += Time.deltaTime; + if(m_groundedTime >= 0.25f) + m_reachedGround = true; + } + } if(m_avatarReady && m_enabled && !BodySystem.isCalibrating) BodySystem.TrackingPositionWeight = 0f; @@ -189,6 +194,7 @@ namespace ml_prm m_boneLinks.Clear(); m_jointAnchors.Clear(); m_reachedGround = true; + m_groundedTime = 0f; m_downTime = float.MinValue; m_puppetRoot.localScale = Vector3.one; } @@ -335,7 +341,10 @@ namespace ml_prm internal void OnCombatDown() { if(m_avatarReady && !m_enabled && Settings.CombatReaction) + { + m_reachedGround = true; SwitchRagdoll(); + } } internal void OnToggleFlight() @@ -451,7 +460,10 @@ namespace ml_prm BodySystem.TrackingPositionWeight = 0f; if(!Utils.IsWorldSafe()) + { m_reachedGround = false; // Force player to unragdoll and reach ground first + m_groundedTime = 0f; + } m_puppetRoot.gameObject.SetActive(true); @@ -485,6 +497,13 @@ namespace ml_prm if(IsSafeToUnragdoll()) { MovementSystem.Instance.SetImmobilized(false); + if(!Utils.IsWorldSafe()) + { + Vector3 l_vec = MovementSystem.Instance.GetAppliedGravity(); + l_vec.y = Mathf.Clamp(l_vec.y, float.MinValue, 0f); + MovementSystem.Instance.SetAppliedGravity(l_vec); + } + m_ragdolledParameter.SetValue(false); if(!BodySystem.isCalibrating) BodySystem.TrackingPositionWeight = 1f; diff --git a/ml_prm/Utils.cs b/ml_prm/Utils.cs index d4aa8f0..b9d1e48 100644 --- a/ml_prm/Utils.cs +++ b/ml_prm/Utils.cs @@ -8,7 +8,8 @@ namespace ml_prm { static class Utils { - static readonly FieldInfo ms_grounded = typeof(MovementSystem).GetField("_isGrounded", BindingFlags.NonPublic | BindingFlags.Instance); + static readonly FieldInfo ms_groundedRaw = typeof(MovementSystem).GetField("_isGroundedRaw", BindingFlags.NonPublic | BindingFlags.Instance); + static readonly FieldInfo ms_appliedGravity = typeof(MovementSystem).GetField("_appliedGravity", BindingFlags.NonPublic | BindingFlags.Instance); public static bool IsInVR() => ((CheckVR.Instance != null) && CheckVR.Instance.hasVrDeviceLoaded); public static bool IsWorldSafe() => ((CVRWorld.Instance != null) && CVRWorld.Instance.allowFlying); @@ -25,7 +26,9 @@ namespace ml_prm return l_result; } - public static bool IsGrounded(this MovementSystem p_instance) => (bool)ms_grounded.GetValue(p_instance); + public static bool IsGrounded(this MovementSystem p_instance) => (bool)ms_groundedRaw.GetValue(p_instance); + public static Vector3 GetAppliedGravity(this MovementSystem p_instance) => (Vector3)ms_appliedGravity.GetValue(p_instance); + public static void SetAppliedGravity(this MovementSystem p_instance, Vector3 p_vec) => ms_appliedGravity.SetValue(p_instance, p_vec); public static void CopyGlobal(this Transform p_source, Transform p_target) { From 1000da71006e62d5e459aedd445602d5b7fda9eb Mon Sep 17 00:00:00 2001 From: SDraw Date: Sun, 11 Jun 2023 14:21:37 +0000 Subject: [PATCH 63/63] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 667a2bb..d66b80f 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ Merged set of MelonLoader mods for ChilloutVR. | Desktop Reticle Switch | ml_drs | 1.0.0 | ✔ Yes | | Extended Game Notifications | ml_egn | 1.0.2 | ✔ Yes | | Four Point Tracking | ml_fpt | 1.0.9 | ✔ Yes
⭕ **Retired** | In-game feature since 2022r170 update -| Leap Motion Extension | ml_lme | 1.3.7 | ✔ Yes
⏱ Update review | -| Pickup Arm Movement | ml_pam | 1.0.5 | ✔ Yes
⏱ Update review | +| Leap Motion Extension | ml_lme | 1.3.7 | ✔ Yes | +| Pickup Arm Movement | ml_pam | 1.0.5 | ✔ Yes | | Player Movement Copycat | ml_pmc | 1.0.0 | ✔ Yes | -| Player Ragdoll Mod | ml_prm | 1.0.5 | ✔ Yes
⏱ Update review | +| Player Ragdoll Mod | ml_prm | 1.0.5 | ✔ Yes | | Server Connection Info | ml_sci | 1.0.2 | ✔ Yes
⭕ **Retired** | Superseded by `Extended Game Notifications`