diff --git a/ml_prm/Main.cs b/ml_prm/Main.cs index 8a7bc12..75709ac 100644 --- a/ml_prm/Main.cs +++ b/ml_prm/Main.cs @@ -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(); + 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; diff --git a/ml_prm/ModUi.cs b/ml_prm/ModUi.cs index bd366c2..c7c11d7 100644 --- a/ml_prm/ModUi.cs +++ b/ml_prm/ModUi.cs @@ -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

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(100f); } static void OnHotkeyKeyChanged(UnityEngine.KeyCode p_keyCode) diff --git a/ml_prm/Properties/AssemblyInfo.cs b/ml_prm/Properties/AssemblyInfo.cs index 22daa45..e968e2d 100644 --- a/ml_prm/Properties/AssemblyInfo.cs +++ b/ml_prm/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -[assembly: MelonLoader.MelonInfo(typeof(ml_prm.PlayerRagdollMod), "PlayerRagdollMod", "1.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")] diff --git a/ml_prm/README.md b/ml_prm/README.md index ffede43..ef09eb1 100644 --- a/ml_prm/README.md +++ b/ml_prm/README.md @@ -31,6 +31,8 @@ Optional mod's settings page with [BTKUILib](https://github.com/BTK-Development/ * **Fall damage:** enables ragdoll when falling from specific height; `true` 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. +* **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. @@ -39,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): diff --git a/ml_prm/RagdollBodypartHandler.cs b/ml_prm/RagdollBodypartHandler.cs index 30d196f..d98f681 100644 --- a/ml_prm/RagdollBodypartHandler.cs +++ b/ml_prm/RagdollBodypartHandler.cs @@ -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) diff --git a/ml_prm/RagdollController.cs b/ml_prm/RagdollController.cs index 8581275..e0b073c 100644 --- a/ml_prm/RagdollController.cs +++ b/ml_prm/RagdollController.cs @@ -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; } } diff --git a/ml_prm/ResourcesHandler.cs b/ml_prm/ResourcesHandler.cs new file mode 100644 index 0000000..ba44ef3 --- /dev/null +++ b/ml_prm/ResourcesHandler.cs @@ -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 ms_audioResources = new List() + { + "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."); + } + } + } +} diff --git a/ml_prm/Settings.cs b/ml_prm/Settings.cs index e084f86..80aafbb 100644 --- a/ml_prm/Settings.cs +++ b/ml_prm/Settings.cs @@ -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; } = 1f; public static readonly SettingEvent OnHotkeyChanged = new SettingEvent(); public static readonly SettingEvent OnHotkeyKeyChanged = new SettingEvent(); @@ -73,6 +77,8 @@ namespace ml_prm public static readonly SettingEvent OnFallDamageChanged = new SettingEvent(); public static readonly SettingEvent OnFallLimitChanged = new SettingEvent(); public static readonly SettingEvent OnGestureGrabChanged = new SettingEvent(); + public static readonly SettingEvent OnImpactSoundsChanged = new SettingEvent(); + public static readonly SettingEvent OnImpactVolumeChanged = new SettingEvent(); static MelonLoader.MelonPreferences_Category ms_category = null; static List 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) diff --git a/ml_prm/SoundManager.cs b/ml_prm/SoundManager.cs new file mode 100644 index 0000000..40df8b1 --- /dev/null +++ b/ml_prm/SoundManager.cs @@ -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(); + 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); + } + } + } +} diff --git a/ml_prm/ml_prm.csproj b/ml_prm/ml_prm.csproj index bc52523..2969588 100644 --- a/ml_prm/ml_prm.csproj +++ b/ml_prm/ml_prm.csproj @@ -1,99 +1,127 @@ - - - - netstandard2.1 - x64 - PlayerRagdollMod - 1.2.6 - SDraw - SDraw - PlayerRagdollMod - PlayerRagdollMod - - + + + + netstandard2.1 + x64 + PlayerRagdollMod + 1.2.7 + SDraw + SDraw + PlayerRagdollMod + PlayerRagdollMod + + embedded true - - - - - - - - - - - - - $(CVRPath)/MelonLoader/net35/0Harmony.dll - false - false - - - $(CVRPath)/ChilloutVR_Data/Managed/Assembly-CSharp.dll - false - false - - - $(CVRPath)/ChilloutVR_Data/Managed/Assembly-CSharp-firstpass.dll - false - false - - - $(CVRPath)/Mods/BTKUILib.dll - false - false - + + + + + + + + + + + + + + + + + + + + + + + + + + $(CVRPath)/MelonLoader/net35/0Harmony.dll + false + false + + + $(CVRPath)/ChilloutVR_Data/Managed/Assembly-CSharp.dll + false + false + + + $(CVRPath)/ChilloutVR_Data/Managed/Assembly-CSharp-firstpass.dll + false + false + + + $(CVRPath)/Mods/BTKUILib.dll + false + false + $(CVRPath)/ChilloutVR_Data/Managed/ECM2.dll false false - - - $(CVRPath)/MelonLoader/net35/MelonLoader.dll - false - false - - - $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.dll - false - false - - - $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.AnimationModule.dll - false - false - - - $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.ClothModule.dll - false - false - - - $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.CoreModule.dll - false - false - - - $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.InputLegacyModule.dll - false - false - - - $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.PhysicsModule.dll - false - false - - - $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.ParticleSystemModule.dll - false - false - - - - - - - - + + + $(CVRPath)/MelonLoader/net35/MelonLoader.dll + false + false + + + $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.dll + false + false + + + $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.AnimationModule.dll + false + false + + + D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.AudioModule.dll + false + false + + + $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.ClothModule.dll + false + false + + + $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.CoreModule.dll + false + false + + + $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.InputLegacyModule.dll + false + false + + + $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.PhysicsModule.dll + false + false + + + $(CVRPath)/ChilloutVR_Data/Managed/UnityEngine.ParticleSystemModule.dll + false + false + + + D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.UnityWebRequestAudioModule.dll + false + false + + + D:\Games\Steam\steamapps\common\ChilloutVR\ChilloutVR_Data\Managed\UnityEngine.UnityWebRequestModule.dll + false + false + + + + + + + + diff --git a/ml_prm/resources/sounds/body_medium_impact_hard1.wav b/ml_prm/resources/sounds/body_medium_impact_hard1.wav new file mode 100644 index 0000000..adebd1e Binary files /dev/null and b/ml_prm/resources/sounds/body_medium_impact_hard1.wav differ diff --git a/ml_prm/resources/sounds/body_medium_impact_hard2.wav b/ml_prm/resources/sounds/body_medium_impact_hard2.wav new file mode 100644 index 0000000..85d0840 Binary files /dev/null and b/ml_prm/resources/sounds/body_medium_impact_hard2.wav differ diff --git a/ml_prm/resources/sounds/body_medium_impact_hard3.wav b/ml_prm/resources/sounds/body_medium_impact_hard3.wav new file mode 100644 index 0000000..5cb0d89 Binary files /dev/null and b/ml_prm/resources/sounds/body_medium_impact_hard3.wav differ diff --git a/ml_prm/resources/sounds/body_medium_impact_hard4.wav b/ml_prm/resources/sounds/body_medium_impact_hard4.wav new file mode 100644 index 0000000..9c5a4e0 Binary files /dev/null and b/ml_prm/resources/sounds/body_medium_impact_hard4.wav differ diff --git a/ml_prm/resources/sounds/body_medium_impact_hard5.wav b/ml_prm/resources/sounds/body_medium_impact_hard5.wav new file mode 100644 index 0000000..a51837e Binary files /dev/null and b/ml_prm/resources/sounds/body_medium_impact_hard5.wav differ diff --git a/ml_prm/resources/sounds/body_medium_impact_hard6.wav b/ml_prm/resources/sounds/body_medium_impact_hard6.wav new file mode 100644 index 0000000..1ab9f78 Binary files /dev/null and b/ml_prm/resources/sounds/body_medium_impact_hard6.wav differ diff --git a/ml_prm/resources/sounds/body_medium_impact_soft1.wav b/ml_prm/resources/sounds/body_medium_impact_soft1.wav new file mode 100644 index 0000000..130a77e Binary files /dev/null and b/ml_prm/resources/sounds/body_medium_impact_soft1.wav differ diff --git a/ml_prm/resources/sounds/body_medium_impact_soft2.wav b/ml_prm/resources/sounds/body_medium_impact_soft2.wav new file mode 100644 index 0000000..25b2004 Binary files /dev/null and b/ml_prm/resources/sounds/body_medium_impact_soft2.wav differ diff --git a/ml_prm/resources/sounds/body_medium_impact_soft3.wav b/ml_prm/resources/sounds/body_medium_impact_soft3.wav new file mode 100644 index 0000000..3b0b03c Binary files /dev/null and b/ml_prm/resources/sounds/body_medium_impact_soft3.wav differ diff --git a/ml_prm/resources/sounds/body_medium_impact_soft4.wav b/ml_prm/resources/sounds/body_medium_impact_soft4.wav new file mode 100644 index 0000000..b0b0ff6 Binary files /dev/null and b/ml_prm/resources/sounds/body_medium_impact_soft4.wav differ diff --git a/ml_prm/resources/sounds/body_medium_impact_soft5.wav b/ml_prm/resources/sounds/body_medium_impact_soft5.wav new file mode 100644 index 0000000..3e8a152 Binary files /dev/null and b/ml_prm/resources/sounds/body_medium_impact_soft5.wav differ diff --git a/ml_prm/resources/sounds/body_medium_impact_soft6.wav b/ml_prm/resources/sounds/body_medium_impact_soft6.wav new file mode 100644 index 0000000..d5ebcac Binary files /dev/null and b/ml_prm/resources/sounds/body_medium_impact_soft6.wav differ diff --git a/ml_prm/resources/sounds/body_medium_impact_soft7.wav b/ml_prm/resources/sounds/body_medium_impact_soft7.wav new file mode 100644 index 0000000..fdebe11 Binary files /dev/null and b/ml_prm/resources/sounds/body_medium_impact_soft7.wav differ