Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PersonalHelper v0.3.0
BepInEx\plugins\PersonalHelper\PersonalHelper.dll
Decompiled 7 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; using UnityEngine.Video; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PersonalHelper")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.3.0.0")] [assembly: AssemblyInformationalVersion("0.3.0")] [assembly: AssemblyProduct("PersonalHelper")] [assembly: AssemblyTitle("PersonalHelper")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.0.0")] [module: UnverifiableCode] [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 PersonalHelper { public class PersonalHelperAdmin : MonoBehaviour { public static string Feedback = string.Empty; private static bool _open; private Rect _window = new Rect(40f, 40f, 420f, 560f); private Vector2 _scroll; private int _targetIndex = -1; private string _lockdownSeconds = "120"; private string _videoSeconds = "11"; public static PersonalHelperAdmin Instance { get; private set; } public static void Toggle() { //IL_0012: 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_001d: Expected O, but got Unknown if ((Object)(object)Instance == (Object)null) { GameObject val = new GameObject("PersonalHelperAdmin"); Object.DontDestroyOnLoad((Object)val); Instance = val.AddComponent<PersonalHelperAdmin>(); } if (!LocalIsAdmin()) { PersonalHelperPlugin.Verbose("Admin panel refused: SteamID not on the list."); return; } _open = !_open; Cursor.visible = _open; Cursor.lockState = (CursorLockMode)(!_open); } private static bool LocalIsAdmin() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null) { return PersonalHelperPlugin.IsAdminSteamId(val.playerSteamId); } return false; } private void OnGUI() { //IL_000f: 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) //IL_002a: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (_open) { _window = GUI.Window(22085, _window, new WindowFunction(DrawWindow), "PersonalHelper // admin"); } } private void DrawWindow(int id) { //IL_0017: 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_0350: Unknown result type (might be due to invalid IL or missing references) List<PlayerControllerB> list = LivingPlayers(); GUILayout.Label("Target", Array.Empty<GUILayoutOption>()); _scroll = GUILayout.BeginScrollView(_scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(150f) }); if (GUILayout.Toggle(_targetIndex == -1, " Everyone", Array.Empty<GUILayoutOption>())) { _targetIndex = -1; } for (int i = 0; i < list.Count; i++) { PlayerControllerB val = list[i]; string text = (val.isInsideFactory ? "inside" : "outside"); if (GUILayout.Toggle(_targetIndex == i, " " + val.playerUsername + " (" + text + ")", Array.Empty<GUILayoutOption>())) { _targetIndex = i; } } GUILayout.EndScrollView(); GUILayout.Space(8f); GUILayout.Label("Events", Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Distant sound", Array.Empty<GUILayoutOption>())) { Fire(PersonalHelperEvent.DistantSound, list); } if (GUILayout.Button("Vigil (music + 1:30)", Array.Empty<GUILayoutOption>())) { Fire(PersonalHelperEvent.VigilStart, list); } if (GUILayout.Button("Jumpscare (image + death)", Array.Empty<GUILayoutOption>())) { Fire(PersonalHelperEvent.Jumpscare, list); } if (GUILayout.Button("Random flash", Array.Empty<GUILayoutOption>())) { Fire(PersonalHelperEvent.Flash, list); } if (GUILayout.Button("Spawn stalker behind them", Array.Empty<GUILayoutOption>())) { Fire(PersonalHelperEvent.Stalker, list); } GUILayout.Space(8f); GUILayout.Label("Video", Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Seconds", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }); _videoSeconds = GUILayout.TextField(_videoSeconds, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }); GUILayout.EndHorizontal(); if (GUILayout.Button("PLAY VIDEO", Array.Empty<GUILayoutOption>())) { float.TryParse(_videoSeconds, out var result); FireWithDuration(PersonalHelperEvent.PlayVideo, list, result); } GUILayout.Space(8f); GUILayout.Label("Lockdown", Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Seconds", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }); _lockdownSeconds = GUILayout.TextField(_lockdownSeconds, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }); GUILayout.EndHorizontal(); if (GUILayout.Button((GUI.enabled = PersonalHelperNetHandler.AllLivingPlayersInside()) ? "START LOCKDOWN" : "start lockdown (not everyone inside)", Array.Empty<GUILayoutOption>())) { float.TryParse(_lockdownSeconds, out var result2); PersonalHelperRuntime.Instance?.Request(PersonalHelperEvent.LockdownStart, everyone: true, 0uL, result2); } GUI.enabled = true; if (GUILayout.Button("Lift lockdown", Array.Empty<GUILayoutOption>())) { PersonalHelperRuntime.Instance?.Request(PersonalHelperEvent.LockdownStop, everyone: true, 0uL); } GUILayout.Space(8f); if (GUILayout.Button("Reset round state", Array.Empty<GUILayoutOption>())) { PersonalHelperRuntime.Instance?.Request(PersonalHelperEvent.ResetRound, everyone: true, 0uL); } if (!string.IsNullOrEmpty(Feedback)) { GUILayout.Space(6f); GUILayout.Label(Feedback, Array.Empty<GUILayoutOption>()); } GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f)); } private void Fire(PersonalHelperEvent phEvent, List<PlayerControllerB> players) { FireWithDuration(phEvent, players, 0f); } private void FireWithDuration(PersonalHelperEvent phEvent, List<PlayerControllerB> players, float duration) { Feedback = string.Empty; if (_targetIndex == -1) { PersonalHelperRuntime.Instance?.Request(phEvent, everyone: true, 0uL, duration); } else if (_targetIndex >= 0 && _targetIndex < players.Count) { PersonalHelperRuntime.Instance?.Request(phEvent, everyone: false, players[_targetIndex].actualClientId, duration); } } private static List<PlayerControllerB> LivingPlayers() { List<PlayerControllerB> list = new List<PlayerControllerB>(); if ((Object)(object)StartOfRound.Instance == (Object)null) { return list; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if ((Object)(object)val != (Object)null && val.isPlayerControlled) { list.Add(val); } } return list; } } public static class PersonalHelperAssets { public const string SoundsDistant = "sounds/distant"; public const string SoundsMusic = "sounds/music"; public const string SoundsStingers = "sounds/stingers"; public const string SoundsMeme = "sounds/meme"; public const string ImagesJumpscare = "images/jumpscare"; public const string ImagesFlash = "images/flash"; public const string ImagesMeme = "images/meme"; public const string ImagesLockdown = "images/lockdown"; public const string Videos = "videos"; private static readonly string[] AudioExtensions = new string[3] { ".ogg", ".wav", ".mp3" }; private static readonly string[] ImageExtensions = new string[3] { ".png", ".jpg", ".jpeg" }; private static readonly string[] VideoExtensions = new string[4] { ".mp4", ".webm", ".m4v", ".mov" }; private static readonly Dictionary<string, AudioClip> ClipCache = new Dictionary<string, AudioClip>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Texture2D> TextureCache = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase); private static string _root; private static readonly Random Rng = new Random(); public static void Init(string root) { _root = root; string[] array = new string[9] { "sounds/distant", "sounds/music", "sounds/stingers", "sounds/meme", "images/jumpscare", "images/flash", "images/meme", "images/lockdown", "videos" }; foreach (string text in array) { Directory.CreateDirectory(Path.Combine(_root, text.Replace('/', Path.DirectorySeparatorChar))); } } private static string[] FilesIn(string folder, string[] extensions) { string path = Path.Combine(_root, folder.Replace('/', Path.DirectorySeparatorChar)); if (!Directory.Exists(path)) { return Array.Empty<string>(); } return (from f in Directory.GetFiles(path) where extensions.Contains<string>(Path.GetExtension(f), StringComparer.OrdinalIgnoreCase) select f).OrderBy<string, string>((string f) => f, StringComparer.OrdinalIgnoreCase).ToArray(); } public static int CountAudio(string folder) { return FilesIn(folder, AudioExtensions).Length; } public static int CountImages(string folder) { return FilesIn(folder, ImageExtensions).Length; } public static int CountVideos() { return FilesIn("videos", VideoExtensions).Length; } public static string PickAudioPath(string folder, int seed = -1) { string[] array = FilesIn(folder, AudioExtensions); if (array.Length == 0) { return null; } int num = ((seed < 0) ? Rng.Next(array.Length) : (Mathf.Abs(seed) % array.Length)); return array[num]; } public static string PickImagePath(string folder, int seed = -1) { string[] array = FilesIn(folder, ImageExtensions); if (array.Length == 0) { return null; } int num = ((seed < 0) ? Rng.Next(array.Length) : (Mathf.Abs(seed) % array.Length)); return array[num]; } public static string PickVideoPath(int seed = -1) { string[] array = FilesIn("videos", VideoExtensions); if (array.Length == 0) { return null; } int num = ((seed < 0) ? Rng.Next(array.Length) : (Mathf.Abs(seed) % array.Length)); return array[num]; } public static Texture2D LoadTexture(string folder, int seed = -1) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown string text = PickImagePath(folder, seed); if (text == null) { PersonalHelperPlugin.Verbose("No images in " + folder + ", skipping."); return null; } if (TextureCache.TryGetValue(text, out var value) && (Object)(object)value != (Object)null) { return value; } try { Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ImageConversion.LoadImage(val, File.ReadAllBytes(text)); ((Object)val).name = Path.GetFileName(text); ((Texture)val).wrapMode = (TextureWrapMode)1; TextureCache[text] = val; return val; } catch (Exception ex) { PersonalHelperPlugin.Log.LogWarning((object)("Could not read image " + text + ": " + ex.Message)); return null; } } public static void LoadClip(MonoBehaviour host, string folder, int seed, Action<AudioClip> onLoaded) { string text = PickAudioPath(folder, seed); AudioClip value; if (text == null) { PersonalHelperPlugin.Verbose("No audio in " + folder + ", skipping."); onLoaded?.Invoke(null); } else if (ClipCache.TryGetValue(text, out value) && (Object)(object)value != (Object)null) { onLoaded?.Invoke(value); } else { host.StartCoroutine(LoadClipRoutine(text, onLoaded)); } } private static IEnumerator LoadClipRoutine(string path, Action<AudioClip> onLoaded) { AudioType val = (AudioType)(Path.GetExtension(path).ToLowerInvariant() switch { ".ogg" => 14, ".wav" => 20, ".mp3" => 13, _ => 0, }); string absoluteUri = new Uri(path).AbsoluteUri; UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(absoluteUri, val); try { yield return request.SendWebRequest(); if ((int)request.result != 1) { PersonalHelperPlugin.Log.LogWarning((object)("Could not read audio " + path + ": " + request.error)); onLoaded?.Invoke(null); yield break; } AudioClip content = DownloadHandlerAudioClip.GetContent(request); if ((Object)(object)content == (Object)null) { onLoaded?.Invoke(null); yield break; } ((Object)content).name = Path.GetFileName(path); ClipCache[path] = content; onLoaded?.Invoke(content); } finally { ((IDisposable)request)?.Dispose(); } } public static void LogInventory() { PersonalHelperPlugin.Log.LogInfo((object)(string.Format("Assets: distant={0} music={1} ", CountAudio("sounds/distant"), CountAudio("sounds/music")) + string.Format("stingers={0} meme_sfx={1} ", CountAudio("sounds/stingers"), CountAudio("sounds/meme")) + string.Format("jumpscare={0} flash={1} ", CountImages("images/jumpscare"), CountImages("images/flash")) + string.Format("meme_img={0} lockdown={1} ", CountImages("images/meme"), CountImages("images/lockdown")) + $"videos={CountVideos()}")); } } public static class PersonalHelperLockdown { public static bool Active; public static void HostBegin(float seconds) { Active = true; PersonalHelperPlugin.Log.LogInfo((object)$"Lockdown started for {seconds:F0}s."); } public static void HostEnd(bool timedOut) { if (Active) { Active = false; PersonalHelperPlugin.Log.LogInfo((object)(timedOut ? "Lockdown timed out." : "Lockdown lifted.")); } } [HarmonyPatch(typeof(EntranceTeleport), "TeleportPlayer")] [HarmonyPrefix] private static bool BlockMainEntrance(EntranceTeleport __instance) { if (!Active) { return true; } if ((!__instance.isEntranceToBuilding || __instance.entranceId != 0) && PersonalHelperPlugin.LockdownAllowFireExit.Value) { return true; } if ((Object)(object)GameNetworkManager.Instance?.localPlayerController != (Object)null) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("LOCKED", "The main entrance will not open. Find a fire exit.", true, false, "LC_Tip1"); } } return false; } [HarmonyPatch(typeof(EntranceTeleport), "TeleportPlayerClientRpc")] [HarmonyPrefix] private static bool BlockMainEntranceRpc(EntranceTeleport __instance) { return BlockMainEntrance(__instance); } } public enum PersonalHelperEvent { DistantSound, VigilStart, Jumpscare, Flash, Stalker, LockdownStart, LockdownStop, ResetRound, PlayVideo } public static class PersonalHelperNet { public static GameObject HandlerPrefab; public static void Init() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown HandlerPrefab = new GameObject("PersonalHelperNetHandler"); HandlerPrefab.AddComponent<NetworkObject>(); HandlerPrefab.AddComponent<PersonalHelperNetHandler>(); Object.DontDestroyOnLoad((Object)(object)HandlerPrefab); ((Object)HandlerPrefab).hideFlags = (HideFlags)61; } [HarmonyPatch(typeof(GameNetworkManager), "Start")] [HarmonyPostfix] private static void RegisterPrefab() { if (!((Object)(object)HandlerPrefab == (Object)null)) { NetworkManager.Singleton.AddNetworkPrefab(HandlerPrefab); PersonalHelperPlugin.Verbose("Network prefab registered."); } } [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] private static void SpawnHandler(StartOfRound __instance) { if ((((NetworkBehaviour)__instance).IsHost || ((NetworkBehaviour)__instance).IsServer) && !((Object)(object)PersonalHelperNetHandler.Instance != (Object)null)) { Object.Instantiate<GameObject>(HandlerPrefab).GetComponent<NetworkObject>().Spawn(false); PersonalHelperPlugin.Verbose("Network handler spawned."); } } } public class PersonalHelperNetHandler : NetworkBehaviour { private bool _event1Rolled; private bool _event1Fired; private bool _event2Rolled; private bool _event2Won; private bool _event2Fired; private float _insideSeconds; private float _flashRollTimer; public static PersonalHelperNetHandler Instance { get; private set; } public override void OnNetworkSpawn() { if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)Instance).gameObject); } Instance = this; ((NetworkBehaviour)this).OnNetworkSpawn(); PersonalHelperAssets.LogInventory(); } public override void OnNetworkDespawn() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } ((NetworkBehaviour)this).OnNetworkDespawn(); } private void Update() { if (!((NetworkBehaviour)this).IsServer || (Object)(object)StartOfRound.Instance == (Object)null || !StartOfRound.Instance.shipDoorsEnabled) { return; } bool flag = false; PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if ((Object)(object)val != (Object)null && val.isPlayerControlled && !val.isPlayerDead && val.isInsideFactory) { flag = true; break; } } if (!flag) { return; } _insideSeconds += Time.deltaTime; if (!_event2Rolled) { _event2Rolled = true; _event2Won = Random.Range(0, 100) < PersonalHelperPlugin.E2Chance.Value; PersonalHelperPlugin.Verbose("Vigil roll: " + (_event2Won ? "won" : "lost")); } if (_event2Won && !_event2Fired && _insideSeconds >= PersonalHelperPlugin.E2TriggerAfterSeconds.Value) { _event2Fired = true; BroadcastToAll(PersonalHelperEvent.VigilStart); } _flashRollTimer += Time.deltaTime; if (_flashRollTimer >= 60f) { _flashRollTimer -= 60f; if (Random.Range(0, 100) < PersonalHelperPlugin.FlashChancePerMinute.Value) { BroadcastToAll(PersonalHelperEvent.Flash); } } } [ServerRpc(RequireOwnership = false)] public void ReportEnteredFacilityServerRpc(ServerRpcParams rpcParams = default(ServerRpcParams)) { if (!_event1Rolled) { _event1Rolled = true; if (Random.Range(0, 100) >= PersonalHelperPlugin.E1Chance.Value) { PersonalHelperPlugin.Verbose("Distant sound roll: lost"); return; } _event1Fired = true; BroadcastToAll(PersonalHelperEvent.DistantSound); } } public void ResetRoundState() { _event1Rolled = (_event1Fired = false); _event2Rolled = (_event2Won = (_event2Fired = false)); _insideSeconds = 0f; _flashRollTimer = 0f; PersonalHelperPlugin.Verbose("Round state reset."); } [ServerRpc(RequireOwnership = false)] public void RequestEventServerRpc(int eventId, ulong targetClientId, bool everyone, float duration, ServerRpcParams rpcParams = default(ServerRpcParams)) { //IL_0000: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00c6: Unknown result type (might be due to invalid IL or missing references) ulong senderClientId = rpcParams.Receive.SenderClientId; if (!IsAuthorized(senderClientId)) { PersonalHelperPlugin.Log.LogWarning((object)$"Rejected admin request from client {senderClientId}: SteamID not on the list."); return; } int seed = Random.Range(int.MinValue, int.MaxValue); NetworkTime serverTime; switch (eventId) { case 5: { if (!AllLivingPlayersInside()) { SendAdminFeedbackClientRpc("Not everyone is inside the complex.", Target(senderClientId)); break; } PersonalHelperLockdown.HostBegin((duration <= 0f) ? PersonalHelperPlugin.LockdownDefaultSeconds.Value : duration); float duration2 = ((duration <= 0f) ? PersonalHelperPlugin.LockdownDefaultSeconds.Value : duration); serverTime = ((NetworkBehaviour)this).NetworkManager.ServerTime; PlayEventClientRpc(eventId, seed, duration2, ((NetworkTime)(ref serverTime)).TimeAsFloat); break; } case 6: PersonalHelperLockdown.HostEnd(timedOut: false); serverTime = ((NetworkBehaviour)this).NetworkManager.ServerTime; PlayEventClientRpc(eventId, seed, 0f, ((NetworkTime)(ref serverTime)).TimeAsFloat); break; case 7: ResetRoundState(); serverTime = ((NetworkBehaviour)this).NetworkManager.ServerTime; PlayEventClientRpc(eventId, seed, 0f, ((NetworkTime)(ref serverTime)).TimeAsFloat); break; default: if (everyone) { BroadcastToAll((PersonalHelperEvent)eventId, duration); break; } serverTime = ((NetworkBehaviour)this).NetworkManager.ServerTime; PlayEventClientRpc(eventId, seed, duration, ((NetworkTime)(ref serverTime)).TimeAsFloat, Target(targetClientId)); break; } } private bool IsAuthorized(ulong clientId) { return PersonalHelperPlugin.IsAdminSteamId(SteamIdOf(clientId)); } public static ulong SteamIdOf(ulong clientId) { if ((Object)(object)StartOfRound.Instance == (Object)null) { return 0uL; } int value; int num = (StartOfRound.Instance.ClientPlayerList.TryGetValue(clientId, out value) ? value : (-1)); if (num < 0 || num >= StartOfRound.Instance.allPlayerScripts.Length) { return 0uL; } return StartOfRound.Instance.allPlayerScripts[num].playerSteamId; } public static bool AllLivingPlayersInside() { if ((Object)(object)StartOfRound.Instance == (Object)null) { return false; } int num = 0; PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (!((Object)(object)val == (Object)null) && val.isPlayerControlled && !val.isPlayerDead) { num++; if (!val.isInsideFactory) { return false; } } } return num > 0; } private static ClientRpcParams Target(ulong clientId) { //IL_0002: 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_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_002b: Unknown result type (might be due to invalid IL or missing references) return new ClientRpcParams { Send = new ClientRpcSendParams { TargetClientIds = new List<ulong> { clientId } } }; } public void BroadcastToAll(PersonalHelperEvent phEvent, float duration = 0f) { //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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (((NetworkBehaviour)this).IsServer) { int seed = Random.Range(int.MinValue, int.MaxValue); NetworkTime serverTime = ((NetworkBehaviour)this).NetworkManager.ServerTime; PlayEventClientRpc((int)phEvent, seed, duration, ((NetworkTime)(ref serverTime)).TimeAsFloat); } } [ClientRpc] public void PlayEventClientRpc(int eventId, int seed, float duration, float serverStartTime, ClientRpcParams rpcParams = default(ClientRpcParams)) { PersonalHelperRuntime.Instance?.Handle((PersonalHelperEvent)eventId, seed, duration, serverStartTime); } [ClientRpc] public void SendAdminFeedbackClientRpc(string message, ClientRpcParams rpcParams = default(ClientRpcParams)) { PersonalHelperAdmin.Feedback = message; PersonalHelperPlugin.Log.LogInfo((object)("[admin] " + message)); } } public static class PersonalHelperPatches { [HarmonyPatch(typeof(StartOfRound), "Start")] [HarmonyPostfix] private static void AttachRuntime(StartOfRound __instance) { //IL_0012: 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_001d: Expected O, but got Unknown if ((Object)(object)PersonalHelperRuntime.Instance == (Object)null) { GameObject val = new GameObject("PersonalHelperRuntime"); Object.DontDestroyOnLoad((Object)val); val.AddComponent<PersonalHelperRuntime>(); } } [HarmonyPatch(typeof(StartOfRound), "StartGame")] [HarmonyPostfix] private static void OnRoundStart() { PersonalHelperRuntime.Instance?.ResetRound(); if ((Object)(object)PersonalHelperNetHandler.Instance != (Object)null && ((NetworkBehaviour)PersonalHelperNetHandler.Instance).IsServer) { PersonalHelperNetHandler.Instance.ResetRoundState(); } } [HarmonyPatch(typeof(StartOfRound), "ShipHasLeft")] [HarmonyPostfix] private static void OnShipLeft() { PersonalHelperRuntime.Instance?.ResetRound(); PersonalHelperLockdown.HostEnd(timedOut: false); } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPostfix] private static void OnPlayerKilled(PlayerControllerB __instance) { if ((Object)(object)__instance != (Object)null && ((NetworkBehaviour)__instance).IsOwner) { PersonalHelperRuntime.Instance?.StopEverything(); } } } [BepInPlugin("experimenter.personalhelper", "PersonalHelper", "0.3.0")] [BepInProcess("Lethal Company.exe")] public class PersonalHelperPlugin : BaseUnityPlugin { public const string GUID = "experimenter.personalhelper"; public const string NAME = "PersonalHelper"; public const string VERSION = "0.3.0"; public static ConfigEntry<int> E1Chance; public static ConfigEntry<float> E1MinDistance; public static ConfigEntry<float> E1MaxDistance; public static ConfigEntry<float> E1MaxAudibleDistance; public static ConfigEntry<int> E2Chance; public static ConfigEntry<float> E2TriggerAfterSeconds; public static ConfigEntry<float> E2BuildupSeconds; public static ConfigEntry<float> E2StartVolume; public static ConfigEntry<float> E2EndVolume; public static ConfigEntry<float> E2ImageSeconds; public static ConfigEntry<bool> E2KillPlayer; public static ConfigEntry<int> FlashChancePerMinute; public static ConfigEntry<float> FlashFrameSeconds; public static ConfigEntry<bool> StalkerEnabled; public static ConfigEntry<float> StalkerStraightWalkSeconds; public static ConfigEntry<float> StalkerYawTolerance; public static ConfigEntry<float> StalkerSpawnDistance; public static ConfigEntry<float> StalkerCooldownSeconds; public static ConfigEntry<int> StalkerMaxPerRound; public static ConfigEntry<float> StalkerMemeSeconds; public static ConfigEntry<float> StalkerFadeSeconds; public static ConfigEntry<bool> StalkerKillPlayer; public static ConfigEntry<float> VideoSeconds; public static ConfigEntry<float> VideoVolume; public static ConfigEntry<bool> VideoKillPlayer; public static ConfigEntry<float> LockdownDefaultSeconds; public static ConfigEntry<bool> LockdownKillOnTimeout; public static ConfigEntry<float> LockdownPulseSpeed; public static ConfigEntry<float> LockdownMinAlpha; public static ConfigEntry<float> LockdownMaxAlpha; public static ConfigEntry<bool> LockdownAllowFireExit; public static ConfigEntry<string> AdminSteamIDs; public static ConfigEntry<KeyCode> AdminPanelKey; public static ConfigEntry<bool> HotkeysEnabled; public static ConfigEntry<bool> VerboseLogging; private readonly Harmony _harmony = new Harmony("experimenter.personalhelper"); public static PersonalHelperPlugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } public static string AssetRoot { get; private set; } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; AssetRoot = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? ".", "Assets"); Directory.CreateDirectory(AssetRoot); BindConfig(); PersonalHelperAssets.Init(AssetRoot); PersonalHelperNet.Init(); _harmony.PatchAll(typeof(PersonalHelperPatches)); _harmony.PatchAll(typeof(PersonalHelperNet)); _harmony.PatchAll(typeof(PersonalHelperLockdown)); Log.LogInfo((object)"PersonalHelper 0.3.0 loaded. It knows everything."); Log.LogInfo((object)("Assets: " + AssetRoot)); } private void BindConfig() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Expected O, but got Unknown E1Chance = ((BaseUnityPlugin)this).Config.Bind<int>("Event1", "Chance", 85, new ConfigDescription("Chance of the distant sound event, in percent.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); E1MinDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Event1", "MinDistance", 22f, "Closest the sound can spawn, in meters."); E1MaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Event1", "MaxDistance", 40f, "Furthest the sound can spawn, in meters."); E1MaxAudibleDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Event1", "MaxAudibleDistance", 90f, "Falloff range of the sound, in meters."); E2Chance = ((BaseUnityPlugin)this).Config.Bind<int>("Event2", "Chance", 67, new ConfigDescription("Chance of the vigil event, in percent.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); E2TriggerAfterSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Event2", "TriggerAfterSeconds", 60f, "Seconds spent inside the facility before the music starts."); E2BuildupSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Event2", "BuildupSeconds", 90f, "Seconds of buildup before the payoff. 90 = 1:30."); E2StartVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Event2", "StartVolume", 0.05f, "Music volume at the start of the buildup."); E2EndVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Event2", "EndVolume", 1f, "Music volume at the end of the buildup."); E2ImageSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Event2", "ImageSeconds", 1.2f, "How long the full screen image stays."); E2KillPlayer = ((BaseUnityPlugin)this).Config.Bind<bool>("Event2", "KillPlayer", true, "Kill the player when the image appears."); FlashChancePerMinute = ((BaseUnityPlugin)this).Config.Bind<int>("RandomFlash", "ChancePerMinute", 4, new ConfigDescription("Chance per minute of a single frame flash while inside.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); FlashFrameSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("RandomFlash", "FrameSeconds", 0.05f, "How long a flash stays on screen. Keep it tiny."); StalkerEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Stalker", "Enabled", true, "Something spawns behind you when you walk straight for too long."); StalkerStraightWalkSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Stalker", "StraightWalkSeconds", 11f, "Seconds of walking forward without turning before it spawns."); StalkerYawTolerance = ((BaseUnityPlugin)this).Config.Bind<float>("Stalker", "YawTolerance", 35f, "Degrees per second of turning still counted as walking straight."); StalkerSpawnDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Stalker", "SpawnDistance", 7.5f, "How far behind you it spawns, in meters."); StalkerCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Stalker", "CooldownSeconds", 300f, "Cooldown between stalkers, in seconds."); StalkerMaxPerRound = ((BaseUnityPlugin)this).Config.Bind<int>("Stalker", "MaxPerRound", 2, "Maximum stalkers per round, per player."); StalkerMemeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Stalker", "MemeSeconds", 1f, "How long the payoff image stays at full opacity."); StalkerFadeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Stalker", "FadeSeconds", 1.5f, "Fade out time of the payoff image and sound."); StalkerKillPlayer = ((BaseUnityPlugin)this).Config.Bind<bool>("Stalker", "KillPlayer", false, "Lethal or not. False keeps it a joke, true keeps it a threat."); VideoSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Video", "Seconds", 11f, "How long the full screen video plays before it is cut off."); VideoVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Video", "Volume", 1f, "Volume of the video audio track."); VideoKillPlayer = ((BaseUnityPlugin)this).Config.Bind<bool>("Video", "KillPlayer", false, "Kill the player when the video ends."); LockdownDefaultSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Lockdown", "DefaultSeconds", 120f, "Default countdown length."); LockdownKillOnTimeout = ((BaseUnityPlugin)this).Config.Bind<bool>("Lockdown", "KillOnTimeout", true, "Kill whoever is still inside when the timer hits zero."); LockdownPulseSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Lockdown", "PulseSpeed", 1.4f, "Pulses per second of the full screen image."); LockdownMinAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("Lockdown", "MinAlpha", 0.25f, "Dimmest point of the pulse."); LockdownMaxAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("Lockdown", "MaxAlpha", 0.7f, "Brightest point of the pulse."); LockdownAllowFireExit = ((BaseUnityPlugin)this).Config.Bind<bool>("Lockdown", "AllowFireExit", true, "Fire exits keep working during a lockdown. Turning this off is cruel."); AdminSteamIDs = ((BaseUnityPlugin)this).Config.Bind<string>("Admin", "SteamIDs", "76561199058784388", "Comma separated SteamID64 list allowed to open the admin panel. Validated on the host, editing this locally does nothing."); AdminPanelKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Admin", "PanelKey", (KeyCode)287, "Key that toggles the admin panel."); HotkeysEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "HotkeysEnabled", true, "F7-F11 test hotkeys. Turn this off before playing seriously."); VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogging", false, "Spam the console with what the mod is thinking."); } public static bool IsAdminSteamId(ulong steamId) { if (steamId == 0L) { return false; } string text = AdminSteamIDs?.Value; if (string.IsNullOrWhiteSpace(text)) { return false; } ulong result; return (from s in text.Split(new char[3] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries) select s.Trim()).Any((string s) => ulong.TryParse(s, out result) && result == steamId); } public static void Verbose(string message) { if (VerboseLogging != null && VerboseLogging.Value) { Log.LogInfo((object)message); } } } public class PersonalHelperRuntime : MonoBehaviour { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ErrorEventHandler <>9__42_0; internal void <EnsureVideoPlayer>b__42_0(VideoPlayer source, string message) { PersonalHelperPlugin.Log.LogWarning((object)("Video error: " + message)); } } private Canvas _canvas; private RawImage _fullscreen; private RawImage _lockdownImage; private RawImage _videoImage; private Text _timerText; private AudioSource _music; private AudioSource _stinger; private AudioSource _distant; private VideoPlayer _videoPlayer; private AudioSource _videoAudio; private RenderTexture _videoTarget; private Coroutine _video; private PersonalHelperStalker _stalker; private bool _reportedEntrance; private Coroutine _vigil; private Coroutine _lockdown; public static PersonalHelperRuntime Instance { get; private set; } private static PlayerControllerB Local { get { if (!((Object)(object)GameNetworkManager.Instance != (Object)null)) { return null; } return GameNetworkManager.Instance.localPlayerController; } } public AudioSource StingerSource => _stinger; private void Awake() { Instance = this; BuildUi(); BuildAudio(); _stalker = ((Component)this).gameObject.AddComponent<PersonalHelperStalker>(); } private void BuildUi() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //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_013a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("PersonalHelperCanvas"); val.transform.SetParent(((Component)this).transform, false); _canvas = val.AddComponent<Canvas>(); _canvas.renderMode = (RenderMode)0; _canvas.sortingOrder = 30000; val.AddComponent<CanvasScaler>().uiScaleMode = (ScaleMode)1; _lockdownImage = CreateFullscreenImage("PersonalHelperLockdownImage"); _fullscreen = CreateFullscreenImage("PersonalHelperFullscreen"); _videoImage = CreateFullscreenImage("PersonalHelperVideo"); GameObject val2 = new GameObject("PersonalHelperTimer"); val2.transform.SetParent(val.transform, false); _timerText = val2.AddComponent<Text>(); _timerText.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); _timerText.fontSize = 64; _timerText.alignment = (TextAnchor)1; ((Graphic)_timerText).color = new Color(0.85f, 0.05f, 0.05f, 1f); _timerText.text = string.Empty; RectTransform rectTransform = ((Graphic)_timerText).rectTransform; rectTransform.anchorMin = new Vector2(0.5f, 1f); rectTransform.anchorMax = new Vector2(0.5f, 1f); rectTransform.pivot = new Vector2(0.5f, 1f); rectTransform.anchoredPosition = new Vector2(0f, -60f); rectTransform.sizeDelta = new Vector2(600f, 90f); } private RawImage CreateFullscreenImage(string name) { //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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(((Component)_canvas).transform, false); RawImage obj = val.AddComponent<RawImage>(); ((Graphic)obj).raycastTarget = false; ((Graphic)obj).color = new Color(1f, 1f, 1f, 0f); RectTransform rectTransform = ((Graphic)obj).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; return obj; } private void BuildAudio() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown _music = ((Component)this).gameObject.AddComponent<AudioSource>(); _music.spatialBlend = 0f; _music.loop = false; _music.playOnAwake = false; _stinger = ((Component)this).gameObject.AddComponent<AudioSource>(); _stinger.spatialBlend = 0f; _stinger.playOnAwake = false; GameObject val = new GameObject("PersonalHelperDistantSource"); val.transform.SetParent(((Component)this).transform, false); _distant = val.AddComponent<AudioSource>(); _distant.spatialBlend = 1f; _distant.rolloffMode = (AudioRolloffMode)1; _distant.minDistance = 5f; _distant.playOnAwake = false; _videoAudio = ((Component)this).gameObject.AddComponent<AudioSource>(); _videoAudio.spatialBlend = 0f; _videoAudio.playOnAwake = false; } private void Update() { TrackEntrance(); HandleHotkeys(); } private void TrackEntrance() { //IL_003b: 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) PlayerControllerB local = Local; if (!((Object)(object)local == (Object)null) && !_reportedEntrance && local.isInsideFactory && !local.isPlayerDead) { _reportedEntrance = true; PersonalHelperNetHandler.Instance?.ReportEnteredFacilityServerRpc(); } } private void HandleHotkeys() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (PersonalHelperPlugin.AdminPanelKey != null && Input.GetKeyDown(PersonalHelperPlugin.AdminPanelKey.Value)) { PersonalHelperAdmin.Toggle(); } if (PersonalHelperPlugin.HotkeysEnabled.Value) { if (Input.GetKeyDown((KeyCode)288)) { Request(PersonalHelperEvent.DistantSound, everyone: true, 0uL); } if (Input.GetKeyDown((KeyCode)289)) { Request(PersonalHelperEvent.VigilStart, everyone: true, 0uL); } if (Input.GetKeyDown((KeyCode)290)) { Handle(PersonalHelperEvent.Jumpscare, Random.Range(0, 9999), 0f, 0f); } if (Input.GetKeyDown((KeyCode)291)) { Handle(PersonalHelperEvent.Flash, Random.Range(0, 9999), 0f, 0f); } if (Input.GetKeyDown((KeyCode)292)) { ResetRound(); PersonalHelperNetHandler.Instance?.ResetRoundState(); } if (Input.GetKeyDown((KeyCode)293)) { Handle(PersonalHelperEvent.PlayVideo, Random.Range(0, 9999), 0f, 0f); } } } public void Request(PersonalHelperEvent phEvent, bool everyone, ulong target = 0uL, float duration = 0f) { //IL_004c: 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) PersonalHelperNetHandler instance = PersonalHelperNetHandler.Instance; if ((Object)(object)instance == (Object)null) { Handle(phEvent, Random.Range(0, 9999), duration, 0f); return; } if (((NetworkBehaviour)instance).IsServer && !everyone && target == 0L) { target = ((NetworkBehaviour)instance).NetworkManager.LocalClientId; } instance.RequestEventServerRpc((int)phEvent, target, everyone, duration); } public void Handle(PersonalHelperEvent phEvent, int seed, float duration, float serverStartTime) { switch (phEvent) { case PersonalHelperEvent.DistantSound: PlayDistantSound(seed); break; case PersonalHelperEvent.VigilStart: StartVigil(seed); break; case PersonalHelperEvent.Jumpscare: PlayJumpscare(seed, PersonalHelperPlugin.E2KillPlayer.Value); break; case PersonalHelperEvent.Flash: PlayFlash(seed); break; case PersonalHelperEvent.Stalker: _stalker?.ForceSpawn(seed); break; case PersonalHelperEvent.LockdownStart: StartLockdown(seed, duration, serverStartTime); break; case PersonalHelperEvent.LockdownStop: StopLockdown(); break; case PersonalHelperEvent.PlayVideo: PlayVideo(seed, duration); break; case PersonalHelperEvent.ResetRound: ResetRound(); break; } } private void PlayDistantSound(int seed) { PlayerControllerB player = Local; if ((Object)(object)player == (Object)null) { return; } PersonalHelperAssets.LoadClip((MonoBehaviour)(object)this, "sounds/distant", seed, delegate(AudioClip clip) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)clip == (Object)null)) { float num = Random.Range(0f, MathF.PI * 2f); float num2 = Random.Range(PersonalHelperPlugin.E1MinDistance.Value, PersonalHelperPlugin.E1MaxDistance.Value); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Cos(num) * num2, Random.Range(-2f, 4f), Mathf.Sin(num) * num2); ((Component)_distant).transform.position = ((Component)player).transform.position + val; _distant.maxDistance = PersonalHelperPlugin.E1MaxAudibleDistance.Value; _distant.clip = clip; _distant.volume = 1f; _distant.Play(); PersonalHelperPlugin.Verbose($"Distant sound at {num2:F1} m, {((Object)clip).name}"); } }); } private void StartVigil(int seed) { if (_vigil == null) { _vigil = ((MonoBehaviour)this).StartCoroutine(VigilRoutine(seed)); } } private IEnumerator VigilRoutine(int seed) { AudioClip music = null; bool loading = true; PersonalHelperAssets.LoadClip((MonoBehaviour)(object)this, "sounds/music", seed, delegate(AudioClip clip) { music = clip; loading = false; }); while (loading) { yield return null; } float buildup = Mathf.Max(1f, PersonalHelperPlugin.E2BuildupSeconds.Value); float startVolume = PersonalHelperPlugin.E2StartVolume.Value; float endVolume = PersonalHelperPlugin.E2EndVolume.Value; if ((Object)(object)music != (Object)null) { _music.clip = music; _music.volume = startVolume; _music.Play(); } float elapsed = 0f; while (elapsed < buildup) { elapsed += Time.deltaTime; if ((Object)(object)music != (Object)null) { _music.volume = Mathf.Lerp(startVolume, endVolume, elapsed / buildup); } yield return null; } PlayJumpscare(seed, PersonalHelperPlugin.E2KillPlayer.Value); _music.Stop(); _vigil = null; } public void PlayJumpscare(int seed, bool kill) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) Texture2D val = PersonalHelperAssets.LoadTexture("images/jumpscare", seed); PersonalHelperAssets.LoadClip((MonoBehaviour)(object)this, "sounds/stingers", seed, delegate(AudioClip clip) { if ((Object)(object)clip != (Object)null) { _stinger.PlayOneShot(clip, 1f); } }); if ((Object)(object)val != (Object)null) { ((MonoBehaviour)this).StartCoroutine(ShowFullscreen(val, PersonalHelperPlugin.E2ImageSeconds.Value, 0f)); } _music.Stop(); if (kill) { PlayerControllerB local = Local; if ((Object)(object)local != (Object)null && !local.isPlayerDead) { local.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 0, default(Vector3), false); } } } private void PlayFlash(int seed) { Texture2D val = PersonalHelperAssets.LoadTexture("images/flash", seed); if (!((Object)(object)val == (Object)null)) { ((MonoBehaviour)this).StartCoroutine(ShowFullscreen(val, PersonalHelperPlugin.FlashFrameSeconds.Value, 0f)); } } public IEnumerator ShowFullscreen(Texture2D texture, float hold, float fade) { _fullscreen.texture = (Texture)(object)texture; ((Graphic)_fullscreen).color = Color.white; yield return (object)new WaitForSeconds(Mathf.Max(0f, hold)); if (fade > 0f) { float elapsed = 0f; while (elapsed < fade) { elapsed += Time.deltaTime; ((Graphic)_fullscreen).color = new Color(1f, 1f, 1f, 1f - elapsed / fade); yield return null; } } ((Graphic)_fullscreen).color = new Color(1f, 1f, 1f, 0f); _fullscreen.texture = null; } public void PlayOneShot2D(AudioClip clip, float volume = 1f) { if ((Object)(object)clip != (Object)null) { _stinger.PlayOneShot(clip, volume); } } private void PlayVideo(int seed, float duration) { string text = PersonalHelperAssets.PickVideoPath(seed); if (text == null) { PersonalHelperPlugin.Verbose("No videos in Assets/videos, skipping."); return; } if (_video != null) { StopVideo(); } _video = ((MonoBehaviour)this).StartCoroutine(VideoRoutine(text, (duration <= 0f) ? PersonalHelperPlugin.VideoSeconds.Value : duration)); } private IEnumerator VideoRoutine(string path, float seconds) { EnsureVideoPlayer(); _videoPlayer.url = new Uri(path).AbsoluteUri; _videoPlayer.isLooping = false; _videoAudio.volume = PersonalHelperPlugin.VideoVolume.Value; _videoPlayer.Prepare(); float timeout = 8f; while (!_videoPlayer.isPrepared && timeout > 0f) { timeout -= Time.deltaTime; yield return null; } if (!_videoPlayer.isPrepared) { PersonalHelperPlugin.Log.LogWarning((object)("Video never got ready: " + path)); StopVideo(); yield break; } _videoImage.texture = (Texture)(object)_videoTarget; ((Graphic)_videoImage).color = Color.white; _videoPlayer.Play(); PersonalHelperPlugin.Verbose($"Video playing for {seconds:F1}s: {path}"); float elapsed = 0f; while (elapsed < seconds && _videoPlayer.isPlaying) { elapsed += Time.deltaTime; yield return null; } StopVideo(); if (PersonalHelperPlugin.VideoKillPlayer.Value) { PlayerControllerB local = Local; if ((Object)(object)local != (Object)null && !local.isPlayerDead) { local.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 0, default(Vector3), false); } } } private void EnsureVideoPlayer() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Expected O, but got Unknown if ((Object)(object)_videoTarget == (Object)null || ((Texture)_videoTarget).width != Screen.width || ((Texture)_videoTarget).height != Screen.height) { if ((Object)(object)_videoTarget != (Object)null) { _videoTarget.Release(); } _videoTarget = new RenderTexture(Mathf.Max(2, Screen.width), Mathf.Max(2, Screen.height), 0); _videoTarget.Create(); if ((Object)(object)_videoPlayer != (Object)null) { _videoPlayer.targetTexture = _videoTarget; } } if ((Object)(object)_videoPlayer != (Object)null) { return; } _videoPlayer = ((Component)this).gameObject.AddComponent<VideoPlayer>(); _videoPlayer.playOnAwake = false; _videoPlayer.isLooping = false; _videoPlayer.source = (VideoSource)1; _videoPlayer.renderMode = (VideoRenderMode)2; _videoPlayer.targetTexture = _videoTarget; _videoPlayer.audioOutputMode = (VideoAudioOutputMode)1; _videoPlayer.SetTargetAudioSource((ushort)0, _videoAudio); VideoPlayer videoPlayer = _videoPlayer; object obj = <>c.<>9__42_0; if (obj == null) { ErrorEventHandler val = delegate(VideoPlayer source, string message) { PersonalHelperPlugin.Log.LogWarning((object)("Video error: " + message)); }; <>c.<>9__42_0 = val; obj = (object)val; } videoPlayer.errorReceived += (ErrorEventHandler)obj; } public void StopVideo() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (_video != null) { ((MonoBehaviour)this).StopCoroutine(_video); _video = null; } if ((Object)(object)_videoPlayer != (Object)null) { _videoPlayer.Stop(); } _videoAudio.Stop(); ((Graphic)_videoImage).color = new Color(1f, 1f, 1f, 0f); _videoImage.texture = null; } private void StartLockdown(int seed, float duration, float serverStartTime) { if (_lockdown != null) { StopLockdown(); } _lockdown = ((MonoBehaviour)this).StartCoroutine(LockdownRoutine(seed, (duration <= 0f) ? PersonalHelperPlugin.LockdownDefaultSeconds.Value : duration, serverStartTime)); } private IEnumerator LockdownRoutine(int seed, float duration, float serverStartTime) { PersonalHelperLockdown.Active = true; Texture2D texture = PersonalHelperAssets.LoadTexture("images/lockdown", seed); if ((Object)(object)texture != (Object)null) { _lockdownImage.texture = (Texture)(object)texture; ((Graphic)_lockdownImage).color = new Color(1f, 1f, 1f, PersonalHelperPlugin.LockdownMinAlpha.Value); } PersonalHelperAssets.LoadClip((MonoBehaviour)(object)this, "sounds/music", seed, delegate(AudioClip clip) { if (!((Object)(object)clip == (Object)null)) { _music.clip = clip; _music.volume = 0.8f; _music.Play(); } }); while (PersonalHelperLockdown.Active) { float num; if (!((Object)(object)PersonalHelperNetHandler.Instance != (Object)null)) { num = serverStartTime + Time.timeSinceLevelLoad; } else { NetworkTime serverTime = ((NetworkBehaviour)PersonalHelperNetHandler.Instance).NetworkManager.ServerTime; num = ((NetworkTime)(ref serverTime)).TimeAsFloat; } float num2 = num; float num3 = duration - (num2 - serverStartTime); if (num3 <= 0f) { break; } _timerText.text = $"{Mathf.FloorToInt(num3 / 60f):0}:{Mathf.FloorToInt(num3 % 60f):00}"; if ((Object)(object)texture != (Object)null) { float num4 = (Mathf.Sin(Time.time * MathF.PI * 2f * PersonalHelperPlugin.LockdownPulseSpeed.Value) + 1f) * 0.5f; float num5 = Mathf.Lerp(PersonalHelperPlugin.LockdownMinAlpha.Value, PersonalHelperPlugin.LockdownMaxAlpha.Value, num4); ((Graphic)_lockdownImage).color = new Color(1f, 1f, 1f, num5); } yield return null; } PlayerControllerB local = Local; bool flag = (Object)(object)local != (Object)null && local.isInsideFactory && !local.isPlayerDead; StopLockdown(); if (PersonalHelperPlugin.LockdownKillOnTimeout.Value && flag) { PlayJumpscare(seed, kill: true); } } public void StopLockdown() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) PersonalHelperLockdown.Active = false; if (_lockdown != null) { ((MonoBehaviour)this).StopCoroutine(_lockdown); _lockdown = null; } _timerText.text = string.Empty; ((Graphic)_lockdownImage).color = new Color(1f, 1f, 1f, 0f); _lockdownImage.texture = null; _music.Stop(); } public void StopEverything() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (_vigil != null) { ((MonoBehaviour)this).StopCoroutine(_vigil); _vigil = null; } StopVideo(); _music.Stop(); ((Graphic)_fullscreen).color = new Color(1f, 1f, 1f, 0f); } public void ResetRound() { StopEverything(); StopLockdown(); _reportedEntrance = false; _stalker?.ResetRound(); PersonalHelperPlugin.Verbose("Local round state reset."); } } public class PersonalHelperStalker : MonoBehaviour { private float _straightTime; private float _cooldown; private int _spawnedThisRound; private float _lastYaw; private GameObject _entity; private Renderer _entityRenderer; private bool _armed; private int _seed; private static PlayerControllerB Local { get { if (!((Object)(object)GameNetworkManager.Instance != (Object)null)) { return null; } return GameNetworkManager.Instance.localPlayerController; } } private void Update() { if (!PersonalHelperPlugin.StalkerEnabled.Value) { return; } PlayerControllerB local = Local; if ((Object)(object)local == (Object)null || local.isPlayerDead) { Despawn(); return; } if (_cooldown > 0f) { _cooldown -= Time.deltaTime; } if (_armed) { CheckSeen(local); } else { TrackStraightWalk(local); } } private void TrackStraightWalk(PlayerControllerB player) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) float y = ((Component)player).transform.eulerAngles.y; float num = Mathf.Abs(Mathf.DeltaAngle(_lastYaw, y)) / Mathf.Max(Time.deltaTime, 0.0001f); _lastYaw = y; bool flag = ((Vector2)(ref player.moveInputVector)).sqrMagnitude > 0.1f; bool flag2 = player.moveInputVector.y > 0.4f; bool flag3 = num > PersonalHelperPlugin.StalkerYawTolerance.Value; if (!player.isInsideFactory || !flag || !flag2 || flag3) { _straightTime = 0f; return; } _straightTime += Time.deltaTime; if (!(_straightTime < PersonalHelperPlugin.StalkerStraightWalkSeconds.Value) && !(_cooldown > 0f) && _spawnedThisRound < PersonalHelperPlugin.StalkerMaxPerRound.Value) { Spawn(Random.Range(int.MinValue, int.MaxValue), player); } } public void ForceSpawn(int seed) { PlayerControllerB local = Local; if (!((Object)(object)local == (Object)null)) { Spawn(seed, local); } } private void Spawn(int seed, PlayerControllerB player) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00be: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: 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_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Expected O, but got Unknown //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) Despawn(); _seed = seed; _straightTime = 0f; _spawnedThisRound++; _cooldown = PersonalHelperPlugin.StalkerCooldownSeconds.Value; Texture2D val = PersonalHelperAssets.LoadTexture("images/meme", seed); _entity = GameObject.CreatePrimitive((PrimitiveType)5); Object.Destroy((Object)(object)_entity.GetComponent<Collider>()); ((Object)_entity).name = "PersonalHelperStalker"; _entity.transform.localScale = new Vector3(1.4f, 2.2f, 1f); Vector3 val2 = -((Component)player).transform.forward * PersonalHelperPlugin.StalkerSpawnDistance.Value; Vector3 val3 = ((Component)player).transform.position + val2; val3.y = ((Component)player).transform.position.y + 1.1f; RaycastHit val4 = default(RaycastHit); if (Physics.Linecast(((Component)player).transform.position, val3, ref val4, StartOfRound.Instance.collidersAndRoomMaskAndDefault)) { val3 = ((RaycastHit)(ref val4)).point + ((Component)player).transform.forward * 0.4f; } _entity.transform.position = val3; _entityRenderer = _entity.GetComponent<Renderer>(); _entityRenderer.material = new Material(Shader.Find("Unlit/Transparent")); if ((Object)(object)val != (Object)null) { _entityRenderer.material.mainTexture = (Texture)(object)val; } _entityRenderer.material.color = new Color(1f, 1f, 1f, 0.9f); _armed = true; PersonalHelperPlugin.Verbose("Stalker spawned behind the player."); } private void CheckSeen(PlayerControllerB player) { //IL_003d: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_entity == (Object)null) { _armed = false; return; } Camera gameplayCamera = player.gameplayCamera; if (!((Object)(object)gameplayCamera == (Object)null)) { _entity.transform.rotation = Quaternion.LookRotation(_entity.transform.position - ((Component)gameplayCamera).transform.position); Vector3 val = _entity.transform.position - ((Component)gameplayCamera).transform.position; if (!(Vector3.Angle(((Component)gameplayCamera).transform.forward, val) > gameplayCamera.fieldOfView * 0.5f) && !Physics.Linecast(((Component)gameplayCamera).transform.position, _entity.transform.position, StartOfRound.Instance.collidersAndRoomMaskAndDefault)) { Payoff(); } } } private void Payoff() { //IL_00b9: 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_00c9: Unknown result type (might be due to invalid IL or missing references) _armed = false; Despawn(); PersonalHelperRuntime runtime = PersonalHelperRuntime.Instance; if ((Object)(object)runtime == (Object)null) { return; } Texture2D val = PersonalHelperAssets.LoadTexture("images/meme", _seed); if ((Object)(object)val != (Object)null) { ((MonoBehaviour)runtime).StartCoroutine(runtime.ShowFullscreen(val, PersonalHelperPlugin.StalkerMemeSeconds.Value, PersonalHelperPlugin.StalkerFadeSeconds.Value)); } PersonalHelperAssets.LoadClip((MonoBehaviour)(object)runtime, "sounds/meme", _seed, delegate(AudioClip clip) { if (!((Object)(object)clip == (Object)null)) { runtime.PlayOneShot2D(clip); ((MonoBehaviour)runtime).StartCoroutine(FadeOutStinger(runtime, PersonalHelperPlugin.StalkerMemeSeconds.Value, PersonalHelperPlugin.StalkerFadeSeconds.Value)); } }); if (PersonalHelperPlugin.StalkerKillPlayer.Value) { PlayerControllerB local = Local; if ((Object)(object)local != (Object)null && !local.isPlayerDead) { local.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 0, default(Vector3), false); } } PersonalHelperPlugin.Verbose("Stalker seen. Payoff fired."); } private static IEnumerator FadeOutStinger(PersonalHelperRuntime runtime, float hold, float fade) { AudioSource source = runtime.StingerSource; float startVolume = source.volume; yield return (object)new WaitForSeconds(Mathf.Max(0f, hold)); float elapsed = 0f; while (elapsed < fade) { elapsed += Time.deltaTime; source.volume = Mathf.Lerp(startVolume, 0f, elapsed / fade); yield return null; } source.Stop(); source.volume = startVolume; } private void Despawn() { if ((Object)(object)_entity != (Object)null) { Object.Destroy((Object)(object)_entity); } _entity = null; _entityRenderer = null; _armed = false; } public void ResetRound() { Despawn(); _straightTime = 0f; _cooldown = 0f; _spawnedThisRound = 0; } } public static class PluginInfo { public const string PLUGIN_GUID = "PersonalHelper"; public const string PLUGIN_NAME = "PersonalHelper"; public const string PLUGIN_VERSION = "0.3.0"; } }