Fix PlayerMovementCopycat

This commit is contained in:
SDraw 2026-06-20 16:00:13 +03:00
parent 4838b66b6a
commit bc3cb07ddb
No known key found for this signature in database
GPG key ID: BB95B4DAB2BB8BB5
5 changed files with 50 additions and 169 deletions

View file

@ -14,9 +14,17 @@ namespace ml_pmc
public void RemoveListener(Action p_listener) => m_action -= p_listener; public void RemoveListener(Action p_listener) => m_action -= p_listener;
public void Invoke() => m_action?.Invoke(); public void Invoke() => m_action?.Invoke();
} }
internal class GameEvent<T1>
{
event Action<T1> m_action;
public void AddListener(Action<T1> p_listener) => m_action += p_listener;
public void RemoveListener(Action<T1> p_listener) => m_action -= p_listener;
public void Invoke(T1 p_obj) => m_action?.Invoke(p_obj);
}
public static readonly GameEvent OnAvatarPreReuse = new GameEvent(); public static readonly GameEvent OnAvatarPreReuse = new GameEvent();
public static readonly GameEvent OnAvatarPostReuse = new GameEvent(); public static readonly GameEvent OnAvatarPostReuse = new GameEvent();
public static readonly GameEvent<PlayerAvatarMovementData> OnPostLocalPlayerMovementDataUpdate = new GameEvent<PlayerAvatarMovementData>();
internal static void Init(HarmonyLib.Harmony p_instance) internal static void Init(HarmonyLib.Harmony p_instance)
{ {
@ -27,6 +35,12 @@ namespace ml_pmc
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarReinitialize_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarReinitialize_Prefix), BindingFlags.Static | BindingFlags.NonPublic)),
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarReinitialize_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarReinitialize_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
); );
p_instance.Patch(
typeof(PlayerSetup).GetMethod("UpdatePlayerAvatarMovementData", BindingFlags.Instance | BindingFlags.NonPublic),
null,
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnPlayerAvatarMovementDataUpdate_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
);
} }
catch(Exception e) catch(Exception e)
{ {
@ -57,5 +71,17 @@ namespace ml_pmc
MelonLoader.MelonLogger.Error(e); MelonLoader.MelonLogger.Error(e);
} }
} }
static void OnPlayerAvatarMovementDataUpdate_Postfix(PlayerAvatarMovementData ____playerAvatarMovementData)
{
try
{
OnPostLocalPlayerMovementDataUpdate.Invoke(____playerAvatarMovementData);
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
} }
} }

View file

