Decompiled source of FusionKillerMode v0.3.11

Mods/BONELABFusionKillerMode.dll

Decompiled an hour ago
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.Json;
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.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("BONELAB Fusion Killer Mode")]
[assembly: AssemblyFileVersion("0.3.11")]
[assembly: MelonInfo(typeof(KillerModeMod), "BONELAB Fusion Killer Mode", "0.3.11", "Fusion Killer Mode Team", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonOptionalDependencies(new string[] { "LabFusion" })]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.11.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 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_005d: 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_00a1: 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_00b2: 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.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_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		if (!_captured)
		{
			_captured = true;
			_ambientIntensity = RenderSettings.ambientIntensity;
			_reflectionIntensity = RenderSettings.reflectionIntensity;
			_ambientLight = RenderSettings.ambientLight;
			_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_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		RenderSettings.ambientIntensity = _ambientIntensity;
		RenderSettings.reflectionIntensity = _reflectionIntensity;
		RenderSettings.ambientLight = _ambientLight;
		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_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_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_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		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.sortingOrder = -32768;
		((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 _roundEnd;

	private static AudioClip _lastSurvivor;

	private static AudioClip _countdownTick;

	private static AudioClip _heartbeatSlow;

	private static AudioClip _heartbeatFast;

	private static AudioSource _heartbeatSource;

	private static AudioSource _oneShotSource;

	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 PlayRoundEnd(bool survivorsWin)
	{
		Play(_roundEnd ?? (_roundEnd = Load("round_end.wav", () => CreateRoundEnd(survivorsWin))), 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();
			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();
			_oneShotSource.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;
			_heartbeatSource.outputAudioMixerGroup = LocalAudioPlayer.InHead;
		}
	}

	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;
			_oneShotSource.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 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 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))
		{
			try
			{
				Current = JsonSerializer.Deserialize<KillerModeSettings>(_settingsJson.Value) ?? new KillerModeSettings();
			}
			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);
		_settingsJson.Value = JsonSerializer.Serialize(Current);
		_category.SaveToFile(false);
	}
}
public sealed class KillerModeSettings
{
	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 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 FlashbangBarcode { get; set; } = string.Empty;

