-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
609 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
Merged set of MelonLoader mods for ChilloutVR. | ||
|
||
**State table for game build 2022r166:** | ||
**State table for game build 2022r166p1:** | ||
| Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes | | ||
|-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------| | ||
| Avatar Change Info | ml_aci | 1.0.1 | Pending approval | Working | | ||
| Avatar Motion Tweaker | ml_amt | 1.0.0 | Pending approval | Working | | ||
| Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | | ||
| Four Point Tracking | ml_fpt | 1.0.1 | Pending approval | Working | | ||
| Leap Motion Extension | ml_lme | 1.1.2 | Pending approval | Working | | ||
| Leap Motion Extension | ml_lme | 1.1.3 | Pending approval | Working | |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using ABI_RC.Core.Player; | ||
|
||
namespace ml_amt | ||
{ | ||
public class AvatarMotionTweaker : MelonLoader.MelonMod | ||
{ | ||
static AvatarMotionTweaker ms_instance = null; | ||
|
||
MotionTweaker m_localTweaker = null; | ||
|
||
public override void OnApplicationStart() | ||
{ | ||
ms_instance = this; | ||
|
||
Settings.Init(); | ||
Settings.CrouchLimitChange += this.OnCrouchLimitChange; | ||
|
||
HarmonyInstance.Patch( | ||
typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)), | ||
null, | ||
new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnAvatarClear_Postfix), System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)) | ||
); | ||
|
||
HarmonyInstance.Patch( | ||
typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)), | ||
null, | ||
new HarmonyLib.HarmonyMethod(typeof(AvatarMotionTweaker).GetMethod(nameof(OnLocalAvatarSetup_Postfix), System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)) | ||
); | ||
|
||
MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); | ||
} | ||
|
||
System.Collections.IEnumerator WaitForLocalPlayer() | ||
{ | ||
while(PlayerSetup.Instance == null) | ||
yield return null; | ||
|
||
m_localTweaker = PlayerSetup.Instance.gameObject.AddComponent<MotionTweaker>(); | ||
} | ||
|
||
void OnCrouchLimitChange(float p_value) | ||
{ | ||
if(m_localTweaker != null) | ||
m_localTweaker.SetCrouchLimit(p_value); | ||
} | ||
|
||
static void OnLocalAvatarSetup_Postfix() => ms_instance?.OnLocalAvatarSetup(); | ||
void OnLocalAvatarSetup() | ||
{ | ||
if((m_localTweaker != null) && !PlayerSetup.Instance._inVr) | ||
m_localTweaker.OnAvatarSetup(); | ||
} | ||
|
||
static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear(); | ||
void OnAvatarClear() | ||
{ | ||
if(m_localTweaker != null) | ||
m_localTweaker.OnAvatarClear(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
using ABI_RC.Core.Player; | ||
using System.Collections.Generic; | ||
using UnityEngine; | ||
|
||
namespace ml_amt | ||
{ | ||
class MotionTweaker : MonoBehaviour | ||
{ | ||
enum ParameterType | ||
{ | ||
Upright | ||
} | ||
enum ParameterSyncType | ||
{ | ||
Local, | ||
Synced | ||
} | ||
|
||
struct AdditionalParameterInfo | ||
{ | ||
public ParameterType m_type; | ||
public ParameterSyncType m_sync; | ||
public string m_name; | ||
public int m_hash; // For local only | ||
} | ||
|
||
static readonly Vector4 ms_pointVector = new Vector4(0f, 0f, 0f, 1f); | ||
|
||
RootMotion.FinalIK.VRIK m_vrIk = null; | ||
|
||
bool m_standing = true; | ||
float m_currentUpright = 1f; | ||
float m_locomotionWeight = 1f; | ||
float m_crouchLimit = 0.65f; | ||
bool m_customCrouchLimit = false; | ||
|
||
readonly List<AdditionalParameterInfo> m_parameters = null; | ||
|
||
public MotionTweaker() | ||
{ | ||
m_parameters = new List<AdditionalParameterInfo>(); | ||
} | ||
|
||
void Start() | ||
{ | ||
if(PlayerSetup.Instance._inVr) | ||
PlayerSetup.Instance.avatarSetupCompleted.AddListener(this.OnAvatarSetup); | ||
} | ||
|
||
void Update() | ||
{ | ||
// Update upright | ||
Matrix4x4 l_hmdMatrix = PlayerSetup.Instance.transform.GetMatrix().inverse * (PlayerSetup.Instance._inVr ? PlayerSetup.Instance.vrHeadTracker.transform.GetMatrix() : PlayerSetup.Instance.desktopCameraRig.transform.GetMatrix()); | ||
float l_currentHeight = Mathf.Clamp((l_hmdMatrix * ms_pointVector).y, 0f, float.MaxValue); | ||
float l_avatarViewHeight = Mathf.Clamp(PlayerSetup.Instance.GetViewPointHeight() * PlayerSetup.Instance._avatar.transform.localScale.y, 0f, float.MaxValue); | ||
m_currentUpright = Mathf.Clamp((((l_currentHeight > 0f) && (l_avatarViewHeight > 0f)) ? (l_currentHeight / l_avatarViewHeight) : 0f), 0f, 1f); | ||
m_standing = (m_currentUpright > m_crouchLimit); | ||
|
||
if((m_vrIk != null) && m_vrIk.enabled && !PlayerSetup.Instance._movementSystem.sitting && (PlayerSetup.Instance._movementSystem.movementVector.magnitude <= Mathf.Epsilon) && !PlayerSetup.Instance.fullBodyActive) | ||
{ | ||
m_locomotionWeight = Mathf.Lerp(m_locomotionWeight, m_standing ? 1f : 0f, 0.5f); | ||
m_vrIk.solver.locomotion.weight = m_locomotionWeight; | ||
} | ||
|
||
if(m_parameters.Count > 0) | ||
{ | ||
foreach(AdditionalParameterInfo l_param in m_parameters) | ||
{ | ||
switch(l_param.m_type) | ||
{ | ||
case ParameterType.Upright: | ||
{ | ||
switch(l_param.m_sync) | ||
{ | ||
case ParameterSyncType.Local: | ||
PlayerSetup.Instance._animator.SetFloat(l_param.m_hash, m_currentUpright); | ||
break; | ||
case ParameterSyncType.Synced: | ||
PlayerSetup.Instance.changeAnimatorParam(l_param.m_name, m_currentUpright); | ||
break; | ||
} | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
public void OnAvatarClear() | ||
{ | ||
m_vrIk = null; | ||
m_standing = true; | ||
m_parameters.Clear(); | ||
m_locomotionWeight = 1f; | ||
m_crouchLimit = 0.65f; | ||
m_customCrouchLimit = false; | ||
} | ||
|
||
public void OnAvatarSetup() | ||
{ | ||
m_vrIk = PlayerSetup.Instance._avatar.GetComponent<RootMotion.FinalIK.VRIK>(); | ||
|
||
// Parse animator parameters | ||
AnimatorControllerParameter[] l_params = PlayerSetup.Instance._animator.parameters; | ||
ParameterType[] l_enumParams = (ParameterType[])System.Enum.GetValues(typeof(ParameterType)); | ||
|
||
foreach(var l_param in l_params) | ||
{ | ||
foreach(var l_enumParam in l_enumParams) | ||
{ | ||
if(l_param.name.Contains(l_enumParam.ToString()) && (m_parameters.FindIndex(p => p.m_type == l_enumParam) == -1)) | ||
{ | ||
bool l_local = (l_param.name[0] == '#'); | ||
|
||
m_parameters.Add(new AdditionalParameterInfo | ||
{ | ||
m_type = l_enumParam, | ||
m_sync = (l_local ? ParameterSyncType.Local : ParameterSyncType.Synced), | ||
m_name = l_param.name, | ||
m_hash = (l_local ? l_param.nameHash : 0) | ||
}); | ||
|
||
break; | ||
} | ||
} | ||
} | ||
|
||
Transform l_customLimit = PlayerSetup.Instance._avatar.transform.Find("CrouchLimit"); | ||
m_customCrouchLimit = (l_customLimit != null); | ||
m_crouchLimit = m_customCrouchLimit ? Mathf.Clamp(l_customLimit.localPosition.y, 0f, 1f) : Settings.CrouchLimit; | ||
} | ||
|
||
public void SetCrouchLimit(float p_value) | ||
{ | ||
if(!m_customCrouchLimit) | ||
m_crouchLimit = Mathf.Clamp(p_value, 0f, 1f); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System.Reflection; | ||
|
||
[assembly: AssemblyTitle("AvatarMotionTweaker")] | ||
[assembly: AssemblyVersion("1.0.0")] | ||
[assembly: AssemblyFileVersion("1.0.0")] | ||
|
||
[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "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)] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Avatar Motion Tweaker | ||
This mod adds `Upright` parameter for usage in AAS animator and allows disabling legs autostep upon reaching specific `Upright` value. | ||
|
||
![](.github/img_01.png) | ||
|
||
# Installation | ||
* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader) | ||
* Get [latest release DLL](../../../releases/latest): | ||
* Put `ml_amt.dll` in `Mods` folder of game | ||
|
||
# Usage | ||
Available mod's settings in `Settings - Implementation - Avatar Motion Tweaker`: | ||
* **Legs locomotion upright limit:** defines upright limit of legs autostep. If HMD tracking goes below set limit, legs autostep is disabled. Default value - 65. | ||
* Limit can be overrided by avatar. For this avatar has to have child gameobject with name `CrouchLimit` and its Y-axis location will be used as limit, should be in range [0.0, 1.0]. | ||
|
||
Available additional parameters for AAS animator: | ||
* **`Upright`:** defines linear coefficient between current viewpoint height and avatar's viewpoint height. Range - [0.0,1.0] (0.0 - floor, 1.0 - full standing). | ||
* Note: can be set as local-only (not synced) if starts with `#` character. | ||
|
||
## Example of usage in AAS animator for mixed desktop and VR | ||
* To differentiate between desktop and VR players use `CVR Parameter Stream` component on avatar's root gameobject. As example, `InVR` and `InFBT` are boolean typed animator parameters: | ||
![](.github/img_02.png) | ||
* Add additional transitions between standing, crouching and proning blend trees: | ||
![](.github/img_03.png) | ||
* Add conditions for new VR transitions: | ||
* Standing -> Crouching: | ||
![](.github/img_04.png) | ||
* Crouching -> Standing: | ||
![](.github/img_05.png) | ||
* Crouching -> Proning: | ||
![](.github/img_06.png) | ||
* Proning -> Crouching: | ||
![](.github/img_07.png) | ||
* Add condition check for all desktop transitions: | ||
![](.github/img_08.png) | ||
|
||
# Notes | ||
* Sometimes after restoring legs autostep avatar's torso shakes, currently investigating solution. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using System; | ||
using System.IO; | ||
using System.Reflection; | ||
|
||
namespace ml_amt | ||
{ | ||
static class Scripts | ||
{ | ||
public static string GetEmbeddedScript(string p_name) | ||
{ | ||
string l_result = ""; | ||
Assembly l_assembly = Assembly.GetExecutingAssembly(); | ||
string l_assemblyName = l_assembly.GetName().Name; | ||
|
||
try | ||
{ | ||
Stream l_libraryStream = l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + p_name); | ||
StreamReader l_streadReader = new StreamReader(l_libraryStream); | ||
l_result = l_streadReader.ReadToEnd(); | ||
} | ||
catch(Exception) { } | ||
|
||
return l_result; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
using ABI_RC.Core.InteractionSystem; | ||
using cohtml; | ||
using System; | ||
using System.Collections.Generic; | ||
using UnityEngine; | ||
|
||
namespace ml_amt | ||
{ | ||
static class Settings | ||
{ | ||
enum ModSetting | ||
{ | ||
CrouchLimit = 0 | ||
}; | ||
|
||
static float ms_crouchLimit = 0.65f; | ||
|
||
static MelonLoader.MelonPreferences_Category ms_category = null; | ||
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null; | ||
|
||
static public event Action<float> CrouchLimitChange; | ||
|
||
public static void Init() | ||
{ | ||
ms_category = MelonLoader.MelonPreferences.CreateCategory("AMT"); | ||
|
||
ms_entries = new List<MelonLoader.MelonPreferences_Entry>(); | ||
ms_entries.Add(ms_category.CreateEntry(ModSetting.CrouchLimit.ToString(), 65)); | ||
|
||
Load(); | ||
|
||
MelonLoader.MelonCoroutines.Start(WaitMainMenuUi()); | ||
} | ||
|
||
static System.Collections.IEnumerator WaitMainMenuUi() | ||
{ | ||
while(ViewManager.Instance == null) | ||
yield return null; | ||
while(ViewManager.Instance.gameMenuView == null) | ||
yield return null; | ||
while(ViewManager.Instance.gameMenuView.Listener == null) | ||
yield return null; | ||
|
||
ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () => | ||
{ | ||
ViewManager.Instance.gameMenuView.View.BindCall("MelonMod_AMT_Call_InpSlider", new Action<string, string>(OnSliderUpdate)); | ||
}; | ||
ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) => | ||
{ | ||
ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("menu.js")); | ||
foreach(var l_entry in ms_entries) | ||
ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSettingAMT", l_entry.DisplayName, l_entry.GetValueAsString()); | ||
}; | ||
} | ||
|
||
static void Load() | ||
{ | ||
ms_crouchLimit = ((int)ms_entries[(int)ModSetting.CrouchLimit].BoxedValue) * 0.01f; | ||
} | ||
|
||
static void OnSliderUpdate(string p_name, string p_value) | ||
{ | ||
if(Enum.TryParse(p_name, out ModSetting l_setting)) | ||
{ | ||
switch(l_setting) | ||
{ | ||
case ModSetting.CrouchLimit: | ||
{ | ||
ms_crouchLimit = ((int)ms_entries[(int)ModSetting.CrouchLimit].BoxedValue) * 0.01f; | ||
CrouchLimitChange?.Invoke(ms_crouchLimit); | ||
} break; | ||
} | ||
|
||
ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value); | ||
} | ||
} | ||
|
||
public static float CrouchLimit | ||
{ | ||
get => ms_crouchLimit; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using UnityEngine; | ||
|
||
namespace ml_amt | ||
{ | ||
static class Utils | ||
{ | ||
// Extensions | ||
public static Matrix4x4 GetMatrix(this Transform p_transform, bool p_pos = true, bool p_rot = true, bool p_scl = false) | ||
{ | ||
return Matrix4x4.TRS(p_pos ? p_transform.position : Vector3.zero, p_rot ? p_transform.rotation : Quaternion.identity, p_scl ? p_transform.localScale : Vector3.one); | ||
} | ||
} | ||
} |
Oops, something went wrong.