Decompiled source of BehindYou v1.0.0

Mods\BehindYou.dll

Decompiled 16 hours ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BehindYou;
using BehindYou.Audio;
using BehindYou.Config;
using BehindYou.Haunt;
using BehindYou.Menu;
using BoneLib;
using BoneLib.BoneMenu;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("BehindYou")]
[assembly: AssemblyDescription("Footsteps that follow you when nothing is there.")]
[assembly: AssemblyCompany(null)]
[assembly: AssemblyProduct("BehindYou")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: MelonInfo(typeof(BehindYouMod), "BehindYou", "1.0.0", "Rocner", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonColor(255, 138, 20, 20)]
[assembly: MelonAuthorColor(255, 120, 200, 255)]
[assembly: MelonAdditionalDependencies(new string[] { "BoneLib" })]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[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 BehindYou
{
	public sealed class BehindYouMod : MelonMod
	{
		public override void OnInitializeMelon()
		{
			Step("preferences", Prefs.Load);
			Step("audio", StepBank.Load);
			Step("menu", MenuPage.Build);
			Step("level loaded hook", delegate
			{
				Hooking.OnLevelLoaded += OnLevelLoaded;
			});
			Step("level unloaded hook", delegate
			{
				Hooking.OnLevelUnloaded += OnLevelUnloaded;
			});
			((MelonBase)this).LoggerInstance.Msg("BehindYou ready. Something will be along shortly.");
		}

		private void Step(string name, Action action)
		{
			try
			{
				action();
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Error("Init step '" + name + "' failed: " + ex);
			}
		}

		private static void OnLevelLoaded(LevelInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			Haunting.OnLevelLoaded(info.barcode);
		}

		private static void OnLevelUnloaded()
		{
			Haunting.OnLevelUnloaded();
		}

		public override void OnUpdate()
		{
			//IL_0000: 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)
			try
			{
				if ((int)Prefs.TestKey != 0 && Input.GetKeyDown(Prefs.TestKey))
				{
					Haunting.TriggerNow();
				}
				Haunting.Tick(Time.deltaTime);
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Error("Update failed: " + ex);
				Haunting.Stop();
			}
		}

		public override void OnDeinitializeMelon()
		{
			try
			{
				Hooking.OnLevelLoaded -= OnLevelLoaded;
			}
			catch
			{
			}
			try
			{
				Hooking.OnLevelUnloaded -= OnLevelUnloaded;
			}
			catch
			{
			}
			try
			{
				Haunting.Stop();
			}
			catch
			{
			}
			try
			{
				StepEmitter.Destroy();
			}
			catch
			{
			}
			try
			{
				StepBank.Unload();
			}
			catch
			{
			}
			try
			{
				Prefs.Save();
			}
			catch
			{
			}
		}
	}
	internal static class BuildInfo
	{
		public const string Name = "BehindYou";

		public const string Description = "Footsteps that follow you when nothing is there.";

		public const string Author = "Rocner";

		public const string Company = null;

		public const string Version = "1.0.0";
	}
}
namespace BehindYou.Menu
{
	internal static class MenuPage
	{
		private static readonly Color Accent = new Color(0.78f, 0.16f, 0.16f);

		public static void Build()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Page root;
			try
			{
				root = Page.Root.CreatePage("Behind You", Accent, 0, true);
			}
			catch (Exception ex)
			{
				Melon<BehindYouMod>.Logger.Error("BoneMenu root page failed: " + ex);
				return;
			}
			Section("main", delegate
			{
				BuildMain(root);
			});
			Section("timing", delegate
			{
				BuildTiming(root);
			});
			Section("behaviour", delegate
			{
				BuildBehaviour(root);
			});
			Section("modes", delegate
			{
				BuildModes(root);
			});
		}

		private static void Section(string name, Action build)
		{
			try
			{
				build();
			}
			catch (Exception ex)
			{
				Melon<BehindYouMod>.Logger.Error("BoneMenu section '" + name + "' failed: " + ex);
			}
		}

		private static void BuildMain(Page root)
		{
			//IL_0006: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			root.CreateBool("Enabled", Accent, Prefs.Enabled, (Action<bool>)delegate(bool value)
			{
				Prefs.Enabled = value;
				Prefs.Save();
				if (value)
				{
					Haunting.Rearm();
				}
				else
				{
					Haunting.Stop();
				}
			});
			root.CreateFloat("Volume", Accent, Prefs.Volume, 0.05f, 0f, 1f, (Action<float>)delegate(float value)
			{
				Prefs.Volume = value;
				Prefs.Save();
			});
			root.CreateFloat("Trigger Chance", Accent, Prefs.Chance, 5f, 0f, 100f, (Action<float>)delegate(float value)
			{
				Prefs.Chance = value;
				Prefs.Save();
			});
			root.CreateFunction("Trigger Now", Accent, (Action)delegate
			{
				Haunting.TriggerNow();
			});
			root.CreateFunction("Stop Now", Accent, (Action)Haunting.Stop);
		}

		private static void BuildTiming(Page root)
		{
			//IL_0006: 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_005c: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			Page obj = root.CreatePage("Timing", Accent, 0, true);
			obj.CreateFloat("Min Delay", Accent, Prefs.MinDelay, 10f, 5f, 1800f, (Action<float>)delegate(float value)
			{
				Prefs.MinDelay = value;
				Prefs.Save();
			});
			obj.CreateFloat("Max Delay", Accent, Prefs.MaxDelay, 10f, 5f, 3600f, (Action<float>)delegate(float value)
			{
				Prefs.MaxDelay = value;
				Prefs.Save();
			});
			obj.CreateFloat("Cooldown", Accent, Prefs.Cooldown, 5f, 0f, 600f, (Action<float>)delegate(float value)
			{
				Prefs.Cooldown = value;
				Prefs.Save();
			});
			obj.CreateFloat("Level Warmup", Accent, Prefs.Warmup, 5f, 0f, 300f, (Action<float>)delegate(float value)
			{
				Prefs.Warmup = value;
				Prefs.Save();
			});
			obj.CreateFunction("Reroll Timer", Accent, (Action)Haunting.Rearm);
		}

		private static void BuildBehaviour(Page root)
		{
			//IL_0006: 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_005c: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			Page obj = root.CreatePage("Behaviour", Accent, 0, true);
			obj.CreateFloat("Start Distance", Accent, Prefs.StartDistance, 0.5f, 3f, 20f, (Action<float>)delegate(float value)
			{
				Prefs.StartDistance = value;
				Prefs.Save();
			});
			obj.CreateBool("Stop When You Look", Accent, Prefs.StopWhenLookedAt, (Action<bool>)delegate(bool value)
			{
				Prefs.StopWhenLookedAt = value;
				Prefs.Save();
			});
			obj.CreateBool("Keep In Room", Accent, Prefs.KeepInRoom, (Action<bool>)delegate(bool value)
			{
				Prefs.KeepInRoom = value;
				Prefs.Save();
			});
			obj.CreateBool("HRTF Spatializer", Accent, Prefs.Spatialize, (Action<bool>)delegate(bool value)
			{
				Prefs.Spatialize = value;
				Prefs.Save();
				StepEmitter.Destroy();
			});
			obj.CreateBool("Log Events", Accent, Prefs.LogEvents, (Action<bool>)delegate(bool value)
			{
				Prefs.LogEvents = value;
				Prefs.Save();
			});
		}

		private static void BuildModes(Page root)
		{
			//IL_0006: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			Page obj = root.CreatePage("Modes", Accent, 0, true);
			obj.CreateBool("Approach", Accent, Prefs.ModeApproach, (Action<bool>)delegate(bool value)
			{
				Prefs.ModeApproach = value;
				Prefs.Save();
			});
			obj.CreateBool("Pass By", Accent, Prefs.ModePassBy, (Action<bool>)delegate(bool value)
			{
				Prefs.ModePassBy = value;
				Prefs.Save();
			});
			obj.CreateBool("Follow", Accent, Prefs.ModeFollow, (Action<bool>)delegate(bool value)
			{
				Prefs.ModeFollow = value;
				Prefs.Save();
			});
			obj.CreateBool("Single Step", Accent, Prefs.ModeSingle, (Action<bool>)delegate(bool value)
			{
				Prefs.ModeSingle = value;
				Prefs.Save();
			});
			obj.CreateBool("Retreat", Accent, Prefs.ModeRetreat, (Action<bool>)delegate(bool value)
			{
				Prefs.ModeRetreat = value;
				Prefs.Save();
			});
			obj.CreateBool("Circle", Accent, Prefs.ModeCircle, (Action<bool>)delegate(bool value)
			{
				Prefs.ModeCircle = value;
				Prefs.Save();
			});
		}
	}
}
namespace BehindYou.Haunt
{
	internal static class Haunting
	{
		private const float BusyPlayerSpeed = 3f;

		private const float BusyRetryDelay = 15f;

		private static readonly StalkKind[] Kinds = new StalkKind[6]
		{
			StalkKind.Approach,
			StalkKind.PassBy,
			StalkKind.Follow,
			StalkKind.Single,
			StalkKind.Retreat,
			StalkKind.Circle
		};

		private static readonly int[] Weights = new int[6] { 26, 16, 16, 18, 14, 10 };

		private static StalkEvent _event;

		private static Vector3 _lastHead;

		private static bool _levelReady;

		private static bool _levelAllowed;

		private static bool _hasLastHead;

		private static float _levelTime;

		private static float _timer;

		private static float _speed;

		public static bool Active
		{
			get
			{
				if (_event != null)
				{
					return !_event.Finished;
				}
				return false;
			}
		}

		public static void OnLevelLoaded(string barcode)
		{
			_levelReady = true;
			_levelAllowed = barcode != "c2534c5a-80e1-4a29-93ca-f3254d656e75";
			_levelTime = 0f;
			_speed = 0f;
			_hasLastHead = false;
			_event = null;
			StepEmitter.Silence();
			Rearm();
		}

		public static void OnLevelUnloaded()
		{
			_levelReady = false;
			_event = null;
			StepEmitter.Silence();
		}

		public static void Tick(float dt)
		{
			//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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			if (dt <= 0f)
			{
				return;
			}
			if (!Prefs.Enabled)
			{
				if (_event != null)
				{
					Stop();
				}
			}
			else
			{
				if (!_levelReady || !StepBank.Ready)
				{
					return;
				}
				Transform head = Player.Head;
				if ((Object)(object)head == (Object)null)
				{
					return;
				}
				Vector3 position = head.position;
				Vector3 forward = head.forward;
				Vector3 flatForward = FlatForward(forward);
				TrackSpeed(dt, position);
				_levelTime += dt;
				if (_event != null)
				{
					Advance(dt, position, flatForward, forward);
				}
				else
				{
					if (!_levelAllowed || _levelTime < Prefs.Warmup)
					{
						return;
					}
					_timer -= dt;
					if (_timer > 0f)
					{
						return;
					}
					if (Random.value * 100f >= Prefs.Chance)
					{
						Rearm();
						if (Prefs.LogEvents)
						{
							Melon<BehindYouMod>.Logger.Msg($"Not this time. Next roll in {_timer:0}s.");
						}
					}
					else if (_speed > 3f)
					{
						_timer = 15f;
					}
					else
					{
						Start(position, flatForward);
					}
				}
			}
		}

		public static bool TriggerNow()
		{
			//IL_0054: 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)
			if (!StepBank.Ready)
			{
				Melon<BehindYouMod>.Logger.Warning("Footstep audio is not loaded yet.");
				return false;
			}
			Transform head = Player.Head;
			if ((Object)(object)head == (Object)null)
			{
				Melon<BehindYouMod>.Logger.Warning("No player head found, load into a level first.");
				return false;
			}
			Stop();
			_levelReady = true;
			_levelTime = Prefs.Warmup + 1f;
			return Start(head.position, FlatForward(head.forward));
		}

