Decompiled source of Player Pain Sounds v1.0.4
BitWizrd.PlayerPainSounds.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using BitWizrd.PlayerPainSounds.Configuration; using FistVR; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Player Pain Sounds")] [assembly: AssemblyDescription("Custom injury and death sounds for H3VR")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("BitWizrd")] [assembly: AssemblyProduct("Player Pain Sounds")] [assembly: AssemblyCopyright("Copyright © BitWizrd 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("a1b2c3d4-e5f6-4a5b-8c7d-9e0f1a2b3c4d")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace BitWizrd.PlayerPainSounds { public static class DamageCalculationHelper { public enum DamageType { Abstract, Projectile, Explosive, Melee, Environmental, Pistol, Shotgun, SMGRifle, Support, ExplosiveAmmo, MeleeWeapon, Trap, Blunt, Piercing, Cutting, Thermal, Chilling, EMP, Stunning, Blinding, Unknown } public enum BodyLocation { Head, Torso, Hand, Unknown } public struct DamageInfo { public float TotalDamage; public float KineticDamage; public float EnergeticDamage; public float BluntDamage; public float PiercingDamage; public float CuttingDamage; public float ThermalDamage; public float ChillingDamage; public float EMPDamage; public float StunningDamage; public float BlindingDamage; public float PointsDamage; public float StunDamage; public float MPa; public float MPaRootMeter; public Vector3 Force; public Vector2 UVCoords; public DamageType PrimaryType; public DamageType SecondaryType; public DamageClass SourceClass; public DamageType SourceDamageType; public BodyLocation Location; public PlayerHitBoxType HitboxType; public Vector3 ImpactPosition; public Vector3 HitNormal; public Vector3 StrikeDirection; public Vector3 EdgeNormal; public float DamageSize; public bool IsInitialContact; public bool IsInside; public bool IsMelee; public bool IsPlayer; public bool DoesIgnite; public bool DoesFreeze; public bool DoesDisrupt; public int SourceIFF; public Transform SourceTransform; public Vector3 SourcePoint; public Transform ShotOrigin; public FVRFireArm SourceFirearm; public bool WouldAffectHealth; public float HealthBefore; public float HealthAfter; public float HealthBeforeRaw; public float HealthAfterRaw; public float MaxHealth; public float DamagePercentage; public string SeverityCategory; public bool PlayerHasDamageResist; public bool PlayerHasDamageMultiplier; public float PlayerDamageResistValue; public float PlayerDamageMultiplier; public bool PlayerIsBlort; public bool PlayerIsDlort; public float EffectiveDamageAfterResist; } private const float MIN_EFFECTIVE_DAMAGE = 0.1f; private const float HEALTH_PRECISION_MULTIPLIER = 100f; private const float HIGH_DAMAGE_THRESHOLD = 0.5f; private const float LOW_DAMAGE_THRESHOLD = 0.1f; public static DamageInfo AnalyzeDamage(float damageAmount, FVRPlayerHitbox hitbox, Vector3 impactPosition) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) DamageInfo info = default(DamageInfo); info.TotalDamage = damageAmount; info.KineticDamage = damageAmount; info.EnergeticDamage = 0f; info.BluntDamage = damageAmount; info.PrimaryType = DamageType.Blunt; info.SourceClass = (DamageClass)0; info.SourceDamageType = (DamageType)0; info.HitboxType = hitbox.Type; info.Location = ConvertHitboxToBodyLocation(hitbox.Type); info.ImpactPosition = impactPosition; info.IsInitialContact = true; CalculatePlayerStateFactors(ref info); CalculateHealthImpact(ref info); info.SeverityCategory = CategorizeDamageSeverity(info.DamagePercentage); LogDamageAnalysis(info); return info; } public static DamageInfo AnalyzeDamage(Damage damageObj, FVRPlayerHitbox hitbox, Vector3 impactPosition) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) DamageInfo info = default(DamageInfo); info.BluntDamage = damageObj.Dam_Blunt; info.PiercingDamage = damageObj.Dam_Piercing; info.CuttingDamage = damageObj.Dam_Cutting; info.KineticDamage = damageObj.Dam_TotalKinetic; info.ThermalDamage = damageObj.Dam_Thermal; info.ChillingDamage = damageObj.Dam_Chilling; info.EMPDamage = damageObj.Dam_EMP; info.EnergeticDamage = damageObj.Dam_TotalEnergetic; info.StunningDamage = damageObj.Dam_Stunning; info.BlindingDamage = damageObj.Dam_Blinding; info.TotalDamage = info.KineticDamage + info.EnergeticDamage; info.SourceClass = damageObj.Class; info.PrimaryType = DeterminePrimaryDamageType(damageObj); info.SecondaryType = DetermineSecondaryDamageType(damageObj); info.HitboxType = hitbox.Type; info.Location = ConvertHitboxToBodyLocation(hitbox.Type); info.ImpactPosition = impactPosition; info.HitNormal = damageObj.hitNormal; info.StrikeDirection = damageObj.strikeDir; info.EdgeNormal = damageObj.edgeNormal; info.DamageSize = damageObj.damageSize; info.IsInitialContact = true; info.SourceIFF = damageObj.Source_IFF; info.SourceTransform = damageObj.Source_Transform; info.SourcePoint = damageObj.Source_Point; CalculatePlayerStateFactors(ref info); CalculateHealthImpact(ref info); info.SeverityCategory = CategorizeDamageSeverity(info.DamagePercentage); LogDamageAnalysis(info); return info; } public static DamageInfo AnalyzeDamage(DamageDealt damageDealt, FVRPlayerHitbox hitbox, Vector3 impactPosition) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) DamageInfo info = default(DamageInfo); info.PointsDamage = damageDealt.PointsDamage; info.StunDamage = damageDealt.StunDamage; info.MPa = damageDealt.MPa; info.MPaRootMeter = damageDealt.MPaRootMeter; info.Force = damageDealt.force; info.UVCoords = damageDealt.uvCoords; info.TotalDamage = damageDealt.PointsDamage; info.KineticDamage = damageDealt.PointsDamage; info.EnergeticDamage = 0f; info.SourceDamageType = damageDealt.Type; info.PrimaryType = ConvertDamageDealtTypeToDamageType(damageDealt.Type); if (damageDealt.IsMelee) { info.SecondaryType = DamageType.MeleeWeapon; } info.HitboxType = hitbox.Type; info.Location = ConvertHitboxToBodyLocation(hitbox.Type); info.ImpactPosition = impactPosition; info.HitNormal = damageDealt.hitNormal; info.StrikeDirection = damageDealt.strikeDir; info.IsInitialContact = damageDealt.IsInitialContact; info.IsInside = damageDealt.IsInside; info.IsMelee = damageDealt.IsMelee; info.IsPlayer = damageDealt.IsPlayer; info.DoesIgnite = damageDealt.DoesIgnite; info.DoesFreeze = damageDealt.DoesFreeze; info.DoesDisrupt = damageDealt.DoesDisrupt; info.ShotOrigin = damageDealt.ShotOrigin; info.SourceFirearm = damageDealt.SourceFirearm; CalculatePlayerStateFactors(ref info); CalculateHealthImpact(ref info); info.SeverityCategory = CategorizeDamageSeverity(info.DamagePercentage); LogDamageAnalysis(info); return info; } public static bool WouldDamageAffectHealth(float damageAmount) { if (damageAmount <= 0f) { return false; } if ((Object)(object)GM.CurrentPlayerBody == (Object)null) { return false; } float health = GM.CurrentPlayerBody.Health; float num = health - damageAmount; int num2 = (int)health; int num3 = (int)num; bool flag = num2 != num3; if (PlayerPainSoundsPlugin.configDebugMessages.Value) { PlayerPainSoundsPlugin.LogInfo($"H3VR Health Impact: damage={damageAmount}, rawHealth: {health:F4} -> {num:F4}, truncated: {num2} -> {num3}, affects={flag}"); } return flag; } public static bool WouldDamageAffectHealth(DamageInfo damageInfo) { return WouldDamageAffectHealth((damageInfo.EffectiveDamageAfterResist > 0f) ? damageInfo.EffectiveDamageAfterResist : damageInfo.TotalDamage); } public static bool ShouldTriggerPainSound(DamageInfo damageInfo) { if (damageInfo.TotalDamage <= 0f) { return false; } if (!damageInfo.IsInitialContact) { return false; } if (!WouldPassH3VRHitboxThreshold(damageInfo)) { return false; } if (!damageInfo.WouldAffectHealth) { return false; } return true; } private static bool WouldPassH3VRHitboxThreshold(DamageInfo damageInfo) { if ((Object)(object)GM.CurrentPlayerBody == (Object)null) { return false; } float num = damageInfo.TotalDamage; if (GM.CurrentPlayerBody.IsBlort && damageInfo.EnergeticDamage > 0f) { num = damageInfo.KineticDamage; } else if (GM.CurrentPlayerBody.IsDlort && damageInfo.EnergeticDamage > 0f) { num = damageInfo.KineticDamage + damageInfo.EnergeticDamage * 3f; } if (GM.CurrentPlayerBody.IsDamResist || GM.CurrentPlayerBody.IsDamMult) { float damageResist = GM.CurrentPlayerBody.GetDamageResist(); if (damageResist <= 0.01f) { return false; } num *= damageResist; } bool flag = num > 0.1f; if (PlayerPainSoundsPlugin.configDebugMessages.Value) { PlayerPainSoundsPlugin.LogInfo($"H3VR Hitbox Threshold Check: original={damageInfo.TotalDamage}, processed={num}, passes={flag}"); } return flag; } public static string GetSoundCategoryForDamage(DamageInfo damageInfo) { if (damageInfo.DamagePercentage >= 0.5f) { return "pain_high"; } if (damageInfo.DamagePercentage <= 0.1f) { return "pain_low"; } return "pain_default"; } private static BodyLocation ConvertHitboxToBodyLocation(PlayerHitBoxType hitboxType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected I4, but got Unknown return (int)hitboxType switch { 0 => BodyLocation.Head, 1 => BodyLocation.Torso, 2 => BodyLocation.Hand, _ => BodyLocation.Unknown, }; } private static void CalculatePlayerStateFactors(ref DamageInfo info) { if (!((Object)(object)GM.CurrentPlayerBody == (Object)null)) { info.PlayerHasDamageResist = GM.CurrentPlayerBody.IsDamResist || GM.CurrentPlayerBody.IsDamMult; info.PlayerHasDamageMultiplier = GM.CurrentPlayerBody.IsDamMult || GM.CurrentPlayerBody.isDamPowerUp; info.PlayerIsBlort = GM.CurrentPlayerBody.IsBlort; info.PlayerIsDlort = GM.CurrentPlayerBody.IsDlort; if (info.PlayerHasDamageResist) { info.PlayerDamageResistValue = GM.CurrentPlayerBody.GetDamageResist(); } else { info.PlayerDamageResistValue = 1f; } if (info.PlayerHasDamageMultiplier) { info.PlayerDamageMultiplier = GM.CurrentPlayerBody.GetDamageMult(); } else { info.PlayerDamageMultiplier = 1f; } float num = info.TotalDamage; if (info.PlayerIsBlort && info.EnergeticDamage > 0f) { num = info.KineticDamage; } else if (info.PlayerIsDlort && info.EnergeticDamage > 0f) { num = info.KineticDamage + info.EnergeticDamage * 3f; } num = ((!(info.PlayerDamageResistValue <= 0.01f)) ? (num * info.PlayerDamageResistValue) : 0f); info.EffectiveDamageAfterResist = num; } } private static void CalculateHealthImpact(ref DamageInfo info) { if ((Object)(object)GM.CurrentPlayerBody == (Object)null) { info.WouldAffectHealth = false; info.HealthBefore = 0f; info.HealthAfter = 0f; info.HealthBeforeRaw = 0f; info.HealthAfterRaw = 0f; info.MaxHealth = 0f; info.DamagePercentage = 0f; return; } float health = GM.CurrentPlayerBody.Health; float num = GM.CurrentPlayerBody.GetMaxHealthPlayerRaw(); float num2 = ((info.EffectiveDamageAfterResist > 0f) ? info.EffectiveDamageAfterResist : info.TotalDamage); float num3 = health - num2; info.HealthBeforeRaw = health; info.HealthAfterRaw = num3; info.MaxHealth = num; info.HealthBefore = GM.CurrentPlayerBody.GetPlayerHealth(); info.HealthAfter = num3 / num; if (num > 0f) { info.DamagePercentage = num2 / num; } else { info.DamagePercentage = 0f; } info.WouldAffectHealth = WouldDamageAffectHealth(info); } private static string CategorizeDamageSeverity(float damagePercentage) { if (damagePercentage >= 0.5f) { return "High"; } if (damagePercentage <= 0.1f) { return "Low"; } return "Medium"; } private static DamageType DeterminePrimaryDamageType(Damage damageObj) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected I4, but got Unknown DamageClass @class = damageObj.Class; switch (@class - 1) { case 0: return DamageType.Projectile; case 1: return DamageType.Explosive; case 2: return DamageType.Melee; case 3: return DamageType.Environmental; default: { float num = 0f; DamageType result = DamageType.Unknown; if (damageObj.Dam_Blunt > num) { num = damageObj.Dam_Blunt; result = DamageType.Blunt; } if (damageObj.Dam_Piercing > num) { num = damageObj.Dam_Piercing; result = DamageType.Piercing; } if (damageObj.Dam_Cutting > num) { num = damageObj.Dam_Cutting; result = DamageType.Cutting; } if (damageObj.Dam_Thermal > num) { num = damageObj.Dam_Thermal; result = DamageType.Thermal; } if (damageObj.Dam_Chilling > num) { num = damageObj.Dam_Chilling; result = DamageType.Chilling; } if (damageObj.Dam_EMP > num) { num = damageObj.Dam_EMP; result = DamageType.EMP; } if (damageObj.Dam_Stunning > num) { num = damageObj.Dam_Stunning; result = DamageType.Stunning; } if (damageObj.Dam_Blinding > num) { num = damageObj.Dam_Blinding; result = DamageType.Blinding; } return result; } } } private static DamageType DetermineSecondaryDamageType(Damage damageObj) { float[] array = new float[8] { damageObj.Dam_Blunt, damageObj.Dam_Piercing, damageObj.Dam_Cutting, damageObj.Dam_Thermal, damageObj.Dam_Chilling, damageObj.Dam_EMP, damageObj.Dam_Stunning, damageObj.Dam_Blinding }; DamageType[] array2 = new DamageType[8] { DamageType.Blunt, DamageType.Piercing, DamageType.Cutting, DamageType.Thermal, DamageType.Chilling, DamageType.EMP, DamageType.Stunning, DamageType.Blinding }; float num = 0f; float num2 = 0f; int num3 = -1; int num4 = -1; for (int i = 0; i < array.Length; i++) { if (array[i] > num) { num2 = num; num4 = num3; num = array[i]; num3 = i; } else if (array[i] > num2) { num2 = array[i]; num4 = i; } } if (num4 < 0) { return DamageType.Unknown; } return array2[num4]; } private static DamageType ConvertDamageDealtTypeToDamageType(DamageType sourceType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected I4, but got Unknown return (sourceType - 1) switch { 0 => DamageType.Pistol, 1 => DamageType.Shotgun, 2 => DamageType.SMGRifle, 3 => DamageType.Support, 4 => DamageType.ExplosiveAmmo, 5 => DamageType.MeleeWeapon, 6 => DamageType.Trap, _ => DamageType.Unknown, }; } private static void LogDamageAnalysis(DamageInfo info) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) if (PlayerPainSoundsPlugin.configDebugMessages.Value) { PlayerPainSoundsPlugin.LogInfo($"=== Damage Analysis ==="); PlayerPainSoundsPlugin.LogInfo($"Total: {info.TotalDamage:F2} damage to {info.Location} ({info.HitboxType})"); PlayerPainSoundsPlugin.LogInfo($"Breakdown - K:{info.KineticDamage:F2}, E:{info.EnergeticDamage:F2} | Blunt:{info.BluntDamage:F2}, Pierce:{info.PiercingDamage:F2}, Cut:{info.CuttingDamage:F2}"); PlayerPainSoundsPlugin.LogInfo($"Energetic - Thermal:{info.ThermalDamage:F2}, Chill:{info.ChillingDamage:F2}, EMP:{info.EMPDamage:F2}"); PlayerPainSoundsPlugin.LogInfo($"Special - Stun:{info.StunningDamage:F2}, Blind:{info.BlindingDamage:F2}"); PlayerPainSoundsPlugin.LogInfo($"Type: {info.PrimaryType} / {info.SecondaryType} | Class: {info.SourceClass} | Source: {info.SourceDamageType}"); PlayerPainSoundsPlugin.LogInfo($"Health: {info.HealthBeforeRaw:F0} -> {info.HealthAfterRaw:F0} ({info.DamagePercentage * 100f:F1}% of {info.MaxHealth:F0})"); PlayerPainSoundsPlugin.LogInfo($"Player State - Resist:{info.PlayerDamageResistValue:F2}, Mult:{info.PlayerDamageMultiplier:F2}, Blort:{info.PlayerIsBlort}, Dlort:{info.PlayerIsDlort}"); PlayerPainSoundsPlugin.LogInfo($"Effective Damage: {info.EffectiveDamageAfterResist:F2} | Affects Health: {info.WouldAffectHealth} | Category: {GetSoundCategoryForDamage(info)}"); PlayerPainSoundsPlugin.LogInfo($"========================"); } } public static float ApplyLocationMultiplier(float baseDamage, BodyLocation location, DamageInfo damageInfo) { switch (location) { case BodyLocation.Head: return baseDamage * 1f; case BodyLocation.Torso: return baseDamage * 1f; case BodyLocation.Hand: if ((Object)(object)damageInfo.SourceFirearm != (Object)null) { return 0f; } return baseDamage * 1f; default: return baseDamage; } } public static float CalculateDamageReduction(DamageInfo damageInfo) { return 0f; } public static DamageInfo ProcessEnvironmentalDamage(float damage, Vector3 position, DamageType environmentType) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) DamageInfo result = default(DamageInfo); result.TotalDamage = damage; result.PrimaryType = environmentType; result.ImpactPosition = position; return result; } public static string GetImpactSoundCategory(Damage damage) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 if (damage == null) { return "impact_default"; } if ((int)damage.Class == 1) { return "impact_bullet"; } if ((int)damage.Class == 2) { return "impact_default"; } if (damage.Dam_Cutting > 0f || damage.Dam_Piercing > 0f) { return "impact_default"; } if (damage.Dam_Blunt > 0f) { return "impact_default"; } _ = damage.Dam_Thermal; _ = 0f; return "impact_default"; } public static string GetImpactSoundCategory(PlayerHitBoxType hitboxType, float damageAmount) { _ = 50f; return "impact_default"; } } public class InjurySoundManager : MonoBehaviour { [CompilerGenerated] private sealed class <>c__DisplayClass91_0 { public string packName; internal bool <LoadSinglePackAndSwitch>b__0(OuchPackInfo p) { return p.Name == packName; } } [CompilerGenerated] private sealed class <LoadCustomSoundPacks>d__88 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public InjurySoundManager <>4__this; private List<OuchPackInfo>.Enumerator <>7__wrap1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadCustomSoundPacks>d__88(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = default(List<OuchPackInfo>.Enumerator); <>1__state = -2; } private bool MoveNext() { try { int num = <>1__state; InjurySoundManager injurySoundManager = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>7__wrap1 = PlayerPainSoundsPlugin.DiscoveredOuchPacks.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } if (<>7__wrap1.MoveNext()) { OuchPackInfo current = <>7__wrap1.Current; string name = current.Name; string path = current.Path; injurySoundManager.InitializePackDictionaries(name); injurySoundManager.injurySounds[name].Clear(); injurySoundManager.deathSounds[name].Clear(); injurySoundManager.availableCategories[name].Clear(); <>2__current = ((MonoBehaviour)injurySoundManager).StartCoroutine(injurySoundManager.LoadSoundPackCategories(name, path)); <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap1 = default(List<OuchPackInfo>.Enumerator); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap1).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <LoadSinglePackAndSwitch>d__91 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string packName; public InjurySoundManager <>4__this; private <>c__DisplayClass91_0 <>8__1; private string <packPath>5__2; private Dictionary<string, List<AudioClip>> <packInjurySounds>5__3; private Dictionary<string, List<AudioClip>> <packDeathSounds>5__4; private Dictionary<string, List<AudioClip>> <packImpactSounds>5__5; private string[] <>7__wrap5; private int <>7__wrap6; private string <category>5__8; private List<AudioClip> <clips>5__9; private string[] <>7__wrap9; private int <>7__wrap10; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadSinglePackAndSwitch>d__91(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <packPath>5__2 = null; <packInjurySounds>5__3 = null; <packDeathSounds>5__4 = null; <packImpactSounds>5__5 = null; <>7__wrap5 = null; <category>5__8 = null; <clips>5__9 = null; <>7__wrap9 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; InjurySoundManager injurySoundManager = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; <>7__wrap10++; goto IL_01ee; } <>1__state = -1; <>8__1 = new <>c__DisplayClass91_0(); <>8__1.packName = packName; OuchPackInfo ouchPackInfo = PlayerPainSoundsPlugin.DiscoveredOuchPacks.FirstOrDefault((OuchPackInfo p) => p.Name == <>8__1.packName); if (ouchPackInfo == null) { PlayerPainSoundsPlugin.LogError("Pack not found: " + <>8__1.packName); injurySoundManager.currentSoundPack = "Default"; injurySoundManager.ClearLoadedSounds(); injurySoundManager.LoadDefaultSounds(); PlayerPainSoundsPlugin.LogInfo("Fell back to Default sound pack"); return false; } <packPath>5__2 = ouchPackInfo.Path; if (string.IsNullOrEmpty(<packPath>5__2) || !Directory.Exists(<packPath>5__2)) { PlayerPainSoundsPlugin.LogError("Invalid pack path: " + <packPath>5__2); injurySoundManager.currentSoundPack = "Default"; injurySoundManager.ClearLoadedSounds(); injurySoundManager.LoadDefaultSounds(); PlayerPainSoundsPlugin.LogInfo("Fell back to Default sound pack due to invalid path"); return false; } PlayerPainSoundsPlugin.LogInfo("Loading sound pack from path: " + <packPath>5__2); <packInjurySounds>5__3 = new Dictionary<string, List<AudioClip>>(); <packDeathSounds>5__4 = new Dictionary<string, List<AudioClip>>(); <packImpactSounds>5__5 = new Dictionary<string, List<AudioClip>>(); <>7__wrap5 = SoundCategories.ALL_CATEGORIES; <>7__wrap6 = 0; goto IL_032c; IL_0317: <category>5__8 = null; <>7__wrap6++; goto IL_032c; IL_032c: if (<>7__wrap6 < <>7__wrap5.Length) { <category>5__8 = <>7__wrap5[<>7__wrap6]; string path = Path.Combine(<packPath>5__2, <category>5__8); if (Directory.Exists(path)) { <clips>5__9 = new List<AudioClip>(); string[] files = Directory.GetFiles(path, "*.*", SearchOption.TopDirectoryOnly); <>7__wrap9 = files; <>7__wrap10 = 0; goto IL_01ee; } goto IL_0317; } <>7__wrap5 = null; bool flag = false; injurySoundManager.InitializePackDictionaries(<>8__1.packName); if (<packInjurySounds>5__3.Count > 0) { injurySoundManager.injurySounds[<>8__1.packName] = <packInjurySounds>5__3; foreach (string key in <packInjurySounds>5__3.Keys) { injurySoundManager.availableCategories[<>8__1.packName].Add(key); } flag = true; } if (<packDeathSounds>5__4.Count > 0) { injurySoundManager.deathSounds[<>8__1.packName] = <packDeathSounds>5__4; foreach (string key2 in <packDeathSounds>5__4.Keys) { injurySoundManager.availableCategories[<>8__1.packName].Add(key2); } flag = true; } if (<packImpactSounds>5__5.Count > 0) { injurySoundManager.impactSounds[<>8__1.packName] = <packImpactSounds>5__5; foreach (string key3 in <packImpactSounds>5__5.Keys) { injurySoundManager.availableCategories[<>8__1.packName].Add(key3); } flag = true; } if (!flag) { PlayerPainSoundsPlugin.LogWarning("No sounds found in pack: " + <>8__1.packName); injurySoundManager.currentSoundPack = "Default"; injurySoundManager.ClearLoadedSounds(); injurySoundManager.LoadDefaultSounds(); PlayerPainSoundsPlugin.LogInfo("Fell back to Default sound pack due to no sounds found"); } else { injurySoundManager.currentSoundPack = <>8__1.packName; PlayerPainSoundsPlugin.LogInfo("Successfully loaded sound pack: " + <>8__1.packName); } if (injurySoundManager.hasInitialized && injurySoundManager.isInLastStand) { injurySoundManager.PlayerStateCheck(); } return false; IL_01ee: if (<>7__wrap10 < <>7__wrap9.Length) { string file = <>7__wrap9[<>7__wrap10]; <>2__current = ((MonoBehaviour)injurySoundManager).StartCoroutine(injurySoundManager.LoadSoundFile(file, <clips>5__9, <category>5__8)); <>1__state = 1; return true; } <>7__wrap9 = null; if (<clips>5__9.Count > 0) { if (<category>5__8 == "death") { <packDeathSounds>5__4[<category>5__8] = <clips>5__9; PlayerPainSoundsPlugin.LogInfo("Loaded " + <clips>5__9.Count + " death sounds for category: " + <category>5__8); } else if (SoundCategories.IS_IMPACT_CATEGORY[<category>5__8]) { <packImpactSounds>5__5[<category>5__8] = <clips>5__9; PlayerPainSoundsPlugin.LogInfo("Loaded " + <clips>5__9.Count + " impact sounds for category: " + <category>5__8); } else { <packInjurySounds>5__3[<category>5__8] = <clips>5__9; PlayerPainSoundsPlugin.LogInfo("Loaded " + <clips>5__9.Count + " injury sounds for category: " + <category>5__8); } } <clips>5__9 = null; goto IL_0317; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <LoadSoundFile>d__122 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string file; public List<AudioClip> clips; public string category; private string <fileUrl>5__2; private WWW <www>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadSoundFile>d__122(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <fileUrl>5__2 = null; <www>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: { <>1__state = -1; if (string.IsNullOrEmpty(file) || clips == null) { PlayerPainSoundsPlugin.LogError("Invalid parameters passed to LoadSoundFile"); return false; } string text = Path.GetExtension(file).ToLower(); if (ConfigurationConstants.IsSupportedAudioFormat(text)) { <fileUrl>5__2 = "file:///" + file.Replace("\\", "/"); PlayerPainSoundsPlugin.LogInfo("Loading sound file: " + <fileUrl>5__2); <www>5__3 = null; <www>5__3 = new WWW(<fileUrl>5__2); <>2__current = <www>5__3; <>1__state = 1; return true; } PlayerPainSoundsPlugin.LogWarning("Unsupported audio file format: " + text + " - File: " + file); break; } case 1: <>1__state = -1; try { if (!string.IsNullOrEmpty(<www>5__3.error)) { PlayerPainSoundsPlugin.LogError("Error loading sound file: " + <fileUrl>5__2 + " - " + <www>5__3.error); return false; } AudioClip audioClip = WWWAudioExtensions.GetAudioClip(<www>5__3, false, false); if ((Object)(object)audioClip != (Object)null) { ((Object)audioClip).name = Path.GetFileNameWithoutExtension(file); clips.Add(audioClip); PlayerPainSoundsPlugin.LogInfo("Successfully loaded sound: " + ((Object)audioClip).name + " for category: " + category); } else { PlayerPainSoundsPlugin.LogError("Failed to create AudioClip from: " + <fileUrl>5__2); } } catch (Exception ex) { PlayerPainSoundsPlugin.LogError("Exception in LoadSoundFile: " + ex.Message); } finally { if (<www>5__3 != null) { <www>5__3.Dispose(); } } <fileUrl>5__2 = null; <www>5__3 = null; break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <LoadSoundPackCategories>d__90 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string packPath; public InjurySoundManager <>4__this; public string packName; private string[] <>7__wrap1; private int <>7__wrap2; private string <category>5__4; private bool <hasValidSounds>5__5; private string[] <>7__wrap5; private int <>7__wrap6; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadSoundPackCategories>d__90(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>7__wrap1 = null; <category>5__4 = null; <>7__wrap5 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; InjurySoundManager injurySoundManager = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>7__wrap1 = SoundCategories.ALL_CATEGORIES; <>7__wrap2 = 0; goto IL_0303; case 1: <>1__state = -1; goto IL_02a1; case 2: <>1__state = -1; goto IL_02a1; case 3: { <>1__state = -1; goto IL_02a1; } IL_0303: if (<>7__wrap2 < <>7__wrap1.Length) { <category>5__4 = <>7__wrap1[<>7__wrap2]; string path = Path.Combine(packPath, <category>5__4); if (Directory.Exists(path)) { string[] files = Directory.GetFiles(path, "*.*", SearchOption.TopDirectoryOnly); <hasValidSounds>5__5 = false; <>7__wrap5 = files; <>7__wrap6 = 0; goto IL_02af; } goto IL_02ee; } <>7__wrap1 = null; PlayerPainSoundsPlugin.LogInfo(string.Format("Loaded pack '{0}' with categories: {1}", packName, string.Join(", ", injurySoundManager.availableCategories[packName].ToArray()))); return false; IL_02ee: <category>5__4 = null; <>7__wrap2++; goto IL_0303; IL_02a1: <>7__wrap6++; goto IL_02af; IL_02af: if (<>7__wrap6 < <>7__wrap5.Length) { string text = <>7__wrap5[<>7__wrap6]; string text2 = Path.GetExtension(text).ToLower(); if (text2 == ".wav" || text2 == ".ogg") { <hasValidSounds>5__5 = true; if (<category>5__4 == "death") { if (!injurySoundManager.deathSounds[packName].ContainsKey(<category>5__4)) { injurySoundManager.deathSounds[packName][<category>5__4] = new List<AudioClip>(); } <>2__current = ((MonoBehaviour)injurySoundManager).StartCoroutine(injurySoundManager.LoadSoundFile(text, injurySoundManager.deathSounds[packName][<category>5__4], <category>5__4)); <>1__state = 1; return true; } if (SoundCategories.IS_IMPACT_CATEGORY[<category>5__4]) { if (!injurySoundManager.impactSounds[packName].ContainsKey(<category>5__4)) { injurySoundManager.impactSounds[packName][<category>5__4] = new List<AudioClip>(); } <>2__current = ((MonoBehaviour)injurySoundManager).StartCoroutine(injurySoundManager.LoadSoundFile(text, injurySoundManager.impactSounds[packName][<category>5__4], <category>5__4)); <>1__state = 2; return true; } if (!injurySoundManager.injurySounds[packName].ContainsKey(<category>5__4)) { injurySoundManager.injurySounds[packName][<category>5__4] = new List<AudioClip>(); } <>2__current = ((MonoBehaviour)injurySoundManager).StartCoroutine(injurySoundManager.LoadSoundFile(text, injurySoundManager.injurySounds[packName][<category>5__4], <category>5__4)); <>1__state = 3; return true; } goto IL_02a1; } <>7__wrap5 = null; if (<hasValidSounds>5__5) { injurySoundManager.availableCategories[packName].Add(<category>5__4); } goto IL_02ee; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <PlayCriticalHealthSoundWithDelay>d__79 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public InjurySoundManager <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PlayCriticalHealthSoundWithDelay>d__79(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown int num = <>1__state; InjurySoundManager injurySoundManager = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; case 1: { <>1__state = -1; if (!injurySoundManager.isCriticalHealthEnabled || (Object)(object)injurySoundManager.audioSource == (Object)null || injurySoundManager.isDying) { return false; } AudioClip val = null; if (injurySoundManager.currentSoundPack == "Default") { val = injurySoundManager.GetDefaultCriticalHealthSound(); } else if (injurySoundManager.injurySounds.ContainsKey(injurySoundManager.currentSoundPack) && injurySoundManager.injurySounds[injurySoundManager.currentSoundPack].ContainsKey("critical_health") && injurySoundManager.injurySounds[injurySoundManager.currentSoundPack]["critical_health"].Count > 0) { List<AudioClip> sounds = injurySoundManager.injurySounds[injurySoundManager.currentSoundPack]["critical_health"]; val = injurySoundManager.GetUniqueRandomSound("critical_health", sounds); } if ((Object)(object)val == (Object)null) { PlayerPainSoundsPlugin.LogInfo("No critical health sound available"); return false; } float num2 = 1f * injurySoundManager.GetVolumeMultiplier(); injurySoundManager.audioSource2D.pitch = 1f; injurySoundManager.audioSource2D.PlayOneShot(val, num2); PlayerPainSoundsPlugin.LogInfo("Playing critical health sound"); return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <PlayInjuryClipsWithDelay>d__111 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float delay; public InjurySoundManager <>4__this; public Vector3 headPosition; public float pitch; public AudioClip clip; public float spatialVolume; public float volume2D; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PlayInjuryClipsWithDelay>d__111(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown int num = <>1__state; InjurySoundManager injurySoundManager = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; if (delay > 0f) { <>2__current = (object)new WaitForSeconds(delay); <>1__state = 1; return true; } break; case 1: <>1__state = -1; break; } ((Component)injurySoundManager.audioSource).transform.position = headPosition; injurySoundManager.audioSource.pitch = pitch; injurySoundManager.audioSource2D.pitch = pitch; injurySoundManager.audioSource.PlayOneShot(clip, spatialVolume); injurySoundManager.audioSource2D.PlayOneShot(clip, volume2D); injurySoundManager.lastInjurySoundTime = Time.time; injurySoundManager.lastPlayedInjuryClip = clip; string text = delay.ToString(); Vector3 val = headPosition; PlayerPainSoundsPlugin.LogInfo("Playing injury sound with delay " + text + " seconds at head position: " + ((object)(Vector3)(ref val)).ToString()); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <PlayPainAndDeathSequence>d__116 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public InjurySoundManager <>4__this; public AudioClip deathSound; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PlayPainAndDeathSequence>d__116(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; InjurySoundManager injurySoundManager = <>4__this; switch (num) { default: return false; case 0: { <>1__state = -1; Vector3 position = GM.CurrentPlayerBody.Head.position; AudioClip appropriateSound = injurySoundManager.GetAppropriateSound(); if ((Object)(object)appropriateSound != (Object)null) { float num2 = 1f * injurySoundManager.GetVolumeMultiplier(); ((Component)injurySoundManager.audioSource).transform.position = position; injurySoundManager.audioSource.spatialBlend = 1f; float num3 = num2 * 0.2f; injurySoundManager.audioSource.PlayOneShot(appropriateSound, num3); injurySoundManager.audioSource2D.PlayOneShot(appropriateSound, num2); PlayerPainSoundsPlugin.LogInfo($"Playing pain sound before death at head position: {position}"); <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } break; } case 1: <>1__state = -1; break; } if ((Object)(object)deathSound != (Object)null) { Vector3 position = GM.CurrentPlayerBody.Head.position; float num4 = 1f * injurySoundManager.GetVolumeMultiplier(); ((Component)injurySoundManager.audioSource).transform.position = position; injurySoundManager.audioSource.spatialBlend = 1f; float num5 = num4 * 0.2f; injurySoundManager.audioSource.PlayOneShot(deathSound, num5); injurySoundManager.audioSource2D.PlayOneShot(deathSound, num4); PlayerPainSoundsPlugin.LogInfo($"Playing death sound after pain at head position: {position}"); ((MonoBehaviour)injurySoundManager).StartCoroutine(injurySoundManager.ResetStateAfterDeathSound()); } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ResetStateAfterDeathSound>d__121 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public InjurySoundManager <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ResetStateAfterDeathSound>d__121(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown int num = <>1__state; InjurySoundManager injurySoundManager = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(5f); <>1__state = 1; return true; case 1: <>1__state = -1; injurySoundManager.isDying = false; injurySoundManager.m_hasPlayedDeathSound = false; if (PlayerPainSoundsPlugin.IsManagerReady()) { injurySoundManager.PlayerStateCheck(); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <StartLoadingSoundPacks>d__83 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public InjurySoundManager <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <StartLoadingSoundPacks>d__83(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; InjurySoundManager injurySoundManager = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; injurySoundManager.isLoading = true; injurySoundManager.LoadDefaultSounds(); <>2__current = ((MonoBehaviour)injurySoundManager).StartCoroutine(injurySoundManager.LoadCustomSoundPacks()); <>1__state = 1; return true; case 1: { <>1__state = -1; string value = PlayerPainSoundsPlugin.configInjurySoundPack.Value; injurySoundManager.SetSoundPack(value); injurySoundManager.isLoading = false; return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <TransitionLastStandSound>d__87 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public InjurySoundManager <>4__this; public string newPackName; private bool <wasInLastStand>5__2; private bool <shouldBeInLastStand>5__3; private float <startVolume>5__4; private float <fadeStartTime>5__5; private float <fadeDuration>5__6; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TransitionLastStandSound>d__87(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Expected O, but got Unknown int num = <>1__state; InjurySoundManager injurySoundManager = <>4__this; switch (num) { default: return false; case 0: { <>1__state = -1; injurySoundManager.isTransitioningPacks = true; <wasInLastStand>5__2 = injurySoundManager.isInLastStand; PlayerPainSoundsPlugin.LogInfo("Starting transition to sound pack: " + newPackName + " (was in last stand: " + <wasInLastStand>5__2 + ")"); float num2 = GM.CurrentPlayerBody.GetPlayerHealthRaw(); float num3 = GM.CurrentPlayerBody.GetMaxHealthPlayerRaw(); float num4 = num2 / num3; <shouldBeInLastStand>5__3 = num4 <= injurySoundManager.lastStandThreshold && injurySoundManager.isLastStandEnabled; if (<wasInLastStand>5__2 && (Object)(object)injurySoundManager.lastStandAudioSource != (Object)null && injurySoundManager.lastStandAudioSource.isPlaying) { <startVolume>5__4 = injurySoundManager.lastStandAudioSource.volume; <fadeStartTime>5__5 = Time.time; <fadeDuration>5__6 = 0.5f; PlayerPainSoundsPlugin.LogInfo("Fading out last stand sound"); goto IL_0159; } goto IL_0184; } case 1: <>1__state = -1; goto IL_0159; case 2: <>1__state = -1; PlayerPainSoundsPlugin.LogInfo("Finished loading sounds for pack: " + newPackName); goto IL_026a; case 3: { <>1__state = -1; injurySoundManager.StartLastStandSound(); PlayerPainSoundsPlugin.LogInfo("Restarted last stand with new sound pack"); break; } IL_0184: if (newPackName == "Default") { injurySoundManager.currentSoundPack = "Default"; injurySoundManager.ClearLoadedSounds(); injurySoundManager.LoadDefaultSounds(); PlayerPainSoundsPlugin.LogInfo("Transitioned to Default sound pack"); } else { if (!injurySoundManager.injurySounds.ContainsKey(newPackName) || !injurySoundManager.deathSounds.ContainsKey(newPackName) || !injurySoundManager.availableCategories.ContainsKey(newPackName)) { PlayerPainSoundsPlugin.LogInfo("Loading sounds for pack: " + newPackName); <>2__current = ((MonoBehaviour)injurySoundManager).StartCoroutine(injurySoundManager.LoadSinglePackAndSwitch(newPackName)); <>1__state = 2; return true; } injurySoundManager.currentSoundPack = newPackName; PlayerPainSoundsPlugin.LogInfo("Transitioned to sound pack: " + newPackName); } goto IL_026a; IL_0159: if (Time.time < <fadeStartTime>5__5 + <fadeDuration>5__6) { float num5 = (Time.time - <fadeStartTime>5__5) / <fadeDuration>5__6; injurySoundManager.lastStandAudioSource.volume = Mathf.Lerp(<startVolume>5__4, 0f, num5); <>2__current = null; <>1__state = 1; return true; } injurySoundManager.lastStandAudioSource.Stop(); injurySoundManager.lastStandAudioSource.clip = null; goto IL_0184; IL_026a: if (<wasInLastStand>5__2 & <shouldBeInLastStand>5__3) { injurySoundManager.isInLastStand = true; <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 3; return true; } break; } injurySoundManager.isTransitioningPacks = false; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static InjurySoundManager _instance; private Dictionary<string, Dictionary<string, List<AudioClip>>> injurySounds = new Dictionary<string, Dictionary<string, List<AudioClip>>>(); private Dictionary<string, Dictionary<string, List<AudioClip>>> deathSounds = new Dictionary<string, Dictionary<string, List<AudioClip>>>(); private Dictionary<string, Dictionary<string, List<AudioClip>>> impactSounds = new Dictionary<string, Dictionary<string, List<AudioClip>>>(); private Dictionary<string, HashSet<string>> availableCategories = new Dictionary<string, HashSet<string>>(); private string currentSoundPack = "Default"; private bool isDying; private const float DEATH_SOUND_VOLUME = 1f; private const float MIN_PITCH_VARIANCE = 0.98f; private const float MAX_PITCH_VARIANCE = 1.02f; private const float CRITICAL_HEALTH_DELAY = 0.5f; private const float PAIN_DEATH_DELAY = 0.1f; private AudioSource lastStandAudioSource; private bool isInLastStand; private bool isLastStandEnabled = true; private float lastStandThreshold = 0.25f; private const float FADE_DURATION = 2f; private float fadeStartTime; private float targetVolume = 1f; private bool isFadingIn; private bool isFadingOut; private bool shouldBeInLastStand; private bool hasCriticalHealthTriggered; private bool isCriticalHealthEnabled = true; private float criticalHealthThreshold = 0.25f; private const float HIGH_DAMAGE_THRESHOLD = 0.5f; private const float LOW_DAMAGE_THRESHOLD = 0.1f; private bool playPainWithDeath; private bool enableImpactSounds = true; private float impactVolumeMultiplier = 1f; private float lastImpactSoundTime; private const float MIN_TIME_BETWEEN_IMPACTS = 0.05f; private AudioSource audioSource; private AudioSource audioSource2D; private AudioSource impactAudioSource; private float lastInjurySoundTime; private const float MIN_TIME_BETWEEN_SOUNDS = 0.1f; private AudioClip lastPlayedInjuryClip; private bool hasInitialized; private bool isTransitioningPacks; public bool m_hasPlayedDeathSound; private Dictionary<string, AudioClip> lastPlayedClips = new Dictionary<string, AudioClip>(); private bool enablePainSounds = true; private bool preventPainOverlap; public static InjurySoundManager Instance { get { return _instance; } set { _instance = value; } } public bool isLoading { get; private set; } public string CurrentSoundPack => currentSoundPack; public bool IsDying { get { return isDying; } set { isDying = value; } } public float LastStandThreshold => lastStandThreshold; public float CriticalHealthThreshold => criticalHealthThreshold; public void SetVolumeMultiplier(float multiplier) { PlayerPainSoundsPlugin.configVolumeMultiplier.Value = Mathf.Clamp(multiplier, 0f, 2f); } private float GetVolumeMultiplier() { return PlayerPainSoundsPlugin.configVolumeMultiplier.Value; } public void SetLastStandEnabled(bool enabled) { isLastStandEnabled = enabled; if (!enabled && isInLastStand) { StopLastStandSound(); } PlayerStateCheck(); } public void SetLastStandThreshold(float threshold) { lastStandThreshold = Mathf.Clamp01(threshold); PlayerStateCheck(); } public void SetCriticalHealthEnabled(bool enabled) { isCriticalHealthEnabled = enabled; if (!enabled) { hasCriticalHealthTriggered = false; } PlayerStateCheck(); } public void SetCriticalHealthThreshold(float threshold) { criticalHealthThreshold = Mathf.Clamp01(threshold); hasCriticalHealthTriggered = false; PlayerStateCheck(); } public void SetPlayPainWithDeath(bool enabled) { playPainWithDeath = enabled; PlayerPainSoundsPlugin.LogInfo("Play pain with death set to: " + enabled); } public void SetEnableImpactSounds(bool enabled) { enableImpactSounds = enabled; PlayerPainSoundsPlugin.LogInfo("Impact sounds enabled: " + enabled); } public void SetImpactVolumeMultiplier(float multiplier) { impactVolumeMultiplier = Mathf.Clamp(multiplier, 0f, 5f); PlayerPainSoundsPlugin.LogInfo("Impact volume multiplier set to: " + multiplier); } public void SetEnablePainSounds(bool enabled) { enablePainSounds = enabled; PlayerPainSoundsPlugin.LogInfo("Pain sounds enabled: " + enabled); } public void SetPreventPainOverlap(bool enabled) { preventPainOverlap = enabled; PlayerPainSoundsPlugin.LogInfo("Prevent pain overlap enabled: " + enabled); } private float GetImpactVolumeMultiplier() { return impactVolumeMultiplier; } private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); audioSource = ((Component)this).gameObject.AddComponent<AudioSource>(); audioSource.spatialBlend = 1f; audioSource.minDistance = 0.1f; audioSource.maxDistance = 15f; audioSource.rolloffMode = (AudioRolloffMode)0; audioSource2D = ((Component)this).gameObject.AddComponent<AudioSource>(); audioSource2D.spatialBlend = 0f; audioSource2D.volume = 1f; audioSource2D.priority = 0; audioSource.priority = 128; lastStandAudioSource = ((Component)this).gameObject.AddComponent<AudioSource>(); lastStandAudioSource.spatialBlend = 0f; lastStandAudioSource.minDistance = 1f; lastStandAudioSource.maxDistance = 15f; lastStandAudioSource.rolloffMode = (AudioRolloffMode)1; lastStandAudioSource.loop = true; lastStandAudioSource.playOnAwake = false; impactAudioSource = ((Component)this).gameObject.AddComponent<AudioSource>(); impactAudioSource.spatialBlend = 1f; impactAudioSource.minDistance = 0.1f; impactAudioSource.maxDistance = 25f; impactAudioSource.rolloffMode = (AudioRolloffMode)1; impactAudioSource.priority = 64; } else { Object.Destroy((Object)(object)((Component)this).gameObject); } } private void Update() { if ((Object)(object)lastStandAudioSource != (Object)null && lastStandAudioSource.isPlaying) { UpdateFadeState(); } } private void UpdateFadeState() { if (isFadingIn) { float num = Mathf.Clamp01((Time.time - fadeStartTime) / 2f); lastStandAudioSource.volume = Mathf.Lerp(0f, targetVolume, num); if (num >= 1f) { isFadingIn = false; } } else if (isFadingOut) { float num2 = Mathf.Clamp01((Time.time - fadeStartTime) / 2f); lastStandAudioSource.volume = Mathf.Lerp(targetVolume, 0f, num2); if (num2 >= 1f) { lastStandAudioSource.Stop(); isFadingOut = false; isInLastStand = false; } } } private void StartFadeIn(AudioSource source, float targetVol, float duration) { source.volume = 0f; targetVolume = targetVol * GetVolumeMultiplier(); fadeStartTime = Time.time; isFadingIn = true; isFadingOut = false; } private void StartFadeOut(AudioSource source, float duration) { targetVolume = source.volume; fadeStartTime = Time.time; isFadingOut = true; isFadingIn = false; } public void PlayerStateCheck() { if ((Object)(object)GM.CurrentPlayerBody == (Object)null || !hasInitialized) { hasInitialized = true; } else { if (PlayerPainSoundsPlugin.IsPlayerDead()) { return; } float num = GM.CurrentPlayerBody.GetPlayerHealthRaw(); float num2 = GM.CurrentPlayerBody.GetMaxHealthPlayerRaw(); if (num2 <= 0f) { return; } float num3 = num / num2; CheckCriticalHealthState(num3); if (!isLastStandEnabled) { if (isInLastStand) { isInLastStand = false; StopLastStandSound(); } return; } shouldBeInLastStand = num3 <= lastStandThreshold && !isDying; if (shouldBeInLastStand && !isInLastStand && !lastStandAudioSource.isPlaying) { isInLastStand = true; StartLastStandSound(); } else if (!shouldBeInLastStand && isInLastStand) { isInLastStand = false; StopLastStandSound(); } } } private void CheckCriticalHealthState(float healthPercent) { if (isCriticalHealthEnabled) { bool flag = healthPercent <= criticalHealthThreshold; if (flag && !hasCriticalHealthTriggered && !isDying) { ((MonoBehaviour)this).StartCoroutine(PlayCriticalHealthSoundWithDelay()); hasCriticalHealthTriggered = true; } else if (!flag && hasCriticalHealthTriggered) { hasCriticalHealthTriggered = false; } } } private IEnumerator PlayCriticalHealthSoundWithDelay() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PlayCriticalHealthSoundWithDelay>d__79(0) { <>4__this = this }; } private AudioClip GetDefaultCriticalHealthSound() { return Resources.Load<AudioClip>("Sounds/Default/critical_health"); } private void StartLastStandSound() { if (isLastStandEnabled && !((Object)(object)lastStandAudioSource == (Object)null) && !lastStandAudioSource.isPlaying) { AudioClip val = null; if (currentSoundPack == "Default") { val = GetDefaultLastStandSound(); } else if (injurySounds.ContainsKey(currentSoundPack) && injurySounds[currentSoundPack].ContainsKey("last_stand") && injurySounds[currentSoundPack]["last_stand"].Count > 0) { List<AudioClip> sounds = injurySounds[currentSoundPack]["last_stand"]; val = GetUniqueRandomSound("last_stand", sounds); } if ((Object)(object)val == (Object)null) { isInLastStand = false; return; } lastStandAudioSource.clip = val; StartFadeIn(lastStandAudioSource, 1f, 2f); lastStandAudioSource.Play(); } } private void StopLastStandSound() { if ((Object)(object)lastStandAudioSource != (Object)null && lastStandAudioSource.isPlaying) { StartFadeOut(lastStandAudioSource, 2f); } } public IEnumerator StartLoadingSoundPacks() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <StartLoadingSoundPacks>d__83(0) { <>4__this = this }; } public void StopAllSounds() { if ((Object)(object)audioSource != (Object)null) { audioSource.Stop(); audioSource.clip = null; } if ((Object)(object)audioSource2D != (Object)null) { audioSource2D.Stop(); audioSource2D.clip = null; } if ((Object)(object)impactAudioSource != (Object)null) { impactAudioSource.Stop(); impactAudioSource.clip = null; } if ((Object)(object)lastStandAudioSource != (Object)null) { lastStandAudioSource.Stop(); lastStandAudioSource.clip = null; isFadingIn = false; isFadingOut = false; } lastPlayedInjuryClip = null; lastInjurySoundTime = 0f; lastImpactSoundTime = 0f; } public void SetSoundPack(string packName) { if (!string.IsNullOrEmpty(packName) && !(packName == currentSoundPack)) { PlayerPainSoundsPlugin.LogInfo("Switching sound pack from '" + currentSoundPack + "' to '" + packName + "'"); if ((Object)(object)audioSource != (Object)null) { audioSource.Stop(); } if ((Object)(object)audioSource2D != (Object)null) { audioSource2D.Stop(); } if ((Object)(object)lastStandAudioSource != (Object)null && lastStandAudioSource.isPlaying) { ((MonoBehaviour)this).StartCoroutine(TransitionLastStandSound(packName)); } else { SwitchSoundPackDirect(packName); } } } private void SwitchSoundPackDirect(string packName) { if (packName == "Default") { currentSoundPack = "Default"; ClearLoadedSounds(); LoadDefaultSounds(); PlayerPainSoundsPlugin.LogInfo("Switched to Default sound pack"); PlayerStateCheck(); } else if (!injurySounds.ContainsKey(packName) || !deathSounds.ContainsKey(packName) || !availableCategories.ContainsKey(packName)) { PlayerPainSoundsPlugin.LogInfo("Loading sounds for pack: " + packName); ((MonoBehaviour)this).StartCoroutine(LoadSinglePackAndSwitch(packName)); } else { currentSoundPack = packName; PlayerPainSoundsPlugin.LogInfo("Switched to sound pack: " + packName); PlayerStateCheck(); } } private IEnumerator TransitionLastStandSound(string newPackName) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TransitionLastStandSound>d__87(0) { <>4__this = this, newPackName = newPackName }; } private IEnumerator LoadCustomSoundPacks() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadCustomSoundPacks>d__88(0) { <>4__this = this }; } private void InitializePackDictionaries(string packName) { if (!injurySounds.ContainsKey(packName)) { injurySounds[packName] = new Dictionary<string, List<AudioClip>>(); } if (!deathSounds.ContainsKey(packName)) { deathSounds[packName] = new Dictionary<string, List<AudioClip>>(); } if (!impactSounds.ContainsKey(packName)) { impactSounds[packName] = new Dictionary<string, List<AudioClip>>(); } if (!availableCategories.ContainsKey(packName)) { availableCategories[packName] = new HashSet<string>(); } } private IEnumerator LoadSoundPackCategories(string packName, string packPath) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadSoundPackCategories>d__90(0) { <>4__this = this, packName = packName, packPath = packPath }; } private IEnumerator LoadSinglePackAndSwitch(string packName) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadSinglePackAndSwitch>d__91(0) { <>4__this = this, packName = packName }; } private void LoadDefaultSounds() { LoadDefaultInjurySounds(); LoadDefaultDeathSounds(); LoadDefaultLastStandSound(); } private void LoadDefaultInjurySounds() { if (!injurySounds.ContainsKey("Default")) { injurySounds["Default"] = new Dictionary<string, List<AudioClip>>(); } string[] aLL_CATEGORIES = SoundCategories.ALL_CATEGORIES; foreach (string key in aLL_CATEGORIES) { if (SoundCategories.IS_INJURY_CATEGORY[key] && !injurySounds["Default"].ContainsKey(key)) { injurySounds["Default"][key] = new List<AudioClip>(); } } } private void LoadDefaultDeathSounds() { if (!deathSounds.ContainsKey("Default")) { deathSounds["Default"] = new Dictionary<string, List<AudioClip>>(); } if (!deathSounds["Default"].ContainsKey("death")) { deathSounds["Default"]["death"] = new List<AudioClip>(); } } private void LoadDefaultLastStandSound() { if (!injurySounds.ContainsKey("Default")) { injurySounds["Default"] = new Dictionary<string, List<AudioClip>>(); } if (!injurySounds["Default"].ContainsKey("last_stand")) { injurySounds["Default"]["last_stand"] = new List<AudioClip>(); } if (!injurySounds["Default"].ContainsKey("critical_health")) { injurySounds["Default"]["critical_health"] = new List<AudioClip>(); } } private void ClearLoadedSounds() { foreach (string item in injurySounds.Keys.ToList()) { injurySounds[item].Clear(); } foreach (string item2 in deathSounds.Keys.ToList()) { deathSounds[item2].Clear(); } foreach (string item3 in impactSounds.Keys.ToList()) { impactSounds[item3].Clear(); } availableCategories.Clear(); if (lastPlayedClips != null) { lastPlayedClips.Clear(); } } public bool HasSoundsInCategory(string packName, string category) { if (injurySounds.ContainsKey(packName) && injurySounds[packName].ContainsKey(category)) { return injurySounds[packName][category].Count > 0; } return false; } public bool HasDeathSoundsInCategory(string packName, string category) { if (deathSounds.ContainsKey(packName) && deathSounds[packName].ContainsKey(category)) { return deathSounds[packName][category].Count > 0; } return false; } public void PlayInjurySound(Vector3 position) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (enablePainSounds && injurySounds.ContainsKey(currentSoundPack) && !((Object)(object)GM.CurrentPlayerBody == (Object)null) && !((float)GM.CurrentPlayerBody.GetPlayerHealthRaw() <= 0f) && !PlayerPainSoundsPlugin.IsPlayerDead() && !isDying) { PlayInjurySoundInternal(position, 1f, (PlayerHitBoxType)1, null); } } public void PlayInjurySound(Vector3 position, float distanceMult) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (enablePainSounds && injurySounds.ContainsKey(currentSoundPack) && !((Object)(object)GM.CurrentPlayerBody == (Object)null) && !((float)GM.CurrentPlayerBody.GetPlayerHealthRaw() <= 0f) && !PlayerPainSoundsPlugin.IsPlayerDead() && !isDying) { PlayInjurySoundInternal(position, distanceMult, (PlayerHitBoxType)1, null); } } public void PlayInjurySound(Vector3 position, float distanceMult, PlayerHitBoxType hitboxType) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (enablePainSounds && injurySounds.ContainsKey(currentSoundPack) && !((Object)(object)GM.CurrentPlayerBody == (Object)null) && !((float)GM.CurrentPlayerBody.GetPlayerHealthRaw() <= 0f) && !PlayerPainSoundsPlugin.IsPlayerDead() && !isDying) { PlayInjurySoundInternal(position, distanceMult, hitboxType, null); } } public void PlayInjurySound(Vector3 position, float distanceMult, PlayerHitBoxType hitboxType, Damage damage) { //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) if (!enablePainSounds || isTransitioningPacks || !hasInitialized || currentSoundPack == "Default") { return; } if ((Object)(object)GM.CurrentPlayerBody == (Object)null) { PlayerPainSoundsPlugin.LogInfo("Pain blocked - CurrentPlayerBody is null"); return; } float num = GM.CurrentPlayerBody.GetPlayerHealthRaw(); if (num <= 0f) { PlayerPainSoundsPlugin.LogInfo("Pain blocked - player health is " + num + " (dead)"); return; } if (PlayerPainSoundsPlugin.IsPlayerDead() || isDying) { PlayerPainSoundsPlugin.LogInfo("Pain blocked - player dead or dying"); return; } if (damage == null) { if (PlayerPainSoundsPlugin.configDebugMessages.Value) { PlayerPainSoundsPlugin.LogInfo("PlayInjurySound called with null damage - pain sound blocked"); } return; } float num2 = damage.Dam_TotalKinetic + damage.Dam_TotalEnergetic; if (num2 <= 0f) { if (PlayerPainSoundsPlugin.configDebugMessages.Value) { PlayerPainSoundsPlugin.LogInfo($"PlayInjurySound called with zero damage ({num2}) - pain sound blocked"); } } else if (!playPainWithDeath && num - num2 <= 0f) { PlayerPainSoundsPlugin.LogInfo("Pain blocked - damage would be lethal and play pain with death is disabled"); } else { PlayInjurySoundInternalWithDamage(position, distanceMult, hitboxType, null, num2); } } public void PlayInjurySoundWithDamage(Vector3 position, float distanceMult, PlayerHitBoxType hitboxType, float damageAmount) { //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) if (!enablePainSounds || isTransitioningPacks || !hasInitialized || currentSoundPack == "Default") { return; } if ((Object)(object)GM.CurrentPlayerBody == (Object)null) { PlayerPainSoundsPlugin.LogInfo("Pain blocked - CurrentPlayerBody is null"); return; } float num = GM.CurrentPlayerBody.GetPlayerHealthRaw(); if (num <= 0f) { PlayerPainSoundsPlugin.LogInfo("Pain blocked - player health is " + num + " (dead)"); } else if (PlayerPainSoundsPlugin.IsPlayerDead() || isDying) { PlayerPainSoundsPlugin.LogInfo("Pain blocked - player dead or dying"); } else if (damageAmount <= 0f) { if (PlayerPainSoundsPlugin.configDebugMessages.Value) { PlayerPainSoundsPlugin.LogInfo($"PlayInjurySoundWithDamage called with zero damage ({damageAmount}) - pain sound blocked"); } } else if (!playPainWithDeath && num - damageAmount <= 0f) { PlayerPainSoundsPlugin.LogInfo("Pain blocked - damage would be lethal and play pain with death is disabled"); } else { PlayInjurySoundInternalWithDamage(position, distanceMult, hitboxType, null, damageAmount); } } public void OnPlayerHitDetected(PlayerHitBoxType hitboxType, float damageAmount, Vector3 position) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (PlayerPainSoundsPlugin.configDebugMessages.Value) { PlayerPainSoundsPlugin.LogInfo($"Hit detected on {hitboxType}: damage={damageAmount}, position={position}"); } } public void PlayImpactSound(Vector3 position, Damage damage) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (enableImpactSounds && damage != null && !(Time.time - lastImpactSoundTime < 0.05f)) { string impactSoundCategory = DamageCalculationHelper.GetImpactSoundCategory(damage); string actualCategory; AudioClip impactSoundAndCategory = GetImpactSoundAndCategory(impactSoundCategory, out actualCategory); if ((Object)(object)impactSoundAndCategory != (Object)null) { float num = 1f * GetImpactVolumeMultiplier(); float pitch = Random.Range(0.98f, 1.02f); ((Component)impactAudioSource).transform.position = position; impactAudioSource.pitch = pitch; impactAudioSource.PlayOneShot(impactSoundAndCategory, num); lastImpactSoundTime = Time.time; PlayerPainSoundsPlugin.LogInfo($"Playing impact sound: {actualCategory} at {position}"); } } } public void PlayImpactSoundWithType(Vector3 position, PlayerHitBoxType hitboxType, float damageAmount) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (enableImpactSounds && !(Time.time - lastImpactSoundTime < 0.05f)) { string impactSoundCategory = DamageCalculationHelper.GetImpactSoundCategory(hitboxType, damageAmount); string actualCategory; AudioClip impactSoundAndCategory = GetImpactSoundAndCategory(impactSoundCategory, out actualCategory); if ((Object)(object)impactSoundAndCategory != (Object)null) { float num = 1f * GetImpactVolumeMultiplier(); float pitch = Random.Range(0.98f, 1.02f); ((Component)impactAudioSource).transform.position = position; impactAudioSource.pitch = pitch; impactAudioSource.PlayOneShot(impactSoundAndCategory, num); lastImpactSoundTime = Time.time; PlayerPainSoundsPlugin.LogInfo($"Playing impact sound: {actualCategory} at {position}"); } } } private AudioClip GetImpactSound(string category) { string actualCategory; return GetImpactSoundAndCategory(category, out actualCategory); } private AudioClip GetImpactSoundAndCategory(string category, out string actualCategory) { actualCategory = category; if (!impactSounds.ContainsKey(currentSoundPack)) { PlayerPainSoundsPlugin.LogInfo("No impact sounds loaded for current sound pack: " + currentSoundPack); return null; } if (impactSounds[currentSoundPack].ContainsKey(category) && impactSounds[currentSoundPack][category].Count > 0) { List<AudioClip> list = impactSounds[currentSoundPack][category]; int index = Random.Range(0, list.Count); PlayerPainSoundsPlugin.LogInfo($"Using impact category: {category} ({list.Count} sounds available)"); return list[index]; } if (category != "impact_default") { PlayerPainSoundsPlugin.LogInfo(string.Format("Impact category {0} not found, falling back to {1}", category, "impact_default")); actualCategory = "impact_default"; return GetImpactSoundAndCategory("impact_default", out actualCategory); } if (impactSounds[currentSoundPack].Count > 0) { string arg = string.Join(", ", impactSounds[currentSoundPack].Keys.ToArray()); PlayerPainSoundsPlugin.LogInfo($"Impact category {category} not found. Available impact categories: {arg}"); } else { PlayerPainSoundsPlugin.LogInfo("No impact sounds available in current sound pack"); } return null; } private void PlayInjurySoundInternal(Vector3 position, float distanceMult, PlayerHitBoxType hitboxType, AudioClip forcedClip) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) PlayInjurySoundInternalWithDamage(position, distanceMult, hitboxType, forcedClip, 0f); } private void PlayInjurySoundInternalWithDamage(Vector3 position, float distanceMult, PlayerHitBoxType hitboxType, AudioClip forcedClip, float damageAmount) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) try { if (!enablePainSounds) { return; } if (preventPainOverlap && (audioSource.isPlaying || audioSource2D.isPlaying)) { PlayerPainSoundsPlugin.LogInfo("Pain sound blocked due to overlap prevention - previous sound still playing"); return; } if (Time.time - lastInjurySoundTime < 0.1f) { PlayerPainSoundsPlugin.LogInfo("Pain sound rate limited - too soon after last sound"); return; } Vector3 position2 = ((Component)GM.CurrentPlayerBody.Head).transform.position; if (isTransitioningPacks || !hasInitialized || currentSoundPack == "Default" || Time.time - lastInjurySoundTime < 0.1f) { return; } if (!injurySounds.ContainsKey(currentSoundPack)) { PlayerPainSoundsPlugin.LogWarning("No injury sounds found for current sound pack: " + currentSoundPack); return; } AudioClip val = forcedClip; if ((Object)(object)val == (Object)null) { if ((Object)(object)GM.CurrentPlayerBody == (Object)null) { return; } val = ((!(damageAmount > 0f)) ? GetAppropriateSound() : GetAppropriateSoundForDamage(damageAmount)); } if (!((Object)(object)val != (Object)null)) { return; } float num = 1f * distanceMult * GetVolumeMultiplier(); float pitch = Random.Range(0.98f, 1.02f); float num2 = 0f; if (enableImpactSounds) { float num3 = Time.time - lastImpactSoundTime; num2 = 0.25f - num3; if (num2 < 0f) { num2 = 0f; } } float spatialVolume = num * 0.2f; lastInjurySoundTime = Time.time; ((MonoBehaviour)this).StartCoroutine(PlayInjuryClipsWithDelay(val, spatialVolume, num, pitch, position2, num2)); } catch (Exception ex) { PlayerPainSoundsPlugin.LogError("Error in PlayInjurySoundInternalWithDamage: " + ex.Message); } } private IEnumerator PlayInjuryClipsWithDelay(AudioClip clip, float spatialVolume, float volume2D, float pitch, Vector3 headPosition, float delay) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PlayInjuryClipsWithDelay>d__111(0) { <>4__this = this, clip = clip, spatialVolume = spatialVolume, volume2D = volume2D, pitch = pitch, headPosition = headPosition, delay = delay }; } private AudioClip GetAppropriateSound() { float num = GM.CurrentPlayerBody.GetPlayerHealthRaw(); float num2 = GM.CurrentPlayerBody.GetMaxHealthPlayerRaw(); if (num2 <= 0f) { return null; } float num3 = num / num2; string text = "pain_default"; List<AudioClip> list = null; if (num3 <= 0.5f && injurySounds[currentSoundPack].ContainsKey("pain_high")) { list = injurySounds[currentSoundPack]["pain_high"]; if (list != null && list.Count > 0) { text = "pain_high"; } } if (list == null || list.Count == 0) { text = "pain_default"; if (injurySounds[currentSoundPack].ContainsKey("pain_default") && injurySounds[currentSoundPack]["pain_default"].Count > 0) { list = injurySounds[currentSoundPack]["pain_default"]; } } if ((list == null || list.Count == 0) && injurySounds[currentSoundPack].ContainsKey("pain_low")) { list = injurySounds[currentSoundPack]["pain_low"]; if (list != null && list.Count > 0) { text = "pain_low"; } } if (list == null || list.Count == 0) { text = "pain_default"; if (injurySounds[currentSoundPack].ContainsKey("pain_default") && injurySounds[currentSoundPack]["pain_default"].Count > 0) { list = injurySounds[currentSoundPack]["pain_default"]; } } if (list != null && list.Count > 0) { AudioClip uniqueRandomSound = GetUniqueRandomSound(text, list); PlayerPainSoundsPlugin.LogInfo("Selected sound from category: " + text + " (health-based fallback)"); return uniqueRandomSound; } return null; } private AudioClip GetAppropriateSoundForDamage(float damageAmount) { float num = GM.CurrentPlayerBody.GetMaxHealthPlayerRaw(); if (num <= 0f || damageAmount <= 0f) { return null; } DamageCalculationHelper.DamageInfo damageInfo = default(DamageCalculationHelper.DamageInfo); damageInfo.TotalDamage = damageAmount; damageInfo.DamagePercentage = damageAmount / num; string text = DamageCalculationHelper.GetSoundCategoryForDamage(damageInfo); List<AudioClip> list = null; if (injurySounds[currentSoundPack].ContainsKey(text) && injurySounds[currentSoundPack][text].Count > 0) { list = injurySounds[currentSoundPack][text]; } if (list == null || list.Count == 0) { text = "pain_default"; if (injurySounds[currentSoundPack].ContainsKey("pain_default") && injurySounds[currentSoundPack]["pain_default"].Count > 0) { list = injurySounds[currentSoundPack]["pain_default"]; } } if (list == null || list.Count == 0) { if (injurySounds[currentSoundPack].ContainsKey("pain_high") && injurySounds[currentSoundPack]["pain_high"].Count > 0) { list = injurySounds[currentSoundPack]["pain_high"]; text = "pain_high"; } else if (injurySounds[currentSoundPack].ContainsKey("pain_low") && injurySounds[currentSoundPack]["pain_low"].Count > 0) { list = injurySounds[currentSoundPack]["pain_low"]; text = "pain_low"; } } if (list != null && list.Count > 0) { AudioClip uniqueRandomSound = GetUniqueRandomSound(text, list); PlayerPainSoundsPlugin.LogInfo($"Selected sound from category: {text} (damage={damageAmount:F2}, damagePercent={damageInfo.DamagePercentage * 100f:F1}%)"); return uniqueRandomSound; } return null; } private AudioClip GetUniqueRandomSound(string category, List<AudioClip> sounds) { if (sounds == null || sounds.Count == 0) { return null; } if (sounds.Count == 1) { return sounds[0]; } AudioClip val = null; if (lastPlayedClips.ContainsKey(category)) { val = lastPlayedClips[category]; } List<AudioClip> list = sounds; if ((Object)(object)val != (Object)null) { List<AudioClip> list2 = new List<AudioClip>(); foreach (AudioClip sound in sounds) { if ((Object)(object)sound != (Object)(object)val) { list2.Add(sound); } } if (list2.Count > 0) { list = list2; } } AudioClip val2 = list[Random.Range(0, list.Count)]; lastPlayedClips[category] = val2; return val2; } public void PlayDeathSound() { //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)audioSource == (Object)null || currentSoundPack == "Default") { return; } try { if (m_hasPlayedDeathSound) { PlayerPainSoundsPlugin.LogInfo("Death sound already played, ignoring duplicate call"); return; } m_hasPlayedDeathSound = true; isDying = true; StopLastStandSound(); PlayerPainSoundsPlugin.LogInfo("Playing death sound (flag set to prevent duplicates)"); if (!deathSounds.ContainsKey(currentSoundPack)) { PlayerPainSoundsPlugin.LogWarning("No death sounds dictionary found for pack: " + currentSoundPack); return; } if (!deathSounds[currentSoundPack].ContainsKey("death")) { PlayerPainSoundsPlugin.LogWarning("No death sounds category found for pack: " + currentSoundPack); return; } List<AudioClip> list = deathSounds[currentSoundPack]["death"]; if (list == null || list.Count == 0) { PlayerPainSoundsPlugin.LogInfo("No death sounds available in death category for pack: " + currentSoundPack); return; } AudioClip uniqueRandomSound = GetUniqueRandomSound("death", list); if (playPainWithDeath) { ((MonoBehaviour)this).StartCoroutine(PlayPainAndDeathSequence(uniqueRandomSound)); } else if ((Object)(object)uniqueRandomSound != (Object)null) { Vector3 position = GM.CurrentPlayerBody.Head.position; float num = 1f * GetVolumeMultiplier(); ((Component)audioSource).transform.position = position; audioSource.spatialBlend = 1f; float num2 = num * 0.2f; audioSource.PlayOneShot(uniqueRandomSound, num2); audioSource2D.PlayOneShot(uniqueRandomSound, num); PlayerPainSoundsPlugin.LogInfo($"Playing death sound at head position: {position}"); ((MonoBehaviour)this).StartCoroutine(ResetStateAfterDeathSound()); } } catch (Exception ex) { PlayerPainSoundsPlugin.LogError("Error in PlayDeathSound: " + ex.Message); } } private IEnumerator PlayPainAndDeathSequence(AudioClip deathSound) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PlayPainAndDeathSequence>d__116(0) { <>4__this = this, deathSound = deathSound }; } public void ResetDyingState() { isDying = false; m_hasPlayedDeathSound = false; hasCriticalHealthTriggered = false; StopAllSounds(); } private AudioClip GetDefaultLastStandSound() { return Resources.Load<AudioClip>("Sounds/Default/last_stand"); } public AudioClip GetRandomSound(string category) { if (injurySounds.ContainsKey(currentSoundPack) && injurySounds[currentSoundPack].ContainsKey(category) && injurySounds[currentSoundPack][category].Count > 0) { List<AudioClip> list = injurySounds[currentSoundPack][category]; return list[Random.Range(0, list.Count)]; } return null; } public void PlaySoundAtPosition(AudioClip clip, Vector3 position, float distanceMult) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)audioSource == (Object)null) { PlayerPainSoundsPlugin.LogError("AudioSource is null when trying to play sound"); return; } if ((Object)(object)clip == (Object)null) { PlayerPainSoundsPlugin.LogError("AudioClip is null when trying to play sound"); return; } if (audioSource.spatialBlend != 1f) { audioSource.spatialBlend = 1f; PlayerPainSoundsPlugin.LogWarning("Reset audio source spatial blend to 3D"); } if (audioSource.isPlaying) { audioSource.Stop(); } Vector3 position2 = GM.CurrentPlayerBody.Head.position; ((Component)audioSource).transform.position = position2; audioSource.volume = 1f * distanceMult * GetVolumeMultiplier(); audioSource.pitch = Random.Range(0.98f, 1.02f); audioSource.clip = clip; audioSource.Play(); string[] obj = new string[10] { "Playing sound: ", ((Object)clip).name, " at head position ", null, null, null, null, null, null, null }; Vector3 val = position2; obj[3] = ((object)(Vector3)(ref val)).ToString(); obj[4] = " with volume "; obj[5] = audioSource.volume.ToString(); obj[6] = " and spatial blend "; obj[7] = audioSource.spatialBlend.ToString(); obj[8] = " and priority "; obj[9] = audioSource.priority.ToString(); PlayerPainSoundsPlugin.LogInfo(string.Concat(obj)); } private IEnumerator ResetStateAfterDeathSound() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ResetStateAfterDeathSound>d__121(0) { <>4__this = this }; } private IEnumerator LoadSoundFile(string file, List<AudioClip> clips, string category) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadSoundFile>d__122(0) { file = file, clips = clips, category = category }; } } public static class PlayerDeathPatches { [HarmonyPatch(typeof(FVRPlayerBody))] public class PlayerBodyDeathPatches { [HarmonyPostfix] [HarmonyPatch("RegisterPlayerHit", new Type[] { typeof(float), typeof(bool), typeof(int) })] private static void RegisterPlayerHitPostfix(FVRPlayerBody __instance, float DamagePoints, bool FromSelf, int iff, bool __result) { try { if (PlayerPainSoundsPlugin.IsManagerReady() && !((Object)(object)InjurySoundManager.Instance == (Object)null) && !((Object)(object)GM.CurrentPlayerBody == (Object)null) && __result && !InjurySoundManager.Instance.m_hasPlayedDeathSound) { PlayerPainSoundsPlugin.LogInfo("Player death confirmed via RegisterPlayerHit return value"); InjurySoundManager.Instance.IsDying = true; if (InjurySoundManager.Instance.CurrentSoundPack != "Default") { InjurySoundManager.Instance.PlayDeathSound(); return; } InjurySoundManager.Instance.m_hasPlayedDeathSound = true; PlayerPainSoundsPlugin.LogInfo("Death detected but using Default pack - not playing custom death sound"); } } catch (Exception ex) { PlayerPainSoundsPlugin.LogError("Error in RegisterPlayerHit death detection: " + ex.Message); } } [HarmonyPostfix] [HarmonyPatch("HarmPercent")] private static void HarmPercentPostfix(FVRPlayerBody __instance, float f) { try { if (!PlayerPainSoundsPlugin.IsManagerReady() || (Object)(object)InjurySoundManager.Instance == (Object)null || (Object)(object)GM.CurrentPlayerBody == (Object)null) { return; } float num = __instance.GetPlayerHealthRaw(); if (num <= 0f && !InjurySoundManager.Instance.m_hasPlayedDeathSound) { PlayerPainSoundsPlugin.LogInfo("Player death detected via HarmPercent - health: " + num); InjurySoundManager.Instance.IsDying = true; if (InjurySoundManager.Instance.CurrentSoundPack != "Default") { InjurySoundManager.Instance.PlayDeathSound(); return; } InjurySoundManager.Instance.m_hasPlayedDeathSound = true; PlayerPainSoundsPlugin.LogInfo("Death detected via HarmPercent but using Default pack"); } } catch (Exception ex) { PlayerPainSoundsPlugin.LogError("Error in HarmPercent death detection: " + ex.Message); } } } [HarmonyPatch(typeof(MG_Narrator))] public class NarratorPatches { [HarmonyPostfix] [HarmonyPatch("PlayDiedCheating")] private static void PlayDiedCheatingPostfix() { try { if (PlayerPainSoundsPlugin.IsManagerReady() && !((Object)(object)InjurySoundManager.Instance == (Object)null) && !((Object)(object)GM.CurrentPlayerBody == (Object)null) && !InjurySoundManager.Instance.m_hasPlayedDeathSound) { PlayerPainSoundsPlugin.LogInfo("Player death confirmed via PlayDiedCheating"); InjurySoundManager.Instance.IsDying = true; if (InjurySoundManager.Instance.CurrentSoundPack != "Default") { InjurySoundManager.Instance.PlayDeathSound(); return; } InjurySoundManager.Instance.m_hasPlayedDeathSound = true; PlayerPainSoundsPlugin.LogInfo("Death confirmed via PlayDiedCheating but using Default pack"); } } catch (Exception ex) { PlayerPainSoundsPlugin.LogError("Error in PlayDiedCheating death detection: " + ex.Message); } } [HarmonyPostfix] [HarmonyPatch("PlayDiedOutOfHealth")] private static void PlayDiedOutOfHealthPostfix() { try { if (PlayerPainSoundsPlugin.IsManagerReady() && !((Object)(object)InjurySoundManager.Instance == (Object)null) && !((Object)(object)GM.CurrentPlayerBody == (Object)null) && !InjurySoundManager.Instance.m_hasPlayedDeathSound) { PlayerPainSoundsPlugin.LogInfo("Player death confirmed via PlayDiedOutOfHealth"); InjurySoundManager.Instance.IsDying = true; if (InjurySoundManager.Instance.CurrentSoundPack != "Default") { InjurySoundManager.Instance.PlayDeathSound(); return; } InjurySoundManager.Instance.m_hasPlayedDeathSound = true; PlayerPainSoundsPlugin.LogInfo("Death confirmed via PlayDiedOutOfHealth but using Default pack"); } } catch (Exception ex) { PlayerPainSoundsPlugin.LogError("Error in PlayDiedOutOfHealth death detection: " + ex.Message); } } } [HarmonyPatch(typeof(GM))] [HarmonyPriority(600)] public class GMDeathPatches { [HarmonyPostfix] [HarmonyPatch("KillPlayer", new Type[] { typeof(bool), typeof(int) })] private static void KillPlayerPostfix(bool KilledSelf, int iff) { try { if (PlayerPainSoundsPlugin.IsManagerReady() && !((Object)(object)InjurySoundManager.Instance == (Object)null) && !InjurySoundManager.Instance.m_hasPlayedDeathSound) { PlayerPainSoundsPlugin.LogInfo("Player death confirmed via GM.KillPlayer"); InjurySoundManager.Instance.IsDying = true; if (InjurySoundManager.Instance.CurrentSoundPack != "Default") { InjurySoundManager.Instance.PlayDeathSound(); return; } InjurySoundManager.Instance.m_hasPlayedDeathSound = true; PlayerPainSoundsPlugin.LogInfo("Death confirmed via GM.KillPlayer but using Default pack"); } } catch (Exception ex) { PlayerPainSoundsPlugin.LogError("Error in GM.KillPlayer death detection: " + ex.Message); } } } [HarmonyPatch(typeof(FVRSceneSettings))] public class SceneSet