diff --git a/ml_pin/Main.cs b/ml_pin/Main.cs index dce09d1..079766f 100644 --- a/ml_pin/Main.cs +++ b/ml_pin/Main.cs @@ -24,8 +24,8 @@ namespace ml_pin { m_soundManager = null; - CVRGameEventSystem.Player.OnJoin.RemoveListener(OnPlayerJoin); - CVRGameEventSystem.Player.OnLeave.RemoveListener(OnPlayerLeave); + CVRGameEventSystem.Player.OnJoinEntity.RemoveListener(OnPlayerJoin); + CVRGameEventSystem.Player.OnLeaveEntity.RemoveListener(OnPlayerLeave); } IEnumerator WaitForInstances() @@ -36,17 +36,17 @@ namespace ml_pin m_soundManager = new SoundManager(); m_soundManager.LoadSounds(); - CVRGameEventSystem.Player.OnJoin.AddListener(OnPlayerJoin); - CVRGameEventSystem.Player.OnLeave.AddListener(OnPlayerLeave); + CVRGameEventSystem.Player.OnJoinEntity.AddListener(OnPlayerJoin); + CVRGameEventSystem.Player.OnLeaveEntity.AddListener(OnPlayerLeave); } - void OnPlayerJoin(PlayerDescriptor p_player) + void OnPlayerJoin(CVRPlayerEntity p_player) { try { - if(p_player != null) // This happens sometimes, no idea why + if((p_player != null) && (p_player.PlayerDescriptor != null)) // This happens sometimes, no idea why { - bool l_isFriend = Friends.FriendsWith(p_player.ownerId); + bool l_isFriend = Friends.FriendsWith(p_player.PlayerDescriptor.ownerId); bool l_notify = false; switch(Settings.NotifyType) @@ -72,13 +72,13 @@ namespace ml_pin MelonLoader.MelonLogger.Warning(e); } } - void OnPlayerLeave(PlayerDescriptor p_player) + void OnPlayerLeave(CVRPlayerEntity p_player) { try { - if(p_player != null) // This happens sometimes, no idea why + if((p_player != null) && (p_player.PlayerDescriptor != null)) // This happens sometimes, no idea why { - bool l_isFriend = Friends.FriendsWith(p_player.ownerId); + bool l_isFriend = Friends.FriendsWith(p_player.PlayerDescriptor.ownerId); bool l_notify = false; switch(Settings.NotifyType) diff --git a/ml_pin/Properties/AssemblyInfo.cs b/ml_pin/Properties/AssemblyInfo.cs index 1662188..4f4fa54 100644 --- a/ml_pin/Properties/AssemblyInfo.cs +++ b/ml_pin/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -[assembly: MelonLoader.MelonInfo(typeof(ml_pin.PlayersInstanceNotifier), "PlayersInstanceNotifier", "1.0.7", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_pin.PlayersInstanceNotifier), "PlayersInstanceNotifier", "1.0.8", "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)] diff --git a/ml_pin/ml_pin.csproj b/ml_pin/ml_pin.csproj index 6cf02d1..cc3dde9 100644 --- a/ml_pin/ml_pin.csproj +++ b/ml_pin/ml_pin.csproj @@ -7,7 +7,7 @@ SDraw None PlayersInstanceNotifier - 1.0.7 + 1.0.8 diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs index 0999a45..dece54f 100644 --- a/ml_prm/Main.cs +++ b/ml_prm/Main.cs @@ -1,5 +1,6 @@ using ABI_RC.Core.Player; using ABI_RC.Core.Util.AssetFiltering; +using ABI_RC.Systems.GameEventSystem; using System; using System.Collections.Generic; using System.Reflection; @@ -17,6 +18,8 @@ namespace ml_prm GameEvents.Init(HarmonyInstance); WorldHandler.Init(); + CVRGameEventSystem.Player.OnJoinEntity.AddListener(this.OnRemotePlayerCreated); + MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer()); MelonLoader.MelonCoroutines.Start(WaitForWhitelist()); } @@ -28,6 +31,8 @@ namespace ml_prm if(m_localController != null) UnityEngine.Object.Destroy(m_localController); m_localController = null; + + CVRGameEventSystem.Player.OnJoinEntity.RemoveListener(this.OnRemotePlayerCreated); } System.Collections.IEnumerator WaitForLocalPlayer() @@ -50,5 +55,11 @@ namespace ml_prm } l_hashSet.Add(typeof(RagdollToggle)); } + + void OnRemotePlayerCreated(CVRPlayerEntity p_player) + { + if((p_player != null) && (p_player.PuppetMaster != null)) + p_player.PuppetMaster.gameObject.AddComponent(); + } } } diff --git a/ml_prm/ModUi.cs b/ml_prm/ModUi.cs index bbd90cc..616da80 100644 --- a/ml_prm/ModUi.cs +++ b/ml_prm/ModUi.cs @@ -34,7 +34,10 @@ namespace ml_prm MovementDrag, AngularDrag, RecoverDelay, - FallLimit + FallLimit, + GestureGrab, + FriendsGrab, + GrabDistance } const string c_ragdollKeyTooltip = "Switch ragdoll mode with '{0}' key"; @@ -58,11 +61,14 @@ namespace ml_prm static ToggleButton ms_jumpRecoverToggle = null; static ToggleButton ms_buoyancyToggle = null; static ToggleButton ms_fallDamageToggle = null; + static ToggleButton ms_gestureGrabToggle = null; + static ToggleButton ms_friendsGrabToggle = null; static SliderFloat ms_velocityMultiplierSlider = null; static SliderFloat ms_movementDragSlider = null; static SliderFloat ms_angularMovementDragSlider = null; static SliderFloat ms_recoverDelaySlider = null; static SliderFloat ms_fallLimitSlider = null; + static SliderFloat ms_grabDistanceSlider = null; static Button ms_resetButton = null; internal static void Init() @@ -77,7 +83,7 @@ namespace ml_prm ms_ragdollButton = ms_category.AddButton("Switch ragdoll", "PRM-Person", "Switch between normal and ragdoll state"); ms_ragdollButton.OnPress += OnSwitch; - + ms_hotkeyToggle = ms_category.AddToggle("Use hotkey", "Switch ragdoll mode with 'R' key", Settings.Hotkey); ms_hotkeyToggle.ToggleTooltip = string.Format(c_ragdollKeyTooltip, Settings.HotkeyKey); ms_hotkeyToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.Hotkey, state); @@ -116,6 +122,12 @@ namespace ml_prm ms_fallDamageToggle = ms_category.AddToggle("Fall damage", "Enable ragdoll when falling from height", Settings.FallDamage); ms_fallDamageToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.FallDamage, state); + ms_gestureGrabToggle = ms_category.AddToggle("Gesture grab", "Enable grabbing of ragdolled body parts by remote players with trigger gesture

Warning: can lead to unpredictable physics behaviour in some cases", Settings.GestureGrab); + ms_gestureGrabToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.GestureGrab, state); + + ms_friendsGrabToggle = ms_category.AddToggle("Friends grab only", " ", Settings.FriendsGrab); + ms_friendsGrabToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.FriendsGrab, state); + ms_velocityMultiplierSlider = ms_category.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", Settings.VelocityMultiplier, 1f, 50f); ms_velocityMultiplierSlider.OnValueUpdated += (value) => OnSliderUpdate(UiIndex.VelocityMultiplier, value); @@ -132,6 +144,9 @@ namespace ml_prm ms_fallLimitSlider.SliderTooltip = string.Format(c_fallLimitTooltip, GetDropHeight(Settings.FallLimit)); ms_fallLimitSlider.OnValueUpdated += (value) => OnSliderUpdate(UiIndex.FallLimit, value); + ms_grabDistanceSlider = ms_category.AddSlider("Grab distance", "Minimal distance for successful grab", Settings.GrabDistance, 0f, 1f); + ms_grabDistanceSlider.OnValueUpdated += (value) => OnSliderUpdate(UiIndex.GrabDistance, value); + ms_resetButton = ms_category.AddButton("Reset settings", "", "Reset mod settings to default"); ms_resetButton.OnPress += Reset; } @@ -201,6 +216,14 @@ namespace ml_prm case UiIndex.FallDamage: Settings.SetSetting(Settings.ModSetting.FallDamage, p_state); break; + + case UiIndex.GestureGrab: + Settings.SetSetting(Settings.ModSetting.GestureGrab, p_state); + break; + + case UiIndex.FriendsGrab: + Settings.SetSetting(Settings.ModSetting.FriendsGrab, p_state); + break; } } catch(Exception e) @@ -237,6 +260,10 @@ namespace ml_prm ms_fallLimitSlider.SliderTooltip = string.Format(c_fallLimitTooltip, GetDropHeight(p_value)); } break; + + case UiIndex.GrabDistance: + Settings.SetSetting(Settings.ModSetting.GrabDistance, p_value); + break; } } catch(Exception e) @@ -283,6 +310,12 @@ namespace ml_prm OnToggleUpdate(UiIndex.FallDamage, true); ms_fallDamageToggle.ToggleValue = true; + OnToggleUpdate(UiIndex.GestureGrab, false); + ms_gestureGrabToggle.ToggleValue = false; + + OnToggleUpdate(UiIndex.FriendsGrab, true); + ms_friendsGrabToggle.ToggleValue = true; + OnSliderUpdate(UiIndex.VelocityMultiplier, 2f); ms_velocityMultiplierSlider.SetSliderValue(2f); @@ -297,6 +330,9 @@ namespace ml_prm OnSliderUpdate(UiIndex.FallLimit, 9.899494f); ms_fallLimitSlider.SetSliderValue(9.899494f); + + OnSliderUpdate(UiIndex.GrabDistance, 0.1f); + ms_grabDistanceSlider.SetSliderValue(0.1f); } static void OnHotkeyKeyChanged(UnityEngine.KeyCode p_keyCode) diff --git a/ml_prm/Properties/AssemblyInfo.cs b/ml_prm/Properties/AssemblyInfo.cs index 1729147..c0c841c 100644 --- a/ml_prm/Properties/AssemblyInfo.cs +++ b/ml_prm/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.1.8", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] +[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.1.9", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonGame(null, "ChilloutVR")] [assembly: MelonLoader.MelonPriority(2)] [assembly: MelonLoader.MelonAdditionalDependencies("BTKUILib")] diff --git a/ml_prm/README.md b/ml_prm/README.md index af7d4d0..7353c9f 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -29,6 +29,9 @@ Optional mod's settings page with [BTKUILib](https://github.com/BTK-Development/ * **Buoyancy:** enables floating in fluid volumes; `true` by default. * Note: Forcibly enabled in worlds that don't allow flight. * **Fall damage:** enables ragdoll when falling from specific height; `true` by default. +* **Gesture grab:** enables grabbing of ragdolled body parts by remote players with trigger gesture; `false` by default. + * Note: Can lead to unpredictable physics behaviour in some cases. +* **Friends grab only:** Allow only friends to be able to grab your radgolled body parts; `true` by default. * **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` by default. * Note: Limited according to world's fly multiplier. * Note: Forcibly set to `1.0` in worlds that don't allow flight. @@ -37,6 +40,7 @@ Optional mod's settings page with [BTKUILib](https://github.com/BTK-Development/ * **Angular movement drag:** angular movement resistance; `2.0` by default. * **Recover delay:** time delay for enabled `Auto recover` in seconds; `3.0` by default. * **Fall limit:** height limit for fall damage; `5.0` by default. +* **Grab distance:** minimal distance for successful grab; `0.1` by default. * **Reset settings:** resets mod settings to default. Optional mod's settings in [UIExpansionKit](https://github.com/ddakebono/ChilloutMods): diff --git a/ml_prm/RagdollBodypartHandler.cs b/ml_prm/RagdollBodypartHandler.cs index 7f58f55..db2c2cf 100644 --- a/ml_prm/RagdollBodypartHandler.cs +++ b/ml_prm/RagdollBodypartHandler.cs @@ -18,6 +18,11 @@ namespace ml_prm bool m_shouldHaveInfluencer = false; bool m_activeGravity = true; + bool m_attached = false; + Transform m_attachedHand = null; + Transform m_attachTransform = null; + FixedJoint m_attachJoint = null; + // Unity events void Awake() { @@ -72,6 +77,8 @@ namespace ml_prm { if(collider != null) CVRParticlePointerManager.RemoveTrigger(collider); + + Detach(); } void FixedUpdate() @@ -80,11 +87,26 @@ namespace ml_prm { m_rigidBody.useGravity = false; - if(m_activeGravity && ((m_physicsInfluencer == null) || !m_physicsInfluencer.enableInfluence || !m_physicsInfluencer.GetSubmerged())) + if(!m_attached && m_activeGravity && ((m_physicsInfluencer == null) || !m_physicsInfluencer.enableInfluence || !m_physicsInfluencer.GetSubmerged())) m_rigidBody.AddForce(BetterBetterCharacterController.Instance.GravityResult.AppliedGravity * m_rigidBody.mass); } } + void Update() + { + if(m_attached && !ReferenceEquals(m_attachTransform, null) && (m_attachTransform == null)) + { + m_attachTransform = null; + + if(m_attachJoint != null) + Object.Destroy(m_attachJoint); + m_attachJoint = null; + + m_attachedHand = null; + m_attached = false; + } + } + void OnTriggerEnter(Collider p_col) { if(Settings.PointersReaction && (RagdollController.Instance != null)) @@ -178,6 +200,54 @@ namespace ml_prm return (Settings.IgnoreLocal && (p_transform.root == PlayerSetup.Instance.transform)); } + public bool Attach(Transform p_hand, Vector3 p_pos) + { + bool l_result = false; + + if(!m_attached && (collider != null)) + { + if(Vector3.Distance(p_pos, collider.ClosestPoint(p_pos)) <= Settings.GrabDistance) + { + GameObject l_attachPoint = new GameObject("[AttachPoint]"); + m_attachTransform = l_attachPoint.transform; + m_attachTransform.parent = p_hand; + m_attachTransform.position = p_pos; + + Rigidbody l_body = l_attachPoint.AddComponent(); + l_body.isKinematic = true; + l_body.detectCollisions = false; + + m_attachJoint = this.gameObject.AddComponent(); + m_attachJoint.connectedBody = l_body; + m_attachJoint.breakForce = Mathf.Infinity; + m_attachJoint.breakTorque = Mathf.Infinity; + + m_attached = true; + m_attachedHand = p_hand; + l_result = true; + } + } + return l_result; + } + + public void Detach() => Detach(m_attachedHand); + public void Detach(Transform p_hand) + { + if(m_attached && ReferenceEquals(m_attachedHand, p_hand)) + { + if(m_attachTransform != null) + Object.Destroy(m_attachTransform.gameObject); + m_attachTransform = null; + + if(m_attachJoint != null) + Object.Destroy(m_attachJoint); + m_attachJoint = null; + + m_attachedHand = null; + m_attached = false; + } + } + // CVRTriggerVolume public void TriggerEnter(CVRPointer pointer) { @@ -187,6 +257,8 @@ namespace ml_prm RagdollController.Instance.SwitchRagdoll(); } } - public void TriggerExit(CVRPointer pointer) { } + public void TriggerExit(CVRPointer pointer) + { + } } } diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index feaf031..7fd72b3 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -88,6 +88,7 @@ namespace ml_prm Settings.OnBouncinessChanged.AddHandler(this.OnPhysicsMaterialChanged); Settings.OnBuoyancyChanged.AddHandler(this.OnBuoyancyChanged); Settings.OnFallDamageChanged.AddHandler(this.OnFallDamageChanged); + Settings.OnGestureGrabChanged.AddHandler(this.OnGestureGrabChanged); GameEvents.OnAvatarClear.AddHandler(this.OnAvatarClear); GameEvents.OnAvatarSetup.AddHandler(this.OnAvatarSetup); @@ -103,6 +104,7 @@ namespace ml_prm BetterBetterCharacterController.OnTeleport.AddListener(this.OnPlayerTeleport); ModUi.OnSwitchChanged.AddHandler(this.SwitchRagdoll); + RemoteGestureHandler.OnGestureState.AddHandler(this.OnRemotePlayerGestureStateChanged); } void OnDestroy() @@ -135,6 +137,7 @@ namespace ml_prm Settings.OnBouncinessChanged.RemoveHandler(this.OnPhysicsMaterialChanged); Settings.OnBuoyancyChanged.RemoveHandler(this.OnBuoyancyChanged); Settings.OnFallDamageChanged.RemoveHandler(this.OnFallDamageChanged); + Settings.OnGestureGrabChanged.RemoveHandler(this.OnGestureGrabChanged); GameEvents.OnAvatarClear.RemoveHandler(this.OnAvatarClear); GameEvents.OnAvatarSetup.RemoveHandler(this.OnAvatarSetup); @@ -150,6 +153,7 @@ namespace ml_prm BetterBetterCharacterController.OnTeleport.RemoveListener(this.OnPlayerTeleport); ModUi.OnSwitchChanged.RemoveHandler(this.SwitchRagdoll); + RemoteGestureHandler.OnGestureState.RemoveHandler(this.OnRemotePlayerGestureStateChanged); } void Update() @@ -485,6 +489,37 @@ namespace ml_prm p_result.m_result |= (m_enabled && (m_vrIK != null)); } + // Custom game events + void OnRemotePlayerGestureStateChanged(ABI_RC.Core.Player.PuppetMaster p_master, bool p_left, bool p_state) + { + if(m_avatarReady && m_enabled && Settings.GestureGrab && (p_master.animatorManager.Animator != null)) + { + Transform l_hand = p_master.animatorManager.Animator.GetBoneTransform(p_left ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand); + Transform l_finger = p_master.animatorManager.Animator.GetBoneTransform(p_left ? HumanBodyBones.LeftMiddleProximal : HumanBodyBones.RightMiddleProximal); + + if(l_hand != null) + { + Vector3 l_pos = l_hand.position; + if(l_finger != null) + { + l_pos += l_finger.position; + l_pos *= 0.5f; + } + + foreach(var l_bodyHandler in m_ragdollBodyHandlers) + { + if(p_state) + { + if(l_bodyHandler.Attach(l_hand, l_pos)) + break; + } + else + l_bodyHandler.Detach(l_hand); + } + } + } + } + // VRIK updates void OnIKPostSolverUpdate() { @@ -505,6 +540,7 @@ namespace ml_prm l_handler.SetDrag(l_drag); } } + void OnAngularDragChanged(float p_value) { if(m_avatarReady) @@ -513,6 +549,7 @@ namespace ml_prm l_handler.SetAngularDrag(p_value); } } + void OnGravityChanged(bool p_state) { if(m_avatarReady) @@ -528,6 +565,7 @@ namespace ml_prm } } } + void OnPhysicsMaterialChanged(bool p_state) { if(m_physicsMaterial != null) @@ -541,6 +579,7 @@ namespace ml_prm m_physicsMaterial.bounceCombine = (l_bounciness ? PhysicMaterialCombine.Maximum : PhysicMaterialCombine.Average); } } + void OnBuoyancyChanged(bool p_state) { if(m_avatarReady) @@ -556,11 +595,21 @@ namespace ml_prm } } } + void OnFallDamageChanged(bool p_state) { m_inAir = false; } + void OnGestureGrabChanged(bool p_state) + { + if(m_avatarReady && m_enabled & !p_state) + { + foreach(var l_hanlder in m_ragdollBodyHandlers) + l_hanlder.Detach(); + } + } + // Arbitrary public void SwitchRagdoll() { @@ -644,8 +693,9 @@ namespace ml_prm foreach(RagdollBodypartHandler l_handler in m_ragdollBodyHandlers) { - l_handler.SetAsKinematic(true); + l_handler.Detach(); l_handler.ClearFluidVolumes(); + l_handler.SetAsKinematic(true); } m_lastPosition = PlayerSetup.Instance.transform.position; diff --git a/ml_prm/RemoteGestureHandler.cs b/ml_prm/RemoteGestureHandler.cs new file mode 100644 index 0000000..a946d8f --- /dev/null +++ b/ml_prm/RemoteGestureHandler.cs @@ -0,0 +1,50 @@ +using ABI_RC.Core.Networking.IO.Social; +using ABI_RC.Core.Player; +using System; +using System.Collections.Generic; +using System.Text; +using UnityEngine; + +namespace ml_prm +{ + class RemoteGestureHandler : MonoBehaviour + { + internal class GestureEvent + { + event Action m_action; + public void AddHandler(Action p_listener) => m_action += p_listener; + public void RemoveHandler(Action p_listener) => m_action -= p_listener; + public void Invoke(T1 p_objA, T2 p_objB, T3 p_objC) => m_action?.Invoke(p_objA, p_objB, p_objC); + } + + public static readonly GestureEvent OnGestureState = new GestureEvent(); + + PuppetMaster m_puppetMaster = null; + bool m_stateLeft = false; + bool m_stateRight = false; + + void Start() + { + m_puppetMaster = this.GetComponent(); + } + + void Update() + { + bool l_state = Mathf.Approximately(m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorGestureLeft, 1f); + if(m_stateLeft != l_state) + { + m_stateLeft = l_state; + if(!Settings.FriendsGrab || Friends.FriendsWith(m_puppetMaster.CVRPlayerEntity.PlayerDescriptor.ownerId)) + OnGestureState.Invoke(m_puppetMaster, true, m_stateLeft); + } + + l_state = Mathf.Approximately(m_puppetMaster.PlayerAvatarMovementDataInput.AnimatorGestureRight, 1f); + if(m_stateRight != l_state) + { + m_stateRight = l_state; + if(!Settings.FriendsGrab || Friends.FriendsWith(m_puppetMaster.CVRPlayerEntity.PlayerDescriptor.ownerId)) + OnGestureState.Invoke(m_puppetMaster, false, m_stateRight); + } + } + } +} diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index 571685e..e16d152 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -33,7 +33,10 @@ namespace ml_prm JumpRecover, Buoyancy, FallDamage, - FallLimit + FallLimit, + GestureGrab, + FriendsGrab, + GrabDistance } public static bool Hotkey { get; private set; } = true; @@ -54,6 +57,9 @@ namespace ml_prm public static bool Buoyancy { get; private set; } = true; public static bool FallDamage { get; private set; } = true; public static float FallLimit { get; private set; } = 9.899494f; + public static bool GestureGrab { get; private set; } = false; + public static bool FriendsGrab { get; private set; } = true; + public static float GrabDistance { get; private set; } = 0.1f; public static readonly SettingEvent OnHotkeyChanged = new SettingEvent(); public static readonly SettingEvent OnHotkeyKeyChanged = new SettingEvent(); @@ -73,6 +79,9 @@ namespace ml_prm public static readonly SettingEvent OnBuoyancyChanged = new SettingEvent(); public static readonly SettingEvent OnFallDamageChanged = new SettingEvent(); public static readonly SettingEvent OnFallLimitChanged = new SettingEvent(); + public static readonly SettingEvent OnGestureGrabChanged = new SettingEvent(); + public static readonly SettingEvent OnFriendsGrabChanged = new SettingEvent(); + public static readonly SettingEvent OnGrabDistanceChanged = new SettingEvent(); static MelonLoader.MelonPreferences_Category ms_category = null; static List ms_entries = null; @@ -101,6 +110,9 @@ namespace ml_prm ms_category.CreateEntry(ModSetting.Buoyancy.ToString(), Buoyancy, 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.GestureGrab.ToString(), GestureGrab, null, null, true), + ms_category.CreateEntry(ModSetting.FriendsGrab.ToString(), FriendsGrab, null, null, true), + ms_category.CreateEntry(ModSetting.GrabDistance.ToString(), GrabDistance, null, null, true), }; ms_entries[(int)ModSetting.HotkeyKey].OnEntryValueChangedUntyped.Subscribe(OnMelonSettingSave_HotkeyKey); @@ -123,6 +135,9 @@ namespace ml_prm Buoyancy = (bool)ms_entries[(int)ModSetting.Buoyancy].BoxedValue; FallDamage = (bool)ms_entries[(int)ModSetting.FallDamage].BoxedValue; FallLimit = Mathf.Clamp((float)ms_entries[(int)ModSetting.FallLimit].BoxedValue, 4.5f, 44.5f); + GestureGrab = (bool)ms_entries[(int)ModSetting.GestureGrab].BoxedValue; + FriendsGrab = (bool)ms_entries[(int)ModSetting.FriendsGrab].BoxedValue; + GrabDistance = Mathf.Clamp01((float)ms_entries[(int)ModSetting.GrabDistance].BoxedValue); } static void OnMelonSettingSave_HotkeyKey(object p_oldValue, object p_newValue) @@ -232,6 +247,20 @@ namespace ml_prm } break; + case ModSetting.GestureGrab: + { + GestureGrab = (bool)p_value; + OnGestureGrabChanged.Invoke(GestureGrab); + } + break; + + case ModSetting.FriendsGrab: + { + FriendsGrab = (bool)p_value; + OnFriendsGrabChanged.Invoke(FriendsGrab); + } + break; + // Floats case ModSetting.VelocityMultiplier: { @@ -267,6 +296,13 @@ namespace ml_prm OnFallLimitChanged.Invoke(FallLimit); } break; + + case ModSetting.GrabDistance: + { + GrabDistance = (float)p_value; + OnGrabDistanceChanged.Invoke(GrabDistance); + } + break; } if(ms_entries != null) diff --git a/ml_prm/ml_prm.csproj b/ml_prm/ml_prm.csproj index 3b7a96c..95f8b33 100644 --- a/ml_prm/ml_prm.csproj +++ b/ml_prm/ml_prm.csproj @@ -4,7 +4,7 @@ netstandard2.1 x64 PlayerRagdollMod - 1.1.8 + 1.1.9 SDraw None PlayerRagdollMod