Decompiled source of Dread v1.3.0

BepInEx/plugins/elytraking-Dread/Dread.dll

Decompiled 10 hours 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 System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dread.Config;
using Dread.Systems;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Dread")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+63da6a0569cfd7cfdcdb6ab2bc79cc9f677c5bc1")]
[assembly: AssemblyProduct("Dread")]
[assembly: AssemblyTitle("Dread")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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 Dread
{
	[BepInPlugin("elytraking.dread", "Dread", "1.3.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "elytraking.dread";

		public const string NAME = "Dread";

		public const string VERSION = "1.3.0";

		internal static ManualLogSource Logger;

		private readonly Harmony _harmony = new Harmony("elytraking.dread");

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			DreadConfig.Initialize(((BaseUnityPlugin)this).Config);
			_harmony.PatchAll();
			Logger.LogInfo((object)"Dread v1.3.0 loaded.");
		}

		private void Start()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0010: 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)
			GameObject val = new GameObject("DreadHost");
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<AudioDreadSystem>();
			val.AddComponent<MonsterOverhaulSystem>();
			val.AddComponent<TensionSystem>();
		}
	}
}
namespace Dread.Systems
{
	public class AudioDreadSystem : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <LoadClips>d__5 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public AudioDreadSystem <>4__this;

			private string <audioDir>5__2;

			private string[] <>7__wrap2;

			private int <>7__wrap3;

			private string <name>5__5;

