Decompiled source of Dynamic Audio Balancing v1.1.0

Sirdoggy.DynamicAudioBalancing.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FMOD.Studio;
using FistVR;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Sirdoggy.DynamicAudioBalancing.Common;
using Sirdoggy.DynamicAudioBalancing.Extensions;
using Sirdoggy.DynamicAudioBalancing.Patches;
using Sirdoggy.DynamicAudioBalancing.Patches.Firearms;
using Sirdoggy.DynamicAudioBalancing.Patches.Tags;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("Sirdoggy")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Makes sustained gunfire less deafening + adds volume controls for different in-game sounds")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("Sirdoggy.DynamicAudioBalancing")]
[assembly: AssemblyTitle("Dynamic_Audio_Balancing")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace Sirdoggy.DynamicAudioBalancing
{
	[BepInProcess("h3vr.exe")]
	[BepInPlugin("Sirdoggy.DynamicAudioBalancing", "Dynamic_Audio_Balancing", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log = null;

		internal static ExceptionCatcher ExceptionCatcher = null;

		private static float _masterVolumeMultiplier = 1f;

		public const string Id = "Sirdoggy.DynamicAudioBalancing";

		public static string Name => "Dynamic_Audio_Balancing";

		public static string Version => "1.1.0";

		public static void LogVerbose(object data)
		{
			if (PluginConfig.VerboseLogs.Value)
			{
				Log.LogDebug(data);
			}
		}

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			ExceptionCatcher = new ExceptionCatcher(Log);
			PluginConfig.Initialize(((BaseUnityPlugin)this).Config);
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(SoundManagerPatcher), (string)null);
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(FVRPooledAudioSourcePatcher), (string)null);
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(Plugin), (string)null);
			});
		}

		private IEnumerator Start()
		{
			UpdateMasterVolume();
			PluginConfig.MasterVolume.SettingChanged += delegate
			{
				UpdateMasterVolume();
			};
			yield return (object)new WaitForSecondsRealtime(3f);
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(InitialCreateChamberTagPatchers), (string)null);
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(InitialCreateChamberTagPatchers2), (string)null);
			}, delegate(Exception exception)
			{
				if (exception is TypeLoadException)
				{
					Log.LogDebug((object)exception.Message);
				}
				else
				{
					Log.LogError((object)exception);
				}
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(FVRFireArmChamberPatcher), (string)null);
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(FVRFireArmPatcher), (string)null);
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(AudioSourcePatcher), (string)null);
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(MusicPatchers), (string)null);
			});
		}

		private static void UpdateMasterVolume()
		{
			_masterVolumeMultiplier = PluginConfig.MasterVolume.PercentToMultiplier();
			Log.LogInfo((object)$"Set master volume multiplier: {_masterVolumeMultiplier}");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(FVRPlayerBody), "Update")]
		private static void Update_Postfix_ApplyMasterVolume()
		{
			AudioListener.volume *= _masterVolumeMultiplier;
		}
	}
	internal static class PluginConfig
	{
		public static ConfigEntry<float> MasterVolume;

		public static ConfigEntry<float> Music;

		public static ConfigEntry<float> GunshotsMain;

		public static ConfigEntry<float> GunshotsReverb;

		public static ConfigEntry<float> GunshotsMechanical;

		public static ConfigEntry<float> OpenBoltPrefire;

		public static ConfigEntry<float> BulletCasings;

		public static ConfigEntry<float> PhysicsImpacts;

		public static ConfigEntry<float> SosigVoicelines;

		public static ConfigEntry<float> GunshotVolumePercentSemiAuto;

		public static ConfigEntry<float> GunshotVolumePercentSustainedFirst;

		public static ConfigEntry<float> GunshotVolumePercentSustainedSubsequent;

		public static ConfigEntry<float> ReverbVolumePercentSemiAuto;

		public static ConfigEntry<float> ReverbVolumePercentSustainedFirst;

		public static ConfigEntry<float> ReverbVolumePercentSustainedSubsequent;

		public static ConfigEntry<float> HammerHitVolumePercentSemiAuto;

		public static ConfigEntry<float> HammerHitVolumePercentSustainedFirst;

		public static ConfigEntry<float> HammerHitVolumePercentSustainedSubsequent;

		public static ConfigEntry<bool> ChangeVolumeOfDryFireHammerHit;

		public static ConfigEntry<bool> VerboseLogs;

		public static ConfigEntry<float> DelayBetweenShotsCalculationMargin;

		private const string SectionBaselineVolumes = "Baseline Volumes";

		private const string SectionDynamicGunshotVolumes = "Dynamic Gunshot Volumes";

		private const string SectionDynamicReverbVolumes = "Dynamic Reverb Volumes";

		private const string SectionDynamicHammerHitVolumes = "Dynamic Hammer Hit Volumes";

		private const string SectionSettings = "Settings";

		private const string SectionTesting = "Testing";

		public const float MaximumDelayMargin = 0.27f;

		public static void Initialize(ConfigFile configFile)
		{
			MasterVolume = configFile.Bind<float>("Baseline Volumes", "Master volume", 100f, "Baseline volume % for all sounds. Set value will be clamped between 0 and 200%.");
			Music = configFile.Bind<float>("Baseline Volumes", "Music", 100f, "Baseline volume % for music in T&H, Meat Fortress, and Return of the Rotwieners. Changes might require scene restart.");
			GunshotsMain = configFile.Bind<float>("Baseline Volumes", "Gunshots main", 100f, "Baseline volume % for all gunshot blasts.");
			GunshotsReverb = configFile.Bind<float>("Baseline Volumes", "Gunshots reverb", 100f, "Baseline volume % for all environment reverb after gunshots.");
			GunshotsMechanical = configFile.Bind<float>("Baseline Volumes", "Gunshots mechanical", 100f, "Baseline volume % for all mechanical sounds that accompany a gunshot. Doesn't affect manual weapon handling sounds.");
			OpenBoltPrefire = configFile.Bind<float>("Baseline Volumes", "Open bolt prefire", 100f, "Volume % for the open bolt delay sound that plays before the first gunshot. Mainly affects open bolt guns.");
			BulletCasings = configFile.Bind<float>("Baseline Volumes", "Bullet casings", 100f, "Volume % for spent bullet casings impact sounds.");
			PhysicsImpacts = configFile.Bind<float>("Baseline Volumes", "Physics impacts", 100f, "Volume % for most physics impact sounds.");
			SosigVoicelines = configFile.Bind<float>("Baseline Volumes", "Sosig voicelines", 100f, "Volume % for most sosig voicelines.");
			GunshotVolumePercentSemiAuto = configFile.Bind<float>("Dynamic Gunshot Volumes", "Semi-auto", 100f, "Volume % for gunshots when in semi-auto mode. Also affects single shot guns. Dynamic volumes are cumulative with baseline volumes.");
			GunshotVolumePercentSustainedFirst = configFile.Bind<float>("Dynamic Gunshot Volumes", "Sustained first", 100f, "Volume % for the first gunshot when beginning full-auto or burst fire.");
			GunshotVolumePercentSustainedSubsequent = configFile.Bind<float>("Dynamic Gunshot Volumes", "Sustained subsequent", 60f, "Volume % for gunshots during sustained full-auto or burst fire.");
			ReverbVolumePercentSemiAuto = configFile.Bind<float>("Dynamic Reverb Volumes", "Semi-auto", 100f, "Volume % for gunshot reverb when in semi-auto mode. Also affects single shot guns.");
			ReverbVolumePercentSustainedFirst = configFile.Bind<float>("Dynamic Reverb Volumes", "Sustained first", 100f, "Volume % for gunshot reverb when beginning full-auto or burst fire.");
			ReverbVolumePercentSustainedSubsequent = configFile.Bind<float>("Dynamic Reverb Volumes", "Sustained subsequent", 70f, "Volume % for gunshot reverb during sustained full-auto or burst fire.");
			HammerHitVolumePercentSemiAuto = configFile.Bind<float>("Dynamic Hammer Hit Volumes", "Semi-auto", 100f, "Volume % for hammer hits when in semi-auto mode. Also affects single shot guns.");
			HammerHitVolumePercentSustainedFirst = configFile.Bind<float>("Dynamic Hammer Hit Volumes", "Sustained first", 125f, "Volume % for the first hammer hit when beginning full-auto or burst fire.");
			HammerHitVolumePercentSustainedSubsequent = configFile.Bind<float>("Dynamic Hammer Hit Volumes", "Sustained subsequent", 40f, "Volume % for hammer hits during sustained full-auto or burst fire.");
			ChangeVolumeOfDryFireHammerHit = configFile.Bind<bool>("Settings", "Change volume of dry fire hammer hit", true, "When enabled, multipliers will affect the volume of the hammer hit that plays when your gun is empty. On some guns, like the AK, this hammer hit also plays after firing the last round.");
			VerboseLogs = configFile.Bind<bool>("Testing", "Enable verbose debug logs", false, "Extra logs that will noticeably spam the console.");
			DelayBetweenShotsCalculationMargin = configFile.Bind<float>("Testing", "Delay between shots calculation margin", 0.03f, "In seconds.");
		}
	}
}
namespace Sirdoggy.DynamicAudioBalancing.Patches
{
	[HarmonyPatch(typeof(AudioSource))]
	internal static class AudioSourcePatcher
	{
		private static readonly List<float> QueuedVolumeMultipliers = new List<float>();

