Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of InsanityMod v1.0.1
BepInEx\plugins\InsanityMod\InsanityMod.dll
Decompiled 2 hours agousing 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<float> InsanityRateInFacility { get; private set; } public static ConfigEntry<float> InsanityRateOnShip { get; private set; } public static ConfigEntry<float> InsanityDecayOutdoor { get; private set; } public static ConfigEntry<float> BloodNightMultiplier { get; private set; } public static ConfigEntry<int> BloodNightSpawnWeight { get; private set; } public static ConfigEntry<float> TunnelVisionThreshold { get; private set; } public static ConfigEntry<float> MobVisibilityScale { get; private set; } public static ConfigEntry<float> MobVisibilityRange { get; private set; } public static ConfigEntry<float> TeammateBuffRate { get; private set; } public static ConfigEntry<float> TeammateBuffRange { get; private set; } public static ConfigEntry<float> LightBuffRate { get; private set; } public static ConfigEntry<float> DeathWitnessSpike { get; private set; } public static ConfigEntry<float> DeathWitnessRange { get; private set; } public static ConfigEntry<float> GhostGirlBoostThreshold { get; private set; } public static ConfigEntry<float> VoiceHauntThreshold { get; private set; } public static ConfigEntry<float> LightProximityRange { get; private set; } public static ConfigEntry<float> ApparatusMultiplier { get; private set; } public static ConfigEntry<bool> EnableMaskedTransform { get; private set; } public static void Initialize(ConfigFile cfg) { InsanityRateInFacility = cfg.Bind<float>("Insanity", "InsanityRateInFacility", 0.167f, "Insanity gained per second inside the facility (baseline, ~10 min solo to 100%)."); InsanityRateOnShip = cfg.Bind<float>("Insanity", "InsanityRateOnShip", 0f, "Insanity gained per second on the ship."); InsanityDecayOutdoor = cfg.Bind<float>("Insanity", "InsanityDecayOutdoor", 0.8f, "Insanity lost per second outdoors."); BloodNightMultiplier = cfg.Bind<float>("BloodNight", "BloodNightMultiplier", 1.2f, "Insanity rate multiplier when Blood Night weather is active."); BloodNightSpawnWeight = cfg.Bind<int>("BloodNight", "BloodNightSpawnWeight", 20, "Spawn weight for Blood Night weather (other weathers are 100, so ~3% per night at 20)."); TunnelVisionThreshold = cfg.Bind<float>("VFX", "TunnelVisionThreshold", 80f, "Insanity % at which the red tunnel-vision overlay starts."); MobVisibilityScale = cfg.Bind<float>("Reactions", "MobVisibilityScale", 1f, "Multiplier for insanity gained per second per visible enemy (per-type rates are scaled by this)."); MobVisibilityRange = cfg.Bind<float>("Reactions", "MobVisibilityRange", 30f, "Max distance (m) at which a visible enemy contributes to insanity."); TeammateBuffRate = cfg.Bind<float>("Reactions", "TeammateBuffRate", 0.15f, "Insanity-rate reduction per second when at least one living teammate is nearby."); TeammateBuffRange = cfg.Bind<float>("Reactions", "TeammateBuffRange", 6f, "Max distance (m) for the teammate proximity buff."); LightBuffRate = cfg.Bind<float>("Reactions", "LightBuffRate", 0.1f, "Insanity-rate reduction per second when player is illuminated (own flashlight on, or in ship)."); DeathWitnessSpike = cfg.Bind<float>("Reactions", "DeathWitnessSpike", 25f, "Instant insanity gain when a teammate dies in your line of sight."); DeathWitnessRange = cfg.Bind<float>("Reactions", "DeathWitnessRange", 40f, "Max distance (m) for the death witness check."); GhostGirlBoostThreshold = cfg.Bind<float>("Reactions", "GhostGirlBoostThreshold", 80f, "Insanity % above which the host slightly raises Ghost Girl haunt chance (set high to disable)."); VoiceHauntThreshold = cfg.Bind<float>("Reactions", "VoiceHauntThreshold", 70f, "Insanity % at which voice distortion + recorded teammate voice playback start."); LightProximityRange = cfg.Bind<float>("Reactions", "LightProximityRange", 8f, "Max distance (m) to a facility light for the light proximity buff."); ApparatusMultiplier = cfg.Bind<float>("Reactions", "ApparatusMultiplier", 2f, "Insanity rate multiplier inside the facility after the apparatus is removed (lights out)."); EnableMaskedTransform = cfg.Bind<bool>("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<string, VoiceTrack> _tracks = new Dictionary<string, VoiceTrack>(); private static readonly Dictionary<int, VoiceTrack> _tracksByPlayback = new Dictionary<int, VoiceTrack>(); 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<DissonanceComms>(); 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<VoiceTrack> list = new List<VoiceTrack>(); 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<AudioSource>(); 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<AudioLowPassFilter>().cutoffFrequency = Mathf.Lerp(6000f, 1200f, intensity); val2.AddComponent<AudioDistortionFilter>().distortionLevel = Mathf.Lerp(0.15f, 0.65f, intensity); val2.AddComponent<AudioReverbFilter>().reverbPreset = (AudioReverbPreset)2; if (intensity > 0.6f) { AudioEchoFilter obj2 = val2.AddComponent<AudioEchoFilter>(); 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<AudioLowPassFilter>(gameObject); Distortion = GetOrAdd<AudioDistortionFilter>(gameObject); Reverb = GetOrAdd<AudioReverbFilter>(gameObject); Echo = GetOrAdd<AudioEchoFilter>(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<T>(GameObject go) where T : Component { return go.GetComponent<T>() ?? go.AddComponent<T>(); } } } 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<TextMeshProUGUI>(); ((TMP_Text)val4).fontSize = 14f; ((TMP_Text)val4).alignment = (TextAlignmentOptions)513; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("<b>— " + text + " —</b>"); 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) ? "<color=#FF4444>" : "<color=#DDDDDD>"); stringBuilder.AppendLine(text3 + playerUsername + " " + text2 + "</color>"); } } ((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<ulong, float> PlayerMaxInsanity = new Dictionary<ulong, float>(); 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<float>(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<float>(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<int>(ref count, default(ForPrimitives)); foreach (KeyValuePair<ulong, float> item in PlayerMaxInsanity) { ulong key = item.Key; ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref key, default(ForPrimitives)); float value = item.Value; ((FastBufferWriter)(ref val)).WriteValueSafe<float>(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<int>(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<ulong>(ref key, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(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<float>(ref position.x, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref position.y, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref position.z, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(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<float>(ref num, default(ForPrimitives)); float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref num3, default(ForPrimitives)); ulong num4 = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(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<MaskedPlayerEnemy>() ?? ((Component)val3).GetComponentInChildren<MaskedPlayerEnemy>(); 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<EnemyType>(); 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<ImprovedWeatherEffect>(); _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<int>)(object)EventManager.DayChanged).AddListener((ParameterEvent<int>)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<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 50; _canvasGO.AddComponent<CanvasScaler>(); _canvasGO.AddComponent<GraphicRaycaster>(); Sprite ringSprite = GetRingSprite(); RectTransform val = new GameObject("InsanityHud_Root").AddComponent<RectTransform>(); ((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<RectTransform>(); ((Transform)obj2).SetParent((Transform)(object)val, false); obj2.anchorMin = Vector2.zero; obj2.anchorMax = Vector2.one; obj2.sizeDelta = Vector2.zero; _ringBg = val2.AddComponent<Image>(); _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<RectTransform>(); ((Transform)obj3).SetParent((Transform)(object)val, false); obj3.anchorMin = Vector2.zero; obj3.anchorMax = Vector2.one; obj3.sizeDelta = Vector2.zero; _ringFill = val3.AddComponent<Image>(); _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<RectTransform>(); ((Transform)obj4).SetParent((Transform)(object)val, false); obj4.anchorMin = Vector2.zero; obj4.anchorMax = Vector2.one; obj4.sizeDelta = Vector2.zero; _label = val4.AddComponent<TextMeshProUGUI>(); ((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<Light>(); private static float _lastLightCacheTime = -100f; private const float LightCacheRefreshSec = 5f; private static readonly Dictionary<string, float> EnemyRates = new Dictionary<string, float> { { "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<Light>(); _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<Light>(); _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<string, string> _strings = new Dictionary<string, string>(); 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<string, Dictionary<string, string>> dictionary = ParseLangSections(File.ReadAllText(text)); if (!dictionary.TryGetValue(text2, out var value)) { dictionary.TryGetValue("EN", out value); } if (value != null) { foreach (KeyValuePair<string, string> 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<string, Dictionary<string, string>> ParseLangSections(string json) { Dictionary<string, Dictionary<string, string>> dictionary = new Dictionary<string, Dictionary<string, string>>(); 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<string, string> dictionary2 = new Dictionary<string, string>(); 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<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 999; val.AddComponent<CanvasScaler>(); val.AddComponent<GraphicRaycaster>(); GameObject val2 = new GameObject("InsanityVFX_Overlay"); val2.transform.SetParent(val.transform, false); RectTransform obj2 = val2.AddComponent<RectTransform>(); obj2.anchorMin = Vector2.zero; obj2.anchorMax = Vector2.one; obj2.sizeDelta = Vector2.zero; _overlay = val2.AddComponent<Image>(); ((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<RectTransform>(); obj3.anchorMin = Vector2.zero; obj3.anchorMax = Vector2.one; obj3.sizeDelta = Vector2.zero; _blackOverlay = val3.AddComponent<Image>(); ((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); } } } }