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 System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Dissonance; using Dissonance.Audio.Playback; using GameNetcodeStuff; using HarmonyLib; using InsanityMod.Managers; using InsanityMod.Network; using InsanityMod.Voice; using Microsoft.CodeAnalysis; using MrovLib.Events; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; using WeatherRegistry; [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("InsanityMod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+5267ece16d7bd055ff8278980f0a51811637c7a3")] [assembly: AssemblyProduct("InsanityMod")] [assembly: AssemblyTitle("InsanityMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace InsanityMod { internal static class ModConfig { public static ConfigEntry InsanityRateInFacility { get; private set; } public static ConfigEntry InsanityRateOnShip { get; private set; } public static ConfigEntry InsanityDecayOutdoor { get; private set; } public static ConfigEntry BloodNightMultiplier { get; private set; } public static ConfigEntry BloodNightSpawnWeight { get; private set; } public static ConfigEntry TunnelVisionThreshold { get; private set; } public static ConfigEntry MobVisibilityScale { get; private set; } public static ConfigEntry MobVisibilityRange { get; private set; } public static ConfigEntry TeammateBuffRate { get; private set; } public static ConfigEntry TeammateBuffRange { get; private set; } public static ConfigEntry LightBuffRate { get; private set; } public static ConfigEntry DeathWitnessSpike { get; private set; } public static ConfigEntry DeathWitnessRange { get; private set; } public static ConfigEntry GhostGirlBoostThreshold { get; private set; } public static ConfigEntry VoiceHauntThreshold { get; private set; } public static ConfigEntry LightProximityRange { get; private set; } public static ConfigEntry ApparatusMultiplier { get; private set; } public static ConfigEntry EnableMaskedTransform { get; private set; } public static void Initialize(ConfigFile cfg) { InsanityRateInFacility = cfg.Bind("Insanity", "InsanityRateInFacility", 0.167f, "Insanity gained per second inside the facility (baseline, ~10 min solo to 100%)."); InsanityRateOnShip = cfg.Bind("Insanity", "InsanityRateOnShip", 0f, "Insanity gained per second on the ship."); InsanityDecayOutdoor = cfg.Bind("Insanity", "InsanityDecayOutdoor", 0.8f, "Insanity lost per second outdoors."); BloodNightMultiplier = cfg.Bind("BloodNight", "BloodNightMultiplier", 1.2f, "Insanity rate multiplier when Blood Night weather is active."); BloodNightSpawnWeight = cfg.Bind("BloodNight", "BloodNightSpawnWeight", 20, "Spawn weight for Blood Night weather (other weathers are 100, so ~3% per night at 20)."); TunnelVisionThreshold = cfg.Bind("VFX", "TunnelVisionThreshold", 80f, "Insanity % at which the red tunnel-vision overlay starts."); MobVisibilityScale = cfg.Bind("Reactions", "MobVisibilityScale", 1f, "Multiplier for insanity gained per second per visible enemy (per-type rates are scaled by this)."); MobVisibilityRange = cfg.Bind("Reactions", "MobVisibilityRange", 30f, "Max distance (m) at which a visible enemy contributes to insanity."); TeammateBuffRate = cfg.Bind("Reactions", "TeammateBuffRate", 0.15f, "Insanity-rate reduction per second when at least one living teammate is nearby."); TeammateBuffRange = cfg.Bind("Reactions", "TeammateBuffRange", 6f, "Max distance (m) for the teammate proximity buff."); LightBuffRate = cfg.Bind("Reactions", "LightBuffRate", 0.1f, "Insanity-rate reduction per second when player is illuminated (own flashlight on, or in ship)."); DeathWitnessSpike = cfg.Bind("Reactions", "DeathWitnessSpike", 25f, "Instant insanity gain when a teammate dies in your line of sight."); DeathWitnessRange = cfg.Bind("Reactions", "DeathWitnessRange", 40f, "Max distance (m) for the death witness check."); GhostGirlBoostThreshold = cfg.Bind("Reactions", "GhostGirlBoostThreshold", 80f, "Insanity % above which the host slightly raises Ghost Girl haunt chance (set high to disable)."); VoiceHauntThreshold = cfg.Bind("Reactions", "VoiceHauntThreshold", 70f, "Insanity % at which voice distortion + recorded teammate voice playback start."); LightProximityRange = cfg.Bind("Reactions", "LightProximityRange", 8f, "Max distance (m) to a facility light for the light proximity buff."); ApparatusMultiplier = cfg.Bind("Reactions", "ApparatusMultiplier", 2f, "Insanity rate multiplier inside the facility after the apparatus is removed (lights out)."); EnableMaskedTransform = cfg.Bind("Reactions", "EnableMaskedTransform", true, "If true, reaching 100% insanity transforms the player into a Masked enemy."); } } internal static class InsanityCalculator { public static float TickDelta(bool isInFacility, bool isInShip, float rateInFacility, float rateOnShip, float decayOutdoor, float multiplier, float deltaTime) { float num = (isInFacility ? (rateInFacility * multiplier) : (isInShip ? rateOnShip : (0f - decayOutdoor))); return num * deltaTime; } public static float Clamp(float value) { return Math.Clamp(value, 0f, 100f); } public static float TunnelVisionAlpha(float insanity, float threshold) { if (!(insanity >= threshold)) { return 0f; } return (insanity - threshold) / (100f - threshold); } } [BepInPlugin("com.insanitymod.lethalcompany", "InsanityMod", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string GUID = "com.insanitymod.lethalcompany"; public const string NAME = "InsanityMod"; public const string VERSION = "1.0.1"; internal static ManualLogSource Log; internal static Plugin Instance; private readonly Harmony _harmony = new Harmony("com.insanitymod.lethalcompany"); private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; ModConfig.Initialize(((BaseUnityPlugin)this).Config); LocalizationManager.Initialize(); BloodNightManager.Initialize(); VFXManager.Initialize(); InsanityHud.Initialize(); _harmony.PatchAll(); Log.LogInfo((object)"InsanityMod v1.0.1 loaded."); } private void LateUpdate() { if (!InsanityManager.IsRoundActive) { return; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null)) { if (val.isPlayerDead) { MaskedTransformManager.Reset(); VFXManager.ClearEffect(); InsanityManager.ResetOnDeath(); } else { CameraShakeManager.ApplyShake(val, InsanityManager.Insanity); } } } } } namespace InsanityMod.Voice { internal sealed class CircularSampleBuffer { private readonly float[] _data; private readonly object _lock = new object(); private int _writeIdx; private int _filled; public int Capacity => _data.Length; public int FilledSamples { get { lock (_lock) { return _filled; } } } public CircularSampleBuffer(int capacity) { _data = new float[capacity]; } public void Write(float[] samples, int offset, int count) { if (count <= 0) { return; } lock (_lock) { int num = _data.Length; for (int i = 0; i < count; i++) { _data[_writeIdx] = samples[offset + i]; _writeIdx = (_writeIdx + 1) % num; } _filled = Math.Min(_filled + count, num); } } public float[]? ExtractSnippet(int sampleCount, Random rng) { lock (_lock) { if (_filled < sampleCount) { return null; } int num = _data.Length; int filled = _filled; int num2 = (_writeIdx - filled + num) % num; int num3 = filled - sampleCount; int num4 = ((num3 > 0) ? rng.Next(0, num3 + 1) : 0); int num5 = (num2 + num4) % num; float[] array = new float[sampleCount]; for (int i = 0; i < sampleCount; i++) { array[i] = _data[num5]; num5 = (num5 + 1) % num; } return array; } } public void Clear() { lock (_lock) { Array.Clear(_data, 0, _data.Length); _writeIdx = 0; _filled = 0; } } } [HarmonyPatch(typeof(SamplePlaybackComponent))] internal static class VoiceCapturePatcher { [HarmonyPatch("OnAudioFilterRead")] [HarmonyPostfix] private static void CaptureSamples(SamplePlaybackComponent __instance, float[] data, int channels) { VoiceTrack trackFor = VoiceHaunt.GetTrackFor(__instance); if (trackFor == null || channels <= 0 || data.Length == 0) { return; } int num = data.Length / channels; float[] array = new float[num]; for (int i = 0; i < num; i++) { float num2 = 0f; for (int j = 0; j < channels; j++) { num2 += data[i * channels + j]; } array[i] = num2 / (float)channels; } trackFor.Buffer.Write(array, 0, num); } } internal static class VoiceHaunt { private const int SampleRate = 48000; private const int BufferSeconds = 30; private const int SnippetMinMs = 600; private const int SnippetMaxMs = 2000; private static DissonanceComms? _comms; private static readonly Dictionary _tracks = new Dictionary(); private static readonly Dictionary _tracksByPlayback = new Dictionary(); private static readonly Random _rng = new Random(); private static float _hauntCooldown = 5f; private static bool _subscribed; public static void Tick(float localInsanity, float deltaTime) { EnsureComms(); if ((Object)(object)_comms == (Object)null) { return; } RefreshTracks(); float value = ModConfig.VoiceHauntThreshold.Value; float num = Mathf.Clamp01((localInsanity - value) / Mathf.Max(0.01f, 100f - value)); foreach (VoiceTrack value2 in _tracks.Values) { value2.ApplyLiveDistortion(num); } if (localInsanity < value) { _hauntCooldown = NextInterval(localInsanity); return; } _hauntCooldown -= deltaTime; if (!(_hauntCooldown > 0f)) { _hauntCooldown = NextInterval(localInsanity); TryHauntPlayback(num); } } public static void ResetForRound() { foreach (VoiceTrack value in _tracks.Values) { value.ClearBuffer(); value.ResetFilters(); } _hauntCooldown = 5f; } public static VoiceTrack? GetTrackFor(SamplePlaybackComponent component) { if ((Object)(object)component == (Object)null) { return null; } int instanceID = ((Object)((Component)component).gameObject).GetInstanceID(); _tracksByPlayback.TryGetValue(instanceID, out VoiceTrack value); return value; } private static void EnsureComms() { if (!((Object)(object)_comms != (Object)null)) { _comms = Object.FindObjectOfType(); if (!((Object)(object)_comms == (Object)null) && !_subscribed) { _comms.OnPlayerLeftSession += OnPlayerLeft; _subscribed = true; } } } private static void OnPlayerLeft(VoicePlayerState state) { if (state != null && _tracks.TryGetValue(state.Name, out VoiceTrack value)) { _tracks.Remove(state.Name); _tracksByPlayback.Remove(((Object)((Component)value.Playback).gameObject).GetInstanceID()); } } private static void RefreshTracks() { if ((Object)(object)_comms == (Object)null) { return; } foreach (VoicePlayerState player in _comms.Players) { if (!player.IsLocalPlayer) { IVoicePlayback playback = player.Playback; VoicePlayback val = (VoicePlayback)(object)((playback is VoicePlayback) ? playback : null); if (val != null && !_tracks.ContainsKey(player.Name)) { int bufferSamples = 1440000; VoiceTrack value = new VoiceTrack(val, bufferSamples); _tracks[player.Name] = value; _tracksByPlayback[((Object)((Component)val).gameObject).GetInstanceID()] = value; } } } } private static float NextInterval(float insanity) { if (insanity >= 90f) { return Random.Range(3f, 8f); } return Random.Range(12f, 25f); } private static void TryHauntPlayback(float intensity) { //IL_00be: Unknown result type (might be due to invalid IL or missing references) List list = new List(); foreach (VoiceTrack value in _tracks.Values) { if (value.Buffer.FilledSamples > 24000) { list.Add(value); } } if (list.Count != 0) { VoiceTrack voiceTrack = list[_rng.Next(list.Count)]; int num = _rng.Next(600, 2001); int sampleCount = 48000 * num / 1000; float[] array = voiceTrack.Buffer.ExtractSnippet(sampleCount, _rng); if (array != null) { PlayHauntClip(array, ((Component)voiceTrack.Playback).transform.position, intensity); } } } private static void PlayHauntClip(float[] samples, Vector3 position, float intensity) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) AudioClip val = AudioClip.Create("InsanityHaunt", samples.Length, 1, 48000, false); val.SetData(samples, 0); GameObject val2 = new GameObject("InsanityHauntPlayer"); val2.transform.position = position; Object.DontDestroyOnLoad((Object)(object)val2); AudioSource obj = val2.AddComponent(); obj.clip = val; obj.spatialBlend = 1f; obj.minDistance = 1f; obj.maxDistance = 25f; obj.rolloffMode = (AudioRolloffMode)0; obj.volume = Mathf.Lerp(0.4f, 0.85f, intensity); obj.pitch = Mathf.Lerp(0.95f, 0.55f, intensity); val2.AddComponent().cutoffFrequency = Mathf.Lerp(6000f, 1200f, intensity); val2.AddComponent().distortionLevel = Mathf.Lerp(0.15f, 0.65f, intensity); val2.AddComponent().reverbPreset = (AudioReverbPreset)2; if (intensity > 0.6f) { AudioEchoFilter obj2 = val2.AddComponent(); obj2.delay = Mathf.Lerp(120f, 280f, intensity); obj2.wetMix = 0.5f; obj2.dryMix = 1f; obj2.decayRatio = Mathf.Lerp(0.4f, 0.7f, intensity); } obj.Play(); Object.Destroy((Object)(object)val2, (float)samples.Length / 48000f + 1f); } } internal sealed class VoiceTrack { public string PlayerName { get; } public VoicePlayback Playback { get; } public AudioSource Source { get; } public CircularSampleBuffer Buffer { get; } public AudioLowPassFilter LowPass { get; } public AudioDistortionFilter Distortion { get; } public AudioReverbFilter Reverb { get; } public AudioEchoFilter Echo { get; } public VoiceTrack(VoicePlayback playback, int bufferSamples) { PlayerName = playback.PlayerName; Playback = playback; Source = playback.AudioSource; Buffer = new CircularSampleBuffer(bufferSamples); GameObject gameObject = ((Component)playback).gameObject; LowPass = GetOrAdd(gameObject); Distortion = GetOrAdd(gameObject); Reverb = GetOrAdd(gameObject); Echo = GetOrAdd(gameObject); ResetFilters(); } public void ApplyLiveDistortion(float insanityNorm) { float num = Mathf.Clamp01(insanityNorm); LowPass.cutoffFrequency = Mathf.Lerp(22000f, 1500f, num); Distortion.distortionLevel = Mathf.Lerp(0f, 0.55f, num); Reverb.reverbLevel = Mathf.Lerp(-10000f, 800f, num); Reverb.decayTime = Mathf.Lerp(0.1f, 3.5f, num); Echo.delay = Mathf.Lerp(0f, 180f, num); Echo.wetMix = Mathf.Lerp(0f, 0.45f, num); Echo.dryMix = 1f; Echo.decayRatio = Mathf.Lerp(0f, 0.55f, num); ((Behaviour)LowPass).enabled = num > 0.01f; ((Behaviour)Distortion).enabled = num > 0.2f; ((Behaviour)Reverb).enabled = num > 0.01f; ((Behaviour)Echo).enabled = num > 0.4f; } public void ResetFilters() { LowPass.cutoffFrequency = 22000f; ((Behaviour)LowPass).enabled = false; Distortion.distortionLevel = 0f; ((Behaviour)Distortion).enabled = false; Reverb.reverbLevel = -10000f; Reverb.decayTime = 0.1f; ((Behaviour)Reverb).enabled = false; Echo.delay = 0f; Echo.wetMix = 0f; Echo.dryMix = 1f; Echo.decayRatio = 0f; ((Behaviour)Echo).enabled = false; } public void ClearBuffer() { Buffer.Clear(); } private static T GetOrAdd(GameObject go) where T : Component { return go.GetComponent() ?? go.AddComponent(); } } } namespace InsanityMod.Patches { [HarmonyPatch(typeof(PlayerControllerB))] internal static class DeathWitnessPatcher { [HarmonyPatch("KillPlayer")] [HarmonyPostfix] private static void KillPlayerPostfix(PlayerControllerB __instance) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (!InsanityManager.IsRoundActive || (Object)(object)__instance == (Object)null) { return; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)__instance) && !val.isPlayerDead) { float value = ModConfig.DeathWitnessRange.Value; if (InsanityModifiers.IsPositionVisible(val, ((Component)__instance).transform.position, value)) { InsanityManager.AddInsanity(ModConfig.DeathWitnessSpike.Value); } } } } [HarmonyPatch(typeof(DressGirlAI))] internal static class GhostGirlBoostPatcher { [HarmonyPatch("Update")] [HarmonyPostfix] private static void UpdatePostfix(DressGirlAI __instance) { if (InsanityManager.IsRoundActive && __instance.hauntingLocalPlayer) { float value = ModConfig.GhostGirlBoostThreshold.Value; float insanity = InsanityManager.Insanity; if (!(insanity < value)) { float num = (insanity - value) / Mathf.Max(0.01f, 100f - value); __instance.timer += Time.deltaTime * num * 0.5f; } } } } [HarmonyPatch(typeof(LungProp))] internal static class LungPropPatcher { [HarmonyPatch("EquipItem")] [HarmonyPrefix] private static void EquipItemPrefix(LungProp __instance) { if (__instance.isLungDocked) { InsanityManager.OnApparatusRemoved(); } } } [HarmonyPatch(typeof(PlayerControllerB))] internal static class PlayerPatcher { [HarmonyPatch("Update")] [HarmonyPostfix] private static void UpdatePostfix(PlayerControllerB __instance) { GameNetworkManager instance = GameNetworkManager.Instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)__instance != (Object)(object)instance.localPlayerController) && !__instance.isPlayerDead) { InsanityManager.Tick(__instance, Time.deltaTime); } } } [HarmonyPatch(typeof(StartOfRound))] internal static class RoundPatcher { [HarmonyPatch("StartGame")] [HarmonyPostfix] private static void StartGamePostfix() { InsanityManager.StartRound(); InsanityNetworkHandler.PlayerMaxInsanity.Clear(); InsanityNetworkHandler.RegisterHandlers(); VoiceHaunt.ResetForRound(); InsanityModifiers.InvalidateLightCache(); } [HarmonyPatch("ShipLeave")] [HarmonyPostfix] private static void ShipLeavePostfix() { InsanityNetworkHandler.SendMaxInsanity(InsanityManager.MaxInsanityThisRound); } [HarmonyPatch("EndGameClientRpc")] [HarmonyPostfix] private static void EndGamePostfix() { InsanityNetworkHandler.BroadcastResults(); InsanityNetworkHandler.UnregisterHandlers(); InsanityManager.EndRound(); } } [HarmonyPatch(typeof(HUDManager))] internal static class RoundResultsPatcher { [HarmonyPatch("ApplyPenalty")] [HarmonyPostfix] private static void ShowInsanityStats(HUDManager __instance) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) if (InsanityNetworkHandler.PlayerMaxInsanity.Count == 0) { return; } EndOfGameStatUIElements statsUIElements = __instance.statsUIElements; object obj; if (statsUIElements == null) { obj = null; } else { TextMeshProUGUI penaltyTotal = statsUIElements.penaltyTotal; obj = ((penaltyTotal != null) ? ((TMP_Text)penaltyTotal).transform.parent : null); } Transform val = (Transform)obj; if ((Object)(object)val == (Object)null) { return; } Transform val2 = val.Find("InsanityStats"); if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)((Component)val2).gameObject); } string text = LocalizationManager.Get("hud.max_insanity"); GameObject val3 = new GameObject("InsanityStats", new Type[1] { typeof(RectTransform) }); val3.transform.SetParent(val, false); TextMeshProUGUI val4 = val3.AddComponent(); ((TMP_Text)val4).fontSize = 14f; ((TMP_Text)val4).alignment = (TextAlignmentOptions)513; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("— " + text + " —"); PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val5 in allPlayerScripts) { ulong actualClientId = val5.actualClientId; if (InsanityNetworkHandler.PlayerMaxInsanity.TryGetValue(actualClientId, out var value)) { string playerUsername = val5.playerUsername; string text2 = $"{value:F0}%"; string text3 = ((value >= 100f) ? "" : ""); stringBuilder.AppendLine(text3 + playerUsername + " " + text2 + ""); } } ((TMP_Text)val4).text = stringBuilder.ToString(); } } } namespace InsanityMod.Network { internal static class InsanityNetworkHandler { private const string MSG_SUBMIT = "InsanityMod.SubmitMaxInsanity"; private const string MSG_RESULTS = "InsanityMod.BroadcastResults"; private const string MSG_SPAWN_MASKED = "InsanityMod.SpawnMasked"; private static EnemyType? _maskedEnemyType; public static readonly Dictionary PlayerMaxInsanity = new Dictionary(); public static void RegisterHandlers() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown if (!((Object)(object)NetworkManager.Singleton == (Object)null)) { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; if (NetworkManager.Singleton.IsServer) { customMessagingManager.RegisterNamedMessageHandler("InsanityMod.SubmitMaxInsanity", new HandleNamedMessageDelegate(ReceiveMaxInsanity)); customMessagingManager.RegisterNamedMessageHandler("InsanityMod.SpawnMasked", new HandleNamedMessageDelegate(ReceiveSpawnMasked)); } customMessagingManager.RegisterNamedMessageHandler("InsanityMod.BroadcastResults", new HandleNamedMessageDelegate(ReceiveBroadcastResults)); } } public static void UnregisterHandlers() { if (!((Object)(object)NetworkManager.Singleton == (Object)null)) { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; customMessagingManager.UnregisterNamedMessageHandler("InsanityMod.SubmitMaxInsanity"); customMessagingManager.UnregisterNamedMessageHandler("InsanityMod.BroadcastResults"); customMessagingManager.UnregisterNamedMessageHandler("InsanityMod.SpawnMasked"); } } public static void SendMaxInsanity(float maxInsanity) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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) if (!((Object)(object)NetworkManager.Singleton == (Object)null)) { FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); ((FastBufferWriter)(ref val)).WriteValueSafe(ref maxInsanity, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("InsanityMod.SubmitMaxInsanity", 0uL, val, (NetworkDelivery)3); ((FastBufferWriter)(ref val)).Dispose(); } } private static void ReceiveMaxInsanity(ulong senderId, FastBufferReader reader) { //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) float value = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref value, default(ForPrimitives)); PlayerMaxInsanity[senderId] = value; } public static void BroadcastResults() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } int count = PlayerMaxInsanity.Count; int num = 4 + count * 12; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num, (Allocator)2, -1); ((FastBufferWriter)(ref val)).WriteValueSafe(ref count, default(ForPrimitives)); foreach (KeyValuePair item in PlayerMaxInsanity) { ulong key = item.Key; ((FastBufferWriter)(ref val)).WriteValueSafe(ref key, default(ForPrimitives)); float value = item.Value; ((FastBufferWriter)(ref val)).WriteValueSafe(ref value, default(ForPrimitives)); } NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("InsanityMod.BroadcastResults", val, (NetworkDelivery)3); ((FastBufferWriter)(ref val)).Dispose(); } private static void ReceiveBroadcastResults(ulong _, FastBufferReader reader) { //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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); PlayerMaxInsanity.Clear(); ulong key = default(ulong); float value = default(float); for (int i = 0; i < num; i++) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref key, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref value, default(ForPrimitives)); PlayerMaxInsanity[key] = value; } } public static void SendSpawnMasked(PlayerControllerB local) { //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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null)) { FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(20, (Allocator)2, -1); Vector3 position = ((Component)local).transform.position; ((FastBufferWriter)(ref val)).WriteValueSafe(ref position.x, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref position.y, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref position.z, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref local.playerClientId, default(ForPrimitives)); if (singleton.IsServer) { FastBufferReader reader = default(FastBufferReader); ((FastBufferReader)(ref reader))..ctor(val, (Allocator)2, -1, 0, (Allocator)2); ReceiveSpawnMasked(singleton.LocalClientId, reader); ((FastBufferReader)(ref reader)).Dispose(); } else { singleton.CustomMessagingManager.SendNamedMessage("InsanityMod.SpawnMasked", 0uL, val, (NetworkDelivery)3); } ((FastBufferWriter)(ref val)).Dispose(); } } private static void ReceiveSpawnMasked(ulong _, FastBufferReader reader) { //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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_007a: 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) float num = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); ulong num4 = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num4, default(ForPrimitives)); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(num, num2, num3); EnemyType maskedEnemyType = GetMaskedEnemyType(); if ((Object)(object)maskedEnemyType == (Object)null || (Object)(object)RoundManager.Instance == (Object)null) { return; } NetworkObjectReference val2 = RoundManager.Instance.SpawnEnemyGameObject(val, 0f, -1, maskedEnemyType); NetworkObject val3 = default(NetworkObject); if (!((NetworkObjectReference)(ref val2)).TryGet(ref val3, (NetworkManager)null)) { return; } MaskedPlayerEnemy val4 = ((Component)val3).GetComponent() ?? ((Component)val3).GetComponentInChildren(); if ((Object)(object)val4 == (Object)null) { return; } PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return; } PlayerControllerB[] array2 = array; foreach (PlayerControllerB val5 in array2) { if (val5.playerClientId == num4) { val4.mimickingPlayer = val5; val4.SetSuit(val5.currentSuitID); break; } } } private static EnemyType? GetMaskedEnemyType() { if ((Object)(object)_maskedEnemyType != (Object)null) { return _maskedEnemyType; } EnemyType[] array = Resources.FindObjectsOfTypeAll(); foreach (EnemyType val in array) { if (val.enemyName == "Masked") { _maskedEnemyType = val; return val; } } return null; } } } namespace InsanityMod.Managers { internal static class BloodNightManager { private static Weather? _bloodNightWeather; public static bool IsActive { get; private set; } public static void Initialize() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown ImprovedWeatherEffect val = ScriptableObject.CreateInstance(); _bloodNightWeather = new Weather(LocalizationManager.Get("weather.blood_night"), val); _bloodNightWeather.Config.DefaultWeight = new IntegerConfigHandler(ModConfig.BloodNightSpawnWeight.Value, false); WeatherManager.RegisterWeather(_bloodNightWeather); ((CustomEvent<(SelectableLevel, Weather)>)(object)EventManager.WeatherChanged).AddListener((ParameterEvent<(SelectableLevel, Weather)>)OnWeatherChanged); ((CustomEvent)(object)EventManager.DayChanged).AddListener((ParameterEvent)OnDayChanged); } private static void OnWeatherChanged((SelectableLevel level, Weather weather) args) { IsActive = _bloodNightWeather != null && args.weather == _bloodNightWeather; } private static void OnDayChanged(int day) { } } internal static class CameraShakeManager { private const float ShakeThreshold = 90f; private const float NoiseFrequency = 8f; private const float MaxPositionAmplitude = 0.02f; private const float MaxRotationAmplitude = 0.8f; private static Vector3 _prevPosShake = Vector3.zero; private static Quaternion _prevRotShake = Quaternion.identity; public static void ApplyShake(PlayerControllerB local, float insanity) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012c: 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_0136: 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_0151: 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_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_0068: Unknown result type (might be due to invalid IL or missing references) Camera gameplayCamera = local.gameplayCamera; if (!((Object)(object)gameplayCamera == (Object)null)) { Transform transform = ((Component)gameplayCamera).transform; transform.localPosition -= _prevPosShake; ((Component)gameplayCamera).transform.localRotation = ((Component)gameplayCamera).transform.localRotation * Quaternion.Inverse(_prevRotShake); if (insanity < 90f) { _prevPosShake = Vector3.zero; _prevRotShake = Quaternion.identity; return; } float num = Mathf.Clamp01((insanity - 90f) / 10f); float num2 = Time.time * 8f; float num3 = (Mathf.PerlinNoise(num2, 0f) - 0.5f) * 2f; float num4 = (Mathf.PerlinNoise(0f, num2) - 0.5f) * 2f; float num5 = (Mathf.PerlinNoise(num2 + 7f, num2) - 0.5f) * 2f; _prevPosShake = new Vector3(num3, num4, num5) * 0.02f * num; _prevRotShake = Quaternion.Euler(num4 * 0.8f * num, num3 * 0.8f * num, num5 * 0.8f * 0.6f * num); Transform transform2 = ((Component)gameplayCamera).transform; transform2.localPosition += _prevPosShake; Transform transform3 = ((Component)gameplayCamera).transform; transform3.localRotation *= _prevRotShake; } } } internal static class InsanityHud { private const int RingSize = 110; private const int RingThickness = 7; private const float ScreenMarginX = 35f; private const float ScreenMarginY = 130f; private static GameObject? _canvasGO; private static Image? _ringFill; private static Image? _ringBg; private static TextMeshProUGUI? _label; private static Sprite? _ringSprite; public static void Initialize() { SceneManager.sceneLoaded += OnSceneLoaded; } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (!(((Scene)(ref scene)).name != "SampleSceneRelay")) { CreateOverlay(); SetVisible(visible: false); } } public static void SetVisible(bool visible) { if (!((Object)(object)_canvasGO == (Object)null)) { _canvasGO.SetActive(visible); } } public static void UpdateValue(float insanity) { //IL_0046: 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) if (!((Object)(object)_ringFill == (Object)null) && !((Object)(object)_ringBg == (Object)null) && !((Object)(object)_label == (Object)null)) { float num = Mathf.Clamp01(insanity / 100f); _ringFill.fillAmount = num; ((Graphic)_ringFill).color = ColorForInsanity(num); ((TMP_Text)_label).text = $"{Mathf.FloorToInt(insanity)}%"; ((Graphic)_label).color = ColorForInsanity(num); } } private static void CreateOverlay() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0060: 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_009c: 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_00c6: 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_014b: 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_016a: 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_0184: 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_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_canvasGO != (Object)null)) { _canvasGO = new GameObject("InsanityHud_Canvas"); Object.DontDestroyOnLoad((Object)(object)_canvasGO); Canvas obj = _canvasGO.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 50; _canvasGO.AddComponent(); _canvasGO.AddComponent(); Sprite ringSprite = GetRingSprite(); RectTransform val = new GameObject("InsanityHud_Root").AddComponent(); ((Transform)val).SetParent(_canvasGO.transform, false); val.anchorMin = new Vector2(1f, 0f); val.anchorMax = new Vector2(1f, 0f); val.pivot = new Vector2(1f, 0f); val.anchoredPosition = new Vector2(-35f, 130f); val.sizeDelta = new Vector2(110f, 110f); GameObject val2 = new GameObject("InsanityHud_RingBg"); RectTransform obj2 = val2.AddComponent(); ((Transform)obj2).SetParent((Transform)(object)val, false); obj2.anchorMin = Vector2.zero; obj2.anchorMax = Vector2.one; obj2.sizeDelta = Vector2.zero; _ringBg = val2.AddComponent(); _ringBg.sprite = ringSprite; ((Graphic)_ringBg).color = new Color(0.1f, 0.1f, 0.1f, 0.75f); ((Graphic)_ringBg).raycastTarget = false; GameObject val3 = new GameObject("InsanityHud_RingFill"); RectTransform obj3 = val3.AddComponent(); ((Transform)obj3).SetParent((Transform)(object)val, false); obj3.anchorMin = Vector2.zero; obj3.anchorMax = Vector2.one; obj3.sizeDelta = Vector2.zero; _ringFill = val3.AddComponent(); _ringFill.sprite = ringSprite; _ringFill.type = (Type)3; _ringFill.fillMethod = (FillMethod)4; _ringFill.fillOrigin = 2; _ringFill.fillClockwise = true; _ringFill.fillAmount = 0f; ((Graphic)_ringFill).color = ColorForInsanity(0f); ((Graphic)_ringFill).raycastTarget = false; GameObject val4 = new GameObject("InsanityHud_Label"); RectTransform obj4 = val4.AddComponent(); ((Transform)obj4).SetParent((Transform)(object)val, false); obj4.anchorMin = Vector2.zero; obj4.anchorMax = Vector2.one; obj4.sizeDelta = Vector2.zero; _label = val4.AddComponent(); ((TMP_Text)_label).alignment = (TextAlignmentOptions)514; ((TMP_Text)_label).fontSize = 22f; ((TMP_Text)_label).fontStyle = (FontStyles)1; ((TMP_Text)_label).text = "0%"; ((Graphic)_label).color = ColorForInsanity(0f); ((Graphic)_label).raycastTarget = false; Plugin.Log.LogInfo((object)"InsanityHud overlay created."); } } private static Color ColorForInsanity(float t) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (t < 0.5f) { return Color.Lerp(new Color(0.85f, 0.85f, 0.85f), new Color(1f, 0.85f, 0.2f), t / 0.5f); } return Color.Lerp(new Color(1f, 0.85f, 0.2f), new Color(1f, 0.15f, 0.15f), (t - 0.5f) / 0.5f); } private static Sprite GetRingSprite() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_002e: Expected O, but got Unknown //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0155: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0103: 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)_ringSprite != (Object)null) { return _ringSprite; } int num = 110; Texture2D val = new Texture2D(num, num, (TextureFormat)1, false) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor((float)num / 2f, (float)num / 2f); float num2 = (float)num / 2f - 1.5f; float num3 = num2 - 7f; Color32[] array = (Color32[])(object)new Color32[num * num]; for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { float num4 = Vector2.Distance(new Vector2((float)j, (float)i), val2); float num5 = 0f; if (num4 >= num3 && num4 <= num2) { num5 = 1f; } else if (num4 > num2 && num4 < num2 + 1f) { num5 = 1f - (num4 - num2); } else if (num4 < num3 && num4 > num3 - 1f) { num5 = 1f - (num3 - num4); } array[i * num + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(num5 * 255f)); } } val.SetPixels32(array); val.Apply(); _ringSprite = Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num), new Vector2(0.5f, 0.5f)); return _ringSprite; } } internal static class InsanityManager { private static float _insanity; private static float _maxInsanityThisRound; private static bool _roundActive; private static bool _apparatusRemoved; private static bool _hasTransformedThisRound; public static float Insanity => _insanity; public static float MaxInsanityThisRound => _maxInsanityThisRound; public static bool IsRoundActive => _roundActive; public static void OnApparatusRemoved() { if (_roundActive) { _apparatusRemoved = true; } } public static void StartRound() { _insanity = 0f; _maxInsanityThisRound = 0f; _roundActive = true; _apparatusRemoved = false; _hasTransformedThisRound = false; MaskedTransformManager.Reset(); InsanityHud.SetVisible(visible: true); } public static void EndRound() { _roundActive = false; VFXManager.ClearEffect(); InsanityHud.SetVisible(visible: false); } public static void ResetForRound() { StartRound(); } public static void Tick(PlayerControllerB player, float deltaTime) { if (_roundActive) { float num = ((_apparatusRemoved && player.isInsideFactory) ? ModConfig.ApparatusMultiplier.Value : 1f); float num2 = InsanityCalculator.TickDelta(player.isInsideFactory, player.isInHangarShipRoom, ModConfig.InsanityRateInFacility.Value * num, ModConfig.InsanityRateOnShip.Value, ModConfig.InsanityDecayOutdoor.Value, BloodNightManager.IsActive ? ModConfig.BloodNightMultiplier.Value : 1f, deltaTime); float num3 = InsanityModifiers.ComputeBonusRate(player) * deltaTime; _insanity = InsanityCalculator.Clamp(_insanity + num2 + num3); if (_insanity > _maxInsanityThisRound) { _maxInsanityThisRound = _insanity; } VFXManager.UpdateTunnelVision(_insanity); InsanityHud.UpdateValue(_insanity); VoiceHaunt.Tick(_insanity, deltaTime); if (_insanity >= 100f && !_hasTransformedThisRound && !MaskedTransformManager.IsActive && ModConfig.EnableMaskedTransform.Value) { _hasTransformedThisRound = true; MaskedTransformManager.TriggerTransform(player); } if (MaskedTransformManager.IsActive) { MaskedTransformManager.Tick(player, deltaTime); } } } public static void ResetOnDeath() { _insanity = 0f; InsanityHud.UpdateValue(0f); } public static void AddInsanity(float amount) { if (_roundActive) { _insanity = InsanityCalculator.Clamp(_insanity + amount); if (_insanity > _maxInsanityThisRound) { _maxInsanityThisRound = _insanity; } } } } internal static class InsanityModifiers { private static Light[] _cachedLights = Array.Empty(); private static float _lastLightCacheTime = -100f; private const float LightCacheRefreshSec = 5f; private static readonly Dictionary EnemyRates = new Dictionary { { "Flowerman", 2f }, { "Crawler", 0.8f }, { "Spring", 1.5f }, { "Hoarding bug", 0.1f }, { "Centipede", 0.6f }, { "SandSpider", 0.9f }, { "BushWolf", 1.2f }, { "ForestGiant", 1.4f }, { "DressGirl", 2f }, { "Jester", 1.5f }, { "Blob", 0.3f }, { "Puffer", 0.4f }, { "MaskedPlayerEnemy", 1.6f }, { "Maneater", 1.4f }, { "BaboonHawk", 0.5f }, { "RedLocustBees", 0.2f }, { "DocileLocustBees", 0f }, { "DoublewingBird", 0f }, { "SandWorm", 1.8f }, { "Tulip Snake", 0.3f }, { "Butler", 1.4f }, { "Butler Bees", 0.2f }, { "ClaySurgeon", 1.3f } }; private const float DefaultEnemyRate = 0.3f; public static float ComputeBonusRate(PlayerControllerB local) { if ((Object)(object)local == (Object)null) { return 0f; } return 0f + MobVisibilityBonus(local) - ProximityBuff(local) - LightBuff(local); } public static float MobVisibilityBonus(PlayerControllerB local) { //IL_0051: 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: 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_00c9: 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_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) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) Camera gameplayCamera = local.gameplayCamera; if ((Object)(object)gameplayCamera == (Object)null) { return 0f; } RoundManager instance = RoundManager.Instance; if ((Object)(object)instance == (Object)null || instance.SpawnedEnemies == null) { return 0f; } float value = ModConfig.MobVisibilityScale.Value; float value2 = ModConfig.MobVisibilityRange.Value; float num = value2 * value2; Vector3 position = ((Component)gameplayCamera).transform.position; Vector3 forward = ((Component)gameplayCamera).transform.forward; float num2 = gameplayCamera.fieldOfView * 0.5f + 5f; float num3 = 0f; RaycastHit val4 = default(RaycastHit); for (int i = 0; i < instance.SpawnedEnemies.Count; i++) { EnemyAI val = instance.SpawnedEnemies[i]; if ((Object)(object)val == (Object)null || val.isEnemyDead || (Object)(object)val.enemyType == (Object)null) { continue; } Vector3 val2 = ((Component)val).transform.position - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude > num) && !(sqrMagnitude < 0.01f)) { float num4 = Mathf.Sqrt(sqrMagnitude); Vector3 val3 = val2 / num4; if (!(Vector3.Angle(forward, val3) > num2) && (!Physics.Linecast(position, ((Component)val).transform.position, ref val4, -1, (QueryTriggerInteraction)1) || ((Component)((RaycastHit)(ref val4)).collider).transform.IsChildOf(((Component)val).transform))) { float rateForEnemy = GetRateForEnemy(val); num3 += rateForEnemy; } } } return num3 * value; } public static float ProximityBuff(PlayerControllerB local) { //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_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) //IL_0070: 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) PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return 0f; } float value = ModConfig.TeammateBuffRange.Value; float num = value * value; Vector3 position = ((Component)local).transform.position; foreach (PlayerControllerB val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)local) && !val.isPlayerDead && val.isPlayerControlled) { Vector3 val2 = ((Component)val).transform.position - position; if (((Vector3)(ref val2)).sqrMagnitude <= num) { return ModConfig.TeammateBuffRate.Value; } } } return 0f; } public static float LightBuff(PlayerControllerB local) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (local.isInHangarShipRoom) { return ModConfig.LightBuffRate.Value; } if ((Object)(object)local.helmetLight != (Object)null && ((Behaviour)local.helmetLight).enabled) { return ModConfig.LightBuffRate.Value; } if (local.ItemSlots != null) { GrabbableObject[] itemSlots = local.ItemSlots; foreach (GrabbableObject obj in itemSlots) { FlashlightItem val = (FlashlightItem)(object)((obj is FlashlightItem) ? obj : null); if (val != null && ((GrabbableObject)val).isBeingUsed) { return ModConfig.LightBuffRate.Value; } } } if (IsNearActiveLight(((Component)local).transform.position)) { return ModConfig.LightBuffRate.Value; } return 0f; } private static bool IsNearActiveLight(Vector3 pos) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Invalid comparison between Unknown and I4 //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_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) if (Time.time - _lastLightCacheTime > 5f) { _cachedLights = Object.FindObjectsOfType(); _lastLightCacheTime = Time.time; } float value = ModConfig.LightProximityRange.Value; float num = value * value; for (int i = 0; i < _cachedLights.Length; i++) { Light val = _cachedLights[i]; if (!((Object)(object)val == (Object)null) && ((Behaviour)val).enabled && ((Component)val).gameObject.activeInHierarchy && (int)val.type != 1 && !(val.intensity < 0.3f)) { Vector3 val2 = ((Component)val).transform.position - pos; if (((Vector3)(ref val2)).sqrMagnitude <= num) { return true; } } } return false; } public static void InvalidateLightCache() { _cachedLights = Array.Empty(); _lastLightCacheTime = -100f; } public static bool IsPositionVisible(PlayerControllerB local, Vector3 worldPos, float maxRange) { //IL_0012: 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_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_0043: 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_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_007a: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_0098: Unknown result type (might be due to invalid IL or missing references) Camera gameplayCamera = local.gameplayCamera; if ((Object)(object)gameplayCamera == (Object)null) { return false; } Vector3 val = worldPos - ((Component)gameplayCamera).transform.position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude > maxRange * maxRange || sqrMagnitude < 0.01f) { return false; } float num = Mathf.Sqrt(sqrMagnitude); Vector3 val2 = val / num; if (Vector3.Angle(((Component)gameplayCamera).transform.forward, val2) > gameplayCamera.fieldOfView * 0.5f + 5f) { return false; } RaycastHit val3 = default(RaycastHit); if (Physics.Linecast(((Component)gameplayCamera).transform.position, worldPos, ref val3, -1, (QueryTriggerInteraction)1)) { Vector3 val4 = ((RaycastHit)(ref val3)).point - worldPos; if (((Vector3)(ref val4)).sqrMagnitude > 1f) { return false; } } return true; } private static float GetRateForEnemy(EnemyAI enemy) { string key = enemy.enemyType?.enemyName ?? ""; if (EnemyRates.TryGetValue(key, out var value)) { return value; } return 0.3f; } } internal static class LocalizationManager { private static Dictionary _strings = new Dictionary(); public static void Initialize() { string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Langs.json"); if (!File.Exists(text)) { Plugin.Log.LogWarning((object)("Langs.json not found at " + text + ", falling back to EN defaults.")); LoadDefaults(); return; } string text2 = DetectLanguage(); Dictionary> dictionary = ParseLangSections(File.ReadAllText(text)); if (!dictionary.TryGetValue(text2, out var value)) { dictionary.TryGetValue("EN", out value); } if (value != null) { foreach (KeyValuePair item in value) { _strings[item.Key] = item.Value; } } else { LoadDefaults(); } Plugin.Log.LogInfo((object)$"Localization loaded: {text2} ({_strings.Count} strings)"); } public static string Get(string key) { if (!_strings.TryGetValue(key, out string value)) { return key; } return value; } private static string DetectLanguage() { if (CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.ToUpper() == "KO") { return "KO"; } return "EN"; } private static void LoadDefaults() { _strings["item.bread.name"] = "Cheap Bread"; _strings["item.bread.choke"] = "Choking on Bread!"; _strings["item.potion.name"] = "Lucid Doom"; _strings["item.potion.use"] = "Vision cleared, but..."; _strings["hud.max_insanity"] = "Peak Insanity"; _strings["weather.blood_night"] = "Blood Night"; } private static Dictionary> ParseLangSections(string json) { Dictionary> dictionary = new Dictionary>(); int i = 0; SkipWhitespace(json, ref i); if (i >= json.Length || json[i] != '{') { return dictionary; } i++; while (i < json.Length) { SkipWhitespace(json, ref i); if (i < json.Length && json[i] == '}') { break; } string key = ReadString(json, ref i); SkipWhitespace(json, ref i); if (i >= json.Length || json[i] != ':') { break; } i++; SkipWhitespace(json, ref i); if (i >= json.Length || json[i] != '{') { break; } i++; Dictionary dictionary2 = new Dictionary(); while (i < json.Length) { SkipWhitespace(json, ref i); if (i < json.Length && json[i] == '}') { i++; break; } string key2 = ReadString(json, ref i); SkipWhitespace(json, ref i); if (i >= json.Length || json[i] != ':') { break; } i++; SkipWhitespace(json, ref i); string value = ReadString(json, ref i); dictionary2[key2] = value; SkipWhitespace(json, ref i); if (i < json.Length && json[i] == ',') { i++; } } dictionary[key] = dictionary2; SkipWhitespace(json, ref i); if (i < json.Length && json[i] == ',') { i++; } } return dictionary; } private static void SkipWhitespace(string s, ref int i) { while (i < s.Length && char.IsWhiteSpace(s[i])) { i++; } } private static string ReadString(string s, ref int i) { if (i >= s.Length || s[i] != '"') { return ""; } i++; StringBuilder stringBuilder = new StringBuilder(); while (i < s.Length && s[i] != '"') { if (s[i] == '\\' && i + 1 < s.Length) { char c = s[i + 1]; switch (c) { case 'n': stringBuilder.Append('\n'); break; case 't': stringBuilder.Append('\t'); break; case 'r': stringBuilder.Append('\r'); break; default: stringBuilder.Append(c); break; } i += 2; } else { stringBuilder.Append(s[i]); i++; } } if (i < s.Length) { i++; } return stringBuilder.ToString(); } } internal static class MaskedTransformManager { private enum Phase { Idle, Slowing, Cutscene, Done } private static Phase _phase; private static float _timer; private static float _savedSpeed; private static PlayerControllerB? _local; private const float SlowDuration = 6f; private const float CutsceneDuration = 2.5f; public static bool IsActive { get { if (_phase != 0) { return _phase != Phase.Done; } return false; } } public static void TriggerTransform(PlayerControllerB local) { if (_phase == Phase.Idle) { _local = local; _savedSpeed = local.movementSpeed; _phase = Phase.Slowing; _timer = 0f; } } public static void Tick(PlayerControllerB local, float deltaTime) { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) if (_phase == Phase.Idle || _phase == Phase.Done) { return; } _timer += deltaTime; if (_phase == Phase.Slowing) { float num = Mathf.Clamp01(_timer / 6f); local.movementSpeed = Mathf.Lerp(_savedSpeed, 0f, num * num); VFXManager.SetBlackout(Mathf.Clamp01((_timer - 4f) / 2f)); if (num >= 1f) { local.movementSpeed = 0f; local.disableMoveInput = true; local.disableLookInput = true; VFXManager.SetBlackout(1f); InsanityNetworkHandler.SendSpawnMasked(local); _phase = Phase.Cutscene; _timer = 0f; } } else if (_phase == Phase.Cutscene && _timer >= 2.5f) { _phase = Phase.Done; VFXManager.SetBlackout(0f); local.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 0, default(Vector3), false); } } public static void Reset() { if ((Object)(object)_local != (Object)null && _phase != 0) { _local.movementSpeed = ((_savedSpeed > 0f) ? _savedSpeed : 4.6f); _local.disableMoveInput = false; _local.disableLookInput = false; } VFXManager.SetBlackout(0f); _phase = Phase.Idle; _timer = 0f; _local = null; } } internal static class VFXManager { private static Image? _overlay; private static Image? _blackOverlay; private static Sprite? _vignetteSprite; public static void Initialize() { SceneManager.sceneLoaded += OnSceneLoaded; } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (!(((Scene)(ref scene)).name != "SampleSceneRelay")) { CreateOverlay(); } } private static void CreateOverlay() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0049: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: 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_013d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_overlay != (Object)null)) { GameObject val = new GameObject("InsanityVFX_Canvas"); Object.DontDestroyOnLoad((Object)(object)val); Canvas obj = val.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 999; val.AddComponent(); val.AddComponent(); GameObject val2 = new GameObject("InsanityVFX_Overlay"); val2.transform.SetParent(val.transform, false); RectTransform obj2 = val2.AddComponent(); obj2.anchorMin = Vector2.zero; obj2.anchorMax = Vector2.one; obj2.sizeDelta = Vector2.zero; _overlay = val2.AddComponent(); ((Graphic)_overlay).raycastTarget = false; _overlay.sprite = GetVignetteSprite(); ((Graphic)_overlay).color = new Color(1f, 0f, 0f, 0f); GameObject val3 = new GameObject("InsanityVFX_Black"); val3.transform.SetParent(val.transform, false); RectTransform obj3 = val3.AddComponent(); obj3.anchorMin = Vector2.zero; obj3.anchorMax = Vector2.one; obj3.sizeDelta = Vector2.zero; _blackOverlay = val3.AddComponent(); ((Graphic)_blackOverlay).raycastTarget = false; ((Graphic)_blackOverlay).color = new Color(0f, 0f, 0f, 0f); } } private static Sprite GetVignetteSprite() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_00f6: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_vignetteSprite != (Object)null) { return _vignetteSprite; } Texture2D val = new Texture2D(256, 256, (TextureFormat)1, false) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(128f, 128f); float num = 128f; Color32[] array = (Color32[])(object)new Color32[65536]; for (int i = 0; i < 256; i++) { for (int j = 0; j < 256; j++) { float num2 = Mathf.Clamp01(Mathf.Pow(Mathf.Clamp01(Vector2.Distance(new Vector2((float)j, (float)i), val2) / num), 2.5f)); array[i * 256 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(num2 * 255f)); } } val.SetPixels32(array); val.Apply(); _vignetteSprite = Sprite.Create(val, new Rect(0f, 0f, 256f, 256f), new Vector2(0.5f, 0.5f)); return _vignetteSprite; } public static void UpdateTunnelVision(float insanity) { //IL_0026: 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) if (!((Object)(object)_overlay == (Object)null)) { float value = ModConfig.TunnelVisionThreshold.Value; float num = InsanityCalculator.TunnelVisionAlpha(insanity, value); float num2 = Mathf.Lerp(((Graphic)_overlay).color.a, num, Time.deltaTime * 2f); float num3 = 0.94f + 0.06f * Mathf.Sin(Time.time * 1.2f); ((Graphic)_overlay).color = new Color(0.45f * num3, 0.02f, 0.02f, num2); } } public static void SetBlackout(float alpha) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_blackOverlay == (Object)null)) { ((Graphic)_blackOverlay).color = new Color(0f, 0f, 0f, alpha); } } public static void ClearEffect() { //IL_0026: 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) if ((Object)(object)_overlay != (Object)null) { ((Graphic)_overlay).color = new Color(1f, 0f, 0f, 0f); } if ((Object)(object)_blackOverlay != (Object)null) { ((Graphic)_blackOverlay).color = new Color(0f, 0f, 0f, 0f); } } } }