Dedicated BTKUILib page

Internal settings and UI rework
Upcoming mod support
This commit is contained in:
SDraw 2023-04-29 03:18:45 +03:00
parent 0440baa84f
commit 6d13ff1894
No known key found for this signature in database
GPG key ID: BB95B4DAB2BB8BB5
12 changed files with 269 additions and 154 deletions

View file

@ -4,12 +4,12 @@ Merged set of MelonLoader mods for ChilloutVR.
| Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes | | Full name | Short name | Latest version | Available in [CVRMA](https://github.com/knah/CVRMelonAssistant) | Current Status | Notes |
|-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------| |-----------|------------|----------------|-----------------------------------------------------------------|----------------|-------|
| Avatar Change Info | ml_aci | 1.0.3 | Retired | Retired | Superseded by `Extended Game Notifications` | Avatar Change Info | ml_aci | 1.0.3 | Retired | Retired | Superseded by `Extended Game Notifications`
| Avatar Motion Tweaker | ml_amt | 1.2.6 | Yes | Working | | Avatar Motion Tweaker | ml_amt | 1.2.7 | Yes, update review | Working |
| Desktop Head Tracking | ml_dht | 1.1.3 | Yes | Working | | Desktop Head Tracking | ml_dht | 1.1.3 | Yes | Working |
| Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working | | Desktop Reticle Switch | ml_drs | 1.0.0 | Yes | Working |
| Extended Game Notifications | ml_egn | 1.0.2 | Yes | Working | Extended Game Notifications | ml_egn | 1.0.2 | Yes | Working
| Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update | Four Point Tracking | ml_fpt | 1.0.9 | Retired | Deprecated | In-game feature since 2022r170 update
| Leap Motion Extension | ml_lme | 1.3.4 | Yes | Working | | Leap Motion Extension | ml_lme | 1.3.4 | Yes | Working |
| Pickup Arm Movement | ml_pam | 1.0.3 | Yes | Working | | Pickup Arm Movement | ml_pam | 1.0.3 | Yes | Working |
| Player Ragdoll Mod | ml_prm | 1.0.1 | Yes | Working | | Player Ragdoll Mod | ml_prm | 1.0.2 | Yes, update review | Working |
| Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications` | Server Connection Info | ml_sci | 1.0.2 | Retired | Retired | Superseded by `Extended Game Notifications`

View file

@ -6,11 +6,14 @@ namespace ml_amt
static class ModSupporter static class ModSupporter
{ {
static bool ms_ragdollMod = false; static bool ms_ragdollMod = false;
static bool ms_copycatMod = false;
public static void Init() public static void Init()
{ {
if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "PlayerRagdollMod") != null) if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "PlayerRagdollMod") != null)
MelonLoader.MelonCoroutines.Start(WaitForRagdollInstance()); MelonLoader.MelonCoroutines.Start(WaitForRagdollInstance());
if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "PlayerMovementCopycat") != null)
MelonLoader.MelonCoroutines.Start(WaitForCopycatInstance());
} }
// PlayerRagdollMod support // PlayerRagdollMod support
@ -22,11 +25,25 @@ namespace ml_amt
ms_ragdollMod = true; ms_ragdollMod = true;
} }
static bool IsRagdolled() => ml_prm.RagdollController.Instance.IsRagdolled(); static bool IsRagdolled() => ml_prm.RagdollController.Instance.IsRagdolled();
// PlayerMovementCopycat support
static IEnumerator WaitForCopycatInstance()
{
while(ml_pmc.PoseCopycat.Instance == null)
yield return null;
ms_copycatMod = true;
}
static bool IsCopycating() => ml_pmc.PoseCopycat.Instance.IsActive();
public static bool SkipHipsOverride() public static bool SkipHipsOverride()
{ {
bool l_result = false; bool l_result = false;
l_result |= (ms_ragdollMod && IsRagdolled()); l_result |= (ms_ragdollMod && IsRagdolled());
l_result |= (ms_copycatMod && IsCopycating());
return l_result; return l_result;
} }
} }
} }

View file

@ -1,11 +1,11 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyTitle("AvatarMotionTweaker")] [assembly: AssemblyTitle("AvatarMotionTweaker")]
[assembly: AssemblyVersion("1.2.6")] [assembly: AssemblyVersion("1.2.7")]
[assembly: AssemblyFileVersion("1.2.6")] [assembly: AssemblyFileVersion("1.2.7")]
[assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.2.6", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonInfo(typeof(ml_amt.AvatarMotionTweaker), "AvatarMotionTweaker", "1.2.7", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
[assembly: MelonLoader.MelonOptionalDependencies("ml_prm")] [assembly: MelonLoader.MelonOptionalDependencies("ml_prm", "ml_pmc")]
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] [assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)] [assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]

View file

@ -54,6 +54,10 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="ml_pmc">
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\Mods\ml_pmc.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ml_prm"> <Reference Include="ml_prm">
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\Mods\ml_prm.dll</HintPath> <HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\Mods\ml_prm.dll</HintPath>
<Private>False</Private> <Private>False</Private>

View file

@ -24,6 +24,7 @@ namespace ml_prm
ms_instance = this; ms_instance = this;
Settings.Init(); Settings.Init();
ModUi.Init();
HarmonyInstance.Patch( HarmonyInstance.Patch(
typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)), typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)),
@ -81,6 +82,13 @@ namespace ml_prm
yield return null; yield return null;
m_localController = PlayerSetup.Instance.gameObject.AddComponent<RagdollController>(); m_localController = PlayerSetup.Instance.gameObject.AddComponent<RagdollController>();
ModUi.SwitchChange += this.OnSwitchActivation;
}
void OnSwitchActivation()
{
if(m_localController != null)
m_localController.SwitchRagdoll();
} }
// Patches // Patches

189
ml_prm/ModUi.cs Normal file
View file

@ -0,0 +1,189 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace ml_prm
{
static class ModUi
{
enum UiIndex
{
Hotkey = 0,
Gravity,
PointersReaction,
IgnoreLocal,
CombatReaction,
AutoRecover,
Slipperiness,
Bounciness,
ViewVelocity,
VelocityMultiplier,
MovementDrag,
AngularDrag,
RecoverDelay
}
static public event Action SwitchChange;
static List<object> ms_uiElements = null;
internal static void Init()
{
ms_uiElements = new List<object>();
if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null)
CreateUi();
}
// Separated method, otherwise exception is thrown, funny CSharp and optional references, smh
static void CreateUi()
{
BTKUILib.QuickMenuAPI.PrepareIcon("PlayerRagdollMod", "PRM-Person", GetIconStream("person.png"));
var l_modRoot = new BTKUILib.UIObjects.Page("PlayerRagdollMod", "MainPage", true, "PRM-Person");
l_modRoot.MenuTitle = "Player Ragdoll Mod";
l_modRoot.MenuSubtitle = "Become a ragdoll and change various settings for people amusement";
var l_modCategory = l_modRoot.AddCategory("Settings");
l_modCategory.AddButton("Switch ragdoll", "PRM-Person", "Switch between normal and ragdoll state").OnPress += () => SwitchChange?.Invoke();
ms_uiElements.Add(l_modCategory.AddToggle("Use hotkey", "Switch ragdoll mode with 'R' key", Settings.Hotkey));
(ms_uiElements[(int)UiIndex.Hotkey] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Hotkey, state);
ms_uiElements.Add(l_modCategory.AddToggle("Use gravity", "Apply gravity to ragdoll", Settings.Gravity));
(ms_uiElements[(int)UiIndex.Gravity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Gravity, state);
ms_uiElements.Add(l_modCategory.AddToggle("Pointers reaction", "React to trigger colliders with CVRPointer component of 'ragdoll' type", Settings.PointersReaction));
(ms_uiElements[(int)UiIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.PointersReaction, state);
ms_uiElements.Add(l_modCategory.AddToggle("Ignore local pointers", "Ignore local avatar's CVRPointer components of 'ragdoll' type", Settings.IgnoreLocal));
(ms_uiElements[(int)UiIndex.IgnoreLocal] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.IgnoreLocal, state);
ms_uiElements.Add(l_modCategory.AddToggle("Combat reaction", "Ragdoll upon combat system death", Settings.CombatReaction));
(ms_uiElements[(int)UiIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.CombatReaction, state);
ms_uiElements.Add(l_modCategory.AddToggle("Auto recover", "Automatically unragdoll after set recover delay", Settings.AutoRecover));
(ms_uiElements[(int)UiIndex.AutoRecover] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.AutoRecover, state);
ms_uiElements.Add(l_modCategory.AddToggle("Slipperiness", "Enables/disables friction of ragdoll", Settings.Slipperiness));
(ms_uiElements[(int)UiIndex.Slipperiness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Slipperiness, state);
ms_uiElements.Add(l_modCategory.AddToggle("Bounciness", "Enables/disables bounciness of ragdoll", Settings.Bounciness));
(ms_uiElements[(int)UiIndex.Bounciness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Bounciness, state);
ms_uiElements.Add(l_modCategory.AddToggle("View direction velocity", "Apply velocity to camera view direction", Settings.ViewVelocity));
(ms_uiElements[(int)UiIndex.ViewVelocity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(UiIndex.ViewVelocity, state);
ms_uiElements.Add(l_modRoot.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", Settings.VelocityMultiplier, 1f, 50f));
(ms_uiElements[(int)UiIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.VelocityMultiplier, value);
ms_uiElements.Add(l_modRoot.AddSlider("Movement drag", "Movement resistance", Settings.MovementDrag, 0f, 50f));
(ms_uiElements[(int)UiIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.MovementDrag, value);
ms_uiElements.Add(l_modRoot.AddSlider("Angular movement drag", "Rotation movement resistance", Settings.AngularDrag, 0f, 50f));
(ms_uiElements[(int)UiIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.AngularDrag, value);
ms_uiElements.Add(l_modRoot.AddSlider("Recover delay (seconds)", "Recover delay for automatic recover", Settings.RecoverDelay, 1f, 10f));
(ms_uiElements[(int)UiIndex.RecoverDelay] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(UiIndex.RecoverDelay, value);
l_modCategory.AddButton("Reset settings", "", "Reset mod settings to default").OnPress += Reset;
}
static void OnToggleUpdate(UiIndex p_index, bool p_state, bool p_force = false)
{
switch(p_index)
{
case UiIndex.Hotkey:
Settings.SetSetting(Settings.ModSetting.Hotkey, p_state);
break;
case UiIndex.Gravity:
Settings.SetSetting(Settings.ModSetting.Gravity, p_state);
break;
case UiIndex.PointersReaction:
Settings.SetSetting(Settings.ModSetting.PointersReaction, p_state);
break;
case UiIndex.IgnoreLocal:
Settings.SetSetting(Settings.ModSetting.IgnoreLocal, p_state);
break;
case UiIndex.CombatReaction:
Settings.SetSetting(Settings.ModSetting.CombatReaction, p_state);
break;
case UiIndex.AutoRecover:
Settings.SetSetting(Settings.ModSetting.AutoRecover, p_state);
break;
case UiIndex.Slipperiness:
Settings.SetSetting(Settings.ModSetting.Slipperiness, p_state);
break;
case UiIndex.Bounciness:
Settings.SetSetting(Settings.ModSetting.Bounciness, p_state);
break;
case UiIndex.ViewVelocity:
Settings.SetSetting(Settings.ModSetting.ViewVelocity, p_state);
break;
}
if(p_force)
(ms_uiElements[(int)p_index] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = p_state;
}
static void OnSliderUpdate(UiIndex p_index, float p_value, bool p_force = false)
{
switch(p_index)
{
case UiIndex.VelocityMultiplier:
Settings.SetSetting(Settings.ModSetting.VelocityMultiplier, p_value);
break;
case UiIndex.MovementDrag:
Settings.SetSetting(Settings.ModSetting.MovementDrag, p_value);
break;
case UiIndex.AngularDrag:
Settings.SetSetting(Settings.ModSetting.AngularDrag, p_value);
break;
case UiIndex.RecoverDelay:
Settings.SetSetting(Settings.ModSetting.RecoverDelay, p_value);
break;
}
if(p_force)
(ms_uiElements[(int)p_index] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(p_value);
}
static void Reset()
{
OnToggleUpdate(UiIndex.Hotkey, true, true);
OnToggleUpdate(UiIndex.Gravity, true, true);
OnToggleUpdate(UiIndex.PointersReaction, true, true);
OnToggleUpdate(UiIndex.IgnoreLocal, true, true);
OnToggleUpdate(UiIndex.CombatReaction, true, true);
OnToggleUpdate(UiIndex.AutoRecover, false, true);
OnToggleUpdate(UiIndex.Slipperiness, false, true);
OnToggleUpdate(UiIndex.Bounciness, false, true);
OnToggleUpdate(UiIndex.ViewVelocity, false, true);
OnSliderUpdate(UiIndex.VelocityMultiplier, 2f, true);
OnSliderUpdate(UiIndex.MovementDrag, 2f, true);
OnSliderUpdate(UiIndex.AngularDrag, 2f, true);
OnSliderUpdate(UiIndex.RecoverDelay, 3f, true);
}
static Stream GetIconStream(string p_name)
{
Assembly l_assembly = Assembly.GetExecutingAssembly();
string l_assemblyName = l_assembly.GetName().Name;
return l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + p_name);
}
}
}

View file

@ -1,10 +1,10 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyTitle("PlayerRagdollMod")] [assembly: AssemblyTitle("PlayerRagdollMod")]
[assembly: AssemblyVersion("1.0.1")] [assembly: AssemblyVersion("1.0.2")]
[assembly: AssemblyFileVersion("1.0.1")] [assembly: AssemblyFileVersion("1.0.2")]
[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.0.1", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.0.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
[assembly: MelonLoader.MelonPriority(2)] [assembly: MelonLoader.MelonPriority(2)]
[assembly: MelonLoader.MelonOptionalDependencies("BTKUILib")] [assembly: MelonLoader.MelonOptionalDependencies("BTKUILib")]

View file

@ -9,7 +9,7 @@ This mod turns player's avatar into ragdoll puppet.
# Usage # Usage
* Press `R` to turn into ragdoll and back. * Press `R` to turn into ragdoll and back.
Optional mod's settings with [BTKUILib](https://github.com/BTK-Development/BTKUILib): Optional mod's settings page with [BTKUILib](https://github.com/BTK-Development/BTKUILib):
* **Switch ragdoll:** turns into ragdoll state and back, made for VR usage primarily. * **Switch ragdoll:** turns into ragdoll state and back, made for VR usage primarily.
* **Use hotkey:** enables/disables ragdoll state switch with `R` key; `true` by default. * **Use hotkey:** enables/disables ragdoll state switch with `R` key; `true` by default.
* **Use gravity:** enables/disables gravity for ragdoll; `true` by default. * **Use gravity:** enables/disables gravity for ragdoll; `true` by default.

View file

@ -76,7 +76,6 @@ namespace ml_prm
m_customTrigger = MovementSystem.Instance.proxyCollider.gameObject.AddComponent<RagdollTrigger>(); m_customTrigger = MovementSystem.Instance.proxyCollider.gameObject.AddComponent<RagdollTrigger>();
Settings.SwitchChange += this.SwitchRagdoll;
Settings.MovementDragChange += this.OnMovementDragChange; Settings.MovementDragChange += this.OnMovementDragChange;
Settings.AngularDragChange += this.OnAngularDragChange; Settings.AngularDragChange += this.OnAngularDragChange;
Settings.GravityChange += this.OnGravityChange; Settings.GravityChange += this.OnGravityChange;
@ -92,7 +91,6 @@ namespace ml_prm
m_customTrigger = null; m_customTrigger = null;
} }
Settings.SwitchChange -= this.SwitchRagdoll;
Settings.MovementDragChange -= this.OnMovementDragChange; Settings.MovementDragChange -= this.OnMovementDragChange;
Settings.AngularDragChange -= this.OnAngularDragChange; Settings.AngularDragChange -= this.OnAngularDragChange;
Settings.GravityChange -= this.OnGravityChange; Settings.GravityChange -= this.OnGravityChange;
@ -224,10 +222,6 @@ namespace ml_prm
l_options.joints = RagdollCreator.JointType.Character; l_options.joints = RagdollCreator.JointType.Character;
BipedRagdollCreator.Create(m_puppetReferences, l_options); BipedRagdollCreator.Create(m_puppetReferences, l_options);
// And return back
m_puppetRoot.localPosition = Vector3.zero;
m_puppetRoot.localRotation = Quaternion.identity;
Transform[] l_puppetTransforms = m_puppetReferences.GetRagdollTransforms(); Transform[] l_puppetTransforms = m_puppetReferences.GetRagdollTransforms();
Transform[] l_avatarTransforms = l_avatarReferences.GetRagdollTransforms(); Transform[] l_avatarTransforms = l_avatarReferences.GetRagdollTransforms();
for(int i = 0; i < l_puppetTransforms.Length; i++) for(int i = 0; i < l_puppetTransforms.Length; i++)
@ -269,6 +263,10 @@ namespace ml_prm
} }
} }
// And return back
m_puppetRoot.localPosition = Vector3.zero;
m_puppetRoot.localRotation = Quaternion.identity;
m_vrIK = PlayerSetup.Instance._avatar.GetComponent<VRIK>(); m_vrIK = PlayerSetup.Instance._avatar.GetComponent<VRIK>();
if(m_vrIK != null) if(m_vrIK != null)
{ {

View file

@ -7,7 +7,7 @@ namespace ml_prm
{ {
static class Settings static class Settings
{ {
enum ModSetting public enum ModSetting
{ {
Hotkey = 0, Hotkey = 0,
VelocityMultiplier, VelocityMultiplier,
@ -24,25 +24,6 @@ namespace ml_prm
ViewVelocity ViewVelocity
} }
enum UiElementIndex
{
Hotkey = 0,
Gravity,
PointersReaction,
IgnoreLocal,
CombatReaction,
AutoRecover,
Slipperiness,
Bounciness,
ViewVelocity,
VelocityMultiplier,
MovementDrag,
AngularDrag,
RecoverDelay,
Count
}
public static bool Hotkey { get; private set; } = true; public static bool Hotkey { get; private set; } = true;
public static float VelocityMultiplier { get; private set; } = 2f; public static float VelocityMultiplier { get; private set; } = 2f;
public static float MovementDrag { get; private set; } = 2f; public static float MovementDrag { get; private set; } = 2f;
@ -57,7 +38,6 @@ namespace ml_prm
public static bool Bounciness { get; private set; } = false; public static bool Bounciness { get; private set; } = false;
public static bool ViewVelocity { get; private set; } = false; public static bool ViewVelocity { get; private set; } = false;
static public event Action SwitchChange;
static public event Action<bool> HotkeyChange; static public event Action<bool> HotkeyChange;
static public event Action<float> VelocityMultiplierChange; static public event Action<float> VelocityMultiplierChange;
static public event Action<float> MovementDragChange; static public event Action<float> MovementDragChange;
@ -75,8 +55,6 @@ namespace ml_prm
static MelonLoader.MelonPreferences_Category ms_category = null; static MelonLoader.MelonPreferences_Category ms_category = null;
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null; static List<MelonLoader.MelonPreferences_Entry> ms_entries = null;
static List<object> ms_uiElements = new List<object>();
internal static void Init() internal static void Init()
{ {
ms_category = MelonLoader.MelonPreferences.CreateCategory("PRM", null, true); ms_category = MelonLoader.MelonPreferences.CreateCategory("PRM", null, true);
@ -110,190 +88,108 @@ namespace ml_prm
Slipperiness = (bool)ms_entries[(int)ModSetting.Slipperiness].BoxedValue; Slipperiness = (bool)ms_entries[(int)ModSetting.Slipperiness].BoxedValue;
Bounciness = (bool)ms_entries[(int)ModSetting.Bounciness].BoxedValue; Bounciness = (bool)ms_entries[(int)ModSetting.Bounciness].BoxedValue;
ViewVelocity = (bool)ms_entries[(int)ModSetting.ViewVelocity].BoxedValue; ViewVelocity = (bool)ms_entries[(int)ModSetting.ViewVelocity].BoxedValue;
if(MelonLoader.MelonMod.RegisteredMelons.FirstOrDefault(m => m.Info.Name == "BTKUILib") != null)
{
CreateBtkUi();
}
} }
static void CreateBtkUi() public static void SetSetting(ModSetting p_settings, object p_value)
{ {
var l_categoryMain = BTKUILib.QuickMenuAPI.MiscTabPage.AddCategory("PlayerRagdollMod"); switch(p_settings)
var l_page = l_categoryMain.AddPage("Player Ragdoll Settings", "", "PlayerRagdollMod settings", "PlayerRagdollMod");
l_page.MenuTitle = "Ragdoll settings";
var l_categoryMod = l_page.AddCategory("Settings");
l_categoryMod.AddButton("Switch ragdoll", "", "Switch between normal and ragdoll state").OnPress += () => SwitchChange?.Invoke();
ms_uiElements.Add(l_categoryMod.AddToggle("Use hotkey", "Switch ragdoll mode with 'R' key", Hotkey));
(ms_uiElements[(int)UiElementIndex.Hotkey] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Hotkey, state);
ms_uiElements.Add(l_categoryMod.AddToggle("Use gravity", "Apply gravity to ragdoll", Gravity));
(ms_uiElements[(int)UiElementIndex.Gravity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Gravity, state);
ms_uiElements.Add(l_categoryMod.AddToggle("Pointers reaction", "React to trigger colliders with CVRPointer component of 'ragdoll' type", PointersReaction));
(ms_uiElements[(int)UiElementIndex.PointersReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.PointersReaction, state);
ms_uiElements.Add(l_categoryMod.AddToggle("Ignore local pointers", "Ignore local avatar's CVRPointer components of 'ragdoll' type", IgnoreLocal));
(ms_uiElements[(int)UiElementIndex.IgnoreLocal] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.IgnoreLocal, state);
ms_uiElements.Add(l_categoryMod.AddToggle("Combat reaction", "Ragdoll upon combat system death", CombatReaction));
(ms_uiElements[(int)UiElementIndex.CombatReaction] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.CombatReaction, state);
ms_uiElements.Add(l_categoryMod.AddToggle("Auto recover", "Automatically unragdoll after set recover delay", AutoRecover));
(ms_uiElements[(int)UiElementIndex.AutoRecover] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.AutoRecover, state);
ms_uiElements.Add(l_categoryMod.AddToggle("Slipperiness", "Enables/disables friction of ragdoll", Slipperiness));
(ms_uiElements[(int)UiElementIndex.Slipperiness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Slipperiness, state);
ms_uiElements.Add(l_categoryMod.AddToggle("Bounciness", "Enables/disables bounciness of ragdoll", Bounciness));
(ms_uiElements[(int)UiElementIndex.Bounciness] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.Bounciness, state);
ms_uiElements.Add(l_categoryMod.AddToggle("View direction velocity", "Apply velocity to camera view direction", ViewVelocity));
(ms_uiElements[(int)UiElementIndex.ViewVelocity] as BTKUILib.UIObjects.Components.ToggleButton).OnValueUpdated += (state) => OnToggleUpdate(ModSetting.ViewVelocity, state);
ms_uiElements.Add(l_page.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", VelocityMultiplier, 1f, 50f));
(ms_uiElements[(int)UiElementIndex.VelocityMultiplier] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(ModSetting.VelocityMultiplier, value);
ms_uiElements.Add(l_page.AddSlider("Movement drag", "Movement resistance", MovementDrag, 0f, 50f));
(ms_uiElements[(int)UiElementIndex.MovementDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(ModSetting.MovementDrag, value);
ms_uiElements.Add(l_page.AddSlider("Angular movement drag", "Rotation movement resistance", AngularDrag, 0f, 50f));
(ms_uiElements[(int)UiElementIndex.AngularDrag] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(ModSetting.AngularDrag, value);
ms_uiElements.Add(l_page.AddSlider("Recover delay (seconds)", "Recover delay for automatic recover", RecoverDelay, 1f, 10f));
(ms_uiElements[(int)UiElementIndex.RecoverDelay] as BTKUILib.UIObjects.Components.SliderFloat).OnValueUpdated += (value) => OnSliderUpdate(ModSetting.RecoverDelay, value);
l_categoryMod.AddButton("Reset settings", "", "Reset mod settings to default").OnPress += Reset;
}
static void OnToggleUpdate(ModSetting p_setting, bool p_state, UiElementIndex p_uiIndex = UiElementIndex.Count)
{
switch(p_setting)
{ {
// Booleans
case ModSetting.Hotkey: case ModSetting.Hotkey:
{ {
Hotkey = p_state; Hotkey = (bool)p_value;
HotkeyChange?.Invoke(p_state); HotkeyChange?.Invoke((bool)p_value);
} }
break; break;
case ModSetting.Gravity: case ModSetting.Gravity:
{ {
Gravity = p_state; Gravity = (bool)p_value;
GravityChange?.Invoke(p_state); GravityChange?.Invoke((bool)p_value);
} }
break; break;
case ModSetting.PointersReaction: case ModSetting.PointersReaction:
{ {
PointersReaction = p_state; PointersReaction = (bool)p_value;
PointersReactionChange?.Invoke(p_state); PointersReactionChange?.Invoke((bool)p_value);
} }
break; break;
case ModSetting.IgnoreLocal: case ModSetting.IgnoreLocal:
{ {
IgnoreLocal = p_state; IgnoreLocal = (bool)p_value;
IgnoreLocalChange?.Invoke(p_state); IgnoreLocalChange?.Invoke((bool)p_value);
} }
break; break;
case ModSetting.CombatReaction: case ModSetting.CombatReaction:
{ {
CombatReaction = p_state; CombatReaction = (bool)p_value;
CombatReactionChange?.Invoke(p_state); CombatReactionChange?.Invoke((bool)p_value);
} }
break; break;
case ModSetting.AutoRecover: case ModSetting.AutoRecover:
{ {
AutoRecover = p_state; AutoRecover = (bool)p_value;
AutoRecoverChange?.Invoke(p_state); AutoRecoverChange?.Invoke((bool)p_value);
} }
break; break;
case ModSetting.Slipperiness: case ModSetting.Slipperiness:
{ {
Slipperiness = p_state; Slipperiness = (bool)p_value;
SlipperinessChange?.Invoke(p_state); SlipperinessChange?.Invoke((bool)p_value);
} }
break; break;
case ModSetting.Bounciness: case ModSetting.Bounciness:
{ {
Bounciness = p_state; Bounciness = (bool)p_value;
BouncinessChange?.Invoke(p_state); BouncinessChange?.Invoke((bool)p_value);
} }
break; break;
case ModSetting.ViewVelocity: case ModSetting.ViewVelocity:
{ {
ViewVelocity = p_state; ViewVelocity = (bool)p_value;
ViewVelocityChange?.Invoke(p_state); ViewVelocityChange?.Invoke((bool)p_value);
} }
break; break;
}
ms_entries[(int)p_setting].BoxedValue = p_state; // Floats
if(p_uiIndex != UiElementIndex.Count)
(ms_uiElements[(int)p_uiIndex] as BTKUILib.UIObjects.Components.ToggleButton).ToggleValue = p_state;
}
static void OnSliderUpdate(ModSetting p_setting, float p_value, UiElementIndex p_uiIndex = UiElementIndex.Count)
{
switch(p_setting)
{
case ModSetting.VelocityMultiplier: case ModSetting.VelocityMultiplier:
{ {
VelocityMultiplier = p_value; VelocityMultiplier = (float)p_value;
VelocityMultiplierChange?.Invoke(p_value); VelocityMultiplierChange?.Invoke((float)p_value);
} }
break; break;
case ModSetting.MovementDrag: case ModSetting.MovementDrag:
{ {
MovementDrag = p_value; MovementDrag = (float)p_value;
MovementDragChange?.Invoke(p_value); MovementDragChange?.Invoke((float)p_value);
} }
break; break;
case ModSetting.AngularDrag: case ModSetting.AngularDrag:
{ {
AngularDrag = p_value; AngularDrag = (float)p_value;
AngularDragChange?.Invoke(p_value); AngularDragChange?.Invoke((float)p_value);
} }
break; break;
case ModSetting.RecoverDelay: case ModSetting.RecoverDelay:
{ {
RecoverDelay = p_value; RecoverDelay = (float)p_value;
RecoverDelayChange?.Invoke(p_value); RecoverDelayChange?.Invoke((float)p_value);
} }
break; break;
} }
ms_entries[(int)p_setting].BoxedValue = p_value; if(ms_entries != null)
if(p_uiIndex != UiElementIndex.Count) ms_entries[(int)p_settings].BoxedValue = p_value;
(ms_uiElements[(int)p_uiIndex] as BTKUILib.UIObjects.Components.SliderFloat).SetSliderValue(p_value);
}
static void Reset()
{
OnToggleUpdate(ModSetting.Hotkey, true, UiElementIndex.Hotkey);
OnToggleUpdate(ModSetting.Gravity, true, UiElementIndex.Gravity);
OnToggleUpdate(ModSetting.PointersReaction, true, UiElementIndex.PointersReaction);
OnToggleUpdate(ModSetting.IgnoreLocal, true, UiElementIndex.IgnoreLocal);
OnToggleUpdate(ModSetting.CombatReaction, true, UiElementIndex.CombatReaction);
OnToggleUpdate(ModSetting.AutoRecover, false, UiElementIndex.AutoRecover);
OnToggleUpdate(ModSetting.Slipperiness, false, UiElementIndex.Slipperiness);
OnToggleUpdate(ModSetting.Bounciness, false, UiElementIndex.Bounciness);
OnToggleUpdate(ModSetting.ViewVelocity, false, UiElementIndex.ViewVelocity);
OnSliderUpdate(ModSetting.VelocityMultiplier, 2f, UiElementIndex.VelocityMultiplier);
OnSliderUpdate(ModSetting.MovementDrag, 2f, UiElementIndex.MovementDrag);
OnSliderUpdate(ModSetting.AngularDrag, 2f, UiElementIndex.AngularDrag);
OnSliderUpdate(ModSetting.RecoverDelay, 3f, UiElementIndex.RecoverDelay);
} }
} }
} }

View file

@ -87,6 +87,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="AvatarBoolParameter.cs" /> <Compile Include="AvatarBoolParameter.cs" />
<Compile Include="ModUi.cs" />
<Compile Include="RagdollTrigger.cs" /> <Compile Include="RagdollTrigger.cs" />
<Compile Include="Main.cs" /> <Compile Include="Main.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
@ -135,7 +136,9 @@
<Compile Include="vendor\RootMotion\RagdollManager\Scripts\RagdollCreator.cs" /> <Compile Include="vendor\RootMotion\RagdollManager\Scripts\RagdollCreator.cs" />
<Compile Include="vendor\RootMotion\RagdollManager\Scripts\RagdollEditor.cs" /> <Compile Include="vendor\RootMotion\RagdollManager\Scripts\RagdollEditor.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup>
<EmbeddedResource Include="resources\person.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>
<PostBuildEvent>copy /y "$(TargetPath)" "D:\Games\Steam\steamapps\common\ChilloutVR\Mods\"</PostBuildEvent> <PostBuildEvent>copy /y "$(TargetPath)" "D:\Games\Steam\steamapps\common\ChilloutVR\Mods\"</PostBuildEvent>

BIN
ml_prm/resources/person.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB