using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.UI; [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("SlendermanMod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.3.8.0")] [assembly: AssemblyInformationalVersion("1.3.8")] [assembly: AssemblyProduct("SlendermanMod")] [assembly: AssemblyTitle("SlendermanMod")] [assembly: AssemblyVersion("1.3.8.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SlendermanMod { [BepInPlugin("tonys.lethalcompany.slenderman", "Slenderman", "1.3.8")] [BepInProcess("Lethal Company.exe")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "tonys.lethalcompany.slenderman"; public const string PluginName = "Slenderman"; public const string PluginVersion = "1.3.8"; private static SlendermanRuntimeRunner _runtime; internal static ManualLogSource Log { get; private set; } internal static ConfigEntry SpawnRarity { get; private set; } internal static ConfigEntry GuaranteedSpawnChance { get; private set; } internal static ConfigEntry MaxSlendermen { get; private set; } internal static ConfigEntry WakeUpDelayHours { get; private set; } internal static ConfigEntry BaseAppearanceInterval { get; private set; } internal static ConfigEntry MinimumAppearanceInterval { get; private set; } internal static ConfigEntry RoundEscalationSeconds { get; private set; } internal static ConfigEntry MinimumStalkingDistance { get; private set; } internal static ConfigEntry MaximumStalkingDistance { get; private set; } internal static ConfigEntry AppearanceDuration { get; private set; } internal static ConfigEntry GazeAngle { get; private set; } internal static ConfigEntry GazeRange { get; private set; } internal static ConfigEntry BaseStareKillSeconds { get; private set; } internal static ConfigEntry StareKillReductionPerPage { get; private set; } internal static ConfigEntry LookAwayRecoverySpeed { get; private set; } internal static ConfigEntry StaticNoiseVolume { get; private set; } internal static ConfigEntry StaticVisualIntensity { get; private set; } internal static ConfigEntry DeathSoundVolume { get; private set; } internal static ConfigEntry DeathCloseupDuration { get; private set; } internal static ConfigEntry ContactDamage { get; private set; } internal static ConfigEntry Invulnerable { get; private set; } internal static ConfigEntry PagesPerRound { get; private set; } internal static ConfigEntry PageValue { get; private set; } internal static ConfigEntry EnableTestHotkey { get; private set; } internal static ConfigEntry TestSpawnKey { get; private set; } private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; BindConfig(); Harmony val = new Harmony("tonys.lethalcompany.slenderman"); val.PatchAll(typeof(Plugin).Assembly); SlenderCriticalPatches.Install(val); _runtime?.Dispose(); _runtime = new SlendermanRuntimeRunner(); _runtime.Initialize(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Slenderman 1.3.8 loaded for Lethal Company v81 / BepInEx 5.4.x."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Slenderman is registered as a separate enemy; the Bracken is not replaced or modified."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Multiplayer strategy: cloned vanilla network component layouts; no custom NetworkBehaviour RPCs."); } internal static void TickRuntime() { _runtime?.TickFrame(); } private void BindConfig() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected O, but got Unknown //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Expected O, but got Unknown //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Expected O, but got Unknown //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Expected O, but got Unknown //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Expected O, but got Unknown //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Expected O, but got Unknown //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Expected O, but got Unknown //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Expected O, but got Unknown //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Expected O, but got Unknown //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Expected O, but got Unknown //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Expected O, but got Unknown //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Expected O, but got Unknown //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_043e: Expected O, but got Unknown //IL_0471: Unknown result type (might be due to invalid IL or missing references) //IL_047b: Expected O, but got Unknown //IL_04ae: Unknown result type (might be due to invalid IL or missing references) //IL_04b8: Expected O, but got Unknown //IL_04e1: Unknown result type (might be due to invalid IL or missing references) //IL_04eb: Expected O, but got Unknown //IL_0517: Unknown result type (might be due to invalid IL or missing references) //IL_0521: Expected O, but got Unknown SpawnRarity = ((BaseUnityPlugin)this).Config.Bind("01 - Spawning", "Slenderman spawn rarity", 35, new ConfigDescription("Indoor spawn weight for the separate Slenderman enemy on vanilla and custom moons. The Bracken entry is left untouched.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 200), Array.Empty())); GuaranteedSpawnChance = ((BaseUnityPlugin)this).Config.Bind("01 - Spawning", "Guaranteed spawn chance percent", 35, new ConfigDescription("Chance from 0 to 100 that one Slenderman is spawned automatically after the facility has generated. Set this to 100 for a guaranteed Slenderman every round.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); MaxSlendermen = ((BaseUnityPlugin)this).Config.Bind("01 - Spawning", "Maximum Slendermen", 1, new ConfigDescription("Maximum number of Slendermen alive at once.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 5), Array.Empty())); WakeUpDelayHours = ((BaseUnityPlugin)this).Config.Bind("02 - Stalking", "Wake-up delay in game hours", 2f, new ConfigDescription("Slenderman stays dormant for this many in-game hours after landing, unless a page is collected first.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 8f), Array.Empty())); BaseAppearanceInterval = ((BaseUnityPlugin)this).Config.Bind("02 - Stalking", "Base appearance interval", 28f, new ConfigDescription("Seconds between early-round stalking appearances before time and pages increase the pressure.", (AcceptableValueBase)(object)new AcceptableValueRange(8f, 90f), Array.Empty())); MinimumAppearanceInterval = ((BaseUnityPlugin)this).Config.Bind("02 - Stalking", "Minimum appearance interval", 5f, new ConfigDescription("Shortest possible pause between appearances late in a round or after many pages.", (AcceptableValueBase)(object)new AcceptableValueRange(2f, 30f), Array.Empty())); RoundEscalationSeconds = ((BaseUnityPlugin)this).Config.Bind("02 - Stalking", "Seconds per round escalation", 75f, new ConfigDescription("Every this many elapsed round seconds reduces the appearance interval further.", (AcceptableValueBase)(object)new AcceptableValueRange(20f, 240f), Array.Empty())); MinimumStalkingDistance = ((BaseUnityPlugin)this).Config.Bind("02 - Stalking", "Minimum stalking distance", 14f, new ConfigDescription("Minimum distance behind a stalking target when Slenderman appears.", (AcceptableValueBase)(object)new AcceptableValueRange(8f, 30f), Array.Empty())); MaximumStalkingDistance = ((BaseUnityPlugin)this).Config.Bind("02 - Stalking", "Maximum stalking distance", 24f, new ConfigDescription("Maximum distance behind a stalking target when Slenderman appears.", (AcceptableValueBase)(object)new AcceptableValueRange(12f, 45f), Array.Empty())); AppearanceDuration = ((BaseUnityPlugin)this).Config.Bind("02 - Stalking", "Appearance duration", 4f, new ConfigDescription("Minimum time Slenderman offers a chance to notice him before he may vanish outside everyone's view.", (AcceptableValueBase)(object)new AcceptableValueRange(1.5f, 12f), Array.Empty())); ContactDamage = ((BaseUnityPlugin)this).Config.Bind("02 - Stalking", "Contact damage", 40, new ConfigDescription("Damage when a manifested Slenderman is physically touched after his short arrival grace period.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); Invulnerable = ((BaseUnityPlugin)this).Config.Bind("02 - Stalking", "Invulnerable", true, "When enabled, shovels and weapons cannot kill Slenderman."); GazeAngle = ((BaseUnityPlugin)this).Config.Bind("03 - Gaze", "Gaze angle", 18f, new ConfigDescription("Half-angle in degrees used to detect a direct look at Slenderman.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 45f), Array.Empty())); GazeRange = ((BaseUnityPlugin)this).Config.Bind("03 - Gaze", "Gaze range", 65f, new ConfigDescription("Maximum distance at which looking at Slenderman causes static.", (AcceptableValueBase)(object)new AcceptableValueRange(10f, 120f), Array.Empty())); BaseStareKillSeconds = ((BaseUnityPlugin)this).Config.Bind("03 - Gaze", "Seconds until stare kills", 6f, new ConfigDescription("Continuous effective stare time before death with zero collected pages.", (AcceptableValueBase)(object)new AcceptableValueRange(1.5f, 20f), Array.Empty())); StareKillReductionPerPage = ((BaseUnityPlugin)this).Config.Bind("03 - Gaze", "Kill-time reduction per page", 0.27f, new ConfigDescription("Seconds removed from the safe stare time per collected page.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 0.75f), Array.Empty())); LookAwayRecoverySpeed = ((BaseUnityPlugin)this).Config.Bind("03 - Gaze", "Look-away recovery multiplier", 1.35f, new ConfigDescription("How quickly accumulated static recovers after looking away.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 5f), Array.Empty())); StaticNoiseVolume = ((BaseUnityPlugin)this).Config.Bind("03 - Gaze", "Static noise volume", 0.7f, new ConfigDescription("Maximum volume of the gaze static sound.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); StaticVisualIntensity = ((BaseUnityPlugin)this).Config.Bind("03 - Gaze", "Static visual intensity", 1f, new ConfigDescription("Strength of the screen grain and interference strokes. 1 is the intended intensity.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 2f), Array.Empty())); DeathSoundVolume = ((BaseUnityPlugin)this).Config.Bind("03 - Gaze", "Death sound volume", 1.35f, new ConfigDescription("Volume multiplier of the supplied Slenderman death sound during the close-up.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 2f), Array.Empty())); DeathCloseupDuration = ((BaseUnityPlugin)this).Config.Bind("03 - Gaze", "Death close-up duration", 2.6f, new ConfigDescription("Seconds the Slenderman close-up and maximum interference play before the stare kills the player.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 5f), Array.Empty())); PagesPerRound = ((BaseUnityPlugin)this).Config.Bind("04 - Pages", "Pages per round", 11, new ConfigDescription("Number of Slender scribble pages added as loot. Hard-capped at 11.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 11), Array.Empty())); PageValue = ((BaseUnityPlugin)this).Config.Bind("04 - Pages", "Page value", 60, new ConfigDescription("Credit value of every page. The intended value is 60.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 500), Array.Empty())); EnableTestHotkey = ((BaseUnityPlugin)this).Config.Bind("05 - Testing", "Enable test spawn hotkey", true, "Allows the host to spawn one Slenderman with the configured test key while standing inside a facility."); TestSpawnKey = ((BaseUnityPlugin)this).Config.Bind("05 - Testing", "Test spawn key", (KeyCode)288, "Key used by the host to spawn one Slenderman for testing."); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; ((BaseUnityPlugin)this).Config.Save(); } } internal sealed class SlenderAudioAssets : IDisposable { private const string ResourcePrefix = "SlendermanMod.Assets."; private UnityWebRequest _stareRequest; private UnityWebRequest _deathRequest; private string _stareTemporaryPath; private string _deathTemporaryPath; private AudioClip _stareClip; private AudioClip _deathClip; internal AudioClip StareClip => _stareClip; internal AudioClip DeathClip => _deathClip; internal void BeginLoad() { _stareRequest = StartEmbeddedMp3Load("slenderman_stare.mp3", "stare", out _stareTemporaryPath); _deathRequest = StartEmbeddedMp3Load("slenderman_death.mp3", "death", out _deathTemporaryPath); } internal void Tick() { CompleteLoad(ref _stareRequest, ref _stareTemporaryPath, ref _stareClip, "SlendermanStareSound"); CompleteLoad(ref _deathRequest, ref _deathTemporaryPath, ref _deathClip, "SlendermanDeathSound"); } private static UnityWebRequest StartEmbeddedMp3Load(string resourceName, string suffix, out string temporaryPath) { temporaryPath = null; try { Assembly assembly = typeof(SlenderAudioAssets).Assembly; using Stream stream = assembly.GetManifestResourceStream("SlendermanMod.Assets." + resourceName); if (stream == null) { Plugin.Log.LogError((object)("Embedded Slenderman audio resource '" + resourceName + "' was not found.")); return null; } string text = Path.Combine(Path.GetTempPath(), "TonyS-Slenderman-Audio"); Directory.CreateDirectory(text); temporaryPath = Path.Combine(text, $"{Guid.NewGuid():N}-{suffix}.mp3"); using (FileStream destination = File.Create(temporaryPath)) { stream.CopyTo(destination); } UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(new Uri(temporaryPath).AbsoluteUri, (AudioType)13); DownloadHandler downloadHandler = audioClip.downloadHandler; DownloadHandlerAudioClip val = (DownloadHandlerAudioClip)(object)((downloadHandler is DownloadHandlerAudioClip) ? downloadHandler : null); if (val != null) { val.streamAudio = false; val.compressed = false; } audioClip.SendWebRequest(); return audioClip; } catch (Exception arg) { Plugin.Log.LogError((object)$"Could not begin loading embedded Slenderman audio '{resourceName}': {arg}"); DeleteTemporaryFile(ref temporaryPath); return null; } } private static void CompleteLoad(ref UnityWebRequest request, ref string temporaryPath, ref AudioClip clip, string clipName) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 if (request == null || !request.isDone) { return; } try { if ((int)request.result != 1) { Plugin.Log.LogError((object)("Could not decode " + clipName + ": " + request.error)); return; } AudioClip content = DownloadHandlerAudioClip.GetContent(request); if ((Object)(object)content == (Object)null) { Plugin.Log.LogError((object)("Unity returned no clip while decoding " + clipName + ".")); return; } float[] array = new float[content.samples * content.channels]; if (!content.GetData(array, 0)) { Plugin.Log.LogError((object)("Unity could not expose decoded PCM data for " + clipName + ".")); return; } clip = AudioClip.Create(clipName, content.samples, content.channels, content.frequency, false); if (!clip.SetData(array, 0)) { Object.Destroy((Object)(object)clip); clip = null; Plugin.Log.LogError((object)("Unity could not create a persistent PCM copy for " + clipName + ".")); } else { ((Object)clip).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)clip); Plugin.Log.LogInfo((object)$"Loaded embedded {clipName} ({clip.length:F1} seconds)."); } } catch (Exception arg) { Plugin.Log.LogError((object)$"Could not finish loading {clipName}: {arg}"); } finally { request.Dispose(); request = null; DeleteTemporaryFile(ref temporaryPath); } } private static void DeleteTemporaryFile(ref string path) { if (string.IsNullOrEmpty(path)) { return; } try { string directoryName = Path.GetDirectoryName(path); if (File.Exists(path)) { File.Delete(path); } if (!string.IsNullOrEmpty(directoryName) && Directory.Exists(directoryName) && Directory.GetFileSystemEntries(directoryName).Length == 0) { Directory.Delete(directoryName); } } catch (Exception ex) { Plugin.Log.LogDebug((object)("Temporary Slenderman audio file could not be removed yet: " + ex.Message)); } finally { path = null; } } public void Dispose() { UnityWebRequest stareRequest = _stareRequest; if (stareRequest != null) { stareRequest.Dispose(); } UnityWebRequest deathRequest = _deathRequest; if (deathRequest != null) { deathRequest.Dispose(); } _stareRequest = null; _deathRequest = null; DeleteTemporaryFile(ref _stareTemporaryPath); DeleteTemporaryFile(ref _deathTemporaryPath); if ((Object)(object)_stareClip != (Object)null) { Object.Destroy((Object)(object)_stareClip); _stareClip = null; } if ((Object)(object)_deathClip != (Object)null) { Object.Destroy((Object)(object)_deathClip); _deathClip = null; } } } internal sealed class SlenderBootstrap { private float _nextRegistrationAttempt; private float _nextLevelRefresh; private float _nextAutomaticSpawnAttempt; private float _nextEnemyInitializationAttempt; private bool _registered; private int _roundSeed = int.MinValue; private bool _automaticSpawnHandled; private bool _invalidTestKeyReported; private bool _testKeyWasDown; internal void Tick() { TryRegisterBeforeNetworkingStarts(); SlenderLethalEscapeCompatibility.TryInstall(); InitializeSpawnedSlendermen(); SlenderRuntime.TickAll(); RefreshLevelSpawnLists(); HandleGuaranteedRoundSpawn(); HandlePageSpawn(); HandleTestHotkey(); } private void InitializeSpawnedSlendermen() { if (Time.unscaledTime < _nextEnemyInitializationAttempt) { return; } _nextEnemyInitializationAttempt = Time.unscaledTime + 0.25f; FlowermanAI[] array = Resources.FindObjectsOfTypeAll(); foreach (FlowermanAI val in array) { NetworkObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent() : null); if (!((Object)(object)val == (Object)null) && !((EnemyAI)val).isEnemyDead && !((Object)(object)val2 == (Object)null) && val2.IsSpawned && SlenderEnemyRegistry.IsSlendermanInstance((EnemyAI)(object)val)) { SlenderRuntime.EnsureInitialized(val); } } } private void TryRegisterBeforeNetworkingStarts() { if (!_registered && !(Time.unscaledTime < _nextRegistrationAttempt)) { _nextRegistrationAttempt = Time.unscaledTime + 0.5f; NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null)) { _registered = SlenderEnemyRegistry.EnsureRegistered(singleton); } } } private void RefreshLevelSpawnLists() { if (!_registered || Time.unscaledTime < _nextLevelRefresh) { return; } _nextLevelRefresh = Time.unscaledTime + 2f; SelectableLevel[] array = StartOfRound.Instance?.levels; if (array != null) { for (int i = 0; i < array.Length; i++) { SlenderRuntime.AdjustSpawnList(array[i]); } } } private void HandleTestHotkey() { //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.EnableTestHotkey.Value || !WasTestKeyPressed()) { return; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; NetworkManager singleton = NetworkManager.Singleton; RoundManager instance = RoundManager.Instance; if (!_registered && (Object)(object)singleton != (Object)null) { _registered = SlenderEnemyRegistry.EnsureRegistered(singleton); } if (!_registered || (Object)(object)SlenderEnemyRegistry.SlenderEnemyType == (Object)null) { ShowTip("SLENDERMAN-TEST", "Slenderman wurde noch nicht registriert. Spiel bitte neu starten.", warning: true); return; } if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { ShowTip("SLENDERMAN-TEST", "Nur der Host kann den Testgegner erzeugen.", warning: true); return; } if ((Object)(object)val == (Object)null || (Object)(object)instance == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.inShipPhase || !instance.dungeonFinishedGeneratingForAllPlayers) { ShowTip("SLENDERMAN-TEST", "Zuerst landen und warten, bis die Anlage fertig geladen ist.", warning: true); return; } try { SlenderPageSystem.ForceAwakeForTesting(); SlenderMarker slenderMarker = FindLivingSlenderman(instance); if ((Object)(object)slenderMarker != (Object)null) { slenderMarker.ForceAppearanceForTest(val); ShowTip("SLENDERMAN-TEST", "Der vorhandene Slenderman erscheint jetzt hinter dir.", warning: false); Plugin.Log.LogInfo((object)$"F7 forced existing Slenderman network object {((NetworkBehaviour)slenderMarker.Ai).NetworkObjectId} to appear behind the host."); } else { Vector3 val2 = FindSpawnPosition(instance, val); NetworkObjectReference reference = instance.SpawnEnemyGameObject(val2, ((Component)val).transform.eulerAngles.y + 180f, 0, SlenderEnemyRegistry.SlenderEnemyType); InitializeSpawnedReference(reference, "F7")?.ForceAppearanceForTest(val); ShowTip("SLENDERMAN-TEST", "Slenderman erscheint jetzt hinter dir.", warning: false); Plugin.Log.LogInfo((object)$"Test Slenderman spawned at {val2} using {Plugin.TestSpawnKey.Value}."); } } catch (Exception arg) { Plugin.Log.LogError((object)$"Test spawn failed: {arg}"); ShowTip("SLENDERMAN-TEST", "Erzeugen fehlgeschlagen. Bitte LogOutput.log prüfen.", warning: true); } } private bool WasTestKeyPressed() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; if (current == null) { _testKeyWasDown = false; return false; } string text = ((object)Plugin.TestSpawnKey.Value/*cast due to .constrained prefix*/).ToString(); if (Enum.TryParse(text, ignoreCase: true, out Key result) && (int)result != 0) { bool isPressed = ((ButtonControl)current[result]).isPressed; bool result2 = isPressed && !_testKeyWasDown; _testKeyWasDown = isPressed; return result2; } if (!_invalidTestKeyReported) { _invalidTestKeyReported = true; Plugin.Log.LogWarning((object)("Test key '" + text + "' is not supported by the active input system; using F7.")); } bool isPressed2 = ((ButtonControl)current.f7Key).isPressed; bool result3 = isPressed2 && !_testKeyWasDown; _testKeyWasDown = isPressed2; return result3; } private void HandleGuaranteedRoundSpawn() { //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) StartOfRound instance = StartOfRound.Instance; RoundManager instance2 = RoundManager.Instance; NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || (Object)(object)singleton == (Object)null || !singleton.IsServer || instance.inShipPhase) { _automaticSpawnHandled = false; return; } if (_roundSeed != instance.randomMapSeed) { _roundSeed = instance.randomMapSeed; _automaticSpawnHandled = false; SlenderPageSystem.ResetRound(); } if (_automaticSpawnHandled || Time.unscaledTime < _nextAutomaticSpawnAttempt || !instance2.dungeonFinishedGeneratingForAllPlayers || instance2.insideAINodes == null || instance2.insideAINodes.Length == 0) { return; } _nextAutomaticSpawnAttempt = Time.unscaledTime + 1f; if (!_registered) { _registered = SlenderEnemyRegistry.EnsureRegistered(singleton); } if (!_registered || (Object)(object)SlenderEnemyRegistry.SlenderEnemyType == (Object)null) { Plugin.Log.LogError((object)"Guaranteed Slenderman spawn was skipped because registration was unavailable."); return; } _automaticSpawnHandled = true; int num = Mathf.Clamp(Plugin.GuaranteedSpawnChance.Value, 0, 100); int num2 = new Random(instance.randomMapSeed ^ 0x51EAD3).Next(0, 100); Plugin.Log.LogInfo((object)$"Guaranteed Slenderman spawn roll: {num2 + 1}/100 with configured chance {num}%."); if (num2 >= num || CountLivingSlendermen(instance2) >= Mathf.Clamp(Plugin.MaxSlendermen.Value, 1, 5)) { return; } try { Vector3 val = FindSpawnPosition(instance2, null); NetworkObjectReference reference = instance2.SpawnEnemyGameObject(val, Random.Range(0f, 360f), 0, SlenderEnemyRegistry.SlenderEnemyType); InitializeSpawnedReference(reference, "automatic spawn"); SlenderEnemyRegistry.SlenderEnemyType.numberSpawned = Mathf.Max(SlenderEnemyRegistry.SlenderEnemyType.numberSpawned, CountLivingSlendermen(instance2)); Plugin.Log.LogInfo((object)$"Automatically spawned Slenderman at {val}."); } catch (Exception arg) { Plugin.Log.LogError((object)$"Guaranteed Slenderman spawn failed: {arg}"); } } private void HandlePageSpawn() { StartOfRound instance = StartOfRound.Instance; RoundManager instance2 = RoundManager.Instance; NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance2 == (Object)null) && !((Object)(object)singleton == (Object)null) && singleton.IsServer && !instance.inShipPhase && instance2.dungeonFinishedGeneratingForAllPlayers && !SlenderPageSystem.PagesSpawned) { if (!_registered) { _registered = SlenderEnemyRegistry.EnsureRegistered(singleton); } if (_registered) { SlenderPageSystem.SpawnPages(instance2); } } } private static int CountLivingSlendermen(RoundManager round) { int num = 0; for (int i = 0; i < round.SpawnedEnemies.Count; i++) { EnemyAI val = round.SpawnedEnemies[i]; if ((Object)(object)val != (Object)null && !val.isEnemyDead && SlenderEnemyRegistry.IsSlendermanInstance(val)) { num++; } } return num; } private static SlenderMarker FindLivingSlenderman(RoundManager round) { if ((Object)(object)round == (Object)null || round.SpawnedEnemies == null) { return null; } for (int i = 0; i < round.SpawnedEnemies.Count; i++) { EnemyAI obj = round.SpawnedEnemies[i]; FlowermanAI val = (FlowermanAI)(object)((obj is FlowermanAI) ? obj : null); if ((Object)(object)val != (Object)null && !((EnemyAI)val).isEnemyDead && SlenderEnemyRegistry.IsSlendermanInstance((EnemyAI)(object)val)) { return SlenderRuntime.ForceInitialize(val); } } return null; } private static SlenderMarker InitializeSpawnedReference(NetworkObjectReference reference, string source) { NetworkObject val = default(NetworkObject); if (!((NetworkObjectReference)(ref reference)).TryGet(ref val, (NetworkManager)null) || (Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("Could not resolve the Slenderman network object immediately after " + source + "; the runtime scan will retry.")); return null; } FlowermanAI val2 = ((Component)val).GetComponent() ?? ((Component)val).GetComponentInParent() ?? ((Component)val).GetComponentInChildren(true); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogError((object)("The network object created by " + source + " did not contain a FlowermanAI component.")); return null; } SlenderMarker result = SlenderRuntime.ForceInitialize(val2); Plugin.Log.LogInfo((object)$"Directly initialized the Slenderman network object {val.NetworkObjectId} after {source}."); return result; } private static Vector3 FindSpawnPosition(RoundManager round, PlayerControllerB player) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) Vector3 val2; if ((Object)(object)player != (Object)null && player.isInsideFactory) { Vector3 val = Vector3.ProjectOnPlane(((Component)player).transform.forward, Vector3.up); Vector3 normalized = ((Vector3)(ref val)).normalized; val2 = ((Component)player).transform.position + normalized * 8f; } else { GameObject[] insideAINodes = round.insideAINodes; if (insideAINodes == null || insideAINodes.Length == 0) { throw new InvalidOperationException("No indoor AI nodes were available."); } val2 = insideAINodes[Random.Range(0, insideAINodes.Length)].transform.position; } return round.GetRandomNavMeshPositionInRadius(val2, 5f, default(NavMeshHit)); } private static void ShowTip(string title, string message, bool warning) { if ((Object)(object)HUDManager.Instance != (Object)null) { HUDManager.Instance.DisplayTip(title, message, warning, false, "LC_Tip1"); } } } internal static class SlenderCriticalPatches { private static readonly MethodInfo NetworkPrefix = AccessTools.Method(typeof(SlenderCriticalPatches), "BeforeNetworkStart", (Type[])null, (Type[])null); private static readonly MethodInfo GameHostPrefix = AccessTools.Method(typeof(SlenderCriticalPatches), "BeforeGameHostStart", (Type[])null, (Type[])null); private static readonly MethodInfo RuntimePostfix = AccessTools.Method(typeof(SlenderCriticalPatches), "AfterGameFrame", (Type[])null, (Type[])null); internal static void Install(Harmony harmony) { PatchPrefix(harmony, AccessTools.Method(typeof(GameNetworkManager), "StartHost", (Type[])null, (Type[])null), GameHostPrefix); PatchPrefix(harmony, AccessTools.Method(typeof(NetworkManager), "StartHost", (Type[])null, (Type[])null), NetworkPrefix); PatchPrefix(harmony, AccessTools.Method(typeof(NetworkManager), "StartClient", (Type[])null, (Type[])null), NetworkPrefix); PatchPrefix(harmony, AccessTools.Method(typeof(NetworkManager), "StartServer", (Type[])null, (Type[])null), NetworkPrefix); PatchPostfix(harmony, AccessTools.Method(typeof(MenuManager), "Update", (Type[])null, (Type[])null), RuntimePostfix); PatchPostfix(harmony, AccessTools.Method(typeof(StartOfRound), "Update", (Type[])null, (Type[])null), RuntimePostfix); PatchPostfix(harmony, AccessTools.Method(typeof(RoundManager), "Update", (Type[])null, (Type[])null), RuntimePostfix); } private static void PatchPostfix(Harmony harmony, MethodInfo original, MethodInfo postfix) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown if (original == null || postfix == null) { Plugin.Log.LogError((object)"A required Slenderman runtime patch method could not be found."); return; } if (!HasOwnedPostfix(original)) { harmony.Patch((MethodBase)original, (HarmonyMethod)null, new HarmonyMethod(postfix), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } Plugin.Log.LogInfo((object)$"Verified runtime hook on {original.DeclaringType?.Name}.{original.Name}: {HasOwnedPostfix(original)}."); } private static void PatchPrefix(Harmony harmony, MethodInfo original, MethodInfo prefix) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown if (original == null || prefix == null) { Plugin.Log.LogError((object)"A required Slenderman startup patch method could not be found."); return; } if (!HasOwnedPrefix(original)) { harmony.Patch((MethodBase)original, new HarmonyMethod(prefix), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } Plugin.Log.LogInfo((object)$"Verified early registration hook on {original.DeclaringType?.Name}.{original.Name}: {HasOwnedPrefix(original)}."); } private static bool HasOwnedPrefix(MethodBase original) { Patches patchInfo = Harmony.GetPatchInfo(original); if (patchInfo == null) { return false; } for (int i = 0; i < patchInfo.Prefixes.Count; i++) { if (string.Equals(patchInfo.Prefixes[i].owner, "tonys.lethalcompany.slenderman", StringComparison.Ordinal)) { return true; } } return false; } private static bool HasOwnedPostfix(MethodBase original) { Patches patchInfo = Harmony.GetPatchInfo(original); if (patchInfo == null) { return false; } for (int i = 0; i < patchInfo.Postfixes.Count; i++) { if (string.Equals(patchInfo.Postfixes[i].owner, "tonys.lethalcompany.slenderman", StringComparison.Ordinal)) { return true; } } return false; } private static void AfterGameFrame() { Plugin.TickRuntime(); } private static void BeforeGameHostStart() { TryRegister(NetworkManager.Singleton, "game host"); } private static void BeforeNetworkStart(NetworkManager __instance, MethodBase __originalMethod) { TryRegister(__instance, __originalMethod?.Name ?? "network"); } private static void TryRegister(NetworkManager manager, string source) { Plugin.Log.LogInfo((object)("Preparing Slenderman before " + source + " startup.")); if (!SlenderEnemyRegistry.EnsureRegistered(manager)) { Plugin.Log.LogError((object)("Slenderman could not be registered before " + source + " startup.")); } } } internal static class SlenderEnemyRegistry { private const uint SlendermanPrefabHash = 2051879369u; private const uint SlenderPagePrefabHash = 2051879370u; private static readonly FieldInfo GlobalHashField = AccessTools.Field(typeof(NetworkObject), "GlobalObjectIdHash"); private static readonly FieldInfo PrefabHashField = AccessTools.Field(typeof(NetworkObject), "PrefabGlobalObjectIdHash"); private static NetworkManager _registeredManager; internal static EnemyType SlenderEnemyType { get; private set; } internal static GameObject SlendermanPrefab { get; private set; } internal static Item PageItem { get; private set; } internal static GameObject PagePrefab { get; private set; } internal static bool IsSlendermanInstance(EnemyAI ai) { if ((Object)(object)ai == (Object)null) { return false; } if ((Object)(object)((Component)ai).GetComponent() != (Object)null || (Object)(object)((Component)ai).GetComponent() != (Object)null) { return true; } if ((Object)(object)SlenderEnemyType != (Object)null && (Object)(object)ai.enemyType == (Object)(object)SlenderEnemyType) { return true; } if ((Object)(object)ai.enemyType != (Object)null && string.Equals(ai.enemyType.enemyName, "Slenderman", StringComparison.OrdinalIgnoreCase)) { return true; } NetworkObject component = ((Component)ai).GetComponent(); if ((Object)(object)component != (Object)null && component.PrefabIdHash == 2051879369) { return true; } return ((Object)((Component)ai).gameObject).name.StartsWith("SlendermanEnemyPrefab", StringComparison.OrdinalIgnoreCase); } internal static bool EnsureRegistered(NetworkManager manager = null) { if (manager == null) { manager = NetworkManager.Singleton; } if ((Object)(object)manager == (Object)null || manager.NetworkConfig?.Prefabs == null) { Plugin.Log.LogWarning((object)"NetworkManager was not ready; Slenderman registration will be retried."); return false; } if ((Object)(object)SlendermanPrefab == (Object)null && !BuildRuntimePrefabs(manager)) { return false; } if ((Object)(object)_registeredManager == (Object)(object)manager) { return true; } try { RegisterPrefab(manager, SlendermanPrefab, 2051879369u); RegisterPrefab(manager, PagePrefab, 2051879370u); _registeredManager = manager; Plugin.Log.LogInfo((object)"Registered separate Slenderman enemy and Slender page network prefabs."); return true; } catch (Exception arg) { Plugin.Log.LogError((object)$"Could not register Slenderman network prefabs: {arg}"); return false; } } private static bool BuildRuntimePrefabs(NetworkManager manager) { GameObject val = FindFlowermanPrefab(manager); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"Could not find the vanilla Flowerman prefab. Slenderman cannot be created."); return false; } FlowermanAI component = val.GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)((EnemyAI)component).enemyType == (Object)null) { Plugin.Log.LogError((object)"The vanilla Flowerman prefab did not contain a valid enemy type."); return false; } SlenderEnemyType = Object.Instantiate(((EnemyAI)component).enemyType); ((Object)SlenderEnemyType).name = "SlendermanEnemyType"; SlenderEnemyType.enemyName = "Slenderman"; SlenderEnemyType.numberSpawned = 0; SlenderEnemyType.nestsSpawned = 0; SlenderEnemyType.hasSpawnedAtLeastOne = false; SlenderEnemyType.MaxCount = Mathf.Clamp(Plugin.MaxSlendermen.Value, 1, 5); SlenderEnemyType.canBeStunned = false; SlenderEnemyType.canDie = !Plugin.Invulnerable.Value; Object.DontDestroyOnLoad((Object)(object)SlenderEnemyType); SlendermanPrefab = CloneInactivePrefab(val, "SlendermanEnemyPrefab"); FlowermanAI component2 = SlendermanPrefab.GetComponent(); ((EnemyAI)component2).enemyType = SlenderEnemyType; SlendermanPrefab.AddComponent(); SetNetworkHash(SlendermanPrefab, 2051879369u); SlenderEnemyType.enemyPrefab = SlendermanPrefab; GameObject val2 = FindPageShell(manager); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogError((object)"Could not find a vanilla scrap prefab to use for Slender pages."); return false; } GrabbableObject component3 = val2.GetComponent(); PageItem = Object.Instantiate(component3.itemProperties); ((Object)PageItem).name = "SlenderPageItem"; PageItem.itemName = "Slender-Kritzelzettel"; PageItem.itemId = 2051879370; PageItem.isScrap = true; PageItem.creditsWorth = Plugin.PageValue.Value; PageItem.minValue = Plugin.PageValue.Value; PageItem.maxValue = Plugin.PageValue.Value + 1; PageItem.twoHanded = false; PageItem.weight = 1.02f; PageItem.toolTips = Array.Empty(); Object.DontDestroyOnLoad((Object)(object)PageItem); PagePrefab = CloneInactivePrefab(val2, "SlenderPagePrefab"); GrabbableObject component4 = PagePrefab.GetComponent(); component4.itemProperties = PageItem; component4.scrapValue = Plugin.PageValue.Value; PagePrefab.AddComponent(); SetNetworkHash(PagePrefab, 2051879370u); PageItem.spawnPrefab = PagePrefab; return true; } private static GameObject FindFlowermanPrefab(NetworkManager manager) { IReadOnlyList prefabs = manager.NetworkConfig.Prefabs.Prefabs; GameObject val = null; for (int i = 0; i < prefabs.Count; i++) { GameObject val2 = prefabs[i]?.Prefab; FlowermanAI val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent() : null); if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val2.GetComponent() == (Object)null)) { if (val == null) { val = val2; } string a = (((Object)(object)((EnemyAI)val3).enemyType != (Object)null) ? ((EnemyAI)val3).enemyType.enemyName : string.Empty); if (string.Equals(a, "Flowerman", StringComparison.OrdinalIgnoreCase)) { return val2; } } } return val; } private static GameObject FindPageShell(NetworkManager manager) { IReadOnlyList prefabs = manager.NetworkConfig.Prefabs.Prefabs; GameObject val = null; for (int i = 0; i < prefabs.Count; i++) { GameObject val2 = prefabs[i]?.Prefab; GrabbableObject val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent() : null); Item val4 = (((Object)(object)val3 != (Object)null) ? val3.itemProperties : null); if (!((Object)(object)val4 == (Object)null) && val4.isScrap && !val4.twoHanded && !((Object)(object)val2.GetComponent() == (Object)null)) { if ((Object)(object)val == (Object)null && ((object)val3).GetType().Name == "PhysicsProp") { val = val2; } string text = val4.itemName ?? string.Empty; if (text.IndexOf("big bolt", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("large axle", StringComparison.OrdinalIgnoreCase) >= 0) { return val2; } } } return val; } private static GameObject CloneInactivePrefab(GameObject source, string name) { bool activeSelf = source.activeSelf; if (activeSelf) { source.SetActive(false); } GameObject val = Object.Instantiate(source); if (activeSelf) { source.SetActive(true); } ((Object)val).name = name; val.SetActive(false); Object.DontDestroyOnLoad((Object)(object)val); return val; } private static void SetNetworkHash(GameObject prefab, uint hash) { NetworkObject component = prefab.GetComponent(); if ((Object)(object)component == (Object)null || GlobalHashField == null || PrefabHashField == null) { throw new InvalidOperationException("Network hash fields were unavailable for " + ((Object)prefab).name + "."); } GlobalHashField.SetValue(component, hash); PrefabHashField.SetValue(component, hash); } private static void RegisterPrefab(NetworkManager manager, GameObject prefab, uint expectedHash) { IReadOnlyList prefabs = manager.NetworkConfig.Prefabs.Prefabs; for (int i = 0; i < prefabs.Count; i++) { GameObject val = prefabs[i]?.Prefab; NetworkObject val2 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); if (!((Object)(object)val2 == (Object)null) && val2.PrefabIdHash == expectedHash) { if ((Object)(object)val != (Object)(object)prefab) { throw new InvalidOperationException($"Network prefab hash collision: 0x{expectedHash:X8}."); } return; } } manager.AddNetworkPrefab(prefab); } } internal sealed class SlenderIdentity : MonoBehaviour { } internal sealed class SlenderPageIdentity : MonoBehaviour { private void Start() { SlenderPageSystem.PreparePage(((Component)this).gameObject); } } internal static class SlenderLethalEscapeCompatibility { private const string HarmonyId = "tonys.lethalcompany.slenderman.lethalescape.compatibility"; private static readonly MethodInfo FlowermanGuard = AccessTools.Method(typeof(SlenderLethalEscapeCompatibility), "AllowFlowermanPatch", (Type[])null, (Type[])null); private static readonly MethodInfo EnemyGuard = AccessTools.Method(typeof(SlenderLethalEscapeCompatibility), "AllowEnemyTransfer", (Type[])null, (Type[])null); private static bool _installed; private static float _nextAttempt; internal static void TryInstall() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if (!_installed && !(Time.unscaledTime < _nextAttempt)) { _nextAttempt = Time.unscaledTime + 1f; Type type = AccessTools.TypeByName("UpdatedEscape.Plugin"); if (!(type == null)) { Harmony harmony = new Harmony("tonys.lethalcompany.slenderman.lethalescape.compatibility"); int num = 0; num += PatchGuard(harmony, type, "DoAIInterval_BrackenCarryBodyFix", FlowermanGuard); num += PatchGuard(harmony, type, "FlowermanAILEPrefixAI", FlowermanGuard); num += PatchGuard(harmony, type, "FlowerManAILEOutsideAttack", FlowermanGuard); num += PatchGuard(harmony, type, "FlowermanAILEPostfixStart", FlowermanGuard); num += PatchGuard(harmony, type, "SendEnemyInside", EnemyGuard); num += PatchGuard(harmony, type, "SendEnemyOutside", EnemyGuard); _installed = true; Plugin.Log.LogInfo((object)$"Lethal Escape compatibility active: guarded {num} transfer/Bracken patch method(s); normal Brackens and all other enemies remain unchanged."); } } } private static int PatchGuard(Harmony harmony, Type pluginType, string methodName, MethodInfo prefix) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(pluginType, methodName, (Type[])null, (Type[])null); if (methodInfo == null || prefix == null) { Plugin.Log.LogWarning((object)("Lethal Escape compatibility could not find " + pluginType.FullName + "." + methodName + ".")); return 0; } Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo); if (patchInfo != null) { for (int i = 0; i < patchInfo.Prefixes.Count; i++) { if (string.Equals(patchInfo.Prefixes[i].owner, "tonys.lethalcompany.slenderman.lethalescape.compatibility", StringComparison.Ordinal)) { return 1; } } } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(prefix), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); return 1; } private static bool AllowFlowermanPatch(FlowermanAI __0) { return !SlenderEnemyRegistry.IsSlendermanInstance((EnemyAI)(object)__0); } private static bool AllowEnemyTransfer(EnemyAI __0) { return !SlenderEnemyRegistry.IsSlendermanInstance(__0); } } internal sealed class SlendermanRuntimeRunner : IDisposable { private SlenderBootstrap _bootstrap; private SlenderScreenEffect _screenEffect; private SlenderPageWatcher _pageWatcher; private bool _initialized; private bool _runtimeTickConfirmed; private bool _runtimeContinuationConfirmed; private int _firstTickFrame = -1; private int _lastTickFrame = -1; private float _nextRuntimeErrorLog; internal void Initialize() { if (!_initialized) { _initialized = true; _bootstrap = new SlenderBootstrap(); _screenEffect = new SlenderScreenEffect(); _pageWatcher = new SlenderPageWatcher(); Plugin.Log.LogInfo((object)"Harmony-driven Slenderman runtime initialized."); RegisterAnyExistingNetworkManager(); TickFrame(); } } internal void TickFrame() { if (_initialized && _lastTickFrame != Time.frameCount) { _lastTickFrame = Time.frameCount; if (!_runtimeTickConfirmed) { _runtimeTickConfirmed = true; _firstTickFrame = Time.frameCount; Plugin.Log.LogInfo((object)$"Slenderman event runtime tick started at frame {_firstTickFrame}."); } else if (!_runtimeContinuationConfirmed && Time.frameCount != _firstTickFrame) { _runtimeContinuationConfirmed = true; Plugin.Log.LogInfo((object)$"Slenderman event runtime continued on frame {Time.frameCount}."); } RunSafely(_bootstrap.Tick, "bootstrap"); RunSafely(_screenEffect.Tick, "screen effect"); RunSafely(_pageWatcher.Tick, "page watcher"); } } public void Dispose() { if (_initialized) { _initialized = false; _screenEffect?.Dispose(); } } private void RegisterAnyExistingNetworkManager() { NetworkManager[] array = Resources.FindObjectsOfTypeAll(); Plugin.Log.LogInfo((object)$"Found {array.Length} NetworkManager object(s) during runtime initialization."); foreach (NetworkManager val in array) { if ((Object)(object)val != (Object)null && val.NetworkConfig?.Prefabs != null && SlenderEnemyRegistry.EnsureRegistered(val)) { break; } } } private void RunSafely(Action action, string operation) { try { action(); } catch (Exception arg) { if (Time.unscaledTime >= _nextRuntimeErrorLog) { _nextRuntimeErrorLog = Time.unscaledTime + 2f; Plugin.Log.LogError((object)$"Slenderman {operation} failed: {arg}"); } } } } internal sealed class SlenderMarker : MonoBehaviour { private readonly List _originalRenderers = new List(); private readonly List _slenderRenderers = new List(); private Transform[] _tentacles = Array.Empty(); private Vector3 _previousPosition; private float _manifestedAt; private float _visibleUntil; private float _nextAppearanceAt; private float _nextContactDamageAt; private float _nextAiDecisionAt; private float _walkPhase; private Random _stalkRandom; private PlayerControllerB _stalkTarget; private bool _isManifested; private bool _wasObservedThisAppearance; private bool _initialized; private bool _ownerAiConfirmed; internal FlowermanAI Ai { get; private set; } internal Vector3 LookTarget => ((Component)this).transform.position + ((Component)this).transform.up * 3.05f; internal bool IsManifested => _isManifested; internal void Initialize(FlowermanAI ai) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!_initialized && !((Object)(object)ai == (Object)null)) { _initialized = true; Ai = ai; _stalkRandom = new Random((int)(((NetworkBehaviour)ai).NetworkObjectId ^ 0x51E7D3A1)); _previousPosition = ((Component)this).transform.position; _nextAppearanceAt = Time.realtimeSinceStartup + (SlenderPageSystem.IsSlendermanAwake ? 0.8f : Mathf.Min(10f, GetAppearanceInterval() * 0.45f)); Renderer[] componentsInChildren = ((Component)ai).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { _originalRenderers.Add(componentsInChildren[i]); componentsInChildren[i].enabled = false; } SlenderVisualFactory.CreateSlenderman(((Component)this).transform, ((Component)this).gameObject.layer, _slenderRenderers, out _tentacles); ScanNodeProperties[] componentsInChildren2 = ((Component)ai).GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren2.Length; j++) { componentsInChildren2[j].headerText = "SLENDERMAN"; componentsInChildren2[j].subText = "NICHT ANSEHEN"; } ((EnemyAI)ai).currentBehaviourStateIndex = 0; ((EnemyAI)ai).movingTowardsTargetPlayer = false; ((EnemyAI)ai).enemyHP = 9999; _isManifested = false; StopAgent(); ForceRendererState(); SilenceVanillaAudio(); SlenderRuntime.Register(this); Plugin.Log.LogInfo((object)$"Separate stalking Slenderman network object {((NetworkBehaviour)ai).NetworkObjectId} initialized."); } } internal void BeforeVanillaUpdate() { if ((Object)(object)Ai == (Object)null) { return; } int currentBehaviourStateIndex = ((EnemyAI)Ai).currentBehaviourStateIndex; _isManifested = currentBehaviourStateIndex != 0; if (_isManifested) { bool flag = currentBehaviourStateIndex == 2; if (((EnemyAI)Ai).isOutside != flag) { ((EnemyAI)Ai).SetEnemyOutside(flag); } } Ai.inKillAnimation = false; Ai.isInAngerMode = false; ((EnemyAI)Ai).movingTowardsTargetPlayer = false; StopAgent(); SilenceVanillaAudio(); } internal void AfterVanillaUpdate() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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_00c6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Ai == (Object)null || ((EnemyAI)Ai).isEnemyDead) { return; } _isManifested = ((EnemyAI)Ai).currentBehaviourStateIndex != 0; PlayerControllerB observer = null; bool observed = _isManifested && SlenderRuntime.IsObservedByAnyPlayer(this, out observer); StopAgent(); if (_isManifested) { PlayerControllerB val = observer ?? ((EnemyAI)Ai).targetPlayer; if ((Object)(object)val != (Object)null) { Vector3 val2 = ((Component)val).transform.position - ((Component)this).transform.position; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude > 0.01f) { ((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, Quaternion.LookRotation(val2), Time.deltaTime * 5f); } } } AnimateVisual(observed); ForceRendererState(); SilenceVanillaAudio(); } internal void RunAIInterval() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)Ai == (Object)null || (Object)(object)singleton == (Object)null || !singleton.IsServer || ((EnemyAI)Ai).isEnemyDead || (Object)(object)StartOfRound.Instance == (Object)null || Time.unscaledTime < _nextAiDecisionAt) { return; } _nextAiDecisionAt = Time.unscaledTime + 0.1f; if (!_ownerAiConfirmed) { _ownerAiConfirmed = true; Plugin.Log.LogInfo((object)$"Stalking AI is active for Slenderman network object {((NetworkBehaviour)Ai).NetworkObjectId}; awake={SlenderPageSystem.IsSlendermanAwake}."); } if (!SlenderPageSystem.IsSlendermanAwake) { if (_isManifested) { SetManifested(manifested: false, ((EnemyAI)Ai).isOutside); } StopAgent(); return; } PlayerControllerB val = ((_isManifested && IsValidTarget(_stalkTarget)) ? _stalkTarget : SelectStalkingTarget()); if ((Object)(object)val == (Object)null) { SetManifested(manifested: false, ((EnemyAI)Ai).isOutside); StopAgent(); return; } ((EnemyAI)Ai).targetPlayer = val; ((EnemyAI)Ai).movingTowardsTargetPlayer = false; StopAgent(); float realtimeSinceStartup = Time.realtimeSinceStartup; if (!_isManifested) { if (realtimeSinceStartup >= _nextAppearanceAt) { AppearBehindTarget(val); } return; } if (SlenderRuntime.IsObservedByAnyPlayer(this, out var _)) { _wasObservedThisAppearance = true; return; } bool flag = SlenderRuntime.IsWithinAnyPlayerView(this, 58f); bool flag2 = _wasObservedThisAppearance && realtimeSinceStartup >= _manifestedAt + 0.75f; bool flag3 = realtimeSinceStartup >= _visibleUntil && !flag; if (flag2 || flag3) { HideAndScheduleNext(val); } } internal void ForceAppearanceForTest(PlayerControllerB target) { if (!((Object)(object)Ai == (Object)null) && !((EnemyAI)Ai).isEnemyDead && IsValidTarget(target) && !((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer) { _nextAppearanceAt = Time.realtimeSinceStartup; AppearBehindTarget(target); } } internal void RuntimeTick() { if (!((Object)(object)Ai == (Object)null) && !((EnemyAI)Ai).isEnemyDead) { BeforeVanillaUpdate(); RunAIInterval(); AfterVanillaUpdate(); } } internal void HandlePlayerCollision(Collider other) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Ai == (Object)null || !_isManifested || Time.realtimeSinceStartup < _manifestedAt + 1.75f || Time.realtimeSinceStartup < _nextContactDamageAt) { return; } PlayerControllerB val = ((EnemyAI)Ai).MeetsStandardPlayerCollisionConditions(other, false, false); if (!((Object)(object)val == (Object)null)) { _nextContactDamageAt = Time.realtimeSinceStartup + 0.8f; int num = Mathf.Clamp(Plugin.ContactDamage.Value, 0, 100); if (num > 0) { Vector3 val2 = ((Component)val).transform.position - ((Component)this).transform.position; Vector3 val3 = ((Vector3)(ref val2)).normalized * 4f; val.DamagePlayer(num, true, true, (CauseOfDeath)4, 0, false, val3); } } } private PlayerControllerB SelectStalkingTarget() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return null; } PlayerControllerB result = null; int num = -1; float num2 = float.MaxValue; foreach (PlayerControllerB val in array) { if (!((Object)(object)val == (Object)null) && val.isPlayerControlled && !val.isPlayerDead) { int collectedPageCount = SlenderPageSystem.GetCollectedPageCount(val); float num3 = Vector3.SqrMagnitude(((Component)val).transform.position - ((Component)this).transform.position); if (collectedPageCount > num || (collectedPageCount == num && num3 < num2)) { result = val; num = collectedPageCount; num2 = num3; } } } return result; } private static bool IsValidTarget(PlayerControllerB player) { if ((Object)(object)player != (Object)null && player.isPlayerControlled) { return !player.isPlayerDead; } return false; } private void AppearBehindTarget(PlayerControllerB target) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0111: 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_0144: Unknown result type (might be due to invalid IL or missing references) bool flag = !target.isInsideFactory; _stalkTarget = target; Vector3 val = FindStalkingPosition(target, flag); WarpTo(val, flag); SetManifested(manifested: true, flag); _manifestedAt = Time.realtimeSinceStartup; _wasObservedThisAppearance = false; float num = SlenderPageSystem.RoundElapsedSeconds / Mathf.Max(20f, Plugin.RoundEscalationSeconds.Value); _visibleUntil = _manifestedAt + Mathf.Clamp(Plugin.AppearanceDuration.Value + (float)SlenderPageSystem.AggressionLevel * 0.12f + num * 0.08f, 1.5f, 12f); FaceTarget(target); ((EnemyAI)Ai).SyncPositionToClients(); int collectedPageCount = SlenderPageSystem.GetCollectedPageCount(target); int num2 = 0; for (int i = 0; i < _slenderRenderers.Count; i++) { if ((Object)(object)_slenderRenderers[i] != (Object)null && _slenderRenderers[i].enabled && !_slenderRenderers[i].forceRenderingOff) { num2++; } } float num3 = Vector3.Distance(((Component)target).transform.position, ((Component)this).transform.position); Plugin.Log.LogInfo((object)$"Slenderman appeared behind '{target.playerUsername}' at {val}; outside={flag}, distance={num3:F1}m, renderers={num2}/{_slenderRenderers.Count}, layer={((Component)this).gameObject.layer}, collector pages={collectedPageCount}, aggression={SlenderPageSystem.AggressionLevel}/11."); } private void HideAndScheduleNext(PlayerControllerB target) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0070: 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_0080: 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_00a2: Unknown result type (might be due to invalid IL or missing references) bool flag = !target.isInsideFactory; _stalkTarget = null; SetManifested(manifested: false, flag); GameObject[] array = ((!flag) ? RoundManager.Instance?.insideAINodes : RoundManager.Instance?.outsideAINodes); Vector3 position = ((Component)this).transform.position; float num = -1f; if (array != null) { for (int i = 0; i < array.Length; i++) { if (!((Object)(object)array[i] == (Object)null)) { float num2 = Vector3.SqrMagnitude(array[i].transform.position - ((Component)target).transform.position); if (num2 > num) { num = num2; position = array[i].transform.position; } } } } WarpTo(position, flag); ((EnemyAI)Ai).SyncPositionToClients(); float num3 = Mathf.Lerp(0.85f, 1.15f, (float)_stalkRandom.NextDouble()); _nextAppearanceAt = Time.realtimeSinceStartup + GetAppearanceInterval() * num3; Plugin.Log.LogDebug((object)$"Slenderman vanished; next stalking window in {_nextAppearanceAt - Time.realtimeSinceStartup:F1}s."); } private Vector3 FindStalkingPosition(PlayerControllerB target, bool outside) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0111: 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_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) Transform val = (((Object)(object)target.playerEye != (Object)null) ? target.playerEye : ((Component)target).transform); Vector3 val2 = Vector3.ProjectOnPlane(val.forward, Vector3.up); Vector3 normalized = ((Vector3)(ref val2)).normalized; if (((Vector3)(ref normalized)).sqrMagnitude < 0.01f) { val2 = Vector3.ProjectOnPlane(((Component)target).transform.forward, Vector3.up); normalized = ((Vector3)(ref val2)).normalized; } float num = Mathf.Max(8f, Plugin.MinimumStalkingDistance.Value); float num2 = Mathf.Max(num + 1f, Plugin.MaximumStalkingDistance.Value); NavMeshHit val5 = default(NavMeshHit); for (int i = 0; i < 10; i++) { float num3 = Mathf.Lerp(-38f, 38f, (float)_stalkRandom.NextDouble()); Vector3 val3 = Quaternion.AngleAxis(num3, Vector3.up) * -normalized; float num4 = Mathf.Lerp(num, num2, (float)_stalkRandom.NextDouble()); Vector3 val4 = ((Component)target).transform.position + val3 * num4; if (NavMesh.SamplePosition(val4, ref val5, 7f, -1) && Vector3.Distance(((NavMeshHit)(ref val5)).position, ((Component)target).transform.position) >= num * 0.72f) { return ((NavMeshHit)(ref val5)).position; } } GameObject[] array = ((!outside) ? RoundManager.Instance?.insideAINodes : RoundManager.Instance?.outsideAINodes); if (array != null && array.Length != 0) { GameObject val6 = null; float num5 = float.MaxValue; Vector3 val7 = ((Component)target).transform.position - normalized * num; for (int j = 0; j < array.Length; j++) { if ((Object)(object)array[j] == (Object)null) { continue; } float num6 = Vector3.Distance(array[j].transform.position, ((Component)target).transform.position); if (!(num6 < num * 0.65f)) { float num7 = Vector3.SqrMagnitude(array[j].transform.position - val7); if (num7 < num5) { val6 = array[j]; num5 = num7; } } } if ((Object)(object)val6 != (Object)null) { return val6.transform.position; } } return ((Component)target).transform.position - normalized * num; } private void WarpTo(Vector3 position, bool outside) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) ((EnemyAI)Ai).SetEnemyOutside(outside); if ((Object)(object)((EnemyAI)Ai).agent != (Object)null && ((Behaviour)((EnemyAI)Ai).agent).enabled && ((EnemyAI)Ai).agent.isOnNavMesh) { if (!((EnemyAI)Ai).agent.Warp(position)) { ((Behaviour)((EnemyAI)Ai).agent).enabled = false; ((Component)this).transform.position = position; ((Behaviour)((EnemyAI)Ai).agent).enabled = true; } } else { ((Component)this).transform.position = position; } ((EnemyAI)Ai).serverPosition = ((Component)this).transform.position - Vector3.one * 100f; } private void SetManifested(bool manifested, bool outside) { _isManifested = manifested; int num = (manifested ? ((!outside) ? 1 : 2) : 0); if (((EnemyAI)Ai).currentBehaviourStateIndex != num) { ((EnemyAI)Ai).SwitchToBehaviourState(num); } ForceRendererState(); } private float GetAppearanceInterval() { float num = Mathf.Max(8f, Plugin.BaseAppearanceInterval.Value); float num2 = Mathf.Clamp(Plugin.MinimumAppearanceInterval.Value, 2f, num); float num3 = SlenderPageSystem.RoundElapsedSeconds / Mathf.Max(20f, Plugin.RoundEscalationSeconds.Value); float num4 = (float)SlenderPageSystem.AggressionLevel * 1.45f + num3 * 1.6f; return Mathf.Clamp(num - num4, num2, num); } private void FaceTarget(PlayerControllerB target) { //IL_0010: 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_0020: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null)) { Vector3 val = ((Component)target).transform.position - ((Component)this).transform.position; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude > 0.01f) { ((Component)this).transform.rotation = Quaternion.LookRotation(val); } } } private void StopAgent() { //IL_006a: 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) if (!((Object)(object)((EnemyAI)Ai).agent == (Object)null) && ((Behaviour)((EnemyAI)Ai).agent).enabled && ((EnemyAI)Ai).agent.isOnNavMesh) { ((EnemyAI)Ai).agent.speed = 0f; ((EnemyAI)Ai).agent.isStopped = true; ((EnemyAI)Ai).destination = ((Component)this).transform.position; } } private void AnimateVisual(bool observed) { //IL_0006: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) float num = Vector3.Distance(((Component)this).transform.position, _previousPosition) / Mathf.Max(Time.deltaTime, 0.001f); _previousPosition = ((Component)this).transform.position; _walkPhase += Time.deltaTime * Mathf.Clamp(num * 1.2f, 0.25f, 8f); for (int i = 0; i < _tentacles.Length; i++) { Transform val = _tentacles[i]; if (!((Object)(object)val == (Object)null)) { float num2 = (observed ? 2.5f : (11f + (float)SlenderPageSystem.AggressionLevel * 0.6f)); Vector3 localEulerAngles = val.localEulerAngles; localEulerAngles.z += Mathf.Sin(_walkPhase * 0.8f + (float)i * 1.7f) * num2 * Time.deltaTime; localEulerAngles.x += Mathf.Cos(_walkPhase * 0.65f + (float)i) * num2 * 0.55f * Time.deltaTime; val.localEulerAngles = localEulerAngles; } } } private void ForceRendererState() { for (int i = 0; i < _originalRenderers.Count; i++) { if ((Object)(object)_originalRenderers[i] != (Object)null) { _originalRenderers[i].enabled = false; } } for (int j = 0; j < _slenderRenderers.Count; j++) { if ((Object)(object)_slenderRenderers[j] != (Object)null) { if (!((Component)_slenderRenderers[j]).gameObject.activeSelf) { ((Component)_slenderRenderers[j]).gameObject.SetActive(true); } _slenderRenderers[j].forceRenderingOff = false; _slenderRenderers[j].enabled = _isManifested; } } } private void SilenceVanillaAudio() { if (!((Object)(object)Ai == (Object)null)) { if ((Object)(object)((EnemyAI)Ai).creatureVoice != (Object)null) { ((EnemyAI)Ai).creatureVoice.volume = 0f; } if ((Object)(object)((EnemyAI)Ai).creatureSFX != (Object)null) { ((EnemyAI)Ai).creatureSFX.volume = 0f; } if ((Object)(object)Ai.creatureAngerVoice != (Object)null) { Ai.creatureAngerVoice.volume = 0f; } } } private void OnDestroy() { SlenderRuntime.Unregister(this); } } internal static class SlenderModelLoader { private readonly struct VertexKey : IEquatable { internal readonly int Vertex; internal readonly int Uv; internal readonly int Normal; internal VertexKey(int vertex, int uv, int normal) { Vertex = vertex; Uv = uv; Normal = normal; } public bool Equals(VertexKey other) { if (Vertex == other.Vertex && Uv == other.Uv) { return Normal == other.Normal; } return false; } public override bool Equals(object obj) { if (obj is VertexKey other) { return Equals(other); } return false; } public override int GetHashCode() { int vertex = Vertex; vertex = (vertex * 397) ^ Uv; return (vertex * 397) ^ Normal; } } private const string ResourcePrefix = "SlendermanMod.Assets."; private static Mesh _mesh; private static Material _clothingMaterial; private static Material _skinMaterial; private static readonly List Textures = new List(); internal static bool TryCreate(Transform parent, int layer, List renderers) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0058: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) try { EnsureLoaded(); if ((Object)(object)_mesh == (Object)null || (Object)(object)_clothingMaterial == (Object)null || (Object)(object)_skinMaterial == (Object)null) { return false; } GameObject val = new GameObject("RepromancerSlendermanVisual"); val.layer = layer; val.transform.SetParent(parent, false); val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.Euler(0f, 180f, 0f); val.transform.localScale = Vector3.one * 1.52f; MeshFilter val2 = val.AddComponent(); val2.sharedMesh = _mesh; MeshRenderer val3 = val.AddComponent(); ((Renderer)val3).sharedMaterials = (Material[])(object)new Material[2] { _clothingMaterial, _skinMaterial }; ((Renderer)val3).shadowCastingMode = (ShadowCastingMode)1; ((Renderer)val3).receiveShadows = true; renderers?.Add((Renderer)(object)val3); return true; } catch (Exception arg) { Plugin.Log.LogError((object)$"Could not create the embedded Slenderman model; using fallback visuals: {arg}"); return false; } } private static void EnsureLoaded() { if (!((Object)(object)_mesh != (Object)null)) { _mesh = LoadObj("repromancer_slender_man_model.obj"); Texture2D baseColor = LoadTexture("slender_clothing_basecolor.jpg", linear: false); Texture2D normal = LoadTexture("slender_clothing_normal.jpg", linear: true); Texture2D baseColor2 = LoadTexture("slender_skin_basecolor.jpg", linear: false); Texture2D normal2 = LoadTexture("slender_skin_normal.jpg", linear: true); _clothingMaterial = CreateMaterial("SlendermanClothing", baseColor, normal, 0.08f, 0.28f); _skinMaterial = CreateMaterial("SlendermanSkin", baseColor2, normal2, 0f, 0.18f); Plugin.Log.LogInfo((object)$"Loaded embedded Repromancer Slenderman model with {_mesh.vertexCount} vertices."); } } private static Mesh LoadObj(string resourceName) { //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) using Stream stream = OpenResource(resourceName); using StreamReader streamReader = new StreamReader(stream); List list = new List(); List list2 = new List(); List list3 = new List(); List list4 = new List(); List list5 = new List(); List list6 = new List(); List[] array = new List[2] { new List(), new List() }; Dictionary dictionary = new Dictionary(); int num = 0; bool flag = false; while (!streamReader.EndOfStream) { string text = streamReader.ReadLine(); if (string.IsNullOrWhiteSpace(text) || text[0] == '#') { continue; } if (text.StartsWith("v ", StringComparison.Ordinal)) { string[] array2 = Split(text); list.Add(new Vector3(ParseFloat(array2[1]), ParseFloat(array2[2]), 0f - ParseFloat(array2[3]))); } else if (text.StartsWith("vt ", StringComparison.Ordinal)) { string[] array3 = Split(text); list2.Add(new Vector2(ParseFloat(array3[1]), ParseFloat(array3[2]))); } else if (text.StartsWith("vn ", StringComparison.Ordinal)) { string[] array4 = Split(text); Vector3 val = new Vector3(ParseFloat(array4[1]), ParseFloat(array4[2]), 0f - ParseFloat(array4[3])); list3.Add(((Vector3)(ref val)).normalized); } else if (text.StartsWith("g ", StringComparison.Ordinal)) { num = ((text.IndexOf("skin", StringComparison.OrdinalIgnoreCase) >= 0) ? 1 : 0); } else { if (!text.StartsWith("f ", StringComparison.Ordinal)) { continue; } string[] array5 = Split(text); if (array5.Length < 4) { continue; } int[] array6 = new int[array5.Length - 1]; for (int i = 1; i < array5.Length; i++) { VertexKey key = ParseKey(array5[i], list.Count, list2.Count, list3.Count); if (!dictionary.TryGetValue(key, out var value)) { value = list4.Count; dictionary.Add(key, value); list4.Add(list[key.Vertex]); list5.Add((key.Uv >= 0) ? list2[key.Uv] : Vector2.zero); if (key.Normal >= 0) { list6.Add(list3[key.Normal]); } else { list6.Add(Vector3.up); flag = true; } } array6[i - 1] = value; } for (int j = 1; j < array6.Length - 1; j++) { array[num].Add(array6[0]); array[num].Add(array6[j + 1]); array[num].Add(array6[j]); } } } Mesh val2 = new Mesh { name = "RepromancerSlendermanMesh", indexFormat = (IndexFormat)(list4.Count > 65535), subMeshCount = 2 }; val2.SetVertices(list4); val2.SetUVs(0, list5); val2.SetNormals(list6); val2.SetTriangles(array[0], 0, true); val2.SetTriangles(array[1], 1, true); if (flag) { val2.RecalculateNormals(); } val2.RecalculateBounds(); try { val2.RecalculateTangents(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not calculate model tangents: " + ex.Message)); } return val2; } private static Texture2D LoadTexture(string resourceName, bool linear) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown using Stream stream = OpenResource(resourceName); byte[] array = new byte[stream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = stream.Read(array, i, array.Length - i); if (num <= 0) { break; } } Texture2D val = new Texture2D(2, 2, (TextureFormat)3, true, linear) { name = resourceName, wrapMode = (TextureWrapMode)0, filterMode = (FilterMode)1, anisoLevel = 4 }; if (!ImageConversion.LoadImage(val, array, true)) { Object.Destroy((Object)(object)val); throw new InvalidDataException("Texture resource '" + resourceName + "' could not be decoded."); } Textures.Add(val); return val; } private static Material CreateMaterial(string name, Texture2D baseColor, Texture2D normal, float metallic, float smoothness) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown Shader val = Shader.Find("HDRP/Lit") ?? Shader.Find("Standard") ?? Shader.Find("Legacy Shaders/Diffuse"); Material val2 = new Material(val) { name = name }; if (val2.HasProperty("_BaseColorMap")) { val2.SetTexture("_BaseColorMap", (Texture)(object)baseColor); } if (val2.HasProperty("_MainTex")) { val2.SetTexture("_MainTex", (Texture)(object)baseColor); } if (val2.HasProperty("_NormalMap")) { val2.SetTexture("_NormalMap", (Texture)(object)normal); val2.SetFloat("_NormalScale", 1f); val2.EnableKeyword("_NORMALMAP_TANGENT_SPACE"); } if (val2.HasProperty("_BumpMap")) { val2.SetTexture("_BumpMap", (Texture)(object)normal); val2.SetFloat("_BumpScale", 1f); val2.EnableKeyword("_NORMALMAP"); } if (val2.HasProperty("_Metallic")) { val2.SetFloat("_Metallic", metallic); } if (val2.HasProperty("_Smoothness")) { val2.SetFloat("_Smoothness", smoothness); } if (val2.HasProperty("_DoubleSidedEnable")) { val2.SetFloat("_DoubleSidedEnable", 1f); } if (val2.HasProperty("_CullMode")) { val2.SetFloat("_CullMode", 0f); } if (val2.HasProperty("_CullModeForward")) { val2.SetFloat("_CullModeForward", 0f); } return val2; } private static Stream OpenResource(string name) { Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SlendermanMod.Assets." + name); return manifestResourceStream ?? throw new FileNotFoundException("Embedded Slenderman resource '" + name + "' was not found."); } private static string[] Split(string line) { return line.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); } private static float ParseFloat(string value) { return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); } private static VertexKey ParseKey(string value, int vertexCount, int uvCount, int normalCount) { string[] array = value.Split('/'); int vertex = ParseIndex(array[0], vertexCount); int uv = ((array.Length > 1 && array[1].Length > 0) ? ParseIndex(array[1], uvCount) : (-1)); int normal = ((array.Length > 2 && array[2].Length > 0) ? ParseIndex(array[2], normalCount) : (-1)); return new VertexKey(vertex, uv, normal); } private static int ParseIndex(string value, int count) { int num = int.Parse(value, CultureInfo.InvariantCulture); if (num <= 0) { return count + num; } return num - 1; } } internal static class SlenderPageSystem { private static readonly HashSet CollectedPages = new HashSet(); private static readonly Dictionary CollectorPageCounts = new Dictionary(); private static bool _landingClockCaptured; private static float _landingDayTime; private static bool _awakened; private static bool _testAwake; internal static int AggressionLevel { get; private set; } internal static bool PagesSpawned { get; private set; } internal static float RoundStartedAt { get; private set; } internal static float RoundElapsedSeconds => Mathf.Max(0f, Time.realtimeSinceStartup - RoundStartedAt); internal static bool IsSlendermanAwake { get { UpdateWakeState(); return _awakened; } } internal static void ResetRound() { CollectedPages.Clear(); CollectorPageCounts.Clear(); AggressionLevel = 0; PagesSpawned = false; RoundStartedAt = Time.realtimeSinceStartup; _landingClockCaptured = false; _landingDayTime = 0f; _awakened = false; _testAwake = false; SlenderScreenEffect.ResetEffect(); } internal static void SpawnPages(RoundManager roundManager) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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_017e: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) if (PagesSpawned || (Object)(object)roundManager == (Object)null || !((NetworkBehaviour)roundManager).IsServer || (Object)(object)SlenderEnemyRegistry.PagePrefab == (Object)null) { return; } int num = Mathf.Clamp(Plugin.PagesPerRound.Value, 0, 11); if (num == 0) { return; } RandomScrapSpawn[] array = Object.FindObjectsOfType(); if (array == null || array.Length == 0) { Plugin.Log.LogWarning((object)"No scrap spawn points were available for Slender pages."); return; } List list = new List(num); int[] array2 = new int[num]; for (int i = 0; i < num; i++) { RandomScrapSpawn val = array[roundManager.AnomalyRandom.Next(0, array.Length)]; Vector3 val2 = ((!val.spawnedItemsCopyPosition) ? (roundManager.GetRandomNavMeshPositionInBoxPredictable(((Component)val).transform.position, val.itemSpawnRange, roundManager.navHit, roundManager.AnomalyRandom, -8193, 1f) + Vector3.up * SlenderEnemyRegistry.PageItem.verticalOffset) : (((Object)(object)val.spawnWithParent != (Object)null) ? val.spawnWithParent.position : ((Component)val).transform.position)); GameObject val3 = Object.Instantiate(SlenderEnemyRegistry.PagePrefab, val2, Quaternion.identity); GrabbableObject component = val3.GetComponent(); component.scrapValue = Plugin.PageValue.Value; component.fallTime = 0f; ((Component)component).transform.rotation = Quaternion.Euler(component.itemProperties.restingRotation); NetworkObject component2 = val3.GetComponent(); component2.Spawn(true); component.SetScrapValue(Plugin.PageValue.Value); list.Add(NetworkObjectReference.op_Implicit(component2)); array2[i] = Plugin.PageValue.Value; } roundManager.SyncScrapValuesClientRpc(list.ToArray(), array2); RecalculateTotalScrapValue(roundManager); PagesSpawned = true; Plugin.Log.LogInfo((object)$"Spawned {num} Slender pages worth {Plugin.PageValue.Value} credits each."); } internal static void PreparePage(GameObject pageObject) { if (!((Object)(object)pageObject == (Object)null) && !((Object)(object)pageObject.GetComponent() == (Object)null)) { GrabbableObject component = pageObject.GetComponent(); if (!((Object)(object)component == (Object)null)) { SlenderPageMarker slenderPageMarker = pageObject.GetComponent() ?? pageObject.AddComponent(); slenderPageMarker.Initialize(component); } } } internal static void OnPageEquipped(GrabbableObject page) { if ((Object)(object)page == (Object)null || (Object)(object)((Component)page).GetComponent() == (Object)null || (Object)(object)((NetworkBehaviour)page).NetworkObject == (Object)null) { return; } PlayerControllerB playerHeldBy = page.playerHeldBy; if ((Object)(object)playerHeldBy == (Object)null) { return; } ulong networkObjectId = ((NetworkBehaviour)page).NetworkObjectId; if (CollectedPages.Add(networkObjectId)) { AggressionLevel = Mathf.Clamp(AggressionLevel + 1, 0, 11); Awaken("the first Slender page was collected"); ulong playerClientId = playerHeldBy.playerClientId; CollectorPageCounts.TryGetValue(playerClientId, out var value); CollectorPageCounts[playerClientId] = value + 1; Plugin.Log.LogInfo((object)$"Slender page collected by '{playerHeldBy.playerUsername}'. Aggression is now {AggressionLevel}/11; collector has {value + 1}."); PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null && (Object)(object)page.playerHeldBy == (Object)(object)val && (Object)(object)HUDManager.Instance != (Object)null) { HUDManager.Instance.DisplayTip($"SLENDER-ZETTEL {AggressionLevel}/11", "Er ist schneller geworden. Sieh ihn nicht zu lange an!", true, false, "LC_Tip1"); } } } internal static int GetCollectedPageCount(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return 0; } if (!CollectorPageCounts.TryGetValue(player.playerClientId, out var value)) { return 0; } return value; } internal static void ForceAwakeForTesting() { _testAwake = true; Awaken("the F7 test spawn was requested"); } private static void UpdateWakeState() { if (_awakened) { return; } if (_testAwake || AggressionLevel > 0) { Awaken(_testAwake ? "testing is active" : "a Slender page was collected"); return; } StartOfRound instance = StartOfRound.Instance; TimeOfDay instance2 = TimeOfDay.Instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance2 == (Object)null) && !instance.inShipPhase && instance.shipHasLanded && instance2.timeHasStarted) { if (!_landingClockCaptured) { _landingClockCaptured = true; _landingDayTime = instance2.currentDayTime; Plugin.Log.LogInfo((object)$"Slenderman wake timer started after landing at in-game hour {instance2.hour}; delay is {Plugin.WakeUpDelayHours.Value:F1} hours."); } float num = Mathf.Max(1f, instance2.lengthOfHours); float num2 = num * Mathf.Max(0f, Plugin.WakeUpDelayHours.Value); if (instance2.currentDayTime - _landingDayTime >= num2) { Awaken($"{Plugin.WakeUpDelayHours.Value:F1} in-game hours passed after landing"); } } } private static void Awaken(string reason) { if (!_awakened) { _awakened = true; Plugin.Log.LogInfo((object)("Slenderman is now awake because " + reason + ".")); } } internal static void RecalculateTotalScrapValue(RoundManager roundManager) { if ((Object)(object)roundManager == (Object)null) { return; } GrabbableObject[] array = Object.FindObjectsOfType(); int num = 0; foreach (GrabbableObject val in array) { if ((Object)(object)val != (Object)null && !val.deactivated && !val.scrapPersistedThroughRounds && (Object)(object)val.itemProperties != (Object)null && val.itemProperties.isScrap) { num += Mathf.Max(0, val.scrapValue); } } roundManager.totalScrapValueInLevel = num; } } internal sealed class SlenderPageMarker : MonoBehaviour { private readonly List _originalRenderers = new List(); private readonly List _pageRenderers = new List(); private GrabbableObject _page; private bool _initialized; internal void Initialize(GrabbableObject page) { if (!_initialized && !((Object)(object)page == (Object)null)) { _initialized = true; _page = page; Renderer[] componentsInChildren = ((Component)page).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { _originalRenderers.Add(componentsInChildren[i]); componentsInChildren[i].enabled = false; } int num = ((!((Object)(object)((NetworkBehaviour)page).NetworkObject != (Object)null) || !((NetworkBehaviour)page).NetworkObject.IsSpawned) ? 1 : ((int)(((NetworkBehaviour)page).NetworkObjectId % 11) + 1)); SlenderVisualFactory.CreatePage(((Component)this).transform, ((Component)this).gameObject.layer, num, _pageRenderers); ScanNodeProperties[] componentsInChildren2 = ((Component)page).GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren2.Length; j++) { componentsInChildren2[j].headerText = $"SLENDER-ZETTEL {num}/11"; componentsInChildren2[j].subText = $"Wert: {page.scrapValue}"; } page.customGrabTooltip = "Slender-Zettel nehmen"; } } private void LateUpdate() { if ((Object)(object)_page == (Object)null) { return; } for (int i = 0; i < _originalRenderers.Count; i++) { if ((Object)(object)_originalRenderers[i] != (Object)null) { _originalRenderers[i].enabled = false; } } bool enabled = !_page.isPocketed && !_page.deactivated; for (int j = 0; j < _pageRenderers.Count; j++) { if ((Object)(object)_pageRenderers[j] != (Object)null) { _pageRenderers[j].enabled = enabled; } } } } internal sealed class SlenderPageWatcher { private float _nextRefresh; internal void Tick() { if (Time.unscaledTime < _nextRefresh) { return; } _nextRefresh = Time.unscaledTime + 0.25f; SlenderPageIdentity[] array = Object.FindObjectsOfType(); for (int i = 0; i < array.Length; i++) { GameObject gameObject = ((Component)array[i]).gameObject; SlenderPageSystem.PreparePage(gameObject); GrabbableObject component = gameObject.GetComponent(); if ((Object)(object)component != (Object)null && (component.isHeld || component.isPocketed || (Object)(object)component.playerHeldBy != (Object)null)) { SlenderPageSystem.OnPageEquipped(component); } } } } [HarmonyPatch] internal static class SlenderPatches { [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "Start")] private static void RegisterNetworkPrefabs() { SlenderEnemyRegistry.EnsureRegistered(); } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "Start")] private static void AddSlendermanToKnownLevels(StartOfRound __instance) { if (SlenderEnemyRegistry.EnsureRegistered() && __instance.levels != null) { for (int i = 0; i < __instance.levels.Length; i++) { SlenderRuntime.AdjustSpawnList(__instance.levels[i]); } } } [HarmonyPrefix] [HarmonyPatch(typeof(RoundManager), "LoadNewLevel")] private static void PrepareLevel(SelectableLevel newLevel) { SlenderPageSystem.ResetRound(); if (SlenderEnemyRegistry.EnsureRegistered()) { SlenderRuntime.AdjustSpawnList(newLevel); } } [HarmonyPrefix] [HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")] private static void ResetClientRound() { SlenderPageSystem.ResetRound(); } [HarmonyPostfix] [HarmonyPatch(typeof(FlowermanAI), "Start")] private static void InitializeSlenderman(FlowermanAI __instance) { SlenderRuntime.EnsureInitialized(__instance); } [HarmonyPrefix] [HarmonyPatch(typeof(FlowermanAI), "Update")] private static bool UpdateSlenderman(FlowermanAI __instance) { SlenderMarker component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } component.BeforeVanillaUpdate(); EnemyAiBaseUpdate((EnemyAI)(object)__instance); component.AfterVanillaUpdate(); return false; } [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch(typeof(EnemyAI), "Update")] private static void EnemyAiBaseUpdate(EnemyAI instance) { throw new NotImplementedException("Harmony reverse patch was not applied."); } [HarmonyPrefix] [HarmonyPatch(typeof(FlowermanAI), "DoAIInterval")] private static bool RunSlendermanAi(FlowermanAI __instance) { SlenderMarker component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } component.RunAIInterval(); return false; } [HarmonyPrefix] [HarmonyPatch(typeof(FlowermanAI), "OnCollideWithPlayer")] private static bool HandleSlendermanCollision(FlowermanAI __instance, Collider other) { SlenderMarker component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } component.HandlePlayerCollision(other); return false; } [HarmonyPrefix] [HarmonyPatch(typeof(FlowermanAI), "HitEnemy")] private static bool HandleSlendermanHit(FlowermanAI __instance) { if (!((Object)(object)((Component)__instance).GetComponent() == (Object)null)) { return !Plugin.Invulnerable.Value; } return true; } [HarmonyPrefix] [HarmonyPatch(typeof(FlowermanAI), "LookAtFlowermanTrigger")] private static bool DisableBrackenLookLogicForSlenderman(FlowermanAI __instance) { return (Object)(object)((Component)__instance).GetComponent() == (Object)null; } [HarmonyPrefix] [HarmonyPatch(typeof(FlowermanAI), "AddToAngerMeter")] private static bool DisableBrackenAngerForSlenderman(FlowermanAI __instance) { return (Object)(object)((Component)__instance).GetComponent() == (Object)null; } [HarmonyPrefix] [HarmonyPatch(typeof(NetworkObject), "Spawn", new Type[] { typeof(bool) })] private static void ActivateRuntimePrefabInstance(NetworkObject __instance) { FlowermanAI component = ((Component)__instance).GetComponent(); if (!((Component)__instance).gameObject.activeSelf && ((Object)(object)((Component)__instance).GetComponent() != (Object)null || (Object)(object)((Component)__instance).GetComponent() != (Object)null || SlenderEnemyRegistry.IsSlendermanInstance((EnemyAI)(object)component))) { ((Component)__instance).gameObject.SetActive(true); } } [HarmonyPostfix] [HarmonyPatch(typeof(RoundManager), "SyncScrapValuesClientRpc")] private static void IncludePagesInScrapTotal(RoundManager __instance) { SlenderPageSystem.RecalculateTotalScrapValue(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(GrabbableObject), "Start")] private static void PrepareSpawnedPage(GrabbableObject __instance) { if ((Object)(object)((Component)__instance).GetComponent() != (Object)null) { SlenderPageSystem.PreparePage(((Component)__instance).gameObject); } } [HarmonyPostfix] [HarmonyPatch(typeof(GrabbableObject), "EquipItem")] private static void CollectSlenderPage(GrabbableObject __instance) { SlenderPageSystem.OnPageEquipped(__instance); } } internal static class SlenderRuntime { internal static readonly List Active = new List(); internal static float CurrentStareKillSeconds => Mathf.Max(1.5f, Plugin.BaseStareKillSeconds.Value - Plugin.StareKillReductionPerPage.Value * (float)SlenderPageSystem.AggressionLevel); internal static void Register(SlenderMarker marker) { Cleanup(); if (!Active.Contains(marker)) { Active.Add(marker); } } internal static SlenderMarker EnsureInitialized(FlowermanAI ai) { if (!SlenderEnemyRegistry.IsSlendermanInstance((EnemyAI)(object)ai)) { return null; } return ForceInitialize(ai); } internal static SlenderMarker ForceInitialize(FlowermanAI ai) { if ((Object)(object)ai == (Object)null) { return null; } if (!((Component)ai).gameObject.activeSelf) { ((Component)ai).gameObject.SetActive(true); } if ((Object)(object)((Component)ai).GetComponent() == (Object)null) { ((Component)ai).gameObject.AddComponent(); } SlenderMarker slenderMarker = ((Component)ai).GetComponent() ?? ((Component)ai).gameObject.AddComponent(); slenderMarker.Initialize(ai); return slenderMarker; } internal static void Unregister(SlenderMarker marker) { Active.Remove(marker); } internal static void Cleanup() { for (int num = Active.Count - 1; num >= 0; num--) { if ((Object)(object)Active[num] == (Object)null) { Active.RemoveAt(num); } } } internal static void TickAll() { Cleanup(); for (int num = Active.Count - 1; num >= 0; num--) { SlenderMarker slenderMarker = Active[num]; if ((Object)(object)slenderMarker != (Object)null) { slenderMarker.RuntimeTick(); } } } internal static bool TryGetLookedAtSlender(PlayerControllerB player, out SlenderMarker marker) { marker = null; if ((Object)(object)player == (Object)null || player.isPlayerDead || !player.isPlayerControlled) { return false; } Cleanup(); float num = -1f; for (int i = 0; i < Active.Count; i++) { SlenderMarker slenderMarker = Active[i]; if (!((Object)(object)slenderMarker == (Object)null) && slenderMarker.IsManifested && !((Object)(object)slenderMarker.Ai == (Object)null) && !((EnemyAI)slenderMarker.Ai).isEnemyDead && IsPlayerLookingAt(player, slenderMarker, out var dot) && dot > num) { num = dot; marker = slenderMarker; } } return (Object)(object)marker != (Object)null; } internal static bool IsObservedByAnyPlayer(SlenderMarker marker, out PlayerControllerB observer) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) observer = null; if ((Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayerScripts == null) { return false; } float num = float.MaxValue; PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (!((Object)(object)val == (Object)null) && !val.isPlayerDead && val.isPlayerControlled && IsPlayerLookingAt(val, marker, out var _)) { float num2 = Vector3.Distance(((Component)val).transform.position, ((Component)marker).transform.position); if (num2 < num) { num = num2; observer = val; } } } return (Object)(object)observer != (Object)null; } private static bool IsPlayerLookingAt(PlayerControllerB player, SlenderMarker marker, out float dot) { return IsPlayerLookingAt(player, marker, Plugin.GazeAngle.Value, out dot); } internal static bool IsWithinPlayerView(PlayerControllerB player, SlenderMarker marker, float halfAngle) { float dot; return IsPlayerLookingAt(player, marker, halfAngle, out dot); } internal static bool IsWithinAnyPlayerView(SlenderMarker marker, float halfAngle) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return false; } foreach (PlayerControllerB val in array) { if ((Object)(object)val != (Object)null && val.isPlayerControlled && !val.isPlayerDead && IsPlayerLookingAt(val, marker, halfAngle, out var _)) { return true; } } return false; } private static bool IsPlayerLookingAt(PlayerControllerB player, SlenderMarker marker, float halfAngle, out float dot) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_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_0057: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) dot = -1f; object obj; if (!((Object)(object)player.playerEye != (Object)null)) { Camera gameplayCamera = player.gameplayCamera; obj = ((gameplayCamera != null) ? ((Component)gameplayCamera).transform : null); } else { obj = player.playerEye; } Transform val = (Transform)obj; if ((Object)(object)val == (Object)null || (Object)(object)marker == (Object)null) { return false; } Vector3 lookTarget = marker.LookTarget; Vector3 val2 = lookTarget - val.position; float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude < 0.01f || magnitude > Plugin.GazeRange.Value) { return false; } Vector3 val3 = val2 / magnitude; dot = Vector3.Dot(val.forward, val3); float num = Mathf.Cos(Mathf.Clamp(halfAngle, 1f, 89f) * (MathF.PI / 180f)); if (dot < num) { return false; } if ((Object)(object)StartOfRound.Instance == (Object)null) { return true; } int collidersAndRoomMaskAndDefault = StartOfRound.Instance.collidersAndRoomMaskAndDefault; RaycastHit val4 = default(RaycastHit); if (Physics.Linecast(val.position, lookTarget, ref val4, collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1)) { Transform transform = ((RaycastHit)(ref val4)).transform; if ((Object)(object)transform != (Object)null) { if (!((Object)(object)transform == (Object)(object)((Component)marker).transform)) { return transform.IsChildOf(((Component)marker).transform); } return true; } return false; } return true; } internal static void AdjustSpawnList(SelectableLevel level) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown if ((Object)(object)level == (Object)null || level.Enemies == null) { return; } EnemyType slender = SlenderEnemyRegistry.SlenderEnemyType; if ((Object)(object)slender == (Object)null) { Plugin.Log.LogWarning((object)("Slenderman could not be added to moon '" + level.PlanetName + "' because its prefab was not registered.")); return; } slender.MaxCount = Mathf.Clamp(Plugin.MaxSlendermen.Value, 1, 5); slender.canDie = !Plugin.Invulnerable.Value; int num = Mathf.Clamp(Plugin.SpawnRarity.Value, 0, 200); SpawnableEnemyWithRarity val = level.Enemies.Find((SpawnableEnemyWithRarity entry) => entry != null && (Object)(object)entry.enemyType == (Object)(object)slender); if (val == null) { level.Enemies.Add(new SpawnableEnemyWithRarity(slender, num)); Plugin.Log.LogDebug((object)$"Added separate Slenderman spawn to moon '{level.PlanetName}' with rarity {num}."); } else { val.rarity = num; } } } internal sealed class SlenderScreenEffect { private const int NoiseWidth = 160; private const int NoiseHeight = 90; private const int GlitchBarCount = 14; private static SlenderScreenEffect _instance; private readonly Random _noiseRandom = new Random(); private Texture2D _noiseTexture; private Color32[] _noisePixels; private GameObject _hudVisualRoot; private GameObject _hudContainer; private RawImage _hudOverlay; private RawImage[] _hudGlitchBars; private AudioSource _gazeAudio; private SlenderAudioAssets _audioAssets; private GameObject _deathCloseup; private Light _deathCloseupLight; private Vector3 _deathCloseupBasePosition; private float _stareProgress; private float _nextNoiseUpdate; private float _nextGlitchUpdate; private float _deathSequenceEndsAt; private bool _deathSequenceActive; private bool _killedByStare; private bool _wasLooking; internal static void ResetEffect() { if (_instance != null) { _instance.ResetInternal(); } } internal SlenderScreenEffect() { //IL_0021: 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_0031: 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) //IL_0044: Expected O, but got Unknown _instance = this; _noiseTexture = new Texture2D(160, 90, (TextureFormat)4, false) { name = "SlendermanStatic", filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)0 }; _noisePixels = (Color32[])(object)new Color32[14400]; _audioAssets = new SlenderAudioAssets(); _audioAssets.BeginLoad(); } internal void Tick() { _audioAssets?.Tick(); EnsureHudIntegration(); AdoptLoadedAudioClips(); PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (_deathSequenceActive) { TickDeathSequence(val); return; } if ((Object)(object)val == (Object)null || !val.isPlayerControlled || val.isPlayerDead) { _wasLooking = false; _stareProgress = Mathf.MoveTowards(_stareProgress, 0f, Time.unscaledDeltaTime * 2f); if ((Object)(object)val != (Object)null && val.isPlayerDead) { _killedByStare = false; } UpdateOverlay(); return; } SlenderMarker marker; bool flag = SlenderRuntime.TryGetLookedAtSlender(val, out marker); if (flag != _wasLooking) { _wasLooking = flag; if (flag) { string arg = (((Object)(object)_gazeAudio != (Object)null && (Object)(object)_gazeAudio.clip != (Object)null) ? ((Object)_gazeAudio.clip).name : "NONE"); string arg2 = (((Object)(object)_gazeAudio != (Object)null && (Object)(object)_gazeAudio.outputAudioMixerGroup != (Object)null) ? ((Object)_gazeAudio.outputAudioMixerGroup).name : "default"); Plugin.Log.LogInfo((object)$"Local gaze effect started; audio clip={arg}, mixer={arg2}, HUD visuals={(Object)(object)_hudOverlay != (Object)null}."); } else { Plugin.Log.LogDebug((object)"Local player looked away from Slenderman."); } } float num = Mathf.Max(1.5f, SlenderRuntime.CurrentStareKillSeconds); if (flag) { _stareProgress = Mathf.Clamp01(_stareProgress + Time.unscaledDeltaTime / num); } else { float num2 = Plugin.LookAwayRecoverySpeed.Value / num; _stareProgress = Mathf.Clamp01(_stareProgress - Time.unscaledDeltaTime * num2); } if (_stareProgress >= 1f && !_killedByStare) { _killedByStare = true; BeginDeathSequence(val); return; } if (_stareProgress > 0.001f && Time.unscaledTime >= _nextNoiseUpdate) { _nextNoiseUpdate = Time.unscaledTime + Mathf.Lerp(0.05f, 0.018f, _stareProgress); RefreshNoise(); } UpdateOverlay(); } private static void ConfigureAudioSource(AudioSource source) { source.playOnAwake = false; source.spatialBlend = 0f; source.spatialize = false; source.bypassEffects = true; source.bypassListenerEffects = true; source.bypassReverbZones = true; source.ignoreListenerPause = true; } private void UpdateOverlay() { //IL_0124: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_hudOverlay == (Object)null) { return; } bool flag = _deathSequenceActive || _stareProgress > 0.001f; ((Behaviour)_hudOverlay).enabled = flag; if (flag) { float num = (_deathSequenceActive ? 1f : Mathf.Pow(_stareProgress, 0.45f)); float num2 = (_deathSequenceActive ? 1f : Mathf.Clamp01(num * Plugin.StaticVisualIntensity.Value)); float num3 = (_deathSequenceActive ? (0.72f + Mathf.Abs(Mathf.Sin(Time.unscaledTime * 43f)) * 0.24f) : (0.94f + Mathf.Sin(Time.unscaledTime * Mathf.Lerp(18f, 34f, num2)) * 0.06f)); float num4 = (_deathSequenceActive ? 0.68f : 0.14f); float num5 = (_deathSequenceActive ? 0.96f : 0.82f); float num6 = Mathf.Clamp01(Mathf.Lerp(num4, num5, num2) * num3); ((Graphic)_hudOverlay).color = new Color(1f, 1f, 1f, num6); UpdateGlitchBars(num2); if ((Object)(object)_gazeAudio != (Object)null) { float num7 = Mathf.Clamp01(Plugin.StaticNoiseVolume.Value); _gazeAudio.volume = num7 * Mathf.Lerp(0.3f, 1f, num); _gazeAudio.pitch = Mathf.Lerp(0.9f, 1.22f, num); if (!_deathSequenceActive && num7 > 0.001f && !_gazeAudio.isPlaying) { _gazeAudio.Play(); } else if ((_deathSequenceActive || num7 <= 0.001f) && _gazeAudio.isPlaying) { _gazeAudio.Stop(); } } } else { SetGlitchBarsVisible(visible: false); if ((Object)(object)_gazeAudio != (Object)null && _gazeAudio.isPlaying) { _gazeAudio.Stop(); } } } private void UpdateGlitchBars(float intensity) { //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) RawImage[] hudGlitchBars = _hudGlitchBars; RawImage hudOverlay = _hudOverlay; if (hudGlitchBars == null || (Object)(object)hudOverlay == (Object)null || Time.unscaledTime < _nextGlitchUpdate) { return; } _nextGlitchUpdate = Time.unscaledTime + (_deathSequenceActive ? 0.01f : Mathf.Lerp(0.1f, 0.018f, intensity)); int num = Mathf.Clamp(2 + Mathf.RoundToInt(intensity * 12f), 2, 14); for (int i = 0; i < hudGlitchBars.Length; i++) { RawImage val = hudGlitchBars[i]; if (((Behaviour)val).enabled = i < num && _noiseRandom.NextDouble() > 0.12) { RectTransform rectTransform = ((Graphic)val).rectTransform; float num2 = (float)_noiseRandom.NextDouble(); float num3 = (_deathSequenceActive ? 110f : 54f); float num4 = Mathf.Lerp(2f, num3, intensity) * Mathf.Lerp(0.35f, 1f, (float)_noiseRandom.NextDouble()); float num5 = (_deathSequenceActive ? 0.16f : 0.09f); float num6 = ((float)_noiseRandom.NextDouble() * 2f - 1f) * (float)Screen.width * Mathf.Lerp(0.01f, num5, intensity); rectTransform.anchorMin = new Vector2(0f, num2); rectTransform.anchorMax = new Vector2(1f, num2); rectTransform.offsetMin = new Vector2(num6, (0f - num4) * 0.5f); rectTransform.offsetMax = new Vector2(num6, num4 * 0.5f); ((Transform)rectTransform).localRotation = Quaternion.Euler(0f, 0f, Mathf.Lerp(-2f, 7f, (float)_noiseRandom.NextDouble())); bool flag2 = _noiseRandom.NextDouble() < 0.38; float num7 = (_deathSequenceActive ? 0.82f : 0.52f); float num8 = Mathf.Lerp(0.1f, num7, intensity) * Mathf.Lerp(0.55f, 1f, (float)_noiseRandom.NextDouble()); ((Graphic)val).color = (flag2 ? new Color(0f, 0f, 0f, num8) : new Color(1f, 1f, 1f, num8)); } } hudOverlay.uvRect = new Rect((float)_noiseRandom.NextDouble(), (float)_noiseRandom.NextDouble(), Mathf.Lerp(1f, 1.8f, intensity), Mathf.Lerp(1f, 1.45f, intensity)); } private void SetGlitchBarsVisible(bool visible) { SetBarArrayVisible(_hudGlitchBars, visible); } private static void SetBarArrayVisible(RawImage[] bars, bool visible) { if (bars == null) { return; } foreach (RawImage val in bars) { if ((Object)(object)val != (Object)null) { ((Behaviour)val).enabled = visible; } } } private void RefreshNoise() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) byte b = (byte)Mathf.Lerp(70f, 255f, _stareProgress); for (int i = 0; i < _noisePixels.Length; i++) { byte b2 = (byte)_noiseRandom.Next(0, 256); b2 = (byte)Mathf.Clamp(128 + (b2 - 128) * b / 128, 0, 255); _noisePixels[i] = new Color32(b2, b2, b2, byte.MaxValue); } _noiseTexture.SetPixels32(_noisePixels); _noiseTexture.Apply(false, false); } private void AdoptLoadedAudioClips() { if ((Object)(object)_audioAssets?.StareClip != (Object)null && (Object)(object)_gazeAudio != (Object)null && (Object)(object)_gazeAudio.clip != (Object)(object)_audioAssets.StareClip) { bool isPlaying = _gazeAudio.isPlaying; _gazeAudio.Stop(); _gazeAudio.clip = _audioAssets.StareClip; if (isPlaying && !_deathSequenceActive) { _gazeAudio.Play(); } } } private void EnsureHudIntegration() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected O, but got Unknown //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Expected O, but got Unknown HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null) { return; } GameObject hUDContainer = instance.HUDContainer; if (!((Object)(object)hUDContainer == (Object)null) && (!((Object)(object)_hudVisualRoot != (Object)null) || !((Object)(object)_hudContainer == (Object)(object)hUDContainer) || !((Object)(object)_gazeAudio != (Object)null))) { DestroyHudVisuals(); _hudContainer = hUDContainer; _hudVisualRoot = new GameObject("Slenderman_HudInterference", new Type[1] { typeof(RectTransform) }); _hudVisualRoot.layer = hUDContainer.layer; _hudVisualRoot.transform.SetParent(hUDContainer.transform, false); RectTransform component = _hudVisualRoot.GetComponent(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; _hudVisualRoot.transform.SetAsLastSibling(); _gazeAudio = _hudVisualRoot.AddComponent(); ConfigureAudioSource(_gazeAudio); _gazeAudio.loop = true; if ((Object)(object)instance.UIAudio != (Object)null) { _gazeAudio.outputAudioMixerGroup = instance.UIAudio.outputAudioMixerGroup; _gazeAudio.priority = instance.UIAudio.priority; } if ((Object)(object)_audioAssets?.StareClip != (Object)null) { _gazeAudio.clip = _audioAssets.StareClip; } GameObject val = new GameObject("Noise", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(RawImage) }); val.layer = hUDContainer.layer; val.transform.SetParent(_hudVisualRoot.transform, false); RectTransform component2 = val.GetComponent(); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.offsetMin = Vector2.zero; component2.offsetMax = Vector2.zero; _hudOverlay = val.GetComponent(); _hudOverlay.texture = (Texture)(object)_noiseTexture; ((Graphic)_hudOverlay).raycastTarget = false; ((Behaviour)_hudOverlay).enabled = false; _hudGlitchBars = (RawImage[])(object)new RawImage[14]; for (int i = 0; i < _hudGlitchBars.Length; i++) { GameObject val2 = new GameObject($"Interference_{i:00}", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(RawImage) }); val2.layer = hUDContainer.layer; val2.transform.SetParent(_hudVisualRoot.transform, false); RawImage component3 = val2.GetComponent(); component3.texture = (Texture)(object)Texture2D.whiteTexture; ((Graphic)component3).raycastTarget = false; ((Behaviour)component3).enabled = false; _hudGlitchBars[i] = component3; } Plugin.Log.LogInfo((object)"Slenderman interference visuals attached to the active game HUD."); } } private void BeginDeathSequence(PlayerControllerB player) { _deathSequenceActive = true; float num = Mathf.Clamp(Plugin.DeathCloseupDuration.Value, 1f, 5f); _deathSequenceEndsAt = Time.unscaledTime + num; _stareProgress = 1f; _wasLooking = false; CreateDeathCloseup(player); if ((Object)(object)_gazeAudio != (Object)null && _gazeAudio.isPlaying) { _gazeAudio.Stop(); } AudioClip val = _audioAssets?.DeathClip; if ((Object)(object)val != (Object)null) { float num2 = Mathf.Clamp(Plugin.DeathSoundVolume.Value, 0f, 2f); AudioSource val2 = HUDManager.Instance?.UIAudio; if ((Object)(object)val2 != (Object)null) { val2.PlayOneShot(val, num2); } else if ((Object)(object)_gazeAudio != (Object)null) { _gazeAudio.PlayOneShot(val, num2); } Plugin.Log.LogInfo((object)("Slenderman death sound playback requested through " + (((Object)(object)val2 != (Object)null) ? "HUD audio" : "fallback audio") + ".")); } else { Plugin.Log.LogWarning((object)"The Slenderman death sound was not ready; the visual death sequence will still play."); } RefreshNoise(); UpdateOverlay(); Plugin.Log.LogInfo((object)("Slenderman death close-up started for '" + player.playerUsername + "'.")); } private void TickDeathSequence(PlayerControllerB player) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) _stareProgress = 1f; if (Time.unscaledTime >= _nextNoiseUpdate) { _nextNoiseUpdate = Time.unscaledTime + 0.012f; RefreshNoise(); } AnimateDeathCloseup(); UpdateOverlay(); if (!(Time.unscaledTime < _deathSequenceEndsAt)) { DestroyDeathCloseup(); _deathSequenceActive = false; _stareProgress = 0f; UpdateOverlay(); if ((Object)(object)player != (Object)null && !player.isPlayerDead) { Plugin.Log.LogInfo((object)("Slenderman stare killed local player '" + player.playerUsername + "'.")); player.KillPlayer(Vector3.zero, true, (CauseOfDeath)4, 0, default(Vector3), false); } } } private void CreateDeathCloseup(PlayerControllerB player) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Expected O, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0173: 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) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) DestroyDeathCloseup(); Camera val = (((Object)(object)player?.gameplayCamera != (Object)null) ? player.gameplayCamera : Camera.main); if ((Object)(object)val == (Object)null) { return; } int layer = FindVisibleLayer(val); _deathCloseup = new GameObject("Slenderman_DeathCloseup"); _deathCloseup.layer = layer; _deathCloseup.transform.SetParent(((Component)val).transform, false); _deathCloseup.transform.localPosition = Vector3.zero; _deathCloseup.transform.localRotation = Quaternion.Euler(0f, 180f, 0f); List list = new List(); SlenderVisualFactory.CreateSlenderman(_deathCloseup.transform, layer, list, out var _); if (list.Count > 0) { Bounds bounds = list[0].bounds; for (int i = 1; i < list.Count; i++) { ((Bounds)(ref bounds)).Encapsulate(list[i].bounds); } Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y - ((Bounds)(ref bounds)).size.y * 0.11f, ((Bounds)(ref bounds)).center.z); Vector3 val3 = ((Component)val).transform.position + ((Component)val).transform.forward * 0.78f; Transform transform = _deathCloseup.transform; transform.position += val3 - val2; } else { _deathCloseup.transform.localPosition = new Vector3(0f, -3.1f, 0.78f); } _deathCloseupBasePosition = _deathCloseup.transform.localPosition; GameObject val4 = new GameObject("DeathCloseupLight"); val4.layer = layer; val4.transform.SetParent(((Component)val).transform, false); val4.transform.localPosition = new Vector3(0f, 0.1f, 0.25f); _deathCloseupLight = val4.AddComponent(); _deathCloseupLight.type = (LightType)2; _deathCloseupLight.color = new Color(0.72f, 0.76f, 0.82f); _deathCloseupLight.range = 2.2f; _deathCloseupLight.intensity = 35f; } private void AnimateDeathCloseup() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_deathCloseup == (Object)null)) { float num = Time.unscaledTime - (_deathSequenceEndsAt - Mathf.Clamp(Plugin.DeathCloseupDuration.Value, 1f, 5f)); float num2 = Mathf.Lerp(0.006f, 0.035f, Mathf.Clamp01(num / 1.2f)); _deathCloseup.transform.localPosition = _deathCloseupBasePosition + new Vector3(Mathf.Sin(Time.unscaledTime * 47f) * num2, Mathf.Cos(Time.unscaledTime * 39f) * num2, Mathf.Sin(Time.unscaledTime * 29f) * num2 * 0.35f); _deathCloseup.transform.localRotation = Quaternion.Euler(Mathf.Sin(Time.unscaledTime * 31f) * 1.8f, 180f + Mathf.Cos(Time.unscaledTime * 37f) * 2.2f, Mathf.Sin(Time.unscaledTime * 43f) * 1.5f); } } private static int FindVisibleLayer(Camera camera) { if ((camera.cullingMask & 1) != 0) { return 0; } for (int i = 1; i < 32; i++) { if ((camera.cullingMask & (1 << i)) != 0) { return i; } } return 0; } private void DestroyDeathCloseup() { if ((Object)(object)_deathCloseup != (Object)null) { Object.Destroy((Object)(object)_deathCloseup); _deathCloseup = null; } if ((Object)(object)_deathCloseupLight != (Object)null) { Object.Destroy((Object)(object)((Component)_deathCloseupLight).gameObject); _deathCloseupLight = null; } } private void DestroyHudVisuals() { if ((Object)(object)_hudVisualRoot != (Object)null) { Object.Destroy((Object)(object)_hudVisualRoot); } _hudVisualRoot = null; _hudContainer = null; _hudOverlay = null; _hudGlitchBars = null; _gazeAudio = null; } private void ResetInternal() { _stareProgress = 0f; _killedByStare = false; _wasLooking = false; _deathSequenceActive = false; DestroyDeathCloseup(); if ((Object)(object)_gazeAudio != (Object)null) { _gazeAudio.Stop(); } UpdateOverlay(); } internal void Dispose() { ResetInternal(); DestroyHudVisuals(); _audioAssets?.Dispose(); _audioAssets = null; if ((Object)(object)_noiseTexture != (Object)null) { Object.Destroy((Object)(object)_noiseTexture); } if (_instance == this) { _instance = null; } } } internal static class SlenderVisualFactory { private static Material _suit; private static Material _shirt; private static Material _skin; private static Material _tie; private static Material _paper; private static Material _ink; internal static void CreateSlenderman(Transform parent, int layer, List renderers, out Transform[] tentacles) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_0420: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Unknown result type (might be due to invalid IL or missing references) //IL_047d: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Unknown result type (might be due to invalid IL or missing references) //IL_04da: Unknown result type (might be due to invalid IL or missing references) if (SlenderModelLoader.TryCreate(parent, layer, renderers)) { tentacles = Array.Empty(); return; } EnsureMaterials(); GameObject val = new GameObject("SlendermanVisual"); val.layer = layer; val.transform.SetParent(parent, false); val.transform.localPosition = Vector3.zero; CreatePart("LeftLeg", (PrimitiveType)1, val.transform, new Vector3(-0.23f, 0.95f, 0f), new Vector3(0.2f, 1.05f, 0.2f), Vector3.zero, _suit, layer, renderers); CreatePart("RightLeg", (PrimitiveType)1, val.transform, new Vector3(0.23f, 0.95f, 0f), new Vector3(0.2f, 1.05f, 0.2f), Vector3.zero, _suit, layer, renderers); CreatePart("Torso", (PrimitiveType)3, val.transform, new Vector3(0f, 2.35f, 0f), new Vector3(0.74f, 1.35f, 0.38f), Vector3.zero, _suit, layer, renderers); CreatePart("Shirt", (PrimitiveType)3, val.transform, new Vector3(0f, 2.72f, 0.205f), new Vector3(0.24f, 0.57f, 0.025f), Vector3.zero, _shirt, layer, renderers); CreatePart("Tie", (PrimitiveType)3, val.transform, new Vector3(0f, 2.63f, 0.226f), new Vector3(0.075f, 0.48f, 0.018f), new Vector3(0f, 0f, 2f), _tie, layer, renderers); CreatePart("Neck", (PrimitiveType)2, val.transform, new Vector3(0f, 3.22f, 0f), new Vector3(0.17f, 0.18f, 0.17f), Vector3.zero, _skin, layer, renderers); CreatePart("Head", (PrimitiveType)0, val.transform, new Vector3(0f, 3.7f, 0f), new Vector3(0.43f, 0.58f, 0.39f), Vector3.zero, _skin, layer, renderers); CreatePart("LeftArm", (PrimitiveType)1, val.transform, new Vector3(-0.55f, 2.08f, 0f), new Vector3(0.14f, 1.36f, 0.14f), new Vector3(0f, 0f, -4f), _suit, layer, renderers); CreatePart("RightArm", (PrimitiveType)1, val.transform, new Vector3(0.55f, 2.08f, 0f), new Vector3(0.14f, 1.36f, 0.14f), new Vector3(0f, 0f, 4f), _suit, layer, renderers); CreatePart("LeftHand", (PrimitiveType)0, val.transform, new Vector3(-0.64f, 0.73f, 0f), new Vector3(0.16f, 0.27f, 0.13f), Vector3.zero, _skin, layer, renderers); CreatePart("RightHand", (PrimitiveType)0, val.transform, new Vector3(0.64f, 0.73f, 0f), new Vector3(0.16f, 0.27f, 0.13f), Vector3.zero, _skin, layer, renderers); tentacles = (Transform[])(object)new Transform[4]; tentacles[0] = CreatePart("TendrilA", (PrimitiveType)2, val.transform, new Vector3(-0.34f, 2.52f, -0.25f), new Vector3(0.045f, 0.95f, 0.045f), new Vector3(30f, 0f, -25f), _suit, layer, renderers).transform; tentacles[1] = CreatePart("TendrilB", (PrimitiveType)2, val.transform, new Vector3(0.34f, 2.45f, -0.25f), new Vector3(0.045f, 1.05f, 0.045f), new Vector3(-25f, 0f, 28f), _suit, layer, renderers).transform; tentacles[2] = CreatePart("TendrilC", (PrimitiveType)2, val.transform, new Vector3(-0.22f, 2.25f, -0.32f), new Vector3(0.035f, 0.82f, 0.035f), new Vector3(50f, 18f, -42f), _suit, layer, renderers).transform; tentacles[3] = CreatePart("TendrilD", (PrimitiveType)2, val.transform, new Vector3(0.24f, 2.2f, -0.32f), new Vector3(0.035f, 0.86f, 0.035f), new Vector3(-45f, -18f, 43f), _suit, layer, renderers).transform; } internal static void CreatePage(Transform parent, int layer, int pageIndex, List renderers) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) EnsureMaterials(); GameObject val = new GameObject("SlenderPageVisual"); val.layer = layer; val.transform.SetParent(parent, false); val.transform.localPosition = Vector3.zero; CreatePart("Paper", (PrimitiveType)3, val.transform, Vector3.zero, new Vector3(0.68f, 0.025f, 0.46f), Vector3.zero, _paper, layer, renderers); for (int i = 0; i < 6; i++) { float num = (float)pageIndex * 0.73f + (float)i * 1.91f; float num2 = Mathf.Sin(num * 1.7f) * 0.18f; float num3 = -0.15f + (float)i * 0.058f; float num4 = Mathf.Sin(num * 2.3f) * 28f; float num5 = 0.17f + Mathf.Abs(Mathf.Cos(num)) * 0.2f; CreatePart("Scribble" + i, (PrimitiveType)3, val.transform, new Vector3(num2, 0.017f, num3), new Vector3(num5, 0.006f, 0.012f), new Vector3(0f, num4, 0f), _ink, layer, renderers); } CreatePart("CrossA", (PrimitiveType)3, val.transform, new Vector3(0f, 0.019f, 0.11f), new Vector3(0.3f, 0.006f, 0.014f), new Vector3(0f, 45f, 0f), _ink, layer, renderers); CreatePart("CrossB", (PrimitiveType)3, val.transform, new Vector3(0f, 0.019f, 0.11f), new Vector3(0.3f, 0.006f, 0.014f), new Vector3(0f, -45f, 0f), _ink, layer, renderers); } private static GameObject CreatePart(string name, PrimitiveType primitive, Transform parent, Vector3 localPosition, Vector3 localScale, Vector3 localEulerAngles, Material material, int layer, List renderers) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) GameObject val = GameObject.CreatePrimitive(primitive); ((Object)val).name = name; val.layer = layer; val.transform.SetParent(parent, false); val.transform.localPosition = localPosition; val.transform.localScale = localScale; val.transform.localEulerAngles = localEulerAngles; Collider component = val.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Renderer component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.sharedMaterial = material; component2.shadowCastingMode = (ShadowCastingMode)1; component2.receiveShadows = true; renderers?.Add(component2); } return val; } private static void EnsureMaterials() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_suit != (Object)null)) { _suit = CreateMaterial("SlenderSuit", new Color(0.012f, 0.014f, 0.018f, 1f), 0.12f); _shirt = CreateMaterial("SlenderShirt", new Color(0.72f, 0.74f, 0.7f, 1f), 0.25f); _skin = CreateMaterial("SlenderFace", new Color(0.8f, 0.81f, 0.76f, 1f), 0.18f); _tie = CreateMaterial("SlenderTie", new Color(0.12f, 0.008f, 0.012f, 1f), 0.18f); _paper = CreateMaterial("SlenderPaper", new Color(0.72f, 0.68f, 0.55f, 1f), 0.08f); _ink = CreateMaterial("SlenderInk", new Color(0.025f, 0.022f, 0.018f, 1f), 0.05f); } } private static Material CreateMaterial(string name, Color color, float smoothness) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) Shader val = Shader.Find("HDRP/Lit") ?? Shader.Find("Standard") ?? Shader.Find("Legacy Shaders/Diffuse"); Material val2 = new Material(val) { name = name }; if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", color); } if (val2.HasProperty("_Color")) { val2.SetColor("_Color", color); } if (val2.HasProperty("_Smoothness")) { val2.SetFloat("_Smoothness", smoothness); } if (val2.HasProperty("_Metallic")) { val2.SetFloat("_Metallic", 0f); } return val2; } internal static void Dispose() { Material[] array = (Material[])(object)new Material[6] { _suit, _shirt, _skin, _tie, _paper, _ink }; for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null) { Object.Destroy((Object)(object)array[i]); } } _suit = null; _shirt = null; _skin = null; _tie = null; _paper = null; _ink = null; } } }