		public static void Stop()
		{
			if (_event != null)
			{
				_event.Abort();
				_event = null;
			}
			StepEmitter.Silence();
		}

		public static void Rearm()
		{
			_timer = Random.Range(Prefs.MinDelay, Prefs.MaxDelay);
		}

		private static void Advance(float dt, Vector3 headPos, Vector3 flatForward, Vector3 headForward)
		{
			//IL_0019: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			if (!StepEmitter.Ensure())
			{
				_event = null;
				Rearm();
				return;
			}
			_event.Tick(dt, headPos, flatForward, headForward);
			if (_event.Finished)
			{
				StalkEvent stalkEvent = _event;
				_event = null;
				StepEmitter.Silence();
				_timer = Prefs.Cooldown + Random.Range(Prefs.MinDelay, Prefs.MaxDelay);
				if (Prefs.LogEvents)
				{
					string value = (stalkEvent.StoppedByLook ? " (you turned around)" : string.Empty);
					Melon<BehindYouMod>.Logger.Msg($"{stalkEvent.Kind} ended after {stalkEvent.StepsPlayed} steps{value}.");
				}
			}
		}

		private static bool Start(Vector3 headPos, Vector3 flatForward)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (!StepEmitter.Ensure())
			{
				return false;
			}
			if (!PickKind(out var kind))
			{
				_timer = 30f;
				Melon<BehindYouMod>.Logger.Warning("Every mode is turned off, so nothing can play.");
				return false;
			}
			StalkEvent stalkEvent = new StalkEvent();
			stalkEvent.Begin(kind, headPos, flatForward);
			_event = stalkEvent;
			if (Prefs.LogEvents)
			{
				Melon<BehindYouMod>.Logger.Msg($"{kind} starting {stalkEvent.SpawnDistance:0.0}m behind you.");
			}
			return true;
		}

		private static bool PickKind(out StalkKind kind)
		{
			kind = StalkKind.Single;
			int num = 0;
			for (int i = 0; i < Kinds.Length; i++)
			{
				if (IsModeEnabled(Kinds[i]))
				{
					num += Weights[i];
				}
			}
			if (num <= 0)
			{
				return false;
			}
			int num2 = Random.Range(0, num);
			for (int j = 0; j < Kinds.Length; j++)
			{
				if (IsModeEnabled(Kinds[j]))
				{
					num2 -= Weights[j];
					if (num2 < 0)
					{
						kind = Kinds[j];
						return true;
					}
				}
			}
			for (int k = 0; k < Kinds.Length; k++)
			{
				if (IsModeEnabled(Kinds[k]))
				{
					kind = Kinds[k];
					return true;
				}
			}
			return false;
		}

		private static bool IsModeEnabled(StalkKind kind)
		{
			return kind switch
			{
				StalkKind.Approach => Prefs.ModeApproach, 
				StalkKind.PassBy => Prefs.ModePassBy, 
				StalkKind.Follow => Prefs.ModeFollow, 
				StalkKind.Single => Prefs.ModeSingle, 
				StalkKind.Retreat => Prefs.ModeRetreat, 
				StalkKind.Circle => Prefs.ModeCircle, 
				_ => false, 
			};
		}