		private static float _queuedTimestamp;

		public static void QueueVolumeMultiplier(float multiplier)
		{
			Plugin.LogVerbose(string.Format("[{0}] Queued new multiplier: x{1}", "AudioSourcePatcher", multiplier));
			QueuedVolumeMultipliers.Add(multiplier);
			_queuedTimestamp = Time.time;
		}

		[HarmonyPrefix]
		[HarmonyPatch("Play", new Type[] { typeof(ulong) })]
		private static void Play_Prefix(AudioSource __instance)
		{
			ApplyQueuedMultiplier(__instance);
		}

		private static void ApplyQueuedMultiplier(AudioSource audioSource)
		{
			if (QueuedVolumeMultipliers.Count == 0)
			{
				return;
			}
			if (Time.time - _queuedTimestamp > 0.27f)
			{
				Plugin.LogVerbose("[AudioSourcePatcher] Queued multipliers expired, returning.");
				QueuedVolumeMultipliers.Clear();
				return;
			}
			float num = 1f;
			foreach (float queuedVolumeMultiplier in QueuedVolumeMultipliers)
			{
				num *= queuedVolumeMultiplier;
			}
			int count = QueuedVolumeMultipliers.Count;
			QueuedVolumeMultipliers.Clear();
			if (!((Object)(object)audioSource.clip == (Object)null))
			{
				Plugin.LogVerbose("[AudioSourcePatcher] Consuming queued multipliers. " + $"Multiplying volume of AudioClip '{((Object)audioSource.clip).name}' by x{num} " + $"({count} multipliers total)");
				audioSource.volume *= num;
			}
		}
	}
	[HarmonyPatch(typeof(FVRPooledAudioSource))]
	internal static class FVRPooledAudioSourcePatcher
	{
		[HarmonyPrefix]
		[HarmonyPatch("Play")]
		private static void Play_Prefix(FVRPooledAudioSource __instance)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_0047: Invalid comparison between Unknown and I4
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Invalid comparison between Unknown and I4
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Invalid comparison between Unknown and I4
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Invalid comparison between Unknown and I4
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Invalid comparison between Unknown and I4
			AudioSourceTagAudioBalancing component = ((Component)__instance).GetComponent<AudioSourceTagAudioBalancing>();
			float? num = null;
			float? num2;
			if (component != null && component.Type.HasValue)
			{
				FVRPooledAudioType? type = component.Type;
				if (!type.HasValue)
				{
					goto IL_00c8;
				}
				FVRPooledAudioType valueOrDefault = type.GetValueOrDefault();
				if ((int)valueOrDefault <= 2)
				{
					if ((int)valueOrDefault != 1)
					{
						if ((int)valueOrDefault != 2)
						{
							goto IL_00c8;
						}
						num2 = PluginConfig.GunshotsReverb.PercentToMultiplier();
					}
					else
					{
						num2 = PluginConfig.GunshotsMain.PercentToMultiplier();
					}
				}
				else if ((int)valueOrDefault != 33)
				{
					if ((int)valueOrDefault != 40)
					{
						if ((int)valueOrDefault != 41)
						{
							goto IL_00c8;
						}
						num2 = PluginConfig.PhysicsImpacts.PercentToMultiplier();
					}
					else
					{
						num2 = PluginConfig.BulletCasings.PercentToMultiplier();
					}
				}
				else
				{
					num2 = PluginConfig.SosigVoicelines.PercentToMultiplier();
				}
				goto IL_00d4;
			}
			goto IL_00d7;
			IL_00c8:
			num2 = null;
			goto IL_00d4;
			IL_00d4:
			num = num2;
			goto IL_00d7;
			IL_00d7:
			if (!num.HasValue)
			{
				num = ((Object)__instance).name switch
				{
					"PooledSource_Casings" => PluginConfig.BulletCasings.PercentToMultiplier(), 
					"PooledSource_Casings(Clone)" => PluginConfig.BulletCasings.PercentToMultiplier(), 
					"PooledSource_Impacts" => PluginConfig.PhysicsImpacts.PercentToMultiplier(), 
					"PooledSource_Impacts(Clone)" => PluginConfig.PhysicsImpacts.PercentToMultiplier(), 
					"PooledSource_NPCBarks" => PluginConfig.PhysicsImpacts.PercentToMultiplier(), 
					"PooledSource_NPCBarks(Clone)" => PluginConfig.PhysicsImpacts.PercentToMultiplier(), 
					_ => null, 
				};
				if (num.HasValue)
				{
					Plugin.LogVerbose("Using baseline fallback for FVRPooledAudioSource '" + ((Object)__instance).name + "'");
				}
			}
			float num3 = num ?? 1f;
			if (component != null && component.QueuedMultiplier.HasValue)
			{
				if (Time.time - component.QueuedMultiplierTimestamp > 0.27f)
				{
					Plugin.LogVerbose("[FVRPooledAudioSourcePatcher] Queued multiplier expired.");
				}
				else
				{
					float value = component.QueuedMultiplier.Value;
					Plugin.LogVerbose("[FVRPooledAudioSourcePatcher] Using queued " + $"multiplier (x{value}).");
					num3 *= value;
				}
				component.QueuedMultiplier = null;
			}
			Plugin.LogVerbose("[FVRPooledAudioSourcePatcher] Queuing AudioSource volume multiplier for " + $"FVRPooledAudioSource '{((Object)__instance).name}' (x{num3})");
			AudioSourcePatcher.QueueVolumeMultiplier(num3);
		}
	}
	internal static class MusicPatchers
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(FVRFMODController), "SetMasterVolume")]
		private static void SetMasterVolume_Postfix(float i, FVRFMODController __instance)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			float num = i * PluginConfig.Music.PercentToMultiplier();
			((Bus)(ref __instance.MasterBus)).setVolume(num);
			Plugin.LogVerbose($"Applied FVRFMODController music volume multiplier: {i} => {num}");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZosigMusicController), "SetMasterVolume")]
		private static void SetMasterVolume_Postfix(float i, ZosigMusicController __instance)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			float num = i * PluginConfig.Music.PercentToMultiplier();
			((Bus)(ref __instance.MasterBus)).setVolume(num);
			Plugin.LogVerbose($"Applied ZosigMusicController music volume multiplier: {i} => {num}");
		}
	}
	[HarmonyPatch(typeof(SM))]
	internal static class SoundManagerPatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch("CreatePool")]
		private static void CreatePool_Postfix(FVRPooledAudioType type, AudioSourcePool? __result)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (__result?.SourceQueue_Disabled == null)
			{
				return;
			}
			Plugin.Log.LogDebug((object)string.Format("[{0}] New pool created for: {1}", "SoundManagerPatcher", type));
			foreach (FVRPooledAudioSource item in __result.SourceQueue_Disabled)
			{
				if (!((Object)(object)item == (Object)null))
				{
					AudioSourceTagAudioBalancing audioSourceTagAudioBalancing = ((Component)item).GetComponent<AudioSourceTagAudioBalancing>();
					if ((Object)(object)audioSourceTagAudioBalancing == (Object)null)
					{
						audioSourceTagAudioBalancing = ((Component)item).gameObject.AddComponent<AudioSourceTagAudioBalancing>();
						((Object)audioSourceTagAudioBalancing).hideFlags = (HideFlags)61;
					}
					audioSourceTagAudioBalancing.Type = type;
				}
			}
		}
	}
}
namespace Sirdoggy.DynamicAudioBalancing.Patches.Tags
{
	internal class AudioSourceTagAudioBalancing : MonoBehaviour
	{
		public FVRPooledAudioType? Type { get; set; }