	public void CopyFrom(KillerModeSettings other)
	{
		if (other != null)
		{
			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;
			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);
			FlashbangBarcode = other.FlashbangBarcode ?? string.Empty;
		}
	}

	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 SoloTestRole
{
	Killer,
	Survivor
}
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 static class KillerRoundRules
{
	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 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 const string InGameMapSetupMetadataKey = "InGameMapSetupProfile";

	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 TriggerEvent _escapeRequest;

	private TriggerEvent _lastSurvivorEvent;

	private TriggerEvent _timeExpiredEvent;

	private TriggerEvent _flashbangRequestEvent;

	private TriggerEvent _flashbangDetonationEvent;

	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 bool _localRoundStartSoundPlayed;

	private bool _localRoundEndSoundPlayed;

	private bool _localRoleMessageShown;

	private bool _localLastSurvivorHeartbeatActive;

	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 bool _showInGameSetupMarkers = true;

	private bool _inGameSetupEditing;

	private bool _automaticRoundsPaused;

	private bool _pauseAutomaticRoundsAfterCurrentRound;

	private bool _localEscapeRequested;

	private float _localEscapeRetry;

	private float _environmentRefreshTimer;

	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 readonly List<SpawnedRoundItem> _spawnedRoundItems = new List<SpawnedRoundItem>();

	private readonly Dictionary<KillerItemSpawnPoint, ItemSpawnerState> _itemSpawnerStates = new Dictionary<KillerItemSpawnPoint, ItemSpawnerState>();

	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 => IsSoloTest;

	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
		Settings.CopyFrom(KillerModePreferences.Current);
	}

	public override GroupElementData CreateSettingsGroup()
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Expected O, but got Unknown
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Expected O, but got Unknown
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Expected O, but got Unknown
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Expected O, but got Unknown
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Expected O, but got Unknown
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Expected O, but got Unknown
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Expected O, but got Unknown
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Expected O, but got Unknown
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Expected O, but got Unknown
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Expected O, but got Unknown
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		//IL_0358: Unknown result type (might be due to invalid IL or missing references)
		//IL_035d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0368: Unknown result type (might be due to invalid IL or missing references)
		//IL_037f: Expected O, but got Unknown
		//IL_0380: Unknown result type (might be due to invalid IL or missing references)
		//IL_0385: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: 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_03b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cd: Expected O, but got Unknown
		//IL_03ce: 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_03de: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0404: Unknown result type (might be due to invalid IL or missing references)
		//IL_041b: Expected O, but got Unknown
		//IL_041c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0421: Unknown result type (might be due to invalid IL or missing references)
		//IL_042c: Unknown result type (might be due to invalid IL or missing references)
		//IL_043c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0452: Unknown result type (might be due to invalid IL or missing references)
		//IL_0469: Expected O, but got Unknown
		//IL_0491: Unknown result type (might be due to invalid IL or missing references)
		//IL_0496: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b8: Expected O, but got Unknown
		//IL_04b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04be: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e0: Expected O, but got Unknown
		//IL_04e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0501: Unknown result type (might be due to invalid IL or missing references)
		//IL_0517: Unknown result type (might be due to invalid IL or missing references)
		//IL_052e: Expected O, but got Unknown
		//IL_052f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0534: Unknown result type (might be due to invalid IL or missing references)
		//IL_053f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0556: Expected O, but got Unknown
		//IL_0705: Unknown result type (might be due to invalid IL or missing references)
		//IL_070a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0715: Unknown result type (might be due to invalid IL or missing references)
		//IL_072c: Expected O, but got Unknown
		//IL_077b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0780: Unknown result type (might be due to invalid IL or missing references)
		//IL_078b: Unknown result type (might be due to invalid IL or missing references)
		//IL_07a2: Expected O, but got Unknown
		//IL_09cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_09d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_09dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_09f3: Expected O, but got Unknown
		//IL_09f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_09fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a05: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a1c: Expected O, but got Unknown
		//IL_0a1e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a23: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a2e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a45: Expected O, but got Unknown
		//IL_0a8d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a92: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a9d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ab4: Expected O, but got Unknown
		//IL_0ab6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0abb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ac6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0add: Expected O, but got Unknown
		//IL_0adf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ae4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aef: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b06: Expected O, but got Unknown
		//IL_07fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0801: Unknown result type (might be due to invalid IL or missing references)
		//IL_080c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0823: Expected O, but got Unknown
		//IL_08b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_08c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_08dc: Expected O, but got Unknown
		GroupElementData val = ((Gamemode)this).CreateSettingsGroup();
		if (!IsSoloTest && NetworkInfo.HasServer && !NetworkInfo.IsHost)
		{
			GroupElementData val2 = new GroupElementData("Host settings");
			val2.AddElement<LabelElementData>(new LabelElementData
			{
				Title = "Only the Fusion host can configure Killer Mode or control rounds."
			});
			val.AddElement<GroupElementData>(val2);
			return val;
		}
		GroupElementData val3 = new GroupElementData("Host controls");
		GroupElementData val4 = new GroupElementData("Round");
		GroupElementData val5 = new GroupElementData("Roles and equipment");
		GroupElementData val6 = new GroupElementData("Presets and atmosphere");
		GroupElementData val7 = new GroupElementData("In-game map setup");
		if (!IsSoloTest)
		{
			val.AddElement<GroupElementData>(val3);
		}
		val.AddElement<GroupElementData>(val4);
		val.AddElement<GroupElementData>(val5);
		val.AddElement<GroupElementData>(val6);
		val.AddElement<GroupElementData>(val7);
		if (!IsSoloTest)
		{
			val3.AddElement<FunctionElementData>(new FunctionElementData
			{
				Title = "START ROUND NOW",
				OnPressed = StartRoundNow
			});
			val3.AddElement<FunctionElementData>(new FunctionElementData
			{
				Title = "PAUSE AUTO-START AFTER THIS ROUND",
				OnPressed = PauseAutomaticRounds
			});
			val3.AddElement<FunctionElementData>(new FunctionElementData
			{
				Title = "RESUME AUTOMATIC ROUNDS",
				OnPressed = ResumeAutomaticRounds
			});
			val3.AddElement<LabelElementData>(new LabelElementData
			{
				Title = "Start never interrupts an active round. Pause lets the current round finish first."
			});
		}
		val6.AddElement<EnumElementData>(new EnumElementData
		{
			Title = "Gameplay Preset",
			EnumType = typeof(KillerGameplayPreset),
			Value = Settings.GameplayPreset,
			OnValueChanged = delegate(Enum value)
			{
				ApplyGameplayPreset((KillerGameplayPreset)(object)value);
			}
		});
		val6.AddElement<FunctionElementData>(new FunctionElementData
		{
			Title = "APPLY MAP RECOMMENDATIONS",
			OnPressed = ApplyMapRecommendations
		});
		val6.AddElement<BoolElementData>(BoolSetting("Make Map Darker", Settings.DarkMapEnabled, delegate(bool v)
		{
			Settings.DarkMapEnabled = v;
			SyncEnvironmentSettingsIfStarted();
		}));
		val6.AddElement<IntElementData>(IntSetting("Darkness Strength", Settings.DarknessStrength, 0, 100, delegate(int v)
		{
			Settings.DarknessStrength = v;
			SyncEnvironmentSettingsIfStarted();
		}, 5));
		val6.AddElement<BoolElementData>(BoolSetting("Dark Fog", Settings.DarkFogEnabled, delegate(bool v)
		{
			Settings.DarkFogEnabled = v;
			SyncEnvironmentSettingsIfStarted();
		}));
		val6.AddElement<IntElementData>(IntSetting("Fog Strength", Settings.FogStrength, 0, 100, delegate(int v)
		{
			Settings.FogStrength = v;
			SyncEnvironmentSettingsIfStarted();
		}, 5));
		val4.AddElement<IntElementData>(IntSetting("Minimum Players", Settings.MinimumPlayers, IsSoloTest ? 1 : 2, 32, delegate(int v)
		{
			Settings.MinimumPlayers = v;
		}));
		val4.AddElement<IntElementData>(IntSetting("Start Countdown", Settings.StartCountdownSeconds, 3, 30, delegate(int v)
		{
			Settings.StartCountdownSeconds = v;
		}));
		val4.AddElement<IntElementData>(IntSetting("Round Seconds", Settings.RoundSeconds, 60, 3600, delegate(int v)
		{
			Settings.RoundSeconds = v;
		}, 30));
		val4.AddElement<IntElementData>(IntSetting("Killer Head Start", Settings.HeadStartSeconds, 0, 180, delegate(int v)
		{
			Settings.HeadStartSeconds = v;
		}, 5));
		val4.AddElement<IntElementData>(IntSetting("Exit Opens With Time Left", Settings.ExitOpenTimeRemaining, 0, 600, delegate(int v)
		{
			Settings.ExitOpenTimeRemaining = v;
		}, 15));
		val4.AddElement<FunctionElementData>(new FunctionElementData
		{
			Title = "STOP KILLER MODE (STAY STOPPED)",
			OnPressed = StopKillerModeManually
		});
		val4.AddElement<EnumElementData>(new EnumElementData
		{
			Title = "Map Mode",
			EnumType = typeof(KillerMapModeOverride),
			Value = Settings.MapModeOverride,
			OnValueChanged = delegate(Enum v)
			{
				Settings.MapModeOverride = (KillerMapModeOverride)(object)v;
			}
		});
		val5.AddElement<EnumElementData>(new EnumElementData
		{
			Title = "Killer Selection",
			EnumType = typeof(KillerSelectionMode),
			Value = Settings.SelectionMode,
			OnValueChanged = delegate(Enum v)
			{
				Settings.SelectionMode = (KillerSelectionMode)(object)v;
			}
		});
		val5.AddElement<EnumElementData>(new EnumElementData
		{
			Title = "Killer Weapon",
			EnumType = typeof(KillerWeaponChoice),
			Value = Settings.WeaponChoice,
			OnValueChanged = delegate(Enum v)
			{
				Settings.WeaponChoice = (KillerWeaponChoice)(object)v;
			}
		});
		val5.AddElement<StringElementData>(StringSetting("Custom Killer Weapon Barcode", Settings.CustomKillerWeaponBarcode, delegate(string v)
		{
			Settings.CustomKillerWeaponBarcode = v;
		}));
		val5.AddElement<FunctionElementData>(new FunctionElementData
		{
			Title = "USE RIGHT-HAND ITEM AS KILLER WEAPON",
			OnPressed = SelectRightHandAsKillerWeapon
		});
		val5.AddElement<FunctionElementData>(new FunctionElementData
		{
			Title = "RECOVER LOST KILLER WEAPON",
			OnPressed = RecoverLostKillerWeapon
		});
		val5.AddElement<EnumElementData>(new EnumElementData
		{
			Title = "Killer Skin",
			EnumType = typeof(KillerSkinChoice),
			Value = Settings.SkinChoice,
			OnValueChanged = delegate(Enum v)
			{
				Settings.SkinChoice = (KillerSkinChoice)(object)v;
			}
		});
		val5.AddElement<FunctionElementData>(new FunctionElementData
		{
			Title = "USE MY CURRENT AVATAR AS KILLER SKIN",
			OnPressed = SelectCurrentAvatarForKiller
		});
		val5.AddElement<FloatElementData>(FloatSetting("Killer Vitality", Settings.KillerVitality, 0.2f, 20f, delegate(float v)
		{
			Settings.KillerVitality = v;
		}));
		val5.AddElement<FloatElementData>(FloatSetting("Survivor Vitality", Settings.SurvivorVitality, 0.2f, 20f, delegate(float v)
		{
			Settings.SurvivorVitality = v;
		}));
		val5.AddElement<FloatElementData>(FloatSetting("Killer Speed", Settings.KillerSpeedMultiplier, 0.5f, 2f, delegate(float v)
		{
			Settings.KillerSpeedMultiplier = v;
		}));
		val5.AddElement<FloatElementData>(FloatSetting("Survivor Speed", Settings.SurvivorSpeedMultiplier, 0.5f, 2f, delegate(float v)
		{
			Settings.SurvivorSpeedMultiplier = v;
		}));
		val5.AddElement<BoolElementData>(BoolSetting("Survivors Can Damage Killer", Settings.SurvivorsCanDamageKiller, delegate(bool v)
		{
			Settings.SurvivorsCanDamageKiller = v;
		}));
		val5.AddElement<BoolElementData>(BoolSetting("Killer Can Die", Settings.KillerCanDie, delegate(bool v)
		{
			Settings.KillerCanDie = v;
		}));
		val5.AddElement<BoolElementData>(BoolSetting("Prevent Same Killer Twice", Settings.PreventSameKillerTwice, delegate(bool v)
		{
			Settings.PreventSameKillerTwice = v;
		}));
		val5.AddElement<BoolElementData>(BoolSetting("Clear Starting Inventory", Settings.ClearStartingInventory, delegate(bool v)
		{
			Settings.ClearStartingInventory = v;
		}));
		val5.AddElement<BoolElementData>(BoolSetting("Give Survivors Selected Weapon", Settings.GiveSurvivorsWeapon, delegate(bool v)
		{
			Settings.GiveSurvivorsWeapon = v;
		}));
		val5.AddElement<StringElementData>(StringSetting("Survivor Weapon Barcode", Settings.SurvivorWeaponBarcode, delegate(string v)
		{
			Settings.SurvivorWeaponBarcode = v;
		}));
		val5.AddElement<FunctionElementData>(new FunctionElementData
		{
			Title = "USE RIGHT-HAND ITEM AS SURVIVOR WEAPON",
			OnPressed = SelectRightHandAsSurvivorWeapon
		});
		val5.AddElement<BoolElementData>(BoolSetting("Give Survivors Flashlights", Settings.SpawnSurvivorFlashlights, delegate(bool v)
		{
			Settings.SpawnSurvivorFlashlights = v;
		}));
		val5.AddElement<StringElementData>(StringSetting("Flashlight Barcode", Settings.FlashlightBarcode, delegate(string v)
		{
			Settings.FlashlightBarcode = v;
		}));
		val5.AddElement<FunctionElementData>(new FunctionElementData
		{
			Title = "USE RIGHT-HAND ITEM AS SURVIVOR FLASHLIGHT",
			OnPressed = SelectRightHandAsSurvivorFlashlight
		});
		if (FlashbangFeatureEnabled)
		{
			val5.AddElement<BoolElementData>(BoolSetting("Give Survivors Flashbangs", Settings.GiveSurvivorsFlashbangs, delegate(bool v)
			{
				Settings.GiveSurvivorsFlashbangs = v;
			}));
			val5.AddElement<StringElementData>(StringSetting("Flashbang Barcode", Settings.FlashbangBarcode, delegate(string v)
			{
				Settings.FlashbangBarcode = v;
			}));
			val5.AddElement<FunctionElementData>(new FunctionElementData
			{
				Title = "USE RIGHT-HAND ITEM AS SURVIVOR FLASHBANG",
				OnPressed = SelectRightHandAsSurvivorFlashbang
			});
			val5.AddElement<BoolElementData>(BoolSetting("Flashbang Bright Effect", Settings.FlashbangBrightEffect, delegate(bool v)
			{
				Settings.FlashbangBrightEffect = v;
			}));
			val5.AddElement<FloatElementData>(FloatSetting("Flashbang Radius", Settings.FlashbangRadius, 5f, 40f, delegate(float v)
			{
				Settings.FlashbangRadius = v;
			}));
			val5.AddElement<FloatElementData>(FloatSetting("Flashbang Whiteout Seconds", Settings.FlashbangDuration, 0.5f, 8f, delegate(float v)
			{
				Settings.FlashbangDuration = v;
			}));
			if (IsSoloTest)
			{
				val5.AddElement<FunctionElementData>(new FunctionElementData
				{
					Title = "TEST FLASHBANG WHITEOUT (LOCAL)",
					OnPressed = delegate
					{
						KillerFlashEffect.Trigger(Settings.FlashbangDuration, 1f);
					}
				});
			}
		}
		val5.AddElement<BoolElementData>(BoolSetting("Mode Sounds", Settings.EnableModeSounds, delegate(bool v)
		{
			Settings.EnableModeSounds = v;
		}));
		val5.AddElement<BoolElementData>(BoolSetting("Visible Round Timer", Settings.ShowRoundTimer, delegate(bool v)
		{
			Settings.ShowRoundTimer = v;
		}));
		val5.AddElement<BoolElementData>(BoolSetting("Last Survivor Reveal", Settings.LastSurvivorRevealEnabled, delegate(bool v)
		{
			Settings.LastSurvivorRevealEnabled = v;
		}));
		val5.AddElement<IntElementData>(IntSetting("Reveal Interval", Settings.LastSurvivorRevealInterval, 3, 60, delegate(int v)
		{
			Settings.LastSurvivorRevealInterval = v;
		}));
		val5.AddElement<IntElementData>(IntSetting("Reveal Duration", Settings.LastSurvivorRevealDuration, 1, 10, delegate(int v)
		{
			Settings.LastSurvivorRevealDuration = v;
		}));
		val7.AddElement<BoolElementData>(BoolSetting("Show Colored Circles", _showInGameSetupMarkers, delegate(bool value)
		{
			_showInGameSetupMarkers = value;
			KillerInGameMapSetup.SetVisuals(value && !((Gamemode)this).IsStarted);
		}));
		val7.AddElement<FunctionElementData>(new FunctionElementData
		{
			Title = "VALIDATE CURRENT MAP",
			OnPressed = ValidateCurrentMapForHost
		});
		val7.AddElement<FunctionElementData>(new FunctionElementData
		{
			Title = "BEGIN SETUP / PAUSE AUTO-START",
			OnPressed = BeginInGameMapSetupEditing
		});
		val7.AddElement<FunctionElementData>(new FunctionElementData
		{
			Title = "FINISH SETUP / ALLOW ROUND START",
			OnPressed = FinishInGameMapSetupEditing
		});
		AddMapSetupButton(val7, "Set Lobby Spawn Here", InGameSetupPoint.Lobby);
		AddMapSetupButton(val7, "Set Killer Spawn Here", InGameSetupPoint.Killer);
		AddMapSetupButton(val7, "Add Survivor Spawn Here", InGameSetupPoint.Survivor);
		AddMapSetupButton(val7, "Set Spectator Spawn Here", InGameSetupPoint.Spectator);
		AddMapSetupButton(val7, "Set Escape Door Ahead", InGameSetupPoint.Escape);
		val7.AddElement<FunctionElementData>(new FunctionElementData
		{
			Title = "Undo Most Recent Survivor Spawn",
			OnPressed = RemoveLastSurvivorSetupPoint
		});
		val7.AddElement<FunctionElementData>(new FunctionElementData
		{
			Title = "Remove Escape Zone",
			OnPressed = RemoveEscapeSetupPoint
		});
		val7.AddElement<FunctionElementData>(new FunctionElementData
		{
			Title = "Clear This Map Setup",
			OnPressed = ClearCurrentMapSetup
		});
		return val;
	}

	private 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);
		}
	}

	private 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);
	}

	private void SelectRightHandAsKillerWeapon()
	{
		SelectRightHandItem("Killer weapon", delegate(string barcode)
		{
			Settings.CustomKillerWeaponBarcode = barcode;
			Settings.WeaponChoice = KillerWeaponChoice.CustomBarcode;
		});
	}

	private void SelectRightHandAsSurvivorWeapon()
	{
		SelectRightHandItem("Survivor weapon", delegate(string barcode)
		{
			Settings.SurvivorWeaponBarcode = barcode;
			Settings.GiveSurvivorsWeapon = true;
		});
	}

	private void SelectRightHandAsSurvivorFlashlight()
	{
		SelectRightHandItem("Survivor flashlight", delegate(string barcode)
		{
			Settings.FlashlightBarcode = barcode;
			Settings.SpawnSurvivorFlashlights = true;
		});
	}

	private void SelectRightHandAsSurvivorFlashbang()
	{
		SelectRightHandItem("Survivor flashbang", delegate(string barcode)
		{
			Settings.FlashbangBarcode = barcode;
			Settings.GiveSurvivorsFlashbangs = true;
		});
	}

	private void SelectRightHandItem(string destination, Action<string> apply)
	{
		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;
				}
				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);
	}

	private 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;
		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);
			}
		});
	}

	private 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 message = readOnlyList.FirstOrDefault() ?? "Check minimum players and required host barcode settings.";
		Notify("Map Cannot Start", message, (NotificationType)1, 7f);
	}

	private static IntElementData IntSetting(string title, int value, int min, int max, Action<int> changed, int increment = 1)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: 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_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Expected O, but got Unknown
		return new IntElementData
		{
			Title = title,
			Value = value,
			MinValue = min,
			MaxValue = max,
			Increment = increment,
			OnValueChanged = changed
		};
	}

	private static FloatElementData FloatSetting(string title, float value, float min, float max, Action<float> changed)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: 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_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		return new FloatElementData
		{
			Title = title,
			Value = value,
			MinValue = min,
			MaxValue = max,
			Increment = 0.2f,
			OnValueChanged = changed
		};
	}

	private static BoolElementData BoolSetting(string title, bool value, Action<bool> changed)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Expected O, but got Unknown
		return new BoolElementData
		{
			Title = title,
			Value = value,
			OnValueChanged = changed
		};
	}

	private static StringElementData StringSetting(string title, string value, Action<string> changed)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		return new StringElementData
		{
			Title = title,
			Value = (value ?? string.Empty),
			OnValueChanged = changed
		};
	}

	public override bool CheckReadyConditions()
	{
		if (_inGameSetupEditing || _automaticRoundsPaused)
		{
			return false;
		}
		int num = (IsSoloTest ? 1 : Math.Clamp(Settings.MinimumPlayers, 2, 32));
		if (PlayerIDManager.PlayerCount < num)
		{
			return false;
		}
		if ((KillerMapRegistry.ActiveConfig?.ModeOverride ?? Settings.MapModeOverride) == KillerMapModeOverride.Escape && !KillerMapRegistry.EscapeZones.Any((KillerEscapeZone z) => (Object)(object)z != (Object)null && ((Behaviour)z).isActiveAndEnabled))
		{
			return false;
		}
		KillerMapConfig activeConfig = KillerMapRegistry.ActiveConfig;
		if ((Object)(object)activeConfig != (Object)null)
		{
			if (activeConfig.SdkCompatibilityVersion > 3)
			{
				return false;
			}
			if ((activeConfig.RequiredSpawnableBarcodes ?? Array.Empty<string>()).Any((string text) => !string.IsNullOrWhiteSpace(text) && !KillerContentReferences.IsAnyCrateInstalled(text)))
			{
				return false;
			}
		}
		foreach (KillerItemSpawnPoint item in KillerMapRegistry.ItemSpawns.Where((KillerItemSpawnPoint point) => (Object)(object)point != (Object)null && point.RequiredContent))
		{
			if (!KillerContentReferences.IsInstalled((item is KillerFlashlightSpawner { UseHostBarcode: not false }) ? Settings.FlashlightBarcode : ((item is KillerFlashbangSpawner { UseHostBarcode: not false }) ? Settings.FlashbangBarcode : item.SpawnableBarcode)))
			{
				return false;
			}
		}
		string barcode = ResolveKillerWeaponBarcode();
		KillerWeaponChoice weaponChoice = Settings.WeaponChoice;
		if ((weaponChoice == KillerWeaponChoice.CustomBarcode || weaponChoice == KillerWeaponChoice.MapDefined) && !KillerContentReferences.IsInstalled(barcode))
		{
			return false;
		}
		if (IsSoloTest)
		{
			return true;
		}
		bool flag = GamemodeMarker.FilterMarkers((BoneTagReference)null).Count > 0;
		bool num2 = KillerMapRegistry.GetSpawns(KillerSpawnRole.Killer).Any() || flag;
		bool flag2 = KillerMapRegistry.GetSpawns(KillerSpawnRole.Survivor).Any() || flag;
		if (!num2 || !flag2)
		{
			return false;
		}
		return true;
	}

	public override void OnGamemodeSelected()
	{
		_inGameSetupEditing = false;
		_automaticRoundsPaused = false;
		_pauseAutomaticRoundsAfterCurrentRound = false;
		LoadAndPublishInGameMapSetup();
		TeleportLocalToRole(KillerSpawnRole.Lobby);
	}

	public override void OnGamemodeDeselected()
	{
		KillerInGameMapSetup.ClearRuntimeObjects();
		GamemodeHelper.ResetSpawnPoints();
	}

	public override void OnGamemodeRegistered()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Expected O, but got Unknown
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Expected O, but got Unknown
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Expected O, but got Unknown
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Expected O, but got Unknown
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Expected O, but got Unknown
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Expected O, but got Unknown
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Expected O, but got Unknown
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Expected O, but got Unknown
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Expected O, but got Unknown
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Expected O, but got Unknown
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Expected O, but got Unknown
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Expected O, but got Unknown
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Expected O, but got Unknown
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Expected O, but got Unknown
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Expected O, but got Unknown
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Expected O, but got Unknown
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Expected O, but got Unknown
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Expected O, but got Unknown
		//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Expected O, but got Unknown
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Expected O, but got Unknown
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: Expected O, but got Unknown
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Expected O, but got Unknown
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0226: Expected O, but got Unknown
		//IL_0232: Unknown result type (might be due to invalid IL or missing references)
		//IL_023c: Expected O, but got Unknown
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: Expected O, but got Unknown
		//IL_025e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0268: Expected O, but got Unknown
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_027e: Expected O, but got Unknown
		//IL_030e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0318: Expected O, but got Unknown
		//IL_033c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0346: Expected O, but got Unknown
		//IL_036a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0374: Expected O, but got Unknown
		//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b5: Expected O, but got Unknown
		//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e3: Expected O, but got Unknown
		//IL_0401: Unknown result type (might be due to invalid IL or missing references)
		//IL_040b: Expected O, but got Unknown
		//IL_0412: Unknown result type (might be due to invalid IL or missing references)
		//IL_041c: Expected O, but got Unknown
		//IL_0434: Unknown result type (might be due to invalid IL or missing references)
		//IL_043e: Expected O, but got Unknown
		_roundState = new MetadataInt("KillerRoundState", ((Gamemode)this).Metadata);
		_remainingSeconds = new MetadataInt("RemainingSeconds", ((Gamemode)this).Metadata);
		_winReason = new MetadataInt("KillerWinReason", ((Gamemode)this).Metadata);
		_effectiveMapMode = new MetadataInt("EffectiveMapMode", ((Gamemode)this).Metadata);
		_effectiveKillerVitality = new MetadataInt("KillerVitalityX100", ((Gamemode)this).Metadata);
		_effectiveSurvivorVitality = new MetadataInt("SurvivorVitalityX100", ((Gamemode)this).Metadata);
		_effectiveKillerSpeed = new MetadataInt("KillerSpeedX100", ((Gamemode)this).Metadata);
		_effectiveSurvivorSpeed = new MetadataInt("SurvivorSpeedX100", ((Gamemode)this).Metadata);
		_effectiveKillerCanDie = new MetadataBool("KillerCanDie", ((Gamemode)this).Metadata);
		_effectiveSurvivorDamage = new MetadataBool("SurvivorsCanDamageKiller", ((Gamemode)this).Metadata);
		_effectiveClearStartingInventory = new MetadataBool("ClearStartingInventory", ((Gamemode)this).Metadata);
		_effectiveModeSounds = new MetadataBool("ModeSounds", ((Gamemode)this).Metadata);
		_effectiveShowRoundTimer = new MetadataBool("ShowRoundTimer", ((Gamemode)this).Metadata);
		_effectiveWeapon = new MetadataInt("KillerWeapon", ((Gamemode)this).Metadata);
		_effectiveSkin = new MetadataInt("KillerSkin", ((Gamemode)this).Metadata);
		_effectiveSkinBarcode = new MetadataVariable("KillerSkinBarcode", ((Gamemode)this).Metadata);
		_effectiveRevealEnabled = new MetadataBool("LastSurvivorRevealEnabled", ((Gamemode)this).Metadata);
		_effectiveRevealInterval = new MetadataInt("LastSurvivorRevealInterval", ((Gamemode)this).Metadata);
		_effectiveRevealDuration = new MetadataInt("LastSurvivorRevealDuration", ((Gamemode)this).Metadata);
		_effectiveWeaponBarcode = new MetadataVariable("KillerWeaponBarcode", ((Gamemode)this).Metadata);
		_effectiveFlashlightBarcode = new MetadataVariable("FlashlightBarcode", ((Gamemode)this).Metadata);
		_effectiveFlashbangBarcode = new MetadataVariable("FlashbangBarcode", ((Gamemode)this).Metadata);
		_effectiveDarkMap = new MetadataBool("DarkMap", ((Gamemode)this).Metadata);
		_effectiveDarknessStrength = new MetadataInt("DarknessStrength", ((Gamemode)this).Metadata);
		_effectiveDarkFog = new MetadataBool("DarkFog", ((Gamemode)this).Metadata);
		_effectiveFogStrength = new MetadataInt("FogStrength", ((Gamemode)this).Metadata);
		_effectiveFlashbangEffect = new MetadataBool("FlashbangBrightEffect", ((Gamemode)this).Metadata);
		_effectiveFlashbangRadius = new MetadataInt("FlashbangRadiusX100", ((Gamemode)this).Metadata);
		_effectiveFlashbangDuration = new MetadataInt("FlashbangDurationX100", ((Gamemode)this).Metadata);
		((MetadataDictionary<byte, MetadataInt>)(object)_playerStates).Register(((Gamemode)this).Metadata, "KillerPlayerState");
		_playerStates.OnPlayerVariableChanged += OnPlayerStateChanged;
		_teams.Register((Gamemode)(object)this);
		_teams.AddTeam(_killerTeam);
		_teams.AddTeam(_survivorTeam);
		_teams.AddTeam(_spectatorTeam);
		_teams.OnAssignedToTeam += OnAssignedToTeam;
		_escapeRequest = new TriggerEvent("EscapeRequest", ((Gamemode)this).Relay, false);
		_escapeRequest.OnTriggeredWithValue += OnEscapeRequest;
		_lastSurvivorEvent = new TriggerEvent("LastSurvivor", ((Gamemode)this).Relay, true);
		_lastSurvivorEvent.OnTriggered += delegate
		{
			switch ((PlayerIDManager.LocalID != null) ? GetPlayerState(PlayerIDManager.LocalID) : KillerPlayerState.None)
			{
			case KillerPlayerState.SurvivorAlive:
			{
				_localLastSurvivorHeartbeatActive = true;
				string message2 = (IsSoloTest ? "Solo test: the Last Survivor cue and private heartbeat are active." : (((MetadataVariableT<bool>)(object)_effectiveRevealEnabled).GetValue() ? "You are the last Survivor. Your location will be periodically revealed to the Killer." : "You are the last Survivor. Stay alive."));
				Notify("YOU'RE THE LAST SURVIVOR", message2, (NotificationType)1);
				break;
			}
			case KillerPlayerState.Killer:
			{
				_localLastSurvivorHeartbeatActive = false;
				string message = (((MetadataVariableT<bool>)(object)_effectiveRevealEnabled).GetValue() ? "Only one Survivor remains. Their location will be revealed." : "Only one Survivor remains.");
				Notify("LAST SURVIVOR", message, (NotificationType)1);
				break;
			}
			default:
				_localLastSurvivorHeartbeatActive = false;
				Notify("Last Survivor", "Only one living Survivor remains.", (NotificationType)1);
				break;
			}
			if (ModeSoundsEnabled())
			{
				KillerModeAudio.PlayLastSurvivor();
			}
			KillerMapRegistry.InvokeEvents(delegate(KillerMapEvents e)
			{
				e.InvokeLastSurvivor();
			});
		};
		_timeExpiredEvent = new TriggerEvent("TimeExpired", ((Gamemode)this).Relay, true);
		_timeExpiredEvent.OnTriggered += delegate
		{
			KillerMapRegistry.InvokeEvents(delegate(KillerMapEvents e)
			{
				e.InvokeTimeExpired();
			});
		};
		_flashbangRequestEvent = new TriggerEvent("FlashbangRequest", ((Gamemode)this).Relay, false);
		_flashbangRequestEvent.OnTriggeredWithValue += OnFlashbangRequest;
		_flashbangDetonationEvent = new TriggerEvent("FlashbangDetonation", ((Gamemode)this).Relay, true);
		_flashbangDetonationEvent.OnTriggeredWithValue += OnFlashbangDetonation;
		MultiplayerHooking.OnPlayerAction += new PlayerAction(OnPlayerAction);
		FusionOverrides.OnValidateNametag += new UserOverride(OnValidateNametag);
		LocalHealth.OnRespawn += OnLocalRespawn;
		LocalAvatar.OnAvatarChanged += new PlayerAvatarDelegate(OnLocalAvatarChanged);
	}

	public override void OnGamemodeUnregistered()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Expected O, but got Unknown
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		RestoreLocalAvatarLock();
		MultiplayerHooking.OnPlayerAction -= new PlayerAction(OnPlayerAction);
		FusionOverrides.OnValidateNametag -= new UserOverride(OnValidateNametag);
		LocalHealth.OnRespawn -= OnLocalRespawn;
		LocalAvatar.OnAvatarChanged -= new PlayerAvatarDelegate(OnLocalAvatarChanged);
		_playerStates.OnPlayerVariableChanged -= OnPlayerStateChanged;
		((MetadataDictionary<byte, MetadataInt>)(object)_playerStates).Unregister();
		_teams.OnAssignedToTeam -= OnAssignedToTeam;
		_teams.Unregister();
		_escapeRequest.UnregisterEvent();
		_lastSurvivorEvent.UnregisterEvent();
		_timeExpiredEvent.UnregisterEvent();
		_flashbangRequestEvent.UnregisterEvent();
		_flashbangDetonationEvent.UnregisterEvent();
		KillerEnvironmentEffects.Restore();
		KillerFlashEffect.Clear();
	}

	public override void OnGamemodeStarted()
	{
		_localRoundAvatarBarcode = LocalAvatar.AvatarBarcode;
		if (string.IsNullOrWhiteSpace(_localRoundAvatarBarcode) && RigData.HasPlayer)
		{
			_localRoundAvatarBarcode = RigData.GetAvatarBarcode();
		}
		_ending = false;
		_weaponRecoveryCooldown = 0f;
		_flashbangRequestCooldown = 0f;
		_soloLastSurvivorTriggerDelay = 0f;
		_spawnedItems = false;
		_killerWeaponSpawned = false;
		_localInventoryCleared = false;
		_localRoundStartSoundPlayed = false;
		_localRoundEndSoundPlayed = false;
		_localRoleMessageShown = false;
		_localLastSurvivorHeartbeatActive = false;
		_localKillerSkinFallbackNotified = false;
		_failedKillerAvatarBarcode = null;
		KillerModeAudio.StopHeartbeat();
		_lastLocalStartCountdownSecond = -1;
		_lastLocalCountdownSecond = -1;
		KillerInGameMapSetup.SetVisuals(visible: false);
		_localEscapeRequested = false;
		_localEscapeRetry = 0f;
		_environmentRefreshTimer = 0f;
		_revealCycle = 0f;
		_revealVisible = 0f;
		_revealedPlayerId = null;
		_spawnedRoundItems.Clear();
		_itemSpawnerStates.Clear();
		_hostPlayerStates.Clear();
		LocalControls.DisableSlowMo = true;
		KillerEnvironmentEffects.Restore();
		KillerFlashEffect.Clear();
		if (NetworkInfo.IsHost)
		{
			if (SavePreferencesOnStart)
			{
				KillerModePreferences.Save(Settings);
			}
			BeginHostRound();
		}
		ApplyLocalEnvironment();
	}

	private void BeginHostRound()
	{
		KillerMapConfig activeConfig = KillerMapRegistry.ActiveConfig;
		KillerMapMode value = (((Object)(object)activeConfig != (Object)null) ? activeConfig.ModeOverride : Settings.MapModeOverride) switch
		{
			KillerMapModeOverride.Survival => KillerMapMode.Survival, 
			KillerMapModeOverride.Escape => KillerMapMode.Escape, 
			_ => KillerMapRegistry.EscapeZones.Any((KillerEscapeZone z) => (Object)(object)z != (Object)null && ((Behaviour)z).isActiveAndEnabled) ? KillerMapMode.Escape : KillerMapMode.Survival, 
		};
		int val = (((Object)(object)activeConfig != (Object)null) ? activeConfig.ExitOpenTimeRemaining : Settings.ExitOpenTimeRemaining);
		((MetadataVariableT<int>)(object)_effectiveMapMode).SetValue((int)value);
		((MetadataVariableT<int>)(object)_effectiveKillerVitality).SetValue(Mathf.RoundToInt(Settings.KillerVitality * 100f));
		((MetadataVariableT<int>)(object)_effectiveSurvivorVitality).SetValue(Mathf.RoundToInt(Settings.SurvivorVitality * 100f));
		((MetadataVariableT<int>)(object)_effectiveKillerSpeed).SetValue(Mathf.RoundToInt(Mathf.Clamp(Settings.KillerSpeedMultiplier, 0.5f, 2f) * 100f));
		((MetadataVariableT<int>)(object)_effectiveSurvivorSpeed).SetValue(Mathf.RoundToInt(Mathf.Clamp(Settings.SurvivorSpeedMultiplier, 0.5f, 2f) * 100f));
		((MetadataVariableT<bool>)(object)_effectiveKillerCanDie).SetValue(Settings.KillerCanDie);
		((MetadataVariableT<bool>)(object)_effectiveSurvivorDamage).SetValue(Settings.SurvivorsCanDamageKiller);
		_roundClearStartingInventory = Settings.ClearStartingInventory;
		((MetadataVariableT<bool>)(object)_effectiveClearStartingInventory).SetValue(_roundClearStartingInventory);
		_roundModeSoundsEnabled = Settings.EnableModeSounds;
		_roundFlashlightBarcode = (string.IsNullOrWhiteSpace(Settings.FlashlightBarcode) ? "Blueberrycat.BONEWORKSFlashlight.Spawnable.FlashlightBoneworks" : Settings.FlashlightBarcode.Trim());
		_roundFlashbangBarcode = ((!FlashbangFeatureEnabled) ? string.Empty : (Settings.FlashbangBarcode?.Trim() ?? string.Empty));
		((MetadataVariableT<bool>)(object)_effectiveModeSounds).SetValue(_roundModeSoundsEnabled);
		((MetadataVariableT<bool>)(object)_effectiveShowRoundTimer).SetValue(Settings.ShowRoundTimer);
		((MetadataVariableT<int>)(object)_effectiveWeapon).SetValue((int)Settings.WeaponChoice);
		((MetadataVariableT<int>)(object)_effectiveSkin).SetValue((int)Settings.SkinChoice);
		_effectiveSkinBarcode.SetValue(Settings.KillerAvatarBarcode ?? string.Empty);
		((MetadataVariableT<bool>)(object)_effectiveRevealEnabled).SetValue(Settings.LastSurvivorRevealEnabled);
		((MetadataVariableT<int>)(object)_effectiveRevealInterval).SetValue(Math.Clamp(Settings.LastSurvivorRevealInterval, 3, 60));
		((MetadataVariableT<int>)(object)_effectiveRevealDuration).SetValue(Math.Clamp(Settings.LastSurvivorRevealDuration, 1, 10));
		_roundWeaponBarcode = ResolveKillerWeaponBarcode();
		if (!KillerContentReferences.IsInstalled(_roundWeaponBarcode))
		{
			KillerWeaponChoice weaponChoice = Settings.WeaponChoice;
			if (weaponChoice != KillerWeaponChoice.CustomBarcode && weaponChoice != KillerWeaponChoice.MapDefined)
			{
				MelonLogger.Warning("[Killer Mode] Selected weapon is missing; using BONELAB's Combat Knife instead: " + _roundWeaponBarcode);
				_roundWeaponBarcode = "c1534c5a-1fb8-477c-afbe-2a95436f6d62";
			}
		}
		_effectiveWeaponBarcode.SetValue(_roundWeaponBarcode ?? string.Empty);
		_effectiveFlashlightBarcode.SetValue(_roundFlashlightBarcode);
		_effectiveFlashbangBarcode.SetValue(_roundFlashbangBarcode);
		((MetadataVariableT<bool>)(object)_effectiveDarkMap).SetValue(Settings.DarkMapEnabled);
		((MetadataVariableT<int>)(object)_effectiveDarknessStrength).SetValue(Math.Clamp(Settings.DarknessStrength, 0, 100));
		((MetadataVariableT<bool>)(object)_effectiveDarkFog).SetValue(Settings.DarkFogEnabled);
		((MetadataVariableT<int>)(object)_effectiveFogStrength).SetValue(Math.Clamp(Settings.FogStrength, 0, 100));
		((MetadataVariableT<bool>)(object)_effectiveFlashbangEffect).SetValue(FlashbangFeatureEnabled && Settings.FlashbangBrightEffect);
		((MetadataVariableT<int>)(object)_effectiveFlashbangRadius).SetValue(Mathf.RoundToInt(Mathf.Clamp(Settings.FlashbangRadius, 5f, 40f) * 100f));
		((MetadataVariableT<int>)(object)_effectiveFlashbangDuration).SetValue(Mathf.RoundToInt(Mathf.Clamp(Settings.FlashbangDuration, 0.5f, 8f) * 100f));
		((MetadataVariableT<int>)(object)_winReason).SetValue(0);
		ApplyLocalEnvironment();
		SelectAndAssignRoles();
		_hostTimer = Math.Clamp(Settings.StartCountdownSeconds, 3, 30);
		_lastPublishedSecond = -1;
		SetRoundState(KillerRoundState.Preparing);
		((Gamemode)this).Metadata.TrySetMetadata("RoundDuration", Math.Max(60, Settings.RoundSeconds).ToString());
		((Gamemode)this).Metadata.TrySetMetadata("ExitOpenTimeRemaining", Math.Max(0, val).ToString());
		PublishRemaining();
	}

	private void SelectAndAssignRoles()
	{
		PlayerID[] array = PlayerIDManager.PlayerIDs.OrderBy((PlayerID p) => p.