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.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.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)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)delegate(float value) { Prefs.Volume = value; Prefs.Save(); }); root.CreateFloat("Trigger Chance", Accent, Prefs.Chance, 5f, 0f, 100f, (Action)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)delegate(float value) { Prefs.MinDelay = value; Prefs.Save(); }); obj.CreateFloat("Max Delay", Accent, Prefs.MaxDelay, 10f, 5f, 3600f, (Action)delegate(float value) { Prefs.MaxDelay = value; Prefs.Save(); }); obj.CreateFloat("Cooldown", Accent, Prefs.Cooldown, 5f, 0f, 600f, (Action)delegate(float value) { Prefs.Cooldown = value; Prefs.Save(); }); obj.CreateFloat("Level Warmup", Accent, Prefs.Warmup, 5f, 0f, 300f, (Action)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)delegate(float value) { Prefs.StartDistance = value; Prefs.Save(); }); obj.CreateBool("Stop When You Look", Accent, Prefs.StopWhenLookedAt, (Action)delegate(bool value) { Prefs.StopWhenLookedAt = value; Prefs.Save(); }); obj.CreateBool("Keep In Room", Accent, Prefs.KeepInRoom, (Action)delegate(bool value) { Prefs.KeepInRoom = value; Prefs.Save(); }); obj.CreateBool("HRTF Spatializer", Accent, Prefs.Spatialize, (Action)delegate(bool value) { Prefs.Spatialize = value; Prefs.Save(); StepEmitter.Destroy(); }); obj.CreateBool("Log Events", Accent, Prefs.LogEvents, (Action)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)delegate(bool value) { Prefs.ModeApproach = value; Prefs.Save(); }); obj.CreateBool("Pass By", Accent, Prefs.ModePassBy, (Action)delegate(bool value) { Prefs.ModePassBy = value; Prefs.Save(); }); obj.CreateBool("Follow", Accent, Prefs.ModeFollow, (Action)delegate(bool value) { Prefs.ModeFollow = value; Prefs.Save(); }); obj.CreateBool("Single Step", Accent, Prefs.ModeSingle, (Action)delegate(bool value) { Prefs.ModeSingle = value; Prefs.Save(); }); obj.CreateBool("Retreat", Accent, Prefs.ModeRetreat, (Action)delegate(bool value) { Prefs.ModeRetreat = value; Prefs.Save(); }); obj.CreateBool("Circle", Accent, Prefs.ModeCircle, (Action)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.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.Logger.Warning("Footstep audio is not loaded yet."); return false; } Transform head = Player.Head; if ((Object)(object)head == (Object)null) { Melon.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.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.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.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 _enabled; private static MelonPreferences_Entry _volume; private static MelonPreferences_Entry _chance; private static MelonPreferences_Entry _minDelay; private static MelonPreferences_Entry _maxDelay; private static MelonPreferences_Entry _cooldown; private static MelonPreferences_Entry _warmup; private static MelonPreferences_Entry _startDistance; private static MelonPreferences_Entry _stopWhenLookedAt; private static MelonPreferences_Entry _keepInRoom; private static MelonPreferences_Entry _spatialize; private static MelonPreferences_Entry _logEvents; private static MelonPreferences_Entry _testKey; private static MelonPreferences_Entry _modeApproach; private static MelonPreferences_Entry _modePassBy; private static MelonPreferences_Entry _modeFollow; private static MelonPreferences_Entry _modeSingle; private static MelonPreferences_Entry _modeRetreat; private static MelonPreferences_Entry _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 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("Enabled", true, "Enabled", (string)null, false, false, (ValueValidator)null, (string)null); _volume = _category.CreateEntry("Volume", 0.75f, "Volume", (string)null, false, false, (ValueValidator)null, (string)null); _chance = _category.CreateEntry("Chance", 50f, "Trigger Chance (%)", (string)null, false, false, (ValueValidator)null, (string)null); _minDelay = _category.CreateEntry("MinDelay", 90f, "Min Delay (s)", (string)null, false, false, (ValueValidator)null, (string)null); _maxDelay = _category.CreateEntry("MaxDelay", 300f, "Max Delay (s)", (string)null, false, false, (ValueValidator)null, (string)null); _cooldown = _category.CreateEntry("Cooldown", 45f, "Cooldown (s)", (string)null, false, false, (ValueValidator)null, (string)null); _warmup = _category.CreateEntry("Warmup", 20f, "Level Warmup (s)", (string)null, false, false, (ValueValidator)null, (string)null); _startDistance = _category.CreateEntry("StartDistance", 9f, "Start Distance (m)", (string)null, false, false, (ValueValidator)null, (string)null); _stopWhenLookedAt = _category.CreateEntry("StopWhenLookedAt", true, "Stop When You Look", (string)null, false, false, (ValueValidator)null, (string)null); _keepInRoom = _category.CreateEntry("KeepInRoom", true, "Keep In Room", (string)null, false, false, (ValueValidator)null, (string)null); _spatialize = _category.CreateEntry("Spatialize", true, "Use HRTF Spatializer", (string)null, false, false, (ValueValidator)null, (string)null); _logEvents = _category.CreateEntry("LogEvents", true, "Log Events", (string)null, false, false, (ValueValidator)null, (string)null); _testKey = _category.CreateEntry("TestKey", 290, "Test Key", (string)null, false, false, (ValueValidator)null, (string)null); _modeApproach = _category.CreateEntry("ModeApproach", true, "Mode: Approach", (string)null, false, false, (ValueValidator)null, (string)null); _modePassBy = _category.CreateEntry("ModePassBy", true, "Mode: Pass By", (string)null, false, false, (ValueValidator)null, (string)null); _modeFollow = _category.CreateEntry("ModeFollow", true, "Mode: Follow", (string)null, false, false, (ValueValidator)null, (string)null); _modeSingle = _category.CreateEntry("ModeSingle", true, "Mode: Single Step", (string)null, false, false, (ValueValidator)null, (string)null); _modeRetreat = _category.CreateEntry("ModeRetreat", true, "Mode: Retreat", (string)null, false, false, (ValueValidator)null, (string)null); _modeCircle = _category.CreateEntry("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.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.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.Logger.Error("AudioClip.Create returned null."); return; } Il2CppStructArray val2 = new Il2CppStructArray((long)num); int num2 = i * num; for (int j = 0; j < num; j++) { ((Il2CppArrayBase)(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.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.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.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(); _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(); _lowPass.cutoffFrequency = 22000f; _lowPass.lowpassResonanceQ = 1f; return true; } catch (Exception ex) { Melon.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.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); } } }