		private static void TrackSpeed(float dt, Vector3 headPos)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0008: 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_0012: Unknown result type (might be due to invalid IL or missing references)
			if (_hasLastHead)
			{
				Vector3 val = headPos - _lastHead;
				val.y = 0f;
				float num = Mathf.Min(((Vector3)(ref val)).magnitude / dt, 20f);
				_speed = Mathf.Lerp(_speed, num, 1f - Mathf.Exp((0f - dt) / 0.35f));
			}
			_lastHead = headPos;
			_hasLastHead = true;
		}

		private static Vector3 FlatForward(Vector3 forward)
		{
			//IL_0022: 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)
			forward.y = 0f;
			if (!(((Vector3)(ref forward)).sqrMagnitude > 0.0001f))
			{
				return Vector3.forward;
			}
			return ((Vector3)(ref forward)).normalized;
		}
	}
	internal enum StalkKind
	{
		Approach,
		PassBy,
		Follow,
		Single,
		Retreat,
		Circle
	}
	internal sealed class StalkEvent
	{
		private const float Stride = 0.62f;

		private const float LookDot = 0.5f;

		private const float FallbackDrop = 1.6f;

		private StalkKind _kind;

		private Vector3 _pos;

		private Vector3 _lineDir;

		private float _speed;

		private float _moveSpeed;

		private float _stepTimer;

		private float _life;

		private float _maxLife;

		private float _pitchBias;

		private float _stopDistance;

		private float _followDistance;

		private float _holdTimer;

		private float _travelled;

		private float _span;

		private float _angle;

		private float _angleLeft;

		private float _angleDir = 1f;

		private float _radius;

		private float _fade = 1f;

		private float _groundY;

		private float _scuffTimer;

		private float _scuffVolume;

		private float _scuffPitch;

		private int _stepsPlayed;

		private int _stepLimit;

		private int _extraSteps;

		private bool _holding;

		private bool _wasMoving;

		public bool Finished { get; private set; }

		public StalkKind Kind => _kind;

		public int StepsPlayed => _stepsPlayed;

		public bool StoppedByLook { get; private set; }

		public float SpawnDistance { get; private set; }

		public void Begin(StalkKind kind, Vector3 headPos, Vector3 flatForward)
		{
			//IL_001d: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: 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_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			_kind = kind;
			_pitchBias = Random.Range(0.9f, 1.06f);
			_groundY = headPos.y - 1.6f;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(headPos.x, _groundY, headPos.z);
			Vector3 val2 = -flatForward;
			Vector3 val3 = Vector3.Cross(Vector3.up, flatForward);
			Vector3 normalized = ((Vector3)(ref val3)).normalized;
			float num = ((Random.value < 0.5f) ? (-1f) : 1f);
			float startDistance = Prefs.StartDistance;
			switch (kind)
			{
			case StalkKind.Approach:
				_pos = val + val2 * (startDistance * Random.Range(0.8f, 1.15f)) + normalized * (num * Random.Range(0f, 1.4f));
				_speed = Random.Range(0.85f, 1.25f);
				_stopDistance = Random.Range(1.5f, 2.5f);
				_maxLife = 45f;
				break;
			case StalkKind.PassBy:
				_span = startDistance * Random.Range(0.75f, 1.05f);
				_lineDir = normalized * num;
				_pos = val + val2 * Random.Range(2.2f, 4f) - _lineDir * _span;
				_speed = Random.Range(1.05f, 1.5f);
				_maxLife = _span * 2f / _speed + 5f;
				break;
			case StalkKind.Follow:
				_followDistance = Random.Range(3f, 4.5f);
				_pos = val + val2 * _followDistance;
				_speed = 1.9f;
				_maxLife = Random.Range(15f, 28f);
				break;
			case StalkKind.Single:
				_pos = val + val2 * Random.Range(1.9f, 3.2f) + normalized * (num * Random.Range(0f, 1f));
				_stepLimit = ((!(Random.value < 0.35f)) ? 1 : 2);
				_stepTimer = Random.Range(0.15f, 0.5f);
				_maxLife = 5f;
				break;
			case StalkKind.Retreat:
				_pos = val + val2 * Random.Range(1.7f, 2.6f) + normalized * (num * Random.Range(0f, 0.6f));
				val3 = val2 + normalized * (num * Random.Range(-0.45f, 0.45f));
				_lineDir = ((Vector3)(ref val3)).normalized;
				_speed = Random.Range(1f, 1.45f);
				_maxLife = 24f;
				break;
			case StalkKind.Circle:
				_radius = Random.Range(3.2f, 5f);
				_angle = Mathf.Atan2(val2.z, val2.x) + Random.Range(-0.45f, 0.45f);
				_angleLeft = Random.Range(1.8f, 3.4f);
				_angleDir = num;
				_speed = Random.Range(0.9f, 1.3f);
				_pos = val + new Vector3(Mathf.Cos(_angle), 0f, Mathf.Sin(_angle)) * _radius;
				_maxLife = _angleLeft * _radius / _speed + 5f;
				break;
			}
			_pos.y = _groundY;
			val3 = Flat(_pos - headPos);
			SpawnDistance = ((Vector3)(ref val3)).magnitude;
			if (_stepTimer <= 0f)
			{
				_stepTimer = Random.Range(0.05f, 0.35f);
			}
		}

		public void Tick(float dt, Vector3 headPos, Vector3 flatForward, Vector3 headForward)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			if (Finished)
			{
				return;
			}
			_life += dt;
			if (_life > _maxLife)
			{
				Finish();
				return;
			}
			if (Prefs.StopWhenLookedAt && _stepsPlayed > 0 && LookedAt(headPos, headForward))
			{
				StoppedByLook = true;
				Finish();
				return;
			}
			_groundY = headPos.y - 1.6f;
			Vector3 ground = default(Vector3);
			((Vector3)(ref ground))..ctor(headPos.x, _groundY, headPos.z);
			Vector3 pos = _pos;
			bool flag = Move(dt, ground, flatForward);
			if (Finished)
			{
				return;
			}
			Vector3 val = Flat(_pos - pos);
			float magnitude = ((Vector3)(ref val)).magnitude;
			_moveSpeed = Mathf.Lerp(_moveSpeed, (dt > 0f) ? (magnitude / dt) : 0f, 0.3f);
			TickScuff(dt, headPos);
			bool flag2 = flag || _extraSteps > 0 || _kind == StalkKind.Single;
			if (_stepLimit > 0 && _stepsPlayed >= _stepLimit)
			{
				flag2 = false;
			}
			_stepTimer -= dt;
			if (flag2 && !(_stepTimer > 0f))
			{
				bool flag3 = !flag && _extraSteps > 0;
				PlayStep(headPos);
				if (flag3)
				{
					_extraSteps--;
				}
				_stepTimer = NextInterval(flag3);
			}
		}

		public void Abort()
		{
			Finish();
		}

		private bool Move(float dt, Vector3 ground, Vector3 flatForward)
		{
			//IL_002a: 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_0036: 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_00de: 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_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_00b4: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			switch (_kind)
			{
			case StalkKind.Approach:
			{
				Vector3 val = Flat(ground - _pos);
				float magnitude = ((Vector3)(ref val)).magnitude;
				if (_holding || magnitude <= _stopDistance)
				{
					_holding = true;
					_holdTimer += dt;
					if (_holdTimer > 2.4f)
					{
						Finish();
					}
					return false;
				}
				float num2 = Mathf.Min(((magnitude < 4f) ? (_speed * 0.7f) : _speed) * dt, magnitude - _stopDistance);
				_pos += val / magnitude * num2;
				return num2 > 0.0001f;
			}
			case StalkKind.PassBy:
			{
				float num3 = _speed * dt;
				_pos += _lineDir * num3;
				_travelled += num3;
				if (_travelled >= _span * 2f)
				{
					Finish();
				}
				return true;
			}
			case StalkKind.Follow:
			{
				Vector3 val3 = Flat(ground - flatForward * _followDistance - _pos);
				float magnitude3 = ((Vector3)(ref val3)).magnitude;
				bool flag = magnitude3 > 0.3f;
				if (magnitude3 > 0.0001f)
				{
					_pos += val3 / magnitude3 * Mathf.Min(_speed * dt, magnitude3);
				}
				if (_wasMoving && !flag)
				{
					_extraSteps = ((!(Random.value < 0.45f)) ? 1 : 2);
					_stepTimer = Random.Range(0.34f, 0.66f);
				}
				_wasMoving = flag;
				return flag;
			}
			case StalkKind.Retreat:
			{
				_pos += _lineDir * _speed * dt;
				Vector3 val2 = Flat(_pos - ground);
				float magnitude2 = ((Vector3)(ref val2)).magnitude;
				_fade = Mathf.Clamp01(Mathf.InverseLerp(13.5f, 9f, magnitude2));
				if (magnitude2 > 13f)
				{
					Finish();
				}
				return true;
			}
			case StalkKind.Circle:
			{
				float num = _speed / Mathf.Max(0.5f, _radius) * dt;
				if (num > _angleLeft)
				{
					num = _angleLeft;
				}
				_angle += num * _angleDir;
				_angleLeft -= num;
				_pos = ground + new Vector3(Mathf.Cos(_angle), 0f, Mathf.Sin(_angle)) * _radius;
				if (_angleLeft <= 0.0005f)
				{
					Finish();
				}
				return true;
			}
			default:
				return false;
			}
		}

		private void PlayStep(Vector3 headPos)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_0017: 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_002d: 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)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_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)
			Vector3 val = _pos;
			val.y = ResolveGround(val, headPos);
			_pos = val;
			if (Prefs.KeepInRoom)
			{
				val = PullIntoRoom(headPos, val);
			}
			StepEmitter.MoveTo(val);
			float distance = Vector3.Distance(headPos, val);
			float num = Prefs.Volume * _fade * Random.Range(0.86f, 1f);
			float num2 = _pitchBias * Random.Range(0.95f, 1.05f);
			StepEmitter.Play(StepBank.Next(), num, num2, distance);
			_stepsPlayed++;
			if (Random.value < 0.09f)
			{
				_scuffTimer = Random.Range(0.09f, 0.17f);
				_scuffVolume = num * Random.Range(0.28f, 0.45f);
				_scuffPitch = num2 * Random.Range(1.06f, 1.22f);
			}
		}

		private void TickScuff(float dt, Vector3 headPos)
		{
			//IL_002a: 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)
			if (!(_scuffTimer <= 0f))
			{
				_scuffTimer -= dt;
				if (!(_scuffTimer > 0f))
				{
					float distance = Vector3.Distance(headPos, StepEmitter.Position);
					StepEmitter.Play(StepBank.Next(), _scuffVolume, _scuffPitch, distance);
				}
			}
		}

		private float NextInterval(bool extra)
		{
			if (extra)
			{
				return Random.Range(0.42f, 0.62f);
			}
			if (_kind == StalkKind.Single)
			{
				return Random.Range(0.38f, 0.5f);
			}
			return Mathf.Clamp(0.62f / Mathf.Max(0.25f, _moveSpeed), 0.32f, 1.15f) * Random.Range(0.9f, 1.1f);
		}

		private bool LookedAt(Vector3 headPos, Vector3 headForward)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0022: 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_0028: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Flat(_pos - headPos);
			if (((Vector3)(ref val)).sqrMagnitude < 0.04f)
			{
				return false;
			}
			Vector3 val2 = Flat(headForward);
			if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
			{
				return false;
			}
			return Vector3.Dot(((Vector3)(ref val2)).normalized, ((Vector3)(ref val)).normalized) > 0.5f;
		}

		private float ResolveGround(Vector3 point, Vector3 headPos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_001d: 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_0040: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				RaycastHit val = default(RaycastHit);
				if (Physics.Raycast(new Vector3(point.x, headPos.y + 0.6f, point.z), Vector3.down, ref val, 6f, -1, (QueryTriggerInteraction)1))
				{
					float y = ((RaycastHit)(ref val)).point.y;
					if (y < headPos.y + 0.2f && y > headPos.y - 4f)
					{
						return y;
					}
				}
			}
			catch
			{
			}
			return headPos.y - 1.6f;
		}

		private Vector3 PullIntoRoom(Vector3 headPos, Vector3 point)
		{
			//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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_0041: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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)
			try
			{
				Vector3 val = point - headPos;
				float magnitude = ((Vector3)(ref val)).magnitude;
				if (magnitude < 1.2f)
				{
					return point;
				}
				Vector3 val2 = val / magnitude;
				Vector3 val3 = headPos + val2 * 0.45f;
				float num = magnitude - 0.45f;
				RaycastHit val4 = default(RaycastHit);
				if (Physics.Raycast(val3, val2, ref val4, num, -1, (QueryTriggerInteraction)1) && ((RaycastHit)(ref val4)).distance < num - 0.5f)
				{
					Vector3 val5 = headPos + val2 * Mathf.Max(1.3f, 0.1f + ((RaycastHit)(ref val4)).distance);
					val5.y = ResolveGround(val5, headPos);
					return val5;
				}
			}
			catch
			{
			}
			return point;
		}

		private void Finish()
		{
			Finished = true;
		}

		private static Vector3 Flat(Vector3 value)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			value.y = 0f;
			return value;
		}
	}
}
namespace BehindYou.Config
{
	internal static class Prefs
	{
		private static MelonPreferences_Category _category;

