Decompiled source of LCCustomDifficulty v1.3.0

LCCustomDifficulty.dll

Decompiled 11 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LCCustomDifficulty.Blomko.Lib.WeightedRandom;
using LCSyncTool;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LCCustomDifficulty")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A template for Lethal Company")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LCCustomDifficulty")]
[assembly: AssemblyTitle("LCCustomDifficulty")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LCCustomDifficulty
{
	public static class CommandSystem
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<KeyValuePair<string, Action<int, string>>, string> <>9__8_9;

			public static Action<int, string> <>9__8_0;

			public static Action<int, string> <>9__8_1;

			public static Action<int, string> <>9__8_2;

			public static Func<Type, Tuple<string, Type>> <>9__8_14;

			public static Action<int, string> <>9__8_3;

			public static Func<Type, Tuple<string, Type>> <>9__8_16;

			public static Action<int, string> <>9__8_4;

			public static Action<int, string> <>9__8_5;

			public static Action<int, string> <>9__8_6;

			public static Action<int, string> <>9__8_7;

			public static Action<int, string> <>9__8_8;

			public static OnValidateInput <>9__11_0;

			internal void <InitialiseCommands>b__8_0(int id, string _)
			{
				if (!IsLocalPlayer(id))
				{
					s_CurrentHUD.AddTextToChatOnServer("User can't call this command.", -1);
					return;
				}
				ClearChat();
				s_CurrentHUD.AddTextToChatOnServer("Available Commands Are:\n" + GeneralExtensions.Join<KeyValuePair<string, Action<int, string>>>((IEnumerable<KeyValuePair<string, Action<int, string>>>)s_CommandActionMap, (Func<KeyValuePair<string, Action<int, string>>, string>)((KeyValuePair<string, Action<int, string>> x) => x.Key), "\n"), -1);
			}

			internal string <InitialiseCommands>b__8_9(KeyValuePair<string, Action<int, string>> x)
			{
				return x.Key;
			}

			internal void <InitialiseCommands>b__8_1(int _, string _)
			{
				s_CurrentHUD.AddTextToChatOnServer("<color=blue>Pong!</color>", -1);
			}

			internal void <InitialiseCommands>b__8_2(int id, string _)
			{
				<>c__DisplayClass8_0 CS$<>8__locals0 = new <>c__DisplayClass8_0();
				if (!IsLocalPlayer(id))
				{
					s_CurrentHUD.AddTextToChatOnServer("You can't invoke this command!", -1);
					return;
				}
				CS$<>8__locals0.colours = new string[7] { "#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#FF00FF", "#00FFFF", "#FFFFFF" };
				CS$<>8__locals0.t = typeof(AbstractLevelEvent);
				string text = GeneralExtensions.Join<string>(from x in Assembly.GetAssembly(typeof(Plugin)).GetTypes()
					where !x.IsAbstract && CS$<>8__locals0.t.IsAssignableFrom(x) && x.GetConstructor(Type.EmptyTypes) != null && x != typeof(RandomDifficulty)
					select "<color=" + RandomColour() + ">" + x.Name + "</color>", (Func<string, string>)null, ", ");
				ClearChat();
				s_CurrentHUD.AddTextToChatOnServer(text, -1);
				string RandomColour()
				{
					return CS$<>8__locals0.colours[Random.RandomRangeInt(0, CS$<>8__locals0.colours.Length)];
				}
			}

			internal void <InitialiseCommands>b__8_3(int id, string msg)
			{
				<>c__DisplayClass8_1 CS$<>8__locals0 = new <>c__DisplayClass8_1();
				if (!IsLocalPlayer(id))
				{
					s_CurrentHUD.AddTextToChatOnServer("<color=red>You can't invoke this command!</color>", -1);
					return;
				}
				string[] array = msg.Split(" ");
				if (array.Length < 2)
				{
					s_CurrentHUD.AddTextToChatOnServer("<color=red>Error Expected Format is '!add LevelEvent'</color>", -1);
					return;
				}
				CS$<>8__locals0.t = typeof(AbstractLevelEvent);
				foreach (var (text2, type2) in (from x in Assembly.GetAssembly(typeof(Plugin)).GetTypes()
					where !x.IsAbstract && CS$<>8__locals0.t.IsAssignableFrom(x) && x.GetConstructor(Type.EmptyTypes) != null && x != typeof(RandomDifficulty)
					select new Tuple<string, Type>(x.Name, x)).ToList())
				{
					if (text2.Equals(array[1]))
					{
						AbstractLevelEvent abstractLevelEvent = (AbstractLevelEvent)type2.GetConstructor(Type.EmptyTypes).Invoke(null);
						bool flag = LevelModifier.AddToGuaranteed(abstractLevelEvent);
						s_AddedEvents.Add(abstractLevelEvent);
						s_CurrentHUD.AddTextToChatOnServer(flag ? ("<color=green>Successfully added '" + text2 + "'</color>") : ("<color=red>Failed to add '" + text2 + "'</color>"), -1);
						break;
					}
				}
			}

			internal Tuple<string, Type> <InitialiseCommands>b__8_14(Type x)
			{
				return new Tuple<string, Type>(x.Name, x);
			}

			internal void <InitialiseCommands>b__8_4(int id, string msg)
			{
				<>c__DisplayClass8_2 CS$<>8__locals0 = new <>c__DisplayClass8_2();
				if (!IsLocalPlayer(id))
				{
					s_CurrentHUD.AddTextToChatOnServer("You can't invoke this command!", -1);
					return;
				}
				string[] array = msg.Split(" ");
				if (array.Length < 2)
				{
					s_CurrentHUD.AddTextToChatOnServer($"Error Expected Format is '{array} LevelEvent'", -1);
					return;
				}
				CS$<>8__locals0.t = typeof(AbstractLevelEvent);
				foreach (var (text2, type2) in (from x in Assembly.GetAssembly(typeof(Plugin)).GetTypes()
					where !x.IsAbstract && CS$<>8__locals0.t.IsAssignableFrom(x) && x.GetConstructor(Type.EmptyTypes) != null && x != typeof(RandomDifficulty)
					select new Tuple<string, Type>(x.Name, x)).ToList())
				{
					if (text2.Equals(array[1]))
					{
						AbstractLevelEvent instance = (AbstractLevelEvent)type2.GetConstructor(Type.EmptyTypes).Invoke(null);
						s_CurrentHUD.AddTextToChatOnServer(LevelModifier.RemoveFromGuaranteed(instance) ? ("Successfully removed '" + text2 + "'") : ("Failed to remove '" + text2 + "'"), -1);
						break;
					}
				}
			}

			internal Tuple<string, Type> <InitialiseCommands>b__8_16(Type x)
			{
				return new Tuple<string, Type>(x.Name, x);
			}

			internal void <InitialiseCommands>b__8_5(int id, string _)
			{
				if (!IsLocalPlayer(id))
				{
					s_CurrentHUD.AddTextToChatOnServer("<color=red>User not allowed to do this.</color>", -1);
					return;
				}
				int num = s_AddedEvents.RemoveWhere(LevelModifier.RemoveFromGuaranteed);
				s_CurrentHUD.AddTextToChatOnServer($"Pruned {num} level events.", -1);
			}

			internal void <InitialiseCommands>b__8_6(int id, string _)
			{
				if (IsLocalPlayer(id))
				{
					ClearChat();
				}
			}

			internal void <InitialiseCommands>b__8_7(int id, string _)
			{
				if (IsLocalPlayer(id))
				{
					ClearChat();
					LevelModifier.PostCurrentModifiersTo(s_CurrentHUD);
				}
			}

			internal void <InitialiseCommands>b__8_8(int id, string _)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				if (!IsLocalPlayer(id))
				{
					return;
				}
				ClearChat();
				Vector3 position = ((Component)StartOfRound.Instance.localPlayerController).transform.position;
				HashSet<string> hashSet = new HashSet<string>();
				SelectableLevel[] levels = StartOfRound.Instance.levels;
				for (int i = 0; i < levels.Length; i++)
				{
					foreach (SpawnableItemWithRarity item in levels[i].spawnableScrap)
					{
						Item spawnableItem = item.spawnableItem;
						if (hashSet.Add(spawnableItem.itemName))
						{
							GameObject obj = Object.Instantiate<GameObject>(spawnableItem.spawnPrefab);
							obj.GetComponent<GrabbableObject>().grabbable = true;
							obj.transform.position = position;
							obj.GetComponent<NetworkObject>().Spawn(true);
						}
					}
				}
			}

			internal char <SetTextLimits>b__11_0(string _, int _, char c)
			{
				return c;
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass8_0
		{
			public string[] colours;

			public Type t;

			internal bool <InitialiseCommands>b__11(Type x)
			{
				if (!x.IsAbstract && t.IsAssignableFrom(x) && x.GetConstructor(Type.EmptyTypes) != null)
				{
					return x != typeof(RandomDifficulty);
				}
				return false;
			}

			internal string <InitialiseCommands>b__12(Type x)
			{
				return "<color=" + RandomColour() + ">" + x.Name + "</color>";
				string RandomColour()
				{
					return colours[Random.RandomRangeInt(0, colours.Length)];
				}
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass8_1
		{
			public Type t;

			internal bool <InitialiseCommands>b__13(Type x)
			{
				if (!x.IsAbstract && t.IsAssignableFrom(x) && x.GetConstructor(Type.EmptyTypes) != null)
				{
					return x != typeof(RandomDifficulty);
				}
				return false;
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass8_2
		{
			public Type t;

			internal bool <InitialiseCommands>b__15(Type x)
			{
				if (!x.IsAbstract && t.IsAssignableFrom(x) && x.GetConstructor(Type.EmptyTypes) != null)
				{
					return x != typeof(RandomDifficulty);
				}
				return false;
			}
		}

		private static Dictionary<string, Action<int, string>> s_CommandActionMap = new Dictionary<string, Action<int, string>>();

		private static HUDManager s_CurrentHUD;

		private static HashSet<AbstractLevelEvent> s_AddedEvents = new HashSet<AbstractLevelEvent>();

		[HarmonyPatch(typeof(HUDManager), "AddTextToChatOnServer")]
		[HarmonyPostfix]
		private static void OnChatMessageReceived(ref HUDManager __instance, ref string chatMessage, ref int playerId)
		{
			s_CurrentHUD = __instance;
			if (playerId != -1)
			{
				string[] array = chatMessage.Split(" ");
				if (s_CommandActionMap.TryGetValue(array[0], out var value))
				{
					value(playerId, chatMessage);
				}
				Plugin.LOGGER.LogInfo((object)("Received Chat Message: '" + chatMessage + "'; Split: '" + GeneralExtensions.Join<string>((IEnumerable<string>)array, (Func<string, string>)null, ", ") + "'"));
			}
		}

		public static void AddCommand(string command, Action<int, string> handler)
		{
			if (!s_CommandActionMap.TryAdd(command, handler))
			{
				s_CommandActionMap[command] = handler;
			}
		}

		public static void RemoveCommand(string cmd)
		{
			s_CommandActionMap.Remove(cmd);
		}

		public static void Clear()
		{
			s_CommandActionMap.Clear();
		}

		public static bool IsLocalPlayer(int id)
		{
			return (int)StartOfRound.Instance.localPlayerController.playerClientId == id;
		}

		public static void InitialiseCommands()
		{
			AddCommand("!help", delegate(int id, string _)
			{
				if (!IsLocalPlayer(id))
				{
					s_CurrentHUD.AddTextToChatOnServer("User can't call this command.", -1);
				}
				else
				{
					ClearChat();
					s_CurrentHUD.AddTextToChatOnServer("Available Commands Are:\n" + GeneralExtensions.Join<KeyValuePair<string, Action<int, string>>>((IEnumerable<KeyValuePair<string, Action<int, string>>>)s_CommandActionMap, (Func<KeyValuePair<string, Action<int, string>>, string>)((KeyValuePair<string, Action<int, string>> x) => x.Key), "\n"), -1);
				}
			});
			AddCommand("!ping", delegate
			{
				s_CurrentHUD.AddTextToChatOnServer("<color=blue>Pong!</color>", -1);
			});
			AddCommand("!list", delegate(int id, string _)
			{
				string[] colours;
				if (!IsLocalPlayer(id))
				{
					s_CurrentHUD.AddTextToChatOnServer("You can't invoke this command!", -1);
				}
				else
				{
					colours = new string[7] { "#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#FF00FF", "#00FFFF", "#FFFFFF" };
					Type t3 = typeof(AbstractLevelEvent);
					string text5 = GeneralExtensions.Join<string>(from x in Assembly.GetAssembly(typeof(Plugin)).GetTypes()
						where !x.IsAbstract && t3.IsAssignableFrom(x) && x.GetConstructor(Type.EmptyTypes) != null && x != typeof(RandomDifficulty)
						select "<color=" + RandomColour() + ">" + x.Name + "</color>", (Func<string, string>)null, ", ");
					ClearChat();
					s_CurrentHUD.AddTextToChatOnServer(text5, -1);
				}
				string RandomColour()
				{
					return colours[Random.RandomRangeInt(0, colours.Length)];
				}
			});
			AddCommand("!add", delegate(int id, string msg)
			{
				if (!IsLocalPlayer(id))
				{
					s_CurrentHUD.AddTextToChatOnServer("<color=red>You can't invoke this command!</color>", -1);
				}
				else
				{
					string[] array2 = msg.Split(" ");
					if (array2.Length >= 2)
					{
						Type t2 = typeof(AbstractLevelEvent);
						{
							foreach (var (text4, type4) in (from x in Assembly.GetAssembly(typeof(Plugin)).GetTypes()
								where !x.IsAbstract && t2.IsAssignableFrom(x) && x.GetConstructor(Type.EmptyTypes) != null && x != typeof(RandomDifficulty)
								select new Tuple<string, Type>(x.Name, x)).ToList())
							{
								if (text4.Equals(array2[1]))
								{
									AbstractLevelEvent abstractLevelEvent = (AbstractLevelEvent)type4.GetConstructor(Type.EmptyTypes).Invoke(null);
									bool flag = LevelModifier.AddToGuaranteed(abstractLevelEvent);
									s_AddedEvents.Add(abstractLevelEvent);
									s_CurrentHUD.AddTextToChatOnServer(flag ? ("<color=green>Successfully added '" + text4 + "'</color>") : ("<color=red>Failed to add '" + text4 + "'</color>"), -1);
									break;
								}
							}
							return;
						}
					}
					s_CurrentHUD.AddTextToChatOnServer("<color=red>Error Expected Format is '!add LevelEvent'</color>", -1);
				}
			});
			AddCommand("!remove", delegate(int id, string msg)
			{
				if (!IsLocalPlayer(id))
				{
					s_CurrentHUD.AddTextToChatOnServer("You can't invoke this command!", -1);
				}
				else
				{
					string[] array = msg.Split(" ");
					if (array.Length >= 2)
					{
						Type t = typeof(AbstractLevelEvent);
						{
							foreach (var (text2, type2) in (from x in Assembly.GetAssembly(typeof(Plugin)).GetTypes()
								where !x.IsAbstract && t.IsAssignableFrom(x) && x.GetConstructor(Type.EmptyTypes) != null && x != typeof(RandomDifficulty)
								select new Tuple<string, Type>(x.Name, x)).ToList())
							{
								if (text2.Equals(array[1]))
								{
									AbstractLevelEvent instance = (AbstractLevelEvent)type2.GetConstructor(Type.EmptyTypes).Invoke(null);
									s_CurrentHUD.AddTextToChatOnServer(LevelModifier.RemoveFromGuaranteed(instance) ? ("Successfully removed '" + text2 + "'") : ("Failed to remove '" + text2 + "'"), -1);
									break;
								}
							}
							return;
						}
					}
					s_CurrentHUD.AddTextToChatOnServer($"Error Expected Format is '{array} LevelEvent'", -1);
				}
			});
			AddCommand("!reset", delegate(int id, string _)
			{
				if (!IsLocalPlayer(id))
				{
					s_CurrentHUD.AddTextToChatOnServer("<color=red>User not allowed to do this.</color>", -1);
				}
				else
				{
					int num = s_AddedEvents.RemoveWhere(LevelModifier.RemoveFromGuaranteed);
					s_CurrentHUD.AddTextToChatOnServer($"Pruned {num} level events.", -1);
				}
			});
			AddCommand("!clear", delegate(int id, string _)
			{
				if (IsLocalPlayer(id))
				{
					ClearChat();
				}
			});
			AddCommand("!show_events", delegate(int id, string _)
			{
				if (IsLocalPlayer(id))
				{
					ClearChat();
					LevelModifier.PostCurrentModifiersTo(s_CurrentHUD);
				}
			});
			AddCommand("!spawn_scrap", delegate(int id, string _)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				if (IsLocalPlayer(id))
				{
					ClearChat();
					Vector3 position = ((Component)StartOfRound.Instance.localPlayerController).transform.position;
					HashSet<string> hashSet = new HashSet<string>();
					SelectableLevel[] levels = StartOfRound.Instance.levels;
					for (int i = 0; i < levels.Length; i++)
					{
						foreach (SpawnableItemWithRarity item in levels[i].spawnableScrap)
						{
							Item spawnableItem = item.spawnableItem;
							if (hashSet.Add(spawnableItem.itemName))
							{
								GameObject obj = Object.Instantiate<GameObject>(spawnableItem.spawnPrefab);
								obj.GetComponent<GrabbableObject>().grabbable = true;
								obj.transform.position = position;
								obj.GetComponent<NetworkObject>().Spawn(true);
							}
						}
					}
				}
			});
		}

		public static void ClearChat()
		{
			s_CurrentHUD.AddTextToChatOnServer(new string('\n', 30), -1);
		}

		[HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> IncreaseTextInputLimit(IEnumerable<CodeInstruction> xs)
		{
			foreach (CodeInstruction x in xs)
			{
				if (x.opcode == OpCodes.Ldc_I4_S && (sbyte)x.operand == 50)
				{
					yield return new CodeInstruction(OpCodes.Ldc_I4, (object)1024);
				}
				else
				{
					yield return x;
				}
			}
		}

		[HarmonyPatch(typeof(HUDManager), "Update")]
		[HarmonyPrefix]
		private static void SetTextLimits(ref HUDManager __instance)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			if (__instance.chatTextField.characterLimit == 1024)
			{
				return;
			}
			__instance.chatTextField.characterLimit = 1024;
			TMP_InputField chatTextField = __instance.chatTextField;
			object obj = <>c.<>9__11_0;
			if (obj == null)
			{
				OnValidateInput val = (string _, int _, char c) => c;
				<>c.<>9__11_0 = val;
				obj = (object)val;
			}
			chatTextField.onValidateInput = (OnValidateInput)obj;
		}
	}
	[BepInPlugin("LCCustomDifficulty", "LCCustomDifficulty", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static ManualLogSource LOGGER;

		public static Harmony HARMONY = new Harmony("LCCustomDifficulty");

		private void Awake()
		{
			LOGGER = ((BaseUnityPlugin)this).Logger;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin LCCustomDifficulty is loaded!");
			HARMONY.PatchAll(typeof(UtilityPatches));
			HARMONY.PatchAll(typeof(GameDefaults));
			HARMONY.PatchAll(typeof(LevelModifier));
			try
			{
				LevelModifier.InitialiseLevelEvents(Assembly.GetExecutingAssembly());
				LevelModifier.InitialiseLevelEvents(Assembly.GetAssembly(typeof(InstantEnemySpawner)));
				LevelModifier.InitialiseLevelEvents(Assembly.GetAssembly(typeof(EnemyEventRandomiser)));
			}
			catch (Exception ex)
			{
				LOGGER.LogError((object)("Error initialising level events; " + ex.Message + "\n" + ex.StackTrace));
			}
			HARMONY.PatchAll(typeof(ExplosivePlayers));
			HARMONY.PatchAll(typeof(MovingLandmines));
			HARMONY.PatchAll(typeof(ExplosivePuffers));
			HARMONY.PatchAll(typeof(ExplosiveItems));
			HARMONY.PatchAll(typeof(NoisyPlayers));
			HARMONY.PatchAll(typeof(RandomlyScaledEntities));
			HARMONY.PatchAll(typeof(FreeItems));
			HARMONY.PatchAll(typeof(MagneticBodies));
			HARMONY.PatchAll(typeof(InstantEnemySpawner));
			HARMONY.PatchAll(typeof(Jumpscare));
			CommandSystem.InitialiseCommands();
			HARMONY.PatchAll(typeof(CommandSystem));
		}
	}
	public class RandomDifficulty : AbstractLevelEvent
	{
		private float m_Scalar;

		private float m_LogScalar;

		public RandomDifficulty()
			: base("Random Difficulty", -1.0, true, 1, true)
		{
		}

		public override bool Apply(ref SelectableLevel level)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected I4, but got Unknown
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Invalid comparison between Unknown and I4
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Expected O, but got Unknown
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0445: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0464: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_0483: Unknown result type (might be due to invalid IL or missing references)
			//IL_0488: Unknown result type (might be due to invalid IL or missing references)
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_049e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04aa: Expected O, but got Unknown
			float num = new AnimationCurve((Keyframe[])(object)new Keyframe[5]
			{
				new Keyframe(0.33f, 1f),
				new Keyframe(0.45f, 2f),
				new Keyframe(0.66f, 3f),
				new Keyframe(0.85f, 4f),
				new Keyframe(1f, 5f)
			}).Evaluate(Random.Range(0f, 1f));
			m_Scalar = Mathf.RoundToMultipleOf(num, 0.25f);
			m_LogScalar = 1f + Mathf.Log(Mathf.Pow(m_Scalar, 1.3f));
			SelectableLevel obj = level;
			obj.minScrap += Mathf.CeilToInt(4f * m_Scalar);
			SelectableLevel obj2 = level;
			obj2.maxScrap += Mathf.CeilToInt(8f * m_Scalar);
			SelectableLevel obj3 = level;
			obj3.minTotalScrapValue += Mathf.CeilToInt(300f * m_Scalar);
			SelectableLevel obj4 = level;
			obj4.maxTotalScrapValue += Mathf.CeilToInt(850f * m_LogScalar);
			LevelWeatherType currentWeather = level.currentWeather;
			float num2 = (currentWeather - -1) switch
			{
				0 => 1f, 
				1 => 1f, 
				2 => 1.15f, 
				3 => 1.25f, 
				4 => 1.25f, 
				5 => 1.75f, 
				6 => 3f, 
				_ => 1f, 
			};
			level.minScrap = Mathf.CeilToInt((float)level.minScrap * num2);
			level.maxScrap = Mathf.CeilToInt((float)level.maxScrap * num2);
			level.minTotalScrapValue = Mathf.CeilToInt((float)level.minTotalScrapValue * num2);
			level.maxTotalScrapValue = Mathf.CeilToInt((float)level.maxTotalScrapValue * num2);
			level.minScrap = Math.Max(level.minScrap, 5);
			level.minScrap = Math.Max(level.maxScrap, 10);
			level.minTotalScrapValue = Math.Max(level.minTotalScrapValue, 500);
			level.maxTotalScrapValue = Math.Max(level.maxTotalScrapValue, 1000);
			level.maxEnemyPowerCount = 10000;
			level.maxDaytimeEnemyPowerCount = 10000;
			level.maxOutsideEnemyPowerCount = 10000;
			float num3 = new AnimationCurve((Keyframe[])(object)new Keyframe[7]
			{
				new Keyframe(1f, 0f),
				new Keyframe(1.5f, 0.15f),
				new Keyframe(2f, 0.25f),
				new Keyframe(2.5f, 0.75f),
				new Keyframe(3f, 1f),
				new Keyframe(4f, 2f),
				new Keyframe(5f, 3.5f)
			}).Evaluate(m_Scalar);
			if ((int)level.currentWeather == 5)
			{
				num3 += 6.5f;
			}
			float num4 = 3f + num3;
			AnimationCurve enemySpawnChanceThroughoutDay = new AnimationCurve((Keyframe[])(object)new Keyframe[5]
			{
				new Keyframe(0f, -7.5f + num4 * m_LogScalar),
				new Keyframe(0.15f, -6.5f + num4 * m_LogScalar),
				new Keyframe(0.25f, -1f + num4 * m_LogScalar),
				new Keyframe(0.55f, 5f + num4 * m_LogScalar),
				new Keyframe(1f, 15f)
			});
			level.enemySpawnChanceThroughoutDay = enemySpawnChanceThroughoutDay;
			num4 = 1.3f + num3 * 0.4f;
			AnimationCurve val = new AnimationCurve((Keyframe[])(object)new Keyframe[5]
			{
				new Keyframe(0f, -7.5f + num4 * m_LogScalar),
				new Keyframe(0.15f, -5.8f + num4 * m_LogScalar),
				new Keyframe(0.25f, -2.5f + num4 * m_LogScalar),
				new Keyframe(0.55f, -1.5f + num4 * m_LogScalar),
				new Keyframe(1f, 5f)
			});
			level.outsideEnemySpawnChanceThroughDay = val;
			AnimationCurve obj5 = Util.CloneCurve(val);
			obj5.keys = obj5.GetKeys().Reverse().Zip((IEnumerable<Keyframe>)val.GetKeys(), (Func<Keyframe, Keyframe, Keyframe>)((Keyframe l, Keyframe r) => new Keyframe(((Keyframe)(ref r)).time, ((Keyframe)(ref l)).value)))
				.ToArray();
			level.Enemies.ForEach(delegate(SpawnableEnemyWithRarity x)
			{
				ApplyScalarToEnemy(x, 1.3f);
			});
			level.DaytimeEnemies.ForEach(delegate(SpawnableEnemyWithRarity x)
			{
				ApplyScalarToEnemy(x, 1.3f);
			});
			level.OutsideEnemies.ForEach(delegate(SpawnableEnemyWithRarity x)
			{
				ApplyScalarToEnemy(x, 1.3f);
			});
			return true;
			static void ApplyScalarToEnemy(SpawnableEnemyWithRarity enemy, float scalar)
			{
				EnemyType enemyType = enemy.enemyType;
				if (enemyType.MaxCount > 0)
				{
					enemyType.MaxCount = (int)Math.Clamp(Math.Ceiling((float)enemyType.MaxCount * scalar), 0.0, 20.0);
				}
			}
		}

		public override string ToString()
		{
			float scalar = m_Scalar;
			string text = ((scalar <= 2f) ? $"Normal ({m_Scalar:F2})" : ((scalar <= 3f) ? $"Medium ({m_Scalar:F2})" : ((scalar <= 4f) ? $"Hard ({m_Scalar:F2})" : ((!(scalar <= 5f)) ? $"??? ({m_Scalar:F2})" : $"Insane ({m_Scalar:F2})"))));
			string text2 = text;
			return "<color=white>" + text2 + "</color>";
		}
	}
	public class LandmineChaos : AbstractLevelEvent
	{
		public LandmineChaos()
			: base("Lots of Landmines", -1.0, true, -1, true)
		{
		}

		public override bool Apply(ref SelectableLevel level)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			SpawnableMapObject val = Util.FindMapObject<Landmine>(level);
			if (val == null)
			{
				val = Util.FindMapObject<Landmine>();
				if (val == null)
				{
					Plugin.LOGGER.LogInfo((object)"Could not find a Landmine component in any level.");
					return false;
				}
				CollectionExtensions.AddToArray<SpawnableMapObject>(level.spawnableMapObjects, val);
			}
			val.numberToSpawn = new AnimationCurve((Keyframe[])(object)new Keyframe[2]
			{
				new Keyframe(0f, 200f),
				new Keyframe(1f, 75f + Random.Range(0f, 75f))
			});
			return true;
		}
	}
	public class TurretChaos : AbstractLevelEvent
	{
		private enum Mode
		{
			NORMAL,
			MEDIUM,
			IMPOSSIBLE
		}

		private Mode m_Mode;

		public TurretChaos()
			: base("Turret Chaos", 33.333333333333336, false, -1, false)
		{
		}

		public override bool Apply(ref SelectableLevel level)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Expected O, but got Unknown
			m_Mode = (Mode)Random.RandomRangeInt(0, 3);
			SpawnableMapObject val = Util.FindMapObject<Turret>(level);
			if (val == null)
			{
				val = Util.FindMapObject<Turret>();
				if (val == null)
				{
					Plugin.LOGGER.LogInfo((object)"Could not find a Turret component in any level.");
					return false;
				}
				CollectionExtensions.AddToArray<SpawnableMapObject>(level.spawnableMapObjects, val);
			}
			val.numberToSpawn = new AnimationCurve(m_Mode switch
			{
				Mode.NORMAL => (Keyframe[])(object)new Keyframe[2]
				{
					new Keyframe(0f, 75f),
					new Keyframe(1f, 35f)
				}, 
				Mode.MEDIUM => (Keyframe[])(object)new Keyframe[2]
				{
					new Keyframe(0f, 75f),
					new Keyframe(1f, 50f)
				}, 
				Mode.IMPOSSIBLE => (Keyframe[])(object)new Keyframe[2]
				{
					new Keyframe(0f, 150f),
					new Keyframe(1f, 75f)
				}, 
				_ => Util.ZeroCurve().keys, 
			});
			level.Enemies.ForEach(delegate(SpawnableEnemyWithRarity x)
			{
				if (!Util.EnemyIs<HoarderBugAI>(x) && !Util.EnemyIs<PufferAI>(x) && !Util.EnemyIs<BlobAI>(x))
				{
					x.enemyType.probabilityCurve = Util.ZeroCurve();
					x.enemyType.MaxCount = 0;
					x.rarity = 0;
				}
			});
			int num = m_Mode switch
			{
				Mode.NORMAL => 500, 
				Mode.MEDIUM => 1000, 
				Mode.IMPOSSIBLE => 1500, 
				_ => 0, 
			};
			SelectableLevel obj = level;
			obj.minTotalScrapValue += num;
			SelectableLevel obj2 = level;
			obj2.maxTotalScrapValue += num;
			int num2 = m_Mode switch
			{
				Mode.NORMAL => 5, 
				Mode.MEDIUM => 10, 
				Mode.IMPOSSIBLE => 20, 
				_ => 0, 
			};
			SelectableLevel obj3 = level;
			obj3.minScrap += num2;
			SelectableLevel obj4 = level;
			obj4.maxScrap += num2;
			return true;
		}

		public override int CompareTo(AbstractLevelEvent other)
		{
			if (other != null && other.Name == Name)
			{
				return 0;
			}
			if (!(other is RandomDifficulty))
			{
				return 1;
			}
			return -1;
		}

		public override string ToString()
		{
			return m_Mode switch
			{
				Mode.NORMAL => "Some Turrets", 
				Mode.MEDIUM => "Lots of Turrets", 
				Mode.IMPOSSIBLE => "A lot of Turrets", 
				_ => "???", 
			};
		}
	}
	public class FreeItems : AbstractLevelEvent
	{
		private enum Item
		{
			WALKIE_TALKIE,
			FLASHLIGHT,
			SHOVEL,
			LOCK_PICKER,
			PRO_FLASHLIGHT,
			STUN_GRENADE,
			BOOMBOX,
			TZP_INHALANT,
			ZAP_GUN,
			JETPACK,
			EXTENSION_LADDER,
			RADAR_BOOSTER,
			SPRAY_PAINT,
			END_OF_ENUM
		}

		private enum Mode
		{
			RANDOM,
			USEFUL,
			USELESS,
			EXPLOSIONS,
			END_OF_ENUM
		}

		private static bool s_IsEnabled;

		private Mode m_Mode;

		public FreeItems()
			: base("Free Items!", 66.66666666666667, true, -1, true)
		{
		}

		public override bool Apply(ref SelectableLevel level)
		{
			Terminal val = Object.FindObjectOfType<Terminal>();
			if ((Object)(object)val == (Object)null)
			{
				Plugin.LOGGER.LogInfo((object)"Could not find 'Terminal' object...");
				return false;
			}
			if (Random.Range(0f, 1f) > 0.8f)
			{
				m_Mode = Mode.EXPLOSIONS;
			}
			else
			{
				m_Mode = (Mode)Random.RandomRangeInt(0, 3);
			}
			switch (m_Mode)
			{
			case Mode.RANDOM:
			{
				int num2 = Random.RandomRangeInt(2, 7);
				for (int j = 0; j < num2; j++)
				{
					val.orderedItemsFromTerminal.Add(Random.RandomRangeInt(0, 13));
				}
				break;
			}
			case Mode.USEFUL:
			{
				int num3 = Random.RandomRangeInt(2, 5);
				Item[] array2 = new Item[6]
				{
					Item.SHOVEL,
					Item.PRO_FLASHLIGHT,
					Item.STUN_GRENADE,
					Item.ZAP_GUN,
					Item.JETPACK,
					Item.EXTENSION_LADDER
				};
				for (int k = 0; k < num3; k++)
				{
					val.orderedItemsFromTerminal.Add((int)array2[Random.RandomRangeInt(0, array2.Length)]);
				}
				break;
			}
			case Mode.USELESS:
			{
				int num = Random.RandomRangeInt(2, 5);
				Item[] array = new Item[7]
				{
					Item.WALKIE_TALKIE,
					Item.FLASHLIGHT,
					Item.LOCK_PICKER,
					Item.BOOMBOX,
					Item.TZP_INHALANT,
					Item.RADAR_BOOSTER,
					Item.SPRAY_PAINT
				};
				for (int i = 0; i < num; i++)
				{
					val.orderedItemsFromTerminal.Add((int)array[Random.RandomRangeInt(0, array.Length)]);
				}
				break;
			}
			case Mode.EXPLOSIONS:
				s_IsEnabled = true;
				val.orderedItemsFromTerminal.Add(9);
				break;
			}
			return true;
		}

		public override void OnMatchFinished()
		{
			s_IsEnabled = false;
		}

		public override string ToString()
		{
			string[] messages = new string[4] { "Random Items :)", "Useful Items :)", "Useless Items :(", "Explosive Delivery!" };
			return m_Mode switch
			{
				Mode.RANDOM => messages[0], 
				Mode.USEFUL => messages[1], 
				Mode.USELESS => messages[2], 
				Mode.EXPLOSIONS => GetExplosiveStr(), 
				_ => "Should Not Happen; Error", 
			};
			string GetExplosiveStr()
			{
				int num = Random.RandomRangeInt(0, messages.Length);
				string text = messages[num];
				if (num == messages.Length - 1)
				{
					return text;
				}
				char[] array = text.ToCharArray();
				int num2 = Random.RandomRangeInt(0, array.Length);
				int num3 = Random.RandomRangeInt(0, array.Length);
				ref char reference = ref array[num2];
				ref char reference2 = ref array[num3];
				char c = array[num3];
				char c2 = array[num2];
				reference = c;
				reference2 = c2;
				return new string(array);
			}
		}

		[HarmonyPatch(typeof(ItemDropship), "Update")]
		[HarmonyPrefix]
		private static void ExplodeOnDropShipOpen(ref ItemDropship __instance)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (s_IsEnabled && __instance.shipDoorsOpened)
			{
				Plugin.LOGGER.LogInfo((object)"Drop Ship Opened!");
				Vector3 position = ((Component)__instance).transform.position;
				((MonoBehaviour)__instance).StartCoroutine(SpawnExplosionsAround(position, 8f, 24, 1f / 3f));
				s_IsEnabled = false;
			}
		}

		private static IEnumerator SpawnExplosionsAround(Vector3 pos, float radius, int count, float delay)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			float theta = 360f / (float)count;
			Vector3 val = default(Vector3);
			for (int i = 0; i < count; i++)
			{
				float num = (float)i * theta;
				((Vector3)(ref val))..ctor(radius * Mathf.Cos(MathF.PI / 180f * num), 0f, radius * Mathf.Sin(MathF.PI / 180f * num));
				MessageBuilder.Create().SetSourceClientToLocal().SetTargetClientAll(true)
					.AddParam("SpawnExplosionAt", true)
					.AddParams(new object[4]
					{
						pos + val,
						true,
						radius,
						radius * 1.5f
					})
					.Broadcast();
				yield return (object)new WaitForSeconds(delay);
			}
		}
	}
	public abstract class OnlyEnemyType : AbstractLevelEvent
	{
		protected struct EnemyData
		{
			public bool IsUntouched { get; set; }

			public int Rarity { get; set; }

			public int MaxCount { get; set; }

			public AnimationCurve DropOff { get; set; }

			public AnimationCurve SpawnCurve { get; set; }

			public EnemyData()
			{
				IsUntouched = false;
				Rarity = -1;
				MaxCount = -1;
				DropOff = null;
				SpawnCurve = null;
			}

			public void Apply(SpawnableEnemyWithRarity enemy)
			{
				if (!IsUntouched)
				{
					if (Rarity >= 0)
					{
						enemy.rarity = Rarity;
					}
					if (MaxCount >= 0)
					{
						enemy.enemyType.MaxCount = MaxCount;
					}
					if (DropOff != null)
					{
						enemy.enemyType.numberSpawnedFalloff = DropOff;
					}
					if (DropOff != null)
					{
						enemy.enemyType.probabilityCurve = SpawnCurve;
					}
				}
			}
		}

		protected static Tuple<bool, EnemyData> LowerChance(int rarity)
		{
			return new Tuple<bool, EnemyData>(item1: true, new EnemyData
			{
				Rarity = rarity,
				SpawnCurve = Util.ModerateCurve()
			});
		}

		protected static Tuple<bool, EnemyData> AllowEnemy(EnemyData data)
		{
			return new Tuple<bool, EnemyData>(item1: true, data);
		}

		protected static Tuple<bool, EnemyData> AllowEnemyUntouched()
		{
			return new Tuple<bool, EnemyData>(item1: true, new EnemyData
			{
				IsUntouched = true
			});
		}

		protected static Tuple<bool, EnemyData> DisallowEnemy()
		{
			return new Tuple<bool, EnemyData>(item1: false, new EnemyData());
		}

		protected OnlyEnemyType(string name, double weight = 50.0, bool is_additive = false, int ordering = -1, bool natural_ordering = false, params string[] ordering_tags)
			: base(name, weight, is_additive, ordering, natural_ordering, ordering_tags)
		{
		}

		protected virtual IEnumerable<SpawnableEnemyWithRarity> IterateEnemies(SelectableLevel level)
		{
			return level.Enemies;
		}

		protected abstract Tuple<bool, EnemyData> IsEnemyAllowed(SpawnableEnemyWithRarity enemy);

		public override bool Apply(ref SelectableLevel level)
		{
			foreach (SpawnableEnemyWithRarity item in IterateEnemies(level))
			{
				var (flag2, enemyData2) = IsEnemyAllowed(item);
				if (!flag2)
				{
					Util.ZeroEnemy(item);
				}
				enemyData2.Apply(item);
			}
			return true;
		}

		public override int CompareTo(AbstractLevelEvent other)
		{
			if (other != null && other.Name == Name)
			{
				return 0;
			}
			if (!(other is RandomDifficulty))
			{
				return 1;
			}
			return -1;
		}
	}
	internal class RedLocustBeeChaos : OnlyEnemyType
	{
		public RedLocustBeeChaos()
			: base("Cunt with Wings", 40.0, true, -1, false)
		{
		}

		protected override IEnumerable<SpawnableEnemyWithRarity> IterateEnemies(SelectableLevel level)
		{
			return level.DaytimeEnemies;
		}

		protected override Tuple<bool, EnemyData> IsEnemyAllowed(SpawnableEnemyWithRarity enemy)
		{
			if (Util.EnemyIs<RedLocustBees>(enemy))
			{
				enemy.rarity = 999;
				enemy.enemyType.MaxCount = 4;
				enemy.enemyType.numberSpawnedFalloff = Util.ModerateCurve();
				enemy.enemyType.probabilityCurve = Util.MaxCurve();
			}
			return OnlyEnemyType.AllowEnemyUntouched();
		}
	}
	internal class ApexPredator : OnlyEnemyType
	{
		private enum Type
		{
			DOG,
			GIANT,
			WORM
		}

		private Type m_EnemyType;

		private int GetRarityFor(Type type)
		{
			if (m_EnemyType != type)
			{
				return 5;
			}
			return 90;
		}

		public ApexPredator()
			: base("Apex Predator", 66.66666666666667, true, -1, false)
		{
		}

		protected override IEnumerable<SpawnableEnemyWithRarity> IterateEnemies(SelectableLevel level)
		{
			m_EnemyType = (Type)Random.RandomRangeInt(0, 3);
			return level.OutsideEnemies;
		}

		protected override Tuple<bool, EnemyData> IsEnemyAllowed(SpawnableEnemyWithRarity enemy)
		{
			if (Util.EnemyIs<SandWormAI>(enemy))
			{
				EnemyData data = new EnemyData();
				data.Rarity = GetRarityFor(Type.WORM);
				data.MaxCount = 4;
				data.DropOff = Util.ModerateCurve();
				data.SpawnCurve = Util.MaxCurve();
				return OnlyEnemyType.AllowEnemy(data);
			}
			if (Util.EnemyIs<MouthDogAI>(enemy))
			{
				EnemyData data = new EnemyData();
				data.Rarity = GetRarityFor(Type.DOG);
				data.MaxCount = 4;
				data.DropOff = Util.ModerateCurve();
				data.SpawnCurve = Util.MaxCurve();
				return OnlyEnemyType.AllowEnemy(data);
			}
			if (Util.EnemyIs<ForestGiantAI>(enemy))
			{
				EnemyData data = new EnemyData();
				data.Rarity = GetRarityFor(Type.GIANT);
				data.MaxCount = 4;
				data.DropOff = Util.ModerateCurve();
				data.SpawnCurve = Util.MaxCurve();
				return OnlyEnemyType.AllowEnemy(data);
			}
			return OnlyEnemyType.DisallowEnemy();
		}

		public override string ToString()
		{
			return m_EnemyType switch
			{
				Type.DOG => "Beware the Dogs", 
				Type.GIANT => "POV You are a Snack", 
				Type.WORM => "Tremors???", 
				_ => "???", 
			};
		}
	}
	public class ExplosivePlayers : AbstractLevelEvent
	{
		private static bool s_IsEnabled = false;

		private static HashSet<ulong> s_KilledPlayers = new HashSet<ulong>();

		[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
		[HarmonyPrefix]
		private static void SpawnExplosionOnPlayerDeath(ref PlayerControllerB __instance, ref Vector3 bodyVelocity, ref bool spawnBody, ref CauseOfDeath causeOfDeath, ref int deathAnimation)
		{
			if (s_IsEnabled && (int)causeOfDeath != 3 && s_KilledPlayers.Add(__instance.actualClientId))
			{
				MessageBuilder.Create().SetSourceClientToLocal().SetTargetClientAll(true)
					.AddParam("SpawnExplosionOnPlayer", true)
					.AddParam((float)__instance.actualClientId)
					.AddParams(new object[3] { true, 2f, 2f })
					.Broadcast();
			}
		}

		public ExplosivePlayers()
			: base("Explosive Players", 66.66666666666667, true, -1, true)
		{
		}

		public override bool Apply(ref SelectableLevel level)
		{
			s_KilledPlayers.Clear();
			s_IsEnabled = true;
			return true;
		}

		public override void OnMatchFinished()
		{
			s_IsEnabled = false;
		}
	}
	public class ExplosivePuffers : AbstractLevelEvent
	{
		private static bool s_IsEnabled;

		[HarmonyPatch(typeof(PufferAI), "StompClientRpc")]
		[HarmonyPostfix]
		private static void OnPuffExplode(PufferAI __instance)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (s_IsEnabled)
			{
				MessageBuilder.Create().SetSourceClientToLocal().SetTargetClientAll(true)
					.AddParam("SpawnExplosionAt", true)
					.AddParam(((Component)__instance).transform.position)
					.AddParam(true)
					.AddParam(5f)
					.AddParam(7.5f)
					.Broadcast();
			}
		}

		public ExplosivePuffers()
			: base("Huff and Puff", 50.0, true, -1, true)
		{
		}

		public override bool Apply(ref SelectableLevel level)
		{
			SpawnableEnemyWithRarity val = Util.FindInsideEnemy<PufferAI>(level);
			if (val == null)
			{
				return false;
			}
			s_IsEnabled = true;
			val.rarity = 999;
			val.enemyType.MaxCount = 5;
			val.enemyType.numberSpawnedFalloff = Util.ModerateCurve();
			val.enemyType.probabilityCurve = Util.MaxCurve();
			return true;
		}

		public override void OnMatchFinished()
		{
			s_IsEnabled = false;
		}
	}
	public class ExplosiveItems : AbstractLevelEvent
	{
		public static bool s_IsEnabled;

		public ExplosiveItems()
			: base("Explosive Items?", 33.333333333333336, true, -1, true)
		{
		}

		public override bool Apply(ref SelectableLevel level)
		{
			s_IsEnabled = true;
			return true;
		}

		public override void OnMatchFinished()
		{
			s_IsEnabled = false;
		}

		public static void OnItemActivateImpl(GrabbableObject item, bool is_used)
		{
			if (s_IsEnabled && is_used && !((Object)(object)item.playerHeldBy == (Object)null))
			{
				MessageBuilder.Create().SetSourceClientToLocal().SetTargetClientAll(true)
					.AddParam("SpawnExplosionOnPlayer", true)
					.AddParam((float)item.playerHeldBy.actualClientId)
					.AddParams(new object[3] { true, 2f, 2f })
					.Broadcast();
			}
		}

		[HarmonyPatch(typeof(StunGrenadeItem), "ItemActivate")]
		[HarmonyPrefix]
		private static void ExplodeStunGrenadeOnActivate(ref StunGrenadeItem __instance, ref bool used, ref bool buttonDown)
		{
			OnItemActivateImpl((GrabbableObject)(object)__instance, used);
		}

		[HarmonyPatch(typeof(BoomboxItem), "ItemActivate")]
		[HarmonyPrefix]
		private static void ExplodeBoomboxOnActivate(ref BoomboxItem __instance, ref bool used, ref bool buttonDown)
		{
			OnItemActivateImpl((GrabbableObject)(object)__instance, used);
		}

		[HarmonyPatch(typeof(FlashlightItem), "ItemActivate")]
		[HarmonyPrefix]
		private static void ExplodeFlashlightOnActivate(ref FlashlightItem __instance, ref bool used, ref bool buttonDown)
		{
			OnItemActivateImpl((GrabbableObject)(object)__instance, used);
		}

		[HarmonyPatch(typeof(ExtensionLadderItem), "ItemActivate")]
		[HarmonyPrefix]
		public static void ExplodeLadderOnActivate(ref ExtensionLadderItem __instance, ref bool used, ref bool buttonDown)
		{
			OnItemActivateImpl((GrabbableObject)(object)__instance, used);
		}
	}
	public class MovingLandmines : AbstractLevelEvent
	{
		private enum Mode
		{
			SLOW,
			NORMAL,
			FAST,
			VERY_FAST
		}

		private static bool s_IsEnabled;

		private static StartOfRound s_StartOfRound;

		private static MovingLandmines s_Instance;

		private Mode m_Mode;

		[HarmonyPatch(typeof(Landmine), "Update")]
		[HarmonyPrefix]
		private static void LandmineUpdate(ref Landmine __instance)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			if (!s_IsEnabled || (Object)(object)s_StartOfRound == (Object)null || s_StartOfRound.inShipPhase || __instance.hasExploded)
			{
				return;
			}
			Transform transform = ((Component)__instance).transform;
			Vector3 position = transform.position;
			Vector3 val = default(Vector3);
			float num = float.MaxValue;
			PlayerControllerB val2 = null;
			PlayerControllerB[] allPlayerScripts = s_StartOfRound.allPlayerScripts;
			foreach (PlayerControllerB val3 in allPlayerScripts)
			{
				if (val3.isPlayerDead)
				{
					continue;
				}
				Vector3 position2 = ((Component)val3).transform.position;
				if (!(Mathf.Abs(position2.y - position.y) > 0.15f))
				{
					float num2 = Vector3.Distance(position, position2);
					if (!(num2 > 4f) && !(num2 < 1.75f) && num2 < num)
					{
						val2 = val3;
						num = num2;
						val = position2;
					}
				}
			}
			if (!((Object)(object)val2 == (Object)null))
			{
				Vector3 val4 = val - position;
				((Vector3)(ref val4)).Normalize();
				transform.position += val4 * s_Instance.Speed() * Time.deltaTime;
			}
		}

		public MovingLandmines()
			: base("Is that a Roomba???", 33.333333333333336, false, -1, true)
		{
		}

		public override bool Apply(ref SelectableLevel level)
		{
			s_StartOfRound = StartOfRound.Instance;
			s_Instance = this;
			m_Mode = (Mode)Random.RandomRangeInt(0, 3);
			if (Random.Range(0f, 1f) <= 0.05f)
			{
				m_Mode = Mode.VERY_FAST;
			}
			s_IsEnabled = true;
			MessageBuilder.Create().SetSourceClientToLocal().SetTargetClientAll(false)
				.AddParam("MovingLandmines", true)
				.AddParam(true)
				.AddParam(Speed())
				.Broadcast();
			return true;
		}

		public float Speed()
		{
			return m_Mode switch
			{
				Mode.SLOW => 1.01f, 
				Mode.NORMAL => 1.025f, 
				Mode.FAST => 1.05f, 
				Mode.VERY_FAST => 3f, 
				_ => 1.01f, 
			};
		}

		public override void OnMatchFinished()
		{
			s_IsEnabled = false;
			MessageBuilder.Create().SetSourceClientToLocal().SetTargetClientAll(false)
				.AddParam("MovingLandmines", true)
				.AddParam(false)
				.AddParam(0f)
				.Broadcast();
		}

		public override string ToString()
		{
			return m_Mode switch
			{
				Mode.SLOW => "Slow Roomba", 
				Mode.NORMAL => "Normal Roomba", 
				Mode.FAST => "Fast Roomba", 
				Mode.VERY_FAST => "Ka-Chow Roomba", 
				_ => "??? Roomba", 
			};
		}
	}
	public class NoisyPlayers : AbstractLevelEvent
	{
		private static bool s_IsEnabled;

		private static float s_Theta;

		[HarmonyPatch(typeof(PlayerControllerB), "Update")]
		[HarmonyPrefix]
		private static void PlayNoisePeriodically()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (!s_IsEnabled || StartOfRound.Instance.inShipPhase)
			{
				return;
			}
			s_Theta -= Time.deltaTime;
			if (!(s_Theta > 0f))
			{
				s_Theta = Random.Range(0.5f, 10f);
				PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
				foreach (PlayerControllerB val in allPlayerScripts)
				{
					RoundManager.Instance.PlayAudibleNoise(((Component)val).transform.position, 35f, 1.5f, 0, val.isInHangarShipRoom && val.playersManager.hangarDoorsClosed, 7);
				}
			}
		}

		public NoisyPlayers()
			: base("Noisy Players", 40.0, true, -1, true)
		{
		}

		public override bool Apply(ref SelectableLevel level)
		{
			return s_IsEnabled = true;
		}

		public override void OnMatchFinished()
		{
			s_IsEnabled = false;
		}
	}
	public class RandomlyScaledEntities : AbstractLevelEvent
	{
		public static bool s_IsEnabled = false;

		private static float s_PollingTime = 0f;

		private static HashSet<ulong> s_ModifiedEnemies = new HashSet<ulong>();

		public RandomlyScaledEntities()
			: base("Big or Small?", -1.0, true, -1, true)
		{
		}

		[HarmonyPatch(typeof(RoundManager), "Update")]
		[HarmonyPrefix]
		public static void SetEnemyScaleOnCreation(ref RoundManager __instance)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			if (!s_IsEnabled)
			{
				return;
			}
			s_PollingTime -= Time.deltaTime;
			if (s_PollingTime > 0f)
			{
				return;
			}
			s_PollingTime = 0.5f;
			foreach (EnemyAI spawnedEnemy in __instance.SpawnedEnemies)
			{
				if (s_ModifiedEnemies.Add(spawnedEnemy.thisNetworkObject.NetworkObjectId))
				{
					float num = Random.Range(0.5f, 1.5f);
					MessageBuilder.Create().SetSourceClientToLocal().SetTargetClientAll(true)
						.AddParam("SetEnemyScale", true)
						.AddParam((float)spawnedEnemy.thisNetworkObject.NetworkObjectId)
						.AddParam(new Vector3(num, num, num))
						.AddDelaySeconds(5f)
						.Broadcast();
				}
			}
		}

		public override bool Apply(ref SelectableLevel level)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			s_IsEnabled = true;
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (!((Object)(object)val == (Object)null) && val.isPlayerControlled && (val.actualClientId != 0L || val.isHostPlayerObject))
				{
					float num = Random.Range(0.35f, 1.35f);
					MessageBuilder.Create().SetSourceClientToLocal().SetTargetClientAll(true)
						.AddParam("SetPlayerScale", true)
						.AddParam((float)val.actualClientId)
						.AddParam(new Vector3(num, num, num))
						.Broadcast();
				}
			}
			return true;
		}

		public override void OnMatchFinished()
		{
			s_IsEnabled = false;
			s_ModifiedEnemies.Clear();
			MessageBuilder.Create().SetSourceClientToLocal().SetTargetClientAll(true)
				.AddParam("ResetAllPlayerScales", true)
				.Broadcast();
		}
	}
	public class MagneticBodies : AbstractLevelEvent
	{
		private static bool s_IsEnabled;

		private static float s_Timer;

		public MagneticBodies()
			: base("Magneto", 33.333333333333336, true, -1, true)
		{
		}

		public override bool Apply(ref SelectableLevel level)
		{
			Plugin.LOGGER.LogInfo((object)"Enabling Magneto Mode");
			s_IsEnabled = true;
			return true;
		}

		public override void OnMatchFinished()
		{
			s_IsEnabled = false;
		}

		[HarmonyPatch(typeof(DeadBodyInfo), "Update")]
		[HarmonyPrefix]
		private static void PeriodicallyThrowBodyAtNearestPlayer(ref DeadBodyInfo __instance)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: 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_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: 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_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			if (!s_IsEnabled || __instance.isInShip || __instance.deactivated || __instance.grabBodyObject.isHeld)
			{
				return;
			}
			s_Timer -= Time.deltaTime;
			if (s_Timer > 0f)
			{
				return;
			}
			s_Timer = Random.Range(1.5f, 3f);
			Vector3 position = ((Component)__instance).transform.position;
			Transform val = null;
			Vector3 val2 = default(Vector3);
			float num = 0f;
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val3 in allPlayerScripts)
			{
				if (!val3.isPlayerDead && (val3.actualClientId != 0L || val3.isHostPlayerObject))
				{
					Transform transform = ((Component)val3).transform;
					Vector3 position2 = transform.position;
					float num2 = Vector3.Distance(position, position2);
					if ((Object)(object)val == (Object)null || num2 < num)
					{
						val = transform;
						val2 = position2;
						num = num2;
					}
				}
			}
			Plugin.LOGGER.LogInfo((object)("Closest Player == " + ((object)val)?.ToString() + "; Distance = " + num));
			if (!((Object)(object)val == (Object)null) && !(num > 30f) && !(num < 3f))
			{
				Vector3 val4 = val2 - position + new Vector3(0f, 1f, 0f);
				((Vector3)(ref val4)).Normalize();
				Plugin.LOGGER.LogInfo((object)$"Launching Body towards player: {num:F2}");
				Vector3 val5 = val4 * num * 20f;
				MessageBuilder.Create().SetSourceClientToLocal().SetTargetClientAll(true)
					.AddParam("SetForceToAllBodyParts", true)
					.AddParam((float)__instance.playerScript.actualClientId)
					.AddParam(val5)
					.AddParam(position)
					.AddParam(val2 + new Vector3(0f, 1.5f, 0f))
					.Broadcast();
			}
		}
	}
	public class OnlyClownHorns : AbstractLevelEvent
	{
		private List<SpawnableItemWithRarity> m_OriginalItems = new List<SpawnableItemWithRarity>();

		private SelectableLevel m_PreviousLevel;

		public OnlyClownHorns()
			: base("They Gave Me Clown Juice!", 40.0, true, -1, true)
		{
		}

		public override bool Apply(ref SelectableLevel level)
		{
			m_OriginalItems.Clear();
			m_OriginalItems = level.spawnableScrap.ToList();
			m_PreviousLevel = level;
			level.spawnableScrap.Clear();
			foreach (SpawnableItemWithRarity originalItem in m_OriginalItems)
			{
				if (originalItem.spawnableItem.itemName == "Clown horn")
				{
					level.spawnableScrap.Add(originalItem);
				}
			}
			return true;
		}

		public override void OnMatchFinished()
		{
			m_PreviousLevel.spawnableScrap.Clear();
			foreach (SpawnableItemWithRarity originalItem in m_OriginalItems)
			{
				m_PreviousLevel.spawnableScrap.Add(originalItem);
			}
		}
	}
	public class Jumpscare : AbstractLevelEvent
	{
		public interface IScareEvent
		{
			double Weight { get; }

			string Name()
			{
				return GetType().Name;
			}

			void Apply(ScareablePlayer scareable, PlayerControllerB p);
		}

		public class EmptyScareEvent : IScareEvent
		{
			public double Weight => 1.5;

			public void Apply(ScareablePlayer scareable, PlayerControllerB p)
			{
				Plugin.LOGGER.LogInfo((object)"Empty Scare Event Triggering!");
			}
		}

		public class ScareablePlayer
		{
			private static WeightedRandom<IScareEvent> s_ScareRandom;

			public PlayerControllerB Player { get; set; }

			public float TimeUntilNextScare { get; set; }

			public int ScareCount { get; set; }

			public IScareEvent LastScare { get; set; }

			public ScareablePlayer(PlayerControllerB player)
			{
				Player = player;
				AdvanceState();
				if (s_ScareRandom == null)
				{
					Type scare_type = typeof(IScareEvent);
					s_ScareRandom = new WeightedRandom<IScareEvent>((from x in Assembly.GetExecutingAssembly().GetTypes()
						where !x.IsAbstract && !x.IsInterface && scare_type.IsAssignableFrom(x)
						select x.GetConstructor(Type.EmptyTypes) into x
						where x != null
						select (IScareEvent)x.Invoke(null) into x
						select WeightedParameterFactory.Create(x, x.Weight)).ToList());
					double sum = s_ScareRandom.WeightSum;
					string text = GeneralExtensions.Join<WeightedParameter<IScareEvent>>((IEnumerable<WeightedParameter<IScareEvent>>)s_ScareRandom.WeightedParameters, (Func<WeightedParameter<IScareEvent>, string>)((WeightedParameter<IScareEvent> x) => $"{x.Value.Name(),16} => {Util.GetWeightAsPercentage(x.Weight, sum):F2}"), ", ");
					Plugin.LOGGER.LogInfo((object)("Jumpscare Events => '" + text + "'"));
				}
			}

			public bool CanScare()
			{
				return TimeUntilNextScare <= 0f;
			}

			public void AdvanceState()
			{
				int scareCount = ScareCount + 1;
				ScareCount = scareCount;
				float num = 30f * (float)ScareCount;
				TimeUntilNextScare = Random.Range(60f + num, 80f + num);
				if (ScareCount > 5)
				{
					ScareCount = 0;
				}
			}

			public IScareEvent GetNextScareType(bool adjust_last = true)
			{
				IScareEvent scareEvent;
				do
				{
					scareEvent = s_ScareRandom.Next();
				}
				while (LastScare != null && scareEvent.Name() == LastScare.Name());
				if (adjust_last)
				{
					LastScare = scareEvent;
				}
				return scareEvent;
			}
		}

		private static bool s_IsEnabled = false;

		private static List<ScareablePlayer> s_ScareStats = new List<ScareablePlayer>();

		public Jumpscare()
			: base("The Boogieman", 50.0, false, -1, true)
		{
		}

		public override bool Apply(ref SelectableLevel level)
		{
			s_ScareStats.Clear();
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (val.isPlayerControlled && (val.actualClientId != 0L || val.isHostPlayerObject))
				{
					s_ScareStats.Add(new ScareablePlayer(val));
				}
			}
			s_IsEnabled = true;
			return true;
		}

		public override void OnMatchFinished()
		{
			s_IsEnabled = false;
		}

		[HarmonyPatch(typeof(StartOfRound), "Update")]
		[HarmonyPrefix]
		private static void PerformJumpscarePeriodically(StartOfRound __instance)
		{
			if (!s_IsEnabled || __instance.inShipPhase || __instance.shipIsLeaving)
			{
				return;
			}
			foreach (ScareablePlayer s_ScareStat in s_ScareStats)
			{
				PlayerControllerB player = s_ScareStat.Player;
				if (!player.isPlayerDead && !player.isInElevator)
				{
					s_ScareStat.TimeUntilNextScare -= Time.deltaTime;
					if (s_ScareStat.CanScare())
					{
						s_ScareStat.AdvanceState();
						IScareEvent nextScareType = s_ScareStat.GetNextScareType();
						Plugin.LOGGER.LogInfo((object)("Applying Jumpscare '" + nextScareType.Name() + "' to player '" + player.playerUsername + "'"));
						nextScareType.Apply(s_ScareStat, s_ScareStat.Player);
					}
				}
			}
		}
	}
	public class LethalScareEvent : Jumpscare.IScareEvent
	{
		private static List<SpawnableEnemyWithRarity> s_Enemies;

		public double Weight => 6.5;

		public void Apply(Jumpscare.ScareablePlayer scareable, PlayerControllerB p)
		{
			if (s_Enemies == null)
			{
				s_Enemies = new List<SpawnableEnemyWithRarity>
				{
					Util.FindInsideEnemy<FlowermanAI>(),
					Util.FindInsideEnemy<SpringManAI>(),
					Util.FindInsideEnemy<NutcrackerEnemyAI>(),
					Util.FindInsideEnemy<MaskedPlayerEnemy>(),
					Util.FindInsideEnemy<SandSpiderAI>()
				};
				s_Enemies.RemoveAll(delegate(SpawnableEnemyWithRarity x)
				{
					if (x != null)
					{
						return false;
					}
					Plugin.LOGGER.LogInfo((object)"LethalScareEvent :: Lethal Enemy was not found.");
					return true;
				});
			}
			((MonoBehaviour)p).StartCoroutine(TrackPlayerAndSpawnEnemy(p));
		}

		private IEnumerator TrackPlayerAndSpawnEnemy(PlayerControllerB p)
		{
			Transform transform = ((Component)p).transform;
			Tuple<bool, Vector3>[] positions = new Tuple<bool, Vector3>[10];
			for (int i = 0; i < positions.Length; i++)
			{
				positions[i] = new Tuple<bool, Vector3>(p.isInsideFactory, transform.position);
				yield return (object)new WaitForSeconds(Random.Range(0.1f, 0.2f));
			}
			string text = GeneralExtensions.Join<Vector3>(positions.Select((Tuple<bool, Vector3> x) => x.Item2), (Func<Vector3, string>)((Vector3 p) => $"({p.x:F2}, {p.y:F2}, {p.z:F2})"), ", ");
			Plugin.LOGGER.LogInfo((object)("Jumpscare :: Tracked Player Positions '" + text + "'"));
			Vector3 position = transform.position;
			Vector3 val = Vector3.zero;
			float num = -1f;
			Tuple<bool, Vector3>[] array = positions;
			for (int j = 0; j < array.Length; j++)
			{
				var (flag2, val3) = array[j];
				if (p.isInsideFactory == flag2)
				{
					float num2 = Vector3.Distance(position, val3);
					if (!(num > num2))
					{
						val = val3;
						num = num2;
					}
				}
			}
			if (num < 0f)
			{
				Plugin.LOGGER.LogInfo((object)"No valid points were found for the player to spawn a dangerous enemy on");
				yield break;
			}
			SpawnableEnemyWithRarity val4;
			if (p.isInsideFactory)
			{
				val4 = s_Enemies[Random.RandomRangeInt(0, s_Enemies.Count)];
			}
			else
			{
				SpawnableEnemyWithRarity val5 = Util.FindOutsideEnemy<MouthDogAI>();
				SpawnableEnemyWithRarity val6 = Util.FindOutsideEnemy<ForestGiantAI>();
				if (val5 == null && val6 != null)
				{
					val4 = val6;
				}
				else if (val6 == null && val5 != null)
				{
					val4 = val5;
				}
				else
				{
					if (val5 == null)
					{
						Plugin.LOGGER.LogInfo((object)"LethalScareEvent :: Could not find MouthDogAI");
						yield break;
					}
					val4 = ((Random.Range(0f, 1f) < 0.66f) ? val5 : val6);
				}
			}
			Plugin.LOGGER.LogInfo((object)("LethalScareEvent :: Spawning '" + val4.enemyType.enemyName + "' at " + $"'{val}' to scare player " + "'" + p.playerUsername + "'"));
			GameObject instance = Object.Instantiate<GameObject>(val4.enemyType.enemyPrefab, val + new Vector3(0f, 1f, 0f), Quaternion.Euler(Vector3.zero));
			if (RandomlyScaledEntities.s_IsEnabled)
			{
				float num3 = Random.Range(0.4f, 1.35f);
				instance.transform.localScale = new Vector3(num3, num3, num3);
			}
			instance.GetComponentInChildren<NetworkObject>().Spawn(true);
			yield return (object)new WaitForSeconds(90f);
			if (!((Object)(object)instance == (Object)null))
			{
				instance.GetComponentInChildren<NetworkObject>().Despawn(true);
			}
		}
	}
	public class LandmineScareEvent : Jumpscare.IScareEvent
	{
		public double Weight => 2.0;

		public void Apply(Jumpscare.ScareablePlayer scareable, PlayerControllerB p)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			((MonoBehaviour)p).StartCoroutine(SpawnLandmineDelayed(((Component)p).transform.position, Random.Range(0.05f, 0.5f)));
		}

		private static IEnumerator SpawnLandmineDelayed(Vector3 pos, float delay_seconds)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			SpawnableMapObject mine = Util.FindMapObject<Landmine>();
			yield return (object)new WaitForSeconds(delay_seconds);
			GameObject instance = Object.Instantiate<GameObject>(mine.prefabToSpawn);
			instance.transform.position = pos;
			float num = Random.Range(0.35f, 1.15f);
			instance.transform.localScale = new Vector3(num, 1f, num);
			instance.GetComponent<NetworkObject>().Spawn(true);
			yield return (object)new WaitForSeconds(45f);
			if (!((Object)(object)instance == (Object)null))
			{
				instance.GetComponent<NetworkObject>().Despawn(true);
			}
		}
	}
	public class TurretScareEvent : Jumpscare.IScareEvent
	{
		public double Weight => 3.0;

		public void Apply(Jumpscare.ScareablePlayer scareable, PlayerControllerB p)
		{
			if (p.isInsideFactory)
			{
				((MonoBehaviour)p).StartCoroutine(SpawnTurretDelayed(p, Random.Range(0.1f, 0.5f)));
			}
		}

		private static IEnumerator SpawnTurretDelayed(PlayerControllerB p, float delay_seconds)
		{
			Transform transform = ((Component)p).transform;
			Vector3 player_pos = transform.position;
			Quaternion player_rotate = transform.rotation;
			yield return (object)new WaitForSeconds(delay_seconds);
			if (!p.isInsideFactory)
			{
				yield break;
			}
			SpawnableMapObject val = Util.FindMapObject<Turret>();
			if (val != null)
			{
				GameObject instance = Object.Instantiate<GameObject>(val.prefabToSpawn, player_pos, player_rotate);
				instance.GetComponentInChildren<NetworkObject>().Spawn(true);
				yield return (object)new WaitForSeconds(90f);
				if (!((Object)(object)instance == (Object)null))
				{
					instance.GetComponentInChildren<NetworkObject>().Despawn(true);
				}
			}
		}
	}
	public static class LevelModifier
	{
		private static WeightedRandom<AbstractLevelEvent> s_LevelEventRandom = new WeightedRandom<AbstractLevelEvent>();

		private static List<AbstractLevelEvent> s_GuaranteedLevelEvents = new List<AbstractLevelEvent>();

		private static SortedSet<AbstractLevelEvent> s_ActiveEvents = new SortedSet<AbstractLevelEvent>();

		public static void InitialiseLevelEvents(Assembly asm = null)
		{
			Type type = typeof(AbstractLevelEvent);
			List<AbstractLevelEvent> list = (from x in (asm ?? Assembly.GetExecutingAssembly()).GetTypes()
				where type.IsAssignableFrom(x) && !x.IsAbstract
				select x.GetConstructor(Type.EmptyTypes) into x
				where x != null
				select (AbstractLevelEvent)x.Invoke(null)).ToList();
			HashSet<AbstractLevelEvent> hashSet = new HashSet<AbstractLevelEvent>();
			HashSet<AbstractLevelEvent> hashSet2 = new HashSet<AbstractLevelEvent>();
			foreach (AbstractLevelEvent item3 in list)
			{
				if (item3.IsGuaranteed())
				{
					hashSet.Add(item3);
				}
				else
				{
					hashSet2.Add(item3);
				}
			}
			foreach (AbstractLevelEvent s_GuaranteedLevelEvent in s_GuaranteedLevelEvents)
			{
				if (s_GuaranteedLevelEvent.IsGuaranteed())
				{
					hashSet.Add(s_GuaranteedLevelEvent);
				}
				else
				{
					hashSet2.Add(s_GuaranteedLevelEvent);
				}
			}
			AbstractLevelEvent item;
			double item2;
			foreach (WeightedParameter<AbstractLevelEvent> weightedParameter in s_LevelEventRandom.WeightedParameters)
			{
				weightedParameter.Deconstruct(out item, out item2);
				AbstractLevelEvent abstractLevelEvent = item;
				if (abstractLevelEvent.IsGuaranteed())
				{
					hashSet.Add(abstractLevelEvent);
				}
				else
				{
					hashSet2.Add(abstractLevelEvent);
				}
			}
			List<WeightedParameter<AbstractLevelEvent>> list2 = new List<WeightedParameter<AbstractLevelEvent>>();
			foreach (AbstractLevelEvent item4 in hashSet2)
			{
				list2.Add(new WeightedParameter<AbstractLevelEvent>(item4, item4.Weight));
			}
			s_LevelEventRandom = new WeightedRandom<AbstractLevelEvent>(list2);
			s_GuaranteedLevelEvents = hashSet.ToList();
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("[GUARANTEED LEVEL EVENTS]");
			foreach (AbstractLevelEvent s_GuaranteedLevelEvent2 in s_GuaranteedLevelEvents)
			{
				stringBuilder.AppendLine($"\t-1.00% => {s_GuaranteedLevelEvent2.Name,32}");
			}
			stringBuilder.AppendLine("[WEIGHTED LEVEL EVENTS]");
			double weightSum = s_LevelEventRandom.WeightSum;
			foreach (WeightedParameter<AbstractLevelEvent> weightedParameter2 in s_LevelEventRandom.WeightedParameters)
			{
				weightedParameter2.Deconstruct(out item, out item2);
				AbstractLevelEvent abstractLevelEvent2 = item;
				double weightAsPercentage = Util.GetWeightAsPercentage(item2, weightSum);
				stringBuilder.AppendLine($"\t{weightAsPercentage:F2}% => {abstractLevelEvent2.Name,32}, {abstractLevelEvent2.IsAdditive}");
			}
			Plugin.LOGGER.LogInfo((object)("ALL LEVEL EVENTS ARE\n" + stringBuilder));
		}

		public static bool AddToGuaranteed(AbstractLevelEvent instance)
		{
			if (s_GuaranteedLevelEvents.Contains(instance))
			{
				return false;
			}
			s_GuaranteedLevelEvents.Add(instance);
			return true;
		}

		public static bool RemoveFromGuaranteed(AbstractLevelEvent instance)
		{
			return s_GuaranteedLevelEvents.Remove(instance);
		}

		[HarmonyPatch(typeof(RoundManager), "LoadNewLevel")]
		[HarmonyPrefix]
		public static void ModifyLevel(ref SelectableLevel newLevel)
		{
			try
			{
				Plugin.LOGGER.LogInfo((object)"LevelModifier::ModifyLevel(...) Starting");
				HUDManager.Instance.AddTextToChatOnServer("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", -1);
				if (newLevel.sceneName == "CompanyBuilding")
				{
					return;
				}
				GameDefaults.ResetLevel(newLevel);
				Plugin.LOGGER.LogInfo((object)"Disabling Active Events");
				foreach (AbstractLevelEvent s_ActiveEvent in s_ActiveEvents)
				{
					if (s_ActiveEvent == null)
					{
						Plugin.LOGGER.LogWarning((object)"Level Event is null?");
					}
					else
					{
						s_ActiveEvent.OnMatchFinished();
					}
				}
				s_ActiveEvents.Clear();
				s_GuaranteedLevelEvents.ForEach(delegate(AbstractLevelEvent x)
				{
					s_ActiveEvents.Add(x);
				});
				int num = Random.RandomRangeInt(2, 5);
				int num2 = 0;
				AbstractLevelEvent abstractLevelEvent;
				do
				{
					abstractLevelEvent = s_LevelEventRandom.Next();
					if (abstractLevelEvent == null)
					{
						Plugin.LOGGER.LogWarning((object)"Level Event is null...");
						continue;
					}
					bool flag = s_ActiveEvents.Add(abstractLevelEvent);
					if (flag)
					{
						num2++;
					}
					Plugin.LOGGER.LogInfo((object)("[LevelEvent] " + abstractLevelEvent.Name + "," + $" Additive? {abstractLevelEvent.IsAdditive}," + $" Added? {flag}," + $" Exists? {s_ActiveEvents.Contains(abstractLevelEvent)}"));
				}
				while (abstractLevelEvent != null && abstractLevelEvent.IsAdditive && num2 < num);
				Plugin.LOGGER.LogInfo((object)"Finalising Level Events...");
				SortedSet<AbstractLevelEvent> sortedSet = new SortedSet<AbstractLevelEvent>(s_ActiveEvents);
				foreach (AbstractLevelEvent s_ActiveEvent2 in s_ActiveEvents)
				{
					s_ActiveEvent2.Finalise(sortedSet);
				}
				s_ActiveEvents.IntersectWith(sortedSet);
				Plugin.LOGGER.LogInfo((object)$"Applying '{s_ActiveEvents.Count}' Level Events");
				foreach (AbstractLevelEvent s_ActiveEvent3 in s_ActiveEvents)
				{
					string text = (s_ActiveEvent3.Apply(ref newLevel) ? "Success" : "Fail");
					Plugin.LOGGER.LogInfo((object)("Applying Level Event: '" + s_ActiveEvent3.Name + "' -> '" + text + "'"));
				}
				Plugin.LOGGER.LogInfo((object)Util.LevelToString(newLevel));
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("Level Events are: ");
				stringBuilder.Append(GeneralExtensions.Join<AbstractLevelEvent>((IEnumerable<AbstractLevelEvent>)s_ActiveEvents, (Func<AbstractLevelEvent, string>)((AbstractLevelEvent x) => x.ToString()), ", "));
				Plugin.LOGGER.LogInfo((object)stringBuilder.ToString());
				HUDManager.Instance.AddTextToChatOnServer(stringBuilder.ToString(), -1);
				Plugin.LOGGER.LogInfo((object)"LevelModifier::ModifyLevel(...) Finished");
			}
			catch (Exception ex)
			{
				Plugin.LOGGER.LogError((object)("Error Applying Level Events; '" + ex.Message + "'\n" + ex.StackTrace));
			}
		}

		public static void PostCurrentModifiersTo(HUDManager current_hud)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("Level Events are: ");
			stringBuilder.Append(GeneralExtensions.Join<AbstractLevelEvent>((IEnumerable<AbstractLevelEvent>)s_ActiveEvents, (Func<AbstractLevelEvent, string>)((AbstractLevelEvent x) => x.ToString()), ", "));
			current_hud.AddTextToChatOnServer(stringBuilder.ToString(), -1);
		}
	}
	public static class Util
	{
		public static AnimationCurve ZeroCurve()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			return new AnimationCurve((Keyframe[])(object)new Keyframe[2]
			{
				new Keyframe(0f, 0f),
				new Keyframe(1f, 0f)
			});
		}

		public static AnimationCurve ModerateCurve()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			return new AnimationCurve((Keyframe[])(object)new Keyframe[2]
			{
				new Keyframe(0f, 10f),
				new Keyframe(1f, 100f)
			});
		}

		public static AnimationCurve MaxCurve()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			return new AnimationCurve((Keyframe[])(object)new Keyframe[2]
			{
				new Keyframe(0f, 999f),
				new Keyframe(1f, 999f)
			});
		}

		public static AnimationCurve CloneCurve(AnimationCurve curve)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			return new AnimationCurve(((IEnumerable<Keyframe>)curve.GetKeys()).Select((Func<Keyframe, Keyframe>)((Keyframe x) => new Keyframe(((Keyframe)(ref x)).time, ((Keyframe)(ref x)).value))).ToArray());
		}

		public static AnimationCurve CloneCurveAction(AnimationCurve curve, Func<float, float, Keyframe> action)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			return new AnimationCurve((from x in curve.GetKeys()
				select action(((Keyframe)(ref x)).time, ((Keyframe)(ref x)).value)).ToArray());
		}

		public static List<Enemy> CloneEnemies(List<SpawnableEnemyWithRarity> xs)
		{
			return xs.Select((SpawnableEnemyWithRarity x) => new Enemy(x)).ToList();
		}

		public static List<MapObject> CloneMapObjects(IEnumerable<SpawnableMapObject> xs)
		{
			return xs.Select((SpawnableMapObject x) => new MapObject(x)).ToList();
		}

		public static SpawnableMapObject FindMapObject<T>(SelectableLevel level)
		{
			return ((IEnumerable<SpawnableMapObject>)level.spawnableMapObjects).FirstOrDefault((Func<SpawnableMapObject, bool>)delegate(SpawnableMapObject x)
			{
				if (x == null)
				{
					return false;
				}
				return !((Object)(object)x.prefabToSpawn == (Object)null) && x.prefabToSpawn.GetComponentInChildren<T>() != null;
			});
		}

		public static SpawnableMapObject FindMapObject<T>()
		{
			return StartOfRound.Instance.levels.SelectMany((SelectableLevel x) => x.spawnableMapObjects).FirstOrDefault((Func<SpawnableMapObject, bool>)((SpawnableMapObject x) => x.prefabToSpawn.GetComponentInChildren<T>() != null));
		}

		public static SpawnableEnemyWithRarity FindInsideEnemy<T>(SelectableLevel level)
		{
			SpawnableEnemyWithRarity? obj = ((IEnumerable<SpawnableEnemyWithRarity>)level.Enemies).FirstOrDefault((Func<SpawnableEnemyWithRarity, bool>)((SpawnableEnemyWithRarity x) => x.enemyType.enemyPrefab.GetComponentInChildren<T>() != null));
			if (obj == null)
			{
				Plugin.LOGGER.LogInfo((object)("Could not find enemy in level '" + level.sceneName + "'"));
			}
			return obj;
		}

		public static SpawnableEnemyWithRarity FindInsideEnemy<T>()
		{
			return StartOfRound.Instance.levels.SelectMany((SelectableLevel x) => x.Enemies).FirstOrDefault((Func<SpawnableEnemyWithRarity, bool>)((SpawnableEnemyWithRarity x) => x.enemyType.enemyPrefab.GetComponentInChildren<T>() != null));
		}

		public static AnimationCurve CloneCurveScaled(AnimationCurve curve, float scalar, Func<float, float> clamping_fn = null)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			if (clamping_fn == null)
			{
				clamping_fn = Mathf.Abs;
			}
			return new AnimationCurve(((IEnumerable<Keyframe>)curve.GetKeys()).Select((Func<Keyframe, Keyframe>)((Keyframe x) => new Keyframe(((Keyframe)(ref x)).time, clamping_fn(((Keyframe)(ref x)).value * scalar)))).ToArray());
		}

		public static string CurveToString(AnimationCurve curve)
		{
			return GeneralExtensions.Join<Keyframe>((IEnumerable<Keyframe>)curve.GetKeys(), (Func<Keyframe, string>)((Keyframe x) => $"( {((Keyframe)(ref x)).time,5:F2}, {((Keyframe)(ref x)).value,5:F2} )"), ", ");
		}

		public static string LevelToString(SelectableLevel level)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("[Level :: '" + level.sceneName + "']");
			stringBuilder.AppendLine("\tScrap Count: " + level.minScrap + ", " + level.maxScrap);
			stringBuilder.AppendLine("\tScrap Value: " + level.minTotalScrapValue + ", " + level.maxTotalScrapValue);
			stringBuilder.AppendLine("\t[SCRAP] (Worth, MinValue, MaxValue, Weight, IsTwoHanded)\n");
			stringBuilder.AppendLine(GeneralExtensions.Join<SpawnableItemWithRarity>((IEnumerable<SpawnableItemWithRarity>)level.spawnableScrap, (Func<SpawnableItemWithRarity, string>)delegate(SpawnableItemWithRarity x)
			{
				Item spawnableItem = x.spawnableItem;
				return string.Format("\t{0,32} => {1,4},", "'" + spawnableItem.itemName + "'", spawnableItem.creditsWorth) + $" {spawnableItem.minValue,4} <= V <= {spawnableItem.maxValue,4}," + $" {spawnableItem.weight,5}, {spawnableItem.twoHanded,5}";
			}, ",\n"));
			stringBuilder.AppendLine("\tEnemy Power (Inside) : " + level.maxEnemyPowerCount);
			stringBuilder.AppendLine("\tEnemy Power (Outside): " + level.maxOutsideEnemyPowerCount);
			stringBuilder.AppendLine("\tEnemy Power (Daytime): " + level.maxDaytimeEnemyPowerCount);
			stringBuilder.AppendLine("\tSpawn Curve (Inside): " + CurveToString(level.enemySpawnChanceThroughoutDay));
			stringBuilder.AppendLine("\tSpawn Curve (Outside): " + CurveToString(level.outsideEnemySpawnChanceThroughDay));
			stringBuilder.AppendLine("\tSpawn Curve (Daytime): " + CurveToString(level.daytimeEnemySpawnChanceThroughDay));
			stringBuilder.AppendLine("\n\t[INSIDE ENEMIES] (Rarity, MaxCount, PowerLevel, SpawnCurve)");
			foreach (SpawnableEnemyWithRarity enemy in level.Enemies)
			{
				EnemyType enemyType = enemy.enemyType;
				stringBuilder.AppendLine($"\t\t{enemyType.enemyName,16} => {enemy.rarity,3}, {enemyType.MaxCount,3}, {enemyType.PowerLevel,3}, {CurveToString(enemyType.probabilityCurve)}");
			}
			stringBuilder.AppendLine("\n\t[OUTSIDE ENEMIES] (Rarity, MaxCount, PowerLevel, SpawnCurve)");
			foreach (SpawnableEnemyWithRarity outsideEnemy in level.OutsideEnemies)
			{
				EnemyType enemyType2 = outsideEnemy.enemyType;
				stringBuilder.AppendLine($"\t\t{enemyType2.enemyName,16} => {outsideEnemy.rarity}, {enemyType2.MaxCount}, {enemyType2.PowerLevel}, {CurveToString(enemyType2.probabilityCurve)}");
			}
			stringBuilder.AppendLine("\n\t[DAYTIME ENEMIES] (Rarity, MaxCount, PowerLevel, SpawnCurve)");
			foreach (SpawnableEnemyWithRarity daytimeEnemy in level.DaytimeEnemies)
			{
				EnemyType enemyType3 = daytimeEnemy.enemyType;
				stringBuilder.AppendLine($"\t\t{enemyType3.enemyName,16} => {daytimeEnemy.rarity}, {enemyType3.MaxCount}, {enemyType3.PowerLevel}, {CurveToString(enemyType3.probabilityCurve)}");
			}
			stringBuilder.AppendLine("\n\t[MAP OBJECTS] (SpawnCurve, AwayFromWall)");
			SpawnableMapObject[] spawnableMapObjects = level.spawnableMapObjects;
			foreach (SpawnableMapObject val in spawnableMapObjects)
			{
				stringBuilder.AppendLine($"\t\t{((Object)val.prefabToSpawn).name,16} => {CurveToString(val.numberToSpawn)}, {val.spawnFacingAwayFromWall}");
			}
			stringBuilder.AppendLine("\n\t[OUTSIDE MAP OBJECTS]");
			SpawnableOutsideObjectWithRarity[] spawnableOutsideObjects = level.spawnableOutsideObjects;
			foreach (SpawnableOutsideObjectWithRarity val2 in spawnableOutsideObjects)
			{
				SpawnableOutsideObject spawnableObject = val2.spawnableObject;
				stringBuilder.AppendLine($"\t\t{((Object)spawnableObject.prefabToSpawn).name,16} => {CurveToString(val2.randomAmount)}, {spawnableObject.spawnFacingAwayFromWall}");
			}
			return stringBuilder.ToString();
		}

		public static double GetWeightAsPercentage(double w, double sum)
		{
			if (!(w < 0.0))
			{
				return w / sum * 100.0;
			}
			return -1.0;
		}

		public static SpawnableEnemyWithRarity FindOutsideEnemy<T>(SelectableLevel level)
		{
			SpawnableEnemyWithRarity? obj = ((IEnumerable<SpawnableEnemyWithRarity>)level.OutsideEnemies).FirstOrDefault((Func<SpawnableEnemyWithRarity, bool>)((SpawnableEnemyWithRarity x) => x.enemyType.enemyPrefab.GetComponentInChildren<T>() != null));
			if (obj == null)
			{
				Plugin.LOGGER.LogInfo((object)("Could not find outside enemy in level '" + level.sceneName + "'"));
			}
			return obj;
		}

		public static SpawnableEnemyWithRarity FindOutsideEnemy<T>()
		{
			return StartOfRound.Instance.levels.SelectMany((SelectableLevel x) => x.OutsideEnemies).FirstOrDefault((Func<SpawnableEnemyWithRarity, bool>)((SpawnableEnemyWithRarity x) => x.enemyType.enemyPrefab.GetComponentInChildren<T>() != null));
		}

		public static bool EnemyIs<T>(SpawnableEnemyWithRarity obj)
		{
			if (obj == null)
			{
				return false;
			}
			if ((Object)(object)obj.enemyType == (Object)null)
			{
				return false;
			}
			if ((Object)(object)obj.enemyType.enemyPrefab == (Object)null)
			{
				return false;
			}
			return obj.enemyType.enemyPrefab.GetComponentInChildren<T>() != null;
		}

		public static List<SpawnableScrap> CloneScrap(IEnumerable<SpawnableItemWithRarity> scrap)
		{
			return scrap.Select((SpawnableItemWithRarity x) => new SpawnableScrap(x)).ToList();
		}

		public static void ResetEnemyWhere(IEnumerable<SpawnableEnemyWithRarity> xs, Func<SpawnableEnemyWithRarity, bool> predicate)
		{
			CollectionExtensions.Do<SpawnableEnemyWithRarity>(xs.Where(predicate), (Action<SpawnableEnemyWithRarity>)delegate(SpawnableEnemyWithRarity x)
			{
				x.rarity = 0;
				x.enemyType.MaxCount = 0;
				x.enemyType.probabilityCurve = ZeroCurve();
			});
		}

		public static void ZeroEnemy(SpawnableEnemyWithRarity enemy)
		{
			enemy.rarity = 0;
			enemy.enemyType.MaxCount = 0;
			enemy.enemyType.probabilityCurve = ZeroCurve();
		}

		public static SpawnableEnemyWithRarity RandomInsideEnemy(SelectableLevel level)
		{
			int index = Random.RandomRangeInt(0, level.Enemies.Count);
			return level.Enemies[index];
		}

		public static SpawnableEnemyWithRarity RandomOutsideEnemy(SelectableLevel level)
		{
			int index = Random.RandomRangeInt(0, level.Enemies.Count);
			return level.OutsideEnemies[index];
		}
	}
	public static class GameDefaults
	{
		private static bool HasInitialised = false;

		public static readonly Dictionary<string, Level> s_AllLevels = new Dictionary<string, Level>();

		public static readonly Dictionary<string, Enemy> s_AllInsideEnemies = new Dictionary<string, Enemy>();

		public static readonly Dictionary<string, Enemy> s_AllOutsideEnemies = new Dictionary<string, Enemy>();

		public static readonly Dictionary<string, Enemy> s_AllDaytimeEnemies = new Dictionary<string, Enemy>();

		public static readonly HashSet<MapObject> s_AllMapObjects = new HashSet<MapObject>();

		public static bool ResetLevel(SelectableLevel level)
		{
			if (!s_AllLevels.TryGetValue(level.sceneName, out var value))
			{
				Plugin.LOGGER.LogWarning((object)("Level " + level.sceneName + " does not exist in mapping."));
				return false;
			}
			value.Reset(level);
			return true;
		}

		[HarmonyPatch(typeof(StartOfRound), "StartGame")]
		[HarmonyPrefix]
		public static void InitialiseDefaults(StartOfRound __instance)
		{
			Plugin.LOGGER.LogInfo((object)"GameDefaults::InitialiseDefaults(...) Starting");
			if (HasInitialised)
			{
				return;
			}
			SelectableLevel[] levels = __instance.levels;
			foreach (SelectableLevel val in levels)
			{
				Plugin.LOGGER.LogInfo((object)("Storing Defaults For: '" + val.sceneName + "'"));
				Level level = new Level(val);
				s_AllLevels.TryAdd(level.SceneName, level);
				level.InsideEnemies.ForEach(delegate(Enemy x)
				{
					s_AllInsideEnemies.TryAdd(x.Name, x);
				});
				level.OutsideEnemies.ForEach(delegate(Enemy x)
				{
					s_AllOutsideEnemies.TryAdd(x.Name, x);
				});
				level.DaytimeEnemies.ForEach(delegate(Enemy x)
				{
					s_AllDaytimeEnemies.TryAdd(x.Name, x);
				});
				level.MapObjects.ForEach(delegate(MapObject x)
				{
					s_AllMapObjects.Add(x);
				});
			}
			levels = __instance.levels;
			foreach (SelectableLevel val2 in levels)
			{
				foreach (Enemy enemy in s_AllInsideEnemies.Select((KeyValuePair<string, Enemy> x) => x.Value))
				{
					if (val2.Enemies.All((SpawnableEnemyWithRarity x) => x.enemyType.enemyName != enemy.Name))
					{
						val2.Enemies.Add(enemy.Impl);
					}
				}
			}
			levels = __instance.levels;
			foreach (SelectableLevel val3 in levels)
			{
				List<SpawnableMapObject> list = new List<SpawnableMapObject>(val3.spawnableMapObjects);
				foreach (MapObject obj in s_AllMapObjects)
				{
					if (list.All((SpawnableMapObject x) => ((Object)x.prefabToSpawn).name != ((Object)obj.Prefab).name))
					{
						list.Add(obj.Impl);
					}
				}
				val3.spawnableMapObjects = list.ToArray();
			}
			levels = __instance.levels;
			for (int i = 0; i < levels.Length; i++)
			{
				foreach (SpawnableItemWithRarity item in levels[i].spawnableScrap)
				{
					Item spawnableItem = item.spawnableItem;
					item.spawnableItem.maxValue = Math.Clamp(spawnableItem.maxValue * 10, spawnableItem.minValue, 99999);
				}
			}
			levels = __instance.levels;
			foreach (SelectableLevel level2 in levels)
			{
				Plugin.LOGGER.LogInfo((object)Util.LevelToString(level2));
			}
			HasInitialised = true;
			Plugin.LOGGER.LogInfo((object)"GameDefaults::InitialiseDefaults() Finished");
		}
	}
	public abstract class AbstractLevelEvent : IComparable<AbstractLevelEvent>
	{
		private const double BASE_WEIGHT = 100.0;

		private const double WEIGHT_VERY_HIGH = 100.0;

		public const double WEIGHT_HIGH = 66.66666666666667;

		public const double WEIGHT_NORMAL = 50.0;

		public const double WEIGHT_MEDIUM = 40.0;

		public const double WEIGHT_LOW = 33.333333333333336;

		public const double WEIGHT_VERY_LOW = 20.0;

		public const double WEIGHT_EXTREMELY_LOW = 12.5;

		public const int ORDERING_LOW = -1;

		public const int ORDERING_HIGH = 1;

		public readonly string Name;

		public readonly double Weight;

		public readonly bool IsAdditive;

		public readonly int Ordering;

		private readonly bool IsNaturalOrdering;

		protected readonly HashSet<string> OrderingTags;

		private static int s_ColourIndex = 0;

		private static readonly string[] s_Colours = new string[19]
		{
			"#66C7F4", "#FF1053", "#A8C256", "#FED766", "#FFFFFF", "#B497D6", "#75F4F4", "#CE1483", "#06D6A0", "#92AFD7",
			"#F283B6", "#97CC04", "#B5FFE9", "#6699CC", "#3BC14A", "#92DCE5", "#E2A0FF", "#C1DF1F", "#D972FF"
		};

		protected AbstractLevelEvent(string name, double weight, bool is_additive, int ordering = -1, bool natural_ordering = true, params string[] ordering_tags)
		{
			Name = name;
			Weight = weight;
			IsAdditive = is_additive;
			Ordering = ordering;
			IsNaturalOrdering = natural_ordering;
			OrderingTags = new HashSet<string>();
			foreach (string item in ordering_tags)
			{
				OrderingTags.Add(item);
			}
		}

		public abstract bool Apply(ref SelectableLevel level);

		public virtual void Finalise(SortedSet<AbstractLevelEvent> events)
		{
		}

		public virtual void OnMatchFinished()
		{
		}

		public bool IsGuaranteed()
		{
			return Weight < 0.0;
		}

		protected bool HasAllOf(params string[] tags)
		{
			return tags.All((string tag) => OrderingTags.Contains(tag));
		}

		protected bool HasOneOf(params string[] tags)
		{
			return tags.Any((string x) => OrderingTags.Contains(x));
		}

		protected static string NextColour()
		{
			string result = s_Colours[s_ColourIndex];
			s_ColourIndex = (s_ColourIndex + 1) % s_Colours.Length;
			return result;
		}

		public override string ToString()
		{
			return "<color=" + NextColour() + ">" + Name + "</color>";
		}

		public virtual int CompareTo(AbstractLevelEvent other)
		{
			if (Name == other.Name)
			{
				return 0;
			}
			if (!other.IsNaturalOrdering)
			{
				return other.CompareTo(this) * -1;
			}
			return Ordering;
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return false;
			}
			if (obj is AbstractLevelEvent abstractLevelEvent)
			{
				return abstractLevelEvent.Name == Name;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return Name.GetHashCode();
		}
	}
	public class Enemy
	{
		public readonly string Name;

		public readonly SpawnableEnemyWithRarity Impl;

		public readonly GameObject Prefab;

		public readonly EnemyType Type;

		public readonly int Rarity;

		public readonly int MaxCount;

		public readonly AnimationCurve SpawnCurve;

		public readonly AnimationCurve FalloffCurve;

		public readonly bool IsDaytimeEnemy;

		public readonly bool IsOutsideEnemy;

		public Enemy(SpawnableEnemyWithRarity enemy)
		{
			Name = enemy.enemyType.enemyName;
			Impl = enemy;
			Prefab = enemy.enemyType.enemyPrefab;
			Type = enemy.enemyType;
			Rarity = enemy.rarity;
			MaxCount = enemy.enemyType.MaxCount;
			SpawnCurve = Util.CloneCurve(enemy.enemyType.probabilityCurve);
			FalloffCurve = Util.CloneCurve(enemy.enemyType.numberSpawnedFalloff);
			IsDaytimeEnemy = enemy.enemyType.isDaytimeEnemy;
			IsOutsideEnemy = enemy.enemyType.isOutsideEnemy;
		}

		public void Reset(SpawnableEnemyWithRarity enemy)
		{
			enemy.rarity = Rarity;
			enemy.enemyType.MaxCount = MaxCount;
			enemy.enemyType.probabilityCurve = Util.CloneCurve(SpawnCurve);
			enemy.enemyType.numberSpawnedFalloff = Util.CloneCurve(FalloffCurve);
			enemy.enemyType.isDaytimeEnemy = IsDaytimeEnemy;
			enemy.enemyType.isOutsideEnemy = IsOutsideEnemy;
		}

		public override int GetHashCode()
		{
			return Name.GetHashCode();
		}
	}
	public class MapObject
	{
		public readonly GameObject Prefab;

		public readonly AnimationCurve SpawnCurve;

		public readonly SpawnableMapObject Impl;

		public MapObject(SpawnableMapObject obj)
		{
			Prefab = obj.prefabToSpawn;
			SpawnCurve = Util.CloneCurve(obj.numberToSpawn);
			Impl = obj;
		}

		public void Reset(SpawnableMapObject obj)
		{
			obj.numberToSpawn = Util.CloneCurve(SpawnCurve);
		}

		public override int GetHashCode()
		{
			return ((object)Impl).GetHashCode();
		}
	}
	public class SpawnableScrap
	{
		public readonly Item Impl;

		public readonly int Rarity;

		public readonly bool IsScrap;

		public readonly int CreditsWorth;

		public readonly int HighestSalePercentage;

		public readonly int MaxValue;

		public readonly int MinValue;

		public string ItemName => Impl.itemName;

		public SpawnableScrap(SpawnableItemWithRarity item)
		{
			Impl = item.spawnableItem;
			Rarity = item.rarity;
			IsScrap = item.spawnableItem.isScrap;
			CreditsWorth = item.spawnableItem.creditsWorth;
			HighestSalePercentage = item.spawnableItem.highestSalePercentage;
			MaxValue = item.spawnableItem.maxValue;
			MinValue = item.spawnableItem.minValue;
		}

		public void Reset(SpawnableItemWithRarity item)
		{
			item.spawnableItem = Impl;
			item.rarity = Rarity;
			item.spawnableItem.isScrap = IsScrap;
			item.spawnableItem.creditsWorth = CreditsWorth;
			item.spawnableItem.highestSalePercentage = HighestSalePercentage;
			item.spawnableItem.maxValue = MaxValue;
			item.spawnableItem.minValue = MinValue;
		}

		public override int GetHashCode()
		{
			return ((object)Impl).GetHashCode();
		}

		public override string ToString()
		{
			return $"{ItemName,32}, {Rarity,3}," + $" [{MinValue,3} .. {MaxValue,3}], {CreditsWorth,3}";
		}
	}
	public class Level
	{
		public readonly string SceneName;

		public readonly SelectableLevel Impl;

		public readonly int MinScrap;

		public readonly int MaxScrap;

		public readonly int MinScrapValue;

		public readonly int MaxScrapValue;

		public readonly int MaxEnemyPowerCount;

		public readonly int MaxOutsideEnemyPowerCount;

		public readonly int MaxDaytimeEnemyPowerCount;

		public readonly AnimationCurve EnemySpawnChanceThroughoutDay;

		public readonly AnimationCurve OutsideEnemySpawnChanceThroughDay;

		public readonly AnimationCurve DaytimeEnemySpawnChanceThroughDay;

		public readonly float SpawnProbabilityRange;

		public readonly float DaytimeEnemiesProbabilityRange;

		public readonly List<Enemy> InsideEnemies;

		public readonly List<Enemy> OutsideEnemies;

		public readonly List<Enemy> DaytimeEnemies;

		public readonly List<MapObject> MapObjects;

		public readonly List<SpawnableScrap> Scrap;

		public Level(SelectableLevel level)
		{
			SceneName = level.sceneName;
			Impl = level;
			MinScrap = level.minScrap;
			MaxScrap = level.maxScrap;
			MinScrapValue = level.minTotalScrapValue;
			MaxScrapValue = level.maxTotalScrapValue;
			MaxEnemyPowerCount = level.maxEnemyPowerCount;
			MaxOutsideEnemyPowerCount = level.maxOutsideEnemyPowerCount;
			MaxDaytimeEnemyPowerCount = level.maxDaytimeEnemyPowerCount;
			EnemySpawnChanceThroughoutDay = Util.CloneCurve(level.enemySpawnChanceThroughoutDay);
			OutsideEnemySpawnChanceThroughDay = Util.CloneCurve(level.outsideEnemySpawnChanceThroughDay);
			DaytimeEnemySpawnChanceThroughDay = Util.CloneCurve(level.daytimeEnemySpawnChanceThroughDay);
			SpawnProbabilityRange = level.spawnProbabilityRange;
			DaytimeEnemiesProbabilityRange = level.daytimeEnemiesProbabilityRange;
			InsideEnemies = Util.CloneEnemies(level.Enemies);
			OutsideEnemies = Util.CloneEnemies(level.OutsideEnemies);
			DaytimeEnemies = Util.CloneEnemies(level.DaytimeEnemies);
			MapObjects = Util.CloneMapObjects(level.spawnableMapObjects);
			Scrap = Util.CloneScrap(level.spawnableScrap);
		}

		public void Reset(SelectableLevel level)
		{
			level.minScrap = MinScrap;
			level.maxScrap = MaxScrap;
			level.minTotalScrapValue = MinScrapValue;
			level.maxTotalScrapValue = MaxScrapValue;
			level.maxEnemyPowerCount = MaxEnemyPowerCount;
			level.maxOutsideEnemyPowerCount = MaxOutsideEnemyPowerCount;
			level.maxDaytimeEnemyPowerCount = MaxDaytimeEnemyPowerCount;
			level.enemySpawnChanceThroughoutDay = Util.CloneCurve(EnemySpawnChanceThroughoutDay);
			level.outsideEnemySpawnChanceThroughDay = Util.CloneCurve(OutsideEnemySpawnChanceThroughDay);
			level.daytimeEnemySpawnChanceThroughDay = Util.CloneCurve(DaytimeEnemySpawnChanceThroughDay);
			level.spawnProbabilityRange = SpawnProbabilityRange;
			level.daytimeEnemiesProbabilityRange = DaytimeEnemiesProbabilityRange;
			level.Enemies.ForEach(delegate(SpawnableEnemyWithRarity a)
			{
				ResetEnemyOrZeroOut(a, InsideEnemies);
			});
			level.DaytimeEnemies.ForEach(delegate(SpawnableEnemyWithRarity a)
			{
				ResetEnemyOrZeroOut(a, DaytimeEnemies);
			});
			level.OutsideEnemies.ForEach(delegate(SpawnableEnemyWithRarity a)
			{
				ResetEnemyOrZeroOut(a, OutsideEnemies);
			});
			SpawnableMapObject[] spawnableMapObjects = level.spawnableMapObjects;
			foreach (SpawnableMapObject obj in spawnableMapObjects)
			{
				MapObject mapObject = MapObjects.FirstOrDefault((MapObject x) => ((Object)obj.prefabToSpawn).name == ((Object)x.Prefab).name);
				if (mapObject == null)
				{
					obj.numberToSpawn = Util.ZeroCurve();
				}
				else
				{
					mapObject.Reset(obj);
				}
			}
			foreach (SpawnableItemWithRarity scrap in level.spawnableScrap)
			{
				Scrap.FirstOrDefault((SpawnableScrap x) => scrap.spawnableItem.itemName == x.ItemName)?.Reset(scrap);
			}
			static void ResetEnemyOrZeroOut(SpawnableEnemyWithRarity enemy, IEnumerable<Enemy> enemies)
			{
				Enemy enemy2 = enemies.FirstOrDefault((Enemy x) => x.Name == enemy.enemyType.enemyName);
				if (enemy2 == null)
				{
					enemy.rarity = 0;
					enemy.enemyType.MaxCount = 0;