Decompiled source of ChaosCompany v1.3.6

ChaosCompany.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ChaosCompany.Scripts.Abstracts;
using ChaosCompany.Scripts.Components;
using ChaosCompany.Scripts.DataStructures;
using ChaosCompany.Scripts.Entities;
using ChaosCompany.Scripts.Items;
using ChaosCompany.Scripts.Managers;
using ChaosCompany.Scripts.Patches;
using Dissonance.Integrations.Unity_NFGO;
using GameNetcodeStuff;
using HarmonyLib;
using KaimiraGames;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;

[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("ChaosCompany")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("It's unpredictable chaos can you survive?")]
[assembly: AssemblyFileVersion("1.3.6.0")]
[assembly: AssemblyInformationalVersion("1.3.6+79503519dc0202ed16d18bd5a20f7e5dec7d4abd")]
[assembly: AssemblyProduct("ChaosCompany")]
[assembly: AssemblyTitle("ChaosCompany")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.6.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 KaimiraGames
{
	public class WeightedList<T> : IEnumerable<T>, IEnumerable
	{
		private readonly List<T> _list = new List<T>();

		private readonly List<int> _weights = new List<int>();

		private readonly List<int> _probabilities = new List<int>();

		private readonly List<int> _alias = new List<int>();

		private readonly Random _rand;

		private int _totalWeight;

		private bool _areAllProbabilitiesIdentical;

		private int _minWeight;

		private int _maxWeight;

		public WeightErrorHandlingType BadWeightErrorHandling { get; set; }

		public int TotalWeight => _totalWeight;

		public int MinWeight => _minWeight;

		public int MaxWeight => _maxWeight;

		public IReadOnlyList<T> Items => _list.AsReadOnly();

		public T this[int index] => _list[index];

		public int Count => _list.Count;

		public WeightedList(Random? rand = null)
		{
			_rand = rand ?? new Random();
		}

		public WeightedList(ICollection<WeightedListItem<T>> listItems, Random? rand = null)
		{
			_rand = rand ?? new Random();
			foreach (WeightedListItem<T> listItem in listItems)
			{
				_list.Add(listItem._item);
				_weights.Add(listItem._weight);
			}
			Recalculate();
		}

		public T? Next()
		{
			if (Count == 0)
			{
				return default(T);
			}
			int index = _rand.Next(Count);
			if (_areAllProbabilitiesIdentical)
			{
				return _list[index];
			}
			int num = _rand.Next(_totalWeight);
			if (num >= _probabilities[index])
			{
				return _list[_alias[index]];
			}
			return _list[index];
		}

		public void AddWeightToAll(int weight)
		{
			if (weight + _minWeight <= 0 && BadWeightErrorHandling == WeightErrorHandlingType.ThrowExceptionOnAdd)
			{
				throw new ArgumentException($"Subtracting {-1 * weight} from all items would set weight to non-positive for at least one element.");
			}
			for (int i = 0; i < Count; i++)
			{
				_weights[i] = FixWeight(_weights[i] + weight);
			}
			Recalculate();
		}

		public void SubtractWeightFromAll(int weight)
		{
			AddWeightToAll(weight * -1);
		}

		public void SetWeightOfAll(int weight)
		{
			if (weight <= 0 && BadWeightErrorHandling == WeightErrorHandlingType.ThrowExceptionOnAdd)
			{
				throw new ArgumentException("Weight cannot be non-positive.");
			}
			for (int i = 0; i < Count; i++)
			{
				_weights[i] = FixWeight(weight);
			}
			Recalculate();
		}

		public IEnumerator<T> GetEnumerator()
		{
			return _list.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return _list.GetEnumerator();
		}

		public void Add(T item, int weight)
		{
			_list.Add(item);
			_weights.Add(FixWeight(weight));
			Recalculate();
		}

		public void Add(ICollection<WeightedListItem<T>> listItems)
		{
			foreach (WeightedListItem<T> listItem in listItems)
			{
				_list.Add(listItem._item);
				_weights.Add(FixWeight(listItem._weight));
			}
			Recalculate();
		}

		public void Clear()
		{
			_list.Clear();
			_weights.Clear();
			Recalculate();
		}

		public bool Contains(T item)
		{
			return _list.Contains(item);
		}

		public int IndexOf(T item)
		{
			return _list.IndexOf(item);
		}

		public void Insert(int index, T item, int weight)
		{
			_list.Insert(index, item);
			_weights.Insert(index, FixWeight(weight));
			Recalculate();
		}

		public void Remove(T item)
		{
			int index = IndexOf(item);
			RemoveAt(index);
			Recalculate();
		}

		public void RemoveAt(int index)
		{
			_list.RemoveAt(index);
			_weights.RemoveAt(index);
			Recalculate();
		}

		public void SetWeight(T item, int newWeight)
		{
			SetWeightAtIndex(IndexOf(item), FixWeight(newWeight));
		}

		public int GetWeightOf(T item)
		{
			return GetWeightAtIndex(IndexOf(item));
		}

		public void SetWeightAtIndex(int index, int newWeight)
		{
			_weights[index] = FixWeight(newWeight);
			Recalculate();
		}

		public int GetWeightAtIndex(int index)
		{
			return _weights[index];
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("WeightedList<");
			stringBuilder.Append(typeof(T).Name);
			stringBuilder.Append(">: TotalWeight:");
			stringBuilder.Append(TotalWeight);
			stringBuilder.Append(", Min:");
			stringBuilder.Append(_minWeight);
			stringBuilder.Append(", Max:");
			stringBuilder.Append(_maxWeight);
			stringBuilder.Append(", Count:");
			stringBuilder.Append(Count);
			stringBuilder.Append(", {");
			for (int i = 0; i < _list.Count; i++)
			{
				T val = _list[i];
				stringBuilder.Append((val != null) ? val.ToString() : null);
				stringBuilder.Append(":");
				stringBuilder.Append(_weights[i].ToString());
				if (i < _list.Count - 1)
				{
					stringBuilder.Append(", ");
				}
			}
			stringBuilder.Append("}");
			return stringBuilder.ToString();
		}

		private void Recalculate()
		{
			_totalWeight = 0;
			_areAllProbabilitiesIdentical = false;
			_minWeight = 0;
			_maxWeight = 0;
			bool flag = true;
			_alias.Clear();
			_probabilities.Clear();
			List<int> list = new List<int>(Count);
			List<int> list2 = new List<int>(Count);
			List<int> list3 = new List<int>(Count);
			foreach (int weight in _weights)
			{
				if (flag)
				{
					_minWeight = (_maxWeight = weight);
					flag = false;
				}
				_minWeight = ((weight < _minWeight) ? weight : _minWeight);
				_maxWeight = ((_maxWeight < weight) ? weight : _maxWeight);
				_totalWeight += weight;
				list.Add(weight * Count);
				_alias.Add(0);
				_probabilities.Add(0);
			}
			if (_minWeight == _maxWeight)
			{
				_areAllProbabilitiesIdentical = true;
				return;
			}
			for (int i = 0; i < Count; i++)
			{
				if (list[i] < _totalWeight)
				{
					list2.Add(i);
				}
				else
				{
					list3.Add(i);
				}
			}
			while (list2.Count > 0 && list3.Count > 0)
			{
				int index = list2[list2.Count - 1];
				list2.RemoveAt(list2.Count - 1);
				int num = list3[list3.Count - 1];
				list3.RemoveAt(list3.Count - 1);
				_probabilities[index] = list[index];
				_alias[index] = num;
				int num3 = (list[num] = list[num] + list[index] - _totalWeight);
				if (num3 < _totalWeight)
				{
					list2.Add(num);
				}
				else
				{
					list3.Add(num);
				}
			}
			while (list3.Count > 0)
			{
				int index2 = list3[list3.Count - 1];
				list3.RemoveAt(list3.Count - 1);
				_probabilities[index2] = _totalWeight;
			}
		}

		internal static int FixWeightSetToOne(int weight)
		{
			if (weight > 0)
			{
				return weight;
			}
			return 1;
		}

		internal static int FixWeightExceptionOnAdd(int weight)
		{
			if (weight > 0)
			{
				return weight;
			}
			throw new ArgumentException("Weight cannot be non-positive");
		}

		private int FixWeight(int weight)
		{
			if (BadWeightErrorHandling != WeightErrorHandlingType.ThrowExceptionOnAdd)
			{
				return FixWeightSetToOne(weight);
			}
			return FixWeightExceptionOnAdd(weight);
		}
	}
	public readonly struct WeightedListItem<T>
	{
		internal readonly T _item;

		internal readonly int _weight;

		public WeightedListItem(T item, int weight)
		{
			_item = item;
			_weight = weight;
		}
	}
	public enum WeightErrorHandlingType
	{
		SetWeightToOne,
		ThrowExceptionOnAdd
	}
}
namespace ChaosCompany
{
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "ChaosCompany";

		public const string PLUGIN_NAME = "ChaosCompany";

		public const string PLUGIN_VERSION = "1.3.6";
	}
}
namespace ChaosCompany.Scripts
{
	[BepInPlugin("ChaosCompany", "ChaosCompany", "1.3.6")]
	public class Plugin : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("ChaosCompany");

		public static ManualLogSource Logger { get; private set; } = Logger.CreateLogSource("ChaosCompany");


		public static int MaxChaoticEnemySpawn { get; private set; }

		public static int MaxMoveEnemySpawn { get; private set; }

		public static int SpawnEnemyInterval { get; private set; }

		public static int MinEnemySpawnNumber { get; private set; }

		public static int MaxEnemySpawnNumber { get; private set; }

		public static int MinChaoticItemSpawnNumber { get; private set; }

		public static int MaxChaoticItemSpawnNumber { get; private set; }

		public static List<string>? ModSpawnEnemyExclusionList { get; private set; }

		public static int ChanceOfSpawnEnemyOnItem { get; private set; }

		public static List<string>? SpawnEnemyOnItemExclusionListInside { get; private set; }

		public static List<string>? SpawnEnemyOnItemExclusionListOutside { get; private set; }

		public static float MinTimeMultiplier { get; private set; }

		public static float MaxTimeMultiplier { get; private set; }

		public static int MinDayBeforeDeadline { get; private set; }

		public static int MaxDayBeforeDeadline { get; private set; }

		public static int CompanyMonsterTimesHeardNoiseBeforeWarning { get; private set; }

		public static int CompanyMonsterTimesHeardNoiseBeforeAttack { get; private set; }

		public static float CompanyMonsterConsecutiveNoiseDelay { get; private set; }

		public static int MinPowerOutageDuration { get; set; }

		public static int MaxPowerOutageDuration { get; set; }

		public static float ChaoticEnemySwitchTime { get; private set; }

		public static List<string>? ChaoticEnemySwitchExclusionList { get; private set; }

		public static List<string>? MoveEnemySpawnExclusionList { get; private set; }

		public static int MinChaoticItemPrice { get; private set; }

		public static int MaxChaoticItemPrice { get; private set; }

		public static float ChaoticItemSwitchPriceTime { get; private set; }

		public static int ChanceOfSameDayEnemy { get; private set; }

		public static List<string>? SpawnEnemyNearPlayerExclusionListInside { get; private set; }

		public static List<string>? SpawnEnemyNearPlayerExclusionListOutside { get; private set; }

		private void Awake()
		{
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Expected O, but got Unknown
			//IL_05f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fc: Expected O, but got Unknown
			MaxChaoticEnemySpawn = ((BaseUnityPlugin)this).Config.Bind<int>("Spawning", "Max chaotic enemy spawn", 2, "The maximum number of chaotic enemy that can spawn").Value;
			MaxMoveEnemySpawn = ((BaseUnityPlugin)this).Config.Bind<int>("Spawning", "Max move enemy spawn", 2, "The maximum number of move enemy that can spawn").Value;
			SpawnEnemyInterval = ((BaseUnityPlugin)this).Config.Bind<int>("Spawning", "Spawn enemy interval", 180, "The interval time for spawn behaviour from chaos company to spawn stuff in seconds").Value;
			MinEnemySpawnNumber = ((BaseUnityPlugin)this).Config.Bind<int>("Spawning", "Min enemy spawn number", 2, "Minimum number of enemy the mod can spawn, the final result will be random between the minimum and the maximum").Value;
			MaxEnemySpawnNumber = ((BaseUnityPlugin)this).Config.Bind<int>("Spawning", "Max enemy spawn number", 4, "Maximum number of enemy the mod can spawn, the final result will be random between the minimum and the maximum").Value;
			MinChaoticItemSpawnNumber = ((BaseUnityPlugin)this).Config.Bind<int>("Spawning", "Min chaotic item spawn number", 2, "Minimum number of chaotic item the mod can spawn, the final result will be random between the minimum and the maximum").Value;
			MaxChaoticItemSpawnNumber = ((BaseUnityPlugin)this).Config.Bind<int>("Spawning", "Max chaotic item spawn number", 5, "Maximum number of chaotic item the mod can spawn, the final result will be random between the minimum and the maximum").Value;
			ModSpawnEnemyExclusionList = (from str in ((BaseUnityPlugin)this).Config.Bind<string>("Spawning", "Mod spawning enemy exclusion list", "None, None, None", "The enemy that is excluded from spawning by the mod no matter what, vanilla spawning are not affected, comma separated").Value.ToLower().Split(',')
				select str.Trim()).ToList();
			ChanceOfSpawnEnemyOnItem = ((BaseUnityPlugin)this).Config.Bind<int>("Spawn Enemy When Grabbing", "Chance", 1, new ConfigDescription("The chance of spawning enemy when grabbing an item inside the facility or outside doesn't work if player is inside the ship", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())).Value;
			SpawnEnemyOnItemExclusionListInside = (from str in ((BaseUnityPlugin)this).Config.Bind<string>("Spawn Enemy When Grabbing", "Inside exclusion", "Masked, Spring, Flowerman, ClaySurgeon, DressedGirl, NutCracker", "The spawn exclusion of a chance of spawning enemy when grabbing an item inside, The name of the enemy is the name in the code and not aliases example instead of Bracken it's FlowerMan and capitalization doesn't matter, and full name also not required, comma separated").Value.ToLower().Split(',')
				select str.Trim()).ToList();
			SpawnEnemyOnItemExclusionListOutside = (from str in ((BaseUnityPlugin)this).Config.Bind<string>("Spawn Enemy When Grabbing", "Outside exclusion", "RedLocust, Mech, Worm, Dog, Double", "The spawn exclusion of a chance of spawning enemy when grabbing an item outside, The name of the enemy is the name in the code and not aliases example, instead of Bracken it's FlowerMan and capitalization doesn't matter, full name also not required, comma separated").Value.ToLower().Split(',')
				select str.Trim()).ToList();
			MinDayBeforeDeadline = ((BaseUnityPlugin)this).Config.Bind<int>("Time", "Min day before deadline", 4, "Minimum value for how many day before the deadline, the final result will be random between the minimum and the maximum").Value;
			MaxDayBeforeDeadline = ((BaseUnityPlugin)this).Config.Bind<int>("Time", "Max day before deadline", 6, "Maximum value for how many day before the deadline, the final result will be random between the minimum and the maximum").Value;
			MinTimeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Time", "Min time multiplier", 0.5f, "Minimum value for the time multiplier, the final result will be random between the minimum and the maximum").Value;
			MaxTimeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Time", "Max time multiplier", 1.25f, "Maximum value for the time multiplier, the final result will be random between the minimum and the maximum").Value;
			CompanyMonsterTimesHeardNoiseBeforeWarning = ((BaseUnityPlugin)this).Config.Bind<int>("Company Monster", "Times heard noise before warning", 3, "The company monster noise hearing times before warning, signified by growling and camera shaking").Value;
			CompanyMonsterTimesHeardNoiseBeforeAttack = ((BaseUnityPlugin)this).Config.Bind<int>("Company Monster", "Times heard noise before attack", 6, "The company monster noise hearing times before attacking").Value;
			CompanyMonsterConsecutiveNoiseDelay = ((BaseUnityPlugin)this).Config.Bind<int>("Company Monster", "Consecutive noise delay", 3, "The company monster delay in seconds if it doesn't hear noises with this amount of time it will reset the TimesHeardNoise to 0").Value;
			MinPowerOutageDuration = ((BaseUnityPlugin)this).Config.Bind<int>("Power outage", "Min duration", 30, "The minimum duration for power outage, the final result will be random between the minimum and the maximum").Value;
			MaxPowerOutageDuration = ((BaseUnityPlugin)this).Config.Bind<int>("Power outage", "Max duration", 180, "The maximum duration for power outage, the final result will be random between the minimum and the maximum").Value;
			ChaoticEnemySwitchTime = ((BaseUnityPlugin)this).Config.Bind<int>("Chaotic Enemy", "Chaotic enemy switch timer", 10, "The amount of time before the chaotic enemy switch to another random enemy in seconds").Value;
			ChaoticEnemySwitchExclusionList = (from str in ((BaseUnityPlugin)this).Config.Bind<string>("Chaotic Enemy", "Chaotic enemy switch exclusion", "DocileLocust, CaveDweller, DressGirl, Nutcracker, Spider, double, RedLocust", "The spawn exclusion of chaotic enemy switching choice, The name of the enemy is the name in the code and not aliases example, instead of Bracken it's FlowerMan and capitalization doesn't matter, full name also not required, comma separated").Value.ToLower().Split(',')
				select str.Trim()).ToList();
			MoveEnemySpawnExclusionList = (from str in ((BaseUnityPlugin)this).Config.Bind<string>("Move Enemy", "Move enemy spawn exclusion", "forest, RedLocust, Doublewing, FlowerSnake, DocileLocust, double, Centipede, puffer, CaveDweller", "The spawn exclusion of move enemy, The name of the enemy is the name in the code and not aliases example, instead of Bracken it's FlowerMan and capitalization doesn't matter, full name also not required, comma separated").Value.ToLower().Split(',')
				select str.Trim()).ToList();
			MinChaoticItemPrice = ((BaseUnityPlugin)this).Config.Bind<int>("Chaotic Item", "Min chaotic item price", 10, "The minimum price of the chaotic item, the final result will be random between the minimum and the maximum").Value;
			MaxChaoticItemPrice = ((BaseUnityPlugin)this).Config.Bind<int>("Chaotic Item", "Max chaotic item price", 150, "The maximum price of the chaotic item, the final result will be random between the minimum and the maximum").Value;
			ChaoticItemSwitchPriceTime = ((BaseUnityPlugin)this).Config.Bind<int>("Chaotic Item", "Chaotic item price switch time", 1, "The amount of time before the chaotic item price switch to random price in seconds").Value;
			SpawnEnemyNearPlayerExclusionListInside = (from str in ((BaseUnityPlugin)this).Config.Bind<string>("Spawn Enemy Near Player", "Inside exclusion", "DressGirl", "The spawn exclusion of a chance of spawning enemy near a player inside, The name of the enemy is the name in the code and not aliases example instead of Bracken it's FlowerMan and capitalization doesn't matter, full name also not required, comma separated").Value.ToLower().Split(',')
				select str.Trim()).ToList();
			SpawnEnemyNearPlayerExclusionListOutside = (from str in ((BaseUnityPlugin)this).Config.Bind<string>("Spawn Enemy Near Player", "Outside exclusion", "mech, worm, double", "The spawn exclusion of a chance of spawning enemy near a player outside, The name of the enemy is the name in the code and not aliases example instead of Bracken it's FlowerMan and capitalization doesn't matter, full name also not required, comma separated").Value.ToLower().Split(',')
				select str.Trim()).ToList();
			ChanceOfSameDayEnemy = ((BaseUnityPlugin)this).Config.Bind<int>("Same Day Enemy", "Chance", 20, new ConfigDescription("The chance of inside and outside enemy that spawn being the same", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())).Value;
			Logger.LogInfo((object)"Plugin ChaosCompany is loaded! yeah baby!!!");
			harmony.PatchAll(Assembly.GetExecutingAssembly());
		}
	}
}
namespace ChaosCompany.Scripts.Patches
{
	[HarmonyPatch(typeof(DepositItemsDesk))]
	internal static class DepositItemsDeskPatch
	{
		public static HashSet<float> soundVolumes = new HashSet<float>();