		public float? QueuedMultiplier { get; set; }

		public float QueuedMultiplierTimestamp { get; set; }
	}
	internal class ChamberTagAudioBalancing : MonoBehaviour
	{
		public FVRFireArm? ParentFirearm { get; set; }

		public AttachableFirearm? ParentAttachableFirearm { get; set; }
	}
	internal enum RecordableEvent
	{
		DynamicGunshot,
		PreviousDynamicGunshot,
		SoundGunshot,
		SoundHammerHit,
		SoundBoltSlideBack,
		SoundBoltSlideForward,
		SoundMagazineEjectRound
	}
	internal static class RecordableEventExtensions
	{
		public static RecordableEvent? ToRecordableEventOrNull(this FirearmAudioEventType audioEventType)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected I4, but got Unknown
			if ((int)audioEventType <= 1)
			{
				if ((int)audioEventType == 0)
				{
					return RecordableEvent.SoundBoltSlideForward;
				}
				if ((int)audioEventType == 1)
				{
					return RecordableEvent.SoundBoltSlideBack;
				}
			}
			else
			{
				if ((int)audioEventType == 6)
				{
					return RecordableEvent.SoundHammerHit;
				}
				if ((int)audioEventType == 29)
				{
					return RecordableEvent.SoundMagazineEjectRound;
				}
				switch (audioEventType - 100)
				{
				case 0:
					return RecordableEvent.SoundGunshot;
				case 1:
					return RecordableEvent.SoundGunshot;
				case 2:
					return RecordableEvent.SoundGunshot;
				}
			}
			return null;
		}
	}
	internal class FirearmTagAudioBalancing : MonoBehaviour
	{
		private readonly Dictionary<RecordableEvent, float> _lastTimestampsInSequence = new Dictionary<RecordableEvent, float>
		{
			{
				RecordableEvent.DynamicGunshot,
				0f
			},
			{
				RecordableEvent.PreviousDynamicGunshot,
				0f
			},
			{
				RecordableEvent.SoundGunshot,
				0f
			},
			{
				RecordableEvent.SoundBoltSlideBack,
				0f
			},
			{
				RecordableEvent.SoundBoltSlideForward,
				0f
			},
			{
				RecordableEvent.SoundMagazineEjectRound,
				0f
			}
		};

		public float LastCalculatedDelayBetweenShots { get; private set; }

		public void RecordTimestampFor(RecordableEvent recordableEvent)
		{
			_lastTimestampsInSequence[recordableEvent] = Time.time;
		}

		public float GetTimeSinceLastTimestampOf(RecordableEvent recordableEvent)
		{
			return Time.time - _lastTimestampsInSequence[recordableEvent];
		}

		public void RecordDynamicGunshotTimestamp()
		{
			LastCalculatedDelayBetweenShots = CalculateDelay();
			_lastTimestampsInSequence[RecordableEvent.PreviousDynamicGunshot] = _lastTimestampsInSequence[RecordableEvent.DynamicGunshot];
			_lastTimestampsInSequence[RecordableEvent.DynamicGunshot] = Time.time;
		}

		public float CalculateDelayBetweenShots()
		{
			float num = CalculateDelay();
			if (PluginConfig.VerboseLogs.Value)
			{
				Plugin.Log.LogInfo((object)$"Calculated delay between shots: {num:N}s");
			}
			return num;
		}

		private float CalculateDelay()
		{
			float num = _lastTimestampsInSequence[RecordableEvent.DynamicGunshot];
			float num2 = _lastTimestampsInSequence[RecordableEvent.PreviousDynamicGunshot];
			if (num2 == 0f)
			{
				return 0.27f;
			}
			float num3 = num - num2 + PluginConfig.DelayBetweenShotsCalculationMargin.Value;
			if (!(num3 > 0.27f))
			{
				return num3;
			}
			return 0.27f;
		}
	}
}
namespace Sirdoggy.DynamicAudioBalancing.Patches.Firearms
{
	public enum FireMode
	{
		SemiAuto,
		SustainedFirst,
		SustainedSubsequent
	}
	[HarmonyPriority(100)]
	[HarmonyPatch(typeof(FVRFireArmChamber))]
	internal static class FVRFireArmChamberPatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch("Fire")]
		private static void Fire_Postfix(FVRFireArmChamber __instance, bool __result)
		{
			Plugin.ExceptionCatcher.Run(delegate
			{
				if (!__result)
				{
					Plugin.Log.LogDebug((object)"[FVRFireArmChamberPatcher] Chamber didn't fire, returning...");
				}
				else if ((Object)(object)__instance.Firearm != (Object)null)
				{
					Plugin.Log.LogDebug((object)"Retrieving tag from: __instance.Firearm");
					RetrieveFirearmTagAndRecordTimestamp((MonoBehaviour)(object)__instance.Firearm);
				}
				else
				{
					ChamberTagAudioBalancing component = ((Component)__instance).GetComponent<ChamberTagAudioBalancing>();
					if ((Object)(object)component == (Object)null)
					{
						throw new Exception("ChamberTag firearm is null, can't save gunshot timestamp.");
					}
					if ((Object)(object)component.ParentFirearm != (Object)null)
					{
						Plugin.Log.LogDebug((object)"Retrieving firearm tag from: chamberTag.ParentFirearm");
						RetrieveFirearmTagAndRecordTimestamp((MonoBehaviour)(object)component.ParentFirearm);
					}
					else
					{
						if (!((Object)(object)component.ParentAttachableFirearm != (Object)null))
						{
							throw new Exception("ChamberTag contains null references, can't save gunshot timestamp.");
						}
						Plugin.Log.LogDebug((object)"Retrieving firearm tag from: chamberTag.ParentAttachableFirearm");
						RetrieveFirearmTagAndRecordTimestamp((MonoBehaviour)(object)component.ParentAttachableFirearm);
					}
				}
			});
		}

		private static void RetrieveFirearmTagAndRecordTimestamp(MonoBehaviour firearm)
		{
			FirearmTagAudioBalancing component = ((Component)firearm).GetComponent<FirearmTagAudioBalancing>();
			if ((Object)(object)component == (Object)null)
			{
				throw new Exception("FirearmTag is null, can't save gunshot timestamp.");
			}
			component.RecordDynamicGunshotTimestamp();
		}
	}
	[HarmonyPriority(100)]
	internal static class FVRFireArmPatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(FVRFireArm), "Awake")]
		private static void FVRFireArm_Awake_Postfix(FVRFireArm __instance)
		{
			Awake_Postfix((MonoBehaviour)(object)__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(AttachableFirearm), "Awake")]
		private static void AttachableFirearm_Awake_Postfix(AttachableFirearm __instance)
		{
			Awake_Postfix((MonoBehaviour)(object)__instance);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(FVRFireArm), "PlayAudioEvent")]
		private static void FVRFireArm_PlayAudioEvent_Prefix(FVRFireArm __instance, FirearmAudioEventType eType, float pitchmod)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PlayAudioEvent_Prefix((MonoBehaviour)(object)__instance, eType);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(AttachableFirearm), "PlayAudioEvent")]
		private static void AttachableFirearm_PlayAudioEvent_Prefix(AttachableFirearm __instance, FirearmAudioEventType eType, float pitchmod)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PlayAudioEvent_Prefix((MonoBehaviour)(object)__instance, eType);
		}

		private static void Awake_Postfix(MonoBehaviour instance)
		{
			if ((Object)(object)((Component)instance).GetComponent<FirearmTagAudioBalancing>() == (Object)null)
			{
				((Object)((Component)instance).gameObject.AddComponent<FirearmTagAudioBalancing>()).hideFlags = (HideFlags)61;
			}
		}

		private static void PlayAudioEvent_Prefix(MonoBehaviour instance, FirearmAudioEventType eType)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			Plugin.ExceptionCatcher.Run(delegate
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Invalid comparison between Unknown and I4
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
				Plugin.LogVerbose($"Firearm AudioEvent: {eType}");
				FVRFirearmAudioSet audioClipSet = GetAudioClipSet(instance);
				if ((int)eType == 7)
				{
					AudioEvent val = audioClipSet?.Prefire;
					if (val != null)
					{
						List<AudioClip> clips = val.Clips;
						if (clips != null && clips.Count > 0)
						{
							AudioSourcePatcher.QueueVolumeMultiplier(PluginConfig.OpenBoltPrefire.PercentToMultiplier());
							return;
						}
					}
				}
				RecordableEvent? recordableEvent = eType.ToRecordableEventOrNull();
				if (recordableEvent.HasValue)
				{
					FirearmTagAudioBalancing component = ((Component)instance).GetComponent<FirearmTagAudioBalancing>();
					if ((Object)(object)component == (Object)null)
					{
						throw new Exception("Firearm has no FirearmTag component.");
					}
					RecordableEvent value = recordableEvent.Value;
					if (audioClipSet?.TryGetAudioEventBy(eType) == null)
					{
						Plugin.LogVerbose($"Firearm has null clip set for '{value}', returning...");
					}
					else
					{
						FireMode fireMode = FireMode.SemiAuto;
						if (instance.IsInFullAutoMode() || instance.IsInBurstMode())
						{
							RecordableEvent recordableEvent2 = ((value != RecordableEvent.SoundHammerHit) ? value : RecordableEvent.DynamicGunshot);
							fireMode = ((component.GetTimeSinceLastTimestampOf(recordableEvent2) > component.LastCalculatedDelayBetweenShots) ? FireMode.SustainedFirst : FireMode.SustainedSubsequent);
						}
						if (value == RecordableEvent.SoundHammerHit)
						{
							HandleHammerHit(fireMode, instance);
						}
						else
						{
							HandleGenericRelatedToGunshot(component, instance, value, fireMode);
						}
					}
				}
			});
		}

		private static void HandleHammerHit(FireMode fireMode, MonoBehaviour instance)
		{
			FVRFireArm val = (FVRFireArm)(object)((instance is FVRFireArm) ? instance : null);
			if (val != null && !val.HasLiveAmmoLoaded() && !PluginConfig.ChangeVolumeOfDryFireHammerHit.Value)
			{
				Plugin.LogVerbose("Not changing volume of HammerHit, as gun is not loaded");
				return;
			}
			float num = PluginConfig.GunshotsMechanical.PercentToMultiplier();
			float num2 = fireMode switch
			{
				FireMode.SemiAuto => PluginConfig.HammerHitVolumePercentSemiAuto.PercentToMultiplier(), 
				FireMode.SustainedFirst => PluginConfig.HammerHitVolumePercentSustainedFirst.PercentToMultiplier(), 
				FireMode.SustainedSubsequent => PluginConfig.HammerHitVolumePercentSustainedSubsequent.PercentToMultiplier(), 
				_ => throw new NotSupportedException("Invalid enum value."), 
			};
			Plugin.LogVerbose($"Handling '{fireMode}' HammerHit");
			AudioSourcePatcher.QueueVolumeMultiplier(num * num2);
		}

		private static void HandleGenericRelatedToGunshot(FirearmTagAudioBalancing firearmTag, MonoBehaviour instance, RecordableEvent recordableSoundEvent, FireMode fireMode)
		{
			if (firearmTag.GetTimeSinceLastTimestampOf(RecordableEvent.DynamicGunshot) > firearmTag.CalculateDelayBetweenShots())
			{
				Plugin.LogVerbose($"Not handling {recordableSoundEvent}, because too much time passed since last gunshot.");
				return;
			}
			Plugin.LogVerbose($"Handling '{fireMode}' {recordableSoundEvent}");
			ApplyDynamicAudioForGunshot(fireMode, recordableSoundEvent, instance);
			firearmTag.RecordTimestampFor(recordableSoundEvent);
		}

		private static void ApplyDynamicAudioForGunshot(FireMode mode, RecordableEvent recordableSoundEvent, MonoBehaviour instance)
		{
			float num = mode switch
			{
				FireMode.SemiAuto => PluginConfig.GunshotVolumePercentSemiAuto.PercentToMultiplier(), 
				FireMode.SustainedFirst => PluginConfig.GunshotVolumePercentSustainedFirst.PercentToMultiplier(), 
				FireMode.SustainedSubsequent => PluginConfig.GunshotVolumePercentSustainedSubsequent.PercentToMultiplier(), 
				_ => throw new NotSupportedException("Invalid enum value."), 
			};
			if (recordableSoundEvent != RecordableEvent.SoundGunshot)
			{
				num *= PluginConfig.GunshotsMechanical.PercentToMultiplier();
				AudioSourcePatcher.QueueVolumeMultiplier(num);
				return;
			}
			AudioSourcePatcher.QueueVolumeMultiplier(num);
			float num2 = mode switch
			{
				FireMode.SemiAuto => PluginConfig.ReverbVolumePercentSemiAuto.PercentToMultiplier(), 
				FireMode.SustainedFirst => PluginConfig.ReverbVolumePercentSustainedFirst.PercentToMultiplier(), 
				FireMode.SustainedSubsequent => PluginConfig.ReverbVolumePercentSustainedSubsequent.PercentToMultiplier(), 
				_ => throw new NotSupportedException("Invalid enum value."), 
			};
			AudioSourcePool poolTail = GetPoolTail(instance);
			if (poolTail == null)
			{
				Plugin.Log.LogDebug((object)"(!) m_pool_tail is null.");
				return;
			}
			Queue<FVRPooledAudioSource> sourceQueue_Disabled = poolTail.SourceQueue_Disabled;
			FVRPooledAudioSource val = (FVRPooledAudioSource)((sourceQueue_Disabled != null && sourceQueue_Disabled.Count > 0) ? ((object)poolTail.SourceQueue_Disabled.Peek()) : ((object)poolTail.ActiveSources?.FirstOrDefault()));
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogDebug((object)"(!) Failed to find a free FVRPooledAudioSource in PooledSourcePool.");
				return;
			}
			AudioSourceTagAudioBalancing audioSourceTagAudioBalancing = ((Component)val).GetComponent<AudioSourceTagAudioBalancing>();
			if ((Object)(object)audioSourceTagAudioBalancing == (Object)null)
			{
				audioSourceTagAudioBalancing = ((Component)val).gameObject.AddComponent<AudioSourceTagAudioBalancing>();
				((Object)audioSourceTagAudioBalancing).hideFlags = (HideFlags)61;
			}
			Plugin.LogVerbose($"Saving tail volume multiplier in AudioSourceTag: x{num2}");
			audioSourceTagAudioBalancing.QueuedMultiplier = num2;
			audioSourceTagAudioBalancing.QueuedMultiplierTimestamp = Time.time;
		}

		private static FVRFirearmAudioSet? GetAudioClipSet(MonoBehaviour instance)
		{
			FVRFireArm val = (FVRFireArm)(object)((instance is FVRFireArm) ? instance : null);
			if (val == null)
			{
				return ((AttachableFirearm)(((instance is AttachableFirearm) ? instance : null)?)).AudioClipSet;
			}
			return val.AudioClipSet;
		}

		private static AudioSourcePool? GetPoolTail(MonoBehaviour instance)
		{
			FVRFireArm val = (FVRFireArm)(object)((instance is FVRFireArm) ? instance : null);
			if (val == null)
			{
				return ((AttachableFirearm)(((instance is AttachableFirearm) ? instance : null)?)).m_pool_tail;
			}
			return val.m_pool_tail;
		}
	}
	internal static class InitialCreateChamberTagPatchers
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(BarrageBox))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(BarrageBox __instance)
		{
			AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BoltActionRifle))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(BoltActionRifle __instance)
		{
			AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BreakActionWeapon))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(BreakActionWeapon __instance)
		{
			AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ClosedBoltWeapon))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(ClosedBoltWeapon __instance)
		{
			AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Derringer))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(Derringer __instance)
		{
			AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Flaregun))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(Flaregun __instance)
		{
			AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(LeverActionFirearm))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(LeverActionFirearm __instance)
		{
			AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Minigun))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(Minigun __instance)
		{
			AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(OpenBoltReceiver))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(OpenBoltReceiver __instance)
		{
			AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Revolver))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(Revolver __instance)
		{
			AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(RevolvingShotgun))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(RevolvingShotgun __instance)
		{
			AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(SingleActionRevolver))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(SingleActionRevolver __instance)
		{
			AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(TubeFedShotgun))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(TubeFedShotgun __instance)
		{
			AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(AttachableClosedBoltWeapon))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(AttachableClosedBoltWeapon __instance)
		{
			AssignTagToChambers(new List<FVRFireArmChamber>(1) { __instance.Chamber }, null, (AttachableFirearm?)(object)__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(AttachableTubeFed))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(AttachableTubeFed __instance)
		{
			AssignTagToChambers(new List<FVRFireArmChamber>(1) { __instance.Chamber }, null, (AttachableFirearm?)(object)__instance);
		}

		internal static void AssignTagToChambers(List<FVRFireArmChamber>? chambers, FVRFireArm? firearm, AttachableFirearm? attachableFirearm)
		{
			Plugin.ExceptionCatcher.Run(delegate
			{
				if (chambers == null)
				{
					throw new Exception("Chambers list is null.");
				}
				if (chambers.Count == 0)
				{
					throw new Exception("Chambers list is empty.");
				}
				if ((Object)(object)firearm == (Object)null && (Object)(object)attachableFirearm == (Object)null)
				{
					throw new Exception("Both firearm and attachableFirearm are null.");
				}
				ManualLogSource log = Plugin.Log;
				string[] obj = new string[6]
				{
					"[InitialCreateChamberTagPatchers] Creating ChamberTag ",
					$"for {chambers.Count} chambers",
					"\n- parent firearm: ",
					null,
					null,
					null
				};
				FVRFireArm? obj2 = firearm;
				obj[3] = ((obj2 != null) ? ((Object)obj2).name : null) ?? "null";
				obj[4] = "\n- parent attachableFirearm: ";
				AttachableFirearm? obj3 = attachableFirearm;
				obj[5] = ((obj3 != null) ? ((Object)obj3).name : null) ?? "null";
				log.LogDebug((object)string.Concat(obj));
				foreach (FVRFireArmChamber chamber in chambers)
				{
					ChamberTagAudioBalancing chamberTagAudioBalancing = ((Component)chamber).GetComponent<ChamberTagAudioBalancing>();
					if ((Object)(object)chamberTagAudioBalancing == (Object)null)
					{
						chamberTagAudioBalancing = ((Component)chamber).gameObject.AddComponent<ChamberTagAudioBalancing>();
						((Object)chamberTagAudioBalancing).hideFlags = (HideFlags)61;
					}
					chamberTagAudioBalancing.ParentFirearm = firearm;
					chamberTagAudioBalancing.ParentAttachableFirearm = attachableFirearm;
				}
			});
		}
	}
	internal static class InitialCreateChamberTagPatchers2
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(FBlockPistol))]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(FBlockPistol __instance)
		{
			InitialCreateChamberTagPatchers.AssignTagToChambers(((FVRFireArm)__instance).GetChambers(), (FVRFireArm?)(object)__instance, null);
		}
	}
}
namespace Sirdoggy.DynamicAudioBalancing.Extensions
{
	internal static class ArrayExtensions
	{
		public static T? GetElementAtOrNull<T>(this T[] array, int index)
		{
			if (array == null)
			{
				return default(T);
			}
			if (index < 0 || index >= array.Length)
			{
				return default(T);
			}
			return array[index];
		}
	}
	internal static class FVRAudioExtensions
	{
		public static AudioEvent? TryGetAudioEventBy(this FVRFirearmAudioSet clipSet, FirearmAudioEventType audioEventType)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected I4, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected I4, but got Unknown
			switch ((int)audioEventType)
			{
			default:
				switch (audioEventType - 100)
				{
				case 0:
					return clipSet.Shots_Main;
				case 1:
					return clipSet.Shots_Suppressed;
				case 2:
					return clipSet.Shots_LowPressure;
				}
				break;
			case 8:
				return clipSet.BoltRelease;
			case 1:
				return clipSet.BoltSlideBack;
			case 3:
				return clipSet.BoltSlideBackHeld;
			case 4:
				return clipSet.BoltSlideBackLocked;
			case 0:
				return clipSet.BoltSlideForward;
			case 2:
				return clipSet.BoltSlideForwardHeld;
			case 17:
				return clipSet.BreachOpen;
			case 18:
				return clipSet.BreachClose;
			case 5:
				return clipSet.CatchOnSear;
			case 42:
				return clipSet.ChamberManual;
			case 15:
				return clipSet.FireSelector;
			case 6:
				return clipSet.HammerHit;
			case 10:
				return clipSet.HandleBack;
			case 41:
				return clipSet.HandleBackEmpty;
			case 11:
				return clipSet.HandleForward;
			case 40:
				return clipSet.HandleForwardEmpty;
			case 12:
				return clipSet.HandleUp;
			case 13:
				return clipSet.HandleDown;
			case 9:
				return clipSet.HandleGrab;
			case 21:
				return clipSet.MagazineOut;
			case 20:
				return clipSet.MagazineIn;
			case 28:
				return clipSet.MagazineInsertRound;
			case 29:
				return clipSet.MagazineEjectRound;
			case 7:
				return clipSet.Prefire;
			case 14:
				return clipSet.Safety;
			case 16:
				return clipSet.TriggerReset;
			case 22:
				return clipSet.TopCoverRelease;
			case 23:
				return clipSet.TopCoverUp;
			case 24:
				return clipSet.TopCoverDown;
			case 30:
				return clipSet.StockOpen;
			case 31:
				return clipSet.StockClosed;
			case 32:
				return clipSet.BipodOpen;
			case 33:
				return clipSet.BipodClosed;
			case 50:
				return clipSet.BeltGrab;
			case 51:
				return clipSet.BeltRelease;
			case 52:
				return clipSet.BeltSeat;
			case 53:
				return clipSet.BeltSettle;
			case 19:
			case 25:
			case 26:
			case 27:
			case 34:
			case 35:
			case 36:
			case 37:
			case 38:
			case 39:
			case 43:
			case 44:
			case 45:
			case 46:
			case 47:
			case 48:
			case 49:
				break;
			}
			return null;
		}
	}
	internal static class FVRFirearmExtensions
	{
		public static bool IsInFullAutoMode(this MonoBehaviour firearm)
		{
			//IL_00a1: 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)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Invalid comparison between Unknown and I4
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Invalid comparison between Unknown and I4
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Invalid comparison between Unknown and I4
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Invalid comparison between Unknown and I4
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Invalid comparison between Unknown and I4
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Invalid comparison between Unknown and I4
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Invalid comparison between Unknown and I4
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Invalid comparison between Unknown and I4
			ClosedBoltWeapon val = (ClosedBoltWeapon)(object)((firearm is ClosedBoltWeapon) ? firearm : null);
			if (val == null)
			{
				OpenBoltReceiver val2 = (OpenBoltReceiver)(object)((firearm is OpenBoltReceiver) ? firearm : null);
				if (val2 == null)
				{
					AttachableClosedBoltWeapon val3 = (AttachableClosedBoltWeapon)(object)((firearm is AttachableClosedBoltWeapon) ? firearm : null);
					if (val3 == null)
					{
						Handgun val4 = (Handgun)(object)((firearm is Handgun) ? firearm : null);
						if (val4 == null)
						{
							RevolvingShotgun val5 = (RevolvingShotgun)(object)((firearm is RevolvingShotgun) ? firearm : null);
							if (val5 == null)
							{
								if (!(firearm is BarrageBox))
								{
									if (!(firearm is FlameThrower))
									{
										if (firearm is Minigun)
										{
											return true;
										}
										return false;
									}
									return true;
								}
								return true;
							}
							FireSelectorMode[] fireSelector_Modes = val5.FireSelector_Modes;
							return fireSelector_Modes != null && (int)(fireSelector_Modes.GetElementAtOrNull(val5.m_fireSelectorMode)?.ModeType).GetValueOrDefault() == 2;
						}
						FireSelectorMode[] fireSelectorModes = val4.FireSelectorModes;
						return fireSelectorModes != null && (int)(fireSelectorModes.GetElementAtOrNull(val4.m_fireSelectorMode)?.ModeType).GetValueOrDefault() == 2;
					}
					FireSelectorModeType? val6 = val3.FireSelector_Modes?.GetElementAtOrNull(val3.m_fireSelectorMode)?.ModeType;
					FireSelectorModeType? val7 = val3.FireSelector_Modes2?.GetElementAtOrNull(val3.m_fireSelectorMode)?.ModeType;
					return (int)val6.GetValueOrDefault() == 3 || (int)val7.GetValueOrDefault() == 3;
				}
				FireSelectorModeType? val8 = val2.FireSelector_Modes?.GetElementAtOrNull(val2.m_fireSelectorMode)?.ModeType;
				FireSelectorModeType? val9 = val2.FireSelector_Modes2?.GetElementAtOrNull(val2.m_fireSelectorMode)?.ModeType;
				return (int)val8.GetValueOrDefault() == 2 || (int)val9.GetValueOrDefault() == 2;
			}
			FireSelectorModeType? val10 = val.FireSelector_Modes?.GetElementAtOrNull(val.m_fireSelectorMode)?.ModeType;
			FireSelectorModeType? val11 = val.FireSelector_Modes2?.GetElementAtOrNull(val.m_fireSelectorMode)?.ModeType;
			return (int)val10.GetValueOrDefault() == 3 || (int)val11.GetValueOrDefault() == 3;
		}

		public static bool IsInBurstMode(this MonoBehaviour firearm)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Invalid comparison between Unknown and I4
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Invalid comparison between Unknown and I4
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Invalid comparison between Unknown and I4
			//IL_0266: 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_00e1: Invalid comparison between Unknown and I4
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Invalid comparison between Unknown and I4
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Invalid comparison between Unknown and I4
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Invalid comparison between Unknown and I4
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Invalid comparison between Unknown and I4
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Invalid comparison between Unknown and I4
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Invalid comparison between Unknown and I4
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Invalid comparison between Unknown and I4
			ClosedBoltWeapon val = (ClosedBoltWeapon)(object)((firearm is ClosedBoltWeapon) ? firearm : null);
			if (val == null)
			{
				OpenBoltReceiver val2 = (OpenBoltReceiver)(object)((firearm is OpenBoltReceiver) ? firearm : null);
				if (val2 == null)
				{
					AttachableClosedBoltWeapon val3 = (AttachableClosedBoltWeapon)(object)((firearm is AttachableClosedBoltWeapon) ? firearm : null);
					if (val3 == null)
					{
						Handgun val4 = (Handgun)(object)((firearm is Handgun) ? firearm : null);
						if (val4 == null)
						{
							if (firearm is RevolvingShotgun)
							{
								return false;
							}
							return false;
						}
						FireSelectorMode[] fireSelectorModes = val4.FireSelectorModes;
						return fireSelectorModes != null && (int)(fireSelectorModes.GetElementAtOrNull(val4.m_fireSelectorMode)?.ModeType).GetValueOrDefault() == 4;
					}
					FireSelectorModeType? val5 = val3.FireSelector_Modes?.GetElementAtOrNull(val3.m_fireSelectorMode)?.ModeType;
					FireSelectorModeType? val6 = val3.FireSelector_Modes2?.GetElementAtOrNull(val3.m_fireSelectorMode)?.ModeType;
					return (int)val5.GetValueOrDefault() == 2 || (int)val6.GetValueOrDefault() == 2;
				}
				FireSelectorModeType? val7 = val2.FireSelector_Modes?.GetElementAtOrNull(val2.m_fireSelectorMode)?.ModeType;
				FireSelectorModeType? val8 = val2.FireSelector_Modes2?.GetElementAtOrNull(val2.m_fireSelectorMode)?.ModeType;
				return (int)val7.GetValueOrDefault() == 4 || (int)val8.GetValueOrDefault() == 4 || (int)val7.GetValueOrDefault() == 3 || (int)val7.GetValueOrDefault() == 3;
			}
			FireSelectorModeType? val9 = val.FireSelector_Modes?.GetElementAtOrNull(val.m_fireSelectorMode)?.ModeType;
			FireSelectorModeType? val10 = val.FireSelector_Modes2?.GetElementAtOrNull(val.m_fireSelectorMode)?.ModeType;
			return (int)val9.GetValueOrDefault() == 2 || (int)val9.GetValueOrDefault() == 2 || (int)val10.GetValueOrDefault() == 4 || (int)val10.GetValueOrDefault() == 4;
		}

		public static bool HasLiveAmmoLoaded(this FVRFireArm firearm)
		{
			foreach (FVRFireArmChamber chamber in firearm.GetChambers())
			{
				if (((Behaviour)chamber).isActiveAndEnabled && !chamber.IsSpent && chamber.IsFull)
				{
					return true;
				}
			}
			return false;
		}
	}
}
namespace Sirdoggy.DynamicAudioBalancing.Common
{
	internal static class ConfigEntryExtensions
	{
		public static float PercentToMultiplier(this ConfigEntry<float> configEntry)
		{
			float num = configEntry.Value / 100f;
			if (!(num > 2f))
			{
				if (num < 0f)
				{
					return 0f;
				}
				return num;
			}
			return 2f;
		}
	}
	internal class ExceptionCatcher
	{
		private readonly ManualLogSource _log;

		public ExceptionCatcher(ManualLogSource log)
		{
			_log = log;
		}

		public void Run(Action action, Action<Exception>? customHandler = null)
		{
			try
			{
				action();
			}
			catch (Exception ex)
			{
				if (customHandler == null)
				{
					_log.LogError((object)ex);
				}
				else
				{
					customHandler(ex);
				}
			}
		}
	}
}