Compare commits

...

10 commits
r181 ... master

Author SHA1 Message Date
SDraw
2c4fbb1731
Lower default impact sounds volume 2026-05-02 16:28:39 +03:00
SDraw
812b930bed
Version bump 2026-04-26 10:56:23 +03:00
SDraw
c25eaaf754
Merge pull request #5 from Slime-Senpai/master
Fix ml_vpc
2026-04-26 10:04:13 +03:00
Slime-Senpai
d8bb5881fc Add ml_vpc readme tutorial for linux 2026-04-25 17:29:07 +02:00
Slime-Senpai
e04724ed9d Fix ml_vpc 2026-04-25 17:08:07 +02:00
SDraw
2a06001100
Impact sounds 2026-04-18 22:42:47 +03:00
SDraw
15de34c0bd
Update README.md 2026-04-04 05:41:42 +00:00
SDraw
e357f83227
PRM fix for build 2026r181 2026-04-04 08:29:42 +03:00
SDraw
49987b5d72
Fix for MelonLoader 0.7.1 2026-02-01 17:49:38 +03:00
SDraw
e6feaff0ec
Update README.md 2025-12-29 20:33:59 +00:00
33 changed files with 508 additions and 243 deletions

View file

@ -1,23 +0,0 @@
Merged set of MelonLoader mods for ChilloutVR.
**Table for game build 2025r180:**
| Full name | Latest version |
|:---------:|:--------------:|
|[Avatar Motion Tweaker](/ml_amt/README.md)|1.5.3 [:arrow_down:](../../releases/download/r181/AvatarMotionTweaker.dll)|
|[Avatar Synced Look](/ml_asl/README.md)|1.1.3 [:arrow_down:](../../releases/download/r181/AvatarSyncedLook.dll)|
|[Better Fingers Tracking](/ml_bft/README.md)|1.1.4 [:arrow_down:](../../releases/download/r181/BetterFingersTracking.dll)|
|[Leap Motion Extension](/ml_lme/README.md)| 1.6.4 [:arrow_down:](../../releases/download/r181/LeapMotionExtension.dll)|
|[Pickup Arm Movement](/ml_pam/README.md)|1.2.4 [:arrow_down:](../../releases/download/r181/PickupArmMovement.dll)|
|[Player Avatar History](/ml_pah/README.md)|1.0.1 [:arrow_down:](../../releases/download/r181/PlayerAvatarHistory.dll)|
|[Player Movement Copycat](/ml_pmc/README.md)|1.1.3 [:arrow_down:](../../releases/download/r181/PlayerMovementCopycat.dll)|
|[Player Pick Up](/ml_ppu/README.md)|1.0.2 [:arrow_down:](../../releases/download/r181/PlayerPickUp.dll)|
|[Player Ragdoll Mod](/ml_prm/README.md)|1.2.5 [:arrow_down:](../../releases/download/r181/PlayerRagdollMod.dll)|
|[Players Instance Notifier](/ml_pin/README.md)|1.1.3 [:arrow_down:](../../releases/download/r181/PlayersInstanceNotifier.dll)|
|[Vive Extended Input](/ml_vei/README.md)|1.1.3 [:arrow_down:](../../releases/download/r181/ViveExtendedInput.dll)|
|[Video Player Cookies](/ml_vpc/README.md)|1.0.4 [:arrow_down:](../../releases/download/r181/VideoPlayerCookies.dll)|

View file

@ -12,8 +12,6 @@ namespace ml_asl
public override void OnInitializeMelon() public override void OnInitializeMelon()
{ {
Settings.Init();
HarmonyInstance.Patch( HarmonyInstance.Patch(
typeof(PlayerSetup).GetMethod("UpdatePlayerAvatarMovementData", BindingFlags.Instance | BindingFlags.NonPublic), typeof(PlayerSetup).GetMethod("UpdatePlayerAvatarMovementData", BindingFlags.Instance | BindingFlags.NonPublic),
null, null,
@ -21,6 +19,11 @@ namespace ml_asl
); );
} }
public override void OnLateInitializeMelon()
{
Settings.Init();
}
static void OnPlayerAvatarMovementDataUpdate_Postfix(ref PlayerSetup __instance, PlayerAvatarMovementData ____playerAvatarMovementData) static void OnPlayerAvatarMovementDataUpdate_Postfix(ref PlayerSetup __instance, PlayerAvatarMovementData ____playerAvatarMovementData)
{ {
try try

View file

@ -1,4 +1,4 @@
[assembly: MelonLoader.MelonInfo(typeof(ml_asl.AvatarSyncedLook), "AvatarSyncedLook", "1.1.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonInfo(typeof(ml_asl.AvatarSyncedLook), "AvatarSyncedLook", "1.1.4", "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)]

View file

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

View file

@ -55,7 +55,7 @@ namespace ml_prm
); );
p_instance.Patch( p_instance.Patch(
typeof(PlayerSetup).GetMethod("SetupIKScaling", BindingFlags.Instance |BindingFlags.NonPublic), typeof(PlayerSetup).GetMethod("SetupIKScaling", BindingFlags.Instance | BindingFlags.NonPublic),
null, null,
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupIKScaling_Postfix), BindingFlags.Static | BindingFlags.NonPublic)) new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupIKScaling_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
); );
@ -73,7 +73,7 @@ namespace ml_prm
); );
p_instance.Patch( p_instance.Patch(
typeof(RootLogic).GetMethod(nameof(RootLogic.SpawnOnWorldInstance),BindingFlags.Instance | BindingFlags.Public), typeof(RootLogic).GetMethod(nameof(RootLogic.SpawnOnWorldInstance), BindingFlags.Instance | BindingFlags.Public),
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnWorldSpawn_Prefix), BindingFlags.Static | BindingFlags.NonPublic)), new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnWorldSpawn_Prefix), BindingFlags.Static | BindingFlags.NonPublic)),
null null
); );

View file

@ -5,12 +5,14 @@ namespace ml_prm
public class PlayerRagdollMod : MelonLoader.MelonMod public class PlayerRagdollMod : MelonLoader.MelonMod
{ {
RagdollController m_controller = null; RagdollController m_controller = null;
SoundManager m_soundManager = null;
public override void OnInitializeMelon() public override void OnInitializeMelon()
{ {
Settings.Init(); Settings.Init();
GameEvents.Init(HarmonyInstance); GameEvents.Init(HarmonyInstance);
WorldManager.Init(); WorldManager.Init();
ResourcesHandler.ExtractResources();
} }
public override void OnLateInitializeMelon() public override void OnLateInitializeMelon()
@ -26,6 +28,8 @@ 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_soundManager = new SoundManager(m_controller.transform);
m_soundManager.LoadSounds();
} }
System.Collections.IEnumerator WaitForWhitelist() System.Collections.IEnumerator WaitForWhitelist()
@ -40,6 +44,8 @@ namespace ml_prm
{ {
WorldManager.DeInit(); WorldManager.DeInit();
m_soundManager = null;
if(m_controller != null) if(m_controller != null)
UnityEngine.Object.Destroy(m_controller.gameObject); UnityEngine.Object.Destroy(m_controller.gameObject);
m_controller = null; m_controller = null;

View file

@ -21,7 +21,6 @@ namespace ml_prm
Hotkey = 0, Hotkey = 0,
Gravity, Gravity,
PointersReaction, PointersReaction,
IgnoreLocal,
CombatReaction, CombatReaction,
AutoRecover, AutoRecover,
Slipperiness, Slipperiness,
@ -36,7 +35,8 @@ namespace ml_prm
RecoverDelay, RecoverDelay,
FallLimit, FallLimit,
GestureGrab, GestureGrab,
FriendsGrab ImpactSounds,
ImpactVolume
} }
const string c_ragdollKeyTooltip = "Switch ragdoll mode with '{0}' key"; const string c_ragdollKeyTooltip = "Switch ragdoll mode with '{0}' key";
@ -52,7 +52,6 @@ namespace ml_prm
static ToggleButton ms_hotkeyToggle = null; static ToggleButton ms_hotkeyToggle = null;
static ToggleButton ms_gravityToggle = null; static ToggleButton ms_gravityToggle = null;
static ToggleButton ms_pointersToggle = null; static ToggleButton ms_pointersToggle = null;
static ToggleButton ms_ignoreLocalToggle = null;
static ToggleButton ms_combatToggle = null; static ToggleButton ms_combatToggle = null;
static ToggleButton ms_recoveryToggle = null; static ToggleButton ms_recoveryToggle = null;
static ToggleButton ms_slipperinessToggle = null; static ToggleButton ms_slipperinessToggle = null;
@ -62,12 +61,13 @@ namespace ml_prm
static ToggleButton ms_buoyancyToggle = null; static ToggleButton ms_buoyancyToggle = null;
static ToggleButton ms_fallDamageToggle = null; static ToggleButton ms_fallDamageToggle = null;
static ToggleButton ms_gestureGrabToggle = null; static ToggleButton ms_gestureGrabToggle = null;
static ToggleButton ms_friendsGrabToggle = null; static ToggleButton ms_impactSoundsToggle = null;
static SliderFloat ms_velocityMultiplierSlider = null; static SliderFloat ms_velocityMultiplierSlider = null;
static SliderFloat ms_movementDragSlider = null; static SliderFloat ms_movementDragSlider = null;
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_impactVolumeSlider = null;
static Button ms_resetButton = null; static Button ms_resetButton = null;
internal static void Init() internal static void Init()
@ -94,9 +94,6 @@ namespace ml_prm
ms_pointersToggle = ms_category.AddToggle("Pointers reaction", "React to trigger colliders with CVRPointer component of 'ragdoll' type", Settings.PointersReaction); ms_pointersToggle = ms_category.AddToggle("Pointers reaction", "React to trigger colliders with CVRPointer component of 'ragdoll' type", Settings.PointersReaction);
ms_pointersToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.PointersReaction, state); ms_pointersToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.PointersReaction, state);
ms_ignoreLocalToggle = ms_category.AddToggle("Ignore local pointers", "Ignore local avatar's CVRPointer components of 'ragdoll' type", Settings.IgnoreLocal);
ms_ignoreLocalToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.IgnoreLocal, state);
ms_combatToggle = ms_category.AddToggle("Combat reaction", "Ragdoll upon combat system death", Settings.CombatReaction); ms_combatToggle = ms_category.AddToggle("Combat reaction", "Ragdoll upon combat system death", Settings.CombatReaction);
ms_combatToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.CombatReaction, state); ms_combatToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.CombatReaction, state);
@ -121,11 +118,11 @@ namespace ml_prm
ms_fallDamageToggle = ms_category.AddToggle("Fall damage", "Enable ragdoll when falling from height", Settings.FallDamage); ms_fallDamageToggle = ms_category.AddToggle("Fall damage", "Enable ragdoll when falling from height", Settings.FallDamage);
ms_fallDamageToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.FallDamage, state); 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/grab gesture<p>Warning: can lead to unpredictable physics behaviour in some cases", Settings.GestureGrab); ms_gestureGrabToggle = ms_category.AddToggle("Grab attaching", "Enable attaching of ragdolled body parts to pointers of 'grab' type<p>Warning: can lead to unpredictable physics behaviour in some cases", Settings.GestureGrab);
ms_gestureGrabToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.GestureGrab, state); ms_gestureGrabToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.GestureGrab, state);
ms_friendsGrabToggle = ms_category.AddToggle("Friends grab only", " ", Settings.FriendsGrab); ms_impactSoundsToggle = ms_category.AddToggle("Impact sounds", "Enable collision sound effects of ragdolled body parts", Settings.ImpactSounds);
ms_friendsGrabToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.FriendsGrab, state); ms_impactSoundsToggle.OnValueUpdated += (state) => OnToggleUpdate(UiIndex.ImpactSounds, state);
ms_velocityMultiplierSlider = ms_category.AddSlider("Velocity multiplier", "Velocity multiplier upon entering ragdoll state", Settings.VelocityMultiplier, 1f, 50f); 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); ms_velocityMultiplierSlider.OnValueUpdated += (value) => OnSliderUpdate(UiIndex.VelocityMultiplier, value);
@ -143,6 +140,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_impactVolumeSlider = ms_category.AddSlider("Impact volume", "Volume of collision of ragdolled body parts", Settings.ImpactVolume * 100f, 0f, 100f);
ms_impactVolumeSlider.OnValueUpdated += (value) => OnSliderUpdate(UiIndex.ImpactVolume, 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;
} }
@ -177,10 +177,6 @@ namespace ml_prm
Settings.SetSetting(Settings.ModSetting.PointersReaction, p_state); Settings.SetSetting(Settings.ModSetting.PointersReaction, p_state);
break; break;
case UiIndex.IgnoreLocal:
Settings.SetSetting(Settings.ModSetting.IgnoreLocal, p_state);
break;
case UiIndex.CombatReaction: case UiIndex.CombatReaction:
Settings.SetSetting(Settings.ModSetting.CombatReaction, p_state); Settings.SetSetting(Settings.ModSetting.CombatReaction, p_state);
break; break;
@ -217,8 +213,8 @@ namespace ml_prm
Settings.SetSetting(Settings.ModSetting.GestureGrab, p_state); Settings.SetSetting(Settings.ModSetting.GestureGrab, p_state);
break; break;
case UiIndex.FriendsGrab: case UiIndex.ImpactSounds:
Settings.SetSetting(Settings.ModSetting.FriendsGrab, p_state); Settings.SetSetting(Settings.ModSetting.ImpactSounds, p_state);
break; break;
} }
} }
@ -256,6 +252,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.ImpactVolume:
Settings.SetSetting(Settings.ModSetting.ImpactVolume, p_value * 0.01f);
break;
} }
} }
catch(Exception e) catch(Exception e)
@ -275,9 +275,6 @@ namespace ml_prm
OnToggleUpdate(UiIndex.PointersReaction, true); OnToggleUpdate(UiIndex.PointersReaction, true);
ms_pointersToggle.ToggleValue = true; ms_pointersToggle.ToggleValue = true;
OnToggleUpdate(UiIndex.IgnoreLocal, true);
ms_ignoreLocalToggle.ToggleValue = true;
OnToggleUpdate(UiIndex.CombatReaction, true); OnToggleUpdate(UiIndex.CombatReaction, true);
ms_combatToggle.ToggleValue = true; ms_combatToggle.ToggleValue = true;
@ -305,8 +302,8 @@ namespace ml_prm
OnToggleUpdate(UiIndex.GestureGrab, false); OnToggleUpdate(UiIndex.GestureGrab, false);
ms_gestureGrabToggle.ToggleValue = false; ms_gestureGrabToggle.ToggleValue = false;
OnToggleUpdate(UiIndex.FriendsGrab, true); OnToggleUpdate(UiIndex.ImpactSounds, true);
ms_friendsGrabToggle.ToggleValue = true; ms_impactSoundsToggle.ToggleValue = true;
OnSliderUpdate(UiIndex.VelocityMultiplier, 2f); OnSliderUpdate(UiIndex.VelocityMultiplier, 2f);
ms_velocityMultiplierSlider.SetSliderValue(2f); ms_velocityMultiplierSlider.SetSliderValue(2f);
@ -322,6 +319,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.ImpactVolume, 100f);
ms_impactVolumeSlider.SetSliderValue(25f);
} }
static void OnHotkeyKeyChanged(UnityEngine.KeyCode p_keyCode) static void OnHotkeyKeyChanged(UnityEngine.KeyCode p_keyCode)

View file

@ -1,4 +1,4 @@
[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.2.5", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.2.7", "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")]

View file

@ -17,7 +17,6 @@ Optional mod's settings page with [BTKUILib](https://github.com/BTK-Development/
* **Use gravity:** enables/disables gravity for ragdoll; `true` by default. * **Use gravity:** enables/disables gravity for ragdoll; `true` by default.
* Note: Forcibly enabled in worlds that don't allow flight. * Note: Forcibly enabled in worlds that don't allow flight.
* **Pointers reaction:** enables ragdoll state when player collides with trigger colliders and particle systems with CVRPointer component of `ragdoll` type (avatars, props and world included); `true` by default. * **Pointers reaction:** enables ragdoll state when player collides with trigger colliders and particle systems with CVRPointer component of `ragdoll` type (avatars, props and world included); `true` by default.
* **Ignore local pointers:** enables/disables ignoring of CVRPointer components of `ragdoll` type on local player's avatar; `true` by default.
* **Combat reaction:** enables ragdoll state upon death in worlds with combat system; `true` by default. * **Combat reaction:** enables ragdoll state upon death in worlds with combat system; `true` by default.
* **Auto recover:** enables automatic recovering after specific time delay; `false` by default. * **Auto recover:** enables automatic recovering after specific time delay; `false` by default.
* **Slipperiness:** enables/disable low friction of ragdoll; `false` by default. * **Slipperiness:** enables/disable low friction of ragdoll; `false` by default.
@ -30,9 +29,10 @@ Optional mod's settings page with [BTKUILib](https://github.com/BTK-Development/
* **Buoyancy:** enables floating in fluid volumes; `true` by default. * **Buoyancy:** enables floating in fluid volumes; `true` by default.
* Note: Forcibly enabled in worlds that don't allow flight. * Note: Forcibly enabled in worlds that don't allow flight.
* **Fall damage:** enables ragdoll when falling from specific height; `true` by default. * **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/grab gesture; `false` by default. * **Grab attaching:** enables attaching of ragdolled body parts to pointers with `grab` type of avatars, props and world(s); `false` by default.
* Note: Can lead to unpredictable physics behaviour in some cases. * 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. * **Impact sounds:** enables collision sound effects of ragdolled body parts; `true` by default.
* Note: Sounds can be replaced in `(game_folder)/UserData/PlayerRagdollMod` folder.
* **Velocity multiplier:** velocity force multiplier based on player's movement direction; `2.0` 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: Limited according to world's fly multiplier.
* Note: Forcibly set to `1.0` in worlds that don't allow flight. * Note: Forcibly set to `1.0` in worlds that don't allow flight.
@ -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.
* **Impact volume:** collision sounds volume of ragdolled body parts; `100.0` 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):

View file

@ -1,15 +1,15 @@
using ABI.CCK.Components; using ABI.CCK.Components;
using ABI_RC.Core; 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.Systems.Movement; using ABI_RC.Systems.Movement;
using NAK.Contacts;
using System.Collections.Generic;
using UnityEngine; using UnityEngine;
namespace ml_prm namespace ml_prm
{ {
[DisallowMultipleComponent] [DisallowMultipleComponent]
class RagdollBodypartHandler : MonoBehaviour, CVRTriggerVolume class RagdollBodypartHandler : MonoBehaviour
{ {
const string c_ragdollPointerType = "ragdoll"; const string c_ragdollPointerType = "ragdoll";
const string c_grabPointerType = "grab"; const string c_grabPointerType = "grab";
@ -18,14 +18,16 @@ namespace ml_prm
Rigidbody m_rigidBody = null; Rigidbody m_rigidBody = null;
public Collider collider { get; set; } = null; public Collider collider { get; set; } = null;
ContactReceiver m_contactReciever = null;
PhysicsInfluencer m_physicsInfluencer = null; PhysicsInfluencer m_physicsInfluencer = null;
public bool UseBuoyancy { get; set; } = false; public bool UseBuoyancy { get; set; } = false;
bool m_attached = false; bool m_attached = false;
CVRPointer m_attachedPointer = null;
Transform m_attachTransform = null; Transform m_attachTransform = null;
ContactSender m_attachedSender = null;
FixedJoint m_attachJoint = null; FixedJoint m_attachJoint = null;
static List<ContactSender> ms_attachedSenders = new List<ContactSender>();
// Unity events // Unity events
void Awake() void Awake()
@ -42,7 +44,28 @@ namespace ml_prm
} }
if(collider != null) if(collider != null)
{
RemoveGameCollision(); RemoveGameCollision();
var l_constactShape = ContactConversion.FromCollider(collider, true);
m_contactReciever = this.gameObject.AddComponent<ContactReceiver>();
m_contactReciever.shapeType = l_constactShape.shapeType;
m_contactReciever.localPosition = l_constactShape.localPosition;
m_contactReciever.localRotation = l_constactShape.localRotation;
m_contactReciever.radius = l_constactShape.radius;
m_contactReciever.height = l_constactShape.height;
m_contactReciever.boxSize = l_constactShape.boxSize;
m_contactReciever.collisionTags = new string[] { c_ragdollPointerType, c_grabPointerType };
m_contactReciever.receiverType = ReceiverType.Constant;
m_contactReciever.contentTypes = ContentType.World | ContentType.Avatar | ContentType.Prop;
m_contactReciever.SourceContentType = ContentType.Player;
m_contactReciever.contactValue = 1f;
m_contactReciever.drawGizmos = false;
m_contactReciever.OnContactEnter += this.OnContactEnter;
}
} }
void Start() void Start()
@ -64,46 +87,54 @@ namespace ml_prm
this.gameObject.name = string.Format("{0} [NoGizmo]", this.gameObject.name); this.gameObject.name = string.Format("{0} [NoGizmo]", this.gameObject.name);
} }
if(collider != null)
{
CVRParticlePointerManager.volumes.Add(this);
CVRParticlePointerManager.UpdateParticleSystems();
}
} }
void OnDestroy() void OnDestroy()
{ {
if(collider != null)
CVRParticlePointerManager.RemoveTrigger(collider);
Detach(); Detach();
} }
void Update() void Update()
{ {
if(m_attached && ((m_attachedPointer == null) || !m_attachedPointer.isActiveAndEnabled)) if(m_attached && ((m_attachedSender == null) || !m_attachedSender.isActiveAndEnabled))
Detach(); Detach();
} }
void OnTriggerEnter(Collider p_col) void OnCollisionEnter(Collision p_col)
{ {
if(m_ready && (RagdollController.Instance != null)) if(Settings.ImpactSounds && m_ready && !m_rigidBody.isKinematic && (p_col.gameObject.layer != CVRLayers.PlayerClone))
{ {
CVRPointer l_pointer = p_col.GetComponent<CVRPointer>(); if(p_col.impulse.magnitude > 5f)
SoundManager.Instance.PlaySound(SoundManager.ImpactType.Soft);
}
}
// Ragdolling void OnContactEnter(ContactCollisionInfo p_col)
if(Settings.PointersReaction && !RagdollController.Instance.IsRagdolled()) {
if(m_ready && (RagdollController.Instance != null) && ContactManager.Exists)
{
ContactSender l_sender = ContactManager.Instance.GetSenderById(p_col.senderContactId);
if((l_sender != null) && (l_sender.collisionTags != null))
{ {
if((l_pointer != null) && (l_pointer.type == c_ragdollPointerType) && l_pointer.enabled && !IgnoreCheck(l_pointer.transform)) foreach(string l_tag in l_sender.collisionTags)
RagdollController.Instance.Ragdoll(); {
} switch(l_tag)
{
case c_ragdollPointerType:
{
if(Settings.PointersReaction && !RagdollController.Instance.IsRagdolled() && RestrictionsCheck(l_sender.transform.root))
RagdollController.Instance.Ragdoll();
}
break;
//Attachment case c_grabPointerType:
if(!m_attached && RagdollController.Instance.IsRagdolled()) {
{ if(!m_attached && RagdollController.Instance.IsRagdolled() && RestrictionsCheck(l_sender.transform.root))
if((l_pointer != null) && (l_pointer.type == c_grabPointerType) && RestrictionsCheck(p_col.transform.root)) Attach(l_sender);
Attach(l_pointer); }
break;
}
}
} }
} }
} }
@ -196,16 +227,16 @@ namespace ml_prm
RemoveGameCollision(); RemoveGameCollision();
} }
void Attach(CVRPointer p_pointer) void Attach(ContactSender p_sender)
{ {
if(!m_attached && (collider != null) && (m_rigidBody != null)) if(!m_attached && (collider != null) && (m_rigidBody != null) && !ms_attachedSenders.Contains(p_sender))
{ {
m_attachedPointer = p_pointer; m_attachedSender = p_sender;
GameObject l_attachPoint = new GameObject("[AttachPoint]"); GameObject l_attachPoint = new GameObject("[AttachPoint]");
l_attachPoint.layer = CVRLayers.PlayerNetwork; l_attachPoint.layer = CVRLayers.Default;
m_attachTransform = l_attachPoint.transform; m_attachTransform = l_attachPoint.transform;
m_attachTransform.parent = p_pointer.transform; m_attachTransform.parent = p_sender.transform;
Rigidbody l_body = l_attachPoint.AddComponent<Rigidbody>(); Rigidbody l_body = l_attachPoint.AddComponent<Rigidbody>();
l_body.isKinematic = true; l_body.isKinematic = true;
@ -216,6 +247,7 @@ namespace ml_prm
m_attachJoint.breakForce = Mathf.Infinity; m_attachJoint.breakForce = Mathf.Infinity;
m_attachJoint.breakTorque = Mathf.Infinity; m_attachJoint.breakTorque = Mathf.Infinity;
ms_attachedSenders.Add(p_sender);
m_attached = true; m_attached = true;
} }
} }
@ -232,7 +264,10 @@ namespace ml_prm
Object.Destroy(m_attachJoint); Object.Destroy(m_attachJoint);
m_attachJoint = null; m_attachJoint = null;
m_attachedPointer = null; if(!ReferenceEquals(m_attachedSender, null))
ms_attachedSenders.Remove(m_attachedSender);
m_attachedSender = null;
m_attached = false; m_attached = false;
} }
} }
@ -246,32 +281,12 @@ namespace ml_prm
BetterBetterCharacterController.Instance.IgnoreCollision(collider); BetterBetterCharacterController.Instance.IgnoreCollision(collider);
} }
// CVRTriggerVolume internal void RestoreContact()
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())
RagdollController.Instance.Ragdoll();
}
public void TriggerExit(CVRPointer pointer)
{ {
if((m_contactReciever != null) && ContactManager.Exists)
ContactManager.Instance.RestoreContact(m_contactReciever, m_contactReciever.isActiveAndEnabled);
} }
// Static utility static bool RestrictionsCheck(Transform p_transform) => (p_transform != PlayerSetup.Instance.transform);
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;
}
} }
} }

View file

@ -677,6 +677,7 @@ namespace ml_prm
foreach(RagdollBodypartHandler l_handler in m_ragdollBodyHandlers) foreach(RagdollBodypartHandler l_handler in m_ragdollBodyHandlers)
{ {
l_handler.RestoreContact();
l_handler.SetVelocity(l_velocity); l_handler.SetVelocity(l_velocity);
l_handler.SetAngularVelocity(Vector3.zero); l_handler.SetAngularVelocity(Vector3.zero);
} }
@ -689,6 +690,9 @@ namespace ml_prm
m_lastRagdollPosition = m_puppetReferences.hips.position; m_lastRagdollPosition = m_puppetReferences.hips.position;
m_downTime = 0f; m_downTime = 0f;
if(Settings.ImpactSounds)
SoundManager.Instance.PlaySound(SoundManager.ImpactType.Hard);
m_ragdolled = true; m_ragdolled = true;
} }
} }

View file

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
namespace ml_prm
{
static class ResourcesHandler
{
const string c_modName = "PlayerRagdollMod";
readonly static string ms_namespace = typeof(ResourcesHandler).Namespace;
static readonly List<string> ms_audioResources = new List<string>()
{
"body_medium_impact_hard1.wav",
"body_medium_impact_hard2.wav",
"body_medium_impact_hard3.wav",
"body_medium_impact_hard4.wav",
"body_medium_impact_hard5.wav",
"body_medium_impact_hard6.wav",
"body_medium_impact_soft1.wav",
"body_medium_impact_soft2.wav",
"body_medium_impact_soft3.wav",
"body_medium_impact_soft4.wav",
"body_medium_impact_soft5.wav",
"body_medium_impact_soft6.wav",
"body_medium_impact_soft7.wav"
};
public static void ExtractResources()
{
string l_dirPath = MelonLoader.Utils.MelonEnvironment.UserDataDirectory;
if(!Directory.Exists(l_dirPath))
Directory.CreateDirectory(l_dirPath);
l_dirPath = Path.Combine(l_dirPath, c_modName);
if(!Directory.Exists(l_dirPath))
Directory.CreateDirectory(l_dirPath);
foreach(string l_name in ms_audioResources)
{
string l_filePath = Path.Combine(l_dirPath, l_name);
if(!File.Exists(l_filePath))
ExtractAudioFile(l_name, l_filePath);
}
}
static void ExtractAudioFile(string p_name, string p_path)
{
Assembly l_assembly = Assembly.GetExecutingAssembly();
try
{
Stream l_resourceStream = l_assembly.GetManifestResourceStream(ms_namespace + ".resources.sounds." + p_name);
Stream l_fileStream = File.Create(p_path);
l_resourceStream.CopyTo(l_fileStream);
l_fileStream.Flush();
l_fileStream.Close();
l_resourceStream.Close();
}
catch(Exception)
{
MelonLoader.MelonLogger.Warning("Unable to write '" + p_path + "' file, problems can occur.");
}
}
}
}

View file

@ -23,7 +23,6 @@ namespace ml_prm
AngularDrag, AngularDrag,
Gravity, Gravity,
PointersReaction, PointersReaction,
IgnoreLocal,
CombatReaction, CombatReaction,
AutoRecover, AutoRecover,
RecoverDelay, RecoverDelay,
@ -35,7 +34,8 @@ namespace ml_prm
FallDamage, FallDamage,
FallLimit, FallLimit,
GestureGrab, GestureGrab,
FriendsGrab ImpactSounds,
ImpactVolume
} }
public static bool Hotkey { get; private set; } = true; public static bool Hotkey { get; private set; } = true;
@ -45,7 +45,6 @@ namespace ml_prm
public static float AngularDrag { get; private set; } = 2f; public static float AngularDrag { get; private set; } = 2f;
public static bool Gravity { get; private set; } = true; public static bool Gravity { get; private set; } = true;
public static bool PointersReaction { get; private set; } = true; public static bool PointersReaction { get; private set; } = true;
public static bool IgnoreLocal { get; private set; } = true;
public static bool CombatReaction { get; private set; } = true; public static bool CombatReaction { get; private set; } = true;
public static bool AutoRecover { get; private set; } = false; public static bool AutoRecover { get; private set; } = false;
public static float RecoverDelay { get; private set; } = 3f; public static float RecoverDelay { get; private set; } = 3f;
@ -57,8 +56,8 @@ namespace ml_prm
public static bool FallDamage { get; private set; } = true; public static bool FallDamage { get; private set; } = true;
public static float FallLimit { get; private set; } = 9.899494f; public static float FallLimit { get; private set; } = 9.899494f;
public static bool GestureGrab { get; private set; } = false; public static bool GestureGrab { get; private set; } = false;
public static bool FriendsGrab { get; private set; } = true; public static bool ImpactSounds { get; private set; } = true;
public static float GrabDistance { get; private set; } = 0.1f; public static float ImpactVolume { get; private set; } = 0.25f;
public static readonly SettingEvent<bool> OnHotkeyChanged = new SettingEvent<bool>(); public static readonly SettingEvent<bool> OnHotkeyChanged = new SettingEvent<bool>();
public static readonly SettingEvent<KeyCode> OnHotkeyKeyChanged = new SettingEvent<KeyCode>(); public static readonly SettingEvent<KeyCode> OnHotkeyKeyChanged = new SettingEvent<KeyCode>();
@ -67,7 +66,6 @@ namespace ml_prm
public static readonly SettingEvent<float> OnAngularDragChanged = new SettingEvent<float>(); public static readonly SettingEvent<float> OnAngularDragChanged = new SettingEvent<float>();
public static readonly SettingEvent<bool> OnGravityChanged = new SettingEvent<bool>(); public static readonly SettingEvent<bool> OnGravityChanged = new SettingEvent<bool>();
public static readonly SettingEvent<bool> OnPointersReactionChanged = new SettingEvent<bool>(); public static readonly SettingEvent<bool> OnPointersReactionChanged = new SettingEvent<bool>();
public static readonly SettingEvent<bool> OnIgnoreLocalChanged = new SettingEvent<bool>();
public static readonly SettingEvent<bool> OnCombatReactionChanged = new SettingEvent<bool>(); public static readonly SettingEvent<bool> OnCombatReactionChanged = new SettingEvent<bool>();
public static readonly SettingEvent<bool> OnAutoRecoverChanged = new SettingEvent<bool>(); public static readonly SettingEvent<bool> OnAutoRecoverChanged = new SettingEvent<bool>();
public static readonly SettingEvent<float> OnRecoverDelayChanged = new SettingEvent<float>(); public static readonly SettingEvent<float> OnRecoverDelayChanged = new SettingEvent<float>();
@ -79,8 +77,8 @@ namespace ml_prm
public static readonly SettingEvent<bool> OnFallDamageChanged = new SettingEvent<bool>(); public static readonly SettingEvent<bool> OnFallDamageChanged = new SettingEvent<bool>();
public static readonly SettingEvent<float> OnFallLimitChanged = new SettingEvent<float>(); public static readonly SettingEvent<float> OnFallLimitChanged = new SettingEvent<float>();
public static readonly SettingEvent<bool> OnGestureGrabChanged = new SettingEvent<bool>(); public static readonly SettingEvent<bool> OnGestureGrabChanged = new SettingEvent<bool>();
public static readonly SettingEvent<bool> OnFriendsGrabChanged = new SettingEvent<bool>(); public static readonly SettingEvent<bool> OnImpactSoundsChanged = new SettingEvent<bool>();
public static readonly SettingEvent<float> OnGrabDistanceChanged = new SettingEvent<float>(); public static readonly SettingEvent<float> OnImpactVolumeChanged = new SettingEvent<float>();
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;
@ -98,7 +96,6 @@ namespace ml_prm
ms_category.CreateEntry(ModSetting.AngularDrag.ToString(), AngularDrag, null, null, true), ms_category.CreateEntry(ModSetting.AngularDrag.ToString(), AngularDrag, null, null, true),
ms_category.CreateEntry(ModSetting.Gravity.ToString(), Gravity, null, null, true), ms_category.CreateEntry(ModSetting.Gravity.ToString(), Gravity, null, null, true),
ms_category.CreateEntry(ModSetting.PointersReaction.ToString(), PointersReaction, null, null, true), ms_category.CreateEntry(ModSetting.PointersReaction.ToString(), PointersReaction, null, null, true),
ms_category.CreateEntry(ModSetting.IgnoreLocal.ToString(), IgnoreLocal, null, null, true),
ms_category.CreateEntry(ModSetting.CombatReaction.ToString(), CombatReaction, null, null, true), ms_category.CreateEntry(ModSetting.CombatReaction.ToString(), CombatReaction, null, null, true),
ms_category.CreateEntry(ModSetting.AutoRecover.ToString(), AutoRecover, null, null, true), ms_category.CreateEntry(ModSetting.AutoRecover.ToString(), AutoRecover, null, null, true),
ms_category.CreateEntry(ModSetting.RecoverDelay.ToString(), RecoverDelay, null, null, true), ms_category.CreateEntry(ModSetting.RecoverDelay.ToString(), RecoverDelay, null, null, true),
@ -110,7 +107,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.ImpactSounds.ToString(), ImpactSounds, null, null, true),
ms_category.CreateEntry(ModSetting.ImpactVolume.ToString(), ImpactVolume, null, null, true)
}; };
ms_entries[(int)ModSetting.HotkeyKey].OnEntryValueChangedUntyped.Subscribe(OnMelonSettingSave_HotkeyKey); ms_entries[(int)ModSetting.HotkeyKey].OnEntryValueChangedUntyped.Subscribe(OnMelonSettingSave_HotkeyKey);
@ -122,7 +120,6 @@ namespace ml_prm
AngularDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.AngularDrag].BoxedValue, 0f, 50f); AngularDrag = Mathf.Clamp((float)ms_entries[(int)ModSetting.AngularDrag].BoxedValue, 0f, 50f);
Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue; Gravity = (bool)ms_entries[(int)ModSetting.Gravity].BoxedValue;
PointersReaction = (bool)ms_entries[(int)ModSetting.PointersReaction].BoxedValue; PointersReaction = (bool)ms_entries[(int)ModSetting.PointersReaction].BoxedValue;
IgnoreLocal = (bool)ms_entries[(int)ModSetting.IgnoreLocal].BoxedValue;
CombatReaction = (bool)ms_entries[(int)ModSetting.CombatReaction].BoxedValue; CombatReaction = (bool)ms_entries[(int)ModSetting.CombatReaction].BoxedValue;
AutoRecover = (bool)ms_entries[(int)ModSetting.AutoRecover].BoxedValue; AutoRecover = (bool)ms_entries[(int)ModSetting.AutoRecover].BoxedValue;
RecoverDelay = Mathf.Clamp((float)ms_entries[(int)ModSetting.RecoverDelay].BoxedValue, 1f, 10f); RecoverDelay = Mathf.Clamp((float)ms_entries[(int)ModSetting.RecoverDelay].BoxedValue, 1f, 10f);
@ -134,7 +131,8 @@ namespace ml_prm
FallDamage = (bool)ms_entries[(int)ModSetting.FallDamage].BoxedValue; FallDamage = (bool)ms_entries[(int)ModSetting.FallDamage].BoxedValue;
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; ImpactSounds = (bool)ms_entries[(int)ModSetting.ImpactSounds].BoxedValue;
ImpactVolume = Mathf.Clamp((float)ms_entries[(int)ModSetting.ImpactVolume].BoxedValue, 0f, 1f);
} }
static void OnMelonSettingSave_HotkeyKey(object p_oldValue, object p_newValue) static void OnMelonSettingSave_HotkeyKey(object p_oldValue, object p_newValue)
@ -181,13 +179,6 @@ namespace ml_prm
} }
break; break;
case ModSetting.IgnoreLocal:
{
IgnoreLocal = (bool)p_value;
OnIgnoreLocalChanged.Invoke(IgnoreLocal);
}
break;
case ModSetting.CombatReaction: case ModSetting.CombatReaction:
{ {
CombatReaction = (bool)p_value; CombatReaction = (bool)p_value;
@ -251,10 +242,10 @@ namespace ml_prm
} }
break; break;
case ModSetting.FriendsGrab: case ModSetting.ImpactSounds:
{ {
FriendsGrab = (bool)p_value; ImpactSounds = (bool)p_value;
OnFriendsGrabChanged.Invoke(FriendsGrab); OnImpactSoundsChanged.Invoke(ImpactSounds);
} }
break; break;
@ -293,6 +284,13 @@ namespace ml_prm
OnFallLimitChanged.Invoke(FallLimit); OnFallLimitChanged.Invoke(FallLimit);
} }
break; break;
case ModSetting.ImpactVolume:
{
ImpactVolume = (float)p_value;
OnImpactVolumeChanged.Invoke(ImpactVolume);
}
break;
} }
if(ms_entries != null) if(ms_entries != null)

141
ml_prm/SoundManager.cs Normal file
View file

@ -0,0 +1,141 @@
using ABI_RC.Core;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
namespace ml_prm
{
public class SoundManager
{
enum SoundType
{
ImpactHard1 = 0,
ImpactHard2,
ImpactHard3,
ImpactHard4,
ImpactHard5,
ImpactHard6,
ImpactSoft1,
ImpactSoft2,
ImpactSoft3,
ImpactSoft4,
ImpactSoft5,
ImpactSoft6,
ImpactSoft7,
Count
}
public enum ImpactType
{
Hard = 0,
Soft
}
const string c_modName = "PlayerRagdollMod";
public static SoundManager Instance { get; private set; } = null;
bool m_loaded = false;
readonly AudioClip[] m_clips = null;
AudioSource m_audioSource = null;
public SoundManager(Transform p_root)
{
m_clips = new AudioClip[(int)SoundType.Count];
for(int i = 0; i < (int)SoundType.Count; i++)
m_clips[i] = null;
GameObject l_audioSource = new GameObject("[ImpactSource]");
l_audioSource.transform.parent = p_root;
l_audioSource.transform.localPosition = Vector3.zero;
l_audioSource.transform.localRotation = Quaternion.identity;
m_audioSource = l_audioSource.AddComponent<AudioSource>();
m_audioSource.playOnAwake = false;
m_audioSource.loop = false;
m_audioSource.minDistance = 2f;
m_audioSource.maxDistance = 5f;
m_audioSource.dopplerLevel = 0f;
m_audioSource.panStereo = 0f;
m_audioSource.spatialBlend = 0f; // 2D
m_audioSource.spread = 0f;
m_audioSource.rolloffMode = AudioRolloffMode.Linear;
m_audioSource.outputAudioMixerGroup = RootLogic.Instance.mainSfx;
Instance = this;
}
~SoundManager()
{
if(Instance == this)
Instance = null;
if(m_audioSource != null)
Object.Destroy(m_audioSource);
m_audioSource = null;
}
internal void LoadSounds()
{
if(!m_loaded)
{
MelonLoader.MelonCoroutines.Start(LoadAudioClip(SoundType.ImpactHard1, Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, c_modName, "body_medium_impact_hard1.wav")));
MelonLoader.MelonCoroutines.Start(LoadAudioClip(SoundType.ImpactHard2, Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, c_modName, "body_medium_impact_hard2.wav")));
MelonLoader.MelonCoroutines.Start(LoadAudioClip(SoundType.ImpactHard3, Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, c_modName, "body_medium_impact_hard3.wav")));
MelonLoader.MelonCoroutines.Start(LoadAudioClip(SoundType.ImpactHard4, Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, c_modName, "body_medium_impact_hard4.wav")));
MelonLoader.MelonCoroutines.Start(LoadAudioClip(SoundType.ImpactHard5, Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, c_modName, "body_medium_impact_hard5.wav")));
MelonLoader.MelonCoroutines.Start(LoadAudioClip(SoundType.ImpactHard6, Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, c_modName, "body_medium_impact_hard6.wav")));
MelonLoader.MelonCoroutines.Start(LoadAudioClip(SoundType.ImpactSoft1, Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, c_modName, "body_medium_impact_soft1.wav")));
MelonLoader.MelonCoroutines.Start(LoadAudioClip(SoundType.ImpactSoft2, Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, c_modName, "body_medium_impact_soft2.wav")));
MelonLoader.MelonCoroutines.Start(LoadAudioClip(SoundType.ImpactSoft3, Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, c_modName, "body_medium_impact_soft3.wav")));
MelonLoader.MelonCoroutines.Start(LoadAudioClip(SoundType.ImpactSoft4, Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, c_modName, "body_medium_impact_soft4.wav")));
MelonLoader.MelonCoroutines.Start(LoadAudioClip(SoundType.ImpactSoft5, Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, c_modName, "body_medium_impact_soft5.wav")));
MelonLoader.MelonCoroutines.Start(LoadAudioClip(SoundType.ImpactSoft6, Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, c_modName, "body_medium_impact_soft6.wav")));
MelonLoader.MelonCoroutines.Start(LoadAudioClip(SoundType.ImpactSoft7, Path.Combine(MelonLoader.Utils.MelonEnvironment.UserDataDirectory, c_modName, "body_medium_impact_soft7.wav")));
m_loaded = true;
}
}
IEnumerator LoadAudioClip(SoundType p_type, string p_path)
{
using UnityWebRequest l_uwr = UnityWebRequestMultimedia.GetAudioClip("file://" + p_path, AudioType.WAV);
((DownloadHandlerAudioClip)l_uwr.downloadHandler).streamAudio = true;
yield return l_uwr.SendWebRequest();
if((l_uwr.result == UnityWebRequest.Result.ConnectionError) || (l_uwr.result == UnityWebRequest.Result.ProtocolError))
{
MelonLoader.MelonLogger.Warning(l_uwr.error);
yield break;
}
AudioClip l_content;
AudioClip l_clip = (l_content = DownloadHandlerAudioClip.GetContent(l_uwr));
yield return l_content;
if(!l_uwr.isDone || (l_clip == null))
yield break;
m_clips[(int)p_type] = l_clip;
}
public void PlaySound(ImpactType p_type)
{
if(m_loaded)
{
int l_index = -1;
switch(p_type)
{
case ImpactType.Hard:
l_index = (int)SoundType.ImpactHard1 + Random.Range(0, 6);
break;
case ImpactType.Soft:
l_index = (int)SoundType.ImpactSoft1 + Random.Range(0, 7);
break;
}
if((l_index != -1) && (m_clips[l_index] != null))
m_audioSource.PlayOneShot(m_clips[l_index], Settings.ImpactVolume);
}
}
}
}

View file

@ -1,13 +1,11 @@
using ABI.CCK.Components; using ABI.CCK.Components;
using ABI_RC.Core.Player;
using ABI_RC.Core.Savior;
using ABI_RC.Systems.IK;
using ABI_RC.Systems.Movement; using ABI_RC.Systems.Movement;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using UnityEngine; using UnityEngine;
using System.Linq; using System.Linq;
using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.InteractionSystem;
using NAK.Contacts;
namespace ml_prm namespace ml_prm
{ {
@ -18,6 +16,8 @@ namespace ml_prm
static readonly FieldInfo ms_influencerTouchingVolumes = typeof(PhysicsInfluencer).GetField("_touchingVolumes", BindingFlags.Instance | BindingFlags.NonPublic); static readonly FieldInfo ms_influencerTouchingVolumes = typeof(PhysicsInfluencer).GetField("_touchingVolumes", BindingFlags.Instance | BindingFlags.NonPublic);
static readonly FieldInfo ms_influencerSubmergedColliders = typeof(PhysicsInfluencer).GetField("_submergedColliders", BindingFlags.Instance | BindingFlags.NonPublic); static readonly FieldInfo ms_influencerSubmergedColliders = typeof(PhysicsInfluencer).GetField("_submergedColliders", BindingFlags.Instance | BindingFlags.NonPublic);
static readonly FieldInfo ms_lastCVRSeat = typeof(BetterBetterCharacterController).GetField("_lastCvrSeat", BindingFlags.Instance | BindingFlags.NonPublic); static readonly FieldInfo ms_lastCVRSeat = typeof(BetterBetterCharacterController).GetField("_lastCvrSeat", BindingFlags.Instance | BindingFlags.NonPublic);
static readonly FieldInfo ms_contactList = typeof(ContactManager).GetField("contactList", BindingFlags.Instance | BindingFlags.NonPublic);
static readonly FieldInfo ms_pendingRemove = typeof(ContactManager).GetField("pendingRemove", BindingFlags.Instance | BindingFlags.NonPublic);
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();
@ -35,6 +35,18 @@ namespace ml_prm
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);
public static bool IsRegistered(this ContactManager p_instance, ContactBase p_contact) => (ms_contactList?.GetValue(p_instance) as List<ContactBase>).Contains(p_contact);
public static void RestoreContact(this ContactManager p_instance, ContactBase p_contact, bool p_state)
{
if(p_instance.IsRegistered(p_contact))
(ms_pendingRemove?.GetValue(p_instance) as HashSet<int>).Remove(p_contact.ContactId);
else
p_instance.Register(p_contact);
p_instance.SetEnabled(p_contact.ContactId, p_state);
}
// Unity specific // Unity specific
public static void CopyGlobal(this Transform p_source, Transform p_target) public static void CopyGlobal(this Transform p_source, Transform p_target)
{ {

View file

@ -1,99 +1,127 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework> <TargetFramework>netstandard2.1</TargetFramework>
<Platforms>x64</Platforms> <Platforms>x64</Platforms>
<PackageId>PlayerRagdollMod</PackageId> <PackageId>PlayerRagdollMod</PackageId>
<Version>1.2.5</Version> <Version>1.2.7</Version>
<Authors>SDraw</Authors> <Authors>SDraw</Authors>
<Company>SDraw</Company> <Company>SDraw</Company>
<Product>PlayerRagdollMod</Product> <Product>PlayerRagdollMod</Product>
<AssemblyName>PlayerRagdollMod</AssemblyName> <AssemblyName>PlayerRagdollMod</AssemblyName>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebugType>embedded</DebugType> <DebugType>embedded</DebugType>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Remove="resources/person.png" /> <None Remove="resources/person.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="resources/person.png" /> <EmbeddedResource Include="resources/person.png" />
</ItemGroup> <EmbeddedResource Include="resources\sounds\body_medium_impact_hard1.wav" />
<EmbeddedResource Include="resources\sounds\body_medium_impact_hard2.wav" />
<ItemGroup> <EmbeddedResource Include="resources\sounds\body_medium_impact_hard3.wav" />
<Reference Include="0Harmony"> <EmbeddedResource Include="resources\sounds\body_medium_impact_hard4.wav" />
<HintPath>$(CVRPath)/MelonLoader/net35/0Harmony.dll</HintPath> <EmbeddedResource Include="resources\sounds\body_medium_impact_hard5.wav" />
<Private>false</Private> <EmbeddedResource Include="resources\sounds\body_medium_impact_hard6.wav" />
<SpecificVersion>false</SpecificVersion> <EmbeddedResource Include="resources\sounds\body_medium_impact_soft1.wav" />
</Reference> <EmbeddedResource Include="resources\sounds\body_medium_impact_soft2.wav" />
<Reference Include="Assembly-CSharp"> <EmbeddedResource Include="resources\sounds\body_medium_impact_soft3.wav" />
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/Assembly-CSharp.dll</HintPath> <EmbeddedResource Include="resources\sounds\body_medium_impact_soft4.wav" />
<Private>false</Private> <EmbeddedResource Include="resources\sounds\body_medium_impact_soft5.wav" />
<SpecificVersion>false</SpecificVersion> <EmbeddedResource Include="resources\sounds\body_medium_impact_soft6.wav" />
</Reference> <EmbeddedResource Include="resources\sounds\body_medium_impact_soft7.wav" />
<Reference Include="Assembly-CSharp-firstpass"> </ItemGroup>
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/Assembly-CSharp-firstpass.dll</HintPath>
<Private>false</Private> <ItemGroup>
<SpecificVersion>false</SpecificVersion> <Reference Include="0Harmony">
</Reference> <HintPath>$(CVRPath)/MelonLoader/net35/0Harmony.dll</HintPath>
<Reference Include="BTKUILib"> <Private>false</Private>
<HintPath>$(CVRPath)/Mods/BTKUILib.dll</HintPath> <SpecificVersion>false</SpecificVersion>
<Private>false</Private> </Reference>
<SpecificVersion>false</SpecificVersion> <Reference Include="Assembly-CSharp">
</Reference> <HintPath>$(CVRPath)/ChilloutVR_Data/Managed/Assembly-CSharp.dll</HintPath>
<Private>false</Private>
<SpecificVersion>false</SpecificVersion>
</Reference>
<Reference Include="Assembly-CSharp-firstpass">
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/Assembly-CSharp-firstpass.dll</HintPath>
<Private>false</Private>
<SpecificVersion>false</SpecificVersion>
</Reference>
<Reference Include="BTKUILib">
<HintPath>$(CVRPath)/Mods/BTKUILib.dll</HintPath>
<Private>false</Private>
<SpecificVersion>false</SpecificVersion>
</Reference>
<Reference Include="ECM2"> <Reference Include="ECM2">
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/ECM2.dll</HintPath> <HintPath>$(CVRPath)/ChilloutVR_Data/Managed/ECM2.dll</HintPath>
<SpecificVersion>false</SpecificVersion> <SpecificVersion>false</SpecificVersion>
<Private>false</Private> <Private>false</Private>
</Reference> </Reference>
<Reference Include="MelonLoader"> <Reference Include="MelonLoader">
<HintPath>$(CVRPath)/MelonLoader/net35/MelonLoader.dll</HintPath> <HintPath>$(CVRPath)/MelonLoader/net35/MelonLoader.dll</HintPath>
<Private>false</Private> <Private>false</Private>
<SpecificVersion>false</SpecificVersion> <SpecificVersion>false</SpecificVersion>
</Reference> </Reference>
<Reference Include="UnityEngine"> <Reference Include="UnityEngine">
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.dll</HintPath> <HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.dll</HintPath>
<Private>false</Private> <Private>false</Private>
<SpecificVersion>false</SpecificVersion> <SpecificVersion>false</SpecificVersion>
</Reference> </Reference>
<Reference Include="UnityEngine.AnimationModule"> <Reference Include="UnityEngine.AnimationModule">
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.AnimationModule.dll</HintPath> <HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.AnimationModule.dll</HintPath>
<Private>false</Private> <Private>false</Private>
<SpecificVersion>false</SpecificVersion> <SpecificVersion>false</SpecificVersion>
</Reference> </Reference>
<Reference Include="UnityEngine.ClothModule"> <Reference Include="UnityEngine.AudioModule">
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.ClothModule.dll</HintPath> <HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AudioModule.dll</HintPath>
<Private>false</Private> <SpecificVersion>false</SpecificVersion>
<SpecificVersion>false</SpecificVersion> <Private>false</Private>
</Reference> </Reference>
<Reference Include="UnityEngine.CoreModule"> <Reference Include="UnityEngine.ClothModule">
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.CoreModule.dll</HintPath> <HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.ClothModule.dll</HintPath>
<Private>false</Private> <Private>false</Private>
<SpecificVersion>false</SpecificVersion> <SpecificVersion>false</SpecificVersion>
</Reference> </Reference>
<Reference Include="UnityEngine.InputLegacyModule"> <Reference Include="UnityEngine.CoreModule">
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.InputLegacyModule.dll</HintPath> <HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.CoreModule.dll</HintPath>
<Private>false</Private> <Private>false</Private>
<SpecificVersion>false</SpecificVersion> <SpecificVersion>false</SpecificVersion>
</Reference> </Reference>
<Reference Include="UnityEngine.PhysicsModule"> <Reference Include="UnityEngine.InputLegacyModule">
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.PhysicsModule.dll</HintPath> <HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.InputLegacyModule.dll</HintPath>
<Private>false</Private> <Private>false</Private>
<SpecificVersion>false</SpecificVersion> <SpecificVersion>false</SpecificVersion>
</Reference> </Reference>
<Reference Include="UnityEngine.ParticleSystemModule"> <Reference Include="UnityEngine.PhysicsModule">
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.ParticleSystemModule.dll</HintPath> <HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.PhysicsModule.dll</HintPath>
<Private>false</Private> <Private>false</Private>
<SpecificVersion>false</SpecificVersion> <SpecificVersion>false</SpecificVersion>
</Reference> </Reference>
</ItemGroup> <Reference Include="UnityEngine.ParticleSystemModule">
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.ParticleSystemModule.dll</HintPath>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Private>false</Private>
<Exec Command="copy /y &quot;$(TargetPath)&quot; &quot;$(CVRPath)/Mods/&quot;" /> <SpecificVersion>false</SpecificVersion>
</Target> </Reference>
<Reference Include="UnityEngine.UnityWebRequestAudioModule">
</Project> <HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.UnityWebRequestAudioModule.dll</HintPath>
<Private>false</Private>
<SpecificVersion>false</SpecificVersion>
</Reference>
<Reference Include="UnityEngine.UnityWebRequestModule">
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.UnityWebRequestModule.dll</HintPath>
<Private>false</Private>
<SpecificVersion>false</SpecificVersion>
</Reference>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="copy /y &quot;$(TargetPath)&quot; &quot;$(CVRPath)/Mods/&quot;" />
</Target>
</Project>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -11,7 +11,7 @@ namespace ml_vpc
public override void OnInitializeMelon() public override void OnInitializeMelon()
{ {
HarmonyInstance.Patch(typeof(YoutubeDl).GetMethod("GetVideoMetaDataAsync", BindingFlags.NonPublic | BindingFlags.Static), HarmonyInstance.Patch(typeof(YoutubeDl).GetMethod("GetVideoMetaDataAsync", BindingFlags.Public | BindingFlags.Static),
new HarmonyLib.HarmonyMethod(typeof(VideoPlayerCookies).GetMethod(nameof(OnGetYoutubeVideoMetaData_Prefix), BindingFlags.NonPublic | BindingFlags.Static)) new HarmonyLib.HarmonyMethod(typeof(VideoPlayerCookies).GetMethod(nameof(OnGetYoutubeVideoMetaData_Prefix), BindingFlags.NonPublic | BindingFlags.Static))
); );
@ -23,7 +23,7 @@ namespace ml_vpc
Settings.Init(); Settings.Init();
} }
static void OnGetYoutubeVideoMetaData_Prefix(ref string parameter) static void OnGetYoutubeVideoMetaData_Prefix(ref string youtubeUrl, ref string existingParameters)
{ {
try try
{ {
@ -34,36 +34,36 @@ namespace ml_vpc
{ {
case Settings.CookieMode.File: case Settings.CookieMode.File:
if (File.Exists(ms_cookiesPath)) if (File.Exists(ms_cookiesPath))
parameter += string.Format(" --cookies \"{0}\"", ms_cookiesPath); existingParameters += string.Format("--cookies \"{0}\"", ms_cookiesPath);
else else
MelonLoader.MelonLogger.Warning("Cookies file not found in: '" + ms_cookiesPath + "'"); MelonLoader.MelonLogger.Warning("Cookies file not found in: '" + ms_cookiesPath + "'");
break; break;
case Settings.CookieMode.BrowserFirefox: case Settings.CookieMode.BrowserFirefox:
parameter += " --cookies-from-browser firefox"; existingParameters += "--cookies-from-browser firefox";
break; break;
case Settings.CookieMode.BrowserBrave: case Settings.CookieMode.BrowserBrave:
parameter += " --cookies-from-browser brave"; existingParameters += "--cookies-from-browser brave";
break; break;
case Settings.CookieMode.BrowserChrome: case Settings.CookieMode.BrowserChrome:
parameter += " --cookies-from-browser chrome"; existingParameters += "--cookies-from-browser chrome";
break; break;
case Settings.CookieMode.BrowserChromium: case Settings.CookieMode.BrowserChromium:
parameter += " --cookies-from-browser chromium"; existingParameters += "--cookies-from-browser chromium";
break; break;
case Settings.CookieMode.BrowserEdge: case Settings.CookieMode.BrowserEdge:
parameter += " --cookies-from-browser edge"; existingParameters += "--cookies-from-browser edge";
break; break;
case Settings.CookieMode.BrowserOpera: case Settings.CookieMode.BrowserOpera:
parameter += " --cookies-from-browser opera"; existingParameters += "--cookies-from-browser opera";
break; break;
case Settings.CookieMode.BrowserSafari: case Settings.CookieMode.BrowserSafari:
parameter += " --cookies-from-browser safari"; existingParameters += "--cookies-from-browser safari";
break; break;
case Settings.CookieMode.BrowserVivaldi: case Settings.CookieMode.BrowserVivaldi:
parameter += " --cookies-from-browser vivaldi"; existingParameters += "--cookies-from-browser vivaldi";
break; break;
case Settings.CookieMode.BrowserWhale: case Settings.CookieMode.BrowserWhale:
parameter += " --cookies-from-browser whale"; existingParameters += "--cookies-from-browser whale";
break; break;
} }
} }

View file

@ -1,5 +1,5 @@
[assembly: MelonLoader.MelonInfo(typeof(ml_vpc.VideoPlayerCookies), "VideoPlayerCookies", "1.0.4", "SDraw", "https://github.com/SDraw/ml_mods_cvr")] [assembly: MelonLoader.MelonInfo(typeof(ml_vpc.VideoPlayerCookies), "VideoPlayerCookies", "1.0.5", "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)]
[assembly: MelonLoader.MelonAdditionalCredits("kafeijao")] [assembly: MelonLoader.MelonAdditionalCredits("kafeijao, Slime")]

View file

@ -27,6 +27,19 @@ Available mod's settings in `Settings - General - Video Player Cookies`:
* Firefox-based browsers: [cookies.txt](https://addons.mozilla.org/en-US/firefox/addon/cookies-txt) extension * Firefox-based browsers: [cookies.txt](https://addons.mozilla.org/en-US/firefox/addon/cookies-txt) extension
* Save result as file named `cookies.txt` in `<game_folder>/UserData` folder * Save result as file named `cookies.txt` in `<game_folder>/UserData` folder
# How to make it work on Linux (Tested on CachyOS / Arch with Firefox)
Because of Linux / Proton, the cookies.txt doesn't seem to work well, instead it's better to use browser mode, the following tutorial explains how to set it up (tested using Firefox)
* Go to the mod settings and select your browser
* Put a video and wait for it to fail, then look at the logs
* It should tell you an error because it can't find your cookies in a path, for Firefox it looks like `AppData/Local/Packages/Mozilla.Firefox_n80bbvh6b1yt2/LocalCache/Roaming/Mozilla/Firefox/Profiles/`
* Go to AppData in the drive_c of the game, on Arch this is usually located at `/home/[USER]/.local/share/Steam/steamapps/compatdata/661130/pfx/drive_c/users/steamuser/Appdata`
* Create all the folders that it requires until the last one, for Firefox this means the folders `Packages`, `Mozilla.Firefox_n80bbvh6b1yt2`, `LocalCache`, `Roaming`, `Mozilla` and `Firefox` but don't create the last one (`Profiles`) yet unless you don't intend to use your real browser
* Because your cookies could change or expire, instead of giving it the files once, we'll use a symlink to the real firefox on your machine. This is completely up to you and you could just copy the files or get them from somewhere else
* Now you can create a link that points to the folder of your browser on Linux. For Firefox, this is the `Profiles` folder that should point to `/home/[USER]/.mozilla/firefox/`
* If you followed all the steps, the next video you put should successfully get the cookies from your browser
# Notes # Notes
* After first use yt-dlp will remove unnecessary cookies from file automatically. * After first use yt-dlp will remove unnecessary cookies from file automatically.
* Cookies contain private information and access to your YouTube account, **do not share them to anyone**. * Cookies contain private information and access to your YouTube account, **do not share them to anyone**.

View file

@ -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.4</Version> <Version>1.0.5</Version>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">