		private static int timesHearingNoise = 0;

		public static Timer consecutiveNoiseDelay = new Timer(Plugin.CompanyMonsterConsecutiveNoiseDelay, oneshot: false);

		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void StartPostfix(DepositItemsDesk __instance)
		{
			if (NetworkManager.Singleton.IsServer)
			{
				GameManager.Timers.Add(consecutiveNoiseDelay);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("SetTimesHeardNoiseServerRpc")]
		private static void SetTimesHeardNoiseServerRpcPostfix(DepositItemsDesk __instance, ref float valueChange)
		{
			if (!NetworkManager.Singleton.IsServer)
			{
				return;
			}
			int num = 0;
			bool flag = false;
			foreach (float soundVolume in soundVolumes)
			{
				if (soundVolume < valueChange)
				{
					num++;
				}
				if (MathF.Abs(soundVolume - valueChange) <= 0.1f)
				{
					flag = true;
				}
			}
			if (flag && num < 1)
			{
				return;
			}
			if (num < 1 || soundVolumes.Count == 0)
			{
				soundVolumes.Add(valueChange);
				return;
			}
			soundVolumes.Add(valueChange);
			consecutiveNoiseDelay.Restart();
			consecutiveNoiseDelay.OnTimeout += delegate
			{
				timesHearingNoise = 0;
				consecutiveNoiseDelay.Stop();
			};
			if (timesHearingNoise + 1 >= Plugin.CompanyMonsterTimesHeardNoiseBeforeWarning * 2)
			{
				__instance.MakeWarningNoiseClientRpc();
			}
			if (timesHearingNoise + 1 >= Plugin.CompanyMonsterTimesHeardNoiseBeforeAttack * 2)
			{
				__instance.AttackPlayersServerRpc();
				timesHearingNoise = 0;
			}
			else
			{
				timesHearingNoise++;
			}
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager))]
	public class GameNetworkManagerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("DisconnectProcess")]
		private static void DisconnectProcessPostfix()
		{
			if (NetworkManager.Singleton.IsServer)
			{
				if (TimeOfDayPatch.Instance != null)
				{
					TimeOfDayPatch.Instance.quotaVariables.deadlineDaysAmount = Random.Range(Plugin.MinDayBeforeDeadline, Plugin.MaxDayBeforeDeadline + 1);
				}
				GameManager.gameOver = true;
				Plugin.Logger.LogError((object)"Game Ended");
				GameManager.Reset();
			}
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal static class PlayerControllerBPatch
	{
		public static bool isEnemyAlreadySpawnedOnItemPosition;

		[HarmonyPrefix]
		[HarmonyPatch("DamagePlayerServerRpc")]
		private static void DamagePlayerServerRpcPrefix(ref int damageNumber, ref int newHealthAmount)
		{
			if (NetworkManager.Singleton.IsServer)
			{
				damageNumber = (int)((float)damageNumber * Random.Range(0.25f, 1f));
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("GrabObjectServerRpc")]
		private static void GrabObjectServerRpcPostfix(PlayerControllerB __instance, ref NetworkObjectReference grabbedObject)
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			NetworkObject val = default(NetworkObject);
			if (!NetworkManager.Singleton.IsServer || (Object)(object)__instance == (Object)null || (Object)(object)NetworkManager.Singleton == (Object)null || (Object)(object)RoundManagerPatch.Instance == (Object)null || !((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val, NetworkManager.Singleton))
			{
				return;
			}
			ChaoticItemAdditionalData component = ((Component)val).GetComponent<ChaoticItemAdditionalData>();
			if (component != null)
			{
				component.pickedUp = true;
			}
			if (RoundManagerPatch.Instance.currentLevel.Enemies.Count == 0 || isEnemyAlreadySpawnedOnItemPosition || __instance.isInElevator)
			{
				return;
			}
			WeightedList<bool> weightedList = new WeightedList<bool>();
			weightedList.Add(item: true, 100 - Plugin.ChanceOfSpawnEnemyOnItem);
			weightedList.Add(item: false, Plugin.ChanceOfSpawnEnemyOnItem);
			if (weightedList.Next())
			{
				return;
			}
			if (__instance.isInsideFactory)
			{
				var (val2, val3) = GameManager.SpawnRandomEnemy(RoundManagerPatch.Instance, inside: true, ((Component)val).transform.position, 0f, Plugin.SpawnEnemyOnItemExclusionListInside);
				if ((Object)(object)val2 == (Object)null)
				{
					return;
				}
			}
			else if (!__instance.isInsideFactory && !__instance.isInHangarShipRoom)
			{
				var (val4, val5) = GameManager.SpawnRandomEnemy(RoundManagerPatch.Instance, inside: false, ((Component)val).transform.position, 0f, Plugin.SpawnEnemyOnItemExclusionListOutside);
				if ((Object)(object)val4 == (Object)null)
				{
					return;
				}
			}
			isEnemyAlreadySpawnedOnItemPosition = true;
			Timer timer = new Timer(1f, oneshot: true);
			timer.OnTimeout += delegate
			{
				isEnemyAlreadySpawnedOnItemPosition = false;
			};
			timer.Start();
			GameManager.Timers.Add(timer);
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal static class RoundManagerPatch
	{
		public static RoundManager? Instance { get; private set; }

		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void StartPostfix(RoundManager __instance)
		{
			if (NetworkManager.Singleton.IsServer)
			{
				Plugin.Logger.LogError((object)"Round Manager start method get called");
				GameManager.Reset();
				Instance = __instance;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("Update")]
		private static void UpdatePrefix()
		{
			if (!NetworkManager.Singleton.IsServer || StartOfRoundPatch.CurrentMoonName == "CompanyBuilding")
			{
				return;
			}
			for (int num = GameManager.Timers.Count - 1; num >= 0; num--)
			{
				GameManager.Timers[num].Update();
				if (GameManager.Timers[num].Finished)
				{
					GameManager.Timers.RemoveAt(num);
				}
			}
			if (Instance == null || GameManager.gameOver || !Instance.dungeonFinishedGeneratingForAllPlayers || Instance.allEnemyVents.Length == 0)
			{
				return;
			}
			for (int num2 = GameManager.chaoticEntities.Count - 1; num2 >= 0; num2--)
			{
				GameManager.chaoticEntities[num2].Update();
				if (GameManager.chaoticEntities[num2].ItsJoever)
				{
					if (GameManager.chaoticEntities[num2] is ChaoticEnemy)
					{
						Timer timer = new Timer(Random.Range(120, 150), oneshot: true);
						timer.OnTimeout += delegate
						{
							GameManager.SpawnChaoticEnemy(Instance);
						};
						timer.Start();
						GameManager.Timers.Add(timer);
					}
					GameManager.chaoticEntities.RemoveAt(num2);
				}
			}
			if (GameManager.beginChaos)
			{
				return;
			}
			GameManager.StartSpawning(Instance);
			Plugin.Logger.LogError((object)"Chaos is starting");
			TimeOfDay.Instance.globalTimeSpeedMultiplier = Random.Range(Plugin.MinTimeMultiplier, Plugin.MaxTimeMultiplier);
			GameManager.ChanceOfSameEnemyDay(Instance);
			Timer timer2 = new Timer(5f, oneshot: true);
			timer2.OnTimeout += delegate
			{
				for (int i = 0; i < GameManager.maxChaoticItemSpawn; i++)
				{
					GameManager.SpawnChaoticItem(Instance);
				}
			};
			timer2.Start();
			GameManager.Timers.Add(timer2);
			if (GameManager.spawnEnemyTimer != null)
			{
				GameManager.spawnEnemyTimer.Start();
				GameManager.beginChaos = true;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("DetectElevatorIsRunning")]
		private static void DetectElevatorIsRunningPrefix()
		{
			if (NetworkManager.Singleton.IsServer)
			{
				if (TimeOfDayPatch.Instance != null)
				{
					TimeOfDayPatch.Instance.quotaVariables.deadlineDaysAmount = Random.Range(Plugin.MinDayBeforeDeadline, Plugin.MaxDayBeforeDeadline + 1);
				}
				GameManager.gameOver = true;
				GameManager.Reset();
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	public class StartOfRoundPatch
	{
		public static string? CurrentMoonName { get; private set; }

		[HarmonyPrefix]
		[HarmonyPatch("SceneManager_OnLoad")]
		private static void SceneManager_OnLoadPatch(StartOfRound __instance, ulong clientId, ref string sceneName, ref LoadSceneMode loadSceneMode, ref AsyncOperation asyncOperation)
		{
			if (NetworkManager.Singleton.IsServer)
			{
				CurrentMoonName = sceneName;
				Random.InitState(__instance.randomMapSeed);
				Plugin.Logger.LogError((object)("Game Starting with level " + CurrentMoonName));
				if (CurrentMoonName != "CompanyBuilding")
				{
					GameManager.gameOver = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(TimeOfDay))]
	internal static class TimeOfDayPatch
	{
		public static TimeOfDay? Instance { get; set; }

		[HarmonyPrefix]
		[HarmonyPatch("Awake")]
		private static void AwakePrefix(TimeOfDay __instance)
		{
			if (NetworkManager.Singleton.IsServer)
			{
				if ((Object)(object)Instance == (Object)null)
				{
					__instance.quotaVariables.deadlineDaysAmount = Random.Range(Plugin.MinDayBeforeDeadline, Plugin.MaxDayBeforeDeadline + 1);
					__instance.SyncTimeClientRpc(__instance.globalTime, (int)__instance.timeUntilDeadline);
				}
				Instance = __instance;
				Instance.globalTimeSpeedMultiplier = Random.Range(Plugin.MinTimeMultiplier, Plugin.MaxTimeMultiplier);
			}
		}
	}
}
namespace ChaosCompany.Scripts.Managers
{
	public enum EnemySpawnType
	{
		Inside,
		Outside
	}
	public static class GameManager
	{
		public static bool gameOver;

		public static Timer? spawnEnemyTimer;

		public static EnemySpawnType[] spawnTypes = new EnemySpawnType[2]
		{
			EnemySpawnType.Inside,
			EnemySpawnType.Outside
		};

		public static List<Chaotic> chaoticEntities = new List<Chaotic>();

		public static int numberOfTriesOfSpawningRandomEnemyNearPlayer;

		public static int modMaxEnemyNumber;

		public static int modEnemyNumber;

		public static int maxChaoticEnemySpawn;

		public static int maxMoveEnemySpawn;

		public static int maxChaoticItemSpawn;

		public static bool beginChaos;

		public static List<Timer> Timers { get; private set; } = new List<Timer>();


		public static void Reset()
		{
			Plugin.Logger.LogError((object)"Game Reset");
			Timers.Clear();
			foreach (Chaotic chaoticEntity in chaoticEntities)
			{
				if ((Object)(object)chaoticEntity.NetworkObject == (Object)null)
				{
					Plugin.Logger.LogError((object)"Despawning chaotic entities failed because network object == null");
					continue;
				}
				if (!chaoticEntity.NetworkObject.IsSpawned)
				{
					Plugin.Logger.LogError((object)"chaoticEntity is not spawned on the network");
					continue;
				}
				if (chaoticEntity is ChaoticEnemy chaoticEnemy)
				{
					if ((Object)(object)chaoticEnemy.EnemyAI == (Object)null)
					{
						Plugin.Logger.LogError((object)"chaoticEnemy.EnemyAI == null while trying to print the enemy");
						chaoticEntity.NetworkObject.Despawn(true);
						continue;
					}
					Plugin.Logger.LogError((object)("Despawning chaotic enemy " + chaoticEnemy.EnemyAI.enemyType.enemyName));
				}
				else if (chaoticEntity is MoveEnemy moveEnemy)
				{
					if ((Object)(object)moveEnemy.EnemyAI == (Object)null)
					{
						Plugin.Logger.LogError((object)"moveEnemy.EnemyAI == null while trying to print the enemy");
						chaoticEntity.NetworkObject.Despawn(true);
						continue;
					}
					Plugin.Logger.LogError((object)("Despawning move enemy " + moveEnemy.EnemyAI.enemyType.enemyName));
				}
				else if (chaoticEntity is ChaoticItem)
				{
					Plugin.Logger.LogError((object)"Despawning chaotic item");
				}
				chaoticEntity.NetworkObject.Despawn(true);
			}
			PlayerControllerBPatch.isEnemyAlreadySpawnedOnItemPosition = false;
			chaoticEntities.Clear();
			modEnemyNumber = 0;
			maxChaoticItemSpawn = Random.Range(Plugin.MinChaoticItemSpawnNumber, Plugin.MaxChaoticItemSpawnNumber);
			spawnEnemyTimer = new Timer(Plugin.SpawnEnemyInterval, oneshot: false);
			modMaxEnemyNumber = Random.Range(Plugin.MinEnemySpawnNumber, Plugin.MaxChaoticEnemySpawn);
			maxChaoticEnemySpawn = Plugin.MaxChaoticEnemySpawn;
			maxMoveEnemySpawn = Plugin.MaxMoveEnemySpawn;
			beginChaos = false;
			numberOfTriesOfSpawningRandomEnemyNearPlayer = 6;
		}

		public static void ChanceOfSameEnemyDay(RoundManager roundManager)
		{
			WeightedList<bool> weightedList = new WeightedList<bool>();
			weightedList.Add(item: true, Plugin.ChanceOfSameDayEnemy);
			weightedList.Add(item: false, 100 - Plugin.ChanceOfSameDayEnemy);
			if (weightedList.Next())
			{
				SpawnableEnemyWithRarity val = roundManager.currentLevel.Enemies[Random.Range(0, roundManager.currentLevel.Enemies.Count)];
				SpawnableEnemyWithRarity val2 = roundManager.currentLevel.OutsideEnemies[Random.Range(0, roundManager.currentLevel.OutsideEnemies.Count)];
				HUDManager.Instance.AddTextToChatOnServer("It's " + val.enemyType.enemyName + " and " + val2.enemyType.enemyName + "  day!", -1);
				for (int i = 0; i < roundManager.currentLevel.Enemies.Count; i++)
				{
					roundManager.currentLevel.Enemies[i] = val;
				}
				for (int j = 0; j < roundManager.currentLevel.OutsideEnemies.Count; j++)
				{
					roundManager.currentLevel.OutsideEnemies[j] = val2;
				}
			}
		}

		public static (EnemyType?, NetworkObjectReference?) SpawnRandomEnemy(RoundManager roundManager, bool inside, Vector3 position, float yRotation = 0f, List<string>? exclusion = null)
		{
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			if (StartOfRoundPatch.CurrentMoonName == "CompanyBuilding")
			{
				Plugin.Logger.LogError((object)"DON'T SPAWN MONSTER ON THE COMPANY BUILDING");
				return (null, null);
			}
			Plugin.Logger.LogError((object)"Trying to spawn random enemy");
			List<SpawnableEnemyWithRarity> list;
			if (inside)
			{
				list = roundManager.currentLevel.Enemies;
			}
			else
			{
				List<SpawnableEnemyWithRarity> outsideEnemies = roundManager.currentLevel.OutsideEnemies;
				outsideEnemies.AddRange(roundManager.currentLevel.DaytimeEnemies);
				list = outsideEnemies;
			}
			int count = list.Count;
			if (count == 0)
			{
				Plugin.Logger.LogError((object)"Cannot spawn enemy, enemiesTypes list is empty");
				return (null, null);
			}
			SpawnableEnemyWithRarity val = list[Random.Range(0, count)];
			bool flag = false;
			if (exclusion != null)
			{
				exclusion.AddRange(Plugin.ModSpawnEnemyExclusionList);
				foreach (string item in exclusion)
				{
					string text = ((Object)val.enemyType).name.ToLower().Trim();
					string text2 = val.enemyType.enemyName.ToLower().Trim();
					string text3 = ((object)val.enemyType).ToString().ToLower().Trim();
					string text4 = item.ToLower().Trim();
					if (text.Contains(text4) || text2.Contains(text4) || text3.Contains(text4) || text == text4)
					{
						flag = true;
						break;
					}
				}
				int num = 20;
				while (flag && num != 0)
				{
					val = list[Random.Range(0, count)];
					flag = false;
					foreach (string item2 in exclusion)
					{
						string text5 = ((Object)val.enemyType).name.ToLower().Trim();
						string text6 = val.enemyType.enemyName.ToLower().Trim();
						string text7 = ((object)val.enemyType).ToString().ToLower().Trim();
						if (text5.Contains(item2.ToLower().Trim()) || text6.Contains(item2.ToLower().Trim()) || text7.Contains(item2.ToLower().Trim()) || text5 == item2)
						{
							flag = true;
							break;
						}
					}
					num--;
				}
			}
			if (flag)
			{
				Plugin.Logger.LogError((object)"Cannot spawn enemy all of the enemies level in the map is in the exclusion list");
				return (null, null);
			}
			NetworkObjectReference value = roundManager.SpawnEnemyGameObject(position, yRotation, -1, val.enemyType);
			NetworkObject val2 = default(NetworkObject);
			((NetworkObjectReference)(ref value)).TryGet(ref val2, (NetworkManager)null);
			return (val.enemyType, value);
		}

		public static PlayerControllerB? GetClosestPlayerWithLineOfSight(RoundManager roundManager, EnemyAI enemyAI)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			List<PlayerControllerB> list = roundManager.playersManager.allPlayerScripts.ToList();
			for (int num = list.Count - 1; num >= 0; num--)
			{
				if (list[num].isPlayerDead)
				{
					list.RemoveAt(num);
				}
			}
			if (list.Count == 0)
			{
				return null;
			}
			PlayerControllerB val = list[0];
			for (int i = 0; i < list.Count; i++)
			{
				if (enemyAI.CheckLineOfSightForPosition(((Component)((NetworkBehaviour)list[i]).NetworkObject).transform.position, 360f, 100000, -1f, (Transform)null) && !list[i].isPlayerDead && Vector3.Distance(((Component)((NetworkBehaviour)list[i]).NetworkObject).transform.position, ((Component)((NetworkBehaviour)enemyAI).NetworkObject).transform.position) < Vector3.Distance(((Component)((NetworkBehaviour)val).NetworkObject).transform.position, ((Component)((NetworkBehaviour)enemyAI).NetworkObject).transform.position))
				{
					val = list[i];
				}
			}
			return val;
		}

		public static PlayerControllerB? GetRandomAlivePlayer(RoundManager roundManager, bool inside)
		{
			Plugin.Logger.LogError((object)"Trying to get random alive player");
			List<PlayerControllerB> list = roundManager.playersManager.allPlayerScripts.ToList();
			int count = list.Count;
			if (count == 0)
			{
				Plugin.Logger.LogError((object)"No player is online lmao");
				return null;
			}
			PlayerControllerB val = list[Random.Range(0, count)];
			int num = list.Count;
			int num2 = 20;
			while ((val.isInsideFactory != inside || (Object)(object)val.deadBody != (Object)null) && num2 != 0)
			{
				list.Remove(val);
				if (list.Count == 0)
				{
					return null;
				}
				val = list[Random.Range(0, list.Count)];
				num--;
				if (num <= 0)
				{
					return null;
				}
				num2--;
			}
			if (val.isInsideFactory != inside && (Object)(object)val.deadBody != (Object)null)
			{
				return null;
			}
			return val;
		}

		public static void SpawnRandomEnemyNearRandomPlayer(RoundManager roundManager, bool inside)
		{
			//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)
			RoundManager roundManager2 = roundManager;
			if (roundManager2.playersManager.allPlayerScripts.Length == 0)
			{
				Plugin.Logger.LogError((object)"Cannot spawn enemy there is no player");
				return;
			}
			PlayerControllerB randomAlivePlayer = GetRandomAlivePlayer(roundManager2, inside);
			if ((Object)(object)randomAlivePlayer == (Object)null)
			{
				return;
			}
			Vector3 targetPositionPrevious = ((Component)randomAlivePlayer).gameObject.GetComponent<NfgoPlayer>().Position;
			Timer timer = new Timer(10f, oneshot: true);
			timer.OnTimeout += delegate
			{
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_00be: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c4: 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_011b: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)randomAlivePlayer.deadBody != (Object)null || randomAlivePlayer.isInsideFactory != inside)
				{
					if (numberOfTriesOfSpawningRandomEnemyNearPlayer != 0)
					{
						SpawnRandomEnemyNearRandomPlayer(roundManager2, inside);
						numberOfTriesOfSpawningRandomEnemyNearPlayer--;
					}
				}
				else
				{
					Vector3 position = ((Component)randomAlivePlayer).gameObject.GetComponent<NfgoPlayer>().Position;
					int num = 20;
					if (Vector3.Distance(targetPositionPrevious, position) <= (float)num)
					{
						if (numberOfTriesOfSpawningRandomEnemyNearPlayer != 0)
						{
							SpawnRandomEnemyNearRandomPlayer(roundManager2, inside);
							numberOfTriesOfSpawningRandomEnemyNearPlayer--;
						}
					}
					else
					{
						bool flag = false;
						PlayerControllerB[] allPlayerScripts = roundManager2.playersManager.allPlayerScripts;
						foreach (PlayerControllerB val in allPlayerScripts)
						{
							if (Vector3.Distance(((Component)val).transform.position, targetPositionPrevious) <= (float)num)
							{
								flag = true;
								break;
							}
						}
						if (flag)
						{
							if (numberOfTriesOfSpawningRandomEnemyNearPlayer != 0)
							{
								SpawnRandomEnemyNearRandomPlayer(roundManager2, inside);
								numberOfTriesOfSpawningRandomEnemyNearPlayer--;
							}
						}
						else
						{
							if (inside)
							{
								var (val2, val3) = SpawnRandomEnemy(roundManager2, inside: true, targetPositionPrevious, 0f, Plugin.SpawnEnemyNearPlayerExclusionListInside);
								if ((Object)(object)val2 == (Object)null)
								{
									return;
								}
							}
							else
							{
								var (val4, val5) = SpawnRandomEnemy(roundManager2, inside: false, targetPositionPrevious, 0f, Plugin.SpawnEnemyNearPlayerExclusionListOutside);
								if ((Object)(object)val4 == (Object)null)
								{
									return;
								}
							}
							numberOfTriesOfSpawningRandomEnemyNearPlayer = 6;
						}
					}
				}
			};
			Timers.Add(timer);
			timer.Start();
		}

		public static void SpawnChaoticItem(RoundManager roundManager)
		{
			if ((Object)(object)roundManager == (Object)null)
			{
				Plugin.Logger.LogError((object)"roundManager == null");
				return;
			}
			ChaoticItem chaoticItem = new ChaoticItem(roundManager);
			if (chaoticItem.Spawn() == null)
			{
				Plugin.Logger.LogError((object)"Cannot spawn chaotic item");
			}
			else
			{
				chaoticEntities.Add(chaoticItem);
			}
		}

		public static NetworkObjectReference? SwitchToRandomEnemyType(RoundManager roundManager, EnemyAI? enemyTarget, bool inside, NetworkObject networkObject)
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Logger.LogError((object)"Trying to switch an enemy type to random enemy");
			if ((Object)(object)enemyTarget == (Object)null)
			{
				Plugin.Logger.LogError((object)"enemyTarget target == null");
				return null;
			}
			if ((Object)(object)enemyTarget.thisNetworkObject == (Object)null)
			{
				Plugin.Logger.LogError((object)"enemyTarget.thisNetworkObject == null");
				return null;
			}
			if (roundManager?.currentLevel.Enemies == null)
			{
				Plugin.Logger.LogError((object)"roundManager?.currentLevel.Enemies == null");
				return null;
			}
			if (!((NetworkBehaviour)enemyTarget).IsSpawned)
			{
				Plugin.Logger.LogError((object)"!enemyTarget.IsSpawned");
				return null;
			}
			var (val, result) = SpawnRandomEnemy(roundManager, inside, ((Component)enemyTarget.thisNetworkObject).transform.position, 0f, Plugin.ChaoticEnemySwitchExclusionList);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Logger.LogError((object)"enemySpawnedType == null");
				return null;
			}
			if (!result.HasValue)
			{
				Plugin.Logger.LogError((object)"networkObjectReference == null");
				return null;
			}
			enemyTarget.KillEnemyOnOwnerClient(true);
			if (((NetworkBehaviour)enemyTarget).IsSpawned)
			{
				networkObject.Despawn(true);
			}
			return result;
		}

		public static void SpawnChaoticEnemy(RoundManager roundManager)
		{
			ChaoticEnemy chaoticEnemy = new ChaoticEnemy(roundManager, Random.Range(0f, 1f) > 0.2f);
			if (chaoticEnemy.Spawn() == null)
			{
				Plugin.Logger.LogError((object)"Cannot spawn chaotic enemy");
			}
			else
			{
				chaoticEntities.Add(chaoticEnemy);
			}
		}

		public static void SpawnMoveEnemy(RoundManager roundManager)
		{
			MoveEnemy moveEnemy = new MoveEnemy(roundManager, Random.Range(0f, 1f) > 0.5f);
			if (moveEnemy.Spawn() == null)
			{
				Plugin.Logger.LogError((object)"Cannot spawn move enemy");
			}
			else
			{
				chaoticEntities.Add(moveEnemy);
			}
		}

		public static void StartSpawning(RoundManager roundManager)
		{
			RoundManager roundManager2 = roundManager;
			Plugin.Logger.LogError((object)"Start spawning enemies");
			if ((Object)(object)roundManager2 == (Object)null)
			{
				Plugin.Logger.LogError((object)"Cannot spawn monster roundManager == null");
			}
			else
			{
				if (spawnEnemyTimer == null)
				{
					return;
				}
				spawnEnemyTimer.OnTimeout += delegate
				{
					//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
					//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
					//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
					//IL_01d7: 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_02d5: 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_02e4: Unknown result type (might be due to invalid IL or missing references)
					//IL_0303: Unknown result type (might be due to invalid IL or missing references)
					//IL_0308: Unknown result type (might be due to invalid IL or missing references)
					//IL_0310: Unknown result type (might be due to invalid IL or missing references)
					//IL_031b: 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_0329: Unknown result type (might be due to invalid IL or missing references)
					Console.WriteLine("spawning enemy");
					if (modEnemyNumber >= modMaxEnemyNumber)
					{
						spawnEnemyTimer.Stop();
						return;
					}
					if (Random.Range(0f, 1f) > 0.5f)
					{
						if (Random.Range(0f, 1f) > 0.5f)
						{
							if (maxChaoticEnemySpawn != 0)
							{
								SpawnChaoticEnemy(roundManager2);
								maxChaoticEnemySpawn--;
								return;
							}
						}
						else if (maxMoveEnemySpawn != 0)
						{
							SpawnMoveEnemy(roundManager2);
							maxMoveEnemySpawn--;
							return;
						}
					}
					float num = Random.Range(0, 100);
					EnemySpawnType enemySpawnType = ((num <= 30f) ? EnemySpawnType.Outside : EnemySpawnType.Inside);
					if (Random.Range(0, 100) < 10)
					{
						roundManager2.SwitchPower(false);
						int num2 = Random.Range(Plugin.MinPowerOutageDuration, Plugin.MaxPowerOutageDuration);
						HUDManager.Instance.AddTextToChatOnServer("Warning: There is a power outage for " + TimeSpan.FromSeconds(num2).ToString("mm\\:ss"), -1);
						Timer timer = new Timer(num2, oneshot: true);
						timer.OnTimeout += delegate
						{
							roundManager2.SwitchPower(true);
						};
						timer.Start();
						Timers.Add(timer);
					}
					try
					{
						switch (enemySpawnType)
						{
						case EnemySpawnType.Inside:
							if (Random.Range(0, 100) <= 20)
							{
								SpawnRandomEnemyNearRandomPlayer(roundManager2, inside: true);
								modEnemyNumber++;
							}
							else
							{
								int num4 = roundManager2.allEnemyVents.Length;
								if (num4 == 0)
								{
									Plugin.Logger.LogError((object)"Cannot spawn enemy on the vent because there is no vent available");
								}
								else
								{
									EnemyVent val2 = roundManager2.allEnemyVents[Random.Range(0, num4)];
									Vector3 randomNavMeshPositionInBoxPredictable = val2.floorNode.position;
									float y = val2.floorNode.eulerAngles.y;
									var (val3, val4) = SpawnRandomEnemy(roundManager2, inside: true, randomNavMeshPositionInBoxPredictable, y);
									if (!((Object)(object)val3 == (Object)null))
									{
										val2.OpenVentClientRpc();
										modEnemyNumber++;
									}
								}
							}
							break;
						case EnemySpawnType.Outside:
							if (Random.Range(0, 100) <= 20)
							{
								SpawnRandomEnemyNearRandomPlayer(roundManager2, inside: false);
								modEnemyNumber++;
							}
							else
							{
								int count = roundManager2.currentLevel.OutsideEnemies.Count;
								if (count == 0)
								{
									Plugin.Logger.LogError((object)"Cannot spawn enemy outside, no enemy list available");
								}
								else
								{
									SpawnableEnemyWithRarity val = roundManager2.currentLevel.OutsideEnemies[Random.Range(0, count)];
									GameObject[] array = GameObject.FindGameObjectsWithTag("OutsideAINode");
									int num3 = array.Length;
									if (num3 == 0)
									{
										Plugin.Logger.LogError((object)"Cannot spawn enemy outside, no spawn point available");
									}
									else
									{
										Vector3 position = array[Random.Range(0, num3)].transform.position;
										Vector3 randomNavMeshPositionInBoxPredictable = roundManager2.GetRandomNavMeshPositionInBoxPredictable(position, 10f, default(NavMeshHit), roundManager2.AnomalyRandom, roundManager2.GetLayermaskForEnemySizeLimit(val.enemyType));
										randomNavMeshPositionInBoxPredictable = roundManager2.PositionWithDenialPointsChecked(randomNavMeshPositionInBoxPredictable, array, val.enemyType);
										SpawnRandomEnemy(roundManager2, inside: false, randomNavMeshPositionInBoxPredictable);
										modEnemyNumber++;
									}
								}
							}
							break;
						}
					}
					catch (Exception ex)
					{
						Plugin.Logger.LogError((object)ex);
					}
				};
				Timers.Add(spawnEnemyTimer);
			}
		}
	}
}
namespace ChaosCompany.Scripts.Items
{
	public class ChaoticItem : Chaotic
	{
		private Timer changeType;

		public ChaoticItem(RoundManager roundManager)
			: base(roundManager)
		{
			changeType = new Timer(Plugin.ChaoticItemSwitchPriceTime, oneshot: false);
			changeType.OnTimeout += delegate
			{
				if (!((Object)(object)base.NetworkObject == (Object)null))
				{
					GrabbableObject component = ((Component)base.NetworkObject).gameObject.GetComponent<GrabbableObject>();
					if (component != null)
					{
						ChaoticItemAdditionalData component2 = ((Component)base.NetworkObject).gameObject.GetComponent<ChaoticItemAdditionalData>();
						if (component2 != null && component2.pickedUp)
						{
							changeType.Stop();
							changeType.Finished = true;
							base.ItsJoever = true;
						}
						component.scrapValue = Random.Range(Plugin.MinChaoticItemPrice, Plugin.MaxChaoticItemPrice);
					}
				}
			};
			GameManager.Timers.Add(changeType);
		}

		public override void Update()
		{
			if (!((Object)(object)base.NetworkObject == (Object)null) && ((Component)base.NetworkObject).gameObject.GetComponent<GrabbableObject>().isHeld)
			{
				changeType.Stop();
				changeType.Finished = true;
				base.ItsJoever = true;
			}
		}

		public override Chaotic? Spawn()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			if (base.RoundManager.currentLevel.spawnableScrap.Count == 0)
			{
				Plugin.Logger.LogError((object)"No spawnable scrap in the level");
				return null;
			}
			SpawnableItemWithRarity val = base.RoundManager.currentLevel.spawnableScrap[Random.Range(0, base.RoundManager.currentLevel.spawnableScrap.Count)];
			RandomScrapSpawn[] array = Object.FindObjectsOfType<RandomScrapSpawn>();
			if (array.Length == 0)
			{
				Plugin.Logger.LogError((object)"randomScrapSpawnArray is empty");
				return null;
			}
			RandomScrapSpawn val2 = array[Random.Range(0, array.Length)];
			Vector3 val3 = base.RoundManager.GetRandomNavMeshPositionInBoxPredictable(((Component)val2).transform.position, val2.itemSpawnRange, base.RoundManager.navHit, base.RoundManager.AnomalyRandom, -1) + Vector3.up * val.spawnableItem.verticalOffset;
			GameObject val4 = Object.Instantiate<GameObject>(val.spawnableItem.spawnPrefab, val3 + new Vector3(0f, 0.5f, 0f), Quaternion.identity);
			GrabbableObject component = val4.GetComponent<GrabbableObject>();
			((Component)component).transform.rotation = Quaternion.Euler(component.itemProperties.restingRotation);
			component.fallTime = 0f;
			component.scrapValue = Random.Range(Plugin.MinChaoticItemPrice, Plugin.MaxChaoticItemPrice);
			((NetworkBehaviour)component).NetworkObject.Spawn(false);
			base.NetworkObject = ((NetworkBehaviour)component).NetworkObject;
			((Component)base.NetworkObject).gameObject.AddComponent<ChaoticItemAdditionalData>();
			changeType.Start();
			return this;
		}
	}
}
namespace ChaosCompany.Scripts.Extensions
{
	public static class Vector2Extension
	{
		public static Vector2 RotateDegrees(this Vector2 value, float degrees)
		{
			float x = MathF.PI / 180f * degrees;
			float num = MathF.Cos(x);
			float num2 = MathF.Sin(x);
			return new Vector2(num * value.X - num2 * value.Y, num2 * value.X + num * value.Y);
		}
	}
}
namespace ChaosCompany.Scripts.Entities
{
	public class ChaoticEnemy : ChaoticEntities
	{
		private Timer changeType;

		private bool isChaoticEnemyAlreadyTryingToChange;

		public ChaoticEnemy(RoundManager roundManager, bool inside)
		{
			RoundManager roundManager2 = roundManager;
			base..ctor(roundManager2, inside, Plugin.ChaoticEnemySwitchExclusionList);
			ChaoticEnemy chaoticEnemy = this;
			changeType = new Timer(Plugin.ChaoticEnemySwitchTime, oneshot: false);
			changeType.OnTimeout += delegate
			{
				//IL_015d: Unknown result type (might be due to invalid IL or missing references)
				if (!GameManager.gameOver)
				{
					if (chaoticEnemy.isChaoticEnemyAlreadyTryingToChange)
					{
						chaoticEnemy.isChaoticEnemyAlreadyTryingToChange = !chaoticEnemy.isChaoticEnemyAlreadyTryingToChange;
					}
					else if ((Object)(object)chaoticEnemy.NetworkObject == (Object)null)
					{
						Plugin.Logger.LogError((object)"NetworkObject == null");
					}
					else if ((Object)(object)chaoticEnemy.EnemyAI == (Object)null)
					{
						Plugin.Logger.LogError((object)"enemyAI == null");
					}
					else
					{
						NetworkObject? networkObject = chaoticEnemy.NetworkObject;
						if ((Object)(object)((networkObject != null) ? ((Component)networkObject).gameObject : null) == (Object)null)
						{
							Plugin.Logger.LogError((object)"NetworkObject.gameObject == null");
						}
						else if ((Object)(object)((Component)chaoticEnemy.NetworkObject).gameObject == (Object)null)
						{
							Plugin.Logger.LogError((object)"A chaotic enemy gameObject == null");
						}
						else
						{
							Plugin.Logger.LogError((object)("An " + chaoticEnemy.kindString + " " + chaoticEnemy.EnemyAI.enemyType.enemyName + " chaotic enemy is changing"));
							NetworkObjectReference? val = GameManager.SwitchToRandomEnemyType(roundManager2, chaoticEnemy.EnemyAI, chaoticEnemy.Inside, chaoticEnemy.NetworkObject);
							if (val.HasValue)
							{
								chaoticEnemy.NetworkObject = NetworkObjectReference.op_Implicit(val.GetValueOrDefault());
								chaoticEnemy.EnemyAI = ((Component)chaoticEnemy.NetworkObject).gameObject.GetComponent<EnemyAI>();
							}
							else
							{
								Plugin.Logger.LogError((object)"networkObjectReference == null after switching enemy type");
							}
							chaoticEnemy.isChaoticEnemyAlreadyTryingToChange = !chaoticEnemy.isChaoticEnemyAlreadyTryingToChange;
						}
					}
				}
			};
			GameManager.Timers.Add(changeType);
		}

		public override void Update()
		{
			if (!((Object)(object)base.EnemyAI == (Object)null))
			{
				if (base.EnemyAI.isEnemyDead)
				{
					Plugin.Logger.LogError((object)("An " + kindString + " chaotic enemy died as " + base.EnemyAI.enemyType.enemyName));
					changeType.Stop();
					changeType.Finished = true;
					base.ItsJoever = true;
				}
				else
				{
					base.Inside = !base.EnemyAI.isOutside;
				}
			}
		}

		public override Chaotic? Spawn()
		{
			ChaoticEnemy chaoticEnemy = (ChaoticEnemy)base.Spawn();
			if (chaoticEnemy == null)
			{
				return null;
			}
			if ((Object)(object)base.EnemyAI == (Object)null)
			{
				Plugin.Logger.LogError((object)"EnemyAI shouldn't be null here");
				return null;
			}
			changeType.Start();
			return chaoticEnemy;
		}
	}
	public class ChaoticEntities : Chaotic
	{
		protected string kindString;

		private List<string>? exclusion;

		public EnemyAI? EnemyAI { get; protected set; }

		public bool Inside { get; protected set; }

		public ChaoticEntities(RoundManager roundManager, bool inside, List<string>? exclusion)
			: base(roundManager)
		{
			this.exclusion = exclusion;
			Inside = inside;
			kindString = (Inside ? "inside" : "outside");
		}

		public override Chaotic? Spawn()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			float yRotation;
			Vector3 position;
			if (Inside)
			{
				int num = base.RoundManager.allEnemyVents.Length;
				if (num == 0)
				{
					return null;
				}
				EnemyVent val = base.RoundManager.allEnemyVents[Random.Range(0, num)];
				position = val.floorNode.position;
				yRotation = val.floorNode.eulerAngles.y;
				val.OpenVentClientRpc();
			}
			else
			{
				int count = base.RoundManager.currentLevel.OutsideEnemies.Count;
				if (count == 0)
				{
					Plugin.Logger.LogError((object)"Cannot spawn enemy outside, no enemy list available");
					return null;
				}
				SpawnableEnemyWithRarity val2 = base.RoundManager.currentLevel.OutsideEnemies[Random.Range(0, count)];
				GameObject[] array = GameObject.FindGameObjectsWithTag("OutsideAINode");
				int num2 = array.Length;
				if (num2 == 0)
				{
					Plugin.Logger.LogError((object)"Cannot chaotic outside, no spawn point available");
					return null;
				}
				Vector3 position2 = array[Random.Range(0, num2)].transform.position;
				yRotation = 0f;
				position = base.RoundManager.GetRandomNavMeshPositionInBoxPredictable(position2, 10f, default(NavMeshHit), base.RoundManager.AnomalyRandom, base.RoundManager.GetLayermaskForEnemySizeLimit(val2.enemyType));
				position = base.RoundManager.PositionWithDenialPointsChecked(position, array, val2.enemyType);
			}
			var (val3, val4) = GameManager.SpawnRandomEnemy(base.RoundManager, Inside, position, yRotation, exclusion);
			if ((Object)(object)val3 == (Object)null || !val4.HasValue)
			{
				return null;
			}
			if (!val4.HasValue)
			{
				Plugin.Logger.LogError((object)"Error networkObjectReference == null when trying to spawn chaotic entity");
				return null;
			}
			NetworkObjectReference? val5 = val4;
			base.NetworkObject = (val5.HasValue ? NetworkObjectReference.op_Implicit(val5.GetValueOrDefault()) : null);
			EnemyAI = ((Component)base.NetworkObject).gameObject.GetComponent<EnemyAI>();
			return this;
		}
	}
	public class MoveEnemy : ChaoticEntities
	{
		private PlayerControllerB? closestPlayer;

		private Vector3 lastClosestPlayerPosition;

		private NavMeshAgent? navMeshAgent;

		private Timer findClosestPlayerDelay;

		private Vector3? freezePosition;

		private string playerUsername = "";

		private string previousPlayerUsername = "";

		public MoveEnemy(RoundManager roundManager, bool inside)
			: base(roundManager, inside, Plugin.MoveEnemySpawnExclusionList)
		{
			findClosestPlayerDelay = new Timer(1f, oneshot: false);
			findClosestPlayerDelay.OnTimeout += delegate
			{
				if (!((Object)(object)base.NetworkObject == (Object)null) && !((Object)(object)base.EnemyAI == (Object)null))
				{
					closestPlayer = GameManager.GetClosestPlayerWithLineOfSight(base.RoundManager, base.EnemyAI);
					if (!((Object)(object)closestPlayer == (Object)null))
					{
						previousPlayerUsername = playerUsername;
						playerUsername = closestPlayer.playerUsername;
						if (playerUsername != previousPlayerUsername)
						{
							Plugin.Logger.LogError((object)("Changing target to " + closestPlayer.playerUsername));
						}
					}
				}
			};
			findClosestPlayerDelay.Start();
			GameManager.Timers.Add(findClosestPlayerDelay);
		}

		public override void Update()
		{
			//IL_00f2: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			if (GameManager.gameOver || (Object)(object)base.EnemyAI == (Object)null || (Object)(object)base.NetworkObject == (Object)null)
			{
				return;
			}
			if (base.EnemyAI.isEnemyDead)
			{
				Plugin.Logger.LogError((object)("A " + kindString + " move enemy died as " + base.EnemyAI.enemyType.enemyName));
				base.ItsJoever = true;
				return;
			}
			EnemyAIAdditionalData component = ((Component)base.NetworkObject).gameObject.GetComponent<EnemyAIAdditionalData>();
			if ((Object)(object)closestPlayer == (Object)null)
			{
				component.paused = false;
				return;
			}
			component.paused = closestPlayer.timeSincePlayerMoving > 0.05f;
			if (component.paused)
			{
				Vector3? val = freezePosition;
				if (val.HasValue)
				{
					Vector3 valueOrDefault = val.GetValueOrDefault();
					((Component)base.NetworkObject).transform.position = valueOrDefault;
					base.EnemyAI.SyncPositionToClients();
				}
			}
			else
			{
				freezePosition = ((Component)base.NetworkObject).transform.position;
			}
		}

		public override Chaotic? Spawn()
		{
			MoveEnemy moveEnemy = (MoveEnemy)base.Spawn();
			if ((Object)(object)base.EnemyAI == (Object)null)
			{
				Plugin.Logger.LogError((object)"EnemyAI shouldn't be null here");
				return null;
			}
			if (moveEnemy == null)
			{
				Plugin.Logger.LogError((object)"Move enemy == null");
				return null;
			}
			if ((Object)(object)moveEnemy.NetworkObject == (Object)null)
			{
				Plugin.Logger.LogError((object)"Move enemy NetworkObject == null");
				return null;
			}
			((Component)moveEnemy.NetworkObject).gameObject.AddComponent<EnemyAIAdditionalData>();
			navMeshAgent = ((Component)base.EnemyAI).GetComponent<NavMeshAgent>();
			return moveEnemy;
		}
	}
}
namespace ChaosCompany.Scripts.DataStructures
{
	public class ChaoticItemAdditionalData : MonoBehaviour
	{
		public bool pickedUp;
	}
	public class EnemyAIAdditionalData : MonoBehaviour
	{
		public bool paused;
	}
}
namespace ChaosCompany.Scripts.Components
{
	public sealed class Timer
	{
		public bool Finished { get; set; }

		public float WaitTime { get; set; }

		public bool Oneshot { get; set; }

		public float TimeLeft { get; private set; }

		public bool Paused { get; private set; } = true;


		public event Action? OnTimeout;

		public Timer(float waitTime, bool oneshot)
		{
			WaitTime = waitTime;
			Oneshot = oneshot;
		}

		public void Start()
		{
			Paused = false;
		}

		public void Restart()
		{
			TimeLeft = 0f;
			Start();
		}

		public void Stop()
		{
			Paused = true;
		}

		public void Update()
		{
			if (Paused)
			{
				return;
			}
			TimeLeft += Time.deltaTime;
			if (!(TimeLeft >= WaitTime))
			{
				return;
			}
			TimeLeft = 0f;
			if (this.OnTimeout != null)
			{
				this.OnTimeout();
				if (Oneshot)
				{
					Finished = true;
				}
			}
			if (Oneshot)
			{
				Paused = true;
			}
		}
	}
}
namespace ChaosCompany.Scripts.Abstracts
{
	public abstract class Chaotic
	{
		public RoundManager RoundManager { get; private set; }

		public NetworkObject? NetworkObject { get; protected set; }

		public bool ItsJoever { get; protected set; }

		public Chaotic(RoundManager roundManager)
		{
			RoundManager = roundManager;
		}

		public virtual void Update()
		{
		}

		public virtual Chaotic? Spawn()
		{
			return null;
		}
	}
}