		private static MelonPreferences_Entry<bool> _enabled;

		private static MelonPreferences_Entry<float> _volume;

		private static MelonPreferences_Entry<float> _chance;

		private static MelonPreferences_Entry<float> _minDelay;

		private static MelonPreferences_Entry<float> _maxDelay;

		private static MelonPreferences_Entry<float> _cooldown;

		private static MelonPreferences_Entry<float> _warmup;

		private static MelonPreferences_Entry<float> _startDistance;

		private static MelonPreferences_Entry<bool> _stopWhenLookedAt;

		private static MelonPreferences_Entry<bool> _keepInRoom;

		private static MelonPreferences_Entry<bool> _spatialize;

		private static MelonPreferences_Entry<bool> _logEvents;

		private static MelonPreferences_Entry<int> _testKey;

		private static MelonPreferences_Entry<bool> _modeApproach;

		private static MelonPreferences_Entry<bool> _modePassBy;

		private static MelonPreferences_Entry<bool> _modeFollow;

		private static MelonPreferences_Entry<bool> _modeSingle;

		private static MelonPreferences_Entry<bool> _modeRetreat;

		private static MelonPreferences_Entry<bool> _modeCircle;

		public static bool Enabled
		{
			get
			{
				return _enabled?.Value ?? true;
			}
			set
			{
				if (_enabled != null)
				{
					_enabled.Value = value;
				}
			}
		}

