Decompiled source of Shadowman v1.7.2

plugins\Shadowman\Shadowman.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using FMOD;
using FMOD.Studio;
using FMODUnity;
using Features.AIModule.Scripts;
using Features.AIModule.Scripts.ManInShadows;
using Fusion;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Shadowman")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Shadowman")]
[assembly: AssemblyTitle("Shadowman")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 LastPirates.Shadowman
{
	[BepInPlugin("com.bwadd.lastpirates.shadowman", "Shadowman", "1.7.2")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class SpatialSmoothing
		{
			internal float Vertical = 1f;

			internal float Occlusion = 1f;
		}

		private sealed class DeathPlayback
		{
			internal Channel Channel;

			internal DSP Reverb;

			internal Vector3 Position;

			internal int ObstacleMask;

			internal readonly SpatialSmoothing Smoothing = new SpatialSmoothing();
		}

		public const string PluginGuid = "com.bwadd.lastpirates.shadowman";

		public const string PluginName = "Shadowman";

		public const string PluginVersion = "1.7.2";

		private const string AudioFileName = "Shadowman_18s.wav";

		private const string DeathAudioFileName = "Shadowman_Death.mp3";

		private const uint DeathAudioStartMilliseconds = 54000u;

		internal static Plugin Instance;

		internal static ConfigEntry<float> Volume;

		internal static ConfigEntry<float> MinimumDistance;

		internal static ConfigEntry<float> MaximumDistance;

		internal static ConfigEntry<float> DeathVolume;

		internal static ConfigEntry<float> FarReverbWetLevel;

		internal static ConfigEntry<float> NearReverbWetLevel;

		internal static ConfigEntry<float> PlaybackSpeed;

		internal static ConfigEntry<float> VerticalSilenceDistance;

		internal static ConfigEntry<float> OccludedVolumeMultiplier;

		private readonly Dictionary<int, Channel> _channels = new Dictionary<int, Channel>();

		private readonly Dictionary<int, DSP> _reverbs = new Dictionary<int, DSP>();

		private readonly Dictionary<int, SpatialSmoothing> _spatialSmoothing = new Dictionary<int, SpatialSmoothing>();

		private readonly List<DeathPlayback> _deathPlaybacks = new List<DeathPlayback>();

		private Sound _replacementSound;

		private Sound _deathSound;

		private bool _soundReady;

		private bool _deathSoundReady;

		private Bus _sfxBus;

		private void Awake()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Expected O, but got Unknown
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Expected O, but got Unknown
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Expected O, but got Unknown
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Expected O, but got Unknown
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Expected O, but got Unknown
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Volume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Volume", 0.5f, new ConfigDescription("Replacement whisper volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			MinimumDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "MinimumDistance", 3f, new ConfigDescription("Distance where the replacement plays at full volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 50f), Array.Empty<object>()));
			MaximumDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "MaximumDistance", 25f, new ConfigDescription("Distance where the replacement becomes inaudible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>()));
			DeathVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "DeathVolume", 1f, new ConfigDescription("Volume of the Shadowman death clip.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			FarReverbWetLevel = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "FarReverbWetLevel", 3f, new ConfigDescription("Reverb wet level in decibels at maximum audible distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-80f, 20f), Array.Empty<object>()));
			NearReverbWetLevel = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "NearReverbWetLevel", -45f, new ConfigDescription("Reverb wet level in decibels while close to the Stalker.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-80f, 20f), Array.Empty<object>()));
			PlaybackSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "PlaybackSpeed", 0.85f, new ConfigDescription("Replacement playback speed. Values below one are slower and lower-pitched.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 1.5f), Array.Empty<object>()));
			VerticalSilenceDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Occlusion", "VerticalSilenceDistance", 5f, new ConfigDescription("Center of the two-metre vertical fade from audible to silent.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			OccludedVolumeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Occlusion", "OccludedVolumeMultiplier", 0.16f, new ConfigDescription("Volume multiplier when a wall or other solid obstacle blocks the listener.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			MinimumDistance.SettingChanged += OnDistanceChanged;
			MaximumDistance.SettingChanged += OnDistanceChanged;
			new Harmony("com.bwadd.lastpirates.shadowman").PatchAll(typeof(Plugin).Assembly);
			((MonoBehaviour)this).StartCoroutine(LoadSounds());
		}

		private void Update()
		{
			UpdateDeathPlaybacks();
		}

		private IEnumerator LoadSounds()
		{
			string path = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "Shadowman_18s.wav");
			string deathPath = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "Shadowman_Death.mp3");
			if (!File.Exists(path))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Replacement audio not found: " + path));
				yield break;
			}
			float deadline = Time.realtimeSinceStartup + 30f;
			string lastError = "FMOD is not initialized.";
			while (Time.realtimeSinceStartup < deadline)
			{
				try
				{
					System coreSystem = RuntimeManager.CoreSystem;
					if (((System)(ref coreSystem)).hasHandle())
					{
						RESULT val = ((System)(ref coreSystem)).createSound(path, (MODE)4194450, ref _replacementSound);
						if ((int)val == 0)
						{
							((Sound)(ref _replacementSound)).setLoopCount(-1);
							((Sound)(ref _replacementSound)).set3DMinMaxDistance(MinimumDistance.Value, MaximumDistance.Value);
							_soundReady = true;
							((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded Shadowman_18s.wav; Stalker whispers will be replaced locally.");
							break;
						}
						lastError = $"{val}: {Error.String(val)}";
					}
				}
				catch (Exception ex)
				{
					lastError = ex.ToString();
				}
				yield return (object)new WaitForSecondsRealtime(0.5f);
			}
			if (!_soundReady)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Could not load replacement through FMOD within 30 seconds: " + lastError));
			}
			if (!File.Exists(deathPath))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Death audio not found: " + deathPath));
				yield break;
			}
			System coreSystem2 = RuntimeManager.CoreSystem;
			RESULT val2 = ((System)(ref coreSystem2)).createSound(deathPath, (MODE)4194449, ref _deathSound);
			if ((int)val2 != 0)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Could not load Shadowman death audio: {val2}: {Error.String(val2)}");
				yield break;
			}
			((Sound)(ref _deathSound)).set3DMinMaxDistance(MinimumDistance.Value, MaximumDistance.Value);
			_deathSoundReady = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded Shadowman_Death.mp3; playback begins at 54 seconds on Stalker death.");
		}

		internal void PlayDeathSound(Vector3 worldPosition, int obstacleMask)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_00e5: 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_00ed: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (!_deathSoundReady)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Shadowman died before the death audio was ready.");
				return;
			}
			System coreSystem = RuntimeManager.CoreSystem;
			Channel channel = default(Channel);
			RESULT val = ((System)(ref coreSystem)).playSound(_deathSound, default(ChannelGroup), true, ref channel);
			if ((int)val != 0)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Could not start Shadowman death audio: {val}: {Error.String(val)}");
				return;
			}
			VECTOR val2 = new VECTOR
			{
				x = worldPosition.x,
				y = worldPosition.y,
				z = worldPosition.z
			};
			VECTOR val3 = default(VECTOR);
			((Channel)(ref channel)).set3DAttributes(ref val2, ref val3);
			((Channel)(ref channel)).setPitch(PlaybackSpeed.Value);
			DSP reverb = CreateDistanceReverb(channel);
			((Channel)(ref channel)).setPosition(54000u, (TIMEUNIT)1);
			((Channel)(ref channel)).setPaused(false);
			DeathPlayback deathPlayback = new DeathPlayback
			{
				Channel = channel,
				Reverb = reverb,
				Position = worldPosition,
				ObstacleMask = obstacleMask
			};
			_deathPlaybacks.Add(deathPlayback);
			ApplySpatialEffects(channel, reverb, deathPlayback.Smoothing, worldPosition, obstacleMask, DeathVolume.Value);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Played Shadowman death audio from 54 seconds.");
		}

		private void UpdateDeathPlaybacks()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			bool flag = default(bool);
			for (int num = _deathPlaybacks.Count - 1; num >= 0; num--)
			{
				DeathPlayback deathPlayback = _deathPlaybacks[num];
				if (!((Channel)(ref deathPlayback.Channel)).hasHandle() || (int)((Channel)(ref deathPlayback.Channel)).isPlaying(ref flag) != 0 || !flag)
				{
					if (((DSP)(ref deathPlayback.Reverb)).hasHandle())
					{
						((DSP)(ref deathPlayback.Reverb)).release();
					}
					_deathPlaybacks.RemoveAt(num);
				}
				else
				{
					ApplySpatialEffects(deathPlayback.Channel, deathPlayback.Reverb, deathPlayback.Smoothing, deathPlayback.Position, deathPlayback.ObstacleMask, DeathVolume.Value);
				}
			}
		}

		private void OnDistanceChanged(object sender, EventArgs eventArgs)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			float value = MinimumDistance.Value;
			float num = Mathf.Max(value + 0.1f, MaximumDistance.Value);
			if (((Sound)(ref _replacementSound)).hasHandle())
			{
				((Sound)(ref _replacementSound)).set3DMinMaxDistance(value, num);
			}
			if (((Sound)(ref _deathSound)).hasHandle())
			{
				((Sound)(ref _deathSound)).set3DMinMaxDistance(value, num);
			}
		}

		internal void UpdateReplacement(ManInShadowsBehaviour enemy, float visibilityVolume)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_0046: 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_0056: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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)
			//IL_006e: 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_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_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_0114: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			if (!_soundReady || (Object)(object)enemy == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)enemy).GetInstanceID();
			if (!_channels.TryGetValue(instanceID, out var value) || !((Channel)(ref value)).hasHandle())
			{
				System coreSystem = RuntimeManager.CoreSystem;
				RESULT val = ((System)(ref coreSystem)).playSound(_replacementSound, default(ChannelGroup), false, ref value);
				if ((int)val != 0)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)$"Could not start Shadowman whisper: {val}: {Error.String(val)}");
					return;
				}
				_channels[instanceID] = value;
				_reverbs[instanceID] = CreateDistanceReverb(value);
				_spatialSmoothing[instanceID] = new SpatialSmoothing();
				((Channel)(ref value)).setPitch(PlaybackSpeed.Value);
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Started replacement whisper for Stalker instance {instanceID}.");
			}
			Vector3 val2 = ResolveVisionPosition(enemy);
			VECTOR val3 = new VECTOR
			{
				x = val2.x,
				y = val2.y,
				z = val2.z
			};
			VECTOR val4 = default(VECTOR);
			((Channel)(ref value)).set3DAttributes(ref val3, ref val4);
			((Channel)(ref value)).setPitch(PlaybackSpeed.Value);
			if (!_spatialSmoothing.TryGetValue(instanceID, out var value2))
			{
				value2 = new SpatialSmoothing();
				_spatialSmoothing[instanceID] = value2;
			}
			_reverbs.TryGetValue(instanceID, out var value3);
			ApplySpatialEffects(value, value3, value2, val2, ResolveObstacleMask(enemy), Mathf.Clamp01(visibilityVolume) * Volume.Value);
		}

		private void ApplySpatialEffects(Channel channel, DSP reverb, SpatialSmoothing smoothing, Vector3 worldPosition, int obstacleMask, float baseVolume)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_0122: 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_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetListenerPosition(out var position))
			{
				((Channel)(ref channel)).setVolume(baseVolume);
				return;
			}
			float num = Mathf.Abs(position.y - worldPosition.y);
			float num2 = Mathf.Max(0f, VerticalSilenceDistance.Value - 1f);
			float num3 = VerticalSilenceDistance.Value + 1f;
			float num4 = Mathf.InverseLerp(num2, num3, num);
			float num5 = 1f - num4 * num4 * (3f - 2f * num4);
			float num6 = (IsOccluded(position, worldPosition, obstacleMask) ? OccludedVolumeMultiplier.Value : 1f);
			float num7 = 1f - Mathf.Exp(-7f * Time.unscaledDeltaTime);
			smoothing.Vertical = Mathf.Lerp(smoothing.Vertical, num5, num7);
			smoothing.Occlusion = Mathf.Lerp(smoothing.Occlusion, num6, num7);
			((Channel)(ref channel)).setVolume(baseVolume * GetGameSfxVolume() * smoothing.Vertical * smoothing.Occlusion);
			if (((DSP)(ref reverb)).hasHandle())
			{
				float value = MinimumDistance.Value;
				float num8 = Mathf.Max(value + 0.1f, MaximumDistance.Value);
				float num9 = Mathf.InverseLerp(value, num8, Vector3.Distance(position, worldPosition));
				float num10 = num9 * num9;
				float num11 = Mathf.Clamp01((1f - smoothing.Occlusion) / Mathf.Max(0.001f, 1f - OccludedVolumeMultiplier.Value));
				num10 = Mathf.Max(num10, 0.72f * num11);
				float num12 = Mathf.Lerp(NearReverbWetLevel.Value, FarReverbWetLevel.Value, num10);
				((DSP)(ref reverb)).setParameterFloat(11, num12);
				((DSP)(ref reverb)).setParameterFloat(12, Mathf.Lerp(0f, -10f, num10));
				((DSP)(ref reverb)).setParameterFloat(0, Mathf.Lerp(900f, 9500f, num10));
				((DSP)(ref reverb)).setParameterFloat(1, Mathf.Lerp(8f, 70f, num10));
				((DSP)(ref reverb)).setParameterFloat(2, Mathf.Lerp(15f, 100f, num10));
				((DSP)(ref reverb)).setParameterFloat(5, Mathf.Lerp(55f, 100f, num10));
				((DSP)(ref reverb)).setParameterFloat(6, Mathf.Lerp(45f, 100f, num10));
				float num13 = Mathf.Lerp(12000f, 4200f, num10);
				num13 = Mathf.Lerp(num13, Mathf.Min(num13, 1800f), num11);
				((DSP)(ref reverb)).setParameterFloat(9, num13);
			}
		}

		private float GetGameSfxVolume()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!((Bus)(ref _sfxBus)).isValid())
				{
					_sfxBus = RuntimeManager.GetBus("bus:/All/SFX");
				}
				float num = default(float);
				float num2 = default(float);
				if (((Bus)(ref _sfxBus)).isValid() && (int)((Bus)(ref _sfxBus)).getVolume(ref num, ref num2) == 0)
				{
					return Mathf.Clamp01(num2);
				}
			}
			catch
			{
			}
			return 1f;
		}

		private static bool TryGetListenerPosition(out Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_005d: 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)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				System coreSystem = RuntimeManager.CoreSystem;
				VECTOR val = default(VECTOR);
				VECTOR val2 = default(VECTOR);
				VECTOR val3 = default(VECTOR);
				VECTOR val4 = default(VECTOR);
				if ((int)((System)(ref coreSystem)).get3DListenerAttributes(0, ref val, ref val2, ref val3, ref val4) == 0)
				{
					position = new Vector3(val.x, val.y, val.z);
					return true;
				}
			}
			catch
			{
			}
			Camera main = Camera.main;
			position = (((Object)(object)main != (Object)null) ? ((Component)main).transform.position : Vector3.zero);
			return (Object)(object)main != (Object)null;
		}

		internal static Vector3 ResolveVisionPosition(ManInShadowsBehaviour enemy)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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)
			if ((Object)(object)enemy == (Object)null)
			{
				return Vector3.zero;
			}
			Transform value = Traverse.Create((object)enemy).Field("_visionPoint").GetValue<Transform>();
			if (!((Object)(object)value != (Object)null))
			{
				return ((Component)enemy).transform.position + Vector3.up * 1.5f;
			}
			return value.position;
		}

		internal static int ResolveObstacleMask(ManInShadowsBehaviour enemy)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)enemy == (Object)null)
			{
				return -5;
			}
			LayerMask value = Traverse.Create((object)enemy).Field("_obstacleMask").GetValue<LayerMask>();
			return ((LayerMask)(ref value)).value;
		}

		private static bool IsOccluded(Vector3 listenerPosition, Vector3 target, int obstacleMask)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: 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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = target - listenerPosition;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude <= 0.01f)
			{
				return false;
			}
			return Physics.Raycast(listenerPosition + ((Vector3)(ref val)).normalized * 0.1f, ((Vector3)(ref val)).normalized, Mathf.Max(0f, magnitude - 0.1f), obstacleMask, (QueryTriggerInteraction)1);
		}

		internal void StopReplacement(ManInShadowsBehaviour enemy)
		{
			//IL_002c: 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)
			if ((Object)(object)enemy == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)enemy).GetInstanceID();
			if (_channels.TryGetValue(instanceID, out var value))
			{
				if (((Channel)(ref value)).hasHandle())
				{
					((Channel)(ref value)).stop();
					((Channel)(ref value)).clearHandle();
				}
				_channels.Remove(instanceID);
			}
			if (_reverbs.TryGetValue(instanceID, out var value2))
			{
				if (((DSP)(ref value2)).hasHandle())
				{
					((DSP)(ref value2)).release();
				}
				_reverbs.Remove(instanceID);
			}
			_spatialSmoothing.Remove(instanceID);
		}

		private DSP CreateDistanceReverb(Channel channel)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_0012: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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)
			System coreSystem = RuntimeManager.CoreSystem;
			DSP val2 = default(DSP);
			RESULT val = ((System)(ref coreSystem)).createDSPByType((DSP_TYPE)17, ref val2);
			if ((int)val != 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"Could not create Shadowman reverb: {val}: {Error.String(val)}");
				return default(DSP);
			}
			((DSP)(ref val2)).setParameterFloat(0, 1800f);
			((DSP)(ref val2)).setParameterFloat(11, NearReverbWetLevel.Value);
			((DSP)(ref val2)).setParameterFloat(12, 0f);
			val = ((Channel)(ref channel)).addDSP(0, val2);
			if ((int)val != 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"Could not attach Shadowman reverb: {val}: {Error.String(val)}");
				((DSP)(ref val2)).release();
				return default(DSP);
			}
			return val2;
		}

		private void OnDestroy()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			MinimumDistance.SettingChanged -= OnDistanceChanged;
			MaximumDistance.SettingChanged -= OnDistanceChanged;
			foreach (Channel value in _channels.Values)
			{
				Channel current = value;
				if (((Channel)(ref current)).hasHandle())
				{
					((Channel)(ref current)).stop();
				}
			}
			_channels.Clear();
			foreach (DSP value2 in _reverbs.Values)
			{
				DSP current2 = value2;
				if (((DSP)(ref current2)).hasHandle())
				{
					((DSP)(ref current2)).release();
				}
			}
			_reverbs.Clear();
			_spatialSmoothing.Clear();
			foreach (DeathPlayback deathPlayback in _deathPlaybacks)
			{
				if (((Channel)(ref deathPlayback.Channel)).hasHandle())
				{
					((Channel)(ref deathPlayback.Channel)).stop();
				}
				if (((DSP)(ref deathPlayback.Reverb)).hasHandle())
				{
					((DSP)(ref deathPlayback.Reverb)).release();
				}
			}
			_deathPlaybacks.Clear();
			if (((Sound)(ref _replacementSound)).hasHandle())
			{
				((Sound)(ref _replacementSound)).release();
				((Sound)(ref _replacementSound)).clearHandle();
			}
			if (((Sound)(ref _deathSound)).hasHandle())
			{
				((Sound)(ref _deathSound)).release();
				((Sound)(ref _deathSound)).clearHandle();
			}
			Instance = null;
		}
	}
	[HarmonyPatch(typeof(SimpleEnemyHealthController), "ReceiveDamage")]
	internal static class ShadowmanDeathPatch
	{
		private struct DeathState
		{
			internal bool WasAlive;

			internal bool IsShadowman;

			internal Vector3 Position;

			internal int ObstacleMask;
		}

		private static void Prefix(SimpleEnemyHealthController __instance, ref DeathState __state)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			__state.WasAlive = __instance.CurrentHealth > 0f;
			ManInShadowsBehaviour component = ((Component)__instance).GetComponent<ManInShadowsBehaviour>();
			__state.IsShadowman = (Object)(object)component != (Object)null;
			__state.Position = Plugin.ResolveVisionPosition(component);
			__state.ObstacleMask = Plugin.ResolveObstacleMask(component);
		}

		private static void Postfix(SimpleEnemyHealthController __instance, DeathState __state)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (__state.WasAlive && __state.IsShadowman && __instance.CurrentHealth <= 0f)
			{
				Plugin.Instance?.PlayDeathSound(__state.Position, __state.ObstacleMask);
			}
		}
	}
	[HarmonyPatch(typeof(ManInShadowsBehaviour), "FixedUpdate")]
	internal static class ReplaceWhisperUpdatePatch
	{
		private static void Postfix(ManInShadowsBehaviour __instance, ref EventInstance ____localVisibilitySoundInstance)
		{
			//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)
			float visibilityVolume = 1f;
			if (((EventInstance)(ref ____localVisibilitySoundInstance)).isValid())
			{
				((EventInstance)(ref ____localVisibilitySoundInstance)).getVolume(ref visibilityVolume);
				((EventInstance)(ref ____localVisibilitySoundInstance)).setVolume(0f);
			}
			Plugin.Instance?.UpdateReplacement(__instance, visibilityVolume);
		}
	}
	[HarmonyPatch(typeof(ManInShadowsBehaviour), "Despawned")]
	internal static class ReplaceWhisperDespawnPatch
	{
		private static void Prefix(ManInShadowsBehaviour __instance, NetworkRunner runner, bool hasState)
		{
			Plugin.Instance?.StopReplacement(__instance);
		}
	}
}