using 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(); } 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 list = LivingPlayers(); GUILayout.Label("Target", Array.Empty()); _scroll = GUILayout.BeginScrollView(_scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(150f) }); if (GUILayout.Toggle(_targetIndex == -1, " Everyone", Array.Empty())) { _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())) { _targetIndex = i; } } GUILayout.EndScrollView(); GUILayout.Space(8f); GUILayout.Label("Events", Array.Empty()); if (GUILayout.Button("Distant sound", Array.Empty())) { Fire(PersonalHelperEvent.DistantSound, list); } if (GUILayout.Button("Vigil (music + 1:30)", Array.Empty())) { Fire(PersonalHelperEvent.VigilStart, list); } if (GUILayout.Button("Jumpscare (image + death)", Array.Empty())) { Fire(PersonalHelperEvent.Jumpscare, list); } if (GUILayout.Button("Random flash", Array.Empty())) { Fire(PersonalHelperEvent.Flash, list); } if (GUILayout.Button("Spawn stalker behind them", Array.Empty())) { Fire(PersonalHelperEvent.Stalker, list); } GUILayout.Space(8f); GUILayout.Label("Video", Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); 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())) { float.TryParse(_videoSeconds, out var result); FireWithDuration(PersonalHelperEvent.PlayVideo, list, result); } GUILayout.Space(8f); GUILayout.Label("Lockdown", Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); 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())) { 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())) { PersonalHelperRuntime.Instance?.Request(PersonalHelperEvent.LockdownStop, everyone: true, 0uL); } GUILayout.Space(8f); if (GUILayout.Button("Reset round state", Array.Empty())) { PersonalHelperRuntime.Instance?.Request(PersonalHelperEvent.ResetRound, everyone: true, 0uL); } if (!string.IsNullOrEmpty(Feedback)) { GUILayout.Space(6f); GUILayout.Label(Feedback, Array.Empty()); } GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f)); } private void Fire(PersonalHelperEvent phEvent, List players) { FireWithDuration(phEvent, players, 0f); } private void FireWithDuration(PersonalHelperEvent phEvent, List 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 LivingPlayers() { List list = new List(); 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 ClipCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary TextureCache = new Dictionary(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(); } return (from f in Directory.GetFiles(path) where extensions.Contains(Path.GetExtension(f), StringComparer.OrdinalIgnoreCase) select f).OrderBy((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 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 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(); HandlerPrefab.AddComponent(); 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(HandlerPrefab).GetComponent().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 { 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(); } } [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 E1Chance; public static ConfigEntry E1MinDistance; public static ConfigEntry E1MaxDistance; public static ConfigEntry E1MaxAudibleDistance; public static ConfigEntry E2Chance; public static ConfigEntry E2TriggerAfterSeconds; public static ConfigEntry E2BuildupSeconds; public static ConfigEntry E2StartVolume; public static ConfigEntry E2EndVolume; public static ConfigEntry E2ImageSeconds; public static ConfigEntry E2KillPlayer; public static ConfigEntry FlashChancePerMinute; public static ConfigEntry FlashFrameSeconds; public static ConfigEntry StalkerEnabled; public static ConfigEntry StalkerStraightWalkSeconds; public static ConfigEntry StalkerYawTolerance; public static ConfigEntry StalkerSpawnDistance; public static ConfigEntry StalkerCooldownSeconds; public static ConfigEntry StalkerMaxPerRound; public static ConfigEntry StalkerMemeSeconds; public static ConfigEntry StalkerFadeSeconds; public static ConfigEntry StalkerKillPlayer; public static ConfigEntry VideoSeconds; public static ConfigEntry VideoVolume; public static ConfigEntry VideoKillPlayer; public static ConfigEntry LockdownDefaultSeconds; public static ConfigEntry LockdownKillOnTimeout; public static ConfigEntry LockdownPulseSpeed; public static ConfigEntry LockdownMinAlpha; public static ConfigEntry LockdownMaxAlpha; public static ConfigEntry LockdownAllowFireExit; public static ConfigEntry AdminSteamIDs; public static ConfigEntry AdminPanelKey; public static ConfigEntry HotkeysEnabled; public static ConfigEntry 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("Event1", "Chance", 85, new ConfigDescription("Chance of the distant sound event, in percent.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); E1MinDistance = ((BaseUnityPlugin)this).Config.Bind("Event1", "MinDistance", 22f, "Closest the sound can spawn, in meters."); E1MaxDistance = ((BaseUnityPlugin)this).Config.Bind("Event1", "MaxDistance", 40f, "Furthest the sound can spawn, in meters."); E1MaxAudibleDistance = ((BaseUnityPlugin)this).Config.Bind("Event1", "MaxAudibleDistance", 90f, "Falloff range of the sound, in meters."); E2Chance = ((BaseUnityPlugin)this).Config.Bind("Event2", "Chance", 67, new ConfigDescription("Chance of the vigil event, in percent.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); E2TriggerAfterSeconds = ((BaseUnityPlugin)this).Config.Bind("Event2", "TriggerAfterSeconds", 60f, "Seconds spent inside the facility before the music starts."); E2BuildupSeconds = ((BaseUnityPlugin)this).Config.Bind("Event2", "BuildupSeconds", 90f, "Seconds of buildup before the payoff. 90 = 1:30."); E2StartVolume = ((BaseUnityPlugin)this).Config.Bind("Event2", "StartVolume", 0.05f, "Music volume at the start of the buildup."); E2EndVolume = ((BaseUnityPlugin)this).Config.Bind("Event2", "EndVolume", 1f, "Music volume at the end of the buildup."); E2ImageSeconds = ((BaseUnityPlugin)this).Config.Bind("Event2", "ImageSeconds", 1.2f, "How long the full screen image stays."); E2KillPlayer = ((BaseUnityPlugin)this).Config.Bind("Event2", "KillPlayer", true, "Kill the player when the image appears."); FlashChancePerMinute = ((BaseUnityPlugin)this).Config.Bind("RandomFlash", "ChancePerMinute", 4, new ConfigDescription("Chance per minute of a single frame flash while inside.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); FlashFrameSeconds = ((BaseUnityPlugin)this).Config.Bind("RandomFlash", "FrameSeconds", 0.05f, "How long a flash stays on screen. Keep it tiny."); StalkerEnabled = ((BaseUnityPlugin)this).Config.Bind("Stalker", "Enabled", true, "Something spawns behind you when you walk straight for too long."); StalkerStraightWalkSeconds = ((BaseUnityPlugin)this).Config.Bind("Stalker", "StraightWalkSeconds", 11f, "Seconds of walking forward without turning before it spawns."); StalkerYawTolerance = ((BaseUnityPlugin)this).Config.Bind("Stalker", "YawTolerance", 35f, "Degrees per second of turning still counted as walking straight."); StalkerSpawnDistance = ((BaseUnityPlugin)this).Config.Bind("Stalker", "SpawnDistance", 7.5f, "How far behind you it spawns, in meters."); StalkerCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind("Stalker", "CooldownSeconds", 300f, "Cooldown between stalkers, in seconds."); StalkerMaxPerRound = ((BaseUnityPlugin)this).Config.Bind("Stalker", "MaxPerRound", 2, "Maximum stalkers per round, per player."); StalkerMemeSeconds = ((BaseUnityPlugin)this).Config.Bind("Stalker", "MemeSeconds", 1f, "How long the payoff image stays at full opacity."); StalkerFadeSeconds = ((BaseUnityPlugin)this).Config.Bind("Stalker", "FadeSeconds", 1.5f, "Fade out time of the payoff image and sound."); StalkerKillPlayer = ((BaseUnityPlugin)this).Config.Bind("Stalker", "KillPlayer", false, "Lethal or not. False keeps it a joke, true keeps it a threat."); VideoSeconds = ((BaseUnityPlugin)this).Config.Bind("Video", "Seconds", 11f, "How long the full screen video plays before it is cut off."); VideoVolume = ((BaseUnityPlugin)this).Config.Bind("Video", "Volume", 1f, "Volume of the video audio track."); VideoKillPlayer = ((BaseUnityPlugin)this).Config.Bind("Video", "KillPlayer", false, "Kill the player when the video ends."); LockdownDefaultSeconds = ((BaseUnityPlugin)this).Config.Bind("Lockdown", "DefaultSeconds", 120f, "Default countdown length."); LockdownKillOnTimeout = ((BaseUnityPlugin)this).Config.Bind("Lockdown", "KillOnTimeout", true, "Kill whoever is still inside when the timer hits zero."); LockdownPulseSpeed = ((BaseUnityPlugin)this).Config.Bind("Lockdown", "PulseSpeed", 1.4f, "Pulses per second of the full screen image."); LockdownMinAlpha = ((BaseUnityPlugin)this).Config.Bind("Lockdown", "MinAlpha", 0.25f, "Dimmest point of the pulse."); LockdownMaxAlpha = ((BaseUnityPlugin)this).Config.Bind("Lockdown", "MaxAlpha", 0.7f, "Brightest point of the pulse."); LockdownAllowFireExit = ((BaseUnityPlugin)this).Config.Bind("Lockdown", "AllowFireExit", true, "Fire exits keep working during a lockdown. Turning this off is cruel."); AdminSteamIDs = ((BaseUnityPlugin)this).Config.Bind("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("Admin", "PanelKey", (KeyCode)287, "Key that toggles the admin panel."); HotkeysEnabled = ((BaseUnityPlugin)this).Config.Bind("Debug", "HotkeysEnabled", true, "F7-F11 test hotkeys. Turn this off before playing seriously."); VerboseLogging = ((BaseUnityPlugin)this).Config.Bind("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 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(); } 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.renderMode = (RenderMode)0; _canvas.sortingOrder = 30000; val.AddComponent().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(); _timerText.font = Resources.GetBuiltinResource("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(); ((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(); _music.spatialBlend = 0f; _music.loop = false; _music.playOnAwake = false; _stinger = ((Component)this).gameObject.AddComponent(); _stinger.spatialBlend = 0f; _stinger.playOnAwake = false; GameObject val = new GameObject("PersonalHelperDistantSource"); val.transform.SetParent(((Component)this).transform, false); _distant = val.AddComponent(); _distant.spatialBlend = 1f; _distant.rolloffMode = (AudioRolloffMode)1; _distant.minDistance = 5f; _distant.playOnAwake = false; _videoAudio = ((Component)this).gameObject.AddComponent(); _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.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()); ((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(); _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"; } }