mirror of
https://github.com/SDraw/ml_mods_cvr.git
synced 2026-05-04 01:07:02 +00:00
Compare commits
7 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c4fbb1731 | ||
|
|
812b930bed | ||
|
|
c25eaaf754 | ||
|
|
d8bb5881fc | ||
|
|
e04724ed9d | ||
|
|
2a06001100 | ||
|
|
15de34c0bd |
27 changed files with 430 additions and 114 deletions
|
|
@ -5,12 +5,14 @@ namespace ml_prm
|
|||
public class PlayerRagdollMod : MelonLoader.MelonMod
|
||||
{
|
||||
RagdollController m_controller = null;
|
||||
SoundManager m_soundManager = null;
|
||||
|
||||
public override void OnInitializeMelon()
|
||||
{
|
||||
Settings.Init();
|
||||
GameEvents.Init(HarmonyInstance);
|
||||
WorldManager.Init();
|
||||
ResourcesHandler.ExtractResources();
|
||||
}
|
||||
|
||||
public override void OnLateInitializeMelon()
|
||||
|
|
@ -26,6 +28,8 @@ namespace ml_prm
|
|||
yield return null;
|
||||
|
||||
m_controller = new UnityEngine.GameObject("[PlayerRagdollMod]").AddComponent<RagdollController>();
|
||||
m_soundManager = new SoundManager(m_controller.transform);
|
||||
m_soundManager.LoadSounds();
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator WaitForWhitelist()
|
||||
|
|
@ -40,6 +44,8 @@ namespace ml_prm
|
|||
{
|
||||
WorldManager.DeInit();
|
||||
|
||||
m_soundManager = null;
|
||||
|
||||
if(m_controller != null)
|
||||
UnityEngine.Object.Destroy(m_controller.gameObject);
|
||||
m_controller = null;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ namespace ml_prm
|
|||
AngularDrag,
|
||||
RecoverDelay,
|
||||
FallLimit,
|
||||
GestureGrab
|
||||
GestureGrab,
|
||||
ImpactSounds,
|
||||
ImpactVolume
|
||||
}
|
||||
|
||||
const string c_ragdollKeyTooltip = "Switch ragdoll mode with '{0}' key";
|
||||
|
|
@ -59,11 +61,13 @@ namespace ml_prm
|
|||
static ToggleButton ms_buoyancyToggle = null;
|
||||
static ToggleButton ms_fallDamageToggle = null;
|
||||
static ToggleButton ms_gestureGrabToggle = null;
|
||||
static ToggleButton ms_impactSoundsToggle = 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_impactVolumeSlider = null;
|
||||
static Button ms_resetButton = null;
|
||||
|
||||
internal static void Init()
|
||||
|
|
@ -117,6 +121,9 @@ namespace ml_prm
|
|||
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_impactSoundsToggle = ms_category.AddToggle("Impact sounds", "Enable collision sound effects of ragdolled body parts", Settings.ImpactSounds);
|
||||
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.OnValueUpdated += (value) => OnSliderUpdate(UiIndex.VelocityMultiplier, value);
|
||||
|
||||
|
|
@ -133,6 +140,9 @@ namespace ml_prm
|
|||
ms_fallLimitSlider.SliderTooltip = string.Format(c_fallLimitTooltip, GetDropHeight(Settings.FallLimit));
|
||||
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.OnPress += Reset;
|
||||
}
|
||||
|
|
@ -202,6 +212,10 @@ namespace ml_prm
|
|||
case UiIndex.GestureGrab:
|
||||
Settings.SetSetting(Settings.ModSetting.GestureGrab, p_state);
|
||||
break;
|
||||
|
||||
case UiIndex.ImpactSounds:
|
||||
Settings.SetSetting(Settings.ModSetting.ImpactSounds, p_state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
|
|
@ -238,6 +252,10 @@ namespace ml_prm
|
|||
ms_fallLimitSlider.SliderTooltip = string.Format(c_fallLimitTooltip, GetDropHeight(p_value));
|
||||
}
|
||||
break;
|
||||
|
||||
case UiIndex.ImpactVolume:
|
||||
Settings.SetSetting(Settings.ModSetting.ImpactVolume, p_value * 0.01f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
|
|
@ -284,6 +302,9 @@ namespace ml_prm
|
|||
OnToggleUpdate(UiIndex.GestureGrab, false);
|
||||
ms_gestureGrabToggle.ToggleValue = false;
|
||||
|
||||
OnToggleUpdate(UiIndex.ImpactSounds, true);
|
||||
ms_impactSoundsToggle.ToggleValue = true;
|
||||
|
||||
OnSliderUpdate(UiIndex.VelocityMultiplier, 2f);
|
||||
ms_velocityMultiplierSlider.SetSliderValue(2f);
|
||||
|
||||
|
|
@ -298,6 +319,9 @@ namespace ml_prm
|
|||
|
||||
OnSliderUpdate(UiIndex.FallLimit, 9.899494f);
|
||||
ms_fallLimitSlider.SetSliderValue(9.899494f);
|
||||
|
||||
OnSliderUpdate(UiIndex.ImpactVolume, 100f);
|
||||
ms_impactVolumeSlider.SetSliderValue(25f);
|
||||
}
|
||||
|
||||
static void OnHotkeyKeyChanged(UnityEngine.KeyCode p_keyCode)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.2.6", "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.MelonPriority(2)]
|
||||
[assembly: MelonLoader.MelonAdditionalDependencies("BTKUILib")]
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
* 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.
|
||||
* **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.
|
||||
* **Auto recover:** enables automatic recovering after specific time delay; `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.
|
||||
* 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/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.
|
||||
* **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.
|
||||
* Note: Limited according to world's fly multiplier.
|
||||
* 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.
|
||||
* **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.
|
||||
* **Impact volume:** collision sounds volume of ragdolled body parts; `100.0` by default.
|
||||
* **Reset settings:** resets mod settings to default.
|
||||
|
||||
Optional mod's settings in [UIExpansionKit](https://github.com/ddakebono/ChilloutMods):
|
||||
|
|
|
|||
|
|
@ -100,6 +100,15 @@ namespace ml_prm
|
|||
Detach();
|
||||
}
|
||||
|
||||
void OnCollisionEnter(Collision p_col)
|
||||
{
|
||||
if(Settings.ImpactSounds && m_ready && !m_rigidBody.isKinematic && (p_col.gameObject.layer != CVRLayers.PlayerClone))
|
||||
{
|
||||
if(p_col.impulse.magnitude > 5f)
|
||||
SoundManager.Instance.PlaySound(SoundManager.ImpactType.Soft);
|
||||
}
|
||||
}
|
||||
|
||||
void OnContactEnter(ContactCollisionInfo p_col)
|
||||
{
|
||||
if(m_ready && (RagdollController.Instance != null) && ContactManager.Exists)
|
||||
|
|
|
|||
|
|
@ -690,6 +690,9 @@ namespace ml_prm
|
|||
m_lastRagdollPosition = m_puppetReferences.hips.position;
|
||||
m_downTime = 0f;
|
||||
|
||||
if(Settings.ImpactSounds)
|
||||
SoundManager.Instance.PlaySound(SoundManager.ImpactType.Hard);
|
||||
|
||||
m_ragdolled = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
67
ml_prm/ResourcesHandler.cs
Normal file
67
ml_prm/ResourcesHandler.cs
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -33,7 +33,9 @@ namespace ml_prm
|
|||
Buoyancy,
|
||||
FallDamage,
|
||||
FallLimit,
|
||||
GestureGrab
|
||||
GestureGrab,
|
||||
ImpactSounds,
|
||||
ImpactVolume
|
||||
}
|
||||
|
||||
public static bool Hotkey { get; private set; } = true;
|
||||
|
|
@ -54,6 +56,8 @@ namespace ml_prm
|
|||
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 ImpactSounds { get; private set; } = true;
|
||||
public static float ImpactVolume { get; private set; } = 0.25f;
|
||||
|
||||
public static readonly SettingEvent<bool> OnHotkeyChanged = new SettingEvent<bool>();
|
||||
public static readonly SettingEvent<KeyCode> OnHotkeyKeyChanged = new SettingEvent<KeyCode>();
|
||||
|
|
@ -73,6 +77,8 @@ namespace ml_prm
|
|||
public static readonly SettingEvent<bool> OnFallDamageChanged = new SettingEvent<bool>();
|
||||
public static readonly SettingEvent<float> OnFallLimitChanged = new SettingEvent<float>();
|
||||
public static readonly SettingEvent<bool> OnGestureGrabChanged = new SettingEvent<bool>();
|
||||
public static readonly SettingEvent<bool> OnImpactSoundsChanged = new SettingEvent<bool>();
|
||||
public static readonly SettingEvent<float> OnImpactVolumeChanged = new SettingEvent<float>();
|
||||
|
||||
static MelonLoader.MelonPreferences_Category ms_category = null;
|
||||
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null;
|
||||
|
|
@ -100,7 +106,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.GestureGrab.ToString(), GestureGrab, 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);
|
||||
|
|
@ -123,6 +131,8 @@ namespace ml_prm
|
|||
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;
|
||||
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)
|
||||
|
|
@ -232,6 +242,13 @@ namespace ml_prm
|
|||
}
|
||||
break;
|
||||
|
||||
case ModSetting.ImpactSounds:
|
||||
{
|
||||
ImpactSounds = (bool)p_value;
|
||||
OnImpactSoundsChanged.Invoke(ImpactSounds);
|
||||
}
|
||||
break;
|
||||
|
||||
// Floats
|
||||
case ModSetting.VelocityMultiplier:
|
||||
{
|
||||
|
|
@ -267,6 +284,13 @@ namespace ml_prm
|
|||
OnFallLimitChanged.Invoke(FallLimit);
|
||||
}
|
||||
break;
|
||||
|
||||
case ModSetting.ImpactVolume:
|
||||
{
|
||||
ImpactVolume = (float)p_value;
|
||||
OnImpactVolumeChanged.Invoke(ImpactVolume);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(ms_entries != null)
|
||||
|
|
|
|||
141
ml_prm/SoundManager.cs
Normal file
141
ml_prm/SoundManager.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<PackageId>PlayerRagdollMod</PackageId>
|
||||
<Version>1.2.6</Version>
|
||||
<Version>1.2.7</Version>
|
||||
<Authors>SDraw</Authors>
|
||||
<Company>SDraw</Company>
|
||||
<Product>PlayerRagdollMod</Product>
|
||||
|
|
@ -22,6 +22,19 @@
|
|||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="resources/person.png" />
|
||||
<EmbeddedResource Include="resources\sounds\body_medium_impact_hard1.wav" />
|
||||
<EmbeddedResource Include="resources\sounds\body_medium_impact_hard2.wav" />
|
||||
<EmbeddedResource Include="resources\sounds\body_medium_impact_hard3.wav" />
|
||||
<EmbeddedResource Include="resources\sounds\body_medium_impact_hard4.wav" />
|
||||
<EmbeddedResource Include="resources\sounds\body_medium_impact_hard5.wav" />
|
||||
<EmbeddedResource Include="resources\sounds\body_medium_impact_hard6.wav" />
|
||||
<EmbeddedResource Include="resources\sounds\body_medium_impact_soft1.wav" />
|
||||
<EmbeddedResource Include="resources\sounds\body_medium_impact_soft2.wav" />
|
||||
<EmbeddedResource Include="resources\sounds\body_medium_impact_soft3.wav" />
|
||||
<EmbeddedResource Include="resources\sounds\body_medium_impact_soft4.wav" />
|
||||
<EmbeddedResource Include="resources\sounds\body_medium_impact_soft5.wav" />
|
||||
<EmbeddedResource Include="resources\sounds\body_medium_impact_soft6.wav" />
|
||||
<EmbeddedResource Include="resources\sounds\body_medium_impact_soft7.wav" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -65,6 +78,11 @@
|
|||
<Private>false</Private>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.AudioModule">
|
||||
<HintPath>D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AudioModule.dll</HintPath>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.ClothModule">
|
||||
<HintPath>$(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.ClothModule.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
|
|
@ -90,6 +108,16 @@
|
|||
<Private>false</Private>
|
||||
<SpecificVersion>false</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.UnityWebRequestAudioModule">
|
||||
<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">
|
||||
|
|
|
|||
BIN
ml_prm/resources/sounds/body_medium_impact_hard1.wav
Normal file
BIN
ml_prm/resources/sounds/body_medium_impact_hard1.wav
Normal file
Binary file not shown.
BIN
ml_prm/resources/sounds/body_medium_impact_hard2.wav
Normal file
BIN
ml_prm/resources/sounds/body_medium_impact_hard2.wav
Normal file
Binary file not shown.
BIN
ml_prm/resources/sounds/body_medium_impact_hard3.wav
Normal file
BIN
ml_prm/resources/sounds/body_medium_impact_hard3.wav
Normal file
Binary file not shown.
BIN
ml_prm/resources/sounds/body_medium_impact_hard4.wav
Normal file
BIN
ml_prm/resources/sounds/body_medium_impact_hard4.wav
Normal file
Binary file not shown.
BIN
ml_prm/resources/sounds/body_medium_impact_hard5.wav
Normal file
BIN
ml_prm/resources/sounds/body_medium_impact_hard5.wav
Normal file
Binary file not shown.
BIN
ml_prm/resources/sounds/body_medium_impact_hard6.wav
Normal file
BIN
ml_prm/resources/sounds/body_medium_impact_hard6.wav
Normal file
Binary file not shown.
BIN
ml_prm/resources/sounds/body_medium_impact_soft1.wav
Normal file
BIN
ml_prm/resources/sounds/body_medium_impact_soft1.wav
Normal file
Binary file not shown.
BIN
ml_prm/resources/sounds/body_medium_impact_soft2.wav
Normal file
BIN
ml_prm/resources/sounds/body_medium_impact_soft2.wav
Normal file
Binary file not shown.
BIN
ml_prm/resources/sounds/body_medium_impact_soft3.wav
Normal file
BIN
ml_prm/resources/sounds/body_medium_impact_soft3.wav
Normal file
Binary file not shown.
BIN
ml_prm/resources/sounds/body_medium_impact_soft4.wav
Normal file
BIN
ml_prm/resources/sounds/body_medium_impact_soft4.wav
Normal file
Binary file not shown.
BIN
ml_prm/resources/sounds/body_medium_impact_soft5.wav
Normal file
BIN
ml_prm/resources/sounds/body_medium_impact_soft5.wav
Normal file
Binary file not shown.
BIN
ml_prm/resources/sounds/body_medium_impact_soft6.wav
Normal file
BIN
ml_prm/resources/sounds/body_medium_impact_soft6.wav
Normal file
Binary file not shown.
BIN
ml_prm/resources/sounds/body_medium_impact_soft7.wav
Normal file
BIN
ml_prm/resources/sounds/body_medium_impact_soft7.wav
Normal file
Binary file not shown.
|
|
@ -11,7 +11,7 @@ namespace ml_vpc
|
|||
|
||||
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))
|
||||
);
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ namespace ml_vpc
|
|||
Settings.Init();
|
||||
}
|
||||
|
||||
static void OnGetYoutubeVideoMetaData_Prefix(ref string parameter)
|
||||
static void OnGetYoutubeVideoMetaData_Prefix(ref string youtubeUrl, ref string existingParameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -34,36 +34,36 @@ namespace ml_vpc
|
|||
{
|
||||
case Settings.CookieMode.File:
|
||||
if (File.Exists(ms_cookiesPath))
|
||||
parameter += string.Format(" --cookies \"{0}\"", ms_cookiesPath);
|
||||
existingParameters += string.Format("--cookies \"{0}\"", ms_cookiesPath);
|
||||
else
|
||||
MelonLoader.MelonLogger.Warning("Cookies file not found in: '" + ms_cookiesPath + "'");
|
||||
break;
|
||||
case Settings.CookieMode.BrowserFirefox:
|
||||
parameter += " --cookies-from-browser firefox";
|
||||
existingParameters += "--cookies-from-browser firefox";
|
||||
break;
|
||||
case Settings.CookieMode.BrowserBrave:
|
||||
parameter += " --cookies-from-browser brave";
|
||||
existingParameters += "--cookies-from-browser brave";
|
||||
break;
|
||||
case Settings.CookieMode.BrowserChrome:
|
||||
parameter += " --cookies-from-browser chrome";
|
||||
existingParameters += "--cookies-from-browser chrome";
|
||||
break;
|
||||
case Settings.CookieMode.BrowserChromium:
|
||||
parameter += " --cookies-from-browser chromium";
|
||||
existingParameters += "--cookies-from-browser chromium";
|
||||
break;
|
||||
case Settings.CookieMode.BrowserEdge:
|
||||
parameter += " --cookies-from-browser edge";
|
||||
existingParameters += "--cookies-from-browser edge";
|
||||
break;
|
||||
case Settings.CookieMode.BrowserOpera:
|
||||
parameter += " --cookies-from-browser opera";
|
||||
existingParameters += "--cookies-from-browser opera";
|
||||
break;
|
||||
case Settings.CookieMode.BrowserSafari:
|
||||
parameter += " --cookies-from-browser safari";
|
||||
existingParameters += "--cookies-from-browser safari";
|
||||
break;
|
||||
case Settings.CookieMode.BrowserVivaldi:
|
||||
parameter += " --cookies-from-browser vivaldi";
|
||||
existingParameters += "--cookies-from-browser vivaldi";
|
||||
break;
|
||||
case Settings.CookieMode.BrowserWhale:
|
||||
parameter += " --cookies-from-browser whale";
|
||||
existingParameters += "--cookies-from-browser whale";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
|
||||
[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
|
||||
[assembly: MelonLoader.MelonAdditionalCredits("kafeijao")]
|
||||
[assembly: MelonLoader.MelonAdditionalCredits("kafeijao, Slime")]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* 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
|
||||
* 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**.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<AssemblyName>VideoPlayerCookies</AssemblyName>
|
||||
<Authors>SDraw</Authors>
|
||||
<Company>SDraw</Company>
|
||||
<Version>1.0.4</Version>
|
||||
<Version>1.0.5</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue