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);
}
}
}