@ -2,7 +2,6 @@ using ABI.CCK.Components;
using ABI_RC.Core.Networking.IO.Social; using ABI_RC.Core.Networking.IO.Social;
using ABI_RC.Core.Player; using ABI_RC.Core.Player;
using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.GameEventSystem;
using ABI_RC.Systems.IK;
using ABI_RC.Systems.IK.SubSystems; using ABI_RC.Systems.IK.SubSystems;
using ABI_RC.Systems.InputManagement; using ABI_RC.Systems.InputManagement;
using ABI_RC.Systems.Movement; using ABI_RC.Systems.Movement;
@ -61,6 +60,7 @@ namespace ml_pmc
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup); CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup);
GameEvents.OnAvatarPreReuse.AddListener(this.OnAvatarPreReuse); GameEvents.OnAvatarPreReuse.AddListener(this.OnAvatarPreReuse);
GameEvents.OnAvatarPostReuse.AddListener(this.OnAvatarPostReuse); GameEvents.OnAvatarPostReuse.AddListener(this.OnAvatarPostReuse);
GameEvents.OnPostLocalPlayerMovementDataUpdate.AddListener(this.OnMovementDataUpdate);
ModUi.OnTargetSelect.AddListener(this.OnTargetSelect); ModUi.OnTargetSelect.AddListener(this.OnTargetSelect);
} }
@ -84,6 +84,7 @@ namespace ml_pmc
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup); CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup);
GameEvents.OnAvatarPreReuse.RemoveListener(this.OnAvatarPreReuse); GameEvents.OnAvatarPreReuse.RemoveListener(this.OnAvatarPreReuse);
GameEvents.OnAvatarPostReuse.RemoveListener(this.OnAvatarPostReuse); GameEvents.OnAvatarPostReuse.RemoveListener(this.OnAvatarPostReuse);
GameEvents.OnPostLocalPlayerMovementDataUpdate.RemoveListener(this.OnMovementDataUpdate);
ModUi.OnTargetSelect.RemoveListener(this.OnTargetSelect); ModUi.OnTargetSelect.RemoveListener(this.OnTargetSelect);
} }
@ -107,76 +108,7 @@ namespace ml_pmc
CVRInputManager.Instance.gestureRight = (l_mirror ? m_puppetParser.GetLeftGesture() : m_puppetParser.GetRightGesture()); CVRInputManager.Instance.gestureRight = (l_mirror ? m_puppetParser.GetLeftGesture() : m_puppetParser.GetRightGesture());
} }
if(m_puppetParser.HasFingerTracking()) m_fingerTracking = m_puppetParser.HasFingerTracking();
{
m_fingerTracking = true;
CVRInputManager.Instance.individualFingerTracking = true;
IKSystem.Instance.FingerSystem.ControlActive = true;
ref readonly float[] l_curls = ref m_puppetParser.GetFingerCurls();
ref readonly float[] l_spreads = ref m_puppetParser.GetFingerSpreads();
// Left hand
CVRInputManager.Instance.finger1StretchedLeftThumb = l_curls[l_mirror ? 15 : 0];
CVRInputManager.Instance.finger2StretchedLeftThumb = l_curls[l_mirror ? 16 : 1];
CVRInputManager.Instance.finger3StretchedLeftThumb = l_curls[l_mirror ? 17 : 2];
CVRInputManager.Instance.fingerSpreadLeftThumb = l_spreads[l_mirror ? 5 : 0];
CVRInputManager.Instance.finger1StretchedLeftIndex = l_curls[l_mirror ? 18 : 3];
CVRInputManager.Instance.finger2StretchedLeftIndex = l_curls[l_mirror ? 19 : 4];
CVRInputManager.Instance.finger3StretchedLeftIndex = l_curls[l_mirror ? 20 : 5];
CVRInputManager.Instance.fingerSpreadLeftIndex = l_spreads[l_mirror ? 6 : 1];
CVRInputManager.Instance.finger1StretchedLeftMiddle = l_curls[l_mirror ? 21 : 6];
CVRInputManager.Instance.finger2StretchedLeftMiddle = l_curls[l_mirror ? 22 : 7];
CVRInputManager.Instance.finger3StretchedLeftMiddle = l_curls[l_mirror ? 23 : 8];
CVRInputManager.Instance.fingerSpreadLeftMiddle = l_spreads[l_mirror ? 7 : 2];
CVRInputManager.Instance.finger1StretchedLeftRing = l_curls[l_mirror ? 24 : 9];
CVRInputManager.Instance.finger2StretchedLeftRing = l_curls[l_mirror ? 25 : 10];
CVRInputManager.Instance.finger3StretchedLeftRing = l_curls[l_mirror ? 26 : 11];
CVRInputManager.Instance.fingerSpreadLeftRing = l_spreads[l_mirror ? 8 : 3];
CVRInputManager.Instance.finger1StretchedLeftPinky = l_curls[l_mirror ? 27 : 12];
CVRInputManager.Instance.finger2StretchedLeftPinky = l_curls[l_mirror ? 28 : 13];
CVRInputManager.Instance.finger3StretchedLeftPinky = l_curls[l_mirror ? 29 : 14];
CVRInputManager.Instance.fingerSpreadLeftPinky = l_spreads[l_mirror ? 9 : 4];
// Right hand
CVRInputManager.Instance.finger1StretchedRightThumb = l_curls[l_mirror ? 0 : 15];
CVRInputManager.Instance.finger2StretchedRightThumb = l_curls[l_mirror ? 1 : 16];
CVRInputManager.Instance.finger3StretchedRightThumb = l_curls[l_mirror ? 2 : 17];
CVRInputManager.Instance.fingerSpreadRightThumb = l_spreads[l_mirror ? 0 : 5];
CVRInputManager.Instance.finger1StretchedRightIndex = l_curls[l_mirror ? 3 : 18];
CVRInputManager.Instance.finger2StretchedRightIndex = l_curls[l_mirror ? 4 : 19];
CVRInputManager.Instance.finger3StretchedRightIndex = l_curls[l_mirror ? 5 : 20];
CVRInputManager.Instance.fingerSpreadRightIndex = l_spreads[l_mirror ? 1 : 6];
CVRInputManager.Instance.finger1StretchedRightMiddle = l_curls[l_mirror ? 6 : 21];
CVRInputManager.Instance.finger2StretchedRightMiddle = l_curls[l_mirror ? 7 : 22];
CVRInputManager.Instance.finger3StretchedRightMiddle = l_curls[l_mirror ? 8 : 23];
CVRInputManager.Instance.fingerSpreadRightMiddle = l_spreads[l_mirror ? 2 : 7];
CVRInputManager.Instance.finger1StretchedRightRing = l_curls[l_mirror ? 9 : 24];
CVRInputManager.Instance.finger2StretchedRightRing = l_curls[l_mirror ? 10 : 25];
CVRInputManager.Instance.finger3StretchedRightRing = l_curls[l_mirror ? 11 : 26];
CVRInputManager.Instance.fingerSpreadRightRing = l_spreads[l_mirror ? 3 : 8];
CVRInputManager.Instance.finger1StretchedRightPinky = l_curls[l_mirror ? 12 : 27];
CVRInputManager.Instance.finger2StretchedRightPinky = l_curls[l_mirror ? 13 : 28];
CVRInputManager.Instance.finger3StretchedRightPinky = l_curls[l_mirror ? 14 : 29];
CVRInputManager.Instance.fingerSpreadRightPinky = l_spreads[l_mirror ? 4 : 9];
}
else
{
if(m_fingerTracking)
{
RestoreFingerTracking();
m_fingerTracking = false;
}
}
Matrix4x4 l_offset = m_puppetParser.GetLastOffset(); Matrix4x4 l_offset = m_puppetParser.GetLastOffset();
Vector3 l_pos = l_offset * ms_pointVector; Vector3 l_pos = l_offset * ms_pointVector;
@ -223,6 +155,8 @@ namespace ml_pmc
m_puppetParser.GetPose().CopyTo(ref m_pose); m_puppetParser.GetPose().CopyTo(ref m_pose);
if(m_fingerTracking)
m_puppetParser.GetFingerMuscles(ref m_pose.muscles);
if(Settings.MirrorPose) if(Settings.MirrorPose)
Utils.MirrorPose(ref m_pose); Utils.MirrorPose(ref m_pose);
@ -238,7 +172,6 @@ namespace ml_pmc
if(m_active) if(m_active)
{ {
RestoreIK(); RestoreIK();
RestoreFingerTracking();
OnCopycatChanged.Invoke(false); OnCopycatChanged.Invoke(false);
} }
m_active = false; m_active = false;
@ -325,6 +258,16 @@ namespace ml_pmc
} }
} }
void OnMovementDataUpdate(PlayerAvatarMovementData p_data)
{
if(m_active)
{
p_data.UseIndividualFingers = true;
System.Array.Copy(m_pose.muscles, PlayerAvatarMovementData.MuscleGroups.LeftFingersStart, p_data.MuscleValues, PlayerAvatarMovementData.MuscleGroups.LeftFingersStart, PlayerAvatarMovementData.MuscleGroups.LeftFingersCount);
System.Array.Copy(m_pose.muscles, PlayerAvatarMovementData.MuscleGroups.RightFingersStart, p_data.MuscleValues, PlayerAvatarMovementData.MuscleGroups.RightFingersStart, PlayerAvatarMovementData.MuscleGroups.RightFingersCount);
}
}
// Ui events // Ui events
void OnTargetSelect(string p_id) void OnTargetSelect(string p_id)
{ {
@ -415,7 +358,6 @@ namespace ml_pmc
} }
RestoreIK(); RestoreIK();
RestoreFingerTracking();
m_fingerTracking = false; m_fingerTracking = false;
m_active = false; m_active = false;
@ -438,77 +380,5 @@ namespace ml_pmc
if(m_vrIk != null) if(m_vrIk != null)
m_vrIk.solver.Reset(); m_vrIk.solver.Reset();
} }
void RestoreFingerTracking()
{
CVRInputManager.Instance.individualFingerTracking = (m_inVr && Utils.AreKnucklesInUse() && !CVRInputManager._moduleXR.SkeletalToggleValue);
IKSystem.Instance.FingerSystem.ControlActive = CVRInputManager.Instance.individualFingerTracking;
if(!CVRInputManager.Instance.individualFingerTracking)
{
// Left hand
CVRInputManager.Instance.finger1StretchedLeftThumb = 0f;
CVRInputManager.Instance.finger2StretchedLeftThumb = 0f;
CVRInputManager.Instance.finger3StretchedLeftThumb = 0f;
CVRInputManager.Instance.fingerSpreadLeftThumb = 0f;
CVRInputManager.Instance.finger1StretchedLeftIndex = 0f;
CVRInputManager.Instance.finger2StretchedLeftIndex = 0f;
CVRInputManager.Instance.finger3StretchedLeftIndex = 0f;
CVRInputManager.Instance.fingerSpreadLeftIndex = 0f;
CVRInputManager.Instance.finger1StretchedLeftMiddle = 0;
CVRInputManager.Instance.finger2StretchedLeftMiddle = 0f;
CVRInputManager.Instance.finger3StretchedLeftMiddle = 0f;
CVRInputManager.Instance.fingerSpreadLeftMiddle = 0f;
CVRInputManager.Instance.finger1StretchedLeftRing = 0f;
CVRInputManager.Instance.finger2StretchedLeftRing = 0f;
CVRInputManager.Instance.finger3StretchedLeftRing = 0f;
CVRInputManager.Instance.fingerSpreadLeftRing = 0f;
CVRInputManager.Instance.finger1StretchedLeftPinky = 0f;
CVRInputManager.Instance.finger2StretchedLeftPinky = 0f;
CVRInputManager.Instance.finger3StretchedLeftPinky = 0f;
CVRInputManager.Instance.fingerSpreadLeftPinky = 0f;
CVRInputManager.Instance.fingerFullCurlNormalizedLeftThumb = 0f;
CVRInputManager.Instance.fingerFullCurlNormalizedLeftIndex = 0f;
CVRInputManager.Instance.fingerFullCurlNormalizedLeftMiddle = 0f;
CVRInputManager.Instance.fingerFullCurlNormalizedLeftRing = 0f;
CVRInputManager.Instance.fingerFullCurlNormalizedLeftPinky = 0f;
// Right hand
CVRInputManager.Instance.finger1StretchedRightThumb = 0f;
CVRInputManager.Instance.finger2StretchedRightThumb = 0f;
CVRInputManager.Instance.finger3StretchedRightThumb = 0f;
CVRInputManager.Instance.fingerSpreadRightThumb = 0f;
CVRInputManager.Instance.finger1StretchedRightIndex = 0f;
CVRInputManager.Instance.finger2StretchedRightIndex = 0f;
CVRInputManager.Instance.finger3StretchedRightIndex = 0f;
CVRInputManager.Instance.fingerSpreadRightIndex = 0f;
CVRInputManager.Instance.finger1StretchedRightMiddle = 0f;
CVRInputManager.Instance.finger2StretchedRightMiddle = 0f;
CVRInputManager.Instance.finger3StretchedRightMiddle = 0f;
CVRInputManager.Instance.fingerSpreadRightMiddle = 0f;
CVRInputManager.Instance.finger1StretchedRightRing = 0f;
CVRInputManager.Instance.finger2StretchedRightRing = 0f;
CVRInputManager.Instance.finger3StretchedRightRing = 0f;
CVRInputManager.Instance.fingerSpreadRightRing = 0f;
CVRInputManager.Instance.finger1StretchedRightPinky = 0f;
CVRInputManager.Instance.finger2StretchedRightPinky = 0f;
CVRInputManager.Instance.finger3StretchedRightPinky = 0f;
CVRInputManager.Instance.fingerSpreadRightPinky = 0f;
CVRInputManager.Instance.fingerFullCurlNormalizedRightThumb = 0f;
CVRInputManager.Instance.fingerFullCurlNormalizedRightIndex = 0f;
CVRInputManager.Instance.fingerFullCurlNormalizedRightMiddle = 0f;
CVRInputManager.Instance.fingerFullCurlNormalizedRightRing = 0f;
CVRInputManager.Instance.fingerFullCurlNormalizedRightPinky = 0f;
}
}
} }
} }

