mirror of
https://github.com/hanetzer/sdraw_mods_cvr.git
synced 2025-09-08 20:49:18 +00:00
Compare commits
No commits in common. "r180" and "master" have entirely different histories.
64 changed files with 1249 additions and 1507 deletions
|
@ -15,6 +15,8 @@ namespace ml_amt
|
||||||
public void Invoke() => m_action?.Invoke();
|
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 OnAvatarReuse = new GameEvent();
|
||||||
public static readonly GameEvent OnPlayspaceScale = new GameEvent();
|
public static readonly GameEvent OnPlayspaceScale = new GameEvent();
|
||||||
|
|
||||||
|
@ -22,6 +24,18 @@ namespace ml_amt
|
||||||
{
|
{
|
||||||
try
|
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(
|
p_instance.Patch(
|
||||||
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
||||||
null,
|
null,
|
||||||
|
@ -40,6 +54,30 @@ 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()
|
static void OnAvatarReinitialize_Postfix()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
using ABI.CCK.Components;
|
using ABI_RC.Core.Player;
|
||||||
using ABI_RC.Core.Player;
|
|
||||||
using ABI_RC.Core.Util.AnimatorManager;
|
using ABI_RC.Core.Util.AnimatorManager;
|
||||||
using ABI_RC.Systems.GameEventSystem;
|
|
||||||
using ABI_RC.Systems.IK.SubSystems;
|
using ABI_RC.Systems.IK.SubSystems;
|
||||||
using ABI_RC.Systems.Movement;
|
using ABI_RC.Systems.Movement;
|
||||||
using RootMotion.FinalIK;
|
using RootMotion.FinalIK;
|
||||||
|
@ -61,8 +59,8 @@ namespace ml_amt
|
||||||
Settings.OnProneLimitChanged.AddListener(this.OnProneLimitChanged);
|
Settings.OnProneLimitChanged.AddListener(this.OnProneLimitChanged);
|
||||||
Settings.OnMassCenterChanged.AddListener(this.OnMassCenterChanged);
|
Settings.OnMassCenterChanged.AddListener(this.OnMassCenterChanged);
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear);
|
GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear);
|
||||||
GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse);
|
GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse);
|
||||||
GameEvents.OnPlayspaceScale.AddListener(this.OnPlayspaceScale);
|
GameEvents.OnPlayspaceScale.AddListener(this.OnPlayspaceScale);
|
||||||
}
|
}
|
||||||
|
@ -80,8 +78,8 @@ namespace ml_amt
|
||||||
Settings.OnProneLimitChanged.RemoveListener(this.OnProneLimitChanged);
|
Settings.OnProneLimitChanged.RemoveListener(this.OnProneLimitChanged);
|
||||||
Settings.OnMassCenterChanged.RemoveListener(this.OnMassCenterChanged);
|
Settings.OnMassCenterChanged.RemoveListener(this.OnMassCenterChanged);
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear);
|
GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear);
|
||||||
GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse);
|
GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse);
|
||||||
GameEvents.OnPlayspaceScale.RemoveListener(this.OnPlayspaceScale);
|
GameEvents.OnPlayspaceScale.RemoveListener(this.OnPlayspaceScale);
|
||||||
}
|
}
|
||||||
|
@ -98,82 +96,68 @@ namespace ml_amt
|
||||||
}
|
}
|
||||||
|
|
||||||
// Game events
|
// Game events
|
||||||
void OnAvatarClear(CVRAvatar p_avatar)
|
void OnAvatarClear()
|
||||||
{
|
{
|
||||||
try
|
m_vrIk = null;
|
||||||
{
|
m_avatarReady = false;
|
||||||
m_vrIk = null;
|
m_avatarScale = 1f;
|
||||||
m_avatarReady = false;
|
m_locomotionOffset = Vector3.zero;
|
||||||
m_avatarScale = 1f;
|
m_massCenter = Vector3.zero;
|
||||||
m_locomotionOffset = Vector3.zero;
|
m_ikLimits = null;
|
||||||
m_massCenter = Vector3.zero;
|
m_parameters.Clear();
|
||||||
m_ikLimits = null;
|
|
||||||
m_parameters.Clear();
|
|
||||||
|
|
||||||
BetterBetterCharacterController.Instance.avatarCrouchLimit = Mathf.Clamp01(Settings.CrouchLimit);
|
BetterBetterCharacterController.Instance.avatarCrouchLimit = Mathf.Clamp01(Settings.CrouchLimit);
|
||||||
BetterBetterCharacterController.Instance.avatarProneLimit = Mathf.Clamp01(Settings.ProneLimit);
|
BetterBetterCharacterController.Instance.avatarProneLimit = Mathf.Clamp01(Settings.ProneLimit);
|
||||||
}
|
|
||||||
catch(System.Exception e)
|
|
||||||
{
|
|
||||||
MelonLoader.MelonLogger.Error(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnAvatarSetup(CVRAvatar p_avatar)
|
void OnAvatarSetup()
|
||||||
{
|
{
|
||||||
try
|
Utils.SetAvatarTPose();
|
||||||
|
|
||||||
|
m_vrIk = PlayerSetup.Instance._avatar.GetComponent<VRIK>();
|
||||||
|
m_avatarScale = Mathf.Abs(PlayerSetup.Instance._avatar.transform.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._avatar.transform.Find("[IKLimits]");
|
||||||
|
UpdateIKLimits();
|
||||||
|
|
||||||
|
// Apply VRIK tweaks
|
||||||
|
if(m_vrIk != null)
|
||||||
{
|
{
|
||||||
Utils.SetAvatarTPose();
|
m_locomotionOffset = m_vrIk.solver.locomotion.offset;
|
||||||
|
m_massCenter = m_locomotionOffset;
|
||||||
|
|
||||||
m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent<VRIK>();
|
if(m_vrIk.solver.HasToes())
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
m_locomotionOffset = m_vrIk.solver.locomotion.offset;
|
Transform l_foot = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftFoot);
|
||||||
m_massCenter = m_locomotionOffset;
|
if(l_foot == null)
|
||||||
|
l_foot = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightFoot);
|
||||||
|
|
||||||
if(m_vrIk.solver.HasToes())
|
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))
|
||||||
{
|
{
|
||||||
Transform l_foot = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.LeftFoot);
|
Vector3 l_footPos = (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_foot.GetMatrix()).GetPosition();
|
||||||
if(l_foot == null)
|
Vector3 l_toePos = (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_toe.GetMatrix()).GetPosition();
|
||||||
l_foot = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.RightFoot);
|
m_massCenter = new Vector3(0f, 0f, l_toePos.z - l_footPos.z);
|
||||||
|
|
||||||
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_avatarReady = true;
|
m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? m_massCenter : m_locomotionOffset);
|
||||||
}
|
|
||||||
catch(System.Exception e)
|
m_vrIk.onPreSolverUpdate.AddListener(this.OnIKPreSolverUpdate);
|
||||||
{
|
m_vrIk.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate);
|
||||||
MelonLoader.MelonLogger.Error(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_avatarReady = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnPlayspaceScale()
|
void OnPlayspaceScale()
|
||||||
|
@ -187,7 +171,7 @@ namespace ml_amt
|
||||||
// Old VRIK is destroyed by game
|
// Old VRIK is destroyed by game
|
||||||
Utils.SetAvatarTPose();
|
Utils.SetAvatarTPose();
|
||||||
|
|
||||||
m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent<VRIK>();
|
m_vrIk = PlayerSetup.Instance._animator.GetComponent<VRIK>();
|
||||||
if(m_vrIk != null)
|
if(m_vrIk != null)
|
||||||
{
|
{
|
||||||
m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? m_massCenter : m_locomotionOffset);
|
m_vrIk.solver.locomotion.offset = (Settings.MassCenter ? m_massCenter : m_locomotionOffset);
|
||||||
|
@ -257,7 +241,7 @@ namespace ml_amt
|
||||||
// Arbitrary
|
// Arbitrary
|
||||||
float GetRelativeScale()
|
float GetRelativeScale()
|
||||||
{
|
{
|
||||||
return ((m_avatarScale > 0f) ? (PlayerSetup.Instance.AvatarTransform.localScale.y / m_avatarScale) : 0f);
|
return ((m_avatarScale > 0f) ? (PlayerSetup.Instance._avatar.transform.localScale.y / m_avatarScale) : 0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateIKLimits()
|
void UpdateIKLimits()
|
||||||
|
@ -274,7 +258,7 @@ namespace ml_amt
|
||||||
public bool IsMoving() => BetterBetterCharacterController.Instance.IsMoving();
|
public bool IsMoving() => BetterBetterCharacterController.Instance.IsMoving();
|
||||||
public float GetMovementSpeed()
|
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);
|
return Mathf.Sqrt(l_animatorManager.MovementX * l_animatorManager.MovementX + l_animatorManager.MovementY * l_animatorManager.MovementY);
|
||||||
}
|
}
|
||||||
public float GetVelocity() => BetterBetterCharacterController.Instance.velocity.magnitude;
|
public float GetVelocity() => BetterBetterCharacterController.Instance.velocity.magnitude;
|
||||||
|
|
|
@ -65,31 +65,31 @@ namespace ml_amt
|
||||||
{
|
{
|
||||||
while(ViewManager.Instance == null)
|
while(ViewManager.Instance == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView == null)
|
while(ViewManager.Instance.gameMenuView == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView.Listener == null)
|
while(ViewManager.Instance.gameMenuView.Listener == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () =>
|
ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
||||||
};
|
};
|
||||||
ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) =>
|
ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
||||||
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static System.Collections.IEnumerator UpdateMenuSettings()
|
static System.Collections.IEnumerator UpdateMenuSettings()
|
||||||
{
|
{
|
||||||
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown)
|
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
foreach(var l_entry in ms_entries)
|
foreach(var l_entry in ms_entries)
|
||||||
ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnSliderUpdate(string p_name, string p_value)
|
static void OnSliderUpdate(string p_name, string p_value)
|
||||||
|
|
|
@ -22,11 +22,11 @@ namespace ml_amt
|
||||||
|
|
||||||
public static void SetAvatarTPose()
|
public static void SetAvatarTPose()
|
||||||
{
|
{
|
||||||
if(PlayerSetup.Instance.Animator.isHuman)
|
if(PlayerSetup.Instance._animator.isHuman)
|
||||||
{
|
{
|
||||||
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
||||||
PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero;
|
PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero;
|
||||||
PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity;
|
PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,30 +44,30 @@ namespace ml_asl
|
||||||
{
|
{
|
||||||
while(ViewManager.Instance == null)
|
while(ViewManager.Instance == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView == null)
|
while(ViewManager.Instance.gameMenuView == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView.Listener == null)
|
while(ViewManager.Instance.gameMenuView.Listener == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () =>
|
ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
||||||
};
|
};
|
||||||
ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) =>
|
ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
||||||
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static System.Collections.IEnumerator UpdateMenuSettings()
|
static System.Collections.IEnumerator UpdateMenuSettings()
|
||||||
{
|
{
|
||||||
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown)
|
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
foreach(var l_entry in ms_entries)
|
foreach(var l_entry in ms_entries)
|
||||||
ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnToggleUpdate(string p_name, string p_value)
|
static void OnToggleUpdate(string p_name, string p_value)
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
using ABI.CCK.Components;
|
using ABI_RC.Core.Player;
|
||||||
using ABI_RC.Core.Player;
|
|
||||||
using ABI_RC.Core.Savior;
|
using ABI_RC.Core.Savior;
|
||||||
using ABI_RC.Systems.GameEventSystem;
|
|
||||||
using ABI_RC.Systems.IK;
|
using ABI_RC.Systems.IK;
|
||||||
using ABI_RC.Systems.InputManagement;
|
using ABI_RC.Systems.InputManagement;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -94,8 +92,8 @@ namespace ml_bft
|
||||||
m_pose = new HumanPose();
|
m_pose = new HumanPose();
|
||||||
m_lastValues = new float[40];
|
m_lastValues = new float[40];
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear);
|
GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear);
|
||||||
GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse);
|
GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse);
|
||||||
GameEvents.OnIKSystemLateUpdate.AddListener(this.OnIKSystemLateUpdate);
|
GameEvents.OnIKSystemLateUpdate.AddListener(this.OnIKSystemLateUpdate);
|
||||||
}
|
}
|
||||||
|
@ -108,129 +106,113 @@ namespace ml_bft
|
||||||
m_rightFingerOffsets.Clear();
|
m_rightFingerOffsets.Clear();
|
||||||
m_ready = false;
|
m_ready = false;
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear);
|
GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear);
|
||||||
GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse);
|
GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse);
|
||||||
GameEvents.OnIKSystemLateUpdate.RemoveListener(this.OnIKSystemLateUpdate);
|
GameEvents.OnIKSystemLateUpdate.RemoveListener(this.OnIKSystemLateUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnAvatarSetup(CVRAvatar p_avatar)
|
internal void OnAvatarSetup()
|
||||||
{
|
{
|
||||||
try
|
Animator l_animator = PlayerSetup.Instance._animator;
|
||||||
|
if(l_animator.isHuman)
|
||||||
{
|
{
|
||||||
Animator l_animator = PlayerSetup.Instance.Animator;
|
Utils.SetAvatarTPose();
|
||||||
if(l_animator.isHuman)
|
InputHandler.Instance.Rebind(PlayerSetup.Instance.transform.rotation);
|
||||||
|
|
||||||
|
foreach(var l_tuple in ms_fingersChains)
|
||||||
{
|
{
|
||||||
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
ReorientateTowards(
|
||||||
PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero;
|
PlayerSetup.Instance.transform,
|
||||||
PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity;
|
l_animator.GetBoneTransform(l_tuple.Item1),
|
||||||
|
(l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null,
|
||||||
InputHandler.Instance.Rebind(PlayerSetup.Instance.transform.rotation);
|
InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3),
|
||||||
foreach(var l_tuple in ms_fingersChains)
|
InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3),
|
||||||
{
|
PlaneType.OXZ
|
||||||
ReorientateTowards(
|
);
|
||||||
PlayerSetup.Instance.transform,
|
ReorientateTowards(
|
||||||
l_animator.GetBoneTransform(l_tuple.Item1),
|
PlayerSetup.Instance.transform,
|
||||||
(l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null,
|
l_animator.GetBoneTransform(l_tuple.Item1),
|
||||||
InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3),
|
(l_tuple.Item2 != HumanBodyBones.LastBone) ? l_animator.GetBoneTransform(l_tuple.Item2) : null,
|
||||||
InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3),
|
InputHandler.Instance.GetSourceForBone(l_tuple.Item1, l_tuple.Item3),
|
||||||
PlaneType.OXZ
|
InputHandler.Instance.GetSourceForBone(l_tuple.Item2, l_tuple.Item3),
|
||||||
);
|
PlaneType.OYX
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
// Bind hands
|
||||||
{
|
m_leftHandOffset.m_source = l_animator.GetBoneTransform(HumanBodyBones.LeftHand);
|
||||||
MelonLoader.MelonLogger.Error(e);
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnAvatarClear(CVRAvatar p_avatar)
|
internal void OnAvatarClear()
|
||||||
{
|
{
|
||||||
try
|
m_ready = false;
|
||||||
{
|
m_pose = new HumanPose();
|
||||||
m_ready = false;
|
|
||||||
m_pose = new HumanPose();
|
|
||||||
|
|
||||||
m_leftHandOffset.Reset();
|
m_leftHandOffset.Reset();
|
||||||
m_rightHandOffset.Reset();
|
m_rightHandOffset.Reset();
|
||||||
|
|
||||||
m_leftFingerOffsets.Clear();
|
m_leftFingerOffsets.Clear();
|
||||||
m_rightFingerOffsets.Clear();
|
m_rightFingerOffsets.Clear();
|
||||||
}
|
|
||||||
catch(System.Exception e)
|
|
||||||
{
|
|
||||||
MelonLoader.MelonLogger.Error(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnAvatarReuse()
|
internal void OnAvatarReuse()
|
||||||
{
|
{
|
||||||
OnAvatarClear(PlayerSetup.Instance.AvatarDescriptor);
|
OnAvatarClear();
|
||||||
OnAvatarSetup(PlayerSetup.Instance.AvatarDescriptor);
|
OnAvatarSetup();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnIKSystemLateUpdate(HumanPoseHandler p_handler, Transform p_hips)
|
internal void OnIKSystemLateUpdate(HumanPoseHandler p_handler, Transform p_hips)
|
||||||
{
|
{
|
||||||
if(m_ready && MetaPort.Instance.isUsingVr && (p_handler != null) && Settings.SkeletalInput)
|
if(m_ready && MetaPort.Instance.isUsingVr && (p_handler != null) && Settings.SkeletalInput)
|
||||||
{
|
{
|
||||||
if(CVRInputManager.Instance.IsLeftControllerTracking())
|
if(CVRInputManager.Instance._leftController != ABI_RC.Systems.InputManagement.XR.eXRControllerType.None)
|
||||||
{
|
{
|
||||||
Quaternion l_turnBack = (m_leftHandOffset.m_source.rotation * m_leftHandOffset.m_offset) * Quaternion.Inverse(m_leftHandOffset.m_target.rotation);
|
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)
|
foreach(var l_offset in m_leftFingerOffsets)
|
||||||
l_offset.m_target.rotation = l_turnBack * (l_offset.m_source.rotation * l_offset.m_offset);
|
l_offset.m_target.rotation = l_turnBack * (l_offset.m_source.rotation * l_offset.m_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(CVRInputManager.Instance.IsRightControllerTracking())
|
if(CVRInputManager.Instance._rightController != ABI_RC.Systems.InputManagement.XR.eXRControllerType.None)
|
||||||
{
|
{
|
||||||
Quaternion l_turnBack = (m_rightHandOffset.m_source.rotation * m_rightHandOffset.m_offset) * Quaternion.Inverse(m_rightHandOffset.m_target.rotation);
|
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)
|
foreach(var l_offset in m_rightFingerOffsets)
|
||||||
|
|
|
@ -24,6 +24,8 @@ namespace ml_bft
|
||||||
public void Invoke(T1 p_objA, T2 p_objB) => m_action?.Invoke(p_objA, p_objB);
|
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 OnAvatarReuse = new GameEvent();
|
||||||
public static readonly GameEvent OnInputUpdate = new GameEvent();
|
public static readonly GameEvent OnInputUpdate = new GameEvent();
|
||||||
public static readonly GameEvent<HumanPoseHandler, Transform> OnIKSystemLateUpdate = new GameEvent<HumanPoseHandler, Transform>();
|
public static readonly GameEvent<HumanPoseHandler, Transform> OnIKSystemLateUpdate = new GameEvent<HumanPoseHandler, Transform>();
|
||||||
|
@ -32,6 +34,18 @@ namespace ml_bft
|
||||||
{
|
{
|
||||||
try
|
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(
|
p_instance.Patch(
|
||||||
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
||||||
null,
|
null,
|
||||||
|
@ -56,6 +70,30 @@ 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()
|
static void OnAvatarReinitialize_Postfix()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -64,31 +64,31 @@ namespace ml_bft
|
||||||
{
|
{
|
||||||
while(ViewManager.Instance == null)
|
while(ViewManager.Instance == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView == null)
|
while(ViewManager.Instance.gameMenuView == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView.Listener == null)
|
while(ViewManager.Instance.gameMenuView.Listener == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () =>
|
ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action<string, string>(OnDropdownUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action<string, string>(OnDropdownUpdate));
|
||||||
};
|
};
|
||||||
ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) =>
|
ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
||||||
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static System.Collections.IEnumerator UpdateMenuSettings()
|
static System.Collections.IEnumerator UpdateMenuSettings()
|
||||||
{
|
{
|
||||||
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown)
|
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
foreach(var l_entry in ms_entries)
|
foreach(var l_entry in ms_entries)
|
||||||
ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnToggleUpdate(string p_name, string p_value)
|
static void OnToggleUpdate(string p_name, string p_value)
|
||||||
|
|
|
@ -17,5 +17,12 @@ namespace ml_bft
|
||||||
public static bool IsInVR() => ((MetaPort.Instance != null) && MetaPort.Instance.isUsingVr);
|
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 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._avatar.transform.localPosition = Vector3.zero;
|
||||||
|
PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ namespace ml_dht
|
||||||
public void Invoke(T1 p_objA, T2 p_objB) => m_action?.Invoke(p_objA, p_objB);
|
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 OnAvatarReuse = new GameEvent();
|
||||||
public static readonly GameEvent<EyeMovementController> OnEyeControllerUpdate = new GameEvent<EyeMovementController>();
|
public static readonly GameEvent<EyeMovementController> OnEyeControllerUpdate = new GameEvent<EyeMovementController>();
|
||||||
public static readonly GameEvent<CVRFaceTracking, EventResult> OnFaceTrackingUpdate = new GameEvent<CVRFaceTracking, EventResult>();
|
public static readonly GameEvent<CVRFaceTracking, EventResult> OnFaceTrackingUpdate = new GameEvent<CVRFaceTracking, EventResult>();
|
||||||
|
@ -45,6 +47,18 @@ namespace ml_dht
|
||||||
{
|
{
|
||||||
try
|
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(
|
p_instance.Patch(
|
||||||
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
||||||
null,
|
null,
|
||||||
|
@ -78,6 +92,30 @@ 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()
|
static void OnAvatarReinitialize_Postfix()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
using ABI_RC.Core.Player;
|
using ABI_RC.Core.Player;
|
||||||
using ABI_RC.Core.Player.EyeMovement;
|
using ABI_RC.Core.Player.EyeMovement;
|
||||||
using ABI_RC.Systems.FaceTracking;
|
using ABI_RC.Systems.FaceTracking;
|
||||||
using ABI_RC.Systems.GameEventSystem;
|
|
||||||
using ABI_RC.Systems.IK;
|
using ABI_RC.Systems.IK;
|
||||||
using ABI_RC.Systems.VRModeSwitch;
|
using ABI_RC.Systems.VRModeSwitch;
|
||||||
using RootMotion.FinalIK;
|
using RootMotion.FinalIK;
|
||||||
|
@ -70,8 +69,8 @@ namespace ml_dht
|
||||||
Settings.OnHeadTrackingChanged.AddListener(this.OnEnabledOrHeadTrackingChanged);
|
Settings.OnHeadTrackingChanged.AddListener(this.OnEnabledOrHeadTrackingChanged);
|
||||||
Settings.OnSmoothingChanged.AddListener(this.OnSmoothingChanged);
|
Settings.OnSmoothingChanged.AddListener(this.OnSmoothingChanged);
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear);
|
GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup);
|
||||||
GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse);
|
GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse);
|
||||||
GameEvents.OnEyeControllerUpdate.AddListener(this.OnEyeControllerUpdate);
|
GameEvents.OnEyeControllerUpdate.AddListener(this.OnEyeControllerUpdate);
|
||||||
GameEvents.OnFaceTrackingUpdate.AddListener(this.UpdateFaceTracking);
|
GameEvents.OnFaceTrackingUpdate.AddListener(this.UpdateFaceTracking);
|
||||||
|
@ -90,8 +89,8 @@ namespace ml_dht
|
||||||
Settings.OnHeadTrackingChanged.RemoveListener(this.OnEnabledOrHeadTrackingChanged);
|
Settings.OnHeadTrackingChanged.RemoveListener(this.OnEnabledOrHeadTrackingChanged);
|
||||||
Settings.OnSmoothingChanged.RemoveListener(this.OnSmoothingChanged);
|
Settings.OnSmoothingChanged.RemoveListener(this.OnSmoothingChanged);
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear);
|
GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup);
|
||||||
GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse);
|
GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse);
|
||||||
GameEvents.OnEyeControllerUpdate.RemoveListener(this.OnEyeControllerUpdate);
|
GameEvents.OnEyeControllerUpdate.RemoveListener(this.OnEyeControllerUpdate);
|
||||||
GameEvents.OnFaceTrackingUpdate.RemoveListener(this.UpdateFaceTracking);
|
GameEvents.OnFaceTrackingUpdate.RemoveListener(this.UpdateFaceTracking);
|
||||||
|
@ -132,59 +131,45 @@ namespace ml_dht
|
||||||
{
|
{
|
||||||
m_lastHeadRotation = Quaternion.Slerp(m_lastHeadRotation, m_avatarDescriptor.transform.rotation * (m_headRotation * m_bindRotation), m_smoothing);
|
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;
|
m_headBone.rotation = m_lastHeadRotation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Game events
|
// Game events
|
||||||
internal void OnAvatarSetup(CVRAvatar p_avatar)
|
internal void OnAvatarSetup()
|
||||||
{
|
{
|
||||||
try
|
m_camera = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||||
|
m_avatarDescriptor = PlayerSetup.Instance._avatar.GetComponent<CVRAvatar>();
|
||||||
|
|
||||||
|
if(PlayerSetup.Instance._animator.isHuman)
|
||||||
{
|
{
|
||||||
m_camera = PlayerSetup.Instance.activeCam.transform;
|
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
||||||
m_avatarDescriptor = PlayerSetup.Instance.AvatarObject.GetComponent<CVRAvatar>();
|
PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero;
|
||||||
|
PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity;
|
||||||
|
|
||||||
if(PlayerSetup.Instance.Animator.isHuman)
|
m_headBone = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Head);
|
||||||
{
|
if(m_headBone != null)
|
||||||
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
m_bindRotation = Quaternion.Inverse(m_avatarDescriptor.transform.rotation) * m_headBone.rotation;
|
||||||
PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero;
|
|
||||||
PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity;
|
|
||||||
|
|
||||||
m_headBone = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.Head);
|
m_lookIK = PlayerSetup.Instance._avatar.GetComponent<LookAtIK>();
|
||||||
if(m_headBone != null)
|
if(m_lookIK != null)
|
||||||
m_bindRotation = Quaternion.Inverse(m_avatarDescriptor.transform.rotation) * m_headBone.rotation;
|
m_lookIK.onPostSolverUpdate.AddListener(this.OnLookIKPostUpdate);
|
||||||
|
|
||||||
m_lookIK = PlayerSetup.Instance.AvatarObject.GetComponent<LookAtIK>();
|
|
||||||
if(m_lookIK != null)
|
|
||||||
m_lookIK.onPostSolverUpdate.AddListener(this.OnLookIKPostUpdate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
MelonLoader.MelonLogger.Error(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void OnAvatarClear(CVRAvatar p_avatar)
|
void OnAvatarClear()
|
||||||
{
|
{
|
||||||
try
|
m_avatarDescriptor = null;
|
||||||
{
|
m_lookIK = null;
|
||||||
m_avatarDescriptor = null;
|
m_headBone = null;
|
||||||
m_lookIK = null;
|
m_lastHeadRotation = Quaternion.identity;
|
||||||
m_headBone = null;
|
m_bindRotation = Quaternion.identity;
|
||||||
m_lastHeadRotation = Quaternion.identity;
|
|
||||||
m_bindRotation = Quaternion.identity;
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
MelonLoader.MelonLogger.Error(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void OnAvatarReuse()
|
void OnAvatarReuse()
|
||||||
{
|
{
|
||||||
m_camera = PlayerSetup.Instance.activeCam.transform;
|
m_camera = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||||
|
|
||||||
m_lookIK = PlayerSetup.Instance.AvatarObject.GetComponent<LookAtIK>();
|
m_lookIK = PlayerSetup.Instance._avatar.GetComponent<LookAtIK>();
|
||||||
if(m_lookIK != null)
|
if(m_lookIK != null)
|
||||||
m_lookIK.onPostSolverUpdate.AddListener(this.OnLookIKPostUpdate);
|
m_lookIK.onPostSolverUpdate.AddListener(this.OnLookIKPostUpdate);
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,31 +74,31 @@ namespace ml_dht
|
||||||
{
|
{
|
||||||
while(ViewManager.Instance == null)
|
while(ViewManager.Instance == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView == null)
|
while(ViewManager.Instance.gameMenuView == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView.Listener == null)
|
while(ViewManager.Instance.gameMenuView.Listener == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () =>
|
ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
||||||
};
|
};
|
||||||
ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) =>
|
ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
||||||
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static System.Collections.IEnumerator UpdateMenuSettings()
|
static System.Collections.IEnumerator UpdateMenuSettings()
|
||||||
{
|
{
|
||||||
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown)
|
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
foreach(var l_entry in ms_entries)
|
foreach(var l_entry in ms_entries)
|
||||||
ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnSliderUpdate(string p_name, string p_value)
|
static void OnSliderUpdate(string p_name, string p_value)
|
||||||
|
|
|
@ -23,6 +23,8 @@ namespace ml_lme
|
||||||
public void Invoke(T1 p_obj) => m_action?.Invoke(p_obj);
|
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 OnAvatarReuse = new GameEvent();
|
||||||
public static readonly GameEvent<float> OnRayScale = new GameEvent<float>();
|
public static readonly GameEvent<float> OnRayScale = new GameEvent<float>();
|
||||||
public static readonly GameEvent<float> OnPlayspaceScale = new GameEvent<float>();
|
public static readonly GameEvent<float> OnPlayspaceScale = new GameEvent<float>();
|
||||||
|
@ -32,6 +34,18 @@ namespace ml_lme
|
||||||
{
|
{
|
||||||
try
|
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(
|
p_instance.Patch(
|
||||||
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
||||||
null,
|
null,
|
||||||
|
@ -39,7 +53,7 @@ namespace ml_lme
|
||||||
);
|
);
|
||||||
|
|
||||||
p_instance.Patch(
|
p_instance.Patch(
|
||||||
typeof(PlayerSetup).GetMethod("SetControllerRayScale", BindingFlags.Instance | BindingFlags.NonPublic),
|
typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetControllerRayScale), BindingFlags.Instance | BindingFlags.Public),
|
||||||
null,
|
null,
|
||||||
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnRayScale_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
|
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnRayScale_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
|
||||||
);
|
);
|
||||||
|
@ -62,6 +76,30 @@ 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()
|
static void OnAvatarReinitialize_Postfix()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace ml_lme
|
||||||
m_handRayLeft.isInteractionRay = true;
|
m_handRayLeft.isInteractionRay = true;
|
||||||
m_handRayLeft.triggerHoverEvents = false;
|
m_handRayLeft.triggerHoverEvents = false;
|
||||||
m_handRayLeft.attachmentDistance = 0f;
|
m_handRayLeft.attachmentDistance = 0f;
|
||||||
|
m_handRayLeft.uiMask = 32;
|
||||||
m_handRayLeft.isDesktopRay = !m_inVR;
|
m_handRayLeft.isDesktopRay = !m_inVR;
|
||||||
|
|
||||||
m_lineLeft = m_handRayLeft.gameObject.AddComponent<LineRenderer>();
|
m_lineLeft = m_handRayLeft.gameObject.AddComponent<LineRenderer>();
|
||||||
|
@ -60,6 +61,7 @@ namespace ml_lme
|
||||||
m_handRayRight.isInteractionRay = true;
|
m_handRayRight.isInteractionRay = true;
|
||||||
m_handRayRight.triggerHoverEvents = false;
|
m_handRayRight.triggerHoverEvents = false;
|
||||||
m_handRayRight.attachmentDistance = 0f;
|
m_handRayRight.attachmentDistance = 0f;
|
||||||
|
m_handRayRight.uiMask = 32;
|
||||||
m_handRayRight.isDesktopRay = !m_inVR;
|
m_handRayRight.isDesktopRay = !m_inVR;
|
||||||
|
|
||||||
m_lineRight = m_handRayRight.gameObject.AddComponent<LineRenderer>();
|
m_lineRight = m_handRayRight.gameObject.AddComponent<LineRenderer>();
|
||||||
|
@ -118,10 +120,12 @@ namespace ml_lme
|
||||||
|
|
||||||
m_lineLeft.material = PlayerSetup.Instance.vrRayLeft.lineRenderer.material;
|
m_lineLeft.material = PlayerSetup.Instance.vrRayLeft.lineRenderer.material;
|
||||||
m_lineLeft.gameObject.layer = PlayerSetup.Instance.vrRayLeft.gameObject.layer;
|
m_lineLeft.gameObject.layer = PlayerSetup.Instance.vrRayLeft.gameObject.layer;
|
||||||
|
m_handRayLeft.highlightMaterial = PlayerSetup.Instance.vrRayLeft.highlightMaterial;
|
||||||
m_handRayLeft.SetVRActive(m_inVR);
|
m_handRayLeft.SetVRActive(m_inVR);
|
||||||
|
|
||||||
m_lineRight.material = PlayerSetup.Instance.vrRayLeft.lineRenderer.material;
|
m_lineRight.material = PlayerSetup.Instance.vrRayLeft.lineRenderer.material;
|
||||||
m_lineRight.gameObject.layer = PlayerSetup.Instance.vrRayLeft.gameObject.layer;
|
m_lineRight.gameObject.layer = PlayerSetup.Instance.vrRayLeft.gameObject.layer;
|
||||||
|
m_handRayRight.highlightMaterial = PlayerSetup.Instance.vrRayLeft.highlightMaterial;
|
||||||
m_handRayRight.SetVRActive(m_inVR);
|
m_handRayRight.SetVRActive(m_inVR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,7 +655,7 @@ namespace ml_lme
|
||||||
void SetGameFingersTracking(bool p_state)
|
void SetGameFingersTracking(bool p_state)
|
||||||
{
|
{
|
||||||
base._inputManager.individualFingerTracking = p_state;
|
base._inputManager.individualFingerTracking = p_state;
|
||||||
IKSystem.Instance.FingerSystem.ControlActive = base._inputManager.individualFingerTracking;
|
IKSystem.Instance.FingerSystem.controlActive = base._inputManager.individualFingerTracking;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
using ABI.CCK.Components;
|
using ABI_RC.Core.Player;
|
||||||
using ABI_RC.Core.Player;
|
|
||||||
using ABI_RC.Systems.GameEventSystem;
|
|
||||||
using ABI_RC.Systems.IK;
|
using ABI_RC.Systems.IK;
|
||||||
using RootMotion.FinalIK;
|
using RootMotion.FinalIK;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -150,8 +148,8 @@ namespace ml_lme
|
||||||
Settings.OnFingersOnlyChanged.AddListener(this.OnEnabledOrFingersOnlyChanged);
|
Settings.OnFingersOnlyChanged.AddListener(this.OnEnabledOrFingersOnlyChanged);
|
||||||
Settings.OnTrackElbowsChanged.AddListener(this.OnTrackElbowsChanged);
|
Settings.OnTrackElbowsChanged.AddListener(this.OnTrackElbowsChanged);
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear);
|
GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup);
|
||||||
GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse);
|
GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,8 +174,8 @@ namespace ml_lme
|
||||||
Settings.OnFingersOnlyChanged.RemoveListener(this.OnEnabledOrFingersOnlyChanged);
|
Settings.OnFingersOnlyChanged.RemoveListener(this.OnEnabledOrFingersOnlyChanged);
|
||||||
Settings.OnTrackElbowsChanged.RemoveListener(this.OnTrackElbowsChanged);
|
Settings.OnTrackElbowsChanged.RemoveListener(this.OnTrackElbowsChanged);
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear);
|
GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup);
|
||||||
GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse);
|
GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,79 +255,65 @@ namespace ml_lme
|
||||||
}
|
}
|
||||||
|
|
||||||
// Game events
|
// Game events
|
||||||
void OnAvatarClear(CVRAvatar p_avatar)
|
void OnAvatarClear()
|
||||||
{
|
{
|
||||||
try
|
m_vrIK = null;
|
||||||
{
|
m_hips = null;
|
||||||
m_vrIK = null;
|
m_leftArmIK = null;
|
||||||
m_hips = null;
|
m_rightArmIK = null;
|
||||||
m_leftArmIK = null;
|
m_leftTargetActive = false;
|
||||||
m_rightArmIK = null;
|
m_rightTargetActive = false;
|
||||||
m_leftTargetActive = false;
|
|
||||||
m_rightTargetActive = false;
|
|
||||||
|
|
||||||
m_poseHandler?.Dispose();
|
m_poseHandler?.Dispose();
|
||||||
m_poseHandler = null;
|
m_poseHandler = null;
|
||||||
|
|
||||||
m_leftHandTarget.localPosition = Vector3.zero;
|
m_leftHandTarget.localPosition = Vector3.zero;
|
||||||
m_leftHandTarget.localRotation = Quaternion.identity;
|
m_leftHandTarget.localRotation = Quaternion.identity;
|
||||||
m_rightHandTarget.localPosition = Vector3.zero;
|
m_rightHandTarget.localPosition = Vector3.zero;
|
||||||
m_rightHandTarget.localRotation = Quaternion.identity;
|
m_rightHandTarget.localRotation = Quaternion.identity;
|
||||||
|
|
||||||
m_leftHandOffset.Reset();
|
m_leftHandOffset.Reset();
|
||||||
m_rightHandOffset.Reset();
|
m_rightHandOffset.Reset();
|
||||||
|
|
||||||
m_leftFingerOffsets.Clear();
|
m_leftFingerOffsets.Clear();
|
||||||
m_rightFingerOffsets.Clear();
|
m_rightFingerOffsets.Clear();
|
||||||
}
|
|
||||||
catch(System.Exception e)
|
|
||||||
{
|
|
||||||
MelonLoader.MelonLogger.Error(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnAvatarSetup(CVRAvatar p_avatar)
|
void OnAvatarSetup()
|
||||||
{
|
{
|
||||||
try
|
Animator l_animator = PlayerSetup.Instance._animator;
|
||||||
|
if(l_animator.isHuman)
|
||||||
{
|
{
|
||||||
Animator l_animator = PlayerSetup.Instance.Animator;
|
Utils.SetAvatarTPose();
|
||||||
if(l_animator.isHuman)
|
|
||||||
|
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<VRIK>();
|
||||||
|
if(m_vrIK != null)
|
||||||
{
|
{
|
||||||
Utils.SetAvatarTPose();
|
m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreSolverUpdate);
|
||||||
|
m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate);
|
||||||
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<VRIK>();
|
|
||||||
if(m_vrIK != null)
|
|
||||||
{
|
|
||||||
m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreSolverUpdate);
|
|
||||||
m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
SetupArmIK();
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
catch(System.Exception e)
|
SetupArmIK();
|
||||||
{
|
|
||||||
MelonLoader.MelonLogger.Error(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnAvatarReuse()
|
void OnAvatarReuse()
|
||||||
{
|
{
|
||||||
// Old VRIK is destroyed by game
|
// Old VRIK is destroyed by game
|
||||||
m_vrIK = PlayerSetup.Instance.AvatarObject.GetComponent<VRIK>();
|
m_vrIK = PlayerSetup.Instance._animator.GetComponent<VRIK>();
|
||||||
|
|
||||||
if(Utils.IsInVR())
|
if(Utils.IsInVR())
|
||||||
RemoveArmIK();
|
RemoveArmIK();
|
||||||
|
@ -425,7 +409,7 @@ namespace ml_lme
|
||||||
|
|
||||||
void SetupArmIK()
|
void SetupArmIK()
|
||||||
{
|
{
|
||||||
Animator l_animator = PlayerSetup.Instance.Animator;
|
Animator l_animator = PlayerSetup.Instance._animator;
|
||||||
Transform l_chest = l_animator.GetBoneTransform(HumanBodyBones.UpperChest);
|
Transform l_chest = l_animator.GetBoneTransform(HumanBodyBones.UpperChest);
|
||||||
if(l_chest == null)
|
if(l_chest == null)
|
||||||
l_chest = l_animator.GetBoneTransform(HumanBodyBones.Chest);
|
l_chest = l_animator.GetBoneTransform(HumanBodyBones.Chest);
|
||||||
|
@ -488,7 +472,7 @@ namespace ml_lme
|
||||||
LeapTracking.Instance.Rebind(PlayerSetup.Instance.transform.rotation);
|
LeapTracking.Instance.Rebind(PlayerSetup.Instance.transform.rotation);
|
||||||
|
|
||||||
// Align rotations of leap fingers to avatar fingers
|
// 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_leapLeft = LeapTracking.Instance.GetLeftHand();
|
||||||
LeapHand l_leapRight = LeapTracking.Instance.GetRightHand();
|
LeapHand l_leapRight = LeapTracking.Instance.GetRightHand();
|
||||||
// Try to "fix" rotations, slightly inaccurate after 0YX plane rotation
|
// Try to "fix" rotations, slightly inaccurate after 0YX plane rotation
|
||||||
|
|
|
@ -136,7 +136,7 @@ namespace ml_lme
|
||||||
{
|
{
|
||||||
if(Settings.Enabled)
|
if(Settings.Enabled)
|
||||||
{
|
{
|
||||||
Transform l_camera = PlayerSetup.Instance.activeCam.transform;
|
Transform l_camera = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||||
m_root.position = l_camera.position;
|
m_root.position = l_camera.position;
|
||||||
m_root.rotation = (Settings.HeadAttach ? l_camera.rotation : PlayerSetup.Instance.GetPlayerRotation());
|
m_root.rotation = (Settings.HeadAttach ? l_camera.rotation : PlayerSetup.Instance.GetPlayerRotation());
|
||||||
|
|
||||||
|
|
|
@ -146,32 +146,32 @@ namespace ml_lme
|
||||||
{
|
{
|
||||||
while(ViewManager.Instance == null)
|
while(ViewManager.Instance == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView == null)
|
while(ViewManager.Instance.gameMenuView == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView.Listener == null)
|
while(ViewManager.Instance.gameMenuView.Listener == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () =>
|
ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action<string, string>(OnDropdownUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action<string, string>(OnDropdownUpdate));
|
||||||
};
|
};
|
||||||
ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) =>
|
ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
||||||
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static System.Collections.IEnumerator UpdateMenuSettings()
|
static System.Collections.IEnumerator UpdateMenuSettings()
|
||||||
{
|
{
|
||||||
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown)
|
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
foreach(var l_entry in ms_entries)
|
foreach(var l_entry in ms_entries)
|
||||||
ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnToggleUpdate(string p_name, string p_value)
|
static void OnToggleUpdate(string p_name, string p_value)
|
||||||
|
|
|
@ -59,8 +59,8 @@ namespace ml_lme
|
||||||
public static void SetAvatarTPose()
|
public static void SetAvatarTPose()
|
||||||
{
|
{
|
||||||
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
||||||
PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero;
|
PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero;
|
||||||
PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity;
|
PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Swap<T>(ref T lhs, ref T rhs)
|
public static void Swap<T>(ref T lhs, ref T rhs)
|
||||||
|
|
|
@ -32,8 +32,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ml_ppu", "ml_ppu\ml_ppu.csp
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ml_vet", "ml_vet\ml_vet.csproj", "{8DB32590-FC5B-46A8-9747-344E86B18ACF}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ml_vet", "ml_vet\ml_vet.csproj", "{8DB32590-FC5B-46A8-9747-344E86B18ACF}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ml_pah", "ml_pah\ml_pah.csproj", "{C4659F60-3FED-4F43-88E4-969907D4C7A6}"
|
|
||||||
EndProject
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
|
@ -85,9 +83,6 @@ Global
|
||||||
{8DB32590-FC5B-46A8-9747-344E86B18ACF}.Debug|x64.Build.0 = Debug|x64
|
{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.ActiveCfg = Release|x64
|
||||||
{8DB32590-FC5B-46A8-9747-344E86B18ACF}.Release|x64.Build.0 = 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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,205 +0,0 @@
|
||||||
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<AvatarEntry> ms_avatarEntries = new List<AvatarEntry>();
|
|
||||||
|
|
||||||
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<AvatarEntry> l_entries = JsonConvert.DeserializeObject<List<AvatarEntry>>(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<AvatarEntry> 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<AvatarEntry> l_listCopy = new List<AvatarEntry>();
|
|
||||||
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<AvatarEntry> 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<AvatarDetailsResponse> l_baseResponse = await ApiConnection.MakeRequest<AvatarDetailsResponse>(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;
|
|
||||||
while(ms_avatarEntries.Count > l_currentLimit)
|
|
||||||
ms_avatarEntries.RemoveAt(ms_avatarEntries.Count - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
131
ml_pah/ModUi.cs
131
ml_pah/ModUi.cs
|
@ -1,131 +0,0 @@
|
||||||
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<Button> ms_avatarButtons = new List<Button>();
|
|
||||||
|
|
||||||
// Init
|
|
||||||
internal static void Initialize()
|
|
||||||
{
|
|
||||||
if(!ms_initialized)
|
|
||||||
{
|
|
||||||
BTKUILib.QuickMenuAPI.PrepareIcon("PlayerAvatarHistory", "guardian", GetIconStream("guardian.png"));
|
|
||||||
BTKUILib.QuickMenuAPI.PrepareIcon("PlayerAvatarHistory", "delete", GetIconStream("delete.png"));
|
|
||||||
BTKUILib.QuickMenuAPI.PrepareIcon("PlayerAvatarHistory", "save", GetIconStream("save.png"));
|
|
||||||
|
|
||||||
ms_page = new Page("PlayerAvatarHistory", "MainPage", true, "guardian");
|
|
||||||
ms_page.MenuTitle = "Player Avatar History";
|
|
||||||
ms_page.MenuSubtitle = "List of last used avatars";
|
|
||||||
|
|
||||||
ms_settingsCategory = ms_page.AddCategory("Settings");
|
|
||||||
|
|
||||||
ms_settingsClearButton = ms_settingsCategory.AddButton("Clear history", "delete", "Clear current history");
|
|
||||||
ms_settingsClearButton.OnPress += ClearHistory;
|
|
||||||
|
|
||||||
ms_settingSaveButton = ms_settingsCategory.AddButton("Save history", "save", "Manually save current history");
|
|
||||||
ms_settingSaveButton.OnPress += SaveHistory;
|
|
||||||
|
|
||||||
ms_settingsEntriesLimit = ms_settingsCategory.AddSlider("History limit", "Number of saved avatar history entries.<p>Warning: Large value can impact performance.", Settings.AvatarsLimit, 10f, 100f, 0);
|
|
||||||
ms_settingsEntriesLimit.OnValueUpdated += OnAvatarLimitChange;
|
|
||||||
|
|
||||||
ms_settingsAutosaveTime = ms_settingsCategory.AddSlider("Autosave period", "Automatic history saving in minutes.", Settings.AutosaveTime, 0f, 60f, 0);
|
|
||||||
ms_settingsAutosaveTime.OnValueUpdated += OnAutosaveTimeChange;
|
|
||||||
|
|
||||||
ms_buttonsCategory = ms_page.AddCategory("Avatars");
|
|
||||||
RegenerateAvatarButtons();
|
|
||||||
|
|
||||||
ms_initialized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void Shutdown()
|
|
||||||
{
|
|
||||||
if(ms_initialized)
|
|
||||||
{
|
|
||||||
ms_page = null;
|
|
||||||
|
|
||||||
ms_buttonsCategory = null;
|
|
||||||
ms_avatarButtons.Clear();
|
|
||||||
|
|
||||||
ms_settingsCategory = null;
|
|
||||||
ms_settingSaveButton = null;
|
|
||||||
ms_settingsClearButton = null;
|
|
||||||
|
|
||||||
ms_initialized = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// History
|
|
||||||
static void ClearHistory()
|
|
||||||
{
|
|
||||||
BTKUILib.QuickMenuAPI.ShowConfirm(
|
|
||||||
"Clear history", "Are you sure want to clear all avatar history?",
|
|
||||||
() =>
|
|
||||||
{
|
|
||||||
HistoryManager.ClearHistory();
|
|
||||||
RegenerateAvatarButtons();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SaveHistory() => HistoryManager.SaveHistory();
|
|
||||||
|
|
||||||
// Update
|
|
||||||
public static void UpdateAvatarsList()
|
|
||||||
{
|
|
||||||
if(ms_initialized)
|
|
||||||
RegenerateAvatarButtons();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Settings
|
|
||||||
static void OnAvatarLimitChange(float p_value) => Settings.SetSetting(Settings.ModSetting.AvatarsLimit, (int)p_value);
|
|
||||||
static void OnAutosaveTimeChange(float p_value) => Settings.SetSetting(Settings.ModSetting.AutosaveTime, (int)p_value);
|
|
||||||
|
|
||||||
// Utility
|
|
||||||
static void RegenerateAvatarButtons()
|
|
||||||
{
|
|
||||||
if(ms_avatarButtons.Count > 0)
|
|
||||||
{
|
|
||||||
foreach(Button l_button in ms_avatarButtons)
|
|
||||||
l_button.Delete();
|
|
||||||
ms_avatarButtons.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(AvatarEntry l_entry in HistoryManager.GetAvatarEntries())
|
|
||||||
{
|
|
||||||
Button l_button = ms_buttonsCategory.AddButton("", "", "", ButtonStyle.FullSizeImage);
|
|
||||||
l_button.ButtonText = (l_entry.m_cached ? l_entry.m_name : "Loading ...");
|
|
||||||
l_button.ButtonIcon = (l_entry.m_cached ? l_entry.m_imageUrl : "");
|
|
||||||
l_button.ButtonTooltip = string.Format("Click to open avatar page, hold to switch avatar.<p>Last used time: {0}", l_entry.m_lastUsageDate.ToString("g"));
|
|
||||||
|
|
||||||
l_button.OnPress += () => ViewManager.Instance.RequestAvatarDetailsPage(l_entry.m_id);
|
|
||||||
l_button.OnHeld += () => AssetManagement.Instance.LoadLocalAvatarFromNetwork(l_entry.m_id);
|
|
||||||
|
|
||||||
ms_avatarButtons.Add(l_button);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Stream GetIconStream(string p_name) => Assembly.GetExecutingAssembly().GetManifestResourceStream(ms_namespace + ".resources." + p_name);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
[assembly: MelonLoader.MelonInfo(typeof(ml_pah.PlayerAvatarHistory), "PlayerAvatarHistory", "1.0.0", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
|
||||||
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
|
|
||||||
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
|
||||||
[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
|
|
|
@ -1,77 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ml_pah
|
|
||||||
{
|
|
||||||
static class Settings
|
|
||||||
{
|
|
||||||
internal class SettingEvent<T>
|
|
||||||
{
|
|
||||||
event Action<T> m_action;
|
|
||||||
public void AddListener(Action<T> p_listener) => m_action += p_listener;
|
|
||||||
public void RemoveListener(Action<T> p_listener) => m_action -= p_listener;
|
|
||||||
public void Invoke(T p_value) => m_action?.Invoke(p_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ModSetting
|
|
||||||
{
|
|
||||||
AvatarsLimit = 0,
|
|
||||||
AutosaveTime
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int AvatarsLimit { get; private set; } = 12;
|
|
||||||
public static int AutosaveTime { get; private set; } = 15;
|
|
||||||
|
|
||||||
public static readonly SettingEvent<int> OnAvatarsLimitChanged = new SettingEvent<int>();
|
|
||||||
public static readonly SettingEvent<int> OnAutosaveTimeChanged = new SettingEvent<int>();
|
|
||||||
|
|
||||||
static MelonLoader.MelonPreferences_Category ms_category = null;
|
|
||||||
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null;
|
|
||||||
|
|
||||||
internal static void Init()
|
|
||||||
{
|
|
||||||
ms_category = MelonLoader.MelonPreferences.CreateCategory("PAH", "Player Avatar History");
|
|
||||||
|
|
||||||
ms_entries = new List<MelonLoader.MelonPreferences_Entry>()
|
|
||||||
{
|
|
||||||
ms_category.CreateEntry(ModSetting.AvatarsLimit.ToString(), AvatarsLimit),
|
|
||||||
ms_category.CreateEntry(ModSetting.AutosaveTime.ToString(), AutosaveTime)
|
|
||||||
};
|
|
||||||
|
|
||||||
AvatarsLimit = Mathf.Clamp((int)ms_entries[(int)ModSetting.AvatarsLimit].BoxedValue, 10, 100);
|
|
||||||
AutosaveTime = Mathf.Clamp((int)ms_entries[(int)ModSetting.AutosaveTime].BoxedValue, 0, 60);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetSetting(ModSetting p_settings, object p_value)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch(p_settings)
|
|
||||||
{
|
|
||||||
// Booleans
|
|
||||||
case ModSetting.AvatarsLimit:
|
|
||||||
{
|
|
||||||
AvatarsLimit = (int)p_value;
|
|
||||||
OnAvatarsLimitChanged.Invoke(AvatarsLimit);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ModSetting.AutosaveTime:
|
|
||||||
{
|
|
||||||
AutosaveTime = (int)p_value;
|
|
||||||
OnAutosaveTimeChanged.Invoke(AutosaveTime);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ms_entries != null)
|
|
||||||
ms_entries[(int)p_settings].BoxedValue = p_value;
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
MelonLoader.MelonLogger.Error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
|
||||||
<Platforms>x64</Platforms>
|
|
||||||
<PackageId>PlayerAvatarHistory</PackageId>
|
|
||||||
<AssemblyName>PlayerAvatarHistory</AssemblyName>
|
|
||||||
<Authors>SDraw</Authors>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<DebugType>embedded</DebugType>
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Remove="resources\delete.png" />
|
|
||||||
<None Remove="resources\guardian.png" />
|
|
||||||
<None Remove="resources\save.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Include="resources\delete.png" />
|
|
||||||
<EmbeddedResource Include="resources\guardian.png" />
|
|
||||||
<EmbeddedResource Include="resources\save.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="Assembly-CSharp">
|
|
||||||
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll</HintPath>
|
|
||||||
<Private>false</Private>
|
|
||||||
<SpecificVersion>false</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="BTKUILib">
|
|
||||||
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\Mods\BTKUILib.dll</HintPath>
|
|
||||||
<Private>false</Private>
|
|
||||||
<SpecificVersion>false</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MelonLoader">
|
|
||||||
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\MelonLoader\net35\MelonLoader.dll</HintPath>
|
|
||||||
<Private>false</Private>
|
|
||||||
<SpecificVersion>false</SpecificVersion>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Newtonsoft.Json">
|
|
||||||
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\Newtonsoft.Json.dll</HintPath>
|
|
||||||
<SpecificVersion>false</SpecificVersion>
|
|
||||||
<Private>false</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="UnityEngine.CoreModule">
|
|
||||||
<HintPath>D:\games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
|
||||||
<SpecificVersion>false</SpecificVersion>
|
|
||||||
<Private>false</Private>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
|
||||||
<Exec Command="copy /y "$(TargetPath)" "D:\Games\Steam\steamapps\common\ChilloutVR\Mods\"" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
</Project>
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 6.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.7 KiB |
|
@ -1,7 +1,6 @@
|
||||||
using ABI.CCK.Components;
|
using ABI.CCK.Components;
|
||||||
using ABI_RC.Core.InteractionSystem;
|
using ABI_RC.Core.InteractionSystem;
|
||||||
using ABI_RC.Core.Player;
|
using ABI_RC.Core.Player;
|
||||||
using ABI_RC.Systems.GameEventSystem;
|
|
||||||
using ABI_RC.Systems.VRModeSwitch;
|
using ABI_RC.Systems.VRModeSwitch;
|
||||||
using RootMotion.FinalIK;
|
using RootMotion.FinalIK;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
@ -69,7 +68,7 @@ namespace ml_pam
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
m_camera = PlayerSetup.Instance.activeCam.transform;
|
m_camera = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||||
|
|
||||||
m_root = new GameObject("Root").transform;
|
m_root = new GameObject("Root").transform;
|
||||||
m_root.parent = this.transform;
|
m_root.parent = this.transform;
|
||||||
|
@ -101,8 +100,8 @@ namespace ml_pam
|
||||||
Settings.OnLeadingHandChanged.AddListener(this.OnLeadingHandChanged);
|
Settings.OnLeadingHandChanged.AddListener(this.OnLeadingHandChanged);
|
||||||
Settings.OnHandsExtensionChanged.AddListener(this.OnHandsExtensionChanged);
|
Settings.OnHandsExtensionChanged.AddListener(this.OnHandsExtensionChanged);
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear);
|
GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup);
|
||||||
GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse);
|
GameEvents.OnAvatarReuse.AddListener(this.OnAvatarReuse);
|
||||||
GameEvents.OnIKScaling.AddListener(this.OnIKScaling);
|
GameEvents.OnIKScaling.AddListener(this.OnIKScaling);
|
||||||
GameEvents.OnPickupGrab.AddListener(this.OnPickupGrab);
|
GameEvents.OnPickupGrab.AddListener(this.OnPickupGrab);
|
||||||
|
@ -150,10 +149,10 @@ namespace ml_pam
|
||||||
Settings.OnLeadingHandChanged.RemoveListener(this.OnLeadingHandChanged);
|
Settings.OnLeadingHandChanged.RemoveListener(this.OnLeadingHandChanged);
|
||||||
Settings.OnHandsExtensionChanged.RemoveListener(this.OnHandsExtensionChanged);
|
Settings.OnHandsExtensionChanged.RemoveListener(this.OnHandsExtensionChanged);
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear);
|
GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup);
|
||||||
GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse);
|
GameEvents.OnAvatarReuse.RemoveListener(this.OnAvatarReuse);
|
||||||
GameEvents.OnIKScaling.RemoveListener(this.OnIKScaling);
|
GameEvents.OnIKScaling.AddListener(this.OnIKScaling);
|
||||||
GameEvents.OnPickupGrab.RemoveListener(this.OnPickupGrab);
|
GameEvents.OnPickupGrab.RemoveListener(this.OnPickupGrab);
|
||||||
GameEvents.OnPickupDrop.RemoveListener(this.OnPickupDrop);
|
GameEvents.OnPickupDrop.RemoveListener(this.OnPickupDrop);
|
||||||
|
|
||||||
|
@ -342,86 +341,72 @@ namespace ml_pam
|
||||||
}
|
}
|
||||||
|
|
||||||
// Game events
|
// Game events
|
||||||
void OnAvatarClear(CVRAvatar p_avatar)
|
void OnAvatarClear()
|
||||||
{
|
{
|
||||||
try
|
m_vrIK = null;
|
||||||
{
|
m_armIKLeft = null;
|
||||||
m_vrIK = null;
|
m_armIKRight = null;
|
||||||
m_armIKLeft = null;
|
m_armsLength.Set(0f, 0f, 0f, 0f);
|
||||||
m_armIKRight = null;
|
m_leftHandParameter = null;
|
||||||
m_armsLength.Set(0f, 0f, 0f, 0f);
|
m_rightHandParameter = null;
|
||||||
m_leftHandParameter = null;
|
|
||||||
m_rightHandParameter = null;
|
|
||||||
}
|
|
||||||
catch(System.Exception e)
|
|
||||||
{
|
|
||||||
MelonLoader.MelonLogger.Error(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnAvatarSetup(CVRAvatar p_avatar)
|
void OnAvatarSetup()
|
||||||
{
|
{
|
||||||
try
|
m_camera = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||||
|
|
||||||
|
if(PlayerSetup.Instance._animator.isHuman)
|
||||||
{
|
{
|
||||||
m_camera = PlayerSetup.Instance.activeCam.transform;
|
m_vrIK = PlayerSetup.Instance._animator.GetComponent<VRIK>();
|
||||||
|
Utils.SetAvatarTPose();
|
||||||
|
|
||||||
if(PlayerSetup.Instance.Animator.isHuman)
|
Animator l_animator = PlayerSetup.Instance._animator;
|
||||||
{
|
Matrix4x4 l_avatarMatrixInv = l_animator.transform.GetMatrix().inverse; // Animator and avatar are on same game object
|
||||||
m_vrIK = PlayerSetup.Instance.Animator.GetComponent<VRIK>();
|
|
||||||
Utils.SetAvatarTPose();
|
|
||||||
|
|
||||||
Animator l_animator = PlayerSetup.Instance.Animator;
|
Transform l_leftHand = l_animator.GetBoneTransform(HumanBodyBones.LeftHand);
|
||||||
Matrix4x4 l_avatarMatrixInv = l_animator.transform.GetMatrix().inverse; // Animator and avatar are on same game object
|
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;
|
||||||
|
|
||||||
Transform l_leftHand = l_animator.GetBoneTransform(HumanBodyBones.LeftHand);
|
m_armsLength.x = GetChainLength(new Transform[]{
|
||||||
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.LeftUpperArm),
|
||||||
l_animator.GetBoneTransform(HumanBodyBones.LeftLowerArm),
|
l_animator.GetBoneTransform(HumanBodyBones.LeftLowerArm),
|
||||||
l_animator.GetBoneTransform(HumanBodyBones.LeftHand)
|
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.RightUpperArm),
|
||||||
l_animator.GetBoneTransform(HumanBodyBones.RightLowerArm),
|
l_animator.GetBoneTransform(HumanBodyBones.RightLowerArm),
|
||||||
l_animator.GetBoneTransform(HumanBodyBones.RightHand)
|
l_animator.GetBoneTransform(HumanBodyBones.RightHand)
|
||||||
});
|
});
|
||||||
m_armsLength.z = Mathf.Abs((l_avatarMatrixInv * l_animator.GetBoneTransform(HumanBodyBones.LeftUpperArm).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);
|
m_armsLength.w = Mathf.Abs((l_avatarMatrixInv * l_animator.GetBoneTransform(HumanBodyBones.RightUpperArm).GetMatrix()).GetPosition().x);
|
||||||
|
|
||||||
if(!Utils.IsInVR())
|
if(!Utils.IsInVR())
|
||||||
|
{
|
||||||
|
if(m_vrIK != null)
|
||||||
{
|
{
|
||||||
if(m_vrIK != null)
|
m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreUpdate);
|
||||||
{
|
m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostUpdate);
|
||||||
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()
|
void OnAvatarReuse()
|
||||||
{
|
{
|
||||||
// Old VRIK is destroyed by game
|
// Old VRIK is destroyed by game
|
||||||
m_vrIK = PlayerSetup.Instance.Animator.GetComponent<VRIK>();
|
m_vrIK = PlayerSetup.Instance._animator.GetComponent<VRIK>();
|
||||||
|
|
||||||
if(Utils.IsInVR())
|
if(Utils.IsInVR())
|
||||||
RemoveArmIK();
|
RemoveArmIK();
|
||||||
|
@ -485,7 +470,7 @@ namespace ml_pam
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_camera = PlayerSetup.Instance.activeCam.transform;
|
m_camera = PlayerSetup.Instance.GetActiveCamera().transform;
|
||||||
this.enabled = !Utils.IsInVR();
|
this.enabled = !Utils.IsInVR();
|
||||||
}
|
}
|
||||||
catch(System.Exception e)
|
catch(System.Exception e)
|
||||||
|
@ -497,7 +482,7 @@ namespace ml_pam
|
||||||
// Arbitrary
|
// Arbitrary
|
||||||
void SetupArmIK()
|
void SetupArmIK()
|
||||||
{
|
{
|
||||||
Animator l_animator = PlayerSetup.Instance.Animator;
|
Animator l_animator = PlayerSetup.Instance._animator;
|
||||||
|
|
||||||
Transform l_chest = l_animator.GetBoneTransform(HumanBodyBones.UpperChest);
|
Transform l_chest = l_animator.GetBoneTransform(HumanBodyBones.UpperChest);
|
||||||
if(l_chest == null)
|
if(l_chest == null)
|
||||||
|
@ -505,7 +490,7 @@ namespace ml_pam
|
||||||
if(l_chest == null)
|
if(l_chest == null)
|
||||||
l_chest = l_animator.GetBoneTransform(HumanBodyBones.Spine);
|
l_chest = l_animator.GetBoneTransform(HumanBodyBones.Spine);
|
||||||
|
|
||||||
m_armIKLeft = PlayerSetup.Instance.AvatarObject.AddComponent<ArmIK>();
|
m_armIKLeft = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
|
||||||
m_armIKLeft.solver.isLeft = true;
|
m_armIKLeft.solver.isLeft = true;
|
||||||
m_armIKLeft.solver.SetChain(
|
m_armIKLeft.solver.SetChain(
|
||||||
l_chest,
|
l_chest,
|
||||||
|
@ -522,7 +507,7 @@ namespace ml_pam
|
||||||
m_armIKLeft.solver.IKRotationWeight = 0f;
|
m_armIKLeft.solver.IKRotationWeight = 0f;
|
||||||
m_armIKLeft.enabled = false;
|
m_armIKLeft.enabled = false;
|
||||||
|
|
||||||
m_armIKRight = PlayerSetup.Instance.AvatarObject.AddComponent<ArmIK>();
|
m_armIKRight = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
|
||||||
m_armIKRight.solver.isLeft = false;
|
m_armIKRight.solver.isLeft = false;
|
||||||
m_armIKRight.solver.SetChain(
|
m_armIKRight.solver.SetChain(
|
||||||
l_chest,
|
l_chest,
|
||||||
|
|
|
@ -31,6 +31,8 @@ namespace ml_pam
|
||||||
public void Invoke(T1 p_objA, T2 p_objB) => m_action?.Invoke(p_objA, p_objB);
|
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 OnAvatarReuse = new GameEvent();
|
||||||
public static readonly GameEvent<float> OnIKScaling = new GameEvent<float>();
|
public static readonly GameEvent<float> OnIKScaling = new GameEvent<float>();
|
||||||
public static readonly GameEvent<CVRPickupObject, Vector3> OnPickupGrab = new GameEvent<CVRPickupObject, Vector3>();
|
public static readonly GameEvent<CVRPickupObject, Vector3> OnPickupGrab = new GameEvent<CVRPickupObject, Vector3>();
|
||||||
|
@ -40,6 +42,18 @@ namespace ml_pam
|
||||||
{
|
{
|
||||||
try
|
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(
|
p_instance.Patch(
|
||||||
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
||||||
null,
|
null,
|
||||||
|
@ -70,6 +84,30 @@ 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()
|
static void OnAvatarReinitialize_Postfix()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -84,33 +84,33 @@ namespace ml_pam
|
||||||
{
|
{
|
||||||
while(ViewManager.Instance == null)
|
while(ViewManager.Instance == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView == null)
|
while(ViewManager.Instance.gameMenuView == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView.Listener == null)
|
while(ViewManager.Instance.gameMenuView.Listener == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () =>
|
ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () =>
|
||||||
{
|
{
|
||||||
|
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action<string, string>(OnDropdownUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action<string, string>(OnDropdownUpdate));
|
||||||
};
|
};
|
||||||
ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) =>
|
ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResources("mods_extension.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResources("mods_extension.js"));
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResources("mod_menu.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResources("mod_menu.js"));
|
||||||
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static System.Collections.IEnumerator UpdateMenuSettings()
|
static System.Collections.IEnumerator UpdateMenuSettings()
|
||||||
{
|
{
|
||||||
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown)
|
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
foreach(var l_entry in ms_entries)
|
foreach(var l_entry in ms_entries)
|
||||||
ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnMelonSettingSave_LeftHandKey(object p_oldValue, object p_newValue)
|
static void OnMelonSettingSave_LeftHandKey(object p_oldValue, object p_newValue)
|
||||||
|
|
|
@ -18,8 +18,8 @@ namespace ml_pam
|
||||||
public static void SetAvatarTPose()
|
public static void SetAvatarTPose()
|
||||||
{
|
{
|
||||||
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
||||||
PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero;
|
PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero;
|
||||||
PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity;
|
PlayerSetup.Instance._avatar.transform.localRotation = Quaternion.identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extensions
|
// Extensions
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
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.Core.Savior;
|
using ABI_RC.Core.Savior;
|
||||||
using ABI_RC.Core.Networking.IO.Instancing;
|
|
||||||
using ABI_RC.Systems.GameEventSystem;
|
using ABI_RC.Systems.GameEventSystem;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
@ -108,9 +107,9 @@ namespace ml_pin
|
||||||
|
|
||||||
bool ShouldNotifyInCurrentInstance()
|
bool ShouldNotifyInCurrentInstance()
|
||||||
{
|
{
|
||||||
bool l_isInPublic = ((MetaPort.Instance.CurrentInstancePrivacyType == Instances.InstancePrivacyType.Public) && Settings.NotifyInPublic);
|
bool l_isInPublic = ((MetaPort.Instance.CurrentInstancePrivacyType == MetaPort.InstancePrivacy.Public) && Settings.NotifyInPublic);
|
||||||
bool l_isInFriends = (((MetaPort.Instance.CurrentInstancePrivacyType == Instances.InstancePrivacyType.Friends) || (MetaPort.Instance.CurrentInstancePrivacyType == Instances.InstancePrivacyType.FriendsOfFriends)) && Settings.NotifyInFriends);
|
bool l_isInFriends = (((MetaPort.Instance.CurrentInstancePrivacyType == MetaPort.InstancePrivacy.Friends) || (MetaPort.Instance.CurrentInstancePrivacyType == MetaPort.InstancePrivacy.FriendsOfFriends)) && Settings.NotifyInFriends);
|
||||||
bool l_isInPrivate = (((MetaPort.Instance.CurrentInstancePrivacyType == Instances.InstancePrivacyType.EveryoneCanInvite) || (MetaPort.Instance.CurrentInstancePrivacyType == Instances.InstancePrivacyType.OwnerMustInvite)) && Settings.NotifyInPrivate);
|
bool l_isInPrivate = (((MetaPort.Instance.CurrentInstancePrivacyType == MetaPort.InstancePrivacy.EveryoneCanInvite) || (MetaPort.Instance.CurrentInstancePrivacyType == MetaPort.InstancePrivacy.OwnerMustInvite)) && Settings.NotifyInPrivate);
|
||||||
return (l_isInPublic || l_isInFriends || l_isInPrivate);
|
return (l_isInPublic || l_isInFriends || l_isInPrivate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,32 +81,32 @@ namespace ml_pin
|
||||||
{
|
{
|
||||||
while(ViewManager.Instance == null)
|
while(ViewManager.Instance == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView == null)
|
while(ViewManager.Instance.gameMenuView == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView.Listener == null)
|
while(ViewManager.Instance.gameMenuView.Listener == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () =>
|
ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action<string, string>(OnDropdownUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action<string, string>(OnDropdownUpdate));
|
||||||
};
|
};
|
||||||
ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) =>
|
ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
||||||
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static System.Collections.IEnumerator UpdateMenuSettings()
|
static System.Collections.IEnumerator UpdateMenuSettings()
|
||||||
{
|
{
|
||||||
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown)
|
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
foreach(var l_entry in ms_entries)
|
foreach(var l_entry in ms_entries)
|
||||||
ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnToggleUpdate(string p_name, string p_value)
|
static void OnToggleUpdate(string p_name, string p_value)
|
||||||
|
|
|
@ -15,6 +15,8 @@ namespace ml_pmc
|
||||||
public void Invoke() => m_action?.Invoke();
|
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 OnAvatarPreReuse = new GameEvent();
|
||||||
public static readonly GameEvent OnAvatarPostReuse = new GameEvent();
|
public static readonly GameEvent OnAvatarPostReuse = new GameEvent();
|
||||||
|
|
||||||
|
@ -22,6 +24,18 @@ namespace ml_pmc
|
||||||
{
|
{
|
||||||
try
|
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(
|
p_instance.Patch(
|
||||||
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
||||||
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)),
|
||||||
|
@ -34,6 +48,30 @@ 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()
|
static void OnAvatarReinitialize_Prefix()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
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.IK;
|
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;
|
||||||
|
@ -57,8 +55,8 @@ namespace ml_pmc
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear);
|
GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup);
|
||||||
GameEvents.OnAvatarPreReuse.AddListener(this.OnAvatarPreReuse);
|
GameEvents.OnAvatarPreReuse.AddListener(this.OnAvatarPreReuse);
|
||||||
GameEvents.OnAvatarPostReuse.AddListener(this.OnAvatarPostReuse);
|
GameEvents.OnAvatarPostReuse.AddListener(this.OnAvatarPostReuse);
|
||||||
|
|
||||||
|
@ -80,8 +78,8 @@ namespace ml_pmc
|
||||||
m_vrIk = null;
|
m_vrIk = null;
|
||||||
m_lookAtIk = null;
|
m_lookAtIk = null;
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear);
|
GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup);
|
||||||
GameEvents.OnAvatarPreReuse.RemoveListener(this.OnAvatarPreReuse);
|
GameEvents.OnAvatarPreReuse.RemoveListener(this.OnAvatarPreReuse);
|
||||||
GameEvents.OnAvatarPostReuse.RemoveListener(this.OnAvatarPostReuse);
|
GameEvents.OnAvatarPostReuse.RemoveListener(this.OnAvatarPostReuse);
|
||||||
|
|
||||||
|
@ -112,7 +110,7 @@ namespace ml_pmc
|
||||||
m_fingerTracking = true;
|
m_fingerTracking = true;
|
||||||
|
|
||||||
CVRInputManager.Instance.individualFingerTracking = 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_curls = ref m_puppetParser.GetFingerCurls();
|
||||||
ref readonly float[] l_spreads = ref m_puppetParser.GetFingerSpreads();
|
ref readonly float[] l_spreads = ref m_puppetParser.GetFingerSpreads();
|
||||||
|
@ -198,9 +196,9 @@ namespace ml_pmc
|
||||||
{
|
{
|
||||||
if(m_inVr)
|
if(m_inVr)
|
||||||
{
|
{
|
||||||
Vector3 l_avatarPos = PlayerSetup.Instance.AvatarTransform.position;
|
Vector3 l_avatarPos = PlayerSetup.Instance._avatar.transform.position;
|
||||||
PlayerSetup.Instance.transform.rotation = l_result.rotation;
|
PlayerSetup.Instance.transform.rotation = l_result.rotation;
|
||||||
Vector3 l_dif = l_avatarPos - PlayerSetup.Instance.AvatarTransform.position;
|
Vector3 l_dif = l_avatarPos - PlayerSetup.Instance._avatar.transform.position;
|
||||||
PlayerSetup.Instance.transform.position += l_dif;
|
PlayerSetup.Instance.transform.position += l_dif;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -231,72 +229,58 @@ namespace ml_pmc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Game events
|
// Game events
|
||||||
void OnAvatarClear(CVRAvatar p_avatar)
|
void OnAvatarClear()
|
||||||
{
|
{
|
||||||
try
|
if(m_active)
|
||||||
{
|
{
|
||||||
if(m_active)
|
RestoreIK();
|
||||||
{
|
RestoreFingerTracking();
|
||||||
RestoreIK();
|
OnCopycatChanged.Invoke(false);
|
||||||
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(CVRAvatar p_avatar)
|
void OnAvatarSetup()
|
||||||
{
|
{
|
||||||
try
|
m_inVr = Utils.IsInVR();
|
||||||
{
|
m_animator = PlayerSetup.Instance._animator;
|
||||||
m_inVr = Utils.IsInVR();
|
m_vrIk = PlayerSetup.Instance._avatar.GetComponent<VRIK>();
|
||||||
m_animator = PlayerSetup.Instance.Animator;
|
m_lookAtIk = PlayerSetup.Instance._avatar.GetComponent<LookAtIK>();
|
||||||
m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent<VRIK>();
|
|
||||||
m_lookAtIk = PlayerSetup.Instance.AvatarObject.GetComponent<LookAtIK>();
|
|
||||||
|
|
||||||
if((m_animator != null) && m_animator.isHuman)
|
if((m_animator != null) && m_animator.isHuman)
|
||||||
|
{
|
||||||
|
m_poseHandler = new HumanPoseHandler(m_animator.avatar, m_animator.transform);
|
||||||
|
m_poseHandler.GetHumanPose(ref m_pose);
|
||||||
|
|
||||||
|
if(m_vrIk != null)
|
||||||
{
|
{
|
||||||
m_poseHandler = new HumanPoseHandler(m_animator.avatar, m_animator.transform);
|
m_vrIk.onPreSolverUpdate.AddListener(this.OnVRIKPreUpdate);
|
||||||
m_poseHandler.GetHumanPose(ref m_pose);
|
m_vrIk.onPostSolverUpdate.AddListener(this.OnVRIKPostUpdate);
|
||||||
|
}
|
||||||
if(m_vrIk != null)
|
|
||||||
{
|
if(m_lookAtIk != null)
|
||||||
m_vrIk.onPreSolverUpdate.AddListener(this.OnVRIKPreUpdate);
|
{
|
||||||
m_vrIk.onPostSolverUpdate.AddListener(this.OnVRIKPostUpdate);
|
m_lookAtIk.onPreSolverUpdate.AddListener(this.OnLookAtIKPreUpdate);
|
||||||
}
|
m_lookAtIk.onPostSolverUpdate.AddListener(this.OnLookAtIKPostUpdate);
|
||||||
|
|
||||||
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()
|
void OnAvatarPreReuse()
|
||||||
|
@ -309,8 +293,8 @@ namespace ml_pmc
|
||||||
m_inVr = Utils.IsInVR();
|
m_inVr = Utils.IsInVR();
|
||||||
|
|
||||||
// Old VRIK and LookAtIK are destroyed by game
|
// Old VRIK and LookAtIK are destroyed by game
|
||||||
m_vrIk = PlayerSetup.Instance.AvatarObject.GetComponent<VRIK>();
|
m_vrIk = PlayerSetup.Instance._avatar.GetComponent<VRIK>();
|
||||||
m_lookAtIk = PlayerSetup.Instance.AvatarObject.GetComponent<LookAtIK>();
|
m_lookAtIk = PlayerSetup.Instance._avatar.GetComponent<LookAtIK>();
|
||||||
|
|
||||||
if(m_vrIk != null)
|
if(m_vrIk != null)
|
||||||
{
|
{
|
||||||
|
@ -336,10 +320,10 @@ namespace ml_pmc
|
||||||
{
|
{
|
||||||
if(Friends.FriendsWith(p_id))
|
if(Friends.FriendsWith(p_id))
|
||||||
{
|
{
|
||||||
if(CVRPlayerManager.Instance.UserIdToPlayerEntity.TryGetValue(p_id, out CVRPlayerEntity l_playerEntity))
|
if(CVRPlayerManager.Instance.GetPlayerPuppetMaster(p_id, out PuppetMaster l_puppetMaster))
|
||||||
{
|
{
|
||||||
if(Utils.IsInSight(BetterBetterCharacterController.Instance.KinematicTriggerProxy.Collider, l_playerEntity.PuppetMaster.GetComponent<CapsuleCollider>(), Utils.GetWorldMovementLimit()))
|
if(Utils.IsInSight(BetterBetterCharacterController.Instance.KinematicTriggerProxy.Collider, l_puppetMaster.GetComponent<CapsuleCollider>(), Utils.GetWorldMovementLimit()))
|
||||||
SetTarget(l_playerEntity.PuppetMaster);
|
SetTarget(l_puppetMaster);
|
||||||
else
|
else
|
||||||
ModUi.ShowAlert("Selected player is too far away or obstructed");
|
ModUi.ShowAlert("Selected player is too far away or obstructed");
|
||||||
}
|
}
|
||||||
|
@ -390,9 +374,9 @@ namespace ml_pmc
|
||||||
{
|
{
|
||||||
if(!m_active)
|
if(!m_active)
|
||||||
{
|
{
|
||||||
if((p_target != null) && (p_target.AnimatorManager != null) && (p_target.Animator != null) && p_target.Animator.isHuman)
|
if((p_target != null) && (p_target.animatorManager != null) && (p_target.animatorManager.Animator != null) && p_target.animatorManager.Animator.isHuman)
|
||||||
{
|
{
|
||||||
m_puppetParser = p_target.Animator.gameObject.AddComponent<PuppetParser>();
|
m_puppetParser = p_target.animatorManager.Animator.gameObject.AddComponent<PuppetParser>();
|
||||||
m_puppetParser.m_puppetMaster = p_target;
|
m_puppetParser.m_puppetMaster = p_target;
|
||||||
m_distanceLimit = Utils.GetWorldMovementLimit();
|
m_distanceLimit = Utils.GetWorldMovementLimit();
|
||||||
|
|
||||||
|
@ -441,7 +425,7 @@ namespace ml_pmc
|
||||||
void RestoreFingerTracking()
|
void RestoreFingerTracking()
|
||||||
{
|
{
|
||||||
CVRInputManager.Instance.individualFingerTracking = (m_inVr && Utils.AreKnucklesInUse() && !CVRInputManager._moduleXR.SkeletalToggleValue);
|
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)
|
if(!CVRInputManager.Instance.individualFingerTracking)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[assembly: MelonLoader.MelonInfo(typeof(ml_pmc.PlayerMovementCopycat), "PlayerMovementCopycat", "1.1.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
[assembly: MelonLoader.MelonInfo(typeof(ml_pmc.PlayerMovementCopycat), "PlayerMovementCopycat", "1.1.1", "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")]
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using ABI.CCK.Components;
|
using ABI.CCK.Components;
|
||||||
using ABI_RC.Core;
|
|
||||||
using ABI_RC.Core.Savior;
|
using ABI_RC.Core.Savior;
|
||||||
using ABI_RC.Systems.InputManagement;
|
using ABI_RC.Systems.InputManagement;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -87,9 +86,9 @@ namespace ml_pmc
|
||||||
List<RaycastHit> l_hits = Physics.RaycastAll(l_ray, p_limit).ToList();
|
List<RaycastHit> l_hits = Physics.RaycastAll(l_ray, p_limit).ToList();
|
||||||
if(l_hits.Count > 0)
|
if(l_hits.Count > 0)
|
||||||
{
|
{
|
||||||
l_hits.RemoveAll(hit => hit.collider.gameObject.layer == CVRLayers.UIInternal); // Somehow layer mask in RaycastAll just ignores players entirely
|
l_hits.RemoveAll(hit => hit.collider.gameObject.layer == LayerMask.NameToLayer("UI Internal")); // Somehow layer mask in RaycastAll just ignores players entirely
|
||||||
l_hits.RemoveAll(hit => hit.collider.gameObject.layer == CVRLayers.PlayerLocal);
|
l_hits.RemoveAll(hit => hit.collider.gameObject.layer == LayerMask.NameToLayer("PlayerLocal"));
|
||||||
l_hits.RemoveAll(hit => hit.collider.gameObject.layer == CVRLayers.PlayerClone);
|
l_hits.RemoveAll(hit => hit.collider.gameObject.layer == LayerMask.NameToLayer("PlayerClone"));
|
||||||
l_hits.Sort((a, b) => ((a.distance < b.distance) ? -1 : 1));
|
l_hits.Sort((a, b) => ((a.distance < b.distance) ? -1 : 1));
|
||||||
l_result = (l_hits[0].collider.gameObject.transform.root == p_target.transform.root);
|
l_result = (l_hits[0].collider.gameObject.transform.root == p_target.transform.root);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.2</Version>
|
<Version>1.1.1</Version>
|
||||||
<AssemblyName>PlayerMovementCopycat</AssemblyName>
|
<AssemblyName>PlayerMovementCopycat</AssemblyName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="resources\dancing.png" />
|
<None Remove="resources\dancing.png" />
|
||||||
<None Remove="resources\dancing_on.png" />
|
<None Remove="resources\dancing_on.png" />
|
||||||
<None Remove="Utils.cs~RFd8ec2a.TMP" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -23,6 +23,8 @@ namespace ml_ppu
|
||||||
public void Invoke(T1 p_obj) => m_action?.Invoke(p_obj);
|
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<float> OnIKScaling = new GameEvent<float>();
|
public static readonly GameEvent<float> OnIKScaling = new GameEvent<float>();
|
||||||
public static readonly GameEvent OnWorldPreSpawn = new GameEvent();
|
public static readonly GameEvent OnWorldPreSpawn = new GameEvent();
|
||||||
public static readonly GameEvent<CVRSeat> OnSeatPreSit = new GameEvent<CVRSeat>();
|
public static readonly GameEvent<CVRSeat> OnSeatPreSit = new GameEvent<CVRSeat>();
|
||||||
|
@ -31,6 +33,18 @@ namespace ml_ppu
|
||||||
{
|
{
|
||||||
try
|
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(
|
p_instance.Patch(
|
||||||
typeof(PlayerSetup).GetMethod("SetupIKScaling", BindingFlags.Instance | BindingFlags.NonPublic),
|
typeof(PlayerSetup).GetMethod("SetupIKScaling", BindingFlags.Instance | BindingFlags.NonPublic),
|
||||||
null,
|
null,
|
||||||
|
@ -55,6 +69,30 @@ 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)
|
static void OnSetupIKScaling_Postfix(ref UnityEngine.Vector3 ___scaleDifference)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
using ABI.CCK.Components;
|
using ABI.CCK.Components;
|
||||||
using ABI_RC.Core;
|
|
||||||
using ABI_RC.Core.InteractionSystem;
|
using ABI_RC.Core.InteractionSystem;
|
||||||
using ABI_RC.Core.Player;
|
using ABI_RC.Core.Player;
|
||||||
using ABI_RC.Systems.GameEventSystem;
|
|
||||||
using ABI_RC.Systems.IK;
|
using ABI_RC.Systems.IK;
|
||||||
using ABI_RC.Systems.Movement;
|
using ABI_RC.Systems.Movement;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
@ -47,8 +45,8 @@ namespace ml_ppu
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear);
|
GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear);
|
||||||
GameEvents.OnIKScaling.AddListener(this.OnIKScaling);
|
GameEvents.OnIKScaling.AddListener(this.OnIKScaling);
|
||||||
GameEvents.OnWorldPreSpawn.AddListener(this.OnWorldPreSpawn);
|
GameEvents.OnWorldPreSpawn.AddListener(this.OnWorldPreSpawn);
|
||||||
GameEvents.OnSeatPreSit.AddListener(this.OnSeatPreSit);
|
GameEvents.OnSeatPreSit.AddListener(this.OnSeatPreSit);
|
||||||
|
@ -61,8 +59,8 @@ namespace ml_ppu
|
||||||
if(Instance == this)
|
if(Instance == this)
|
||||||
Instance = null;
|
Instance = null;
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear);
|
GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear);
|
||||||
GameEvents.OnIKScaling.RemoveListener(this.OnIKScaling);
|
GameEvents.OnIKScaling.RemoveListener(this.OnIKScaling);
|
||||||
GameEvents.OnWorldPreSpawn.RemoveListener(this.OnWorldPreSpawn);
|
GameEvents.OnWorldPreSpawn.RemoveListener(this.OnWorldPreSpawn);
|
||||||
GameEvents.OnSeatPreSit.RemoveListener(this.OnSeatPreSit);
|
GameEvents.OnSeatPreSit.RemoveListener(this.OnSeatPreSit);
|
||||||
|
@ -83,7 +81,7 @@ namespace ml_ppu
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 l_armsMidPoint = (m_armLeft.position + m_armRight.position) * 0.5f;
|
Vector3 l_armsMidPoint = (m_armLeft.position + m_armRight.position) * 0.5f;
|
||||||
Quaternion l_avatarRot = PlayerSetup.Instance.AvatarTransform.rotation;
|
Quaternion l_avatarRot = PlayerSetup.Instance._avatar.transform.rotation;
|
||||||
|
|
||||||
m_collider.transform.position = Vector3.zero;
|
m_collider.transform.position = Vector3.zero;
|
||||||
m_collider.transform.rotation = Quaternion.identity;
|
m_collider.transform.rotation = Quaternion.identity;
|
||||||
|
@ -127,67 +125,52 @@ namespace ml_ppu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnAvatarSetup(CVRAvatar p_avatar)
|
void OnAvatarSetup()
|
||||||
{
|
{
|
||||||
try
|
Animator l_animator = PlayerSetup.Instance._animator;
|
||||||
|
if((l_animator != null) && l_animator.isHuman)
|
||||||
{
|
{
|
||||||
Animator l_animator = PlayerSetup.Instance.Animator;
|
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
||||||
if((l_animator != null) && l_animator.isHuman)
|
PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero;
|
||||||
|
PlayerSetup.Instance._avatar.transform.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))
|
||||||
{
|
{
|
||||||
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
Matrix4x4 l_avatarMatInv = PlayerSetup.Instance._avatar.transform.GetMatrix().inverse;
|
||||||
PlayerSetup.Instance.AvatarTransform.localPosition = Vector3.zero;
|
Vector3 l_hipsPos = (l_avatarMatInv * m_hips.GetMatrix()).GetPosition();
|
||||||
PlayerSetup.Instance.AvatarTransform.localRotation = Quaternion.identity;
|
Vector3 l_armPos = (l_avatarMatInv * m_armLeft.GetMatrix()).GetPosition();
|
||||||
|
|
||||||
m_hips = l_animator.GetBoneTransform(HumanBodyBones.Hips);
|
m_collider = new GameObject("[Collider]").AddComponent<CapsuleCollider>();
|
||||||
m_armLeft = l_animator.GetBoneTransform(HumanBodyBones.LeftUpperArm);
|
m_collider.transform.parent = this.transform;
|
||||||
m_armRight = l_animator.GetBoneTransform(HumanBodyBones.RightUpperArm);
|
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<GrabDetector>();
|
||||||
|
|
||||||
if((m_hips != null) && (m_armLeft != null) && (m_armRight != null))
|
m_ready = true;
|
||||||
{
|
|
||||||
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<CapsuleCollider>();
|
|
||||||
m_collider.gameObject.layer = CVRLayers.PassPlayer;
|
|
||||||
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<GrabDetector>();
|
|
||||||
|
|
||||||
m_ready = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(System.Exception e)
|
|
||||||
{
|
|
||||||
MelonLoader.MelonLogger.Error(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnAvatarClear(CVRAvatar p_avatar)
|
void OnAvatarClear()
|
||||||
{
|
{
|
||||||
try
|
m_ready = false;
|
||||||
{
|
m_held = false;
|
||||||
m_ready = false;
|
|
||||||
m_held = false;
|
|
||||||
|
|
||||||
if(m_collider != null)
|
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);
|
Destroy(m_collider.gameObject);
|
||||||
|
m_collider = null;
|
||||||
}
|
}
|
||||||
|
m_holderPointA = null;
|
||||||
|
m_holderPointerA = null;
|
||||||
|
m_holderPointB = null;
|
||||||
|
m_holderPointerB = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnIKScaling(float p_scale)
|
void OnIKScaling(float p_scale)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[assembly: MelonLoader.MelonInfo(typeof(ml_ppu.PlayerPickUp), "PlayerPickUp", "1.0.1", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
[assembly: MelonLoader.MelonInfo(typeof(ml_ppu.PlayerPickUp), "PlayerPickUp", "1.0.0", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
||||||
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
|
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
|
||||||
[assembly: MelonLoader.MelonOptionalDependencies("PlayerRagdollMod")]
|
[assembly: MelonLoader.MelonOptionalDependencies("PlayerRagdollMod")]
|
||||||
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using ABI_RC.Core;
|
using ABI_RC.Core;
|
||||||
using ABI_RC.Core.Player;
|
using ABI_RC.Core.Player;
|
||||||
using ABI_RC.Core.Savior;
|
|
||||||
using ABI_RC.Systems.Movement;
|
using ABI_RC.Systems.Movement;
|
||||||
using ABI_RC.Systems.Safety.AdvancedSafety;
|
using ABI_RC.Systems.Safety.AdvancedSafety;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
@ -9,8 +8,6 @@ namespace ml_ppu
|
||||||
{
|
{
|
||||||
static class Utils
|
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)
|
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);
|
return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.lossyScale : Vector3.one);
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<AssemblyName>PlayerPickUp</AssemblyName>
|
<AssemblyName>PlayerPickUp</AssemblyName>
|
||||||
<Authors>SDraw</Authors>
|
<Authors>SDraw</Authors>
|
||||||
<Version>1.0.1</Version>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
|
43
ml_prm/AvatarBoolParameter.cs
Normal file
43
ml_prm/AvatarBoolParameter.cs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,109 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -32,6 +32,8 @@ namespace ml_prm
|
||||||
public void Invoke(T1 p_obj) => m_action?.Invoke(p_obj);
|
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 OnAvatarPreReuse = new GameEvent();
|
||||||
public static readonly GameEvent OnAvatarPostReuse = new GameEvent();
|
public static readonly GameEvent OnAvatarPostReuse = new GameEvent();
|
||||||
public static readonly GameEvent<float> OnIKScaling = new GameEvent<float>();
|
public static readonly GameEvent<float> OnIKScaling = new GameEvent<float>();
|
||||||
|
@ -48,6 +50,18 @@ namespace ml_prm
|
||||||
{
|
{
|
||||||
try
|
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(
|
p_instance.Patch(
|
||||||
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
|
||||||
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)),
|
||||||
|
@ -94,12 +108,30 @@ namespace ml_prm
|
||||||
typeof(IKSystem).GetMethod("OnPreSolverUpdateActiveOffset", BindingFlags.Instance | BindingFlags.NonPublic),
|
typeof(IKSystem).GetMethod("OnPreSolverUpdateActiveOffset", BindingFlags.Instance | BindingFlags.NonPublic),
|
||||||
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnOffsetUpdate_Prefix), BindingFlags.Static | BindingFlags.NonPublic))
|
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnOffsetUpdate_Prefix), BindingFlags.Static | BindingFlags.NonPublic))
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
MelonLoader.MelonLogger.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
p_instance.Patch(
|
static void OnAvatarClear_Postfix()
|
||||||
typeof(ControllerRay).GetMethod("UpdateInteractionMask", BindingFlags.Instance | BindingFlags.NonPublic),
|
{
|
||||||
null,
|
try
|
||||||
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnControllerRayUpdateInteractionMask_Prefix), BindingFlags.Static | BindingFlags.NonPublic))
|
{
|
||||||
);
|
OnAvatarClear.Invoke();
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
MelonLoader.MelonLogger.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnSetupAvatar_Postfix()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
OnAvatarSetup.Invoke();
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
|
@ -216,10 +248,5 @@ namespace ml_prm
|
||||||
}
|
}
|
||||||
return !ms_result.m_result;
|
return !ms_result.m_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnControllerRayUpdateInteractionMask_Prefix(ControllerRay __instance)
|
|
||||||
{
|
|
||||||
__instance.generalMask &= ~(1 << CVRLayers.PlayerClone);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
using ABI_RC.Core.Util.AssetFiltering;
|
using ABI_RC.Core.Player;
|
||||||
|
using ABI_RC.Core.Util.AssetFiltering;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace ml_prm
|
namespace ml_prm
|
||||||
{
|
{
|
||||||
|
@ -23,6 +27,7 @@ namespace ml_prm
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
m_controller = new UnityEngine.GameObject("[PlayerRagdollMod]").AddComponent<RagdollController>();
|
m_controller = new UnityEngine.GameObject("[PlayerRagdollMod]").AddComponent<RagdollController>();
|
||||||
|
m_controller.gameObject.AddComponent<RemoteGesturesManager>();
|
||||||
}
|
}
|
||||||
|
|
||||||
System.Collections.IEnumerator WaitForWhitelist()
|
System.Collections.IEnumerator WaitForWhitelist()
|
||||||
|
|
|
@ -36,7 +36,8 @@ namespace ml_prm
|
||||||
RecoverDelay,
|
RecoverDelay,
|
||||||
FallLimit,
|
FallLimit,
|
||||||
GestureGrab,
|
GestureGrab,
|
||||||
FriendsGrab
|
FriendsGrab,
|
||||||
|
GrabDistance
|
||||||
}
|
}
|
||||||
|
|
||||||
const string c_ragdollKeyTooltip = "Switch ragdoll mode with '{0}' key";
|
const string c_ragdollKeyTooltip = "Switch ragdoll mode with '{0}' key";
|
||||||
|
@ -68,6 +69,7 @@ namespace ml_prm
|
||||||
static SliderFloat ms_angularMovementDragSlider = null;
|
static SliderFloat ms_angularMovementDragSlider = null;
|
||||||
static SliderFloat ms_recoverDelaySlider = null;
|
static SliderFloat ms_recoverDelaySlider = null;
|
||||||
static SliderFloat ms_fallLimitSlider = null;
|
static SliderFloat ms_fallLimitSlider = null;
|
||||||
|
static SliderFloat ms_grabDistanceSlider = null;
|
||||||
static Button ms_resetButton = null;
|
static Button ms_resetButton = null;
|
||||||
|
|
||||||
internal static void Init()
|
internal static void Init()
|
||||||
|
@ -143,6 +145,9 @@ namespace ml_prm
|
||||||
ms_fallLimitSlider.SliderTooltip = string.Format(c_fallLimitTooltip, GetDropHeight(Settings.FallLimit));
|
ms_fallLimitSlider.SliderTooltip = string.Format(c_fallLimitTooltip, GetDropHeight(Settings.FallLimit));
|
||||||
ms_fallLimitSlider.OnValueUpdated += (value) => OnSliderUpdate(UiIndex.FallLimit, value);
|
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 = ms_category.AddButton("Reset settings", "", "Reset mod settings to default");
|
||||||
ms_resetButton.OnPress += Reset;
|
ms_resetButton.OnPress += Reset;
|
||||||
}
|
}
|
||||||
|
@ -256,6 +261,10 @@ namespace ml_prm
|
||||||
ms_fallLimitSlider.SliderTooltip = string.Format(c_fallLimitTooltip, GetDropHeight(p_value));
|
ms_fallLimitSlider.SliderTooltip = string.Format(c_fallLimitTooltip, GetDropHeight(p_value));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case UiIndex.GrabDistance:
|
||||||
|
Settings.SetSetting(Settings.ModSetting.GrabDistance, p_value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
|
@ -322,6 +331,9 @@ namespace ml_prm
|
||||||
|
|
||||||
OnSliderUpdate(UiIndex.FallLimit, 9.899494f);
|
OnSliderUpdate(UiIndex.FallLimit, 9.899494f);
|
||||||
ms_fallLimitSlider.SetSliderValue(9.899494f);
|
ms_fallLimitSlider.SetSliderValue(9.899494f);
|
||||||
|
|
||||||
|
OnSliderUpdate(UiIndex.GrabDistance, 0.1f);
|
||||||
|
ms_grabDistanceSlider.SetSliderValue(0.1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnHotkeyKeyChanged(UnityEngine.KeyCode p_keyCode)
|
static void OnHotkeyKeyChanged(UnityEngine.KeyCode p_keyCode)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.2.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.2.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
||||||
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
|
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
|
||||||
[assembly: MelonLoader.MelonPriority(2)]
|
[assembly: MelonLoader.MelonPriority(2)]
|
||||||
[assembly: MelonLoader.MelonAdditionalDependencies("BTKUILib")]
|
[assembly: MelonLoader.MelonAdditionalDependencies("BTKUILib")]
|
||||||
|
|
|
@ -41,6 +41,7 @@ Optional mod's settings page with [BTKUILib](https://github.com/BTK-Development/
|
||||||
* **Angular movement drag:** angular movement resistance; `2.0` by default.
|
* **Angular movement drag:** angular movement resistance; `2.0` by default.
|
||||||
* **Recover delay:** time delay for enabled `Auto recover` in seconds; `3.0` by default.
|
* **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.
|
* **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.
|
* **Reset settings:** resets mod settings to default.
|
||||||
|
|
||||||
Optional mod's settings in [UIExpansionKit](https://github.com/ddakebono/ChilloutMods):
|
Optional mod's settings in [UIExpansionKit](https://github.com/ddakebono/ChilloutMods):
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
using ABI.CCK.Components;
|
using ABI.CCK.Components;
|
||||||
using ABI_RC.Core;
|
|
||||||
using ABI_RC.Core.Networking.IO.Social;
|
|
||||||
using ABI_RC.Core.Player;
|
using ABI_RC.Core.Player;
|
||||||
using ABI_RC.Core.Savior;
|
using ABI_RC.Core.Savior;
|
||||||
using ABI_RC.Systems.Movement;
|
using ABI_RC.Systems.Movement;
|
||||||
|
@ -12,24 +10,24 @@ namespace ml_prm
|
||||||
class RagdollBodypartHandler : MonoBehaviour, CVRTriggerVolume
|
class RagdollBodypartHandler : MonoBehaviour, CVRTriggerVolume
|
||||||
{
|
{
|
||||||
const string c_ragdollPointerType = "ragdoll";
|
const string c_ragdollPointerType = "ragdoll";
|
||||||
const string c_grabPointerType = "grab";
|
|
||||||
|
|
||||||
bool m_ready = false;
|
|
||||||
|
|
||||||
Rigidbody m_rigidBody = null;
|
Rigidbody m_rigidBody = null;
|
||||||
public Collider collider { get; set; } = null;
|
public Collider collider { get; set; } = null;
|
||||||
|
|
||||||
PhysicsInfluencer m_physicsInfluencer = null;
|
PhysicsInfluencer m_physicsInfluencer = null;
|
||||||
public bool UseBuoyancy { get; set; } = false;
|
|
||||||
|
bool m_shouldHaveInfluencer = false;
|
||||||
|
bool m_activeGravity = true;
|
||||||
|
|
||||||
bool m_attached = false;
|
bool m_attached = false;
|
||||||
CVRPointer m_attachedPointer = null;
|
Transform m_attachedHand = null;
|
||||||
Transform m_attachTransform = null;
|
Transform m_attachTransform = null;
|
||||||
FixedJoint m_attachJoint = null;
|
FixedJoint m_attachJoint = null;
|
||||||
|
|
||||||
// Unity events
|
// Unity events
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
|
this.gameObject.layer = LayerMask.NameToLayer("PlayerLocal");
|
||||||
|
|
||||||
collider = this.GetComponent<Collider>();
|
collider = this.GetComponent<Collider>();
|
||||||
m_rigidBody = this.GetComponent<Rigidbody>();
|
m_rigidBody = this.GetComponent<Rigidbody>();
|
||||||
|
|
||||||
|
@ -42,25 +40,30 @@ namespace ml_prm
|
||||||
}
|
}
|
||||||
|
|
||||||
if(collider != null)
|
if(collider != null)
|
||||||
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, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
if((m_rigidBody != null) && (collider != null))
|
if(m_shouldHaveInfluencer && (m_rigidBody != null) && (collider != null))
|
||||||
{
|
{
|
||||||
m_physicsInfluencer = this.gameObject.AddComponent<PhysicsInfluencer>();
|
m_physicsInfluencer = this.gameObject.AddComponent<PhysicsInfluencer>();
|
||||||
m_physicsInfluencer.fluidDrag = 3f;
|
m_physicsInfluencer.fluidDrag = 3f;
|
||||||
m_physicsInfluencer.fluidAngularDrag = 1f;
|
m_physicsInfluencer.fluidAngularDrag = 1f;
|
||||||
m_physicsInfluencer.enableInfluence = true;
|
|
||||||
m_physicsInfluencer.enableLocalGravity = true;
|
|
||||||
m_physicsInfluencer.enableBuoyancy = true;
|
m_physicsInfluencer.enableBuoyancy = true;
|
||||||
|
m_physicsInfluencer.enableInfluence = false;
|
||||||
m_physicsInfluencer.forceAlignUpright = false;
|
m_physicsInfluencer.forceAlignUpright = false;
|
||||||
|
float mass = m_rigidBody.mass;
|
||||||
float l_mass = m_rigidBody.mass;
|
|
||||||
m_physicsInfluencer.UpdateDensity();
|
m_physicsInfluencer.UpdateDensity();
|
||||||
m_rigidBody.mass = l_mass;
|
m_rigidBody.mass = mass;
|
||||||
m_physicsInfluencer.volume = l_mass * 0.005f;
|
m_physicsInfluencer.volume = mass * 0.005f;
|
||||||
|
m_physicsInfluencer.enableLocalGravity = true;
|
||||||
|
|
||||||
this.gameObject.name = string.Format("{0} [NoGizmo]", this.gameObject.name);
|
this.gameObject.name = string.Format("{0} [NoGizmo]", this.gameObject.name);
|
||||||
}
|
}
|
||||||
|
@ -80,36 +83,45 @@ namespace ml_prm
|
||||||
Detach();
|
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()
|
void Update()
|
||||||
{
|
{
|
||||||
if(m_attached && ((m_attachedPointer == null) || !m_attachedPointer.isActiveAndEnabled))
|
if(m_attached && !ReferenceEquals(m_attachTransform, null) && (m_attachTransform == null))
|
||||||
Detach();
|
{
|
||||||
|
m_attachTransform = null;
|
||||||
|
|
||||||
|
if(m_attachJoint != null)
|
||||||
|
Object.Destroy(m_attachJoint);
|
||||||
|
m_attachJoint = null;
|
||||||
|
|
||||||
|
m_attachedHand = null;
|
||||||
|
m_attached = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnTriggerEnter(Collider p_col)
|
void OnTriggerEnter(Collider p_col)
|
||||||
{
|
{
|
||||||
if(m_ready && (RagdollController.Instance != null))
|
if(Settings.PointersReaction && (RagdollController.Instance != null) && !RagdollController.Instance.IsRagdolled())
|
||||||
{
|
{
|
||||||
CVRPointer l_pointer = p_col.GetComponent<CVRPointer>();
|
CVRPointer l_pointer = p_col.GetComponent<CVRPointer>();
|
||||||
|
if((l_pointer != null) && (l_pointer.type == c_ragdollPointerType) && l_pointer.enabled && !IsIgnored(l_pointer.transform))
|
||||||
// Ragdolling
|
RagdollController.Instance.Ragdoll();
|
||||||
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
|
// Arbitrary
|
||||||
public bool IsReady() => ((m_rigidBody != null) && (collider != null) && (m_physicsInfluencer != null) && m_physicsInfluencer.IsReady());
|
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 void SetColliderMaterial(PhysicMaterial p_material)
|
public void SetColliderMaterial(PhysicMaterial p_material)
|
||||||
{
|
{
|
||||||
|
@ -122,15 +134,13 @@ namespace ml_prm
|
||||||
|
|
||||||
public void SetAsKinematic(bool p_state)
|
public void SetAsKinematic(bool p_state)
|
||||||
{
|
{
|
||||||
|
if(collider != null)
|
||||||
|
collider.isTrigger = p_state;
|
||||||
if(m_rigidBody != null)
|
if(m_rigidBody != null)
|
||||||
{
|
{
|
||||||
m_rigidBody.isKinematic = p_state;
|
m_rigidBody.isKinematic = p_state;
|
||||||
m_rigidBody.collisionDetectionMode = (p_state ? CollisionDetectionMode.Discrete : CollisionDetectionMode.ContinuousDynamic);
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetVelocity(Vector3 p_vec)
|
public void SetVelocity(Vector3 p_vec)
|
||||||
|
@ -147,8 +157,10 @@ namespace ml_prm
|
||||||
|
|
||||||
public void SetActiveGravity(bool p_state)
|
public void SetActiveGravity(bool p_state)
|
||||||
{
|
{
|
||||||
|
m_activeGravity = p_state;
|
||||||
|
|
||||||
if(m_physicsInfluencer != null)
|
if(m_physicsInfluencer != null)
|
||||||
m_physicsInfluencer.gravityFactor = (p_state ? 1f : 0f);
|
m_physicsInfluencer.enabled = m_activeGravity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetDrag(float p_value)
|
public void SetDrag(float p_value)
|
||||||
|
@ -176,7 +188,7 @@ namespace ml_prm
|
||||||
public void SetBuoyancy(bool p_state)
|
public void SetBuoyancy(bool p_state)
|
||||||
{
|
{
|
||||||
if(m_physicsInfluencer != null)
|
if(m_physicsInfluencer != null)
|
||||||
m_physicsInfluencer.enableBuoyancy = (UseBuoyancy && p_state);
|
m_physicsInfluencer.enableInfluence = p_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearFluidVolumes()
|
public void ClearFluidVolumes()
|
||||||
|
@ -185,27 +197,21 @@ namespace ml_prm
|
||||||
m_physicsInfluencer.ClearFluidVolumes();
|
m_physicsInfluencer.ClearFluidVolumes();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void RemovePhysicsController()
|
static bool IsIgnored(Transform p_transform)
|
||||||
{
|
{
|
||||||
if(this.gameObject.TryGetComponent<CVRSharedPhysicsController>(out var l_controller))
|
return (Settings.IgnoreLocal && (p_transform.root == PlayerSetup.Instance.transform));
|
||||||
{
|
|
||||||
Object.Destroy(l_controller); // Yeet!
|
|
||||||
m_ready = true;
|
|
||||||
}
|
|
||||||
if(collider != null)
|
|
||||||
RemoveGameCollision();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attach(CVRPointer p_pointer)
|
public bool Attach(Transform p_hand, Vector3 p_pos)
|
||||||
{
|
{
|
||||||
if(!m_attached && (collider != null) && (m_rigidBody != null))
|
bool l_result = false;
|
||||||
{
|
|
||||||
m_attachedPointer = p_pointer;
|
|
||||||
|
|
||||||
|
if(!m_attached && (collider != null) && (Vector3.Distance(p_pos, collider.ClosestPoint(p_pos)) <= Settings.GrabDistance))
|
||||||
|
{
|
||||||
GameObject l_attachPoint = new GameObject("[AttachPoint]");
|
GameObject l_attachPoint = new GameObject("[AttachPoint]");
|
||||||
l_attachPoint.layer = CVRLayers.PlayerNetwork;
|
|
||||||
m_attachTransform = l_attachPoint.transform;
|
m_attachTransform = l_attachPoint.transform;
|
||||||
m_attachTransform.parent = p_pointer.transform;
|
m_attachTransform.parent = p_hand;
|
||||||
|
m_attachTransform.position = p_pos;
|
||||||
|
|
||||||
Rigidbody l_body = l_attachPoint.AddComponent<Rigidbody>();
|
Rigidbody l_body = l_attachPoint.AddComponent<Rigidbody>();
|
||||||
l_body.isKinematic = true;
|
l_body.isKinematic = true;
|
||||||
|
@ -217,12 +223,16 @@ namespace ml_prm
|
||||||
m_attachJoint.breakTorque = Mathf.Infinity;
|
m_attachJoint.breakTorque = Mathf.Infinity;
|
||||||
|
|
||||||
m_attached = true;
|
m_attached = true;
|
||||||
|
m_attachedHand = p_hand;
|
||||||
|
l_result = true;
|
||||||
}
|
}
|
||||||
|
return l_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Detach()
|
public void Detach() => Detach(m_attachedHand);
|
||||||
|
public void Detach(Transform p_hand)
|
||||||
{
|
{
|
||||||
if(m_attached)
|
if(m_attached && ReferenceEquals(m_attachedHand, p_hand))
|
||||||
{
|
{
|
||||||
if(m_attachTransform != null)
|
if(m_attachTransform != null)
|
||||||
Object.Destroy(m_attachTransform.gameObject);
|
Object.Destroy(m_attachTransform.gameObject);
|
||||||
|
@ -232,46 +242,19 @@ namespace ml_prm
|
||||||
Object.Destroy(m_attachJoint);
|
Object.Destroy(m_attachJoint);
|
||||||
m_attachJoint = null;
|
m_attachJoint = null;
|
||||||
|
|
||||||
m_attachedPointer = null;
|
m_attachedHand = null;
|
||||||
m_attached = false;
|
m_attached = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// CVRTriggerVolume
|
||||||
public void TriggerEnter(CVRPointer pointer)
|
public void TriggerEnter(CVRPointer pointer)
|
||||||
{
|
{
|
||||||
if(Settings.PointersReaction && (pointer != null) && pointer.enabled && (pointer.type == c_ragdollPointerType) && !IgnoreCheck(pointer.transform) && (RagdollController.Instance != null) && !RagdollController.Instance.IsRagdolled())
|
if(Settings.PointersReaction && (pointer != null) && pointer.enabled && (pointer.type == c_ragdollPointerType) && !IsIgnored(pointer.transform) && (RagdollController.Instance != null) && !RagdollController.Instance.IsRagdolled())
|
||||||
RagdollController.Instance.Ragdoll();
|
RagdollController.Instance.Ragdoll();
|
||||||
}
|
}
|
||||||
public void TriggerExit(CVRPointer pointer)
|
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<PlayerDescriptor>();
|
|
||||||
if(l_playerDescriptor != null)
|
|
||||||
return (!Settings.FriendsGrab || Friends.FriendsWith(l_playerDescriptor.ownerId));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
using ABI.CCK.Components;
|
using ABI.CCK.Components;
|
||||||
using ABI_RC.Core;
|
|
||||||
using ABI_RC.Core.InteractionSystem;
|
using ABI_RC.Core.InteractionSystem;
|
||||||
using ABI_RC.Core.Player;
|
using ABI_RC.Core.Player;
|
||||||
using ABI_RC.Systems.GameEventSystem;
|
|
||||||
using ABI_RC.Systems.IK;
|
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;
|
||||||
|
@ -41,7 +39,7 @@ namespace ml_prm
|
||||||
readonly List<System.Tuple<CharacterJoint, Vector3>> m_jointAnchors = null;
|
readonly List<System.Tuple<CharacterJoint, Vector3>> m_jointAnchors = null;
|
||||||
|
|
||||||
RagdollToggle m_avatarRagdollToggle = null; // Custom component available for editor
|
RagdollToggle m_avatarRagdollToggle = null; // Custom component available for editor
|
||||||
AvatarParameter m_ragdolledParameter = null;
|
AvatarBoolParameter m_ragdolledParameter = null;
|
||||||
PhysicMaterial m_physicsMaterial = null;
|
PhysicMaterial m_physicsMaterial = null;
|
||||||
|
|
||||||
bool m_inAir = false;
|
bool m_inAir = false;
|
||||||
|
@ -77,7 +75,7 @@ namespace ml_prm
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
this.gameObject.layer = CVRLayers.PlayerClone;
|
this.gameObject.layer = LayerMask.NameToLayer("PlayerLocal");
|
||||||
|
|
||||||
m_physicsMaterial = new PhysicMaterial("Ragdoll");
|
m_physicsMaterial = new PhysicMaterial("Ragdoll");
|
||||||
m_physicsMaterial.dynamicFriction = c_defaultFriction;
|
m_physicsMaterial.dynamicFriction = c_defaultFriction;
|
||||||
|
@ -100,8 +98,8 @@ namespace ml_prm
|
||||||
Settings.OnFallDamageChanged.AddListener(this.OnFallDamageChanged);
|
Settings.OnFallDamageChanged.AddListener(this.OnFallDamageChanged);
|
||||||
Settings.OnGestureGrabChanged.AddListener(this.OnGestureGrabChanged);
|
Settings.OnGestureGrabChanged.AddListener(this.OnGestureGrabChanged);
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(this.OnAvatarClear);
|
GameEvents.OnAvatarClear.AddListener(this.OnAvatarClear);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarSetup.AddListener(this.OnAvatarSetup);
|
||||||
GameEvents.OnAvatarPreReuse.AddListener(this.OnAvatarPreReuse);
|
GameEvents.OnAvatarPreReuse.AddListener(this.OnAvatarPreReuse);
|
||||||
GameEvents.OnAvatarPostReuse.AddListener(this.OnAvatarPostReuse);
|
GameEvents.OnAvatarPostReuse.AddListener(this.OnAvatarPostReuse);
|
||||||
GameEvents.OnIKScaling.AddListener(this.OnAvatarScaling);
|
GameEvents.OnIKScaling.AddListener(this.OnAvatarScaling);
|
||||||
|
@ -114,6 +112,7 @@ namespace ml_prm
|
||||||
BetterBetterCharacterController.OnTeleport.AddListener(this.OnPlayerTeleport);
|
BetterBetterCharacterController.OnTeleport.AddListener(this.OnPlayerTeleport);
|
||||||
|
|
||||||
ModUi.OnSwitchChanged.AddListener(this.SwitchRagdoll);
|
ModUi.OnSwitchChanged.AddListener(this.SwitchRagdoll);
|
||||||
|
RemoteGesturesManager.OnGestureState.AddListener(this.OnRemoteGestureStateChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnDestroy()
|
void OnDestroy()
|
||||||
|
@ -148,8 +147,8 @@ namespace ml_prm
|
||||||
Settings.OnFallDamageChanged.RemoveListener(this.OnFallDamageChanged);
|
Settings.OnFallDamageChanged.RemoveListener(this.OnFallDamageChanged);
|
||||||
Settings.OnGestureGrabChanged.RemoveListener(this.OnGestureGrabChanged);
|
Settings.OnGestureGrabChanged.RemoveListener(this.OnGestureGrabChanged);
|
||||||
|
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarClear.RemoveListener(this.OnAvatarClear);
|
GameEvents.OnAvatarClear.RemoveListener(this.OnAvatarClear);
|
||||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.RemoveListener(this.OnAvatarSetup);
|
GameEvents.OnAvatarSetup.RemoveListener(this.OnAvatarSetup);
|
||||||
GameEvents.OnAvatarPreReuse.RemoveListener(this.OnAvatarPreReuse);
|
GameEvents.OnAvatarPreReuse.RemoveListener(this.OnAvatarPreReuse);
|
||||||
GameEvents.OnAvatarPostReuse.RemoveListener(this.OnAvatarPostReuse);
|
GameEvents.OnAvatarPostReuse.RemoveListener(this.OnAvatarPostReuse);
|
||||||
GameEvents.OnIKScaling.RemoveListener(this.OnAvatarScaling);
|
GameEvents.OnIKScaling.RemoveListener(this.OnAvatarScaling);
|
||||||
|
@ -162,6 +161,7 @@ namespace ml_prm
|
||||||
BetterBetterCharacterController.OnTeleport.RemoveListener(this.OnPlayerTeleport);
|
BetterBetterCharacterController.OnTeleport.RemoveListener(this.OnPlayerTeleport);
|
||||||
|
|
||||||
ModUi.OnSwitchChanged.RemoveListener(this.SwitchRagdoll);
|
ModUi.OnSwitchChanged.RemoveListener(this.SwitchRagdoll);
|
||||||
|
RemoteGesturesManager.OnGestureState.RemoveListener(this.OnRemoteGestureStateChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update()
|
void Update()
|
||||||
|
@ -194,7 +194,7 @@ namespace ml_prm
|
||||||
BodySystem.TrackingPositionWeight = 0f;
|
BodySystem.TrackingPositionWeight = 0f;
|
||||||
BetterBetterCharacterController.Instance.PauseGroundConstraint();
|
BetterBetterCharacterController.Instance.PauseGroundConstraint();
|
||||||
BetterBetterCharacterController.Instance.ResetAllForces();
|
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()))
|
if(!m_ragdolled && !m_reachedGround && (BetterBetterCharacterController.Instance.IsOnGround() || BetterBetterCharacterController.Instance.IsInWater() || BetterBetterCharacterController.Instance.IsSitting()))
|
||||||
|
@ -251,146 +251,128 @@ namespace ml_prm
|
||||||
}
|
}
|
||||||
|
|
||||||
// Game events
|
// Game events
|
||||||
void OnAvatarClear(CVRAvatar p_avatar)
|
void OnAvatarClear()
|
||||||
{
|
{
|
||||||
try
|
if(m_initTask != null)
|
||||||
{
|
{
|
||||||
if(m_initTask != null)
|
StopCoroutine(m_initTask);
|
||||||
{
|
m_initTask = null;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
catch(System.Exception e)
|
|
||||||
|
if(m_ragdolled)
|
||||||
{
|
{
|
||||||
MelonLoader.MelonLogger.Error(e);
|
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(CVRAvatar p_avatar)
|
void OnAvatarSetup()
|
||||||
{
|
{
|
||||||
try
|
if(PlayerSetup.Instance._animator.isHuman)
|
||||||
{
|
{
|
||||||
if(PlayerSetup.Instance.Animator.isHuman)
|
m_avatarTransform = PlayerSetup.Instance._avatar.transform;
|
||||||
|
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.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++)
|
||||||
{
|
{
|
||||||
m_avatarTransform = PlayerSetup.Instance.AvatarTransform;
|
if(l_puppetTransforms[i] != null)
|
||||||
m_hips = PlayerSetup.Instance.Animator.GetBoneTransform(HumanBodyBones.Hips);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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<CharacterJoint>();
|
||||||
|
if(l_joint != null)
|
||||||
{
|
{
|
||||||
CharacterJoint l_joint = l_puppetTransforms[i].GetComponent<CharacterJoint>();
|
l_joint.enablePreprocessing = false;
|
||||||
if(l_joint != null)
|
l_joint.enableProjection = true;
|
||||||
{
|
m_jointAnchors.Add(System.Tuple.Create(l_joint, l_joint.connectedAnchor));
|
||||||
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<Rigidbody>();
|
|
||||||
Collider l_collider = l_puppetTransforms[i].GetComponent<Collider>();
|
|
||||||
if((l_body != null) && (l_collider != null))
|
|
||||||
{
|
|
||||||
RagdollBodypartHandler l_handler = l_puppetTransforms[i].gameObject.AddComponent<RagdollBodypartHandler>();
|
|
||||||
l_handler.UseBuoyancy = Utils.IsObjectInArray(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]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rigidbody l_body = l_puppetTransforms[i].GetComponent<Rigidbody>();
|
||||||
|
Collider l_collider = l_puppetTransforms[i].GetComponent<Collider>();
|
||||||
|
if((l_body != null) && (l_collider != null))
|
||||||
|
{
|
||||||
|
RagdollBodypartHandler l_handler = l_puppetTransforms[i].gameObject.AddComponent<RagdollBodypartHandler>();
|
||||||
|
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<VRIK>();
|
|
||||||
if(m_vrIK != null)
|
|
||||||
m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate);
|
|
||||||
|
|
||||||
m_avatarRagdollToggle = PlayerSetup.Instance.AvatarObject.GetComponentInChildren<RagdollToggle>(true);
|
|
||||||
m_ragdolledParameter = new AvatarParameter("Ragdolled", PlayerSetup.Instance.AnimatorManager);
|
|
||||||
|
|
||||||
m_initTask = StartCoroutine(WaitForBodyHandlers());
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch(System.Exception e)
|
m_vrIK = PlayerSetup.Instance._avatar.GetComponent<VRIK>();
|
||||||
{
|
if(m_vrIK != null)
|
||||||
MelonLoader.MelonLogger.Error(e);
|
m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate);
|
||||||
|
|
||||||
|
m_avatarRagdollToggle = PlayerSetup.Instance._avatar.GetComponentInChildren<RagdollToggle>(true);
|
||||||
|
m_ragdolledParameter = new AvatarBoolParameter("Ragdolled", PlayerSetup.Instance.animatorManager);
|
||||||
|
|
||||||
|
m_initTask = StartCoroutine(WaitForBodyHandlers());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,7 +383,6 @@ namespace ml_prm
|
||||||
|
|
||||||
foreach(RagdollBodypartHandler l_handler in m_ragdollBodyHandlers)
|
foreach(RagdollBodypartHandler l_handler in m_ragdollBodyHandlers)
|
||||||
{
|
{
|
||||||
l_handler.RemovePhysicsController();
|
|
||||||
l_handler.SetAsKinematic(true);
|
l_handler.SetAsKinematic(true);
|
||||||
l_handler.SetColliderMaterial(m_physicsMaterial);
|
l_handler.SetColliderMaterial(m_physicsMaterial);
|
||||||
}
|
}
|
||||||
|
@ -427,7 +408,7 @@ namespace ml_prm
|
||||||
}
|
}
|
||||||
void OnAvatarPostReuse()
|
void OnAvatarPostReuse()
|
||||||
{
|
{
|
||||||
m_vrIK = PlayerSetup.Instance.AvatarObject.GetComponent<VRIK>();
|
m_vrIK = PlayerSetup.Instance._avatar.GetComponent<VRIK>();
|
||||||
|
|
||||||
if(m_vrIK != null)
|
if(m_vrIK != null)
|
||||||
m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate);
|
m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostSolverUpdate);
|
||||||
|
@ -520,6 +501,31 @@ namespace ml_prm
|
||||||
p_result.m_result |= (m_ragdolled && (m_vrIK != null));
|
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.animatorManager.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);
|
||||||
|
|
||||||
|
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
|
// VRIK updates
|
||||||
void OnIKPostSolverUpdate()
|
void OnIKPostSolverUpdate()
|
||||||
{
|
{
|
||||||
|
@ -634,7 +640,7 @@ namespace ml_prm
|
||||||
if(Settings.ViewVelocity && WorldManager.IsSafeWorld())
|
if(Settings.ViewVelocity && WorldManager.IsSafeWorld())
|
||||||
{
|
{
|
||||||
float l_mag = l_velocity.magnitude;
|
float l_mag = l_velocity.magnitude;
|
||||||
l_velocity = PlayerSetup.Instance.activeCam.transform.forward * l_mag;
|
l_velocity = PlayerSetup.Instance.GetActiveCamera().transform.forward * l_mag;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 l_playerPos = PlayerSetup.Instance.transform.position;
|
Vector3 l_playerPos = PlayerSetup.Instance.transform.position;
|
||||||
|
@ -658,7 +664,7 @@ namespace ml_prm
|
||||||
m_applyHipsRotation = IKSystem.Instance.applyOriginalHipRotation;
|
m_applyHipsRotation = IKSystem.Instance.applyOriginalHipRotation;
|
||||||
IKSystem.Instance.applyOriginalHipRotation = true;
|
IKSystem.Instance.applyOriginalHipRotation = true;
|
||||||
|
|
||||||
PlayerSetup.Instance.AnimatorManager.CancelEmote = true;
|
PlayerSetup.Instance.animatorManager.CancelEmote = true;
|
||||||
m_ragdolledParameter.SetValue(true);
|
m_ragdolledParameter.SetValue(true);
|
||||||
|
|
||||||
if(!WorldManager.IsSafeWorld())
|
if(!WorldManager.IsSafeWorld())
|
||||||
|
@ -775,7 +781,6 @@ namespace ml_prm
|
||||||
static Transform CloneTransform(Transform p_source, Transform p_parent, string p_name)
|
static Transform CloneTransform(Transform p_source, Transform p_parent, string p_name)
|
||||||
{
|
{
|
||||||
Transform l_target = new GameObject(p_name).transform;
|
Transform l_target = new GameObject(p_name).transform;
|
||||||
l_target.gameObject.layer = CVRLayers.PlayerClone;
|
|
||||||
l_target.parent = p_parent;
|
l_target.parent = p_parent;
|
||||||
p_source.CopyGlobal(l_target);
|
p_source.CopyGlobal(l_target);
|
||||||
return l_target;
|
return l_target;
|
||||||
|
|
148
ml_prm/RemoteGesturesManager.cs
Normal file
148
ml_prm/RemoteGesturesManager.cs
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
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<T1, T2, T3>
|
||||||
|
{
|
||||||
|
event Action<T1, T2, T3> m_action;
|
||||||
|
public void AddListener(Action<T1, T2, T3> p_listener) => m_action += p_listener;
|
||||||
|
public void RemoveListener(Action<T1, T2, T3> 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<PuppetMaster, GestureHand, bool> OnGestureState = new GestureEvent<PuppetMaster, GestureHand, bool>();
|
||||||
|
|
||||||
|
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<PlayerEntry> m_entries = null;
|
||||||
|
|
||||||
|
internal RemoteGesturesManager()
|
||||||
|
{
|
||||||
|
m_entries = new List<PlayerEntry>();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,7 +35,8 @@ namespace ml_prm
|
||||||
FallDamage,
|
FallDamage,
|
||||||
FallLimit,
|
FallLimit,
|
||||||
GestureGrab,
|
GestureGrab,
|
||||||
FriendsGrab
|
FriendsGrab,
|
||||||
|
GrabDistance
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Hotkey { get; private set; } = true;
|
public static bool Hotkey { get; private set; } = true;
|
||||||
|
@ -110,7 +111,8 @@ namespace ml_prm
|
||||||
ms_category.CreateEntry(ModSetting.FallDamage.ToString(), FallDamage, null, null, true),
|
ms_category.CreateEntry(ModSetting.FallDamage.ToString(), FallDamage, null, null, true),
|
||||||
ms_category.CreateEntry(ModSetting.FallLimit.ToString(), FallLimit, 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.GestureGrab.ToString(), GestureGrab, null, null, true),
|
||||||
ms_category.CreateEntry(ModSetting.FriendsGrab.ToString(), FriendsGrab, null, null, true)
|
ms_category.CreateEntry(ModSetting.FriendsGrab.ToString(), FriendsGrab, null, null, true),
|
||||||
|
ms_category.CreateEntry(ModSetting.GrabDistance.ToString(), GrabDistance, null, null, true),
|
||||||
};
|
};
|
||||||
|
|
||||||
ms_entries[(int)ModSetting.HotkeyKey].OnEntryValueChangedUntyped.Subscribe(OnMelonSettingSave_HotkeyKey);
|
ms_entries[(int)ModSetting.HotkeyKey].OnEntryValueChangedUntyped.Subscribe(OnMelonSettingSave_HotkeyKey);
|
||||||
|
@ -135,6 +137,7 @@ namespace ml_prm
|
||||||
FallLimit = Mathf.Clamp((float)ms_entries[(int)ModSetting.FallLimit].BoxedValue, 4.5f, 44.5f);
|
FallLimit = Mathf.Clamp((float)ms_entries[(int)ModSetting.FallLimit].BoxedValue, 4.5f, 44.5f);
|
||||||
GestureGrab = (bool)ms_entries[(int)ModSetting.GestureGrab].BoxedValue;
|
GestureGrab = (bool)ms_entries[(int)ModSetting.GestureGrab].BoxedValue;
|
||||||
FriendsGrab = (bool)ms_entries[(int)ModSetting.FriendsGrab].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)
|
static void OnMelonSettingSave_HotkeyKey(object p_oldValue, object p_newValue)
|
||||||
|
@ -293,6 +296,13 @@ namespace ml_prm
|
||||||
OnFallLimitChanged.Invoke(FallLimit);
|
OnFallLimitChanged.Invoke(FallLimit);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ModSetting.GrabDistance:
|
||||||
|
{
|
||||||
|
GrabDistance = (float)p_value;
|
||||||
|
OnGrabDistanceChanged.Invoke(GrabDistance);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ms_entries != null)
|
if(ms_entries != null)
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using ABI_RC.Systems.IK.SubSystems;
|
||||||
using ABI_RC.Core.InteractionSystem;
|
using ABI_RC.Core.InteractionSystem;
|
||||||
|
|
||||||
namespace ml_prm
|
namespace ml_prm
|
||||||
|
@ -21,6 +22,12 @@ namespace ml_prm
|
||||||
|
|
||||||
public static void ClearFluidVolumes(this BetterBetterCharacterController p_instance) => (ms_touchingVolumes?.GetValue(p_instance) as List<FluidVolume>)?.Clear();
|
public static void ClearFluidVolumes(this BetterBetterCharacterController p_instance) => (ms_touchingVolumes?.GetValue(p_instance) as List<FluidVolume>)?.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)
|
public static bool IsReady(this PhysicsInfluencer p_instance)
|
||||||
{
|
{
|
||||||
return ((ms_referencePoints.GetValue(p_instance) as List<Vector3>).Count > 0);
|
return ((ms_referencePoints.GetValue(p_instance) as List<Vector3>).Count > 0);
|
||||||
|
@ -31,15 +38,27 @@ namespace ml_prm
|
||||||
(ms_influencerSubmergedColliders.GetValue(p_instance) as Dictionary<FluidVolume, int>)?.Clear();
|
(ms_influencerSubmergedColliders.GetValue(p_instance) as Dictionary<FluidVolume, int>)?.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsObjectInArray(object p_obj, object[] p_enumeration) => p_enumeration.Contains(p_obj);
|
public static void SetAvatarTPose()
|
||||||
|
{
|
||||||
|
IKSystem.Instance.SetAvatarPose(IKSystem.AvatarPose.TPose);
|
||||||
|
PlayerSetup.Instance._avatar.transform.localPosition = Vector3.zero;
|
||||||
|
PlayerSetup.Instance._avatar.transform.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 CVRSeat GetCurrentSeat(this BetterBetterCharacterController p_instance) => (ms_lastCVRSeat?.GetValue(p_instance) as CVRSeat);
|
public static CVRSeat GetCurrentSeat(this BetterBetterCharacterController p_instance) => (ms_lastCVRSeat?.GetValue(p_instance) as CVRSeat);
|
||||||
|
|
||||||
// Unity specific
|
public static bool IsInRange(float p_value, float p_min, float p_max) => ((p_min <= p_value) && (p_value <= p_max));
|
||||||
public static void CopyGlobal(this Transform p_source, Transform p_target)
|
|
||||||
{
|
|
||||||
p_target.position = p_source.position;
|
|
||||||
p_target.rotation = p_source.rotation;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<PackageId>PlayerRagdollMod</PackageId>
|
<PackageId>PlayerRagdollMod</PackageId>
|
||||||
<Version>1.2.4</Version>
|
<Version>1.2.3</Version>
|
||||||
<Authors>SDraw</Authors>
|
<Authors>SDraw</Authors>
|
||||||
<Company>SDraw</Company>
|
<Company>SDraw</Company>
|
||||||
<Product>PlayerRagdollMod</Product>
|
<Product>PlayerRagdollMod</Product>
|
||||||
|
|
|
@ -60,31 +60,31 @@ namespace ml_vei
|
||||||
{
|
{
|
||||||
while(ViewManager.Instance == null)
|
while(ViewManager.Instance == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView == null)
|
while(ViewManager.Instance.gameMenuView == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView.Listener == null)
|
while(ViewManager.Instance.gameMenuView.Listener == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () =>
|
ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action<string, string>(OnDropdownUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnDropdownUpdate_" + ms_category.Identifier, new Action<string, string>(OnDropdownUpdate));
|
||||||
};
|
};
|
||||||
ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) =>
|
ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
||||||
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static System.Collections.IEnumerator UpdateMenuSettings()
|
static System.Collections.IEnumerator UpdateMenuSettings()
|
||||||
{
|
{
|
||||||
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown)
|
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
foreach(var l_entry in ms_entries)
|
foreach(var l_entry in ms_entries)
|
||||||
ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnToggleUpdate(string p_name, string p_value)
|
static void OnToggleUpdate(string p_name, string p_value)
|
||||||
|
|
|
@ -174,12 +174,9 @@ namespace ml_vet
|
||||||
if(p_controller.IsLocal && IsReadyForUpdate())
|
if(p_controller.IsLocal && IsReadyForUpdate())
|
||||||
{
|
{
|
||||||
p_controller.manualBlinking = true;
|
p_controller.manualBlinking = true;
|
||||||
#if NIGHTLY_BUILD
|
|
||||||
p_controller.blinkProgressLeft = 1f - m_openness.x;
|
p_controller.blinkProgressLeft = 1f - m_openness.x;
|
||||||
p_controller.blinkProgressRight = 1f - m_openness.y;
|
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;
|
p_controller.manualViewTarget = true;
|
||||||
|
|
||||||
Vector3 l_gazePoint = m_gazePoint;
|
Vector3 l_gazePoint = m_gazePoint;
|
||||||
|
|
|
@ -54,31 +54,31 @@ namespace ml_vet
|
||||||
{
|
{
|
||||||
while(ViewManager.Instance == null)
|
while(ViewManager.Instance == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView == null)
|
while(ViewManager.Instance.gameMenuView == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
while(ViewManager.Instance.cohtmlView.Listener == null)
|
while(ViewManager.Instance.gameMenuView.Listener == null)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () =>
|
ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnToggleUpdate_" + ms_category.Identifier, new Action<string, string>(OnToggleUpdate));
|
||||||
ViewManager.Instance.cohtmlView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
ViewManager.Instance.gameMenuView.View.BindCall("OnSliderUpdate_" + ms_category.Identifier, new Action<string, string>(OnSliderUpdate));
|
||||||
};
|
};
|
||||||
ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) =>
|
ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) =>
|
||||||
{
|
{
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mods_extension.js"));
|
||||||
ViewManager.Instance.cohtmlView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
ViewManager.Instance.gameMenuView.View.ExecuteScript(ResourcesHandler.GetEmbeddedResource("mod_menu.js"));
|
||||||
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
MelonLoader.MelonCoroutines.Start(UpdateMenuSettings());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static System.Collections.IEnumerator UpdateMenuSettings()
|
static System.Collections.IEnumerator UpdateMenuSettings()
|
||||||
{
|
{
|
||||||
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsViewShown)
|
while(!ViewManager.Instance.IsReady || !ViewManager.Instance.IsMainMenuOpen)
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
foreach(var l_entry in ms_entries)
|
foreach(var l_entry in ms_entries)
|
||||||
ViewManager.Instance.cohtmlView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSetting", ms_category.Identifier, l_entry.DisplayName, l_entry.GetValueAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void OnToggleUpdate(string p_name, string p_value)
|
static void OnToggleUpdate(string p_name, string p_value)
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DefineConstants>TRACE;NIGHTLY_BUILD</DefineConstants>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[assembly: MelonLoader.MelonInfo(typeof(ml_vpc.VideoPlayerCookies), "VideoPlayerCookies", "1.0.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
[assembly: MelonLoader.MelonInfo(typeof(ml_vpc.VideoPlayerCookies), "VideoPlayerCookies", "1.0.1", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
|
||||||
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
|
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
|
||||||
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
||||||
[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
|
[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<AssemblyName>VideoPlayerCookies</AssemblyName>
|
<AssemblyName>VideoPlayerCookies</AssemblyName>
|
||||||
<Authors>SDraw</Authors>
|
<Authors>SDraw</Authors>
|
||||||
<Company>SDraw</Company>
|
<Company>SDraw</Company>
|
||||||
<Version>1.0.2</Version>
|
<Version>1.0.1</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue