From adf7796f9e08b327bed4d57902a851628b7374cf Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 31 May 2025 13:03:22 +0300 Subject: [PATCH 01/12] Fix for new ControllerRay class --- ml_lme/LeapInput.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ml_lme/LeapInput.cs b/ml_lme/LeapInput.cs index b361737..49eee51 100644 --- a/ml_lme/LeapInput.cs +++ b/ml_lme/LeapInput.cs @@ -40,7 +40,6 @@ namespace ml_lme m_handRayLeft.isInteractionRay = true; m_handRayLeft.triggerHoverEvents = false; m_handRayLeft.attachmentDistance = 0f; - m_handRayLeft.uiMask = 32; m_handRayLeft.isDesktopRay = !m_inVR; m_lineLeft = m_handRayLeft.gameObject.AddComponent(); @@ -61,7 +60,6 @@ namespace ml_lme m_handRayRight.isInteractionRay = true; m_handRayRight.triggerHoverEvents = false; m_handRayRight.attachmentDistance = 0f; - m_handRayRight.uiMask = 32; m_handRayRight.isDesktopRay = !m_inVR; m_lineRight = m_handRayRight.gameObject.AddComponent(); @@ -120,12 +118,10 @@ namespace ml_lme m_lineLeft.material = PlayerSetup.Instance.vrRayLeft.lineRenderer.material; m_lineLeft.gameObject.layer = PlayerSetup.Instance.vrRayLeft.gameObject.layer; - m_handRayLeft.highlightMaterial = PlayerSetup.Instance.vrRayLeft.highlightMaterial; m_handRayLeft.SetVRActive(m_inVR); m_lineRight.material = PlayerSetup.Instance.vrRayLeft.lineRenderer.material; m_lineRight.gameObject.layer = PlayerSetup.Instance.vrRayLeft.gameObject.layer; - m_handRayRight.highlightMaterial = PlayerSetup.Instance.vrRayLeft.highlightMaterial; m_handRayRight.SetVRActive(m_inVR); } From 080c0a58760139ccc6d61cc2535149475ede41f9 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sat, 31 May 2025 23:36:46 +0300 Subject: [PATCH 02/12] Avatar as parameter of any animator type --- ml_prm/AvatarBoolParameter.cs | 43 -------------- ml_prm/AvatarParameter.cs | 109 ++++++++++++++++++++++++++++++++++ ml_prm/RagdollController.cs | 7 ++- 3 files changed, 114 insertions(+), 45 deletions(-) delete mode 100644 ml_prm/AvatarBoolParameter.cs create mode 100644 ml_prm/AvatarParameter.cs diff --git a/ml_prm/AvatarBoolParameter.cs b/ml_prm/AvatarBoolParameter.cs deleted file mode 100644 index ee40a63..0000000 --- a/ml_prm/AvatarBoolParameter.cs +++ /dev/null @@ -1,43 +0,0 @@ -using ABI_RC.Core.Util.AnimatorManager; -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 AvatarAnimatorManager m_manager = null; - - public AvatarBoolParameter(string p_name, AvatarAnimatorManager 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_sync = !l_param.name.StartsWith('#'); - m_hash = l_param.nameHash; - break; - } - } - } - - public void SetValue(bool p_value) - { - if(m_hash != 0) - { - if(m_sync) - m_manager.SetParameter(m_name, p_value); - else - m_manager.Animator.SetBool(m_hash, p_value); - } - } - } -} diff --git a/ml_prm/AvatarParameter.cs b/ml_prm/AvatarParameter.cs new file mode 100644 index 0000000..1c736b2 --- /dev/null +++ b/ml_prm/AvatarParameter.cs @@ -0,0 +1,109 @@ +using ABI_RC.Core.Util.AnimatorManager; +using System.Text.RegularExpressions; +using UnityEngine; + +namespace ml_prm +{ + class AvatarParameter + { + public readonly string m_name; + public readonly int m_hash = 0; + public readonly bool m_sync; + public readonly AnimatorControllerParameterType m_type; + readonly AvatarAnimatorManager m_manager = null; + + public AvatarParameter(string p_name, AvatarAnimatorManager 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)) + { + m_name = l_param.name; + m_sync = !l_param.name.StartsWith('#'); + m_hash = l_param.nameHash; + m_type = l_param.type; + break; + } + } + } + + public void SetValue(bool p_value) + { + if(m_hash != 0) + { + if(m_sync) + m_manager.SetParameter(m_name, p_value); + else + { + switch(m_type) + { + case AnimatorControllerParameterType.Bool: + case AnimatorControllerParameterType.Trigger: + m_manager.Animator.SetBool(m_hash, p_value); + break; + case AnimatorControllerParameterType.Int: + m_manager.Animator.SetInteger(m_hash, p_value ? 1 : 0); + break; + case AnimatorControllerParameterType.Float: + m_manager.Animator.SetFloat(m_hash, p_value ? 1f : 0f); + break; + } + } + } + } + + public void SetValue(int p_value) + { + if(m_hash != 0) + { + if(m_sync) + m_manager.SetParameter(m_name, p_value); + else + { + switch(m_type) + { + case AnimatorControllerParameterType.Bool: + case AnimatorControllerParameterType.Trigger: + m_manager.Animator.SetBool(m_hash, p_value > 0); + break; + case AnimatorControllerParameterType.Int: + m_manager.Animator.SetInteger(m_hash, p_value); + break; + case AnimatorControllerParameterType.Float: + m_manager.Animator.SetFloat(m_hash, p_value); + break; + } + } + } + } + + public void SetValue(float p_value) + { + if(m_hash != 0) + { + if(m_sync) + m_manager.SetParameter(m_name, p_value); + else + { + switch(m_type) + { + case AnimatorControllerParameterType.Bool: + case AnimatorControllerParameterType.Trigger: + m_manager.Animator.SetBool(m_hash, p_value > 0f); + break; + case AnimatorControllerParameterType.Int: + m_manager.Animator.SetInteger(m_hash, (int)p_value); + break; + case AnimatorControllerParameterType.Float: + m_manager.Animator.SetFloat(m_hash, p_value); + break; + } + } + } + } + } +} diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index e9c1f0e..b0331c4 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -1,4 +1,5 @@ using ABI.CCK.Components; +using ABI_RC.Core; using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Player; using ABI_RC.Systems.IK; @@ -39,7 +40,7 @@ namespace ml_prm readonly List> m_jointAnchors = null; RagdollToggle m_avatarRagdollToggle = null; // Custom component available for editor - AvatarBoolParameter m_ragdolledParameter = null; + AvatarParameter m_ragdolledParameter = null; PhysicMaterial m_physicsMaterial = null; bool m_inAir = false; @@ -299,6 +300,7 @@ namespace ml_prm BipedRagdollReferences l_avatarReferences = BipedRagdollReferences.FromAvatar(PlayerSetup.Instance._animator); m_puppetRoot = new GameObject("Root").transform; + m_puppetRoot.gameObject.layer = CVRLayers.PlayerClone; m_puppetRoot.parent = m_puppet; m_puppetRoot.position = m_avatarTransform.position; m_puppetRoot.rotation = m_avatarTransform.rotation; @@ -370,7 +372,7 @@ namespace ml_prm m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate); m_avatarRagdollToggle = PlayerSetup.Instance._avatar.GetComponentInChildren(true); - m_ragdolledParameter = new AvatarBoolParameter("Ragdolled", PlayerSetup.Instance.animatorManager); + m_ragdolledParameter = new AvatarParameter("Ragdolled", PlayerSetup.Instance.animatorManager); m_initTask = StartCoroutine(WaitForBodyHandlers()); } @@ -781,6 +783,7 @@ namespace ml_prm static Transform CloneTransform(Transform p_source, Transform p_parent, string p_name) { Transform l_target = new GameObject(p_name).transform; + l_target.gameObject.layer = CVRLayers.PlayerClone; l_target.parent = p_parent; p_source.CopyGlobal(l_target); return l_target; From 0902edd5609d56906962f3c6a2044c18283842df Mon Sep 17 00:00:00 2001 From: SDraw Date: Thu, 5 Jun 2025 14:28:20 +0300 Subject: [PATCH 03/12] Separate stable and nightly game builds functionality --- ml_vet/Main.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ml_vet/Main.cs b/ml_vet/Main.cs index 9a30c1a..6ba63aa 100644 --- a/ml_vet/Main.cs +++ b/ml_vet/Main.cs @@ -174,9 +174,12 @@ namespace ml_vet if(p_controller.IsLocal && IsReadyForUpdate()) { p_controller.manualBlinking = true; +#if NIGHTLY_BUILD p_controller.blinkProgressLeft = 1f - m_openness.x; p_controller.blinkProgressRight = 1f - m_openness.y; - +#else + p_controller.blinkProgress = 1f - (m_openness.x + m_openness.y) * 0.5f; +#endif p_controller.manualViewTarget = true; Vector3 l_gazePoint = m_gazePoint; From 40b683d33cecd119d5e8ad92b73b1a63b37a2a58 Mon Sep 17 00:00:00 2001 From: SDraw Date: Tue, 24 Jun 2025 21:45:18 +0300 Subject: [PATCH 04/12] Fixes for 24/06/2025 nightly build --- ml_amt/MotionTweaker.cs | 30 +++++++++++++++--------------- ml_amt/Utils.cs | 6 +++--- ml_bft/FingerSystem.cs | 2 +- ml_bft/Utils.cs | 4 ++-- ml_dht/HeadTracked.cs | 20 ++++++++++---------- ml_lme/GameEvents.cs | 2 +- ml_lme/LeapTracked.cs | 8 ++++---- ml_lme/LeapTracking.cs | 2 +- ml_lme/Utils.cs | 4 ++-- ml_pam/ArmMover.cs | 24 ++++++++++++------------ ml_pam/Utils.cs | 4 ++-- ml_pmc/PoseCopycat.cs | 24 ++++++++++++------------ ml_ppu/PickUpManager.cs | 12 +++++++----- ml_ppu/Utils.cs | 3 +++ ml_ppu/ml_ppu.csproj | 1 + ml_prm/RagdollController.cs | 28 ++++++++++++++-------------- ml_prm/Utils.cs | 4 ++-- ml_vet/ml_vet.csproj | 1 + 18 files changed, 93 insertions(+), 86 deletions(-) diff --git a/ml_amt/MotionTweaker.cs b/ml_amt/MotionTweaker.cs index 9c01ef5..cc881c6 100644 --- a/ml_amt/MotionTweaker.cs +++ b/ml_amt/MotionTweaker.cs @@ -114,17 +114,17 @@ namespace ml_amt { Utils.SetAvatarTPose(); - m_vrIk = PlayerSetup.Instance._avatar.GetComponent(); - m_avatarScale = Mathf.Abs(PlayerSetup.Instance._avatar.transform.localScale.y); + m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent(); + m_avatarScale = Mathf.Abs(PlayerSetup.Instance.AvatarTransform.localScale.y); // Parse animator parameters - m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Moving, PlayerSetup.Instance.animatorManager)); - m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.MovementSpeed, PlayerSetup.Instance.animatorManager)); - m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Velocity, PlayerSetup.Instance.animatorManager)); + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Moving, PlayerSetup.Instance.AnimatorManager)); + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.MovementSpeed, PlayerSetup.Instance.AnimatorManager)); + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Velocity, PlayerSetup.Instance.AnimatorManager)); m_parameters.RemoveAll(p => !p.IsValid()); // Avatar custom IK limits - m_ikLimits = PlayerSetup.Instance._avatar.transform.Find("[IKLimits]"); + m_ikLimits = PlayerSetup.Instance.AvatarTransform.Find("[IKLimits]"); UpdateIKLimits(); // Apply VRIK tweaks @@ -135,18 +135,18 @@ namespace ml_amt if(m_vrIk.solver.HasToes()) { - Transform l_foot = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftFoot); + Transform l_foot = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.LeftFoot); if(l_foot == null) - l_foot = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightFoot); + l_foot = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.RightFoot); - Transform l_toe = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftToes); + Transform l_toe = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.LeftToes); if(l_toe == null) - l_toe = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightToes); + l_toe = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.RightToes); if((l_foot != null) && (l_toe != null)) { - Vector3 l_footPos = (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_foot.GetMatrix()).GetPosition(); - Vector3 l_toePos = (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_toe.GetMatrix()).GetPosition(); + Vector3 l_footPos = (PlayerSetup.Instance.AvatarTransform.GetMatrix().inverse * l_foot.GetMatrix()).GetPosition(); + Vector3 l_toePos = (PlayerSetup.Instance.AvatarTransform.GetMatrix().inverse * l_toe.GetMatrix()).GetPosition(); m_massCenter = new Vector3(0f, 0f, l_toePos.z - l_footPos.z); } } @@ -171,7 +171,7 @@ namespace ml_amt // Old VRIK is destroyed by game Utils.SetAvatarTPose(); - m_vrIk = PlayerSetup.Instance._animator.GetComponent(); + m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent(); if(m_vrIk != null) { m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? m_massCenter : m_locomotionOffset); @@ -241,7 +241,7 @@ namespace ml_amt // Arbitrary float GetRelativeScale() { - return ((m_avatarScale > 0f) ? (PlayerSetup.Instance._avatar.transform.localScale.y / m_avatarScale) : 0f); + return ((m_avatarScale > 0f) ? (PlayerSetup.Instance.AvatarTransform.localScale.y / m_avatarScale) : 0f); } void UpdateIKLimits() @@ -258,7 +258,7 @@ namespace ml_amt public bool IsMoving() => BetterBetterCharacterController.Instance.IsMoving(); public float GetMovementSpeed() { - AvatarAnimatorManager l_animatorManager = PlayerSetup.Instance.animatorManager; + AvatarAnimatorManager l_animatorManager = PlayerSetup.Instance.AnimatorManager; return Mathf.Sqrt(l_animatorManager.MovementX * l_animatorManager.MovementX + l_animatorManager.MovementY * l_animatorManager.MovementY); } public float GetVelocity() => BetterBetterCharacterController.Instance.velocity.magnitude; diff --git a/ml_amt/Utils.cs b/ml_amt/Utils.cs index 79b1130..6cd79d3 100644 --- a/ml_amt/Utils.cs +++ b/ml_amt/Utils.cs @@ -22,11 +22,11 @@ namespace ml_amt public static void SetAvatarTPose() { - if(PlayerSetup.Instance._animator.isHuman) + if(PlayerSetup.Instance.Animator.isHuman) { IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero; - PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity; + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; } } diff --git a/ml_bft/FingerSystem.cs b/ml_bft/FingerSystem.cs index 3a56cde..6899264 100644 --- a/ml_bft/FingerSystem.cs +++ b/ml_bft/FingerSystem.cs @@ -114,7 +114,7 @@ namespace ml_bft internal void OnAvatarSetup() { - Animator l_animator = PlayerSetup.Instance._animator; + Animator l_animator = PlayerSetup.Instance.Animator; if(l_animator.isHuman) { Utils.SetAvatarTPose(); diff --git a/ml_bft/Utils.cs b/ml_bft/Utils.cs index 688febf..adadeff 100644 --- a/ml_bft/Utils.cs +++ b/ml_bft/Utils.cs @@ -21,8 +21,8 @@ namespace ml_bft public static void SetAvatarTPose() { IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero; - PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity; + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; } } } diff --git a/ml_dht/HeadTracked.cs b/ml_dht/HeadTracked.cs index 17b9e98..424c326 100644 --- a/ml_dht/HeadTracked.cs +++ b/ml_dht/HeadTracked.cs @@ -131,7 +131,7 @@ namespace ml_dht { m_lastHeadRotation = Quaternion.Slerp(m_lastHeadRotation, m_avatarDescriptor.transform.rotation * (m_headRotation * m_bindRotation), m_smoothing); - if(!PlayerSetup.Instance.IsEmotePlaying()) + if(!PlayerSetup.Instance.IsEmotePlaying) m_headBone.rotation = m_lastHeadRotation; } } @@ -139,20 +139,20 @@ namespace ml_dht // Game events internal void OnAvatarSetup() { - m_camera = PlayerSetup.Instance.GetActiveCamera().transform; - m_avatarDescriptor = PlayerSetup.Instance._avatar.GetComponent(); + m_camera = PlayerSetup.Instance.activeCam.transform; + m_avatarDescriptor = PlayerSetup.Instance.AvatarObject.GetComponent(); - if(PlayerSetup.Instance._animator.isHuman) + if(PlayerSetup.Instance.Animator.isHuman) { IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero; - PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity; + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; - m_headBone = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Head); + m_headBone = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.Head); if(m_headBone != null) m_bindRotation = Quaternion.Inverse(m_avatarDescriptor.transform.rotation) * m_headBone.rotation; - m_lookIK = PlayerSetup.Instance._avatar.GetComponent(); + m_lookIK = PlayerSetup.Instance.AvatarObject.GetComponent(); if(m_lookIK != null) m_lookIK.onPostSolverUpdate.AddListener(this.OnLookIKPostUpdate); } @@ -167,9 +167,9 @@ namespace ml_dht } void OnAvatarReuse() { - m_camera = PlayerSetup.Instance.GetActiveCamera().transform; + m_camera = PlayerSetup.Instance.activeCam.transform; - m_lookIK = PlayerSetup.Instance._avatar.GetComponent(); + m_lookIK = PlayerSetup.Instance.AvatarObject.GetComponent(); if(m_lookIK != null) m_lookIK.onPostSolverUpdate.AddListener(this.OnLookIKPostUpdate); } diff --git a/ml_lme/GameEvents.cs b/ml_lme/GameEvents.cs index c3191b5..54c77b3 100644 --- a/ml_lme/GameEvents.cs +++ b/ml_lme/GameEvents.cs @@ -53,7 +53,7 @@ namespace ml_lme ); p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetControllerRayScale), BindingFlags.Instance | BindingFlags.Public), + typeof(PlayerSetup).GetMethod("SetControllerRayScale", BindingFlags.Instance | BindingFlags.NonPublic), null, new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnRayScale_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) ); diff --git a/ml_lme/LeapTracked.cs b/ml_lme/LeapTracked.cs index 0d9cccb..e9bace1 100644 --- a/ml_lme/LeapTracked.cs +++ b/ml_lme/LeapTracked.cs @@ -281,7 +281,7 @@ namespace ml_lme void OnAvatarSetup() { - Animator l_animator = PlayerSetup.Instance._animator; + Animator l_animator = PlayerSetup.Instance.Animator; if(l_animator.isHuman) { Utils.SetAvatarTPose(); @@ -313,7 +313,7 @@ namespace ml_lme void OnAvatarReuse() { // Old VRIK is destroyed by game - m_vrIK = PlayerSetup.Instance._animator.GetComponent(); + m_vrIK = PlayerSetup.Instance.AvatarObject.GetComponent(); if(Utils.IsInVR()) RemoveArmIK(); @@ -409,7 +409,7 @@ namespace ml_lme void SetupArmIK() { - Animator l_animator = PlayerSetup.Instance._animator; + Animator l_animator = PlayerSetup.Instance.Animator; Transform l_chest = l_animator.GetBoneTransform(HumanBodyBones.UpperChest); if(l_chest == null) l_chest = l_animator.GetBoneTransform(HumanBodyBones.Chest); @@ -472,7 +472,7 @@ namespace ml_lme LeapTracking.Instance.Rebind(PlayerSetup.Instance.transform.rotation); // Align rotations of leap fingers to avatar fingers - Animator l_animator = PlayerSetup.Instance._animator; + Animator l_animator = PlayerSetup.Instance.Animator; LeapHand l_leapLeft = LeapTracking.Instance.GetLeftHand(); LeapHand l_leapRight = LeapTracking.Instance.GetRightHand(); // Try to "fix" rotations, slightly inaccurate after 0YX plane rotation diff --git a/ml_lme/LeapTracking.cs b/ml_lme/LeapTracking.cs index eb96377..8b4aba6 100644 --- a/ml_lme/LeapTracking.cs +++ b/ml_lme/LeapTracking.cs @@ -136,7 +136,7 @@ namespace ml_lme { if(Settings.Enabled) { - Transform l_camera = PlayerSetup.Instance.GetActiveCamera().transform; + Transform l_camera = PlayerSetup.Instance.activeCam.transform; m_root.position = l_camera.position; m_root.rotation = (Settings.HeadAttach ? l_camera.rotation : PlayerSetup.Instance.GetPlayerRotation()); diff --git a/ml_lme/Utils.cs b/ml_lme/Utils.cs index 55b0b8b..e653fde 100644 --- a/ml_lme/Utils.cs +++ b/ml_lme/Utils.cs @@ -59,8 +59,8 @@ namespace ml_lme public static void SetAvatarTPose() { IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero; - PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity; + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; } public static void Swap(ref T lhs, ref T rhs) diff --git a/ml_pam/ArmMover.cs b/ml_pam/ArmMover.cs index de26757..a4aebf8 100644 --- a/ml_pam/ArmMover.cs +++ b/ml_pam/ArmMover.cs @@ -68,7 +68,7 @@ namespace ml_pam void Start() { - m_camera = PlayerSetup.Instance.GetActiveCamera().transform; + m_camera = PlayerSetup.Instance.activeCam.transform; m_root = new GameObject("Root").transform; m_root.parent = this.transform; @@ -353,14 +353,14 @@ namespace ml_pam void OnAvatarSetup() { - m_camera = PlayerSetup.Instance.GetActiveCamera().transform; + m_camera = PlayerSetup.Instance.activeCam.transform; - if(PlayerSetup.Instance._animator.isHuman) + if(PlayerSetup.Instance.Animator.isHuman) { - m_vrIK = PlayerSetup.Instance._animator.GetComponent(); + m_vrIK = PlayerSetup.Instance.Animator.GetComponent(); Utils.SetAvatarTPose(); - Animator l_animator = PlayerSetup.Instance._animator; + Animator l_animator = PlayerSetup.Instance.Animator; Matrix4x4 l_avatarMatrixInv = l_animator.transform.GetMatrix().inverse; // Animator and avatar are on same game object Transform l_leftHand = l_animator.GetBoneTransform(HumanBodyBones.LeftHand); @@ -395,8 +395,8 @@ namespace ml_pam } } - m_leftHandParameter = new AvatarBoolParameter("LeftHandExtended", PlayerSetup.Instance.animatorManager); - m_rightHandParameter = new AvatarBoolParameter("RightHandExtended", PlayerSetup.Instance.animatorManager); + m_leftHandParameter = new AvatarBoolParameter("LeftHandExtended", PlayerSetup.Instance.AnimatorManager); + m_rightHandParameter = new AvatarBoolParameter("RightHandExtended", PlayerSetup.Instance.AnimatorManager); OnEnabledChanged(Settings.Enabled); OnGrabOffsetChanged(Settings.GrabOffset); @@ -406,7 +406,7 @@ namespace ml_pam void OnAvatarReuse() { // Old VRIK is destroyed by game - m_vrIK = PlayerSetup.Instance._animator.GetComponent(); + m_vrIK = PlayerSetup.Instance.Animator.GetComponent(); if(Utils.IsInVR()) RemoveArmIK(); @@ -470,7 +470,7 @@ namespace ml_pam { try { - m_camera = PlayerSetup.Instance.GetActiveCamera().transform; + m_camera = PlayerSetup.Instance.activeCam.transform; this.enabled = !Utils.IsInVR(); } catch(System.Exception e) @@ -482,7 +482,7 @@ namespace ml_pam // Arbitrary void SetupArmIK() { - Animator l_animator = PlayerSetup.Instance._animator; + Animator l_animator = PlayerSetup.Instance.Animator; Transform l_chest = l_animator.GetBoneTransform(HumanBodyBones.UpperChest); if(l_chest == null) @@ -490,7 +490,7 @@ namespace ml_pam if(l_chest == null) l_chest = l_animator.GetBoneTransform(HumanBodyBones.Spine); - m_armIKLeft = PlayerSetup.Instance._avatar.AddComponent(); + m_armIKLeft = PlayerSetup.Instance.AvatarObject.AddComponent(); m_armIKLeft.solver.isLeft = true; m_armIKLeft.solver.SetChain( l_chest, @@ -507,7 +507,7 @@ namespace ml_pam m_armIKLeft.solver.IKRotationWeight = 0f; m_armIKLeft.enabled = false; - m_armIKRight = PlayerSetup.Instance._avatar.AddComponent(); + m_armIKRight = PlayerSetup.Instance.AvatarObject.AddComponent(); m_armIKRight.solver.isLeft = false; m_armIKRight.solver.SetChain( l_chest, diff --git a/ml_pam/Utils.cs b/ml_pam/Utils.cs index a01906b..6f5faf1 100644 --- a/ml_pam/Utils.cs +++ b/ml_pam/Utils.cs @@ -18,8 +18,8 @@ namespace ml_pam public static void SetAvatarTPose() { IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero; - PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity; + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; } // Extensions diff --git a/ml_pmc/PoseCopycat.cs b/ml_pmc/PoseCopycat.cs index de9e1c1..6aba068 100644 --- a/ml_pmc/PoseCopycat.cs +++ b/ml_pmc/PoseCopycat.cs @@ -196,9 +196,9 @@ namespace ml_pmc { if(m_inVr) { - Vector3 l_avatarPos = PlayerSetup.Instance._avatar.transform.position; + Vector3 l_avatarPos = PlayerSetup.Instance.AvatarTransform.position; PlayerSetup.Instance.transform.rotation = l_result.rotation; - Vector3 l_dif = l_avatarPos - PlayerSetup.Instance._avatar.transform.position; + Vector3 l_dif = l_avatarPos - PlayerSetup.Instance.AvatarTransform.position; PlayerSetup.Instance.transform.position += l_dif; } else @@ -258,9 +258,9 @@ namespace ml_pmc void OnAvatarSetup() { m_inVr = Utils.IsInVR(); - m_animator = PlayerSetup.Instance._animator; - m_vrIk = PlayerSetup.Instance._avatar.GetComponent(); - m_lookAtIk = PlayerSetup.Instance._avatar.GetComponent(); + m_animator = PlayerSetup.Instance.Animator; + m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent(); + m_lookAtIk = PlayerSetup.Instance.AvatarObject.GetComponent(); if((m_animator != null) && m_animator.isHuman) { @@ -293,8 +293,8 @@ namespace ml_pmc m_inVr = Utils.IsInVR(); // Old VRIK and LookAtIK are destroyed by game - m_vrIk = PlayerSetup.Instance._avatar.GetComponent(); - m_lookAtIk = PlayerSetup.Instance._avatar.GetComponent(); + m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent(); + m_lookAtIk = PlayerSetup.Instance.AvatarObject.GetComponent(); if(m_vrIk != null) { @@ -320,10 +320,10 @@ namespace ml_pmc { if(Friends.FriendsWith(p_id)) { - if(CVRPlayerManager.Instance.GetPlayerPuppetMaster(p_id, out PuppetMaster l_puppetMaster)) + if(CVRPlayerManager.Instance.UserIdToPlayerEntity.TryGetValue(p_id, out CVRPlayerEntity l_playerEntity)) { - if(Utils.IsInSight(BetterBetterCharacterController.Instance.KinematicTriggerProxy.Collider, l_puppetMaster.GetComponent(), Utils.GetWorldMovementLimit())) - SetTarget(l_puppetMaster); + if(Utils.IsInSight(BetterBetterCharacterController.Instance.KinematicTriggerProxy.Collider, l_playerEntity.PuppetMaster.GetComponent(), Utils.GetWorldMovementLimit())) + SetTarget(l_playerEntity.PuppetMaster); else ModUi.ShowAlert("Selected player is too far away or obstructed"); } @@ -374,9 +374,9 @@ namespace ml_pmc { if(!m_active) { - if((p_target != null) && (p_target.animatorManager != null) && (p_target.animatorManager.Animator != null) && p_target.animatorManager.Animator.isHuman) + if((p_target != null) && (p_target.AnimatorManager != null) && (p_target.Animator != null) && p_target.Animator.isHuman) { - m_puppetParser = p_target.animatorManager.Animator.gameObject.AddComponent(); + m_puppetParser = p_target.Animator.gameObject.AddComponent(); m_puppetParser.m_puppetMaster = p_target; m_distanceLimit = Utils.GetWorldMovementLimit(); diff --git a/ml_ppu/PickUpManager.cs b/ml_ppu/PickUpManager.cs index 4f32de3..9030588 100644 --- a/ml_ppu/PickUpManager.cs +++ b/ml_ppu/PickUpManager.cs @@ -1,4 +1,5 @@ using ABI.CCK.Components; +using ABI_RC.Core; using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Player; using ABI_RC.Systems.IK; @@ -81,7 +82,7 @@ namespace ml_ppu } Vector3 l_armsMidPoint = (m_armLeft.position + m_armRight.position) * 0.5f; - Quaternion l_avatarRot = PlayerSetup.Instance._avatar.transform.rotation; + Quaternion l_avatarRot = PlayerSetup.Instance.AvatarTransform.rotation; m_collider.transform.position = Vector3.zero; m_collider.transform.rotation = Quaternion.identity; @@ -127,12 +128,12 @@ namespace ml_ppu void OnAvatarSetup() { - Animator l_animator = PlayerSetup.Instance._animator; + Animator l_animator = PlayerSetup.Instance.Animator; if((l_animator != null) && l_animator.isHuman) { IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero; - PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity; + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; m_hips = l_animator.GetBoneTransform(HumanBodyBones.Hips); m_armLeft = l_animator.GetBoneTransform(HumanBodyBones.LeftUpperArm); @@ -140,11 +141,12 @@ namespace ml_ppu if((m_hips != null) && (m_armLeft != null) && (m_armRight != null)) { - Matrix4x4 l_avatarMatInv = PlayerSetup.Instance._avatar.transform.GetMatrix().inverse; + Matrix4x4 l_avatarMatInv = PlayerSetup.Instance.AvatarTransform.GetMatrix().inverse; Vector3 l_hipsPos = (l_avatarMatInv * m_hips.GetMatrix()).GetPosition(); Vector3 l_armPos = (l_avatarMatInv * m_armLeft.GetMatrix()).GetPosition(); m_collider = new GameObject("[Collider]").AddComponent(); + m_collider.gameObject.layer = CVRLayers.PlayerClone; m_collider.transform.parent = this.transform; m_collider.isTrigger = true; m_collider.height = Vector3.Distance(l_hipsPos, new Vector3(0f, l_armPos.y, l_armPos.z)); diff --git a/ml_ppu/Utils.cs b/ml_ppu/Utils.cs index de56ef0..4629730 100644 --- a/ml_ppu/Utils.cs +++ b/ml_ppu/Utils.cs @@ -1,5 +1,6 @@ using ABI_RC.Core; using ABI_RC.Core.Player; +using ABI_RC.Core.Savior; using ABI_RC.Systems.Movement; using ABI_RC.Systems.Safety.AdvancedSafety; using UnityEngine; @@ -8,6 +9,8 @@ namespace ml_ppu { static class Utils { + public static bool IsInVR() => ((MetaPort.Instance != null) && MetaPort.Instance.isUsingVr); + 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); diff --git a/ml_ppu/ml_ppu.csproj b/ml_ppu/ml_ppu.csproj index 4bbe04c..7977ca2 100644 --- a/ml_ppu/ml_ppu.csproj +++ b/ml_ppu/ml_ppu.csproj @@ -5,6 +5,7 @@ x64 PlayerPickUp SDraw + 1.0.0 diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index b0331c4..0ff7f07 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -195,7 +195,7 @@ namespace ml_prm BodySystem.TrackingPositionWeight = 0f; BetterBetterCharacterController.Instance.PauseGroundConstraint(); BetterBetterCharacterController.Instance.ResetAllForces(); - PlayerSetup.Instance.animatorManager.CancelEmote = true; + PlayerSetup.Instance.AnimatorManager.CancelEmote = true; } if(!m_ragdolled && !m_reachedGround && (BetterBetterCharacterController.Instance.IsOnGround() || BetterBetterCharacterController.Instance.IsInWater() || BetterBetterCharacterController.Instance.IsSitting())) @@ -291,13 +291,13 @@ namespace ml_prm void OnAvatarSetup() { - if(PlayerSetup.Instance._animator.isHuman) + if(PlayerSetup.Instance.Animator.isHuman) { - m_avatarTransform = PlayerSetup.Instance._avatar.transform; - m_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips); + m_avatarTransform = PlayerSetup.Instance.AvatarTransform; + m_hips = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.Hips); Utils.SetAvatarTPose(); - BipedRagdollReferences l_avatarReferences = BipedRagdollReferences.FromAvatar(PlayerSetup.Instance._animator); + BipedRagdollReferences l_avatarReferences = BipedRagdollReferences.FromAvatar(PlayerSetup.Instance.Animator); m_puppetRoot = new GameObject("Root").transform; m_puppetRoot.gameObject.layer = CVRLayers.PlayerClone; @@ -367,12 +367,12 @@ namespace ml_prm } } - m_vrIK = PlayerSetup.Instance._avatar.GetComponent(); + m_vrIK = PlayerSetup.Instance.AvatarObject.GetComponent(); if(m_vrIK != null) m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate); - m_avatarRagdollToggle = PlayerSetup.Instance._avatar.GetComponentInChildren(true); - m_ragdolledParameter = new AvatarParameter("Ragdolled", PlayerSetup.Instance.animatorManager); + m_avatarRagdollToggle = PlayerSetup.Instance.AvatarObject.GetComponentInChildren(true); + m_ragdolledParameter = new AvatarParameter("Ragdolled", PlayerSetup.Instance.AnimatorManager); m_initTask = StartCoroutine(WaitForBodyHandlers()); } @@ -410,7 +410,7 @@ namespace ml_prm } void OnAvatarPostReuse() { - m_vrIK = PlayerSetup.Instance._avatar.GetComponent(); + m_vrIK = PlayerSetup.Instance.AvatarObject.GetComponent(); if(m_vrIK != null) m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate); @@ -506,10 +506,10 @@ namespace ml_prm // Custom game events void OnRemoteGestureStateChanged(ABI_RC.Core.Player.PuppetMaster p_master, RemoteGesturesManager.GestureHand p_hand, bool p_state) { - if(m_avatarReady && m_ragdolled && Settings.GestureGrab && (p_master.animatorManager.Animator != null)) + if(m_avatarReady && m_ragdolled && Settings.GestureGrab && (p_master.Animator != null)) { - Transform l_hand = p_master.animatorManager.Animator.GetBoneTransform((p_hand == RemoteGesturesManager.GestureHand.Left) ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand); - Transform l_finger = p_master.animatorManager.Animator.GetBoneTransform((p_hand == RemoteGesturesManager.GestureHand.Left) ? HumanBodyBones.LeftMiddleProximal : HumanBodyBones.RightMiddleProximal); + Transform l_hand = p_master.Animator.GetBoneTransform((p_hand == RemoteGesturesManager.GestureHand.Left) ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand); + Transform l_finger = p_master.Animator.GetBoneTransform((p_hand == RemoteGesturesManager.GestureHand.Left) ? HumanBodyBones.LeftMiddleProximal : HumanBodyBones.RightMiddleProximal); if(l_hand != null) { @@ -642,7 +642,7 @@ namespace ml_prm if(Settings.ViewVelocity && WorldManager.IsSafeWorld()) { float l_mag = l_velocity.magnitude; - l_velocity = PlayerSetup.Instance.GetActiveCamera().transform.forward * l_mag; + l_velocity = PlayerSetup.Instance.activeCam.transform.forward * l_mag; } Vector3 l_playerPos = PlayerSetup.Instance.transform.position; @@ -666,7 +666,7 @@ namespace ml_prm m_applyHipsRotation = IKSystem.Instance.applyOriginalHipRotation; IKSystem.Instance.applyOriginalHipRotation = true; - PlayerSetup.Instance.animatorManager.CancelEmote = true; + PlayerSetup.Instance.AnimatorManager.CancelEmote = true; m_ragdolledParameter.SetValue(true); if(!WorldManager.IsSafeWorld()) diff --git a/ml_prm/Utils.cs b/ml_prm/Utils.cs index 39347de..5138c28 100644 --- a/ml_prm/Utils.cs +++ b/ml_prm/Utils.cs @@ -41,8 +41,8 @@ namespace ml_prm public static void SetAvatarTPose() { IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero; - PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity; + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; } public static bool IsInEnumeration(object p_obj, object[] p_enumeration) => p_enumeration.Contains(p_obj); diff --git a/ml_vet/ml_vet.csproj b/ml_vet/ml_vet.csproj index 9c8fd1e..2b9cbb9 100644 --- a/ml_vet/ml_vet.csproj +++ b/ml_vet/ml_vet.csproj @@ -14,6 +14,7 @@ embedded true + TRACE;NIGHTLY_BUILD From 5261203833d2286165b9d97dbfc520148d4ee3ef Mon Sep 17 00:00:00 2001 From: SDraw Date: Wed, 25 Jun 2025 01:13:40 +0300 Subject: [PATCH 05/12] Additional nightly fixes --- ml_amt/GameEvents.cs | 38 ------ ml_amt/MotionTweaker.cs | 122 +++++++++-------- ml_bft/FingerSystem.cs | 166 ++++++++++++----------- ml_bft/GameEvents.cs | 38 ------ ml_dht/GameEvents.cs | 38 ------ ml_dht/HeadTracked.cs | 63 +++++---- ml_lme/GameEvents.cs | 38 ------ ml_lme/LeapTracked.cs | 108 ++++++++------- ml_pam/ArmMover.cs | 103 ++++++++------- ml_pam/GameEvents.cs | 38 ------ ml_pmc/GameEvents.cs | 38 ------ ml_pmc/PoseCopycat.cs | 106 ++++++++------- ml_ppu/GameEvents.cs | 38 ------ ml_ppu/PickUpManager.cs | 93 +++++++------ ml_prm/GameEvents.cs | 38 ------ ml_prm/RagdollController.cs | 255 +++++++++++++++++++----------------- 16 files changed, 570 insertions(+), 750 deletions(-) diff --git a/ml_amt/GameEvents.cs b/ml_amt/GameEvents.cs index 00cb0f8..8400096 100644 --- a/ml_amt/GameEvents.cs +++ b/ml_amt/GameEvents.cs @@ -15,8 +15,6 @@ namespace ml_amt public void Invoke() => m_action?.Invoke(); } - public static readonly GameEvent OnAvatarSetup = new GameEvent(); - public static readonly GameEvent OnAvatarClear = new GameEvent(); public static readonly GameEvent OnAvatarReuse = new GameEvent(); public static readonly GameEvent OnPlayspaceScale = new GameEvent(); @@ -24,18 +22,6 @@ namespace ml_amt { try { - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - p_instance.Patch( typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public), null, @@ -54,30 +40,6 @@ namespace ml_amt } } - static void OnAvatarClear_Postfix() - { - try - { - OnAvatarClear.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnSetupAvatar_Postfix() - { - try - { - OnAvatarSetup.Invoke(); - } - catch(Exception l_exception) - { - MelonLoader.MelonLogger.Error(l_exception); - } - } - static void OnAvatarReinitialize_Postfix() { try diff --git a/ml_amt/MotionTweaker.cs b/ml_amt/MotionTweaker.cs index cc881c6..e81097f 100644 --- a/ml_amt/MotionTweaker.cs +++ b/ml_amt/MotionTweaker.cs @@ -1,5 +1,7 @@ -using ABI_RC.Core.Player; +using ABI.CCK.Components; +using ABI_RC.Core.Player; using ABI_RC.Core.Util.AnimatorManager; +using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.Movement; using RootMotion.FinalIK; @@ -59,8 +61,8 @@ namespace ml_amt Settings.OnProneLimitChanged.AddListener(this.OnProneLimitChanged); Settings.OnMassCenterChanged.AddListener(this.OnMassCenterChanged); - GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup); - GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse); GameEvents.OnPlayspaceScale.AddListener(this.OnPlayspaceScale); } @@ -78,8 +80,8 @@ namespace ml_amt Settings.OnProneLimitChanged.RemoveListener(this.OnProneLimitChanged); Settings.OnMassCenterChanged.RemoveListener(this.OnMassCenterChanged); - GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup); - GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse); GameEvents.OnPlayspaceScale.RemoveListener(this.OnPlayspaceScale); } @@ -96,68 +98,82 @@ namespace ml_amt } // Game events - void OnAvatarClear() + void OnAvatarClear(CVRAvatar p_avatar) { - m_vrIk = null; - m_avatarReady = false; - m_avatarScale = 1f; - m_locomotionOffset = Vector3.zero; - m_massCenter = Vector3.zero; - m_ikLimits = null; - m_parameters.Clear(); + try + { + m_vrIk = null; + m_avatarReady = false; + m_avatarScale = 1f; + m_locomotionOffset = Vector3.zero; + m_massCenter = Vector3.zero; + m_ikLimits = null; + m_parameters.Clear(); - BetterBetterCharacterController.Instance.avatarCrouchLimit = Mathf.Clamp01(Settings.CrouchLimit); - BetterBetterCharacterController.Instance.avatarProneLimit = Mathf.Clamp01(Settings.ProneLimit); + BetterBetterCharacterController.Instance.avatarCrouchLimit = Mathf.Clamp01(Settings.CrouchLimit); + BetterBetterCharacterController.Instance.avatarProneLimit = Mathf.Clamp01(Settings.ProneLimit); + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); + } } - void OnAvatarSetup() + void OnAvatarSetup(CVRAvatar p_avatar) { - Utils.SetAvatarTPose(); - - m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent(); - m_avatarScale = Mathf.Abs(PlayerSetup.Instance.AvatarTransform.localScale.y); - - // Parse animator parameters - m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Moving, PlayerSetup.Instance.AnimatorManager)); - m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.MovementSpeed, PlayerSetup.Instance.AnimatorManager)); - m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Velocity, PlayerSetup.Instance.AnimatorManager)); - m_parameters.RemoveAll(p => !p.IsValid()); - - // Avatar custom IK limits - m_ikLimits = PlayerSetup.Instance.AvatarTransform.Find("[IKLimits]"); - UpdateIKLimits(); - - // Apply VRIK tweaks - if(m_vrIk != null) + try { - m_locomotionOffset = m_vrIk.solver.locomotion.offset; - m_massCenter = m_locomotionOffset; + Utils.SetAvatarTPose(); - if(m_vrIk.solver.HasToes()) + m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent(); + m_avatarScale = Mathf.Abs(PlayerSetup.Instance.AvatarTransform.localScale.y); + + // Parse animator parameters + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Moving, PlayerSetup.Instance.AnimatorManager)); + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.MovementSpeed, PlayerSetup.Instance.AnimatorManager)); + m_parameters.Add(new AvatarParameter(AvatarParameter.ParameterType.Velocity, PlayerSetup.Instance.AnimatorManager)); + m_parameters.RemoveAll(p => !p.IsValid()); + + // Avatar custom IK limits + m_ikLimits = PlayerSetup.Instance.AvatarTransform.Find("[IKLimits]"); + UpdateIKLimits(); + + // Apply VRIK tweaks + if(m_vrIk != null) { - Transform l_foot = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.LeftFoot); - if(l_foot == null) - l_foot = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.RightFoot); + m_locomotionOffset = m_vrIk.solver.locomotion.offset; + m_massCenter = m_locomotionOffset; - Transform l_toe = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.LeftToes); - if(l_toe == null) - l_toe = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.RightToes); - - if((l_foot != null) && (l_toe != null)) + if(m_vrIk.solver.HasToes()) { - Vector3 l_footPos = (PlayerSetup.Instance.AvatarTransform.GetMatrix().inverse * l_foot.GetMatrix()).GetPosition(); - Vector3 l_toePos = (PlayerSetup.Instance.AvatarTransform.GetMatrix().inverse * l_toe.GetMatrix()).GetPosition(); - m_massCenter = new Vector3(0f, 0f, l_toePos.z - l_footPos.z); + Transform l_foot = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.LeftFoot); + if(l_foot == null) + l_foot = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.RightFoot); + + Transform l_toe = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.LeftToes); + if(l_toe == null) + l_toe = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.RightToes); + + if((l_foot != null) && (l_toe != null)) + { + Vector3 l_footPos = (PlayerSetup.Instance.AvatarTransform.GetMatrix().inverse * l_foot.GetMatrix()).GetPosition(); + Vector3 l_toePos = (PlayerSetup.Instance.AvatarTransform.GetMatrix().inverse * l_toe.GetMatrix()).GetPosition(); + m_massCenter = new Vector3(0f, 0f, l_toePos.z - l_footPos.z); + } } + + m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? m_massCenter : m_locomotionOffset); + + m_vrIk.onPreSolverUpdate.AddListener(this.OnIKPreSolverUpdate); + m_vrIk.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate); } - m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? m_massCenter : m_locomotionOffset); - - m_vrIk.onPreSolverUpdate.AddListener(this.OnIKPreSolverUpdate); - m_vrIk.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate); + m_avatarReady = true; + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); } - - m_avatarReady = true; } void OnPlayspaceScale() diff --git a/ml_bft/FingerSystem.cs b/ml_bft/FingerSystem.cs index 6899264..8946ef3 100644 --- a/ml_bft/FingerSystem.cs +++ b/ml_bft/FingerSystem.cs @@ -1,5 +1,7 @@ -using ABI_RC.Core.Player; +using ABI.CCK.Components; +using ABI_RC.Core.Player; using ABI_RC.Core.Savior; +using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.IK; using ABI_RC.Systems.InputManagement; using System.Collections.Generic; @@ -92,8 +94,8 @@ namespace ml_bft m_pose = new HumanPose(); m_lastValues = new float[40]; - GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup); - GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse); GameEvents.OnIKSystemLateUpdate.AddListener(this.OnIKSystemLateUpdate); } @@ -106,99 +108,113 @@ namespace ml_bft m_rightFingerOffsets.Clear(); m_ready = false; - GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup); - GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse); GameEvents.OnIKSystemLateUpdate.RemoveListener(this.OnIKSystemLateUpdate); } - internal void OnAvatarSetup() + internal void OnAvatarSetup(CVRAvatar p_avatar) { - Animator l_animator = PlayerSetup.Instance.Animator; - if(l_animator.isHuman) + try { - Utils.SetAvatarTPose(); - InputHandler.Instance.Rebind(PlayerSetup.Instance.transform.rotation); - - foreach(var l_tuple in ms_fingersChains) + Animator l_animator = PlayerSetup.Instance.Animator; + if(l_animator.isHuman) { - ReorientateTowards( - PlayerSetup.Instance.transform, - l_animator.GetBoneTransform(l_tuple.Item1), - (l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null, - InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3), - InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3), - PlaneType.OXZ - ); - ReorientateTowards( - PlayerSetup.Instance.transform, - l_animator.GetBoneTransform(l_tuple.Item1), - (l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null, - InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3), - InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3), - PlaneType.OYX - ); - } + Utils.SetAvatarTPose(); + InputHandler.Instance.Rebind(PlayerSetup.Instance.transform.rotation); - // Bind hands - m_leftHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.LeftHand); - m_leftHandOffset.m_target = InputHandler.Instance.GetSourceForBone(HumanBodyBones.LeftHand, true); - if((m_leftHandOffset.m_source != null) && (m_leftHandOffset.m_target != null)) - m_leftHandOffset.m_offset = Quaternion.Inverse(m_leftHandOffset.m_source.rotation) * m_leftHandOffset.m_target.rotation; - - m_rightHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.RightHand); - m_rightHandOffset.m_target = InputHandler.Instance.GetSourceForBone(HumanBodyBones.RightHand, false); - if((m_rightHandOffset.m_source != null) && (m_rightHandOffset.m_target != null)) - m_rightHandOffset.m_offset = Quaternion.Inverse(m_rightHandOffset.m_source.rotation) * m_rightHandOffset.m_target.rotation; - - // Bind fingers - foreach(HumanBodyBones p_bone in ms_leftFingerBones) - { - Transform l_avatarBone = l_animator.GetBoneTransform(p_bone); - Transform l_controllerBone = InputHandler.Instance.GetSourceForBone(p_bone, true); - if((l_avatarBone != null) && (l_controllerBone != null)) + foreach(var l_tuple in ms_fingersChains) { - RotationOffset l_offset = new RotationOffset(); - l_offset.m_source = l_controllerBone; - l_offset.m_target = l_avatarBone; - l_offset.m_offset = Quaternion.Inverse(l_controllerBone.rotation) * l_avatarBone.rotation; - m_leftFingerOffsets.Add(l_offset); + ReorientateTowards( + PlayerSetup.Instance.transform, + l_animator.GetBoneTransform(l_tuple.Item1), + (l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null, + InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3), + InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3), + PlaneType.OXZ + ); + ReorientateTowards( + PlayerSetup.Instance.transform, + l_animator.GetBoneTransform(l_tuple.Item1), + (l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null, + InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3), + InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3), + PlaneType.OYX + ); } - } - foreach(HumanBodyBones p_bone in ms_rightFingerBones) - { - Transform l_avatarBone = l_animator.GetBoneTransform(p_bone); - Transform l_controllerBone = InputHandler.Instance.GetSourceForBone(p_bone, false); - if((l_avatarBone != null) && (l_controllerBone != null)) - { - RotationOffset l_offset = new RotationOffset(); - l_offset.m_source = l_controllerBone; - l_offset.m_target = l_avatarBone; - l_offset.m_offset = Quaternion.Inverse(l_controllerBone.rotation) * l_avatarBone.rotation; - m_rightFingerOffsets.Add(l_offset); - } - } - m_ready = ((m_leftFingerOffsets.Count > 0) || (m_rightFingerOffsets.Count > 0)); + // Bind hands + m_leftHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.LeftHand); + m_leftHandOffset.m_target = InputHandler.Instance.GetSourceForBone(HumanBodyBones.LeftHand, true); + if((m_leftHandOffset.m_source != null) && (m_leftHandOffset.m_target != null)) + m_leftHandOffset.m_offset = Quaternion.Inverse(m_leftHandOffset.m_source.rotation) * m_leftHandOffset.m_target.rotation; + + m_rightHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.RightHand); + m_rightHandOffset.m_target = InputHandler.Instance.GetSourceForBone(HumanBodyBones.RightHand, false); + if((m_rightHandOffset.m_source != null) && (m_rightHandOffset.m_target != null)) + m_rightHandOffset.m_offset = Quaternion.Inverse(m_rightHandOffset.m_source.rotation) * m_rightHandOffset.m_target.rotation; + + // Bind fingers + foreach(HumanBodyBones p_bone in ms_leftFingerBones) + { + Transform l_avatarBone = l_animator.GetBoneTransform(p_bone); + Transform l_controllerBone = InputHandler.Instance.GetSourceForBone(p_bone, true); + if((l_avatarBone != null) && (l_controllerBone != null)) + { + RotationOffset l_offset = new RotationOffset(); + l_offset.m_source = l_controllerBone; + l_offset.m_target = l_avatarBone; + l_offset.m_offset = Quaternion.Inverse(l_controllerBone.rotation) * l_avatarBone.rotation; + m_leftFingerOffsets.Add(l_offset); + } + } + foreach(HumanBodyBones p_bone in ms_rightFingerBones) + { + Transform l_avatarBone = l_animator.GetBoneTransform(p_bone); + Transform l_controllerBone = InputHandler.Instance.GetSourceForBone(p_bone, false); + if((l_avatarBone != null) && (l_controllerBone != null)) + { + RotationOffset l_offset = new RotationOffset(); + l_offset.m_source = l_controllerBone; + l_offset.m_target = l_avatarBone; + l_offset.m_offset = Quaternion.Inverse(l_controllerBone.rotation) * l_avatarBone.rotation; + m_rightFingerOffsets.Add(l_offset); + } + } + + m_ready = ((m_leftFingerOffsets.Count > 0) || (m_rightFingerOffsets.Count > 0)); + } + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); } } - internal void OnAvatarClear() + internal void OnAvatarClear(CVRAvatar p_avatar) { - m_ready = false; - m_pose = new HumanPose(); + try + { + m_ready = false; + m_pose = new HumanPose(); - m_leftHandOffset.Reset(); - m_rightHandOffset.Reset(); + m_leftHandOffset.Reset(); + m_rightHandOffset.Reset(); - m_leftFingerOffsets.Clear(); - m_rightFingerOffsets.Clear(); + m_leftFingerOffsets.Clear(); + m_rightFingerOffsets.Clear(); + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); + } } internal void OnAvatarReuse() { - OnAvatarClear(); - OnAvatarSetup(); + OnAvatarClear(PlayerSetup.Instance.AvatarDescriptor); + OnAvatarSetup(PlayerSetup.Instance.AvatarDescriptor); } internal void OnIKSystemLateUpdate(HumanPoseHandler p_handler, Transform p_hips) diff --git a/ml_bft/GameEvents.cs b/ml_bft/GameEvents.cs index 58ea46a..0b3d7a6 100644 --- a/ml_bft/GameEvents.cs +++ b/ml_bft/GameEvents.cs @@ -24,8 +24,6 @@ namespace ml_bft public void Invoke(T1 p_objA, T2 p_objB) => m_action?.Invoke(p_objA, p_objB); } - public static readonly GameEvent OnAvatarSetup = new GameEvent(); - public static readonly GameEvent OnAvatarClear = new GameEvent(); public static readonly GameEvent OnAvatarReuse = new GameEvent(); public static readonly GameEvent OnInputUpdate = new GameEvent(); public static readonly GameEvent OnIKSystemLateUpdate = new GameEvent(); @@ -34,18 +32,6 @@ namespace ml_bft { try { - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - p_instance.Patch( typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public), null, @@ -70,30 +56,6 @@ namespace ml_bft } } - static void OnAvatarClear_Postfix() - { - try - { - OnAvatarClear.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnSetupAvatar_Postfix() - { - try - { - OnAvatarSetup.Invoke(); - } - catch(Exception l_exception) - { - MelonLoader.MelonLogger.Error(l_exception); - } - } - static void OnAvatarReinitialize_Postfix() { try diff --git a/ml_dht/GameEvents.cs b/ml_dht/GameEvents.cs index 56e8043..03f2d3d 100644 --- a/ml_dht/GameEvents.cs +++ b/ml_dht/GameEvents.cs @@ -35,8 +35,6 @@ namespace ml_dht public void Invoke(T1 p_objA, T2 p_objB) => m_action?.Invoke(p_objA, p_objB); } - public static readonly GameEvent OnAvatarSetup = new GameEvent(); - public static readonly GameEvent OnAvatarClear = new GameEvent(); public static readonly GameEvent OnAvatarReuse = new GameEvent(); public static readonly GameEvent OnEyeControllerUpdate = new GameEvent(); public static readonly GameEvent OnFaceTrackingUpdate = new GameEvent(); @@ -47,18 +45,6 @@ namespace ml_dht { try { - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - p_instance.Patch( typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public), null, @@ -92,30 +78,6 @@ namespace ml_dht } } - static void OnSetupAvatar_Postfix() - { - try - { - OnAvatarSetup.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnAvatarClear_Postfix() - { - try - { - OnAvatarClear.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - static void OnAvatarReinitialize_Postfix() { try diff --git a/ml_dht/HeadTracked.cs b/ml_dht/HeadTracked.cs index 424c326..7ed33b2 100644 --- a/ml_dht/HeadTracked.cs +++ b/ml_dht/HeadTracked.cs @@ -2,6 +2,7 @@ using ABI_RC.Core.Player; using ABI_RC.Core.Player.EyeMovement; using ABI_RC.Systems.FaceTracking; +using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.IK; using ABI_RC.Systems.VRModeSwitch; using RootMotion.FinalIK; @@ -69,8 +70,8 @@ namespace ml_dht Settings.OnHeadTrackingChanged.AddListener(this.OnEnabledOrHeadTrackingChanged); Settings.OnSmoothingChanged.AddListener(this.OnSmoothingChanged); - GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarSetup); GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse); GameEvents.OnEyeControllerUpdate.AddListener(this.OnEyeControllerUpdate); GameEvents.OnFaceTrackingUpdate.AddListener(this.UpdateFaceTracking); @@ -89,8 +90,8 @@ namespace ml_dht Settings.OnHeadTrackingChanged.RemoveListener(this.OnEnabledOrHeadTrackingChanged); Settings.OnSmoothingChanged.RemoveListener(this.OnSmoothingChanged); - GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarSetup); GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse); GameEvents.OnEyeControllerUpdate.RemoveListener(this.OnEyeControllerUpdate); GameEvents.OnFaceTrackingUpdate.RemoveListener(this.UpdateFaceTracking); @@ -137,33 +138,47 @@ namespace ml_dht } // Game events - internal void OnAvatarSetup() + internal void OnAvatarSetup(CVRAvatar p_avatar) { - m_camera = PlayerSetup.Instance.activeCam.transform; - m_avatarDescriptor = PlayerSetup.Instance.AvatarObject.GetComponent(); - - if(PlayerSetup.Instance.Animator.isHuman) + try { - IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; - PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; + m_camera = PlayerSetup.Instance.activeCam.transform; + m_avatarDescriptor = PlayerSetup.Instance.AvatarObject.GetComponent(); - m_headBone = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.Head); - if(m_headBone != null) - m_bindRotation = Quaternion.Inverse(m_avatarDescriptor.transform.rotation) * m_headBone.rotation; + if(PlayerSetup.Instance.Animator.isHuman) + { + IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; - m_lookIK = PlayerSetup.Instance.AvatarObject.GetComponent(); - if(m_lookIK != null) - m_lookIK.onPostSolverUpdate.AddListener(this.OnLookIKPostUpdate); + m_headBone = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.Head); + if(m_headBone != null) + m_bindRotation = Quaternion.Inverse(m_avatarDescriptor.transform.rotation) * m_headBone.rotation; + + m_lookIK = PlayerSetup.Instance.AvatarObject.GetComponent(); + if(m_lookIK != null) + m_lookIK.onPostSolverUpdate.AddListener(this.OnLookIKPostUpdate); + } + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); } } - void OnAvatarClear() + void OnAvatarClear(CVRAvatar p_avatar) { - m_avatarDescriptor = null; - m_lookIK = null; - m_headBone = null; - m_lastHeadRotation = Quaternion.identity; - m_bindRotation = Quaternion.identity; + try + { + m_avatarDescriptor = null; + m_lookIK = null; + m_headBone = null; + m_lastHeadRotation = Quaternion.identity; + m_bindRotation = Quaternion.identity; + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } } void OnAvatarReuse() { diff --git a/ml_lme/GameEvents.cs b/ml_lme/GameEvents.cs index 54c77b3..281b9eb 100644 --- a/ml_lme/GameEvents.cs +++ b/ml_lme/GameEvents.cs @@ -23,8 +23,6 @@ namespace ml_lme public void Invoke(T1 p_obj) => m_action?.Invoke(p_obj); } - public static readonly GameEvent OnAvatarSetup = new GameEvent(); - public static readonly GameEvent OnAvatarClear = new GameEvent(); public static readonly GameEvent OnAvatarReuse = new GameEvent(); public static readonly GameEvent OnRayScale = new GameEvent(); public static readonly GameEvent OnPlayspaceScale = new GameEvent(); @@ -34,18 +32,6 @@ namespace ml_lme { try { - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - p_instance.Patch( typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public), null, @@ -76,30 +62,6 @@ namespace ml_lme } } - static void OnAvatarClear_Postfix() - { - try - { - OnAvatarClear.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnSetupAvatar_Postfix() - { - try - { - OnAvatarSetup.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - static void OnAvatarReinitialize_Postfix() { try diff --git a/ml_lme/LeapTracked.cs b/ml_lme/LeapTracked.cs index e9bace1..211fc4c 100644 --- a/ml_lme/LeapTracked.cs +++ b/ml_lme/LeapTracked.cs @@ -1,4 +1,6 @@ -using ABI_RC.Core.Player; +using ABI.CCK.Components; +using ABI_RC.Core.Player; +using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.IK; using RootMotion.FinalIK; using System.Collections.Generic; @@ -148,8 +150,8 @@ namespace ml_lme Settings.OnFingersOnlyChanged.AddListener(this.OnEnabledOrFingersOnlyChanged); Settings.OnTrackElbowsChanged.AddListener(this.OnTrackElbowsChanged); - GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse); } @@ -174,8 +176,8 @@ namespace ml_lme Settings.OnFingersOnlyChanged.RemoveListener(this.OnEnabledOrFingersOnlyChanged); Settings.OnTrackElbowsChanged.RemoveListener(this.OnTrackElbowsChanged); - GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse); } @@ -255,58 +257,72 @@ namespace ml_lme } // Game events - void OnAvatarClear() + void OnAvatarClear(CVRAvatar p_avatar) { - m_vrIK = null; - m_hips = null; - m_leftArmIK = null; - m_rightArmIK = null; - m_leftTargetActive = false; - m_rightTargetActive = false; + try + { + m_vrIK = null; + m_hips = null; + m_leftArmIK = null; + m_rightArmIK = null; + m_leftTargetActive = false; + m_rightTargetActive = false; - m_poseHandler?.Dispose(); - m_poseHandler = null; + m_poseHandler?.Dispose(); + m_poseHandler = null; - m_leftHandTarget.localPosition = Vector3.zero; - m_leftHandTarget.localRotation = Quaternion.identity; - m_rightHandTarget.localPosition = Vector3.zero; - m_rightHandTarget.localRotation = Quaternion.identity; + m_leftHandTarget.localPosition = Vector3.zero; + m_leftHandTarget.localRotation = Quaternion.identity; + m_rightHandTarget.localPosition = Vector3.zero; + m_rightHandTarget.localRotation = Quaternion.identity; - m_leftHandOffset.Reset(); - m_rightHandOffset.Reset(); + m_leftHandOffset.Reset(); + m_rightHandOffset.Reset(); - m_leftFingerOffsets.Clear(); - m_rightFingerOffsets.Clear(); + m_leftFingerOffsets.Clear(); + m_rightFingerOffsets.Clear(); + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); + } } - void OnAvatarSetup() + void OnAvatarSetup(CVRAvatar p_avatar) { - Animator l_animator = PlayerSetup.Instance.Animator; - if(l_animator.isHuman) + try { - Utils.SetAvatarTPose(); - - m_poseHandler = new HumanPoseHandler(l_animator.avatar, l_animator.transform); - m_poseHandler.GetHumanPose(ref m_pose); - - m_hips = l_animator.GetBoneTransform(HumanBodyBones.Hips); - - m_leftHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.LeftHand); - m_leftHandTarget.localRotation = ms_offsetLeft * (Quaternion.Inverse(l_animator.transform.rotation) * m_leftHandOffset.m_source.rotation); - - m_rightHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.RightHand); - m_rightHandTarget.localRotation = ms_offsetRight * (Quaternion.Inverse(l_animator.transform.rotation) * m_rightHandOffset.m_source.rotation); - - ParseFingersBones(); - - m_vrIK = l_animator.GetComponent(); - if(m_vrIK != null) + Animator l_animator = PlayerSetup.Instance.Animator; + if(l_animator.isHuman) { - m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreSolverUpdate); - m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate); + Utils.SetAvatarTPose(); + + m_poseHandler = new HumanPoseHandler(l_animator.avatar, l_animator.transform); + m_poseHandler.GetHumanPose(ref m_pose); + + m_hips = l_animator.GetBoneTransform(HumanBodyBones.Hips); + + m_leftHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.LeftHand); + m_leftHandTarget.localRotation = ms_offsetLeft * (Quaternion.Inverse(l_animator.transform.rotation) * m_leftHandOffset.m_source.rotation); + + m_rightHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.RightHand); + m_rightHandTarget.localRotation = ms_offsetRight * (Quaternion.Inverse(l_animator.transform.rotation) * m_rightHandOffset.m_source.rotation); + + ParseFingersBones(); + + m_vrIK = l_animator.GetComponent(); + if(m_vrIK != null) + { + m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreSolverUpdate); + m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate); + } + else + SetupArmIK(); } - else - SetupArmIK(); + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); } } diff --git a/ml_pam/ArmMover.cs b/ml_pam/ArmMover.cs index a4aebf8..7b2d567 100644 --- a/ml_pam/ArmMover.cs +++ b/ml_pam/ArmMover.cs @@ -1,6 +1,7 @@ using ABI.CCK.Components; using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Player; +using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.VRModeSwitch; using RootMotion.FinalIK; using System.Collections; @@ -100,8 +101,8 @@ namespace ml_pam Settings.OnLeadingHandChanged.AddListener(this.OnLeadingHandChanged); Settings.OnHandsExtensionChanged.AddListener(this.OnHandsExtensionChanged); - GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup); GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse); GameEvents.OnIKScaling.AddListener(this.OnIKScaling); GameEvents.OnPickupGrab.AddListener(this.OnPickupGrab); @@ -149,10 +150,10 @@ namespace ml_pam Settings.OnLeadingHandChanged.RemoveListener(this.OnLeadingHandChanged); Settings.OnHandsExtensionChanged.RemoveListener(this.OnHandsExtensionChanged); - GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup); GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse); - GameEvents.OnIKScaling.AddListener(this.OnIKScaling); + GameEvents.OnIKScaling.RemoveListener(this.OnIKScaling); GameEvents.OnPickupGrab.RemoveListener(this.OnPickupGrab); GameEvents.OnPickupDrop.RemoveListener(this.OnPickupDrop); @@ -341,66 +342,80 @@ namespace ml_pam } // Game events - void OnAvatarClear() + void OnAvatarClear(CVRAvatar p_avatar) { - m_vrIK = null; - m_armIKLeft = null; - m_armIKRight = null; - m_armsLength.Set(0f, 0f, 0f, 0f); - m_leftHandParameter = null; - m_rightHandParameter = null; + try + { + m_vrIK = null; + m_armIKLeft = null; + m_armIKRight = null; + m_armsLength.Set(0f, 0f, 0f, 0f); + m_leftHandParameter = null; + m_rightHandParameter = null; + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); + } } - void OnAvatarSetup() + void OnAvatarSetup(CVRAvatar p_avatar) { - m_camera = PlayerSetup.Instance.activeCam.transform; - - if(PlayerSetup.Instance.Animator.isHuman) + try { - m_vrIK = PlayerSetup.Instance.Animator.GetComponent(); - Utils.SetAvatarTPose(); + m_camera = PlayerSetup.Instance.activeCam.transform; - Animator l_animator = PlayerSetup.Instance.Animator; - Matrix4x4 l_avatarMatrixInv = l_animator.transform.GetMatrix().inverse; // Animator and avatar are on same game object + if(PlayerSetup.Instance.Animator.isHuman) + { + m_vrIK = PlayerSetup.Instance.Animator.GetComponent(); + Utils.SetAvatarTPose(); - Transform l_leftHand = l_animator.GetBoneTransform(HumanBodyBones.LeftHand); - if(l_leftHand != null) - m_leftRotationTarget.localRotation = ms_offsetLeft * (l_avatarMatrixInv * l_leftHand.GetMatrix()).rotation; - Transform l_rightHand = l_animator.GetBoneTransform(HumanBodyBones.RightHand); - if(l_rightHand != null) - m_rightRotationTarget.localRotation = ms_offsetRight * (l_avatarMatrixInv * l_rightHand.GetMatrix()).rotation; + Animator l_animator = PlayerSetup.Instance.Animator; + Matrix4x4 l_avatarMatrixInv = l_animator.transform.GetMatrix().inverse; // Animator and avatar are on same game object - m_armsLength.x = GetChainLength(new Transform[]{ + Transform l_leftHand = l_animator.GetBoneTransform(HumanBodyBones.LeftHand); + if(l_leftHand != null) + m_leftRotationTarget.localRotation = ms_offsetLeft * (l_avatarMatrixInv * l_leftHand.GetMatrix()).rotation; + Transform l_rightHand = l_animator.GetBoneTransform(HumanBodyBones.RightHand); + if(l_rightHand != null) + m_rightRotationTarget.localRotation = ms_offsetRight * (l_avatarMatrixInv * l_rightHand.GetMatrix()).rotation; + + m_armsLength.x = GetChainLength(new Transform[]{ l_animator.GetBoneTransform(HumanBodyBones.LeftUpperArm), l_animator.GetBoneTransform(HumanBodyBones.LeftLowerArm), l_animator.GetBoneTransform(HumanBodyBones.LeftHand) }); - m_armsLength.y = GetChainLength(new Transform[]{ + m_armsLength.y = GetChainLength(new Transform[]{ l_animator.GetBoneTransform(HumanBodyBones.RightUpperArm), l_animator.GetBoneTransform(HumanBodyBones.RightLowerArm), l_animator.GetBoneTransform(HumanBodyBones.RightHand) }); - m_armsLength.z = Mathf.Abs((l_avatarMatrixInv * l_animator.GetBoneTransform(HumanBodyBones.LeftUpperArm).GetMatrix()).GetPosition().x); - m_armsLength.w = Mathf.Abs((l_avatarMatrixInv * l_animator.GetBoneTransform(HumanBodyBones.RightUpperArm).GetMatrix()).GetPosition().x); + m_armsLength.z = Mathf.Abs((l_avatarMatrixInv * l_animator.GetBoneTransform(HumanBodyBones.LeftUpperArm).GetMatrix()).GetPosition().x); + m_armsLength.w = Mathf.Abs((l_avatarMatrixInv * l_animator.GetBoneTransform(HumanBodyBones.RightUpperArm).GetMatrix()).GetPosition().x); - if(!Utils.IsInVR()) - { - if(m_vrIK != null) + if(!Utils.IsInVR()) { - m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreUpdate); - m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostUpdate); + if(m_vrIK != null) + { + m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreUpdate); + m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostUpdate); + } + else + SetupArmIK(); } - else - SetupArmIK(); } + + m_leftHandParameter = new AvatarBoolParameter("LeftHandExtended", PlayerSetup.Instance.AnimatorManager); + m_rightHandParameter = new AvatarBoolParameter("RightHandExtended", PlayerSetup.Instance.AnimatorManager); + + OnEnabledChanged(Settings.Enabled); + OnGrabOffsetChanged(Settings.GrabOffset); + OnIKScaling(1f); // Reset scaling, game doesn't do this anymore on avatar switch + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); } - - m_leftHandParameter = new AvatarBoolParameter("LeftHandExtended", PlayerSetup.Instance.AnimatorManager); - m_rightHandParameter = new AvatarBoolParameter("RightHandExtended", PlayerSetup.Instance.AnimatorManager); - - OnEnabledChanged(Settings.Enabled); - OnGrabOffsetChanged(Settings.GrabOffset); - OnIKScaling(1f); // Reset scaling, game doesn't do this anymore on avatar switch } void OnAvatarReuse() diff --git a/ml_pam/GameEvents.cs b/ml_pam/GameEvents.cs index 188e773..64c2f63 100644 --- a/ml_pam/GameEvents.cs +++ b/ml_pam/GameEvents.cs @@ -31,8 +31,6 @@ namespace ml_pam public void Invoke(T1 p_objA, T2 p_objB) => m_action?.Invoke(p_objA, p_objB); } - public static readonly GameEvent OnAvatarSetup = new GameEvent(); - public static readonly GameEvent OnAvatarClear = new GameEvent(); public static readonly GameEvent OnAvatarReuse = new GameEvent(); public static readonly GameEvent OnIKScaling = new GameEvent(); public static readonly GameEvent OnPickupGrab = new GameEvent(); @@ -42,18 +40,6 @@ namespace ml_pam { try { - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - p_instance.Patch( typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public), null, @@ -84,30 +70,6 @@ namespace ml_pam } } - static void OnAvatarClear_Postfix() - { - try - { - OnAvatarClear.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnSetupAvatar_Postfix() - { - try - { - OnAvatarSetup.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - static void OnAvatarReinitialize_Postfix() { try diff --git a/ml_pmc/GameEvents.cs b/ml_pmc/GameEvents.cs index 389065b..3f61aaf 100644 --- a/ml_pmc/GameEvents.cs +++ b/ml_pmc/GameEvents.cs @@ -15,8 +15,6 @@ namespace ml_pmc public void Invoke() => m_action?.Invoke(); } - public static readonly GameEvent OnAvatarSetup = new GameEvent(); - public static readonly GameEvent OnAvatarClear = new GameEvent(); public static readonly GameEvent OnAvatarPreReuse = new GameEvent(); public static readonly GameEvent OnAvatarPostReuse = new GameEvent(); @@ -24,18 +22,6 @@ namespace ml_pmc { try { - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - p_instance.Patch( typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public), new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarReinitialize_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), @@ -48,30 +34,6 @@ namespace ml_pmc } } - static void OnAvatarClear_Postfix() - { - try - { - OnAvatarClear.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnSetupAvatar_Postfix() - { - try - { - OnAvatarSetup.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - static void OnAvatarReinitialize_Prefix() { try diff --git a/ml_pmc/PoseCopycat.cs b/ml_pmc/PoseCopycat.cs index 6aba068..929d5f6 100644 --- a/ml_pmc/PoseCopycat.cs +++ b/ml_pmc/PoseCopycat.cs @@ -1,5 +1,7 @@ -using ABI_RC.Core.Networking.IO.Social; +using ABI.CCK.Components; +using ABI_RC.Core.Networking.IO.Social; using ABI_RC.Core.Player; +using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.IK; using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.InputManagement; @@ -55,8 +57,8 @@ namespace ml_pmc void Start() { - GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup); GameEvents.OnAvatarPreReuse.AddListener(this.OnAvatarPreReuse); GameEvents.OnAvatarPostReuse.AddListener(this.OnAvatarPostReuse); @@ -78,8 +80,8 @@ namespace ml_pmc m_vrIk = null; m_lookAtIk = null; - GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup); GameEvents.OnAvatarPreReuse.RemoveListener(this.OnAvatarPreReuse); GameEvents.OnAvatarPostReuse.RemoveListener(this.OnAvatarPostReuse); @@ -229,58 +231,72 @@ namespace ml_pmc } // Game events - void OnAvatarClear() + void OnAvatarClear(CVRAvatar p_avatar) { - if(m_active) + try { - RestoreIK(); - RestoreFingerTracking(); - OnCopycatChanged.Invoke(false); + if(m_active) + { + RestoreIK(); + RestoreFingerTracking(); + OnCopycatChanged.Invoke(false); + } + m_active = false; + + 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_distanceLimit = float.MaxValue; + m_fingerTracking = false; + m_pose = new HumanPose(); + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); } - m_active = false; - - 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_distanceLimit = float.MaxValue; - m_fingerTracking = false; - m_pose = new HumanPose(); } - void OnAvatarSetup() + void OnAvatarSetup(CVRAvatar p_avatar) { - m_inVr = Utils.IsInVR(); - m_animator = PlayerSetup.Instance.Animator; - m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent(); - m_lookAtIk = PlayerSetup.Instance.AvatarObject.GetComponent(); - - if((m_animator != null) && m_animator.isHuman) + try { - m_poseHandler = new HumanPoseHandler(m_animator.avatar, m_animator.transform); - m_poseHandler.GetHumanPose(ref m_pose); + m_inVr = Utils.IsInVR(); + m_animator = PlayerSetup.Instance.Animator; + m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent(); + m_lookAtIk = PlayerSetup.Instance.AvatarObject.GetComponent(); - if(m_vrIk != null) + if((m_animator != null) && m_animator.isHuman) { - m_vrIk.onPreSolverUpdate.AddListener(this.OnVRIKPreUpdate); - m_vrIk.onPostSolverUpdate.AddListener(this.OnVRIKPostUpdate); - } + m_poseHandler = new HumanPoseHandler(m_animator.avatar, m_animator.transform); + m_poseHandler.GetHumanPose(ref m_pose); - if(m_lookAtIk != null) - { - m_lookAtIk.onPreSolverUpdate.AddListener(this.OnLookAtIKPreUpdate); - m_lookAtIk.onPostSolverUpdate.AddListener(this.OnLookAtIKPostUpdate); + 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; + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); } - else - m_animator = null; } void OnAvatarPreReuse() diff --git a/ml_ppu/GameEvents.cs b/ml_ppu/GameEvents.cs index 3ab7057..b8b70dd 100644 --- a/ml_ppu/GameEvents.cs +++ b/ml_ppu/GameEvents.cs @@ -23,8 +23,6 @@ namespace ml_ppu public void Invoke(T1 p_obj) => m_action?.Invoke(p_obj); } - public static readonly GameEvent OnAvatarSetup = new GameEvent(); - public static readonly GameEvent OnAvatarClear = new GameEvent(); public static readonly GameEvent OnIKScaling = new GameEvent(); public static readonly GameEvent OnWorldPreSpawn = new GameEvent(); public static readonly GameEvent OnSeatPreSit = new GameEvent(); @@ -33,18 +31,6 @@ namespace ml_ppu { try { - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static |BindingFlags.NonPublic)) - ); - - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - p_instance.Patch( typeof(PlayerSetup).GetMethod("SetupIKScaling", BindingFlags.Instance | BindingFlags.NonPublic), null, @@ -69,30 +55,6 @@ namespace ml_ppu } } - static void OnAvatarClear_Postfix() - { - try - { - OnAvatarClear.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnSetupAvatar_Postfix() - { - try - { - OnAvatarSetup.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - static void OnSetupIKScaling_Postfix(ref UnityEngine.Vector3 ___scaleDifference) { try diff --git a/ml_ppu/PickUpManager.cs b/ml_ppu/PickUpManager.cs index 9030588..9ee2ab1 100644 --- a/ml_ppu/PickUpManager.cs +++ b/ml_ppu/PickUpManager.cs @@ -2,6 +2,7 @@ using ABI_RC.Core; using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Player; +using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.IK; using ABI_RC.Systems.Movement; using UnityEngine; @@ -46,8 +47,8 @@ namespace ml_ppu void Start() { - GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup); - GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear); GameEvents.OnIKScaling.AddListener(this.OnIKScaling); GameEvents.OnWorldPreSpawn.AddListener(this.OnWorldPreSpawn); GameEvents.OnSeatPreSit.AddListener(this.OnSeatPreSit); @@ -60,8 +61,8 @@ namespace ml_ppu if(Instance == this) Instance = null; - GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup); - GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear); GameEvents.OnIKScaling.RemoveListener(this.OnIKScaling); GameEvents.OnWorldPreSpawn.RemoveListener(this.OnWorldPreSpawn); GameEvents.OnSeatPreSit.RemoveListener(this.OnSeatPreSit); @@ -126,53 +127,67 @@ namespace ml_ppu } } - void OnAvatarSetup() + void OnAvatarSetup(CVRAvatar p_avatar) { - Animator l_animator = PlayerSetup.Instance.Animator; - if((l_animator != null) && l_animator.isHuman) + try { - IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; - PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; - - m_hips = l_animator.GetBoneTransform(HumanBodyBones.Hips); - m_armLeft = l_animator.GetBoneTransform(HumanBodyBones.LeftUpperArm); - m_armRight = l_animator.GetBoneTransform(HumanBodyBones.RightUpperArm); - - if((m_hips != null) && (m_armLeft != null) && (m_armRight != null)) + Animator l_animator = PlayerSetup.Instance.Animator; + if((l_animator != null) && l_animator.isHuman) { - Matrix4x4 l_avatarMatInv = PlayerSetup.Instance.AvatarTransform.GetMatrix().inverse; - Vector3 l_hipsPos = (l_avatarMatInv * m_hips.GetMatrix()).GetPosition(); - Vector3 l_armPos = (l_avatarMatInv * m_armLeft.GetMatrix()).GetPosition(); + IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; - m_collider = new GameObject("[Collider]").AddComponent(); - m_collider.gameObject.layer = CVRLayers.PlayerClone; - m_collider.transform.parent = this.transform; - m_collider.isTrigger = true; - m_collider.height = Vector3.Distance(l_hipsPos, new Vector3(0f, l_armPos.y, l_armPos.z)); - m_collider.radius = new Vector2(l_armPos.x, l_armPos.z).magnitude; - m_collider.center = new Vector3(0f, m_collider.height * 0.5f, 0f); - m_collider.gameObject.AddComponent(); + m_hips = l_animator.GetBoneTransform(HumanBodyBones.Hips); + m_armLeft = l_animator.GetBoneTransform(HumanBodyBones.LeftUpperArm); + m_armRight = l_animator.GetBoneTransform(HumanBodyBones.RightUpperArm); - m_ready = true; + if((m_hips != null) && (m_armLeft != null) && (m_armRight != null)) + { + Matrix4x4 l_avatarMatInv = PlayerSetup.Instance.AvatarTransform.GetMatrix().inverse; + Vector3 l_hipsPos = (l_avatarMatInv * m_hips.GetMatrix()).GetPosition(); + Vector3 l_armPos = (l_avatarMatInv * m_armLeft.GetMatrix()).GetPosition(); + + m_collider = new GameObject("[Collider]").AddComponent(); + m_collider.gameObject.layer = CVRLayers.PlayerClone; + m_collider.transform.parent = this.transform; + m_collider.isTrigger = true; + m_collider.height = Vector3.Distance(l_hipsPos, new Vector3(0f, l_armPos.y, l_armPos.z)); + m_collider.radius = new Vector2(l_armPos.x, l_armPos.z).magnitude; + m_collider.center = new Vector3(0f, m_collider.height * 0.5f, 0f); + m_collider.gameObject.AddComponent(); + + m_ready = true; + } } } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); + } } - void OnAvatarClear() + void OnAvatarClear(CVRAvatar p_avatar) { - m_ready = false; - m_held = false; - - if(m_collider != null) + try { - Destroy(m_collider.gameObject); - m_collider = null; + m_ready = false; + m_held = false; + + if(m_collider != null) + { + Destroy(m_collider.gameObject); + m_collider = null; + } + m_holderPointA = null; + m_holderPointerA = null; + m_holderPointB = null; + m_holderPointerB = null; + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); } - m_holderPointA = null; - m_holderPointerA = null; - m_holderPointB = null; - m_holderPointerB = null; } void OnIKScaling(float p_scale) diff --git a/ml_prm/GameEvents.cs b/ml_prm/GameEvents.cs index 4e48819..ceb534d 100644 --- a/ml_prm/GameEvents.cs +++ b/ml_prm/GameEvents.cs @@ -32,8 +32,6 @@ namespace ml_prm public void Invoke(T1 p_obj) => m_action?.Invoke(p_obj); } - public static readonly GameEvent OnAvatarSetup = new GameEvent(); - public static readonly GameEvent OnAvatarClear = new GameEvent(); public static readonly GameEvent OnAvatarPreReuse = new GameEvent(); public static readonly GameEvent OnAvatarPostReuse = new GameEvent(); public static readonly GameEvent OnIKScaling = new GameEvent(); @@ -50,18 +48,6 @@ namespace ml_prm { try { - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static |BindingFlags.NonPublic)) - ); - - p_instance.Patch( - typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar), BindingFlags.Instance | BindingFlags.Public), - null, - new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) - ); - p_instance.Patch( typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public), new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarReinitialize_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), @@ -115,30 +101,6 @@ namespace ml_prm } } - static void OnAvatarClear_Postfix() - { - try - { - OnAvatarClear.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - static void OnSetupAvatar_Postfix() - { - try - { - OnAvatarSetup.Invoke(); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - static void OnAvatarReinitialize_Prefix() { try diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 0ff7f07..ea98869 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -2,6 +2,7 @@ using ABI_RC.Core; using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Player; +using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.IK; using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.InputManagement; @@ -99,8 +100,8 @@ namespace ml_prm Settings.OnFallDamageChanged.AddListener(this.OnFallDamageChanged); Settings.OnGestureGrabChanged.AddListener(this.OnGestureGrabChanged); - GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup); GameEvents.OnAvatarPreReuse.AddListener(this.OnAvatarPreReuse); GameEvents.OnAvatarPostReuse.AddListener(this.OnAvatarPostReuse); GameEvents.OnIKScaling.AddListener(this.OnAvatarScaling); @@ -148,8 +149,8 @@ namespace ml_prm Settings.OnFallDamageChanged.RemoveListener(this.OnFallDamageChanged); Settings.OnGestureGrabChanged.RemoveListener(this.OnGestureGrabChanged); - GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear); - GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup); GameEvents.OnAvatarPreReuse.RemoveListener(this.OnAvatarPreReuse); GameEvents.OnAvatarPostReuse.RemoveListener(this.OnAvatarPostReuse); GameEvents.OnIKScaling.RemoveListener(this.OnAvatarScaling); @@ -252,129 +253,143 @@ namespace ml_prm } // Game events - void OnAvatarClear() + void OnAvatarClear(CVRAvatar p_avatar) { - if(m_initTask != null) + try { - StopCoroutine(m_initTask); - m_initTask = null; - } - - if(m_ragdolled) - { - TryRestoreMovement(); - BodySystem.TrackingPositionWeight = 1f; - } - - if(m_puppetRoot != null) - Object.Destroy(m_puppetRoot.gameObject); - m_puppetRoot = null; - - m_avatarTransform = null; - m_hips = null; - m_vrIK = null; - m_applyHipsPosition = false; - m_ragdolled = false; - m_avatarReady = false; - m_avatarRagdollToggle = null; - m_ragdolledParameter = null; - m_puppetReferences = new BipedRagdollReferences(); - m_ragdollBodyHandlers.Clear(); - m_boneLinks.Clear(); - m_jointAnchors.Clear(); - m_reachedGround = true; - m_groundedTime = 0f; - m_downTime = float.MinValue; - m_puppet.localScale = Vector3.one; - m_inAir = false; - } - - void OnAvatarSetup() - { - if(PlayerSetup.Instance.Animator.isHuman) - { - m_avatarTransform = PlayerSetup.Instance.AvatarTransform; - m_hips = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.Hips); - Utils.SetAvatarTPose(); - - BipedRagdollReferences l_avatarReferences = BipedRagdollReferences.FromAvatar(PlayerSetup.Instance.Animator); - - m_puppetRoot = new GameObject("Root").transform; - m_puppetRoot.gameObject.layer = CVRLayers.PlayerClone; - m_puppetRoot.parent = m_puppet; - m_puppetRoot.position = m_avatarTransform.position; - m_puppetRoot.rotation = m_avatarTransform.rotation; - - m_puppetReferences.root = m_puppetRoot; - m_puppetReferences.hips = CloneTransform(l_avatarReferences.hips, m_puppetReferences.root, "Hips"); - m_puppetReferences.spine = CloneTransform(l_avatarReferences.spine, m_puppetReferences.hips, "Spine"); - - if(l_avatarReferences.chest != null) - m_puppetReferences.chest = CloneTransform(l_avatarReferences.chest, m_puppetReferences.spine, "Chest"); - - m_puppetReferences.head = CloneTransform(l_avatarReferences.head, (m_puppetReferences.chest != null) ? m_puppetReferences.chest : m_puppetReferences.spine, "Head"); - - 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(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(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(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"); - - // Move to world origin to overcome possible issues - 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); - - Transform[] l_puppetTransforms = m_puppetReferences.GetRagdollTransforms(); - Transform[] l_avatarTransforms = l_avatarReferences.GetRagdollTransforms(); - Transform[] l_influencedTransforms = new Transform[] { m_puppetReferences.hips, m_puppetReferences.spine, m_puppetReferences.chest }; - for(int i = 0; i < l_puppetTransforms.Length; i++) + if(m_initTask != null) { - if(l_puppetTransforms[i] != null) - { - CharacterJoint l_joint = l_puppetTransforms[i].GetComponent(); - if(l_joint != null) - { - l_joint.enablePreprocessing = false; - l_joint.enableProjection = true; - m_jointAnchors.Add(System.Tuple.Create(l_joint, l_joint.connectedAnchor)); - } - - Rigidbody l_body = l_puppetTransforms[i].GetComponent(); - Collider l_collider = l_puppetTransforms[i].GetComponent(); - if((l_body != null) && (l_collider != null)) - { - RagdollBodypartHandler l_handler = l_puppetTransforms[i].gameObject.AddComponent(); - l_handler.SetInfuencerUsage(Utils.IsInEnumeration(l_puppetTransforms[i], l_influencedTransforms)); - m_ragdollBodyHandlers.Add(l_handler); - } - - if(l_avatarTransforms[i] != null) - m_boneLinks.Add(System.Tuple.Create(l_puppetTransforms[i], l_avatarTransforms[i])); - } + StopCoroutine(m_initTask); + m_initTask = null; } - m_vrIK = PlayerSetup.Instance.AvatarObject.GetComponent(); - if(m_vrIK != null) - m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate); + if(m_ragdolled) + { + TryRestoreMovement(); + BodySystem.TrackingPositionWeight = 1f; + } - m_avatarRagdollToggle = PlayerSetup.Instance.AvatarObject.GetComponentInChildren(true); - m_ragdolledParameter = new AvatarParameter("Ragdolled", PlayerSetup.Instance.AnimatorManager); + if(m_puppetRoot != null) + Object.Destroy(m_puppetRoot.gameObject); + m_puppetRoot = null; - m_initTask = StartCoroutine(WaitForBodyHandlers()); + m_avatarTransform = null; + m_hips = null; + m_vrIK = null; + m_applyHipsPosition = false; + m_ragdolled = false; + m_avatarReady = false; + m_avatarRagdollToggle = null; + m_ragdolledParameter = null; + m_puppetReferences = new BipedRagdollReferences(); + m_ragdollBodyHandlers.Clear(); + m_boneLinks.Clear(); + m_jointAnchors.Clear(); + m_reachedGround = true; + m_groundedTime = 0f; + m_downTime = float.MinValue; + m_puppet.localScale = Vector3.one; + m_inAir = false; + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + void OnAvatarSetup(CVRAvatar p_avatar) + { + try + { + if(PlayerSetup.Instance.Animator.isHuman) + { + m_avatarTransform = PlayerSetup.Instance.AvatarTransform; + m_hips = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.Hips); + Utils.SetAvatarTPose(); + + BipedRagdollReferences l_avatarReferences = BipedRagdollReferences.FromAvatar(PlayerSetup.Instance.Animator); + + m_puppetRoot = new GameObject("Root").transform; + m_puppetRoot.gameObject.layer = CVRLayers.PlayerClone; + m_puppetRoot.parent = m_puppet; + m_puppetRoot.position = m_avatarTransform.position; + m_puppetRoot.rotation = m_avatarTransform.rotation; + + m_puppetReferences.root = m_puppetRoot; + m_puppetReferences.hips = CloneTransform(l_avatarReferences.hips, m_puppetReferences.root, "Hips"); + m_puppetReferences.spine = CloneTransform(l_avatarReferences.spine, m_puppetReferences.hips, "Spine"); + + if(l_avatarReferences.chest != null) + m_puppetReferences.chest = CloneTransform(l_avatarReferences.chest, m_puppetReferences.spine, "Chest"); + + m_puppetReferences.head = CloneTransform(l_avatarReferences.head, (m_puppetReferences.chest != null) ? m_puppetReferences.chest : m_puppetReferences.spine, "Head"); + + 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(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(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(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"); + + // Move to world origin to overcome possible issues + 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); + + Transform[] l_puppetTransforms = m_puppetReferences.GetRagdollTransforms(); + Transform[] l_avatarTransforms = l_avatarReferences.GetRagdollTransforms(); + Transform[] l_influencedTransforms = new Transform[] { m_puppetReferences.hips, m_puppetReferences.spine, m_puppetReferences.chest }; + for(int i = 0; i < l_puppetTransforms.Length; i++) + { + if(l_puppetTransforms[i] != null) + { + CharacterJoint l_joint = l_puppetTransforms[i].GetComponent(); + if(l_joint != null) + { + l_joint.enablePreprocessing = false; + l_joint.enableProjection = true; + m_jointAnchors.Add(System.Tuple.Create(l_joint, l_joint.connectedAnchor)); + } + + Rigidbody l_body = l_puppetTransforms[i].GetComponent(); + Collider l_collider = l_puppetTransforms[i].GetComponent(); + if((l_body != null) && (l_collider != null)) + { + RagdollBodypartHandler l_handler = l_puppetTransforms[i].gameObject.AddComponent(); + l_handler.SetInfuencerUsage(Utils.IsInEnumeration(l_puppetTransforms[i], l_influencedTransforms)); + m_ragdollBodyHandlers.Add(l_handler); + } + + if(l_avatarTransforms[i] != null) + m_boneLinks.Add(System.Tuple.Create(l_puppetTransforms[i], l_avatarTransforms[i])); + } + } + + m_vrIK = PlayerSetup.Instance.AvatarObject.GetComponent(); + if(m_vrIK != null) + m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate); + + m_avatarRagdollToggle = PlayerSetup.Instance.AvatarObject.GetComponentInChildren(true); + m_ragdolledParameter = new AvatarParameter("Ragdolled", PlayerSetup.Instance.AnimatorManager); + + m_initTask = StartCoroutine(WaitForBodyHandlers()); + } + } + catch(System.Exception e) + { + MelonLoader.MelonLogger.Error(e); } } From aa5856b10236ef3ac7ae2321c99685bd2eda8f46 Mon Sep 17 00:00:00 2001 From: SDraw Date: Wed, 25 Jun 2025 18:56:45 +0300 Subject: [PATCH 06/12] Fixes for 25/06/2025 nightly game build --- ml_dht/HeadTracked.cs | 8 ++++---- ml_lme/LeapInput.cs | 2 +- ml_pmc/PoseCopycat.cs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ml_dht/HeadTracked.cs b/ml_dht/HeadTracked.cs index 7ed33b2..858241d 100644 --- a/ml_dht/HeadTracked.cs +++ b/ml_dht/HeadTracked.cs @@ -70,8 +70,8 @@ namespace ml_dht Settings.OnHeadTrackingChanged.AddListener(this.OnEnabledOrHeadTrackingChanged); Settings.OnSmoothingChanged.AddListener(this.OnSmoothingChanged); - CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarClear); - CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse); GameEvents.OnEyeControllerUpdate.AddListener(this.OnEyeControllerUpdate); GameEvents.OnFaceTrackingUpdate.AddListener(this.UpdateFaceTracking); @@ -90,8 +90,8 @@ namespace ml_dht Settings.OnHeadTrackingChanged.RemoveListener(this.OnEnabledOrHeadTrackingChanged); Settings.OnSmoothingChanged.RemoveListener(this.OnSmoothingChanged); - CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarClear); - CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear); GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse); GameEvents.OnEyeControllerUpdate.RemoveListener(this.OnEyeControllerUpdate); GameEvents.OnFaceTrackingUpdate.RemoveListener(this.UpdateFaceTracking); diff --git a/ml_lme/LeapInput.cs b/ml_lme/LeapInput.cs index 49eee51..2273bb2 100644 --- a/ml_lme/LeapInput.cs +++ b/ml_lme/LeapInput.cs @@ -651,7 +651,7 @@ namespace ml_lme void SetGameFingersTracking(bool p_state) { base._inputManager.individualFingerTracking = p_state; - IKSystem.Instance.FingerSystem.controlActive = base._inputManager.individualFingerTracking; + IKSystem.Instance.FingerSystem.ControlActive = base._inputManager.individualFingerTracking; } } } diff --git a/ml_pmc/PoseCopycat.cs b/ml_pmc/PoseCopycat.cs index 929d5f6..1a27aba 100644 --- a/ml_pmc/PoseCopycat.cs +++ b/ml_pmc/PoseCopycat.cs @@ -112,7 +112,7 @@ namespace ml_pmc m_fingerTracking = true; CVRInputManager.Instance.individualFingerTracking = true; - IKSystem.Instance.FingerSystem.controlActive = true; + IKSystem.Instance.FingerSystem.ControlActive = true; ref readonly float[] l_curls = ref m_puppetParser.GetFingerCurls(); ref readonly float[] l_spreads = ref m_puppetParser.GetFingerSpreads(); @@ -441,7 +441,7 @@ namespace ml_pmc void RestoreFingerTracking() { CVRInputManager.Instance.individualFingerTracking = (m_inVr && Utils.AreKnucklesInUse() && !CVRInputManager._moduleXR.SkeletalToggleValue); - IKSystem.Instance.FingerSystem.controlActive = CVRInputManager.Instance.individualFingerTracking; + IKSystem.Instance.FingerSystem.ControlActive = CVRInputManager.Instance.individualFingerTracking; if(!CVRInputManager.Instance.individualFingerTracking) { From aef5af99af3d88404139e84d6979bbfb64f7dfe1 Mon Sep 17 00:00:00 2001 From: SDraw Date: Thu, 26 Jun 2025 18:59:35 +0300 Subject: [PATCH 07/12] Improved usage of PhysicsInfluencer, pointer-based grabbing --- ml_prm/Main.cs | 1 - ml_prm/ModUi.cs | 14 +-- ml_prm/README.md | 1 - ml_prm/RagdollBodypartHandler.cs | 146 +++++++++++++++--------------- ml_prm/RagdollController.cs | 35 ++------ ml_prm/RemoteGesturesManager.cs | 148 ------------------------------- ml_prm/Settings.cs | 14 +-- ml_prm/Utils.cs | 33 ++----- 8 files changed, 92 insertions(+), 300 deletions(-) delete mode 100644 ml_prm/RemoteGesturesManager.cs diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs index fa9fd2a..ad9280b 100644 --- a/ml_prm/Main.cs +++ b/ml_prm/Main.cs @@ -27,7 +27,6 @@ namespace ml_prm yield return null; m_controller = new UnityEngine.GameObject("[PlayerRagdollMod]").AddComponent(); - m_controller.gameObject.AddComponent(); } System.Collections.IEnumerator WaitForWhitelist() diff --git a/ml_prm/ModUi.cs b/ml_prm/ModUi.cs index b393a97..fc5aadc 100644 --- a/ml_prm/ModUi.cs +++ b/ml_prm/ModUi.cs @@ -36,8 +36,7 @@ namespace ml_prm RecoverDelay, FallLimit, GestureGrab, - FriendsGrab, - GrabDistance + FriendsGrab } const string c_ragdollKeyTooltip = "Switch ragdoll mode with '{0}' key"; @@ -69,7 +68,6 @@ namespace ml_prm static SliderFloat ms_angularMovementDragSlider = null; static SliderFloat ms_recoverDelaySlider = null; static SliderFloat ms_fallLimitSlider = null; - static SliderFloat ms_grabDistanceSlider = null; static Button ms_resetButton = null; internal static void Init() @@ -145,9 +143,6 @@ namespace ml_prm ms_fallLimitSlider.SliderTooltip = string.Format(c_fallLimitTooltip, GetDropHeight(Settings.FallLimit)); ms_fallLimitSlider.OnValueUpdated += (value) => OnSliderUpdate(UiIndex.FallLimit, value); - ms_grabDistanceSlider = ms_category.AddSlider("Grab distance", "Minimal distance for successful grab", Settings.GrabDistance, 0f, 1f); - ms_grabDistanceSlider.OnValueUpdated += (value) => OnSliderUpdate(UiIndex.GrabDistance, value); - ms_resetButton = ms_category.AddButton("Reset settings", "", "Reset mod settings to default"); ms_resetButton.OnPress += Reset; } @@ -261,10 +256,6 @@ namespace ml_prm ms_fallLimitSlider.SliderTooltip = string.Format(c_fallLimitTooltip, GetDropHeight(p_value)); } break; - - case UiIndex.GrabDistance: - Settings.SetSetting(Settings.ModSetting.GrabDistance, p_value); - break; } } catch(Exception e) @@ -331,9 +322,6 @@ namespace ml_prm OnSliderUpdate(UiIndex.FallLimit, 9.899494f); ms_fallLimitSlider.SetSliderValue(9.899494f); - - OnSliderUpdate(UiIndex.GrabDistance, 0.1f); - ms_grabDistanceSlider.SetSliderValue(0.1f); } static void OnHotkeyKeyChanged(UnityEngine.KeyCode p_keyCode) diff --git a/ml_prm/README.md b/ml_prm/README.md index 9af7f2a..bfbaa98 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -41,7 +41,6 @@ Optional mod's settings page with [BTKUILib](https://github.com/BTK-Development/ * **Angular movement drag:** angular movement resistance; `2.0` by default. * **Recover delay:** time delay for enabled `Auto recover` in seconds; `3.0` by default. * **Fall limit:** height limit for fall damage; `5.0` by default. -* **Grab distance:** minimal distance for successful grab; `0.1` by default. * **Reset settings:** resets mod settings to default. Optional mod's settings in [UIExpansionKit](https://github.com/ddakebono/ChilloutMods): diff --git a/ml_prm/RagdollBodypartHandler.cs b/ml_prm/RagdollBodypartHandler.cs index 4da1439..aa63f4a 100644 --- a/ml_prm/RagdollBodypartHandler.cs +++ b/ml_prm/RagdollBodypartHandler.cs @@ -1,4 +1,6 @@ using ABI.CCK.Components; +using ABI_RC.Core; +using ABI_RC.Core.Networking.IO.Social; using ABI_RC.Core.Player; using ABI_RC.Core.Savior; using ABI_RC.Systems.Movement; @@ -10,24 +12,24 @@ namespace ml_prm class RagdollBodypartHandler : MonoBehaviour, CVRTriggerVolume { const string c_ragdollPointerType = "ragdoll"; + const string c_grabPointerType = "grab"; + + bool m_ready = false; Rigidbody m_rigidBody = null; public Collider collider { get; set; } = null; - PhysicsInfluencer m_physicsInfluencer = null; - bool m_shouldHaveInfluencer = false; - bool m_activeGravity = true; + PhysicsInfluencer m_physicsInfluencer = null; + public bool UseBuoyancy { get; set; } = false; bool m_attached = false; - Transform m_attachedHand = null; + CVRPointer m_attachedPointer = null; Transform m_attachTransform = null; FixedJoint m_attachJoint = null; // Unity events void Awake() { - this.gameObject.layer = LayerMask.NameToLayer("PlayerLocal"); - collider = this.GetComponent(); m_rigidBody = this.GetComponent(); @@ -40,30 +42,25 @@ namespace ml_prm } if(collider != null) - { - Physics.IgnoreCollision(collider, BetterBetterCharacterController.Instance.Collider, true); - Physics.IgnoreCollision(collider, BetterBetterCharacterController.Instance.KinematicTriggerProxy.Collider, true); - Physics.IgnoreCollision(collider, BetterBetterCharacterController.Instance.NonKinematicProxy.Collider, true); - Physics.IgnoreCollision(collider, BetterBetterCharacterController.Instance.SphereProxy.Collider, true); - BetterBetterCharacterController.Instance.IgnoreCollision(collider, true); - } + BetterBetterCharacterController.Instance.IgnoreCollision(collider); } void Start() { - if(m_shouldHaveInfluencer && (m_rigidBody != null) && (collider != null)) + if((m_rigidBody != null) && (collider != null)) { m_physicsInfluencer = this.gameObject.AddComponent(); m_physicsInfluencer.fluidDrag = 3f; m_physicsInfluencer.fluidAngularDrag = 1f; - m_physicsInfluencer.enableBuoyancy = true; - m_physicsInfluencer.enableInfluence = false; - m_physicsInfluencer.forceAlignUpright = false; - float mass = m_rigidBody.mass; - m_physicsInfluencer.UpdateDensity(); - m_rigidBody.mass = mass; - m_physicsInfluencer.volume = mass * 0.005f; + m_physicsInfluencer.enableInfluence = true; m_physicsInfluencer.enableLocalGravity = true; + m_physicsInfluencer.enableBuoyancy = true; + m_physicsInfluencer.forceAlignUpright = false; + + float l_mass = m_rigidBody.mass; + m_physicsInfluencer.UpdateDensity(); + m_rigidBody.mass = l_mass; + m_physicsInfluencer.volume = l_mass * 0.005f; this.gameObject.name = string.Format("{0} [NoGizmo]", this.gameObject.name); } @@ -83,45 +80,36 @@ namespace ml_prm Detach(); } - void FixedUpdate() - { - if(m_rigidBody != null) - { - m_rigidBody.useGravity = false; - - if(!m_attached && m_activeGravity && ((m_physicsInfluencer == null) || !m_physicsInfluencer.enableInfluence || !m_physicsInfluencer.GetSubmerged())) - m_rigidBody.AddForce(BetterBetterCharacterController.Instance.GravityResult.AppliedGravity * m_rigidBody.mass); - } - } - void Update() { - if(m_attached && !ReferenceEquals(m_attachTransform, null) && (m_attachTransform == null)) - { - m_attachTransform = null; - - if(m_attachJoint != null) - Object.Destroy(m_attachJoint); - m_attachJoint = null; - - m_attachedHand = null; - m_attached = false; - } + if(m_attached && ((m_attachedPointer == null) || !m_attachedPointer.isActiveAndEnabled)) + Detach(); } void OnTriggerEnter(Collider p_col) { - if(Settings.PointersReaction && (RagdollController.Instance != null) && !RagdollController.Instance.IsRagdolled()) + if(m_ready && (RagdollController.Instance != null)) { CVRPointer l_pointer = p_col.GetComponent(); - if((l_pointer != null) && (l_pointer.type == c_ragdollPointerType) && l_pointer.enabled && !IsIgnored(l_pointer.transform)) - RagdollController.Instance.Ragdoll(); + + // Ragdolling + if(Settings.PointersReaction && !RagdollController.Instance.IsRagdolled()) + { + if((l_pointer != null) && (l_pointer.type == c_ragdollPointerType) && l_pointer.enabled && !IgnoreCheck(l_pointer.transform)) + RagdollController.Instance.Ragdoll(); + } + + //Attachment + if(!m_attached && RagdollController.Instance.IsRagdolled()) + { + if((l_pointer != null) && (l_pointer.type == c_grabPointerType) && RestrictionsCheck(p_col.transform.root)) + Attach(l_pointer); + } } } // Arbitrary - public bool IsReady() => ((m_rigidBody != null) && (collider != null) && (!m_shouldHaveInfluencer || ((m_physicsInfluencer != null) && m_physicsInfluencer.IsReady()))); - public void SetInfuencerUsage(bool p_state) => m_shouldHaveInfluencer = p_state; + public bool IsReady() => ((m_rigidBody != null) && (collider != null) && (m_physicsInfluencer != null) && m_physicsInfluencer.IsReady()); public void SetColliderMaterial(PhysicMaterial p_material) { @@ -134,13 +122,13 @@ namespace ml_prm public void SetAsKinematic(bool p_state) { - if(collider != null) - collider.isTrigger = p_state; if(m_rigidBody != null) { m_rigidBody.isKinematic = p_state; m_rigidBody.collisionDetectionMode = (p_state ? CollisionDetectionMode.Discrete : CollisionDetectionMode.ContinuousDynamic); } + if(m_physicsInfluencer != null) + m_physicsInfluencer.enabled = !p_state; } public void SetVelocity(Vector3 p_vec) @@ -157,10 +145,8 @@ namespace ml_prm public void SetActiveGravity(bool p_state) { - m_activeGravity = p_state; - if(m_physicsInfluencer != null) - m_physicsInfluencer.enabled = m_activeGravity; + m_physicsInfluencer.gravityFactor = (p_state ? 1f : 0f); } public void SetDrag(float p_value) @@ -188,7 +174,7 @@ namespace ml_prm public void SetBuoyancy(bool p_state) { if(m_physicsInfluencer != null) - m_physicsInfluencer.enableInfluence = p_state; + m_physicsInfluencer.enableBuoyancy = (UseBuoyancy && p_state); } public void ClearFluidVolumes() @@ -197,21 +183,27 @@ namespace ml_prm m_physicsInfluencer.ClearFluidVolumes(); } - static bool IsIgnored(Transform p_transform) + internal void RemovePhysicsController() { - return (Settings.IgnoreLocal && (p_transform.root == PlayerSetup.Instance.transform)); + if(this.gameObject.TryGetComponent(out var l_controller)) + { + Object.Destroy(l_controller); // Yeet! + m_ready = true; + } + if(collider != null) + BetterBetterCharacterController.Instance.IgnoreCollision(collider); } - public bool Attach(Transform p_hand, Vector3 p_pos) + void Attach(CVRPointer p_pointer) { - bool l_result = false; - - if(!m_attached && (collider != null) && (Vector3.Distance(p_pos, collider.ClosestPoint(p_pos)) <= Settings.GrabDistance)) + if(!m_attached && (collider != null) && (m_rigidBody != null)) { + m_attachedPointer = p_pointer; + GameObject l_attachPoint = new GameObject("[AttachPoint]"); + l_attachPoint.layer = CVRLayers.PlayerClone; m_attachTransform = l_attachPoint.transform; - m_attachTransform.parent = p_hand; - m_attachTransform.position = p_pos; + m_attachTransform.parent = p_pointer.transform; Rigidbody l_body = l_attachPoint.AddComponent(); l_body.isKinematic = true; @@ -223,16 +215,12 @@ namespace ml_prm m_attachJoint.breakTorque = Mathf.Infinity; m_attached = true; - m_attachedHand = p_hand; - l_result = true; } - return l_result; } - public void Detach() => Detach(m_attachedHand); - public void Detach(Transform p_hand) + public void Detach() { - if(m_attached && ReferenceEquals(m_attachedHand, p_hand)) + if(m_attached) { if(m_attachTransform != null) Object.Destroy(m_attachTransform.gameObject); @@ -242,7 +230,7 @@ namespace ml_prm Object.Destroy(m_attachJoint); m_attachJoint = null; - m_attachedHand = null; + m_attachedPointer = null; m_attached = false; } } @@ -250,11 +238,29 @@ namespace ml_prm // CVRTriggerVolume public void TriggerEnter(CVRPointer pointer) { - if(Settings.PointersReaction && (pointer != null) && pointer.enabled && (pointer.type == c_ragdollPointerType) && !IsIgnored(pointer.transform) && (RagdollController.Instance != null) && !RagdollController.Instance.IsRagdolled()) + if(Settings.PointersReaction && (pointer != null) && pointer.enabled && (pointer.type == c_ragdollPointerType) && !IgnoreCheck(pointer.transform) && (RagdollController.Instance != null) && !RagdollController.Instance.IsRagdolled()) RagdollController.Instance.Ragdoll(); } public void TriggerExit(CVRPointer pointer) { } + + // Static utility + static bool IgnoreCheck(Transform p_transform) + { + return (Settings.IgnoreLocal && (p_transform.root == PlayerSetup.Instance.transform)); + } + + static bool RestrictionsCheck(Transform p_transform) + { + if(p_transform == PlayerSetup.Instance.transform) + return false; + + PlayerDescriptor l_playerDescriptor = p_transform.GetComponent(); + if(l_playerDescriptor != null) + return (!Settings.FriendsGrab || Friends.FriendsWith(l_playerDescriptor.ownerId)); + + return false; + } } } diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index ea98869..85c7d51 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -114,7 +114,6 @@ namespace ml_prm BetterBetterCharacterController.OnTeleport.AddListener(this.OnPlayerTeleport); ModUi.OnSwitchChanged.AddListener(this.SwitchRagdoll); - RemoteGesturesManager.OnGestureState.AddListener(this.OnRemoteGestureStateChanged); } void OnDestroy() @@ -163,7 +162,6 @@ namespace ml_prm BetterBetterCharacterController.OnTeleport.RemoveListener(this.OnPlayerTeleport); ModUi.OnSwitchChanged.RemoveListener(this.SwitchRagdoll); - RemoteGesturesManager.OnGestureState.RemoveListener(this.OnRemoteGestureStateChanged); } void Update() @@ -305,7 +303,10 @@ namespace ml_prm { m_avatarTransform = PlayerSetup.Instance.AvatarTransform; m_hips = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.Hips); - Utils.SetAvatarTPose(); + + IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; BipedRagdollReferences l_avatarReferences = BipedRagdollReferences.FromAvatar(PlayerSetup.Instance.Animator); @@ -368,7 +369,7 @@ namespace ml_prm if((l_body != null) && (l_collider != null)) { RagdollBodypartHandler l_handler = l_puppetTransforms[i].gameObject.AddComponent(); - l_handler.SetInfuencerUsage(Utils.IsInEnumeration(l_puppetTransforms[i], l_influencedTransforms)); + l_handler.UseBuoyancy = Utils.IsObjectInArray(l_puppetTransforms[i], l_influencedTransforms); m_ragdollBodyHandlers.Add(l_handler); } @@ -400,6 +401,7 @@ namespace ml_prm foreach(RagdollBodypartHandler l_handler in m_ragdollBodyHandlers) { + l_handler.RemovePhysicsController(); l_handler.SetAsKinematic(true); l_handler.SetColliderMaterial(m_physicsMaterial); } @@ -518,31 +520,6 @@ namespace ml_prm p_result.m_result |= (m_ragdolled && (m_vrIK != null)); } - // Custom game events - void OnRemoteGestureStateChanged(ABI_RC.Core.Player.PuppetMaster p_master, RemoteGesturesManager.GestureHand p_hand, bool p_state) - { - if(m_avatarReady && m_ragdolled && Settings.GestureGrab && (p_master.Animator != null)) - { - Transform l_hand = p_master.Animator.GetBoneTransform((p_hand == RemoteGesturesManager.GestureHand.Left) ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand); - Transform l_finger = p_master.Animator.GetBoneTransform((p_hand == RemoteGesturesManager.GestureHand.Left) ? HumanBodyBones.LeftMiddleProximal : HumanBodyBones.RightMiddleProximal); - - if(l_hand != null) - { - Vector3 l_pos = (l_finger != null) ? ((l_hand.position + l_finger.position) * 0.5f) : l_hand.position; - foreach(var l_bodyHandler in m_ragdollBodyHandlers) - { - if(p_state) - { - if(l_bodyHandler.Attach(l_hand, l_pos)) - break; - } - else - l_bodyHandler.Detach(l_hand); - } - } - } - } - // VRIK updates void OnIKPostSolverUpdate() { diff --git a/ml_prm/RemoteGesturesManager.cs b/ml_prm/RemoteGesturesManager.cs deleted file mode 100644 index 02f54df..0000000 --- a/ml_prm/RemoteGesturesManager.cs +++ /dev/null @@ -1,148 +0,0 @@ -using ABI_RC.Core.Networking.IO.Social; -using ABI_RC.Core.Player; -using ABI_RC.Systems.GameEventSystem; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace ml_prm -{ - [DisallowMultipleComponent] - class RemoteGesturesManager : MonoBehaviour - { - public enum GestureHand - { - Left = 0, - Right - } - internal class GestureEvent - { - event Action m_action; - public void AddListener(Action p_listener) => m_action += p_listener; - public void RemoveListener(Action p_listener) => m_action -= p_listener; - public void Invoke(T1 p_objA, T2 p_objB, T3 p_objC) => m_action?.Invoke(p_objA, p_objB, p_objC); - } - - public static readonly GestureEvent OnGestureState = new GestureEvent(); - - class PlayerEntry - { - public CVRPlayerEntity m_entity = null; - public PuppetMaster m_puppetMaster = null; - public bool m_stateLeft = false; - public bool m_stateRight = false; - } - - static RemoteGesturesManager ms_instance = null; - - readonly List m_entries = null; - - internal RemoteGesturesManager() - { - m_entries = new List(); - } - - void Awake() - { - if(ms_instance != null) - { - DestroyImmediate(this); - return; - } - - ms_instance = this; - DontDestroyOnLoad(this); - } - - void Start() - { - CVRGameEventSystem.Player.OnJoinEntity.AddListener(OnRemotePlayerCreated); - CVRGameEventSystem.Player.OnLeaveEntity.AddListener(OnRemotePlayerDestroyed); - Settings.OnGestureGrabChanged.AddListener(OnGestureGrabChanged); - } - - void OnDestroy() - { - if(ms_instance == this) - ms_instance = null; - - m_entries.Clear(); - - CVRGameEventSystem.Player.OnJoinEntity.RemoveListener(OnRemotePlayerCreated); - CVRGameEventSystem.Player.OnLeaveEntity.RemoveListener(OnRemotePlayerDestroyed); - Settings.OnGestureGrabChanged.RemoveListener(OnGestureGrabChanged); - } - - void Update() - { - if(Settings.GestureGrab) - { - foreach(var l_entry in m_entries) - { - bool l_state = l_entry.m_puppetMaster.IsLeftGrabPointerActive(); - if(l_entry.m_stateLeft != l_state) - { - l_entry.m_stateLeft = l_state; - if(!Settings.FriendsGrab || Friends.FriendsWith(l_entry.m_entity.PlayerDescriptor.ownerId)) - OnGestureState.Invoke(l_entry.m_puppetMaster, GestureHand.Left, l_entry.m_stateLeft); - } - - l_state = l_entry.m_puppetMaster.IsRightGrabPointerActive(); - if(l_entry.m_stateRight != l_state) - { - l_entry.m_stateRight = l_state; - if(!Settings.FriendsGrab || Friends.FriendsWith(l_entry.m_entity.PlayerDescriptor.ownerId)) - OnGestureState.Invoke(l_entry.m_puppetMaster, GestureHand.Right, l_entry.m_stateRight); - } - } - } - } - - void OnRemotePlayerCreated(CVRPlayerEntity p_player) - { - try - { - if((p_player != null) && (p_player.PuppetMaster != null)) - { - PlayerEntry l_entry = new PlayerEntry() - { - m_entity = p_player, - m_puppetMaster = p_player.PuppetMaster, - m_stateLeft = false, - m_stateRight = false - }; - m_entries.Add(l_entry); - } - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - void OnRemotePlayerDestroyed(CVRPlayerEntity p_player) - { - try - { - if(p_player != null) - m_entries.RemoveAll(e => ReferenceEquals(e.m_puppetMaster, p_player.PuppetMaster)); - } - catch(Exception e) - { - MelonLoader.MelonLogger.Error(e); - } - } - - void OnGestureGrabChanged(bool p_state) - { - if(!p_state) - { - foreach(var l_entry in m_entries) - { - l_entry.m_stateLeft = false; - l_entry.m_stateRight = false; - } - } - } - } -} diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index a0f889a..412b48a 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -35,8 +35,7 @@ namespace ml_prm FallDamage, FallLimit, GestureGrab, - FriendsGrab, - GrabDistance + FriendsGrab } public static bool Hotkey { get; private set; } = true; @@ -111,8 +110,7 @@ namespace ml_prm ms_category.CreateEntry(ModSetting.FallDamage.ToString(), FallDamage, null, null, true), ms_category.CreateEntry(ModSetting.FallLimit.ToString(), FallLimit, null, null, true), ms_category.CreateEntry(ModSetting.GestureGrab.ToString(), GestureGrab, null, null, true), - ms_category.CreateEntry(ModSetting.FriendsGrab.ToString(), FriendsGrab, null, null, true), - ms_category.CreateEntry(ModSetting.GrabDistance.ToString(), GrabDistance, null, null, true), + ms_category.CreateEntry(ModSetting.FriendsGrab.ToString(), FriendsGrab, null, null, true) }; ms_entries[(int)ModSetting.HotkeyKey].OnEntryValueChangedUntyped.Subscribe(OnMelonSettingSave_HotkeyKey); @@ -137,7 +135,6 @@ namespace ml_prm FallLimit = Mathf.Clamp((float)ms_entries[(int)ModSetting.FallLimit].BoxedValue, 4.5f, 44.5f); GestureGrab = (bool)ms_entries[(int)ModSetting.GestureGrab].BoxedValue; FriendsGrab = (bool)ms_entries[(int)ModSetting.FriendsGrab].BoxedValue; - GrabDistance = Mathf.Clamp01((float)ms_entries[(int)ModSetting.GrabDistance].BoxedValue); } static void OnMelonSettingSave_HotkeyKey(object p_oldValue, object p_newValue) @@ -296,13 +293,6 @@ namespace ml_prm OnFallLimitChanged.Invoke(FallLimit); } break; - - case ModSetting.GrabDistance: - { - GrabDistance = (float)p_value; - OnGrabDistanceChanged.Invoke(GrabDistance); - } - break; } if(ms_entries != null) diff --git a/ml_prm/Utils.cs b/ml_prm/Utils.cs index 5138c28..ad5f7db 100644 --- a/ml_prm/Utils.cs +++ b/ml_prm/Utils.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.Reflection; using UnityEngine; using System.Linq; -using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Core.InteractionSystem; namespace ml_prm @@ -22,12 +21,6 @@ namespace ml_prm public static void ClearFluidVolumes(this BetterBetterCharacterController p_instance) => (ms_touchingVolumes?.GetValue(p_instance) as List)?.Clear(); - 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 bool IsReady(this PhysicsInfluencer p_instance) { return ((ms_referencePoints.GetValue(p_instance) as List).Count > 0); @@ -38,27 +31,15 @@ namespace ml_prm (ms_influencerSubmergedColliders.GetValue(p_instance) as Dictionary)?.Clear(); } - public static void SetAvatarTPose() - { - IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; - PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; - } - - public static bool IsInEnumeration(object p_obj, object[] p_enumeration) => p_enumeration.Contains(p_obj); - - public static bool IsLeftGrabPointerActive(this PuppetMaster p_source) - { - return p_source._playerAvatarMovementDataCurrent.IsLeftHandGrabbing(); - } - - public static bool IsRightGrabPointerActive(this PuppetMaster p_source) - { - return p_source._playerAvatarMovementDataCurrent.IsRightHandGrabbing(); - } + public static bool IsObjectInArray(object p_obj, object[] p_enumeration) => p_enumeration.Contains(p_obj); public static CVRSeat GetCurrentSeat(this BetterBetterCharacterController p_instance) => (ms_lastCVRSeat?.GetValue(p_instance) as CVRSeat); - public static bool IsInRange(float p_value, float p_min, float p_max) => ((p_min <= p_value) && (p_value <= p_max)); + // Unity specific + public static void CopyGlobal(this Transform p_source, Transform p_target) + { + p_target.position = p_source.position; + p_target.rotation = p_source.rotation; + } } } From 7f29079109f75ffe701413222ab4b9bf0d960f53 Mon Sep 17 00:00:00 2001 From: SDraw Date: Sun, 29 Jun 2025 15:42:29 +0300 Subject: [PATCH 08/12] Fix of collision layers --- ml_ppu/PickUpManager.cs | 2 +- ml_prm/RagdollBodypartHandler.cs | 17 ++++++++++++++--- ml_prm/RagdollController.cs | 4 ++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/ml_ppu/PickUpManager.cs b/ml_ppu/PickUpManager.cs index 9ee2ab1..158632e 100644 --- a/ml_ppu/PickUpManager.cs +++ b/ml_ppu/PickUpManager.cs @@ -149,7 +149,7 @@ namespace ml_ppu Vector3 l_armPos = (l_avatarMatInv * m_armLeft.GetMatrix()).GetPosition(); m_collider = new GameObject("[Collider]").AddComponent(); - m_collider.gameObject.layer = CVRLayers.PlayerClone; + m_collider.gameObject.layer = CVRLayers.PlayerLocal; m_collider.transform.parent = this.transform; m_collider.isTrigger = true; m_collider.height = Vector3.Distance(l_hipsPos, new Vector3(0f, l_armPos.y, l_armPos.z)); diff --git a/ml_prm/RagdollBodypartHandler.cs b/ml_prm/RagdollBodypartHandler.cs index aa63f4a..bd43f99 100644 --- a/ml_prm/RagdollBodypartHandler.cs +++ b/ml_prm/RagdollBodypartHandler.cs @@ -42,7 +42,7 @@ namespace ml_prm } if(collider != null) - BetterBetterCharacterController.Instance.IgnoreCollision(collider); + RemoveGameCollision(); } void Start() @@ -127,6 +127,8 @@ namespace ml_prm m_rigidBody.isKinematic = p_state; m_rigidBody.collisionDetectionMode = (p_state ? CollisionDetectionMode.Discrete : CollisionDetectionMode.ContinuousDynamic); } + if(collider != null) + collider.isTrigger = p_state; if(m_physicsInfluencer != null) m_physicsInfluencer.enabled = !p_state; } @@ -191,7 +193,7 @@ namespace ml_prm m_ready = true; } if(collider != null) - BetterBetterCharacterController.Instance.IgnoreCollision(collider); + RemoveGameCollision(); } void Attach(CVRPointer p_pointer) @@ -201,7 +203,7 @@ namespace ml_prm m_attachedPointer = p_pointer; GameObject l_attachPoint = new GameObject("[AttachPoint]"); - l_attachPoint.layer = CVRLayers.PlayerClone; + l_attachPoint.layer = CVRLayers.PlayerLocal; m_attachTransform = l_attachPoint.transform; m_attachTransform.parent = p_pointer.transform; @@ -235,6 +237,15 @@ namespace ml_prm } } + void RemoveGameCollision() + { + Physics.IgnoreCollision(collider, BetterBetterCharacterController.Instance.Collider, true); + Physics.IgnoreCollision(collider, BetterBetterCharacterController.Instance.KinematicTriggerProxy.Collider, true); + Physics.IgnoreCollision(collider, BetterBetterCharacterController.Instance.NonKinematicProxy.Collider, true); + Physics.IgnoreCollision(collider, BetterBetterCharacterController.Instance.SphereProxy.Collider, true); + BetterBetterCharacterController.Instance.IgnoreCollision(collider); + } + // CVRTriggerVolume public void TriggerEnter(CVRPointer pointer) { diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 85c7d51..f6c9a45 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -311,7 +311,7 @@ namespace ml_prm BipedRagdollReferences l_avatarReferences = BipedRagdollReferences.FromAvatar(PlayerSetup.Instance.Animator); m_puppetRoot = new GameObject("Root").transform; - m_puppetRoot.gameObject.layer = CVRLayers.PlayerClone; + m_puppetRoot.gameObject.layer = CVRLayers.PlayerLocal; m_puppetRoot.parent = m_puppet; m_puppetRoot.position = m_avatarTransform.position; m_puppetRoot.rotation = m_avatarTransform.rotation; @@ -775,7 +775,7 @@ namespace ml_prm static Transform CloneTransform(Transform p_source, Transform p_parent, string p_name) { Transform l_target = new GameObject(p_name).transform; - l_target.gameObject.layer = CVRLayers.PlayerClone; + l_target.gameObject.layer = CVRLayers.PlayerLocal; l_target.parent = p_parent; p_source.CopyGlobal(l_target); return l_target; From 9f78aa46207386f8f6e02a12c4fd268505347e43 Mon Sep 17 00:00:00 2001 From: SDraw Date: Thu, 3 Jul 2025 16:15:47 +0300 Subject: [PATCH 09/12] New mod: PlayerAvatarHistory Incremented version for nightly to prevent rollback by auto-updater Minor fixes --- ml_bft/FingerSystem.cs | 10 +- ml_bft/Utils.cs | 7 - ml_mods_cvr.sln | 5 + ml_pah/AvatarEntry.cs | 14 ++ ml_pah/HistoryManager.cs | 205 ++++++++++++++++++++++++++++++ ml_pah/Main.cs | 59 +++++++++ ml_pah/ModUi.cs | 131 +++++++++++++++++++ ml_pah/Properties/AssemblyInfo.cs | 4 + ml_pah/Settings.cs | 77 +++++++++++ ml_pah/ml_pah.csproj | 60 +++++++++ ml_pah/resources/delete.png | Bin 0 -> 4016 bytes ml_pah/resources/guardian.png | Bin 0 -> 6584 bytes ml_pah/resources/save.png | Bin 0 -> 3801 bytes ml_pmc/Properties/AssemblyInfo.cs | 2 +- ml_pmc/Utils.cs | 7 +- ml_pmc/ml_pmc.csproj | 3 +- ml_ppu/Properties/AssemblyInfo.cs | 2 +- ml_ppu/ml_ppu.csproj | 2 +- ml_prm/Properties/AssemblyInfo.cs | 2 +- ml_prm/RagdollController.cs | 2 +- ml_prm/ml_prm.csproj | 2 +- ml_vpc/Properties/AssemblyInfo.cs | 2 +- ml_vpc/ml_vpc.csproj | 2 +- 23 files changed, 575 insertions(+), 23 deletions(-) create mode 100644 ml_pah/AvatarEntry.cs create mode 100644 ml_pah/HistoryManager.cs create mode 100644 ml_pah/Main.cs create mode 100644 ml_pah/ModUi.cs create mode 100644 ml_pah/Properties/AssemblyInfo.cs create mode 100644 ml_pah/Settings.cs create mode 100644 ml_pah/ml_pah.csproj create mode 100644 ml_pah/resources/delete.png create mode 100644 ml_pah/resources/guardian.png create mode 100644 ml_pah/resources/save.png diff --git a/ml_bft/FingerSystem.cs b/ml_bft/FingerSystem.cs index 8946ef3..f7286d9 100644 --- a/ml_bft/FingerSystem.cs +++ b/ml_bft/FingerSystem.cs @@ -121,9 +121,11 @@ namespace ml_bft Animator l_animator = PlayerSetup.Instance.Animator; if(l_animator.isHuman) { - Utils.SetAvatarTPose(); - InputHandler.Instance.Rebind(PlayerSetup.Instance.transform.rotation); + IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); + PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; + PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; + InputHandler.Instance.Rebind(PlayerSetup.Instance.transform.rotation); foreach(var l_tuple in ms_fingersChains) { ReorientateTowards( @@ -221,14 +223,14 @@ namespace ml_bft { if(m_ready && MetaPort.Instance.isUsingVr && (p_handler != null) && Settings.SkeletalInput) { - if(CVRInputManager.Instance._leftController != ABI_RC.Systems.InputManagement.XR.eXRControllerType.None) + if(CVRInputManager.Instance.IsLeftControllerTracking()) { Quaternion l_turnBack = (m_leftHandOffset.m_source.rotation * m_leftHandOffset.m_offset) * Quaternion.Inverse(m_leftHandOffset.m_target.rotation); foreach(var l_offset in m_leftFingerOffsets) l_offset.m_target.rotation = l_turnBack * (l_offset.m_source.rotation * l_offset.m_offset); } - if(CVRInputManager.Instance._rightController != ABI_RC.Systems.InputManagement.XR.eXRControllerType.None) + if(CVRInputManager.Instance.IsRightControllerTracking()) { Quaternion l_turnBack = (m_rightHandOffset.m_source.rotation * m_rightHandOffset.m_offset) * Quaternion.Inverse(m_rightHandOffset.m_target.rotation); foreach(var l_offset in m_rightFingerOffsets) diff --git a/ml_bft/Utils.cs b/ml_bft/Utils.cs index adadeff..cfdbfd7 100644 --- a/ml_bft/Utils.cs +++ b/ml_bft/Utils.cs @@ -17,12 +17,5 @@ namespace ml_bft public static bool IsInVR() => ((MetaPort.Instance != null) && MetaPort.Instance.isUsingVr); public static bool AreKnucklesInUse() => ((CVRInputManager.Instance._leftController == ABI_RC.Systems.InputManagement.XR.eXRControllerType.Index) || (CVRInputManager.Instance._rightController == ABI_RC.Systems.InputManagement.XR.eXRControllerType.Index)); - - public static void SetAvatarTPose() - { - IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose); - PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero; - PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity; - } } } diff --git a/ml_mods_cvr.sln b/ml_mods_cvr.sln index 1a8e1ef..df44b4a 100644 --- a/ml_mods_cvr.sln +++ b/ml_mods_cvr.sln @@ -32,6 +32,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ml_ppu", "ml_ppu\ml_ppu.csp EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ml_vet", "ml_vet\ml_vet.csproj", "{8DB32590-FC5B-46A8-9747-344E86B18ACF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ml_pah", "ml_pah\ml_pah.csproj", "{C4659F60-3FED-4F43-88E4-969907D4C7A6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -83,6 +85,9 @@ Global {8DB32590-FC5B-46A8-9747-344E86B18ACF}.Debug|x64.Build.0 = Debug|x64 {8DB32590-FC5B-46A8-9747-344E86B18ACF}.Release|x64.ActiveCfg = Release|x64 {8DB32590-FC5B-46A8-9747-344E86B18ACF}.Release|x64.Build.0 = Release|x64 + {C4659F60-3FED-4F43-88E4-969907D4C7A6}.Debug|x64.ActiveCfg = Debug|x64 + {C4659F60-3FED-4F43-88E4-969907D4C7A6}.Release|x64.ActiveCfg = Release|x64 + {C4659F60-3FED-4F43-88E4-969907D4C7A6}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ml_pah/AvatarEntry.cs b/ml_pah/AvatarEntry.cs new file mode 100644 index 0000000..ee940ff --- /dev/null +++ b/ml_pah/AvatarEntry.cs @@ -0,0 +1,14 @@ +using System; + +namespace ml_pah +{ + [Serializable] + class AvatarEntry + { + public string m_id; + public string m_name; + public string m_imageUrl; + public DateTime m_lastUsageDate; + public bool m_cached = false; + } +} diff --git a/ml_pah/HistoryManager.cs b/ml_pah/HistoryManager.cs new file mode 100644 index 0000000..88e9fd5 --- /dev/null +++ b/ml_pah/HistoryManager.cs @@ -0,0 +1,205 @@ +using ABI_RC.Core.Networking.API; +using ABI_RC.Core.Networking.API.Responses; +using Newtonsoft.Json; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + +namespace ml_pah +{ + static class HistoryManager + { + internal class EntriesUpdateEvent + { + event Action m_action; + public void AddListener(Action p_listener) => m_action += p_listener; + public void RemoveListener(Action p_listener) => m_action -= p_listener; + public void Invoke() => m_action?.Invoke(); + } + + public static readonly EntriesUpdateEvent OnEntriesUpdated = new EntriesUpdateEvent(); + + static bool ms_initialized = false; + static string ms_historyPath; + readonly static List ms_avatarEntries = new List(); + + static int ms_lastTick = 0; + + // Init + internal static void Initialize() + { + if(!ms_initialized) + { + ms_historyPath = Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, "PlayerAvatarHistory.json"); + + try + { + if(File.Exists(ms_historyPath)) + { + string l_json = File.ReadAllText(ms_historyPath); + List l_entries = JsonConvert.DeserializeObject>(l_json); + if(l_entries != null) + { + ms_avatarEntries.AddRange(l_entries); + LimitEntries(); + ms_avatarEntries.Sort((a, b) => a.m_lastUsageDate.CompareTo(b.m_lastUsageDate)); + } + } + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + + ms_lastTick = Environment.TickCount; + Settings.OnAutosaveTimeChanged.AddListener(OnAutosaveTimeChanged); + + ms_initialized = true; + } + } + + internal static void Shutdown() + { + if(ms_initialized) + { + SaveHistory(); + + Settings.OnAutosaveTimeChanged.RemoveListener(OnAutosaveTimeChanged); + + ms_initialized = false; + } + } + + // Update + public static void Update() + { + if(ms_initialized && (Settings.AutosaveTime > 0)) + { + int l_tick = Environment.TickCount; + if((l_tick - ms_lastTick) >= (Settings.AutosaveTime * 60000)) + { + MelonLoader.MelonCoroutines.Start(AutosaveCoroutine()); + ms_lastTick = l_tick; + } + } + } + + // Entries + internal static List GetAvatarEntries() => ms_avatarEntries; + + internal static void AddEntry(string p_id) + { + if(ms_initialized) + { + int l_index = ms_avatarEntries.FindIndex(l_entry => l_entry.m_id == p_id); + if(l_index != -1) + { + ms_avatarEntries[l_index].m_lastUsageDate = DateTime.Now; + + if(l_index != 0) + { + // Move in list + AvatarEntry l_entry = ms_avatarEntries[l_index]; + ms_avatarEntries.RemoveAt(l_index); + ms_avatarEntries.Insert(0, l_entry); + + OnEntriesUpdated?.Invoke(); + } + } + else + { + AvatarEntry l_entry = new AvatarEntry(); + l_entry.m_id = p_id; + l_entry.m_name = "Loading ..."; + l_entry.m_lastUsageDate = DateTime.Now; + + MelonLoader.MelonCoroutines.Start(RequestAvatarInfo(l_entry)); + } + } + } + + // History + internal static void ClearHistory() => ms_avatarEntries.Clear(); + + internal static void SaveHistory() + { + if(ms_initialized) + { + try + { + string l_json = JsonConvert.SerializeObject(ms_avatarEntries, Formatting.Indented); + File.WriteAllText(ms_historyPath, l_json); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + } + + static IEnumerator AutosaveCoroutine() + { + List l_listCopy = new List(); + l_listCopy.AddRange(ms_avatarEntries); + + Task l_task = Task.Run(() => AutosaveTask(l_listCopy)); + while(!l_task.IsCompleted) + yield return null; + } + + static async Task AutosaveTask(List p_entries) + { + try + { + string l_json = JsonConvert.SerializeObject(p_entries, Formatting.Indented); + File.WriteAllText(ms_historyPath, l_json); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + + await Task.Delay(1); + } + + // Network request + static IEnumerator RequestAvatarInfo(AvatarEntry p_entry) + { + Task l_task = Task.Run(() => RequestAvatarInfoTask(p_entry)); + while(!l_task.IsCompleted) + yield return null; + + ms_avatarEntries.Insert(0, p_entry); + LimitEntries(); + OnEntriesUpdated?.Invoke(); + } + + static async Task RequestAvatarInfoTask(AvatarEntry p_entry) + { + BaseResponse l_baseResponse = await ApiConnection.MakeRequest(ApiConnection.ApiOperation.AvatarDetail, new { avatarID = p_entry.m_id }); + if(l_baseResponse != null) + { + if(!l_baseResponse.IsSuccessStatusCode) return; + p_entry.m_name = l_baseResponse.Data.Name; + p_entry.m_imageUrl = l_baseResponse.Data.ImageUrl; + p_entry.m_cached = true; + } + } + + // Settings + static void OnAutosaveTimeChanged(int p_value) + { + ms_lastTick = Environment.TickCount; + } + + // Utility + static void LimitEntries() + { + int l_currentLimit = Settings.AvatarsLimit; + if(ms_avatarEntries.Count > l_currentLimit) + ms_avatarEntries.RemoveRange(l_currentLimit, ms_avatarEntries.Count - (l_currentLimit - 1)); + } + } +} diff --git a/ml_pah/Main.cs b/ml_pah/Main.cs new file mode 100644 index 0000000..528c1f8 --- /dev/null +++ b/ml_pah/Main.cs @@ -0,0 +1,59 @@ +using ABI.CCK.Components; +using ABI_RC.Core; +using System; +using System.Collections; +using ABI_RC.Systems.GameEventSystem; + +namespace ml_pah +{ + public class PlayerAvatarHistory : MelonLoader.MelonMod + { + public override void OnInitializeMelon() + { + Settings.Init(); + HistoryManager.Initialize(); + ModUi.Initialize(); + MelonLoader.MelonCoroutines.Start(WaitForRootLogic()); + } + + public override void OnDeinitializeMelon() + { + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnLocalAvatarLoad); + HistoryManager.OnEntriesUpdated.RemoveListener(this.OnHistoryEntriesUpdated); + + ModUi.Shutdown(); + HistoryManager.Shutdown(); + } + + IEnumerator WaitForRootLogic() + { + while(RootLogic.Instance == null) + yield return null; + + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnLocalAvatarLoad); + HistoryManager.OnEntriesUpdated.AddListener(this.OnHistoryEntriesUpdated); + } + + public override void OnUpdate() + { + HistoryManager.Update(); + } + + // Game events + void OnLocalAvatarLoad(CVRAvatar p_avatar) + { + try + { + if((p_avatar.AssetInfo != null) && (p_avatar.AssetInfo.objectId.Length > 0)) + HistoryManager.AddEntry(p_avatar.AssetInfo.objectId); + } + catch(Exception e) + { + MelonLoader.MelonLogger.Error(e); + } + } + + // Mod events + void OnHistoryEntriesUpdated() => ModUi.UpdateAvatarsList(); + } +} diff --git a/ml_pah/ModUi.cs b/ml_pah/ModUi.cs new file mode 100644 index 0000000..a7aa3b9 --- /dev/null +++ b/ml_pah/ModUi.cs @@ -0,0 +1,131 @@ +using ABI_RC.Core.EventSystem; +using ABI_RC.Core.InteractionSystem; +using BTKUILib.UIObjects; +using BTKUILib.UIObjects.Components; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +namespace ml_pah +{ + static class ModUi + { + readonly static string ms_namespace = typeof(ModUi).Namespace; + static bool ms_initialized = false; + + static Page ms_page = null; + + static Category ms_settingsCategory = null; + static Button ms_settingsClearButton = null; + static Button ms_settingSaveButton = null; + static SliderFloat ms_settingsEntriesLimit = null; + static SliderFloat ms_settingsAutosaveTime = null; + + static Category ms_buttonsCategory = null; + static readonly List