		public static float Volume
		{
			get
			{
				return Mathf.Clamp01(_volume?.Value ?? 0.75f);
			}
			set
			{
				if (_volume != null)
				{
					_volume.Value = value;
				}
			}
		}

		public static float Chance
		{
			get
			{
				return Mathf.Clamp(_chance?.Value ?? 50f, 0f, 100f);
			}
			set
			{
				if (_chance != null)
				{
					_chance.Value = value;
				}
			}
		}

		public static float MinDelay
		{
			get
			{
				return Mathf.Clamp(_minDelay?.Value ?? 90f, 5f, 3600f);
			}
			set
			{
				if (_minDelay != null)
				{
					_minDelay.Value = value;
				}
			}
		}

		public static float MaxDelay
		{
			get
			{
				return Mathf.Max(MinDelay, Mathf.Clamp(_maxDelay?.Value ?? 300f, 5f, 3600f));
			}
			set
			{
				if (_maxDelay != null)
				{
					_maxDelay.Value = value;
				}
			}
		}

		public static float Cooldown
		{
			get
			{
				return Mathf.Clamp(_cooldown?.Value ?? 45f, 0f, 600f);
			}
			set
			{
				if (_cooldown != null)
				{
					_cooldown.Value = value;
				}
			}
		}

		public static float Warmup
		{
			get
			{
				return Mathf.Clamp(_warmup?.Value ?? 20f, 0f, 300f);
			}
			set
			{
				if (_warmup != null)
				{
					_warmup.Value = value;
				}
			}
		}

		public static float StartDistance
		{
			get
			{
				return Mathf.Clamp(_startDistance?.Value ?? 9f, 3f, 20f);
			}
			set
			{
				if (_startDistance != null)
				{
					_startDistance.Value = value;
				}
			}
		}

		public static bool StopWhenLookedAt
		{
			get
			{
				return _stopWhenLookedAt?.Value ?? true;
			}
			set
			{
				if (_stopWhenLookedAt != null)
				{
					_stopWhenLookedAt.Value = value;
				}
			}
		}

		public static bool KeepInRoom
		{
			get
			{
				return _keepInRoom?.Value ?? true;
			}
			set
			{
				if (_keepInRoom != null)
				{
					_keepInRoom.Value = value;
				}
			}
		}

		public static bool Spatialize
		{
			get
			{
				return _spatialize?.Value ?? true;
			}
			set
			{
				if (_spatialize != null)
				{
					_spatialize.Value = value;
				}
			}
		}

		public static bool LogEvents
		{
			get
			{
				return _logEvents?.Value ?? true;
			}
			set
			{
				if (_logEvents != null)
				{
					_logEvents.Value = value;
				}
			}
		}

		public static KeyCode TestKey
		{
			get
			{
				MelonPreferences_Entry<int> testKey = _testKey;
				if (testKey != null)
				{
					return (KeyCode)testKey.Value;
				}
				return (KeyCode)290;
			}
			set
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Expected I4, but got Unknown
				if (_testKey != null)
				{
					_testKey.Value = (int)value;
				}
			}
		}

		public static bool ModeApproach
		{
			get
			{
				return _modeApproach?.Value ?? true;
			}
			set
			{
				if (_modeApproach != null)
				{
					_modeApproach.Value = value;
				}
			}
		}

		public static bool ModePassBy
		{
			get
			{
				return _modePassBy?.Value ?? true;
			}
			set
			{
				if (_modePassBy != null)
				{
					_modePassBy.Value = value;
				}
			}
		}

		public static bool ModeFollow
		{
			get
			{
				return _modeFollow?.Value ?? true;
			}
			set
			{
				if (_modeFollow != null)
				{
					_modeFollow.Value = value;
				}
			}
		}

		public static bool ModeSingle
		{
			get
			{
				return _modeSingle?.Value ?? true;
			}
			set
			{
				if (_modeSingle != null)
				{
					_modeSingle.Value = value;
				}
			}
		}

		public static bool ModeRetreat
		{
			get
			{
				return _modeRetreat?.Value ?? true;
			}
			set
			{
				if (_modeRetreat != null)
				{
					_modeRetreat.Value = value;
				}
			}
		}

		public static bool ModeCircle
		{
			get
			{
				return _modeCircle?.Value ?? true;
			}
			set
			{
				if (_modeCircle != null)
				{
					_modeCircle.Value = value;
				}
			}
		}