			private UnityWebRequest <req>5__6;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadClips>d__5(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();
					}
				}
				<audioDir>5__2 = null;
				<>7__wrap2 = null;
				<name>5__5 = null;
				<req>5__6 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ff: Invalid comparison between Unknown and I4
				try
				{
					int num = <>1__state;
					AudioDreadSystem audioDreadSystem = <>4__this;
					if (num != 0)
					{
						if (num != 1)
						{
							return false;
						}
						<>1__state = -3;
						if ((int)<req>5__6.result == 1)
						{
							AudioClip content = DownloadHandlerAudioClip.GetContent(<req>5__6);
							((Object)content).name = <name>5__5;
							audioDreadSystem._clips.Add(content);
						}
						else
						{
							Plugin.Logger.LogWarning((object)("[AudioDread] Failed to load " + <name>5__5 + ": " + <req>5__6.error));
						}
						<>m__Finally1();
						<req>5__6 = null;
						<name>5__5 = null;
						goto IL_0168;
					}
					<>1__state = -1;
					<audioDir>5__2 = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "audio");
					<>7__wrap2 = ClipNames;
					<>7__wrap3 = 0;
					goto IL_0176;
					IL_0176:
					if (<>7__wrap3 < <>7__wrap2.Length)
					{
						<name>5__5 = <>7__wrap2[<>7__wrap3];
						string text = Path.Combine(<audioDir>5__2, <name>5__5);
						if (!File.Exists(text))
						{
							Plugin.Logger.LogWarning((object)("[AudioDread] Missing audio file: " + text));
							goto IL_0168;
						}
						<req>5__6 = UnityWebRequestMultimedia.GetAudioClip("file:///" + text.Replace('\\', '/'), (AudioType)14);
						<>1__state = -3;
						<>2__current = <req>5__6.SendWebRequest();
						<>1__state = 1;
						return true;
					}
					<>7__wrap2 = null;
					Plugin.Logger.LogInfo((object)$"[AudioDread] Loaded {audioDreadSystem._clips.Count}/{ClipNames.Length} clips.");
					((MonoBehaviour)audioDreadSystem).StartCoroutine(audioDreadSystem.PlayLoop());
					return false;
					IL_0168:
					<>7__wrap3++;
					goto IL_0176;
				}
				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;
				if (<req>5__6 != null)
				{
					((IDisposable)<req>5__6).Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <PlayLoop>d__6 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public AudioDreadSystem <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <PlayLoop>d__6(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Expected O, but got Unknown
				int num = <>1__state;
				AudioDreadSystem audioDreadSystem = <>4__this;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					if (DreadConfig.AudioEnabled.Value && !SemiFunc.MenuLevel() && audioDreadSystem._clips.Count != 0)
					{
						if ((Object)(object)audioDreadSystem._mainCam == (Object)null)
						{
							audioDreadSystem._mainCam = Camera.main;
						}
						if (!((Object)(object)audioDreadSystem._mainCam == (Object)null))
						{
							audioDreadSystem.PlayRandomSound();
						}
					}
				}
				else
				{
					<>1__state = -1;
				}
				float num2 = Random.Range(30f, 90f) / DreadConfig.AudioFrequency.Value;
				<>2__current = (object)new WaitForSeconds(num2);
				<>1__state = 1;
				return true;
			}

			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 readonly List<AudioClip> _clips = new List<AudioClip>();

		private Camera? _mainCam;

		private static readonly string[] ClipNames = new string[5] { "scraping.ogg", "footsteps.ogg", "breathing.ogg", "door_creak.ogg", "whisper.ogg" };

		private static readonly Dictionary<string, float> ClipWeights = new Dictionary<string, float>
		{
			{ "scraping.ogg", 1f },
			{ "footsteps.ogg", 1f },
			{ "breathing.ogg", 0.6f },
			{ "door_creak.ogg", 0.25f },
			{ "whisper.ogg", 0.25f }
		};

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(LoadClips());
		}

		[IteratorStateMachine(typeof(<LoadClips>d__5))]
		private IEnumerator LoadClips()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadClips>d__5(0)
			{
				<>4__this = this
			};
		}

		[IteratorStateMachine(typeof(<PlayLoop>d__6))]
		private IEnumerator PlayLoop()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <PlayLoop>d__6(0)
			{
				<>4__this = this
			};
		}

		private AudioClip PickWeightedClip()
		{
			float num = 0f;
			foreach (AudioClip clip in _clips)
			{
				num += (ClipWeights.TryGetValue(((Object)clip).name, out var value) ? value : 1f);
			}
			float num2 = Random.Range(0f, num);
			foreach (AudioClip clip2 in _clips)
			{
				num2 -= (ClipWeights.TryGetValue(((Object)clip2).name, out var value2) ? value2 : 1f);
				if (num2 <= 0f)
				{
					return clip2;
				}
			}
			return _clips[_clips.Count - 1];
		}

		private void PlayRandomSound()
		{
			//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_0042: 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_005b: 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_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)
			//IL_006c: 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)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			AudioClip val = PickWeightedClip();
			Camera? mainCam = _mainCam;
			Vector3 val2 = new Vector3(Random.Range(-1f, 1f), Random.Range(-0.3f, 0.3f), Random.Range(-1f, 1f));
			Vector3 val3 = ((Vector3)(ref val2)).normalized * Random.Range(5f, 15f);
			Vector3 position = ((Component)mainCam).transform.position + val3;
			GameObject val4 = new GameObject("DreadSound");
			val4.transform.position = position;
			AudioSource obj = val4.AddComponent<AudioSource>();
			obj.clip = val;
			obj.spatialBlend = 1f;
			obj.volume = DreadConfig.AudioVolume.Value;
			obj.rolloffMode = (AudioRolloffMode)1;
			obj.minDistance = 1f;
			obj.maxDistance = 25f;
			obj.Play();
			Object.Destroy((Object)val4, val.length + 0.5f);
		}
	}
	public class MonsterOverhaulSystem : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <MonsterAudioLoop>d__4 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public MonsterOverhaulSystem <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <MonsterAudioLoop>d__4(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;
				MonsterOverhaulSystem monsterOverhaulSystem = <>4__this;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					if (DreadConfig.MonsterAudioEnabled.Value && monsterOverhaulSystem._inLevel)
					{
						EnemyHealth[] array = Object.FindObjectsOfType<EnemyHealth>();
						foreach (EnemyHealth val in array)
						{
							if (!((Object)(object)((Component)val).GetComponent<DreadAudioTweaked>() != (Object)null))
							{
								((Component)val).gameObject.AddComponent<DreadAudioTweaked>();
								ApplyAudioTweaks(((Component)val).gameObject);
							}
						}
					}
				}
				else
				{
					<>1__state = -1;
				}
				<>2__current = (object)new WaitForSeconds(4f);
				<>1__state = 1;
				return true;
			}

			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 bool _inLevel;

		private void Start()
		{
			SceneManager.sceneLoaded += OnSceneLoaded;
			((MonoBehaviour)this).StartCoroutine(MonsterAudioLoop());
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			_inLevel = !((Scene)(ref scene)).name.Contains("Menu") && !((Scene)(ref scene)).name.Contains("Main");
		}

		[IteratorStateMachine(typeof(<MonsterAudioLoop>d__4))]
		private IEnumerator MonsterAudioLoop()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <MonsterAudioLoop>d__4(0)
			{
				<>4__this = this
			};
		}

		private static void ApplyAudioTweaks(GameObject enemy)
		{
			AudioSource[] componentsInChildren = enemy.GetComponentsInChildren<AudioSource>();
			foreach (AudioSource obj in componentsInChildren)
			{
				obj.pitch = Mathf.Clamp(obj.pitch * 0.72f, 0.3f, 1f);
				obj.reverbZoneMix = 1.1f;
				obj.spatialBlend = 1f;
			}
		}
	}
	internal class DreadAudioTweaked : MonoBehaviour
	{
	}
	[HarmonyPatch(typeof(EnemyNavMeshAgent), "Awake")]
	internal static class EnemyNavMeshAgentAwakePatch
	{
		[HarmonyPostfix]
		private static void Postfix(EnemyNavMeshAgent __instance)
		{
			if (DreadConfig.MonsterAggressionEnabled.Value)
			{
				Traverse val = Traverse.Create((object)__instance);
				NavMeshAgent value = val.Field<NavMeshAgent>("Agent").Value;
				if (!((Object)(object)value == (Object)null))
				{
					value.speed *= 1.2f;
					value.acceleration *= 1.2f;
					Traverse<float> obj = val.Field<float>("DefaultSpeed");
					obj.Value *= 1.2f;
					Traverse<float> obj2 = val.Field<float>("DefaultAcceleration");
					obj2.Value *= 1.2f;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController), "Awake")]
	internal static class PlayerControllerAwakePatch
	{
		[HarmonyPostfix]
		private static void Postfix(PlayerController __instance)
		{
			if (DreadConfig.CrouchSpeedBoostEnabled.Value)
			{
				__instance.CrouchSpeed *= 1.3f;
				Traverse val = Traverse.Create((object)__instance);
				float value = val.Field<float>("playerOriginalCrouchSpeed").Value;
				if (value > 0f)
				{
					val.Field<float>("playerOriginalCrouchSpeed").Value = value * 1.3f;
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyDirector), "SetInvestigate")]
	internal static class EnemyDirectorSetInvestigatePatch
	{
		[HarmonyPrefix]
		private static void Prefix(ref float radius)
		{
			if (radius < float.MaxValue)
			{
				radius *= 1.5f;
			}
		}
	}
	public class TensionSystem : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <FakeFootstepLoop>d__26 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public TensionSystem <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <FakeFootstepLoop>d__26(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Expected O, but got Unknown
				int num = <>1__state;
				TensionSystem tensionSystem = <>4__this;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					if (DreadConfig.FakeFootstepsEnabled.Value && !SemiFunc.MenuLevel() && !((Object)(object)tensionSystem._footstepClip == (Object)null) && !(Random.value > 0.35f))
					{
						Camera main = Camera.main;
						if (!((Object)(object)main == (Object)null))
						{
							tensionSystem.SpawnFakeFootstep(main);
						}
					}
				}
				else
				{
					<>1__state = -1;
				}
				<>2__current = (object)new WaitForSeconds(Random.Range(120f, 240f));
				<>1__state = 1;
				return true;
			}

			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 <LoadBreathClips>d__24 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public TensionSystem <>4__this;

			private string <audioDir>5__2;

			private string[] <>7__wrap2;

			private int <>7__wrap3;

			private string <name>5__5;

			private UnityWebRequest <req>5__6;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadBreathClips>d__24(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();
					}
				}
				<audioDir>5__2 = null;
				<>7__wrap2 = null;
				<name>5__5 = null;
				<req>5__6 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e8: Invalid comparison between Unknown and I4
				try
				{
					int num = <>1__state;
					TensionSystem tensionSystem = <>4__this;
					if (num != 0)
					{
						if (num != 1)
						{
							return false;
						}
						<>1__state = -3;
						if ((int)<req>5__6.result == 1)
						{
							tensionSystem._breathClips.Add(DownloadHandlerAudioClip.GetContent(<req>5__6));
							Plugin.Logger.LogInfo((object)("[Dread] Breath clip loaded: " + <name>5__5));
						}
						else
						{
							Plugin.Logger.LogWarning((object)("[Dread] Breath clip failed " + <name>5__5 + ": " + <req>5__6.error));
						}
						<>m__Finally1();
						<req>5__6 = null;
						<name>5__5 = null;
						goto IL_015a;
					}
					<>1__state = -1;
					<audioDir>5__2 = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "audio");
					<>7__wrap2 = BreathCandidates;
					<>7__wrap3 = 0;
					goto IL_0168;
					IL_0168:
					if (<>7__wrap3 < <>7__wrap2.Length)
					{
						<name>5__5 = <>7__wrap2[<>7__wrap3];
						string text = Path.Combine(<audioDir>5__2, <name>5__5);
						if (File.Exists(text))
						{
							<req>5__6 = UnityWebRequestMultimedia.GetAudioClip("file:///" + text.Replace('\\', '/'), (AudioType)14);
							<>1__state = -3;
							<>2__current = <req>5__6.SendWebRequest();
							<>1__state = 1;
							return true;
						}
						goto IL_015a;
					}
					<>7__wrap2 = null;
					return false;
					IL_015a:
					<>7__wrap3++;
					goto IL_0168;
				}
				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;
				if (<req>5__6 != null)
				{
					((IDisposable)<req>5__6).Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <LoadFootstepClip>d__25 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public TensionSystem <>4__this;

			private UnityWebRequest <req>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadFootstepClip>d__25(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();
					}
				}
				<req>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00af: Invalid comparison between Unknown and I4
				bool result;
				try
				{
					int num = <>1__state;
					TensionSystem tensionSystem = <>4__this;
					switch (num)
					{
					default:
						result = false;
						break;
					case 0:
					{
						<>1__state = -1;
						string text = Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "audio"), "footsteps.ogg");
						if (!File.Exists(text))
						{
							result = false;
							break;
						}
						<req>5__2 = UnityWebRequestMultimedia.GetAudioClip("file:///" + text.Replace('\\', '/'), (AudioType)14);
						<>1__state = -3;
						<>2__current = <req>5__2.SendWebRequest();
						<>1__state = 1;
						result = true;
						break;
					}
					case 1:
						<>1__state = -3;
						if ((int)<req>5__2.result == 1)
						{
							tensionSystem._footstepClip = DownloadHandlerAudioClip.GetContent(<req>5__2);
						}
						result = false;
						<>m__Finally1();
						break;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
				return result;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<req>5__2 != null)
				{
					((IDisposable)<req>5__2).Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private AudioSource? _breathSource;

		private readonly List<AudioClip> _breathClips = new List<AudioClip>();

		private AudioClip? _footstepClip;

		private float _nextScan;

		private float _nearestDist = float.MaxValue;

		private float _originalDrain = -1f;

		private bool _wasSprintingForBreath;

		private float _breathCooldown;

		private bool _wasSprinting;

		private bool _panicActive;

		private float _panicTimer;

		private float _panicCooldown;

		private float _originalSprintMultiplier = -1f;

		private const float ProximityRange = 15f;

		private static readonly string[] BreathCandidates = new string[3] { "breathing.ogg", "breath2.ogg", "breath3.ogg" };

		private void Start()
		{
			SceneManager.sceneLoaded += OnSceneLoaded;
			_breathSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			_breathSource.spatialBlend = 0f;
			_breathSource.loop = false;
			_breathSource.playOnAwake = false;
			((MonoBehaviour)this).StartCoroutine(LoadBreathClips());
			((MonoBehaviour)this).StartCoroutine(LoadFootstepClip());
			((MonoBehaviour)this).StartCoroutine(FakeFootstepLoop());
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
			RestoreDrain();
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			_originalDrain = -1f;
			_panicActive = false;
			_panicTimer = 0f;
			_panicCooldown = 0f;
			_originalSprintMultiplier = -1f;
			_wasSprinting = false;
			_wasSprintingForBreath = false;
			_breathCooldown = 0f;
		}

		private void Update()
		{
			if (Time.time >= _nextScan)
			{
				_nextScan = Time.time + 0.5f;
				_nearestDist = (SemiFunc.MenuLevel() ? float.MaxValue : FindNearestEnemyDist());
			}
			UpdateAdrenaline();
			UpdateLowStamina();
			UpdatePanicSprint();
		}

		private void UpdateAdrenaline()
		{
			if (!DreadConfig.AdrenalineEnabled.Value || SemiFunc.MenuLevel())
			{
				return;
			}
			PlayerController instance = PlayerController.instance;
			if (instance != null)
			{
				if (_originalDrain < 0f)
				{
					_originalDrain = instance.EnergySprintDrain;
				}
				float num = ((_nearestDist < 15f) ? (_originalDrain * Mathf.Lerp(0.3f, 1f, _nearestDist / 15f)) : _originalDrain);
				instance.EnergySprintDrain = Mathf.Lerp(instance.EnergySprintDrain, num, Time.deltaTime * 1.2f);
			}
		}

		private void RestoreDrain()
		{
			if (_originalDrain >= 0f && PlayerController.instance != null)
			{
				PlayerController.instance.EnergySprintDrain = _originalDrain;
			}
		}

		private void UpdateLowStamina()
		{
			_breathCooldown -= Time.deltaTime;
			if (!DreadConfig.LowStaminaSoundEnabled.Value || SemiFunc.MenuLevel() || (Object)(object)_breathSource == (Object)null || _breathClips.Count == 0)
			{
				return;
			}
			PlayerController instance = PlayerController.instance;
			if (instance != null && !(instance.EnergyStart <= 0f))
			{
				bool sprinting = instance.sprinting;
				if (_wasSprintingForBreath && !sprinting && instance.EnergyCurrent <= 5f && _breathCooldown <= 0f)
				{
					_breathCooldown = 60f;
					AudioClip clip = _breathClips[Random.Range(0, _breathClips.Count)];
					_breathSource.clip = clip;
					_breathSource.pitch = Random.Range(0.88f, 1.15f);
					_breathSource.volume = 1f;
					_breathSource.Play();
				}
				_wasSprintingForBreath = sprinting;
			}
		}

		private void UpdatePanicSprint()
		{
			if (!DreadConfig.PanicSprintEnabled.Value || SemiFunc.MenuLevel())
			{
				return;
			}
			PlayerController instance = PlayerController.instance;
			if (instance == null)
			{
				return;
			}
			_panicCooldown -= Time.deltaTime;
			bool sprinting = instance.sprinting;
			if (_panicActive)
			{
				_panicTimer -= Time.deltaTime;
				if (_panicTimer <= 0f)
				{
					_panicActive = false;
					_panicCooldown = 20f;
					if (_originalSprintMultiplier >= 0f)
					{
						Traverse.Create((object)instance).Field<float>("SprintSpeedMultiplier").Value = _originalSprintMultiplier;
						_originalSprintMultiplier = -1f;
					}
				}
			}
			else if (!_wasSprinting && sprinting && _nearestDist < 15f && _panicCooldown <= 0f)
			{
				Traverse val = Traverse.Create((object)instance);
				_originalSprintMultiplier = val.Field<float>("SprintSpeedMultiplier").Value;
				val.Field<float>("SprintSpeedMultiplier").Value = _originalSprintMultiplier * 1.25f;
				_panicActive = true;
				_panicTimer = 2f;
			}
			_wasSprinting = sprinting;
		}

		private float FindNearestEnemyDist()
		{
			//IL_003a: 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)
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return float.MaxValue;
			}
			EnemyHealth[] array = Object.FindObjectsOfType<EnemyHealth>();
			float num = float.MaxValue;
			EnemyHealth[] array2 = array;
			foreach (EnemyHealth val in array2)
			{
				if (!((Object)(object)val == (Object)null))
				{
					float num2 = Vector3.Distance(((Component)main).transform.position, ((Component)val).transform.position);
					if (num2 < num)
					{
						num = num2;
					}
				}
			}
			return num;
		}

		[IteratorStateMachine(typeof(<LoadBreathClips>d__24))]
		private IEnumerator LoadBreathClips()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadBreathClips>d__24(0)
			{
				<>4__this = this
			};
		}

		[IteratorStateMachine(typeof(<LoadFootstepClip>d__25))]
		private IEnumerator LoadFootstepClip()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadFootstepClip>d__25(0)
			{
				<>4__this = this
			};
		}

		[IteratorStateMachine(typeof(<FakeFootstepLoop>d__26))]
		private IEnumerator FakeFootstepLoop()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <FakeFootstepLoop>d__26(0)
			{
				<>4__this = this
			};
		}

		private void SpawnFakeFootstep(Camera cam)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0043: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_00eb: Expected O, but got Unknown
			Vector3 val = -((Component)cam).transform.forward;
			Vector3 val2 = ((Component)cam).transform.right * Random.Range(-0.8f, 0.8f);
			Vector3 position = ((Component)cam).transform.position;
			Vector3 val3 = val + val2;
			Vector3 position2 = position + ((Vector3)(ref val3)).normalized * Random.Range(2.5f, 5f);
			position2.y -= 1.5f;
			GameObject val4 = new GameObject("DreadFakeStep");
			val4.transform.position = position2;
			AudioSource obj = val4.AddComponent<AudioSource>();
			obj.clip = _footstepClip;
			obj.spatialBlend = 1f;
			obj.volume = 0.55f;
			obj.rolloffMode = (AudioRolloffMode)1;
			obj.minDistance = 0.5f;
			obj.maxDistance = 8f;
			obj.Play();
			Object.Destroy((Object)val4, _footstepClip.length + 0.5f);
		}
	}
}
namespace Dread.Config
{
	public static class DreadConfig
	{
		public static ConfigEntry<bool> AudioEnabled;

