Decompiled source of FusionKillerMode v0.3.20
Mods/BONELABFusionKillerMode.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.Json; using BoneLib.BoneMenu; using FusionKillerMode; using HarmonyLib; using Il2CppInterop.Runtime.Attributes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSLZ.Marrow; using Il2CppSLZ.Marrow.Data; using Il2CppSLZ.Marrow.Pool; using Il2CppSLZ.Marrow.Warehouse; using Il2CppSLZ.VRMK; using Il2CppTMPro; using LabFusion.Data; using LabFusion.Downloading; using LabFusion.Entities; using LabFusion.Extensions; using LabFusion.Marrow; using LabFusion.Marrow.Extenders; using LabFusion.Marrow.Integration; using LabFusion.Marrow.Pool; using LabFusion.Menu.Data; using LabFusion.Network; using LabFusion.Player; using LabFusion.Preferences.Client; using LabFusion.RPC; using LabFusion.SDK.Gamemodes; using LabFusion.SDK.Metadata; using LabFusion.SDK.Modules; using LabFusion.SDK.MonoBehaviours; using LabFusion.SDK.Triggers; using LabFusion.Scene; using LabFusion.Senders; using LabFusion.UI.Popups; using LabFusion.Utilities; using LabFusion.Voice; using MelonLoader; using MelonLoader.Preferences; using UnityEngine; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("BONELAB Fusion Killer Mode")] [assembly: AssemblyFileVersion("0.3.20")] [assembly: MelonInfo(typeof(KillerModeMod), "BONELAB Fusion Killer Mode", "0.3.20", "Fusion Killer Mode Team", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: MelonAdditionalDependencies(new string[] { "LabFusion", "BoneLib" })] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.20.0")] [module: UnverifiableCode] namespace FusionKillerMode; internal static class EmbeddedWavLoader { private const string ResourcePrefix = "FusionKillerMode.Assets.Audio."; public static AudioClip Load(string fileName) { try { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("FusionKillerMode.Assets.Audio." + fileName); if (stream == null) { return null; } using BinaryReader binaryReader = new BinaryReader(stream); if (ReadFourCc(binaryReader) != "RIFF") { return null; } binaryReader.ReadUInt32(); if (ReadFourCc(binaryReader) != "WAVE") { return null; } ushort num = 0; ushort num2 = 0; int num3 = 0; ushort num4 = 0; byte[] array = null; while (stream.Position + 8 <= stream.Length) { string text = ReadFourCc(binaryReader); uint num5 = binaryReader.ReadUInt32(); long val = stream.Position + num5 + (num5 & 1); if (text == "fmt ") { num = binaryReader.ReadUInt16(); num2 = binaryReader.ReadUInt16(); num3 = binaryReader.ReadInt32(); binaryReader.ReadUInt32(); binaryReader.ReadUInt16(); num4 = binaryReader.ReadUInt16(); } else if (text == "data") { array = binaryReader.ReadBytes(checked((int)num5)); } stream.Position = Math.Min(val, stream.Length); } if (num != 1 || num4 != 16 || num2 == 0 || num3 <= 0 || array == null) { return null; } int num6 = array.Length / 2; float[] array2 = new float[num6]; for (int i = 0; i < num6; i++) { array2[i] = (float)BitConverter.ToInt16(array, i * 2) / 32768f; } int num7 = num6 / num2; AudioClip obj = AudioClip.Create("KillerMode_" + Path.GetFileNameWithoutExtension(fileName), num7, (int)num2, num3, false); obj.SetData(Il2CppStructArray<float>.op_Implicit(array2), 0); MelonLogger.Msg($"[Killer Mode audio] Loaded {fileName} ({num2}ch, {num3} Hz, {num7} frames)."); return obj; } catch (Exception ex) { MelonLogger.Warning("[Killer Mode] Could not load embedded sound " + fileName + ": " + ex.Message); return null; } } private static string ReadFourCc(BinaryReader reader) { return new string(reader.ReadChars(4)); } } public static class KillerContentReferences { public const string DefaultCombatKnife = "c1534c5a-1fb8-477c-afbe-2a95436f6d62"; public const string BowieKnife = "BurntLettuce.BowieKnife.Spawnable.BowieKnife"; public const string GiantCleaver = "HorrorLab.GiantCleaver2.Spawnable.GiantCleaver"; public const string DeathloopMachete = "Frictic.DeathloopMachete.Spawnable.DeathloopMachete"; public const string Flashlight = "Blueberrycat.BONEWORKSFlashlight.Spawnable.FlashlightBoneworks"; public const string FlashlightBrighter = "Blueberrycat.BONEWORKSFlashlight.Spawnable.FlashlightBoneworksBrighter"; public const string PolyBlankAvatar = "c3534c5a-94b2-40a4-912a-24a8506f6c79"; public const string StrongAvatar = "fa534c5a83ee4ec6bd641fec424c4142.Avatar.Strong"; public const string HeavyAvatar = "fa534c5a83ee4ec6bd641fec424c4142.Avatar.Heavy"; public const string FastAvatar = "fa534c5a83ee4ec6bd641fec424c4142.Avatar.Fast"; public static string GetWeaponBarcode(KillerWeaponChoice choice) { return choice switch { KillerWeaponChoice.DefaultCombatKnife => "c1534c5a-1fb8-477c-afbe-2a95436f6d62", KillerWeaponChoice.GiantCleaver => "HorrorLab.GiantCleaver2.Spawnable.GiantCleaver", KillerWeaponChoice.DeathloopMachete => "Frictic.DeathloopMachete.Spawnable.DeathloopMachete", KillerWeaponChoice.BowieKnife => "BurntLettuce.BowieKnife.Spawnable.BowieKnife", _ => string.Empty, }; } public static string GetKillerAvatarBarcode(KillerSkinChoice choice) { return choice switch { KillerSkinChoice.Strong => "fa534c5a83ee4ec6bd641fec424c4142.Avatar.Strong", KillerSkinChoice.Heavy => "fa534c5a83ee4ec6bd641fec424c4142.Avatar.Heavy", KillerSkinChoice.Fast => "fa534c5a83ee4ec6bd641fec424c4142.Avatar.Fast", KillerSkinChoice.PolyBlank => "c3534c5a-94b2-40a4-912a-24a8506f6c79", _ => string.Empty, }; } public static bool IsInstalled(string barcode) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if (string.IsNullOrWhiteSpace(barcode) || !AssetWarehouse.ready) { return false; } return CrateFilterer.HasCrate<SpawnableCrate>(new Barcode(barcode)); } public static bool IsAvatarInstalled(string barcode) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if (string.IsNullOrWhiteSpace(barcode) || !AssetWarehouse.ready) { return false; } return CrateFilterer.HasCrate<AvatarCrate>(new Barcode(barcode)); } public static bool IsAnyCrateInstalled(string barcode) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if (string.IsNullOrWhiteSpace(barcode) || !AssetWarehouse.ready) { return false; } return CrateFilterer.HasCrate<Crate>(new Barcode(barcode)); } } public static class KillerEnvironmentEffects { private static bool _captured; private static float _ambientIntensity; private static float _reflectionIntensity; private static Color _ambientLight; private static AmbientMode _ambientMode; private static bool _fog; private static Color _fogColor; private static FogMode _fogMode; private static float _fogDensity; private static float _fogStartDistance; private static float _fogEndDistance; private static GameObject _overlayRoot; private static Image _overlayImage; public static void Apply(bool darkMap, int darknessStrength, bool darkFog, int fogStrength) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) Capture(); RestoreCapturedValues(); if (darkMap) { float num = Mathf.Lerp(1f, 0.08f, Mathf.Clamp01((float)darknessStrength / 100f)); RenderSettings.ambientMode = (AmbientMode)3; RenderSettings.ambientIntensity = _ambientIntensity * num; RenderSettings.reflectionIntensity = _reflectionIntensity * Mathf.Lerp(1f, 0.18f, Mathf.Clamp01((float)darknessStrength / 100f)); RenderSettings.ambientLight = _ambientLight * num; } if (darkFog) { float num2 = Mathf.Clamp01((float)fogStrength / 100f); RenderSettings.fog = true; RenderSettings.fogMode = (FogMode)1; RenderSettings.fogColor = Color.Lerp(new Color(0.025f, 0.03f, 0.04f, 1f), Color.black, num2 * 0.75f); RenderSettings.fogStartDistance = Mathf.Lerp(15f, 2f, num2); RenderSettings.fogEndDistance = Mathf.Lerp(70f, 12f, num2); RenderSettings.fogDensity = Mathf.Max(_fogDensity, Mathf.Lerp(0.008f, 0.055f, num2)); } ApplyReliableOverlay(darkMap, darknessStrength, darkFog, fogStrength); } public static void Restore() { if (_captured) { RestoreCapturedValues(); if ((Object)(object)_overlayRoot != (Object)null) { _overlayRoot.SetActive(false); } _captured = false; } } private static void Capture() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (!_captured) { _captured = true; _ambientIntensity = RenderSettings.ambientIntensity; _reflectionIntensity = RenderSettings.reflectionIntensity; _ambientLight = RenderSettings.ambientLight; _ambientMode = RenderSettings.ambientMode; _fog = RenderSettings.fog; _fogColor = RenderSettings.fogColor; _fogMode = RenderSettings.fogMode; _fogDensity = RenderSettings.fogDensity; _fogStartDistance = RenderSettings.fogStartDistance; _fogEndDistance = RenderSettings.fogEndDistance; } } private static void RestoreCapturedValues() { //IL_0014: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) RenderSettings.ambientIntensity = _ambientIntensity; RenderSettings.reflectionIntensity = _reflectionIntensity; RenderSettings.ambientLight = _ambientLight; RenderSettings.ambientMode = _ambientMode; RenderSettings.fog = _fog; RenderSettings.fogColor = _fogColor; RenderSettings.fogMode = _fogMode; RenderSettings.fogDensity = _fogDensity; RenderSettings.fogStartDistance = _fogStartDistance; RenderSettings.fogEndDistance = _fogEndDistance; } private static void ApplyReliableOverlay(bool darkMap, int darknessStrength, bool darkFog, int fogStrength) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) float num = (darkMap ? (Mathf.Clamp01((float)darknessStrength / 100f) * 0.48f) : 0f); float num2 = (darkFog ? Mathf.Lerp(0.04f, 0.22f, Mathf.Clamp01((float)fogStrength / 100f)) : 0f); float num3 = 1f - (1f - num) * (1f - num2); if (!(num3 <= 0.001f) && RigData.HasPlayer) { RigRefs refs = RigData.Refs; if (!((Object)(object)((refs != null) ? refs.Headset : null) == (Object)null)) { EnsureOverlay(); _overlayRoot.SetActive(true); ((Graphic)_overlayImage).color = new Color(0.005f, 0.008f, 0.012f, Mathf.Clamp01(num3)); return; } } if ((Object)(object)_overlayRoot != (Object)null) { _overlayRoot.SetActive(false); } } private static void EnsureOverlay() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_overlayRoot != (Object)null) { _overlayRoot.transform.SetParent(RigData.Refs.Headset, false); return; } _overlayRoot = new GameObject("Killer Mode Synchronized Darkness"); ((Object)_overlayRoot).hideFlags = (HideFlags)52; _overlayRoot.transform.SetParent(RigData.Refs.Headset, false); _overlayRoot.transform.localPosition = new Vector3(0f, 0f, 0.5f); _overlayRoot.transform.localRotation = Quaternion.identity; _overlayRoot.transform.localScale = Vector3.one * 0.45f; Canvas obj = _overlayRoot.AddComponent<Canvas>(); obj.renderMode = (RenderMode)2; obj.overrideSorting = true; obj.sortingOrder = 32740; ((Component)obj).GetComponent<RectTransform>().sizeDelta = new Vector2(8f, 8f); GameObject val = new GameObject("Dark Atmosphere Panel"); val.transform.SetParent(_overlayRoot.transform, false); _overlayImage = val.AddComponent<Image>(); ((Graphic)_overlayImage).raycastTarget = false; RectTransform rectTransform = ((Graphic)_overlayImage).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; } } public static class KillerFlashEffect { private static GameObject _root; private static Image _image; private static float _remaining; private static float _duration; private static float _intensity; public static void Trigger(float duration, float intensity) { if (RigData.HasPlayer) { EnsureVisual(); _duration = Mathf.Max(0.25f, duration); _remaining = _duration; _intensity = Mathf.Clamp01(intensity); _root.SetActive(true); SetAlpha(_intensity); } } public static void Tick() { if (!((Object)(object)_root == (Object)null) && !(_remaining <= 0f)) { _remaining = Mathf.Max(0f, _remaining - Time.deltaTime); float num = ((_duration <= 0f) ? 0f : (_remaining / _duration)); SetAlpha(_intensity * num * num); if (_remaining <= 0f) { _root.SetActive(false); } } } public static void Clear() { _remaining = 0f; if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } _root = null; _image = null; } private static void EnsureVisual() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root != (Object)null) { _root.transform.SetParent(RigData.Refs.Headset, false); return; } _root = new GameObject("Killer Mode Flashbang Whiteout"); ((Object)_root).hideFlags = (HideFlags)52; _root.transform.SetParent(RigData.Refs.Headset, false); _root.transform.localPosition = new Vector3(0f, 0f, 0.45f); _root.transform.localRotation = Quaternion.identity; _root.transform.localScale = Vector3.one * 0.45f; Canvas obj = _root.AddComponent<Canvas>(); obj.renderMode = (RenderMode)2; obj.sortingOrder = 32767; ((Component)obj).GetComponent<RectTransform>().sizeDelta = new Vector2(8f, 8f); GameObject val = new GameObject("White Panel"); val.transform.SetParent(_root.transform, false); _image = val.AddComponent<Image>(); RectTransform rectTransform = ((Graphic)_image).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; ((Graphic)_image).color = Color.white; } private static void SetAlpha(float alpha) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_image != (Object)null) { ((Graphic)_image).color = new Color(1f, 1f, 1f, Mathf.Clamp01(alpha)); } } } [RegisterTypeInIl2Cpp] public sealed class KillerFlashbangRuntime : MonoBehaviour { private GamemodeItem _item; private NetworkEntity _entity; private float _releasedTimer; private bool _detonated; public KillerFlashbangRuntime(IntPtr ptr) : base(ptr) { } [HideFromIl2Cpp] public void Initialize(NetworkEntity entity, GamemodeItem item) { _entity = entity; _item = item; } private void Update() { //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (_detonated || (Object)(object)_item == (Object)null || _entity == null || !_entity.IsOwner || !_item.HasBeenInteracted) { return; } if (_item.IsHeld) { _releasedTimer = 0f; return; } _releasedTimer += Time.deltaTime; if (!(_releasedTimer < 1.2f)) { _detonated = true; KillerModeGamemode.RequestFlashbangDetonation(((Component)this).transform.position); } } } public static class KillerModeAudio { private const int SampleRate = 44100; private static AudioClip _roundStart; private static AudioClip _survivorRoundEnd; private static AudioClip _killerRoundEnd; private static AudioClip _lastSurvivor; private static AudioClip _countdownTick; private static AudioClip _doorOpen; private static AudioClip _survivorEscaped; private static AudioClip _heartbeatSlow; private static AudioClip _heartbeatFast; private static AudioSource _heartbeatSource; private static AudioSource _oneShotSource; private static AudioSource _eventSource; private static bool _heartbeatIsFast; public static void PlayRoundStart() { Play(_roundStart ?? (_roundStart = Load("round_start.wav", CreateRoundStart)), 0.72f); } public static void PlayCountdownTick(int remaining) { remaining = Mathf.Clamp(remaining, 1, 10); Play(_countdownTick ?? (_countdownTick = Load("countdown_tick.wav", () => CreateCountdownTick(remaining))), (remaining <= 3) ? 0.82f : 0.58f); } public static void PlayLastSurvivor() { Play(_lastSurvivor ?? (_lastSurvivor = Load("last_survivor.wav", CreateLastSurvivor)), 0.64f); } public static void PlayDoorOpen() { PlayEvent(_doorOpen ?? (_doorOpen = Load("door_open.wav", CreateDoorOpen)), 0.72f); } public static void PlaySurvivorEscaped() { PlayEvent(_survivorEscaped ?? (_survivorEscaped = Load("survivor_escaped.wav", CreateSurvivorEscaped)), 0.72f); } public static void PlayRoundEnd(bool survivorsWin) { Play(survivorsWin ? (_survivorRoundEnd ?? (_survivorRoundEnd = Load("round_end.wav", () => CreateRoundEnd(survivorsWin: true)))) : (_killerRoundEnd ?? (_killerRoundEnd = Load("round_end.wav", () => CreateRoundEnd(survivorsWin: false)))), 0.76f); } public static void SetHeartbeat(bool enabled, bool fast) { if (!enabled) { StopHeartbeat(); return; } AudioClip val = (fast ? (_heartbeatFast ?? (_heartbeatFast = Load("heartbeat_fast.wav", () => CreateHeartbeat(fast: true)))) : (_heartbeatSlow ?? (_heartbeatSlow = Load("heartbeat_slow.wav", () => CreateHeartbeat(fast: false))))); if (!((Object)(object)val == (Object)null)) { EnsureHeartbeatSource(); ConfigureSource(_heartbeatSource); if ((Object)(object)_heartbeatSource.clip != (Object)(object)val || _heartbeatIsFast != fast) { _heartbeatSource.Stop(); _heartbeatSource.clip = val; _heartbeatIsFast = fast; } _heartbeatSource.volume = (fast ? 0.34f : 0.27f); if (!_heartbeatSource.isPlaying) { _heartbeatSource.Play(); } } } public static void StopHeartbeat() { if (!((Object)(object)_heartbeatSource == (Object)null)) { _heartbeatSource.Stop(); _heartbeatSource.clip = null; } } private static void Play(AudioClip clip, float volume) { if (!((Object)(object)clip == (Object)null)) { EnsureOneShotSource(); ConfigureSource(_oneShotSource); _oneShotSource.Stop(); _oneShotSource.PlayOneShot(clip, Mathf.Clamp01(volume)); MelonLogger.Msg("[Killer Mode audio] Playing " + ((Object)clip).name + "."); } } private static void PlayEvent(AudioClip clip, float volume) { if (!((Object)(object)clip == (Object)null)) { EnsureEventSource(); ConfigureSource(_eventSource); _eventSource.Stop(); _eventSource.PlayOneShot(clip, Mathf.Clamp01(volume)); MelonLogger.Msg("[Killer Mode audio] Playing " + ((Object)clip).name + "."); } } private static AudioClip Load(string fileName, Func<AudioClip> fallback) { return EmbeddedWavLoader.Load(fileName) ?? fallback(); } private static void EnsureHeartbeatSource() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)_heartbeatSource != (Object)null)) { GameObject val = new GameObject("KillerMode_LastSurvivorHeartbeat"); Object.DontDestroyOnLoad((Object)val); _heartbeatSource = val.AddComponent<AudioSource>(); _heartbeatSource.playOnAwake = false; _heartbeatSource.loop = true; _heartbeatSource.spatialBlend = 0f; _heartbeatSource.bypassReverbZones = true; ConfigureSource(_heartbeatSource); } } private static void EnsureOneShotSource() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)_oneShotSource != (Object)null)) { GameObject val = new GameObject("KillerMode_OneShotAudio"); Object.DontDestroyOnLoad((Object)val); _oneShotSource = val.AddComponent<AudioSource>(); _oneShotSource.playOnAwake = false; _oneShotSource.loop = false; _oneShotSource.spatialBlend = 0f; _oneShotSource.bypassReverbZones = true; ConfigureSource(_oneShotSource); } } private static void EnsureEventSource() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)_eventSource != (Object)null)) { GameObject val = new GameObject("KillerMode_EventAudio"); Object.DontDestroyOnLoad((Object)val); _eventSource = val.AddComponent<AudioSource>(); _eventSource.playOnAwake = false; _eventSource.loop = false; _eventSource.spatialBlend = 0f; _eventSource.bypassReverbZones = true; ConfigureSource(_eventSource); } } private static void ConfigureSource(AudioSource source) { if (!((Object)(object)source == (Object)null)) { source.mute = false; source.priority = 0; source.ignoreListenerPause = true; source.spatialBlend = 0f; source.bypassReverbZones = true; if ((Object)(object)LocalAudioPlayer.InHead != (Object)null) { source.outputAudioMixerGroup = LocalAudioPlayer.InHead; } } } private static AudioClip CreateRoundStart() { return Create("KillerMode_RoundStart", 1.25f, delegate(float time, Random random) { float num = Mathf.Sin((float)Math.PI * 2f * (58f + 34f * time) * time) * Mathf.Exp(-3.4f * time); float num2 = Mathf.Sin((float)Math.PI * 2f * (310f + 520f * time) * time) * Mathf.Exp(-4.5f * time); float num3 = ((float)random.NextDouble() * 2f - 1f) * Mathf.Exp(-8f * time); return 0.62f * num + 0.18f * num2 + 0.1f * num3; }); } private static AudioClip CreateCountdownTick(int remaining) { float frequency = 520f + (float)(10 - remaining) * 38f; return Create($"KillerMode_Countdown_{remaining}", 0.16f, (float time, Random _) => Mathf.Exp(-24f * time) * (0.72f * Mathf.Sin((float)Math.PI * 2f * frequency * time) + 0.18f * Mathf.Sin((float)Math.PI * 2f * frequency * 2.01f * time))); } private static AudioClip CreateLastSurvivor() { return Create("KillerMode_LastSurvivor", 2.35f, delegate(float time, Random random) { float num = Mathf.Clamp01(time * 3f); float num2 = Mathf.Clamp01((2.35f - time) * 1.2f); float num3 = num * num2; float num4 = Mathf.Sin((float)Math.PI * 108f * time) + 0.7f * Mathf.Sin((float)Math.PI * 115f * time); float num5 = Mathf.Sin((float)Math.PI * 2f * (1.7f + time * 0.5f) * time); float num6 = ((float)random.NextDouble() * 2f - 1f) * 0.08f; return num3 * (0.3f * num4 * (0.75f + 0.25f * num5) + num6); }); } private static AudioClip CreateDoorOpen() { return Create("KillerMode_DoorOpen", 1.6f, delegate(float time, Random random) { float num = Mathf.Sin((float)Math.PI * 2f * (112f - 34f * time) * time) * Mathf.Exp(-28f * time); float num2 = Mathf.Max(0f, time - 0.13f); float num3 = ((time >= 0.13f) ? (Mathf.Sin((float)Math.PI * 2f * (205f - 70f * num2) * num2) * Mathf.Exp(-34f * num2)) : 0f); float num4 = Mathf.Max(0f, time - 0.16f); float num5 = ((time >= 0.16f) ? (Mathf.Clamp01(num4 * 7f) * Mathf.Clamp01((1.48f - time) * 2.3f)) : 0f); float num6 = Mathf.Sin((float)Math.PI * 2f * (47f + 11f * num4) * num4) * num5; float num7 = Mathf.Sin((float)Math.PI * 242f * num4) * num5 * (0.55f + 0.45f * Mathf.Sin((float)Math.PI * 14f * num4)); float num8 = ((float)random.NextDouble() * 2f - 1f) * num5; float num9 = Mathf.Max(0f, time - 1.28f); float num10 = ((time >= 1.28f) ? (Mathf.Sin((float)Math.PI * 2f * (78f - 20f * num9) * num9) * Mathf.Exp(-18f * num9)) : 0f); return 0.72f * num + 0.42f * num3 + 0.31f * num6 + 0.09f * num7 + 0.035f * num8 + 0.58f * num10; }); } private static AudioClip CreateSurvivorEscaped() { return Create("KillerMode_SurvivorEscaped", 0.95f, delegate(float time, Random _) { float num = Mathf.Clamp01(time * 14f) * Mathf.Clamp01((0.95f - time) * 3.5f); float num2 = Mathf.Sin((float)Math.PI * 1040f * time) * Mathf.Exp(-5f * time); float num3 = Mathf.Max(0f, time - 0.22f); float num4 = Mathf.Sin((float)Math.PI * 1440f * num3) * Mathf.Exp(-5.5f * num3); return num * (0.34f * num2 + 0.42f * num4); }); } private static AudioClip CreateRoundEnd(bool survivorsWin) { return Create(survivorsWin ? "KillerMode_SurvivorsWin" : "KillerMode_KillerWins", 1.8f, delegate(float time, Random random) { float num = (survivorsWin ? 1f : (-1f)); float num2 = 150f + num * 42f * time; float num3 = Mathf.Clamp01(time * 8f) * Mathf.Clamp01((1.8f - time) * 1.5f); float num4 = Mathf.Sin((float)Math.PI * 2f * num2 * time) + 0.42f * Mathf.Sin((float)Math.PI * 2f * num2 * 1.5f * time); float num5 = Mathf.Sin((float)Math.PI * 108f * time) * Mathf.Exp(-5f * time); float num6 = ((float)random.NextDouble() * 2f - 1f) * Mathf.Exp(-7f * time); return num3 * 0.28f * num4 + 0.48f * num5 + 0.06f * num6; }); } private static AudioClip CreateHeartbeat(bool fast) { float seconds = (fast ? 0.82f : 1.45f); return Create(fast ? "KillerMode_HeartbeatFast" : "KillerMode_HeartbeatSlow", seconds, delegate(float time, Random _) { float num = Mathf.Exp(-42f * time) * Mathf.Sin((float)Math.PI * 116f * time); float num2 = Mathf.Max(0f, time - (fast ? 0.22f : 0.34f)); float num3 = Mathf.Exp(-48f * num2) * Mathf.Sin((float)Math.PI * 104f * num2); return 0.72f * num + 0.54f * num3; }); } private static AudioClip Create(string name, float seconds, Func<float, Random, float> sample) { int num = Mathf.CeilToInt(seconds * 44100f); float[] array = new float[num]; Random arg = new Random(name.GetHashCode()); for (int i = 0; i < num; i++) { array[i] = Mathf.Clamp(sample((float)i / 44100f, arg), -0.95f, 0.95f); } AudioClip obj = AudioClip.Create(name, num, 1, 44100, false); obj.SetData(Il2CppStructArray<float>.op_Implicit(array), 0); return obj; } } public static class KillerModeBranding { private const string LogoResource = "FusionKillerMode.Assets.KillerModeLogo.png"; private static Texture2D _logo; public static Texture Logo { get { //IL_0062: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown if ((Object)(object)_logo != (Object)null) { return (Texture)(object)_logo; } try { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("FusionKillerMode.Assets.KillerModeLogo.png"); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = stream.Read(array, i, array.Length - i); if (num <= 0) { break; } } _logo = new Texture2D(2, 2, (TextureFormat)4, false) { name = "Killer Mode Logo", wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; ImageConversion.LoadImage(_logo, Il2CppStructArray<byte>.op_Implicit(array)); } catch (Exception ex) { MelonLogger.Warning("[Killer Mode] Could not load the embedded logo: " + ex.Message); } return (Texture)(object)_logo; } } } public static class KillerModeHud { private static GameObject _root; private static TextMeshProUGUI _text; private static Image _background; private static string _lastText; private static Color _lastColor; public static void Update(KillerRoundState state, int remainingSeconds, KillerPlayerState localRole, bool enabled) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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_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_013e: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: 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_010e: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) if (!enabled || state == KillerRoundState.Lobby || state == KillerRoundState.Ending) { SetVisible(visible: false); } else if (EnsureCreated()) { object obj = state switch { KillerRoundState.Preparing => "ROUND STARTING", KillerRoundState.SurvivorHeadStart => (localRole != KillerPlayerState.Killer) ? "HEAD START" : "SURVIVORS HIDING", KillerRoundState.ExitOpen => "EXIT OPEN • ROUND TIME", _ => "ROUND TIME", }; string text = ((state == KillerRoundState.Preparing) ? Math.Max(0, remainingSeconds).ToString() : FormatTime(remainingSeconds)); string text2 = (string?)obj + " • " + text; Color val = (Color)(state switch { KillerRoundState.Preparing => new Color(1f, 0.78f, 0.18f, 1f), KillerRoundState.ExitOpen => new Color(0.3f, 1f, 0.45f, 1f), _ => (localRole != KillerPlayerState.Killer) ? new Color(0.4f, 1f, 0.55f, 1f) : new Color(1f, 0.3f, 0.3f, 1f), }); if (_lastText != text2) { _lastText = text2; ((TMP_Text)_text).text = text2; } if (_lastColor != val) { _lastColor = val; ((Graphic)_text).color = val; } SetVisible(visible: true); } } public static void Destroy() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } _root = null; _text = null; _background = null; _lastText = null; _lastColor = default(Color); } private static bool EnsureCreated() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00bb: 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_00f8: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root != (Object)null && (Object)(object)_text != (Object)null) { return true; } if (RigData.HasPlayer) { RigRefs refs = RigData.Refs; if (!((Object)(object)((refs != null) ? refs.Headset : null) == (Object)null)) { _root = new GameObject("KillerMode_RoundTimerHUD"); Canvas obj = _root.AddComponent<Canvas>(); obj.renderMode = (RenderMode)2; obj.overrideSorting = true; obj.sortingOrder = 32760; Transform transform = _root.transform; transform.SetParent(RigData.Refs.Headset, false); transform.localPosition = new Vector3(0f, -0.19f, 0.58f); transform.localRotation = Quaternion.identity; transform.localScale = Vector3.one * 0.00065f; RectTransform component = _root.GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { component.sizeDelta = new Vector2(500f, 58f); } GameObject val = new GameObject("Background"); val.transform.SetParent(transform, false); _background = val.AddComponent<Image>(); ((Graphic)_background).color = new Color(0.015f, 0.015f, 0.02f, 0.72f); ((Graphic)_background).raycastTarget = false; Stretch(val.GetComponent<RectTransform>()); GameObject val2 = new GameObject("Time"); val2.transform.SetParent(transform, false); _text = val2.AddComponent<TextMeshProUGUI>(); ((TMP_Text)_text).alignment = (TextAlignmentOptions)514; ((TMP_Text)_text).fontSize = 27f; ((TMP_Text)_text).fontStyle = (FontStyles)1; ((TMP_Text)_text).enableWordWrapping = false; ((Graphic)_text).raycastTarget = false; ((TMP_Text)_text).outlineWidth = 0.16f; ((TMP_Text)_text).outlineColor = new Color32((byte)0, (byte)0, (byte)0, (byte)230); Stretch(val2.GetComponent<RectTransform>()); return true; } } return false; } private static void Stretch(RectTransform rect) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_0040: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rect == (Object)null)) { rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.offsetMin = new Vector2(12f, 4f); rect.offsetMax = new Vector2(-12f, -4f); } } private static void SetVisible(bool visible) { if ((Object)(object)_root != (Object)null && _root.activeSelf != visible) { _root.SetActive(visible); } } private static string FormatTime(int totalSeconds) { totalSeconds = Math.Max(0, totalSeconds); return $"{totalSeconds / 60:00}:{totalSeconds % 60:00}"; } } public static class KillerModeClientPreferences { private static MelonPreferences_Category _category; private static MelonPreferences_Entry<bool> _modeSounds; private static MelonPreferences_Entry<bool> _lastSurvivorHeartbeat; private static MelonPreferences_Entry<bool> _roundTimer; private static MelonPreferences_Entry<bool> _gameNotifications; private static MelonPreferences_Entry<bool> _automaticLeaderboard; public static bool ModeSounds => _modeSounds?.Value ?? true; public static bool LastSurvivorHeartbeat => _lastSurvivorHeartbeat?.Value ?? true; public static bool RoundTimer => _roundTimer?.Value ?? true; public static bool GameNotifications => _gameNotifications?.Value ?? true; public static bool AutomaticLeaderboard => _automaticLeaderboard?.Value ?? true; public static void Initialize() { _category = MelonPreferences.CreateCategory("BONELAB Fusion Killer Mode - Personal"); _modeSounds = _category.CreateEntry<bool>("ModeSounds", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); _lastSurvivorHeartbeat = _category.CreateEntry<bool>("LastSurvivorHeartbeat", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); _roundTimer = _category.CreateEntry<bool>("RoundTimer", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); _gameNotifications = _category.CreateEntry<bool>("GameNotifications", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); _automaticLeaderboard = _category.CreateEntry<bool>("AutomaticLeaderboard", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); } public static void SetModeSounds(bool value) { Save(_modeSounds, value); } public static void SetLastSurvivorHeartbeat(bool value) { Save(_lastSurvivorHeartbeat, value); if (!value) { KillerModeAudio.StopHeartbeat(); } } public static void SetRoundTimer(bool value) { Save(_roundTimer, value); } public static void SetGameNotifications(bool value) { Save(_gameNotifications, value); } public static void SetAutomaticLeaderboard(bool value) { Save(_automaticLeaderboard, value); } private static void Save(MelonPreferences_Entry<bool> entry, bool value) { if (entry != null) { entry.Value = value; _category.SaveToFile(false); } } } public static class KillerModePreferences { private static MelonPreferences_Category _category; private static MelonPreferences_Entry<string> _settingsJson; public static KillerModeSettings Current { get; private set; } = new KillerModeSettings(); public static void Initialize() { _category = MelonPreferences.CreateCategory("BONELAB Fusion Killer Mode"); _settingsJson = _category.CreateEntry<string>("HostSettings", string.Empty, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); if (string.IsNullOrWhiteSpace(_settingsJson.Value)) { return; } try { int num = 0; using (JsonDocument jsonDocument = JsonDocument.Parse(_settingsJson.Value)) { if (jsonDocument.RootElement.TryGetProperty("SettingsSchemaVersion", out var value) && value.TryGetInt32(out var value2)) { num = value2; } } Current = JsonSerializer.Deserialize<KillerModeSettings>(_settingsJson.Value) ?? new KillerModeSettings(); if (num <= 1) { Current.MigrateFrom(num); if (num < 1) { _settingsJson.Value = JsonSerializer.Serialize(Current); _category.SaveToFile(false); MelonLogger.Msg($"[Killer Mode] Updated saved settings from schema {num} to {1}."); } } else { MelonLogger.Warning($"[Killer Mode] Saved settings schema {num} is newer than supported schema {1}; loaded known values without rewriting the file."); } } catch (Exception ex) { MelonLogger.Warning("[Killer Mode] Could not load saved host settings: " + ex.Message); Current = new KillerModeSettings(); } } public static void Save(KillerModeSettings settings) { Current.CopyFrom(settings); Current.SettingsSchemaVersion = 1; _settingsJson.Value = JsonSerializer.Serialize(Current); _category.SaveToFile(false); } } public sealed class KillerModeSettings { public const int CurrentSchemaVersion = 1; public int SettingsSchemaVersion { get; set; } = 1; public int MinimumPlayers { get; set; } = 2; public int StartCountdownSeconds { get; set; } = 10; public int RoundSeconds { get; set; } = 600; public int HeadStartSeconds { get; set; } = 30; public int ExitOpenTimeRemaining { get; set; } = 60; public float KillerVitality { get; set; } = 3f; public float SurvivorVitality { get; set; } = 1f; public float KillerSpeedMultiplier { get; set; } = 1.1f; public float SurvivorSpeedMultiplier { get; set; } = 1f; public bool KillerCanDie { get; set; } public bool SurvivorsCanDamageKiller { get; set; } public bool PreventSameKillerTwice { get; set; } = true; public bool LastSurvivorRevealEnabled { get; set; } = true; public int LastSurvivorRevealInterval { get; set; } = 10; public int LastSurvivorRevealDuration { get; set; } = 2; public bool ClearStartingInventory { get; set; } = true; public bool GiveSurvivorsWeapon { get; set; } public bool SpawnSurvivorFlashlights { get; set; } = true; public bool GiveSurvivorSmokeGrenades { get; set; } public int SmokeGrenadeCount { get; set; } = 1; public bool EnableModeSounds { get; set; } = true; public bool ShowRoundTimer { get; set; } = true; public bool DarkMapEnabled { get; set; } public int DarknessStrength { get; set; } = 70; public bool DarkFogEnabled { get; set; } public int FogStrength { get; set; } = 35; public bool FlashbangBrightEffect { get; set; } = true; public float FlashbangRadius { get; set; } = 18f; public float FlashbangDuration { get; set; } = 3f; public bool GiveSurvivorsFlashbangs { get; set; } public KillerMapModeOverride MapModeOverride { get; set; } public KillerGameplayPreset GameplayPreset { get; set; } public KillerSelectionMode SelectionMode { get; set; } public KillerWeaponChoice WeaponChoice { get; set; } = KillerWeaponChoice.GiantCleaver; public KillerSkinChoice SkinChoice { get; set; } public string KillerAvatarBarcode { get; set; } = string.Empty; public string CustomKillerWeaponBarcode { get; set; } = string.Empty; public string SurvivorWeaponBarcode { get; set; } = string.Empty; public string FlashlightBarcode { get; set; } = "Blueberrycat.BONEWORKSFlashlight.Spawnable.FlashlightBoneworks"; public string SmokeGrenadeBarcode { get; set; } = string.Empty; public string FlashbangBarcode { get; set; } = string.Empty; public void MigrateFrom(int sourceSchemaVersion) { Normalize(); SettingsSchemaVersion = 1; } public void Normalize() { MinimumPlayers = Math.Clamp(MinimumPlayers, 1, 32); StartCountdownSeconds = Math.Clamp(StartCountdownSeconds, 3, 30); RoundSeconds = Math.Clamp(RoundSeconds, 60, 3600); HeadStartSeconds = Math.Clamp(HeadStartSeconds, 0, 180); ExitOpenTimeRemaining = Math.Clamp(ExitOpenTimeRemaining, 0, 600); KillerVitality = Math.Clamp(KillerVitality, 0.2f, 20f); SurvivorVitality = Math.Clamp(SurvivorVitality, 0.2f, 20f); KillerSpeedMultiplier = Math.Clamp(KillerSpeedMultiplier, 0.5f, 2f); SurvivorSpeedMultiplier = Math.Clamp(SurvivorSpeedMultiplier, 0.5f, 2f); LastSurvivorRevealInterval = Math.Clamp(LastSurvivorRevealInterval, 3, 60); LastSurvivorRevealDuration = Math.Clamp(LastSurvivorRevealDuration, 1, 10); SmokeGrenadeCount = Math.Clamp(SmokeGrenadeCount, 1, 10); DarknessStrength = Math.Clamp(DarknessStrength, 0, 100); FogStrength = Math.Clamp(FogStrength, 0, 100); if (!Enum.IsDefined(typeof(KillerMapModeOverride), MapModeOverride)) { MapModeOverride = KillerMapModeOverride.Auto; } if (!Enum.IsDefined(typeof(KillerGameplayPreset), GameplayPreset)) { GameplayPreset = KillerGameplayPreset.Custom; } if (!Enum.IsDefined(typeof(KillerSelectionMode), SelectionMode)) { SelectionMode = KillerSelectionMode.Random; } if (!Enum.IsDefined(typeof(KillerWeaponChoice), WeaponChoice)) { WeaponChoice = KillerWeaponChoice.GiantCleaver; } if (!Enum.IsDefined(typeof(KillerSkinChoice), SkinChoice)) { SkinChoice = KillerSkinChoice.PlayerAvatar; } if (KillerAvatarBarcode == null) { string text = (KillerAvatarBarcode = string.Empty); } if (CustomKillerWeaponBarcode == null) { string text = (CustomKillerWeaponBarcode = string.Empty); } if (SurvivorWeaponBarcode == null) { string text = (SurvivorWeaponBarcode = string.Empty); } FlashlightBarcode = (string.IsNullOrWhiteSpace(FlashlightBarcode) ? "Blueberrycat.BONEWORKSFlashlight.Spawnable.FlashlightBoneworks" : FlashlightBarcode); if (SmokeGrenadeBarcode == null) { string text = (SmokeGrenadeBarcode = string.Empty); } if (FlashbangBarcode == null) { string text = (FlashbangBarcode = string.Empty); } } public void CopyFrom(KillerModeSettings other) { if (other != null) { SettingsSchemaVersion = 1; MinimumPlayers = other.MinimumPlayers; StartCountdownSeconds = other.StartCountdownSeconds; RoundSeconds = other.RoundSeconds; HeadStartSeconds = other.HeadStartSeconds; ExitOpenTimeRemaining = other.ExitOpenTimeRemaining; KillerVitality = other.KillerVitality; SurvivorVitality = other.SurvivorVitality; KillerSpeedMultiplier = other.KillerSpeedMultiplier; SurvivorSpeedMultiplier = other.SurvivorSpeedMultiplier; KillerCanDie = other.KillerCanDie; SurvivorsCanDamageKiller = other.SurvivorsCanDamageKiller; PreventSameKillerTwice = other.PreventSameKillerTwice; LastSurvivorRevealEnabled = other.LastSurvivorRevealEnabled; LastSurvivorRevealInterval = other.LastSurvivorRevealInterval; LastSurvivorRevealDuration = other.LastSurvivorRevealDuration; ClearStartingInventory = other.ClearStartingInventory; GiveSurvivorsWeapon = other.GiveSurvivorsWeapon; SpawnSurvivorFlashlights = other.SpawnSurvivorFlashlights; GiveSurvivorSmokeGrenades = other.GiveSurvivorSmokeGrenades; SmokeGrenadeCount = Math.Clamp(other.SmokeGrenadeCount, 1, 10); EnableModeSounds = other.EnableModeSounds; ShowRoundTimer = other.ShowRoundTimer; DarkMapEnabled = other.DarkMapEnabled; DarknessStrength = other.DarknessStrength; DarkFogEnabled = other.DarkFogEnabled; FogStrength = other.FogStrength; FlashbangBrightEffect = other.FlashbangBrightEffect; FlashbangRadius = other.FlashbangRadius; FlashbangDuration = other.FlashbangDuration; GiveSurvivorsFlashbangs = other.GiveSurvivorsFlashbangs; MapModeOverride = other.MapModeOverride; GameplayPreset = other.GameplayPreset; SelectionMode = other.SelectionMode; WeaponChoice = other.WeaponChoice; SkinChoice = other.SkinChoice; KillerAvatarBarcode = other.KillerAvatarBarcode ?? string.Empty; CustomKillerWeaponBarcode = other.CustomKillerWeaponBarcode ?? string.Empty; SurvivorWeaponBarcode = other.SurvivorWeaponBarcode ?? string.Empty; FlashlightBarcode = (string.IsNullOrWhiteSpace(other.FlashlightBarcode) ? "Blueberrycat.BONEWORKSFlashlight.Spawnable.FlashlightBoneworks" : other.FlashlightBarcode); SmokeGrenadeBarcode = other.SmokeGrenadeBarcode ?? string.Empty; FlashbangBarcode = other.FlashbangBarcode ?? string.Empty; Normalize(); } } public void ApplyPreset(KillerGameplayPreset preset) { GameplayPreset = preset; switch (preset) { case KillerGameplayPreset.Classic: RoundSeconds = 600; HeadStartSeconds = 30; KillerVitality = 3f; SurvivorVitality = 1f; KillerSpeedMultiplier = 1.1f; SurvivorSpeedMultiplier = 1f; KillerCanDie = false; SurvivorsCanDamageKiller = false; LastSurvivorRevealEnabled = true; DarkMapEnabled = false; DarkFogEnabled = false; break; case KillerGameplayPreset.Casual: RoundSeconds = 720; HeadStartSeconds = 45; KillerVitality = 2f; SurvivorVitality = 1.25f; KillerSpeedMultiplier = 1.02f; SurvivorSpeedMultiplier = 1.05f; KillerCanDie = true; SurvivorsCanDamageKiller = true; LastSurvivorRevealEnabled = false; DarkMapEnabled = false; DarkFogEnabled = false; break; case KillerGameplayPreset.Hardcore: RoundSeconds = 480; HeadStartSeconds = 20; KillerVitality = 5f; SurvivorVitality = 0.8f; KillerSpeedMultiplier = 1.2f; SurvivorSpeedMultiplier = 0.95f; KillerCanDie = false; SurvivorsCanDamageKiller = false; LastSurvivorRevealEnabled = true; DarkMapEnabled = true; DarknessStrength = 78; DarkFogEnabled = true; FogStrength = 32; break; } } } public enum KillerRoundState { Lobby, Preparing, SurvivorHeadStart, Hunt, ExitOpen, Ending } public enum KillerPlayerState { None, Killer, SurvivorAlive, SurvivorEliminated, SurvivorEscaped, Spectator, Disconnected } public enum KillerMapMode { Survival, Escape } public enum KillerMapModeOverride { Auto, Survival, Escape } public enum KillerSelectionMode { Random, Host, Rotation } public enum KillerWeaponChoice { MapDefined, DefaultCombatKnife, GiantCleaver, DeathloopMachete, BowieKnife, CustomBarcode, Random } public enum KillerGameplayPreset { Custom, Classic, Casual, Hardcore } public enum KillerSkinChoice { PlayerAvatar, SelectedDownloadedAvatar, Strong, Heavy, Fast, PolyBlank } public enum KillerSpawnRole { Lobby, Killer, Survivor, Spectator } public enum KillerItemAudience { Everyone, KillerOnly, SurvivorsOnly } public enum KillerDoorRule { LockedUntilHunt, LockedUntilExitOpen, AlwaysUnlocked } public enum KillerDoorAnimation { None, SlideUp, Swing } public enum KillerWinReason { None, KillerEliminatedSurvivors, SurvivorsOutlastedTimer, SurvivorEscaped, KillerDisconnected, KillerDied, NotEnoughPlayers, SoloTestComplete } public enum KillerRoundOutcome { Killer, Survived, Escaped, Died, Disconnected, LeftBehind, Spectator } public static class KillerRoundRules { public static KillerMapMode ResolveMapMode(KillerMapModeOverride mapOverride, bool hasEscapeZone, bool hasExitDoor) { return mapOverride switch { KillerMapModeOverride.Survival => KillerMapMode.Survival, KillerMapModeOverride.Escape => KillerMapMode.Escape, _ => (hasEscapeZone || hasExitDoor) ? KillerMapMode.Escape : KillerMapMode.Survival, }; } public static bool IsSpectator(KillerPlayerState state) { if (state != KillerPlayerState.Spectator && state != KillerPlayerState.SurvivorEliminated) { return state == KillerPlayerState.SurvivorEscaped; } return true; } public static bool CanHearVoice(KillerPlayerState listener, KillerPlayerState speaker) { bool num = listener == KillerPlayerState.Killer || listener == KillerPlayerState.SurvivorAlive; bool flag = speaker == KillerPlayerState.Killer || speaker == KillerPlayerState.SurvivorAlive; bool flag2 = IsSpectator(listener); bool flag3 = IsSpectator(speaker); if (!(num && flag)) { return flag2 && flag3; } return true; } public static bool CanAttack(KillerPlayerState attacker, KillerPlayerState target, KillerRoundState round, bool survivorsCanDamageKiller) { if (round != KillerRoundState.Hunt && round != KillerRoundState.ExitOpen) { return false; } switch (attacker) { case KillerPlayerState.Killer: return target == KillerPlayerState.SurvivorAlive; case KillerPlayerState.SurvivorAlive: if (survivorsCanDamageKiller) { return target == KillerPlayerState.Killer; } return false; default: return false; } } public static bool ShouldOpenExit(KillerMapMode mode, KillerRoundState state, int remainingSeconds, int openTimeRemaining) { if (mode != KillerMapMode.Escape || state == KillerRoundState.ExitOpen) { return false; } return remainingSeconds <= Math.Max(0, openTimeRemaining); } public static KillerWinReason TimerExpired(KillerMapMode mode, bool anyEscaped) { if (mode != KillerMapMode.Survival) { if (!anyEscaped) { return KillerWinReason.KillerEliminatedSurvivors; } return KillerWinReason.SurvivorEscaped; } return KillerWinReason.SurvivorsOutlastedTimer; } public static bool ShouldEndForNoLivingSurvivors(bool soloTest, int livingSurvivors) { if (!soloTest) { return livingSurvivors <= 0; } return false; } public static bool CanStartRoundNow(bool isHost, bool roundStarted, bool requirementsMet) { return isHost && !roundStarted && requirementsMet; } public static bool ShouldDeferAutomaticPause(bool roundStarted) { return roundStarted; } public static bool ShouldWaitForSelectedAvatarBarcode(bool isKiller, KillerSkinChoice choice, string barcode) { if (isKiller && choice == KillerSkinChoice.SelectedDownloadedAvatar) { return string.IsNullOrWhiteSpace(barcode); } return false; } public static bool IsDoorLocked(KillerDoorRule rule, KillerRoundState state, KillerMapMode mode = KillerMapMode.Escape) { return rule switch { KillerDoorRule.LockedUntilHunt => state < KillerRoundState.Hunt, KillerDoorRule.LockedUntilExitOpen => mode != KillerMapMode.Escape || state < KillerRoundState.ExitOpen, _ => false, }; } public static KillerRoundOutcome GetRoundOutcome(KillerPlayerState initialRole, KillerPlayerState finalState, KillerWinReason reason, KillerMapMode mode) { if (finalState == KillerPlayerState.Disconnected) { return KillerRoundOutcome.Disconnected; } switch (initialRole) { case KillerPlayerState.Killer: if (reason != KillerWinReason.KillerDied) { return KillerRoundOutcome.Killer; } return KillerRoundOutcome.Died; default: return KillerRoundOutcome.Spectator; case KillerPlayerState.SurvivorAlive: switch (finalState) { case KillerPlayerState.SurvivorEscaped: return KillerRoundOutcome.Escaped; case KillerPlayerState.SurvivorEliminated: return KillerRoundOutcome.Died; case KillerPlayerState.SurvivorAlive: if (reason == KillerWinReason.KillerDisconnected || reason == KillerWinReason.KillerDied || (mode == KillerMapMode.Survival && reason == KillerWinReason.SurvivorsOutlastedTimer)) { return KillerRoundOutcome.Survived; } if (mode == KillerMapMode.Escape) { return KillerRoundOutcome.LeftBehind; } break; } return KillerRoundOutcome.Spectator; } } } public class KillerModeGamemode : Gamemode { private sealed class SpawnedRoundItem { public ushort EntityId; public GameObject GameObject; public bool DestroyOnRoundEnd; public KillerItemSpawnPoint Source; } private sealed class ItemSpawnerState { public KillerItemSpawnPoint Point; public GamemodeItem CurrentItem; public float Cooldown; public int Uses; } private sealed class RoundParticipant { public ulong PlatformId; public string Name; public KillerPlayerState InitialRole; public KillerPlayerState FinalState; public KillerRoundOutcome? ForcedOutcome; } private sealed class RoundParticipantResult { public RoundParticipant Participant; public KillerRoundOutcome Outcome; } private const string InGameMapSetupMetadataKey = "InGameMapSetupProfile"; private const string InGameMapSetupRevisionKey = "InGameMapSetupRevision"; private const string RoundResultsMetadataKey = "RoundResults"; public readonly KillerModeSettings Settings = new KillerModeSettings(); private readonly TeamManager _teams = new TeamManager(); private readonly Team _killerTeam = new Team("Killer"); private readonly Team _survivorTeam = new Team("Survivors"); private readonly Team _spectatorTeam = new Team("Spectators"); private readonly MetadataPlayerDictionary<MetadataInt> _playerStates = new MetadataPlayerDictionary<MetadataInt>(); private readonly Dictionary<ulong, KillerPlayerState> _hostPlayerStates = new Dictionary<ulong, KillerPlayerState>(); private MetadataInt _roundState; private MetadataInt _remainingSeconds; private MetadataInt _winReason; private MetadataInt _effectiveMapMode; private MetadataInt _effectiveKillerVitality; private MetadataInt _effectiveSurvivorVitality; private MetadataInt _effectiveKillerSpeed; private MetadataInt _effectiveSurvivorSpeed; private MetadataBool _effectiveKillerCanDie; private MetadataBool _effectiveSurvivorDamage; private MetadataBool _effectiveClearStartingInventory; private MetadataBool _effectiveModeSounds; private MetadataBool _effectiveShowRoundTimer; private MetadataInt _effectiveWeapon; private MetadataInt _effectiveSkin; private MetadataVariable _effectiveSkinBarcode; private MetadataBool _effectiveRevealEnabled; private MetadataInt _effectiveRevealInterval; private MetadataInt _effectiveRevealDuration; private MetadataVariable _effectiveWeaponBarcode; private MetadataVariable _effectiveFlashlightBarcode; private MetadataVariable _effectiveFlashbangBarcode; private MetadataBool _effectiveDarkMap; private MetadataInt _effectiveDarknessStrength; private MetadataBool _effectiveDarkFog; private MetadataInt _effectiveFogStrength; private MetadataBool _effectiveFlashbangEffect; private MetadataInt _effectiveFlashbangRadius; private MetadataInt _effectiveFlashbangDuration; private MetadataInt _environmentRevision; private MetadataInt _mapSetupRevision; private MetadataVariable _roundResults; private TriggerEvent _escapeRequest; private TriggerEvent _lastSurvivorEvent; private TriggerEvent _timeExpiredEvent; private TriggerEvent _flashbangRequestEvent; private TriggerEvent _flashbangDetonationEvent; private TriggerEvent _countdownSoundEvent; private TriggerEvent _roundStartSoundEvent; private TriggerEvent _roundEndSoundEvent; private TriggerEvent _lastSurvivorSoundEvent; private TriggerEvent _doorOpenSoundEvent; private TriggerEvent _survivorEscapedSoundEvent; private TriggerEvent _roundLeaderboardEvent; private float _hostTimer; private float _endingTimer; private float _weaponRecoveryCooldown; private float _soloLastSurvivorTriggerDelay; private float _flashbangRequestCooldown; private int _lastPublishedSecond = -1; private ulong _killerPlatformId; private byte _previousKillerSmallId = byte.MaxValue; private bool _ending; private bool _spawnedItems; private bool _killerWeaponSpawned; private bool _localInventoryCleared; private float _localInventoryCleanupTimer; private float _localInventoryCleanupInterval; private int _localInventoryEmptyPasses; private int _localInventoryRemovedCount; private bool _localRoundStartSoundPlayed; private bool _localRoundEndSoundPlayed; private bool _localLastSurvivorSoundPlayed; private bool _localDoorOpenSoundPlayed; private bool _localSurvivorEscapedSoundPlayed; private bool _localRoleMessageShown; private bool _localLastSurvivorHeartbeatActive; private bool _lastSurvivorTriggered; private bool _localAvatarLockApplied; private bool _localKillerSkinFallbackNotified; private string _localRoundAvatarBarcode; private bool _killerAvatarDownloadPending; private string _pendingKillerAvatarBarcode; private string _failedKillerAvatarBarcode; private int _lastLocalStartCountdownSecond = -1; private int _lastLocalCountdownSecond = -1; private KillerRoundState _lastCountdownSoundState; private int _lastCountdownSoundSecond = -1; private bool _showInGameSetupMarkers = true; private bool _inGameSetupEditing; private bool _automaticRoundsPaused; private bool _pauseAutomaticRoundsAfterCurrentRound; private bool _localEscapeRequested; private float _localEscapeRetry; private float _environmentRefreshTimer; private float _doorRefreshTimer; private float _mapSetupSyncRetryTimer; private int _lastAppliedMapSetupRevision = -1; private float _revealCycle; private float _revealVisible; private byte? _revealedPlayerId; private Texture2D _revealTexture; private float? _baseAvatarSpeed; private float? _baseAvatarAgility; private string _roundWeaponBarcode; private string _roundFlashlightBarcode = "Blueberrycat.BONEWORKSFlashlight.Spawnable.FlashlightBoneworks"; private string _roundFlashbangBarcode = string.Empty; private bool _roundModeSoundsEnabled; private bool _roundClearStartingInventory; private int _roundGeneration; private string _lastRoundResultsText; private string _lastShownRoundResultsText; private readonly List<SpawnedRoundItem> _spawnedRoundItems = new List<SpawnedRoundItem>(); private readonly Dictionary<KillerItemSpawnPoint, ItemSpawnerState> _itemSpawnerStates = new Dictionary<KillerItemSpawnPoint, ItemSpawnerState>(); private readonly HashSet<ushort> _roundCleanupEntityIds = new HashSet<ushort>(); private readonly Dictionary<ulong, RoundParticipant> _roundParticipants = new Dictionary<ulong, RoundParticipant>(); internal static KillerModeGamemode CurrentInstance { get; private set; } public override string Title => "Killer Mode"; public override string Author => "Fusion Killer Mode Team"; public override string Barcode => "FusionKillerMode.Gamemode.KillerMode"; public override string Description => "One killer hunts the survivors. Outlast the timer, or escape if the map has an exit."; public override Texture Logo => KillerModeBranding.Logo; public override bool DisableDevTools => true; public override bool DisableSpawnGun => true; public override bool DisableManualUnragdoll => true; public override bool AutoStopOnSceneLoad => true; protected virtual bool IsSoloTest => false; protected virtual bool FlashbangFeatureEnabled => false; protected virtual bool SavePreferencesOnStart => true; protected virtual KillerPlayerState SoloPlayerState => KillerPlayerState.Killer; private KillerRoundState RoundState => (KillerRoundState)((MetadataVariableT<int>)(object)_roundState).GetValue(); private KillerMapMode EffectiveMapMode => (KillerMapMode)((MetadataVariableT<int>)(object)_effectiveMapMode).GetValue(); protected virtual string ResolveKillerWeaponBarcode() { if (Settings.WeaponChoice == KillerWeaponChoice.MapDefined) { return (from point in KillerMapRegistry.ItemSpawns.OfType<KillerWeaponSpawn>() where (Object)(object)point != (Object)null && ((Behaviour)point).isActiveAndEnabled select point.SpawnableBarcode).FirstOrDefault((string barcode) => !string.IsNullOrWhiteSpace(barcode)) ?? string.Empty; } if (Settings.WeaponChoice == KillerWeaponChoice.CustomBarcode) { return Settings.CustomKillerWeaponBarcode?.Trim() ?? string.Empty; } if (Settings.WeaponChoice == KillerWeaponChoice.Random) { string[] array = new string[5] { "c1534c5a-1fb8-477c-afbe-2a95436f6d62", "HorrorLab.GiantCleaver2.Spawnable.GiantCleaver", "Frictic.DeathloopMachete.Spawnable.DeathloopMachete", "BurntLettuce.BowieKnife.Spawnable.BowieKnife", Settings.CustomKillerWeaponBarcode?.Trim() }.Where(KillerContentReferences.IsInstalled).ToArray(); if (array.Length != 0) { return array[Random.Range(0, array.Length)]; } return "c1534c5a-1fb8-477c-afbe-2a95436f6d62"; } return KillerContentReferences.GetWeaponBarcode(Settings.WeaponChoice); } public KillerModeGamemode() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown CurrentInstance = this; Settings.CopyFrom(KillerModePreferences.Current); } public override GroupElementData CreateSettingsGroup() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Expected O, but got Unknown //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Expected O, but got Unknown //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Expected O, but got Unknown //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Expected O, but got Unknown //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown //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_017a: Expected O, but got Unknown GroupElementData val = ((Gamemode)this).CreateSettingsGroup(); GroupElementData val2 = new GroupElementData("Full settings"); val2.AddElement<LabelElementData>(new LabelElementData { Title = "HOST: Create a Fusion server with Killer Mode selected first. Then open BONELAB > BoneMenu > Fusion Killer Mode. Non-hosts may use Personal Settings only." }); val2.AddElement<FunctionElementData>(new FunctionElementData { Title = "OPEN FULL SETTINGS IN BONEMENU", OnPressed = KillerModeBoneMenu.Open }); val.AddElement<GroupElementData>(val2); GroupElementData val3 = new GroupElementData("Personal settings (every player)"); val3.AddElement<BoolElementData>(BoolSetting("Hear Mode Sounds", KillerModeClientPreferences.ModeSounds, KillerModeClientPreferences.SetModeSounds)); val3.AddElement<BoolElementData>(BoolSetting("Hear Last-Survivor Heartbeat", KillerModeClientPreferences.LastSurvivorHeartbeat, KillerModeClientPreferences.SetLastSurvivorHeartbeat)); val3.AddElement<BoolElementData>(BoolSetting("Show Text Timer Box", KillerModeClientPreferences.RoundTimer, KillerModeClientPreferences.SetRoundTimer)); val3.AddElement<BoolElementData>(BoolSetting("Show Game Notifications", KillerModeClientPreferences.GameNotifications, KillerModeClientPreferences.SetGameNotifications)); val3.AddElement<BoolElementData>(BoolSetting("Show Leaderboard Popup", KillerModeClientPreferences.AutomaticLeaderboard, KillerModeClientPreferences.SetAutomaticLeaderboard)); val.AddElement<GroupElementData>(val3); GroupElementData val4 = new GroupElementData("Round results"); val4.AddElement<FunctionElementData>(new FunctionElementData { Title = "SHOW LAST ROUND LEADERBOARD", OnPressed = ShowLastRoundLeaderboard }); if (!IsSoloTest && NetworkInfo.HasServer && !NetworkInfo.IsHost) { GroupElementData val5 = new GroupElementData("Host settings"); val5.AddElement<LabelElementData>(new LabelElementData { Title = "Only the Fusion host can configure Killer Mode or control rounds." }); val.AddElement<GroupElementData>(val5); val.AddElement<GroupElementData>(val4); return val; } if (!IsSoloTest) { GroupElementData val6 = new GroupElementData("Quick host controls"); val6.AddElement<FunctionElementData>(new FunctionElementData { Title = "START ROUND NOW", OnPressed = StartRoundNow }); val6.AddElement<FunctionElementData>(new FunctionElementData { Title = "PAUSE AUTO-START AFTER THIS ROUND", OnPressed = PauseAutomaticRounds }); val6.AddElement<FunctionElementData>(new FunctionElementData { Title = "RESUME AUTOMATIC ROUNDS", OnPressed = ResumeAutomaticRounds }); val6.AddElement<FunctionElementData>(new FunctionElementData { Title = "STOP KILLER MODE (STAY STOPPED)", OnPressed = StopKillerModeManually }); val.AddElement<GroupElementData>(val6); } val.AddElement<GroupElementData>(val4); return val; } private GroupElementData CreateLegacySettingsGroup() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_003a: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Expected O, but got Unknown //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Expected O, but got Unknown //IL_00ff: 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_0126: Expected O, but got Unknown //IL_0127: 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_0137: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //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_0073: Expected O, but got Unknown //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Expected O, but got Unknown //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03f9: Unknown result type (might be due to invalid IL or missing references) //IL_0410: Expected O, but got Unknown //IL_0412: Unknown result type (might be due to invalid IL or missing references) //IL_0417: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_0448: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Expected O, but got Unknown //IL_0461: Unknown result type (might be due to invalid IL or missing references) //IL_0466: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Unknown result type (might be due to invalid IL or missing references) //IL_0481: Unknown result type (might be due to invalid IL or missing references) //IL_0497: Unknown result type (might be due to invalid IL or missing references) //IL_04ae: Expected O, but got Unknown //IL_04d8: Unknown result type (might be due to invalid IL or missing references) //IL_04dd: Unknown result type (might be due to invalid IL or missing references) //IL_04e8: Unknown result type (might be due to invalid IL or missing references) //IL_04ff: Expected O, but got Unknown //IL_0501: Unknown result type (might be due to invalid IL or missing references) //IL_0506: Unknown result type (might be due to invalid IL or missing references) //IL_0511: Unknown result type (might be due to invalid IL or missing references) //IL_0528: Expected O, but got Unknown //IL_052a: Unknown result type (might be due to invalid IL or missing references) //IL_052f: Unknown result type (might be due to invalid IL or missing references) //IL_053a: Unknown result type (might be due to invalid IL or missing references) //IL_054a: Unknown result type (might be due to invalid IL or missing references) //IL_0560: Unknown result type (might be due to invalid IL or missing references) //IL_0577: Expected O, but got Unknown //IL_0579: Unknown result type (might be due to invalid IL or missing references) //IL_057e: Unknown result type (might be due to invalid IL or missing references) //IL_0589: Unknown result type (might be due to invalid IL or missing references) //IL_05a0: Expected O, but got Unknown //IL_075a: Unknown result type (might be due to invalid IL or missing references) //IL_075f: Unknown result type (might be due to invalid IL or missing references) //IL_076a: Unknown result type (might be due to invalid IL or missing references) //IL_0781: Expected O, but got Unknown //IL_07d3: Unknown result type (might be due to invalid IL or missing references) //IL_07d8: Unknown result type (might be due to invalid IL or missing references) //IL_07e3: Unknown result type (might be due to invalid IL or missing references) //IL_07fa: Expected O, but got Unknown //IL_0878: Unknown result type (might be due to invalid IL or missing references) //IL_087d: Unknown result type (might be due to invalid IL or missing references) //IL_0888: Unknown result type (might be due to invalid IL or missing references) //IL_089f: Expected O, but got Unknown //IL_0ad5: Unknown result type (might be due to invalid IL or missing references) //IL_0ada: Unknown result type (might be due to invalid IL or missing references) //IL_0ae5: Unknown result type (might be due to invalid IL or missing references) //IL_0afc: Expected O, but got Unknown //IL_0afe: Unknown result type (might be due to invalid IL or missing references) //IL_0b03: Unknown result type (might be due to invalid IL or missing references) //IL_0b0e: Unknown result type (might be due to invalid IL or missing references) //IL_0b25: Expected O, but got Unknown //IL_0b27: Unknown result type (might be due to invalid IL or missing references) //IL_0b2c: Unknown result type (might be due to invalid IL or missing references) //IL_0b37: Unknown result type (might be due to invalid IL or missing references) //IL_0b4e: Expected O, but got Unknown //IL_0b96: Unknown result type (might be due to invalid IL or missing references) //IL_0b9b: Unknown result type (might be due to invalid IL or missing references) //IL_0ba6: Unknown result type (might be due to invalid IL or missing references) //IL_0bbd: Expected O, but got Unknown //IL_0bbf: Unknown result type (might be due to invalid IL or missing references) //IL_0bc4: Unknown result type (might be due to invalid IL or missing references) //IL_0bcf: Unknown result type (might be due to invalid IL or missing references) //IL_0be6: Expected O, but got Unknown //IL_0be8: Unknown result type (might be due to invalid IL or missing references) //IL_0bed: Unknown result type (might be due to invalid IL or missing references) //IL_0bf8: Unknown result type (might be due to invalid IL or missing references) //IL_0c0f: Expected O, but got Unknown //IL_08fc: Unknown result type (might be due to invalid IL or missing references) //IL_0901: Unknown result type (might be due to invalid IL or missing references) //IL_090c: Unknown result type (might be due to invalid IL or missing references) //IL_0923: Expected O, but got Unknown //IL_09b9: Unknown result type (might be due to invalid IL or missing references) //IL_09be: Unknown result type (might be due to invalid IL or missing references) //IL_09c9: Unknown result type (might be due to invalid IL or missing references) //IL_09e0: Expected O, but got Unknown GroupElementData val = ((Gamemode)this).CreateSettingsGroup(); GroupElementData val2 = new GroupElementData("Round results"); val2.AddElement<FunctionElementData>(new FunctionElementData { Title = "SHOW LAST ROUND LEADERBOARD", OnPressed = ShowLastRoundLeaderboard }); if (!IsSoloTest && NetworkInfo.HasServer && !NetworkInfo.IsHost) { GroupElementData val3 = new GroupElementData("Host settings"); val3.AddElement<LabelElementData>(new LabelElementData { Title = "Only the Fusion host can configure Killer Mode or control rounds." }); val.AddElement<GroupElementData>(val3); val.AddElement<GroupElementData>(val2); return val; } GroupElementData val4 = new GroupElementData("Host controls"); GroupElementData val5 = new GroupElementData("Round"); GroupElementData val6 = new GroupElementData("Roles and equipment"); GroupElementData val7 = new GroupElementData("Presets and atmosphere"); GroupElementData val8 = new GroupElementData("In-game map setup"); if (!IsSoloTest) { val.AddElement<GroupElementData>(val4); } val.AddElement<GroupElementData>(val5); val.AddElement<GroupElementData>(val6); val.AddElement<GroupElementData>(val7); val.AddElement<GroupElementData>(val8); val.AddElement<GroupElementData>(val2); if (!IsSoloTest) { val4.AddElement<FunctionElementData>(new FunctionElementData { Title = "START ROUND NOW", OnPressed = StartRoundNow }); val4.AddElement<FunctionElementData>(new FunctionElementData { Title = "PAUSE AUTO-START AFTER THIS ROUND", OnPressed = PauseAutomaticRounds }); val4.AddElement<FunctionElementData>(new FunctionElementData { Title = "RESUME AUTOMATIC ROUNDS", OnPressed = ResumeAutomaticRounds }); val4.AddElement<LabelElementData>(new LabelElementData { Title = "Start never interrupts an active round. Pause lets the current round finish first." }); } val7.AddElement<EnumElementData>(new EnumElementData { Title = "Gameplay Preset", EnumType = typeof(KillerGameplayPreset), Value = Settings.GameplayPreset, OnValueChanged = delegate(Enum value) { ApplyGameplayPreset((KillerGameplayPreset)(object)value); } }); val7.AddElement<FunctionElementData>(new FunctionElementData { Title = "APPLY MAP RECOMMENDATIONS", OnPressed = ApplyMapRecommendations }); val7.AddElement<BoolElementData>(BoolSetting("Make Map Darker", Settings.DarkMapEnabled, delegate(bool v) { Settings.DarkMapEnabled = v; SyncEnvironmentSettingsIfStarted(); })); val7.AddElement<IntElementData>(IntSetting("Darkness Strength", Settings.DarknessStrength, 0, 100, delegate(int v) { Settings.DarknessStrength = v; SyncEnvironmentSettingsIfStarted(); }, 5)); val7.AddElement<BoolElementData>(BoolSetting("Dark Fog", Settings.DarkFogEnabled, delegate(bool v) { Settings.DarkFogEnabled = v; SyncEnvironmentSettingsIfStarted(); })); val7.AddElement<IntElementData>(IntSetting("Fog Strength", Settings.FogStrength, 0, 100, delegate(int v) { Settings.FogStrength = v; SyncEnvironmentSettingsIfStarted(); }, 5)); val5.AddElement<IntElementData>(IntSetting("Minimum Players", Settings.MinimumPlayers, IsSoloTest ? 1 : 2, 32, delegate(int v) { Settings.MinimumPlayers = v; })); val5.AddElement<IntElementData>(IntSetting("Start Countdown", Settings.StartCountdownSeconds, 3, 30, delegate(int v) { Settings.StartCountdownSeconds = v; })); val5.AddElement<IntElementData>(IntSetting("Round Seconds", Settings.RoundSeconds, 60, 3600, delegate(int v) { Settings.RoundSeconds = v; }, 30)); val5.AddElement<IntElementData>(IntSetting("Killer Head Start", Settings.HeadStartSeconds, 0, 180, delegate(int v) { Settings.HeadStartSeconds = v; }, 5)); val5.AddElement<IntElementData>(IntSetting("Exit Opens With Time Left", Settings.ExitOpenTimeRemaining, 0, 600, delegate(int v) { Settings.ExitOpenTimeRemaining = v; }, 15)); val5.AddElement<FunctionElementData>(new FunctionElementData { Title = "STOP KILLER MODE (STAY STOPPED)", OnPressed = StopKillerModeManually }); val5.AddElement<EnumElementData>(new EnumElementData { Title = "Map Mode", EnumType = typeof(KillerMapModeOverride), Value = Settings.MapModeOverride, OnValueChanged = delegate(Enum v) { Settings.MapModeOverride = (KillerMapModeOverride)(object)v; } }); val6.AddElement<EnumElementData>(new EnumElementData { Title = "Killer Selection", EnumType = typeof(KillerSelectionMode), Value = Settings.SelectionMode, OnValueChanged = delegate(Enum v) { Settings.SelectionMode = (KillerSelectionMode)(object)v; } }); val6.AddElement<EnumElementData>(new EnumElementData { Title = "Killer Weapon", EnumType = typeof(KillerWeaponChoice), Value = Settings.WeaponChoice, OnValueChanged = delegate(Enum v) { Settings.WeaponChoice = (KillerWeaponChoice)(object)v; } }); val6.AddElement<StringElementData>(StringSetting("Custom Killer Weapon Barcode", Settings.CustomKillerWeaponBarcode, delegate(string v) { Settings.CustomKillerWeaponBarcode = v; })); val6.AddElement<FunctionElementData>(new FunctionElementData { Title = "USE RIGHT-HAND ITEM AS KILLER WEAPON", OnPressed = SelectRightHandAsKillerWeapon }); val6.AddElement<FunctionElementData>(new FunctionElementData { Title = "RECOVER LOST KILLER WEAPON", OnPressed = RecoverLostKillerWeapon }); val6.AddElement<EnumElementData>(new EnumElementData { Title = "Killer Skin", EnumType = typeof(KillerSkinChoice), Value = Settings.SkinChoice, OnValueChanged = delegate(Enum v) { Settings.SkinChoice = (KillerSkinChoice)(object)v; } }); val6.AddElement<FunctionElementData>(new FunctionElementData { Title = "USE MY CURRENT AVATAR AS KILLER SKIN", OnPressed = SelectCurrentAvatarForKiller }); val6.AddElement<FloatElementData>(FloatSetting("Killer Vitality", Settings.KillerVitality, 0.2f, 20f, delegate(float v) { Settings.KillerVitality = v; })); val6.AddElement<FloatElementData>(FloatSetting("Survivor Vitality", Settings.SurvivorVitality, 0.2f, 20f, delegate(float v) { Settings.SurvivorVitality = v; })); val6.AddElement<FloatElementData>(FloatSetting("Killer Speed", Settings.KillerSpeedMultiplier, 0.5f, 2f, delegate(float v) { Settings.KillerSpeedMultiplier = v; })); val6.AddElement<FloatElementData>(FloatSetting("Survivor Speed", Settings.SurvivorSpeedMultiplier, 0.5f, 2f, delegate(float v) { Settings.SurvivorSpeedMultiplier = v; })); val6.AddElement<BoolElementData>(BoolSetting("Survivors Can Damage Killer", Settings.SurvivorsCanDamageKiller, delegate(bool v) { Settings.SurvivorsCanDamageKiller = v; })); val6.AddElement<BoolElementData>(BoolSetting("Killer Can Die", Settings.KillerCanDie, delegate(bool v) { Settings.KillerCanDie = v; })); val6.AddElement<BoolElementData>(BoolSetting("Prevent Same Killer Twice", Settings.PreventSameKillerTwice, delegate(bool v) { Settings.PreventSameKillerTwice = v; })); val6.AddElement<BoolElementData>(BoolSetting("Clear Starting Inventory", Settings.ClearStartingInventory, delegate(bool v) { Settings.ClearStartingInventory = v; })); val6.AddElement<BoolElementData>(BoolSetting("Give Survivors Selected Weapon", Settings.GiveSurvivorsWeapon, delegate(bool v) { Settings.GiveSurvivorsWeapon = v; })); val6.AddElement<StringElementData>(StringSetting("Survivor Weapon Barcode", Settings.SurvivorWeaponBarcode, delegate(string v) { Settings.SurvivorWeaponBarcode = v; })); val6.AddElement<FunctionElementData>(new FunctionElementData { Title = "USE RIGHT-HAND ITEM AS SURVIVOR WEAPON", OnPressed = SelectRightHandAsSurvivorWeapon }); val6.AddElement<BoolElementData>(BoolSetting("Give Survivors Flashlights", Settings.SpawnSurvivorFlashlights, delegate(bool v) { Settings.SpawnSurvivorFlashlights = v; })); val6.AddElement<StringElementData>(StringSetting("Flashlight Barcode", Settings.FlashlightBarcode, delegate(string v) { Settings.FlashlightBarcode = v; })); val6.AddElement<FunctionElementData>(new FunctionElementData { Title = "USE RIGHT-HAND ITEM AS SURVIVOR FLASHLIGHT", OnPressed = SelectRightHandAsSurvivorFlashlight }); val6.AddElement<BoolElementData>(BoolSetting("Give Survivors Smoke Grenades", Settings.GiveSurvivorSmokeGrenades, delegate(bool v) { Settings.GiveSurvivorSmokeGrenades = v; })); val6.AddElement<IntElementData>(IntSetting("Smoke Grenade Count", Settings.SmokeGrenadeCount, 1, 10, delegate(int v) { Settings.SmokeGrenadeCount = v; })); val6.AddElement<StringElementData>(StringSetting("Smoke Grenade Barcode", Settings.SmokeGrenadeBarcode, delegate(string v) { Settings.SmokeGrenadeBarcode = v; })); val6.AddElement<FunctionElementData>(new FunctionElementData { Title = "USE RIGHT-HAND ITEM AS SMOKE GRENADE", OnPressed = SelectRightHandAsSurvivorSmokeGrenade }); if (FlashbangFeatureEnabled) { val6.AddElement<BoolElementData>(BoolSetting("Give Survivors Flashbangs", Settings.GiveSurvivorsFlashbangs, delegate(bool v) { Settings.GiveSurvivorsFlashbangs = v; })); val6.AddElement<StringElementData>(StringSetting("Flashbang Barcode", Settings.FlashbangBarcode, delegate(string v) { Settings.FlashbangBarcode = v; })); val6.AddElement<FunctionElementData>(new FunctionElementData { Title = "USE RIGHT-HAND ITEM AS SURVIVOR FLASHBANG", OnPressed = SelectRightHandAsSurvivorFlashbang }); val6.AddElement<BoolElementData>(BoolSetting("Flashbang Bright Effect", Settings.FlashbangBrightEffect, delegate(bool v) { Settings.FlashbangBrightEffect = v; })); val6.AddElement<FloatElementData>(FloatSetting("Flashbang Radius", Settings.FlashbangRadius, 5f, 40f, delegate(float v) { Settings.FlashbangRadius = v; })); val6.AddElement<FloatElementData>(FloatSetting("Flashbang Whiteout Seconds", Settings.FlashbangDuration, 0.5f, 8f, delegate(float v) { Settings.FlashbangDuration = v; })); if (IsSoloTest) { val6.AddElement<FunctionElementData>(new FunctionElementData { Title = "TEST FLASHBANG WHITEOUT (LOCAL)", OnPressed = delegate { KillerFlashEffect.Trigger(Settings.FlashbangDuration, 1f); } }); } } val6.AddElement<BoolElementData>(BoolSetting("Mode Sounds", Settings.EnableModeSounds, delegate(bool v) { Settings.EnableModeSounds = v; })); val6.AddElement<BoolElementData>(BoolSetting("Visible Round Timer", Settings.ShowRoundTimer, delegate(bool v) { Settings.ShowRoundTimer = v; })); val6.AddElement<BoolElementData>(BoolSetting("Last Survivor Reveal", Settings.LastSurvivorRevealEnabled, delegate(bool v) { Settings.LastSurvivorRevealEnabled = v; })); val6.AddElement<IntElementData>(IntSetting("Reveal Interval", Settings.LastSurvivorRevealInterval, 3, 60, delegate(int v) { Settings.LastSurvivorRevealInterval = v; })); val6.AddElement<IntElementData>(IntSetting("Reveal Duration", Settings.LastSurvivorRevealDuration, 1, 10, delegate(int v) { Settings.LastSurvivorRevealDuration = v; })); val8.AddElement<BoolElementData>(BoolSetting("Show Colored Circles", _showInGameSetupMarkers, delegate(bool value) { _showInGameSetupMarkers = value; KillerInGameMapSetup.SetVisuals(value && !((Gamemode)this).IsStarted); })); val8.AddElement<FunctionElementData>(new FunctionElementData { Title = "VALIDATE CURRENT MAP", OnPressed = ValidateCurrentMapForHost }); val8.AddElement<FunctionElementData>(new FunctionElementData { Title = "BEGIN SETUP / PAUSE AUTO-START", OnPressed = BeginInGameMapSetupEditing }); val8.AddElement<FunctionElementData>(new FunctionElementData { Title = "FINISH SETUP / ALLOW ROUND START", OnPressed = FinishInGameMapSetupEditing }); AddMapSetupButton(val8, "Set Lobby Spawn Here", InGameSetupPoint.Lobby); AddMapSetupButton(val8, "Set Killer Spawn Here", InGameSetupPoint.Killer); AddMapSetupButton(val8, "Add Survivor Spawn Here", InGameSetupPoint.Survivor); AddMapSetupButton(val8, "Set Spectator Spawn Here", InGameSetupPoint.Spectator); AddMapSetupButton(val8, "Set Escape Door Ahead", InGameSetupPoint.Escape); val8.AddElement<FunctionElementData>(new FunctionElementData { Title = "Remove Last Spawn", OnPressed = RemoveLastSurvivorSetupPoint }); val8.AddElement<FunctionElementData>(new FunctionElementData { Title = "Remove Escape Zone", OnPressed = RemoveEscapeSetupPoint }); val8.AddElement<FunctionElementData>(new FunctionElementData { Title = "Clear This Map Setup", OnPressed = ClearCurrentMapSetup }); return val; } internal bool ApplyBoneMenuChange(Action<KillerModeSettings> change, bool syncEnvironment = false) { if (NetworkInfo.HasServer && !NetworkInfo.IsHost) { Notify("Killer Mode Settings", "Only the Fusion host can change shared Killer Mode settings.", (NotificationType)1); return false; } change?.Invoke(Settings); KillerModePreferences.Save(Settings); if (syncEnvironment) { SyncEnvironmentSettingsIfStarted(); } return true; } internal static void ShowBoneMenuAccessMessage(string message, bool ready = false) { Notify(ready ? "Killer Mode Ready" : "Killer Mode Setup Required", message, (NotificationType)((!ready) ? 1 : 3), 6f); } internal void ApplyGameplayPreset(KillerGameplayPreset preset) { Settings.ApplyPreset(preset); if (preset != KillerGameplayPreset.Custom) { Notify("Preset Applied", $"{preset} settings are ready. Reopen this page to see every updated value.", (NotificationType)3); } } internal void ApplyMapRecommendations() { if (!NetworkInfo.IsHost) { Notify("Map Recommendations", "Only the Fusion host can apply map recommendations.", (NotificationType)1); return; } KillerMapConfig activeConfig = KillerMapRegistry.ActiveConfig; if ((Object)(object)activeConfig == (Object)null) { Notify("Map Recommendations", "This map does not provide Killer Mode recommendations.", (NotificationType)1); return; } Settings.GameplayPreset = KillerGameplayPreset.Custom; Settings.MinimumPlayers = Math.Clamp(activeConfig.RecommendedPlayersMin, IsSoloTest ? 1 : 2, 32); Settings.RoundSeconds = Math.Clamp(activeConfig.RecommendedRoundSeconds, 60, 3600); Settings.DarkMapEnabled = activeConfig.RecommendDarkMap; Settings.DarkFogEnabled = activeConfig.RecommendDarkFog; Notify("Map Recommendations Applied", "Player count, round time, darkness, and fog recommendations are ready.", (NotificationType)3); } internal void SelectRightHandAsKillerWeapon() { SelectRightHandItem("Killer weapon", delegate(string barcode) { Settings.CustomKillerWeaponBarcode = barcode; Settings.WeaponChoice = KillerWeaponChoice.CustomBarcode; }); } internal void SelectRightHandAsSurvivorWeapon() { SelectRightHandItem("Survivor weapon", delegate(string barcode) { Settings.SurvivorWeaponBarcode = barcode; Settings.GiveSurvivorsWeapon = true; }); } internal void SelectRightHandAsSurvivorFlashlight() { SelectRightHandItem("Survivor flashlight", delegate(string barcode) { Settings.FlashlightBarcode = barcode; Settings.SpawnSurvivorFlashlights = true; }); } internal void SelectRightHandAsSurvivorSmokeGrenade() { SelectRightHandItem("Survivor smoke grenade", delegate(string barcode) { Settings.SmokeGrenadeBarcode = barcode; Settings.GiveSurvivorSmokeGrenades = true; Settings.SmokeGrenadeCount = Math.Clamp(Settings.SmokeGrenadeCount, 1, 10); }, (string barcode) => barcode.Contains("smoke", StringComparison.OrdinalIgnoreCase), "That item does not look like a smoke grenade. Hold the pack's smoke-only grenade; frag, explosive, and flash grenades are rejected."); } internal void SelectRightHandAsSurvivorFlashbang() { SelectRightHandItem("Survivor flashbang", delegate(string barcode) { Settings.FlashbangBarcode = barcode; Settings.GiveSurvivorsFlashbangs = true; }); } private void SelectRightHandItem(string destination, Action<string> apply, Func<string, bool> validator = null, string invalidMessage = null) { if (!NetworkInfo.IsHost) { Notify("Right-Hand Item", "Only the Fusion host can choose shared round equipment.", (NotificationType)1); return; } if (RigData.HasPlayer) { RigRefs refs = RigData.Refs; if (!((Object)(object)((refs != null) ? refs.RightHand : null) == (Object)null)) { GameObject currentAttachedGO = RigData.Refs.RightHand.m_CurrentAttachedGO; if ((Object)(object)currentAttachedGO == (Object)null) { Notify("Right-Hand Item", "Hold the item in your right hand, then press this button with your left hand.", (NotificationType)1, 6f); return; } Poolee obj = currentAttachedGO.GetComponentInParent<Poolee>() ?? Poolee.Cache.Get(currentAttachedGO); object obj2; if (obj == null) { obj2 = null; } else { SpawnableCrate spawnableCrate = obj.SpawnableCrate; if (spawnableCrate == null) { obj2 = null; } else { Barcode barcode = ((Scannable)spawnableCrate).Barcode; obj2 = ((barcode != null) ? barcode.ID : null); } } string text = (string)obj2; if (string.IsNullOrWhiteSpace(text) || !KillerContentReferences.IsInstalled(text)) { Notify("Right-Hand Item", "That held object does not expose a usable Spawnable barcode.", (NotificationType)1, 6f); return; } if (validator != null && !validator(text)) { Notify("Right-Hand Item", invalidMessage ?? "That item cannot be used for this equipment slot.", (NotificationType)1, 7f); return; } apply(text); KillerModePreferences.Save(Settings); Notify("Right-Hand Item Saved", destination + ": " + text + "\nIt will be used next round. Reopen settings to see the updated selection.", (NotificationType)3, 8f); return; } } Notify("Right-Hand Item", "Your player rig is not ready yet.", (NotificationType)1); } internal void SelectCurrentAvatarForKiller() { if (!NetworkInfo.IsHost) { Notify("Killer Skin", "Only the Fusion host can choose the shared Killer skin.", (NotificationType)1); return; } string avatarBarcode = LocalAvatar.AvatarBarcode; if (string.IsNullOrWhiteSpace(avatarBarcode) && RigData.HasPlayer) { avatarBarcode = RigData.GetAvatarBarcode(); } if (string.IsNullOrWhiteSpace(avatarBarcode) || !KillerContentReferences.IsAvatarInstalled(avatarBarcode)) { Notify("Killer Skin", "Wear the downloaded avatar first, then press this button again.", (NotificationType)1); return; } Settings.KillerAvatarBarcode = avatarBarcode; Settings.SkinChoice = KillerSkinChoice.SelectedDownloadedAvatar; KillerModePreferences.Save(Settings); Notify("Killer Skin Saved", "Your currently worn avatar will be used for the Killer next round.", (NotificationType)3); } private void AddMapSetupButton(GroupElementData group, string title, InGameSetupPoint point) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown group.AddElement<FunctionElementData>(new FunctionElementData { Title = title, OnPressed = delegate { PlaceInGameSetupPoint(point); } }); } internal void ValidateCurrentMapForHost() { KillerMapModeOverride killerMapModeOverride = KillerMapRegistry.ActiveConfig?.ModeOverride ?? Settings.MapModeOverride; IReadOnlyList<string> readOnlyList = KillerMapValidator.Validate((killerMapModeOverride == KillerMapModeOverride.Escape || (killerMapModeOverride == KillerMapModeOverride.Auto && KillerMapRegistry.EscapeZones.Any((KillerEscapeZone zone) => (Object)(object)zone != (Object)null && ((Behaviour)zone).isActiveAndEnabled))) ? KillerMapMode.Escape : KillerMapMode.Survival); if (readOnlyList.Count == 0 && ((Gamemode)this).CheckReadyConditions()) { Notify("Map Validation Passed", "This map and the selected required content are ready.", (NotificationType)3); return; } string text = readOnlyList.FirstOrDefault(); if (string.IsNullOrWhiteSpace(text) && TryGetReadinessFailure(out var message)) { text = message; } if (text == null) { text = "Check minimum players and required host barcode settings."; } Notify("Map Cannot Start", text, (NotificationType)1, 7f); } private static IntEl