		public static void Load()
		{
			_category = MelonPreferences.CreateCategory("BehindYou");
			_enabled = _category.CreateEntry<bool>("Enabled", true, "Enabled", (string)null, false, false, (ValueValidator)null, (string)null);
			_volume = _category.CreateEntry<float>("Volume", 0.75f, "Volume", (string)null, false, false, (ValueValidator)null, (string)null);
			_chance = _category.CreateEntry<float>("Chance", 50f, "Trigger Chance (%)", (string)null, false, false, (ValueValidator)null, (string)null);
			_minDelay = _category.CreateEntry<float>("MinDelay", 90f, "Min Delay (s)", (string)null, false, false, (ValueValidator)null, (string)null);
			_maxDelay = _category.CreateEntry<float>("MaxDelay", 300f, "Max Delay (s)", (string)null, false, false, (ValueValidator)null, (string)null);
			_cooldown = _category.CreateEntry<float>("Cooldown", 45f, "Cooldown (s)", (string)null, false, false, (ValueValidator)null, (string)null);
			_warmup = _category.CreateEntry<float>("Warmup", 20f, "Level Warmup (s)", (string)null, false, false, (ValueValidator)null, (string)null);
			_startDistance = _category.CreateEntry<float>("StartDistance", 9f, "Start Distance (m)", (string)null, false, false, (ValueValidator)null, (string)null);
			_stopWhenLookedAt = _category.CreateEntry<bool>("StopWhenLookedAt", true, "Stop When You Look", (string)null, false, false, (ValueValidator)null, (string)null);
			_keepInRoom = _category.CreateEntry<bool>("KeepInRoom", true, "Keep In Room", (string)null, false, false, (ValueValidator)null, (string)null);
			_spatialize = _category.CreateEntry<bool>("Spatialize", true, "Use HRTF Spatializer", (string)null, false, false, (ValueValidator)null, (string)null);
			_logEvents = _category.CreateEntry<bool>("LogEvents", true, "Log Events", (string)null, false, false, (ValueValidator)null, (string)null);
			_testKey = _category.CreateEntry<int>("TestKey", 290, "Test Key", (string)null, false, false, (ValueValidator)null, (string)null);
			_modeApproach = _category.CreateEntry<bool>("ModeApproach", true, "Mode: Approach", (string)null, false, false, (ValueValidator)null, (string)null);
			_modePassBy = _category.CreateEntry<bool>("ModePassBy", true, "Mode: Pass By", (string)null, false, false, (ValueValidator)null, (string)null);
			_modeFollow = _category.CreateEntry<bool>("ModeFollow", true, "Mode: Follow", (string)null, false, false, (ValueValidator)null, (string)null);
			_modeSingle = _category.CreateEntry<bool>("ModeSingle", true, "Mode: Single Step", (string)null, false, false, (ValueValidator)null, (string)null);
			_modeRetreat = _category.CreateEntry<bool>("ModeRetreat", true, "Mode: Retreat", (string)null, false, false, (ValueValidator)null, (string)null);
			_modeCircle = _category.CreateEntry<bool>("ModeCircle", true, "Mode: Circle", (string)null, false, false, (ValueValidator)null, (string)null);
		}

		public static void Save()
		{
			try
			{
				MelonPreferences_Category category = _category;
				if (category != null)
				{
					category.SaveToFile(false);
				}
			}
			catch
			{
			}
		}
	}
}
namespace BehindYou.Audio
{
	internal static class StepBank
	{
		private const string ResourceName = "BehindYou.footsteps.wav";

		private const int Steps = 6;

		private static AudioClip[] _clips;

		private static int _last = -1;

		public static bool Ready
		{
			get
			{
				if (_clips != null)
				{
					return _clips.Length != 0;
				}
				return false;
			}
		}

		public static float StepLength { get; private set; } = 0.3f;

		public static void Load()
		{
			if (Ready)
			{
				return;
			}
			byte[] array = ReadResource();
			if (array == null)
			{
				return;
			}
			if (!Decode(array, out var samples, out var channels, out var rate))
			{
				Melon<BehindYouMod>.Logger.Error("Embedded footstep audio could not be decoded.");
				return;
			}
			if (channels > 1)
			{
				samples = Downmix(samples, channels);
			}
			int num = samples.Length / 6;
			if (num < 64)
			{
				Melon<BehindYouMod>.Logger.Error("Embedded footstep audio is too short.");
				return;
			}
			AudioClip[] array2 = (AudioClip[])(object)new AudioClip[6];
			for (int i = 0; i < 6; i++)
			{
				AudioClip val = AudioClip.Create("BehindYou_Step" + i, num, 1, rate, false);
				if ((Object)(object)val == (Object)null)
				{
					Melon<BehindYouMod>.Logger.Error("AudioClip.Create returned null.");
					return;
				}
				Il2CppStructArray<float> val2 = new Il2CppStructArray<float>((long)num);
				int num2 = i * num;
				for (int j = 0; j < num; j++)
				{
					((Il2CppArrayBase<float>)(object)val2)[j] = samples[num2 + j];
				}
				val.SetData(val2, 0);
				((Object)val).hideFlags = (HideFlags)61;
				array2[i] = val;
			}
			_clips = array2;
			StepLength = (float)num / (float)rate;
			Melon<BehindYouMod>.Logger.Msg($"Loaded {6} footsteps ({rate} Hz, {StepLength:0.00}s each).");
		}

		public static AudioClip Next()
		{
			if (!Ready)
			{
				return null;
			}
			if (_clips.Length == 1)
			{
				return _clips[0];
			}
			int num = _last;
			for (int i = 0; i < 8; i++)
			{
				if (num != _last)
				{
					break;
				}
				num = Random.Range(0, _clips.Length);
			}
			_last = num;
			return _clips[num];
		}

		public static void Unload()
		{
			if (_clips == null)
			{
				return;
			}
			for (int i = 0; i < _clips.Length; i++)
			{
				try
				{
					if ((Object)(object)_clips[i] != (Object)null)
					{
						Object.Destroy((Object)(object)_clips[i]);
					}
				}
				catch
				{
				}
			}
			_clips = null;
			_last = -1;
		}

		private static byte[] ReadResource()
		{
			try
			{
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BehindYou.footsteps.wav");
				if (stream == null)
				{
					Melon<BehindYouMod>.Logger.Error("Embedded resource 'BehindYou.footsteps.wav' is missing.");
					return null;
				}
				byte[] array = new byte[stream.Length];
				int i;
				int num;
				for (i = 0; i < array.Length; i += num)
				{
					num = stream.Read(array, i, array.Length - i);
					if (num <= 0)
					{
						break;
					}
				}
				return (i == array.Length) ? array : null;
			}
			catch (Exception ex)
			{
				Melon<BehindYouMod>.Logger.Error("Reading embedded audio failed: " + ex);
				return null;
			}
		}