		public static ConfigEntry<float> AudioFrequency;

		public static ConfigEntry<float> AudioVolume;

		public static ConfigEntry<bool> MonsterAggressionEnabled;

		public static ConfigEntry<bool> MonsterAudioEnabled;

		public static ConfigEntry<bool> CrouchSpeedBoostEnabled;

		public static ConfigEntry<bool> FakeFootstepsEnabled;

		public static ConfigEntry<bool> AdrenalineEnabled;

		public static ConfigEntry<bool> LowStaminaSoundEnabled;

		public static ConfigEntry<bool> PanicSprintEnabled;

		public static void Initialize(ConfigFile cfg)
		{
			AudioEnabled = cfg.Bind<bool>("1. Audio Dread", "Enabled", true, "Ambient horror sounds during runs.");
			AudioFrequency = cfg.Bind<float>("1. Audio Dread", "Frequency", 1f, "Sound frequency multiplier. 1 = default, 2 = twice as often.");
			AudioVolume = cfg.Bind<float>("1. Audio Dread", "Volume", 0.4f, "Ambient sound volume (0.0 - 1.0).");
			MonsterAggressionEnabled = cfg.Bind<bool>("2. Monster Overhaul", "AggressionEnabled", true, "Increase monster speed. HOST ONLY.");
			MonsterAudioEnabled = cfg.Bind<bool>("2. Monster Overhaul", "AudioEnabled", true, "Lower monster pitch for deeper, scarier sounds.");
			FakeFootstepsEnabled = cfg.Bind<bool>("3. Tension", "FakeFootstepsEnabled", true, "Occasionally plays footstep sounds behind you with no source.");
			AdrenalineEnabled = cfg.Bind<bool>("3. Tension", "AdrenalineEnabled", true, "Sprint drains up to 70% slower when an enemy is nearby (within 15m).");
			LowStaminaSoundEnabled = cfg.Bind<bool>("3. Tension", "LowStaminaSoundEnabled", true, "Plays a gasp sound when sprint energy drops below 10%.");
			PanicSprintEnabled = cfg.Bind<bool>("3. Tension", "PanicSprintEnabled", true, "Brief 1.25x speed burst when sprinting near an enemy (within 15m). 20s cooldown.");
			CrouchSpeedBoostEnabled = cfg.Bind<bool>("4. QOL", "CrouchSpeedBoost", true, "Crouch movement is 30% faster.");
		}
	}
}