View file

@ -1,4 +1,4 @@
[assembly: MelonLoader.MelonInfo(typeof(ml_pmc.PlayerMovementCopycat), "PlayerMovementCopycat", "1.1.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonInfo(typeof(ml_pmc.PlayerMovementCopycat), "PlayerMovementCopycat", "1.1.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
[assembly: MelonLoader.MelonPriority(3)] [assembly: MelonLoader.MelonPriority(3)]
[assembly: MelonLoader.MelonAdditionalDependencies("BTKUILib")] [assembly: MelonLoader.MelonAdditionalDependencies("BTKUILib")]

View file

@ -20,14 +20,6 @@ namespace ml_pmc
float m_leftGesture = 0f; float m_leftGesture = 0f;
float m_rightGesture = 0f; float m_rightGesture = 0f;
bool m_fingerTracking = false; bool m_fingerTracking = false;
readonly float[] m_fingerCurls = null;
readonly float[] m_fingerSpreads = null;
internal PuppetParser()
{
m_fingerCurls = new float[30];
m_fingerSpreads = new float[10];
}
// Unity events // Unity events
void Start() void Start()
@ -59,18 +51,6 @@ namespace ml_pmc
m_leftGesture = m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorGestureLeft; m_leftGesture = m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorGestureLeft;
m_rightGesture = m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorGestureRight; m_rightGesture = m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorGestureRight;
m_fingerTracking = m_puppetMaster.PlayerAvatarMovementDataInput.UseIndividualFingers; m_fingerTracking = m_puppetMaster.PlayerAvatarMovementDataInput.UseIndividualFingers;
if(m_fingerTracking)
{
for(int i = 0; i < 10; i++)
{
int l_stepA = i * 3;
int l_stepB = i * 4;
m_fingerCurls[l_stepA] = m_puppetMaster.PlayerAvatarMovementDataInput.MuscleValues[55 + l_stepB];
m_fingerCurls[l_stepA + 1] = m_puppetMaster.PlayerAvatarMovementDataInput.MuscleValues[57 + l_stepB];
m_fingerCurls[l_stepA + 2] = m_puppetMaster.PlayerAvatarMovementDataInput.MuscleValues[58 + l_stepB];
m_fingerSpreads[i] = m_puppetMaster.PlayerAvatarMovementDataInput.MuscleValues[56 + l_stepB];
}
}
Matrix4x4 l_current = this.transform.GetMatrix(); Matrix4x4 l_current = this.transform.GetMatrix();
m_offset = m_matrix.inverse * l_current; m_offset = m_matrix.inverse * l_current;
@ -84,13 +64,18 @@ namespace ml_pmc
m_poseHandler.GetHumanPose(ref m_pose); m_poseHandler.GetHumanPose(ref m_pose);
} }
// Class methods
public ref HumanPose GetPose() => ref m_pose; public ref HumanPose GetPose() => ref m_pose;
public ref Matrix4x4 GetLastOffset() => ref m_offset; public ref Matrix4x4 GetLastOffset() => ref m_offset;
public bool IsSitting() => m_sitting; public bool IsSitting() => m_sitting;
public float GetLeftGesture() => m_leftGesture; public float GetLeftGesture() => m_leftGesture;
public float GetRightGesture() => m_rightGesture; public float GetRightGesture() => m_rightGesture;
public bool HasFingerTracking() => m_fingerTracking; public bool HasFingerTracking() => m_fingerTracking;
public ref readonly float[] GetFingerCurls() => ref m_fingerCurls;
public ref readonly float[] GetFingerSpreads() => ref m_fingerSpreads; public void GetFingerMuscles(ref float[] target)
{
System.Array.Copy(m_pose.muscles, PlayerAvatarMovementData.MuscleGroups.LeftFingersStart, target, PlayerAvatarMovementData.MuscleGroups.LeftFingersStart, PlayerAvatarMovementData.MuscleGroups.LeftFingersCount);
System.Array.Copy(m_pose.muscles, PlayerAvatarMovementData.MuscleGroups.RightFingersStart, target, PlayerAvatarMovementData.MuscleGroups.RightFingersStart, PlayerAvatarMovementData.MuscleGroups.RightFingersCount);
}
} }
} }

View file

@ -7,7 +7,7 @@
<Authors>SDraw</Authors> <Authors>SDraw</Authors>
<Company>SDraw</Company> <Company>SDraw</Company>
<Product>PlayerMovementCopycat</Product> <Product>PlayerMovementCopycat</Product>
<Version>1.1.3</Version> <Version>1.1.4</Version>
<AssemblyName>PlayerMovementCopycat</AssemblyName> <AssemblyName>PlayerMovementCopycat</AssemblyName>
</PropertyGroup> </PropertyGroup>