		private static bool Decode(byte[] bytes, out float[] samples, out int channels, out int rate)
		{
			samples = null;
			channels = 1;
			rate = 48000;
			if (bytes.Length < 44)
			{
				return false;
			}
			if (Tag(bytes, 0) != "RIFF" || Tag(bytes, 8) != "WAVE")
			{
				return false;
			}
			int num = 0;
			int num2 = 0;
			int num3 = -1;
			int num4 = 0;
			int num5 = 12;
			while (num5 + 8 <= bytes.Length)
			{
				string text = Tag(bytes, num5);
				int num6 = BitConverter.ToInt32(bytes, num5 + 4);
				if (num6 < 0 || num5 + 8 + num6 > bytes.Length)
				{
					num6 = bytes.Length - num5 - 8;
				}
				int num7 = num5 + 8;
				if (text == "fmt " && num6 >= 16)
				{
					num = BitConverter.ToInt16(bytes, num7);
					channels = Math.Max(1, (int)BitConverter.ToInt16(bytes, num7 + 2));
					rate = BitConverter.ToInt32(bytes, num7 + 4);
					num2 = BitConverter.ToInt16(bytes, num7 + 14);
				}
				else if (text == "data")
				{
					num3 = num7;
					num4 = num6;
				}
				num5 = num7 + num6 + (num6 & 1);
			}
			if (num3 < 0 || rate <= 0)
			{
				return false;
			}
			if (num == 1 && num2 == 16)
			{
				int num8 = num4 / 2;
				samples = new float[num8];
				for (int i = 0; i < num8; i++)
				{
					samples[i] = (float)BitConverter.ToInt16(bytes, num3 + i * 2) / 32768f;
				}
				return true;
			}
			if (num == 3 && num2 == 32)
			{
				int num9 = num4 / 4;
				samples = new float[num9];
				for (int j = 0; j < num9; j++)
				{
					samples[j] = BitConverter.ToSingle(bytes, num3 + j * 4);
				}
				return true;
			}
			return false;
		}

		private static float[] Downmix(float[] source, int channels)
		{
			int num = source.Length / channels;
			float[] array = new float[num];
			for (int i = 0; i < num; i++)
			{
				float num2 = 0f;
				for (int j = 0; j < channels; j++)
				{
					num2 += source[i * channels + j];
				}
				array[i] = num2 / (float)channels;
			}
			return array;
		}

		private static string Tag(byte[] bytes, int offset)
		{
			if (offset + 4 > bytes.Length)
			{
				return string.Empty;
			}
			return new string(new char[4]
			{
				(char)bytes[offset],
				(char)bytes[offset + 1],
				(char)bytes[offset + 2],
				(char)bytes[offset + 3]
			});
		}
	}
	internal static class StepEmitter
	{
		private const float NearDistance = 1.6f;

		private const float FarDistance = 14f;

		private const float NearCutoff = 22000f;

		private const float FarCutoff = 1150f;

		private static GameObject _root;

		private static AudioSource _source;

		private static AudioLowPassFilter _lowPass;

		public static bool Exists
		{
			get
			{
				if ((Object)(object)_root != (Object)null)
				{
					return (Object)(object)_source != (Object)null;
				}
				return false;
			}
		}

		public static Vector3 Position
		{
			get
			{
				//IL_001d: 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)
				if (!((Object)(object)_root != (Object)null))
				{
					return Vector3.zero;
				}
				return _root.transform.position;
			}
		}

		public static bool Ensure()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (Exists)
			{
				return true;
			}
			Destroy();
			try
			{
				_root = new GameObject("BehindYou.Steps");
				((Object)_root).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)_root);
				_source = _root.AddComponent<AudioSource>();
				_source.playOnAwake = false;
				_source.loop = false;
				_source.volume = 1f;
				_source.priority = 140;
				_source.spatialBlend = 1f;
				_source.dopplerLevel = 0f;
				_source.spread = 22f;
				_source.rolloffMode = (AudioRolloffMode)0;
				_source.minDistance = 1.4f;
				_source.maxDistance = 32f;
				_source.bypassReverbZones = false;
				RouteToFootstepsBus();
				if (Prefs.Spatialize)
				{
					try
					{
						_source.spatialize = true;
					}
					catch
					{
					}
				}
				_lowPass = _root.AddComponent<AudioLowPassFilter>();
				_lowPass.cutoffFrequency = 22000f;
				_lowPass.lowpassResonanceQ = 1f;
				return true;
			}
			catch (Exception ex)
			{
				Melon<BehindYouMod>.Logger.Error("Creating the footstep emitter failed: " + ex);
				Destroy();
				return false;
			}
		}

		public static void MoveTo(Vector3 position)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root != (Object)null)
			{
				_root.transform.position = position;
			}
		}

		public static void Play(AudioClip clip, float volume, float pitch, float distance)
		{
			if ((Object)(object)clip == (Object)null || !Exists)
			{
				return;
			}
			try
			{
				if ((Object)(object)_source.outputAudioMixerGroup == (Object)null)
				{
					RouteToFootstepsBus();
				}
				if ((Object)(object)_lowPass != (Object)null)
				{
					_lowPass.cutoffFrequency = CutoffFor(distance);
				}
				_source.pitch = Mathf.Clamp(pitch, 0.5f, 2f);
				_source.PlayOneShot(clip, Mathf.Clamp01(volume));
			}
			catch (Exception ex)
			{
				Melon<BehindYouMod>.Logger.Error("Playing a footstep failed: " + ex);
			}
		}

		public static void Silence()
		{
			if ((Object)(object)_source == (Object)null)
			{
				return;
			}
			try
			{
				_source.Stop();
			}
			catch
			{
			}
		}

		public static void Destroy()
		{
			try
			{
				if ((Object)(object)_root != (Object)null)
				{
					Object.Destroy((Object)(object)_root);
				}
			}
			catch
			{
			}
			_root = null;
			_source = null;
			_lowPass = null;
		}

		private static void RouteToFootstepsBus()
		{
			if ((Object)(object)_source == (Object)null)
			{
				return;
			}
			try
			{
				_source.outputAudioMixerGroup = Audio.Footsteps;
			}
			catch
			{
			}
		}

		private static float CutoffFor(float distance)
		{
			float num = Mathf.Clamp01(Mathf.InverseLerp(1.6f, 14f, distance));
			return 22000f * Mathf.Pow(0.052272726f, num);
		}
	}
}