Decompiled source of ExperimentalEnemyInteractions v0.5.30

DLLs/fandovec03.NaturalSelection.dll

Decompiled 2 weeks 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.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CleaningCompany;
using EnhancedMonsters.Monobehaviours;
using GameNetcodeStuff;
using HarmonyLib;
using LethalNetworkAPI;
using LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
using Microsoft.CodeAnalysis;
using NaturalSelection.Compatibility;
using NaturalSelection.EnemyPatches;
using NaturalSelection.Generics;
using NaturalSelectionLib;
using ReXuvination.src;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("EnhancedMonsters")]
[assembly: IgnoresAccessChecksTo("ReXuvination")]
[assembly: IgnoresAccessChecksTo("SellBodies")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("fandovec03.NaturalSelection")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.4.6.0")]
[assembly: AssemblyInformationalVersion("0.4.6+54ff48bd0614f776f9058a0d8edf5dfd364673d9")]
[assembly: AssemblyProduct("NaturalSelection")]
[assembly: AssemblyTitle("fandovec03.NaturalSelection")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.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 NaturalSelection
{
	[BepInPlugin("fandovec03.NaturalSelection", "NaturalSelection", "0.4.6")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Script : BaseUnityPlugin
	{
		public static ManualLogSource Logger = null;

		internal static bool stableToggle;

		private static bool isExperimental = false;

		private static bool isPrerelease = false;

		private static bool debugBool = false;

		private static bool debugKillSwitch = false;

		private static bool spammyLogs = false;

		private static bool debugNetworking = false;

		private static bool debugLibrary = false;

		private static bool debugLibraryTrigger = false;

		private static bool debugTriggerFlags = false;

		private static bool debugGiants = false;

		private static bool debugHygrodere = false;

		private static bool debugNutcrackers = false;

		private static bool debugRedBees = false;

		private static bool debugSandworms = false;

		private static bool debugSpiders = false;

		private static bool debugSpiderWebs = false;

		private static bool debugUnspecified = false;

		internal static bool enhancedMonstersPresent = false;

		internal static bool sellBodiesPresent = false;

		internal static bool rexuvinationPresent = false;

		internal static bool CompatibilityAutoToggle = false;

		internal static bool LobbyCompatibilityPresent = false;

		internal static bool usePathfindingLib = false;

		internal static bool usePathToFindClosestEnemy = false;

		internal static Dictionary<string, bool> Bools = new Dictionary<string, bool>();

		internal static List<EnemyAI> loadedEnemyList = new List<EnemyAI>();

		public static Action<string, bool>? OnConfigSettingChanged;

		private static bool debugKillSwitchScript = false;

		public static Script Instance { get; private set; } = null;


		internal static Harmony? Harmony { get; set; }

		internal static MyModConfig BoundingConfig { get; set; } = null;


		private static void SubscribeDebugConfigBools(ConfigEntry<bool> entryKey, bool boolParam, string entry)
		{
			ConfigEntry<bool> entryKey2 = entryKey;
			string entry2 = entry;
			entryKey2.SettingChanged += delegate
			{
				boolParam = entryKey2.Value;
				Logger.LogMessage((object)$"Updating with entry.Value {entryKey2.Value}. Result: {boolParam}");
				OnConfigSettingChanged?.Invoke(entry2, entryKey2.Value);
			};
		}

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			BoundingConfig = new MyModConfig(((BaseUnityPlugin)this).Config);
			stableToggle = BoundingConfig.stableMode.Value;
			Bools.Add("debugBool", debugBool);
			Bools.Add("debugKillSwitch", debugKillSwitch);
			Bools.Add("spammyLogs", spammyLogs);
			Bools.Add("debugNetworking", debugNetworking);
			Bools.Add("debugLibraryTrigger", debugLibraryTrigger);
			Bools.Add("debugLibrary", debugLibrary);
			Bools.Add("debugTriggerFlags", debugTriggerFlags);
			Bools.Add("debugGiants", debugGiants);
			Bools.Add("debugHygrodere", debugHygrodere);
			Bools.Add("debugNutcrackers", debugNutcrackers);
			Bools.Add("debugRedBees", debugRedBees);
			Bools.Add("debugSandworms", debugSandworms);
			Bools.Add("debugSpiders", debugSpiders);
			Bools.Add("debugSpiderWebs", debugSpiderWebs);
			Bools.Add("debugUnspecified", debugUnspecified);
			CompatibilityAutoToggle = BoundingConfig.CompatibilityAutoToggle.Value;
			usePathfindingLib = BoundingConfig.usePathfindinglibCoroutines.Value;
			usePathToFindClosestEnemy = BoundingConfig.usePathToFindClosestEnemy.Value;
			foreach (KeyValuePair<string, ConfigEntry<bool>> debugEntry in BoundingConfig.debugEntries)
			{
				if (Bools.ContainsKey(debugEntry.Key))
				{
					Bools[debugEntry.Key] = debugEntry.Value.Value;
					SubscribeDebugConfigBools(debugEntry.Value, Bools[debugEntry.Key], debugEntry.Key);
				}
				else
				{
					Logger.LogError((object)("Failed to find bool for config entry " + debugEntry.Key));
				}
			}
			char[] array = "0.4.6".ToCharArray();
			if ((array[0] == '9' && array[1] == '9') || (array[0] == '8' && array[1] == '8'))
			{
				if (array[0] == '9' && array[1] == '9')
				{
					isExperimental = true;
				}
				if (array[0] == '8' && array[1] == '8')
				{
					isPrerelease = true;
				}
				array[0] = '0';
				array[1] = '0';
			}
			Patch();
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(array);
			Logger.LogInfo((object)string.Format("{0} v{1} has loaded!", "fandovec03.NaturalSelection", stringBuilder));
			OnConfigSettingChanged = (Action<string, bool>)Delegate.Combine(OnConfigSettingChanged, new Action<string, bool>(Event_OnConfigSettingChanged));
		}

		internal static void Patch()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony = new Harmony("fandovec03.NaturalSelection");
			}
			Logger.LogInfo((object)"Patching NaturalSelection...");
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				string text = "";
				if (!CompatibilityAutoToggle)
				{
					break;
				}
				switch (pluginInfo.Key)
				{
				case "com.velddev.enhancedmonsters":
					enhancedMonstersPresent = true;
					text = "Found Enhanced Monsters";
					break;
				case "Entity378.sellbodies":
					sellBodiesPresent = true;
					text = "Found SellbodiesFixed";
					break;
				case "XuuXiaolan.ReXuvination":
					rexuvinationPresent = true;
					text = "Found ReXuvination";
					break;
				case "BMX.LobbyCompatibility":
					LobbyCompatibilityPresent = true;
					text = "Found LobbyCompatibility";
					break;
				}
				if (text != "")
				{
					Logger.LogInfo((object)(text + ". Automatically loading compatibility."));
				}
			}
			try
			{
				LobbyCompCompatibility.RegisterLobbyComp("fandovec03.NaturalSelection", Version.Parse("0.4.6"));
			}
			catch
			{
			}
			foreach (KeyValuePair<string, ConfigEntry<bool>> compatibilityEntry in BoundingConfig.CompatibilityEntries)
			{
				string text2 = "";
				if (compatibilityEntry.Value.Value)
				{
					switch (compatibilityEntry.Key)
					{
					case "com.velddev.enhancedmonsters":
						enhancedMonstersPresent = true;
						break;
					case "Entity378.sellbodies":
						sellBodiesPresent = true;
						break;
					case "XuuXiaolan.ReXuvination":
						rexuvinationPresent = true;
						break;
					}
					text2 = "Manually enabling compatibility for " + compatibilityEntry.Key + ".";
				}
				if (text2 != "")
				{
					Logger.LogInfo((object)text2);
				}
			}
			if (isExperimental)
			{
				Logger.LogFatal((object)("LOADING EXPERIMENTAL BUILD OF " + "NaturalSelection".ToUpper() + ", DOWNLOAD NATURAL SELECTION INSTEAD FOR MORE STABLE EXPERIENCE!"));
			}
			if (isPrerelease)
			{
				Logger.LogWarning((object)("LOADING PRERELASE BUILD OF " + "NaturalSelection".ToUpper() + ", DOWNLOAD NATURAL SELECTION INSTEAD FOR MORE STABLE EXPERIENCE!"));
			}
			Harmony.PatchAll(typeof(AICollisionDetectPatch));
			Harmony.PatchAll(typeof(EnemyAIPatch));
			Harmony.PatchAll(typeof(Networking));
			Harmony.PatchAll(typeof(NetworkingMethods));
			Harmony.PatchAll(typeof(InitializeGamePatch));
			try
			{
				NaturalSelectionLib.SetLibraryLoggers(Logger, spammyLogs, debugLibrary, usePathfindingLib);
				Logger.LogMessage((object)("Library successfully setup! Version " + NaturalSelectionLib.ReturnVersion()));
			}
			catch
			{
				Logger.LogError((object)"Failed to setup library!");
			}
			Harmony.PatchAll(typeof(RoundManagerPatch));
			if (BoundingConfig.enableLeviathan.Value)
			{
				Harmony.PatchAll(typeof(SandWormAIPatch));
			}
			if (BoundingConfig.enableSlime.Value)
			{
				Harmony.PatchAll(typeof(BlobAIPatch));
			}
			if (BoundingConfig.enableHoardingBug.Value)
			{
				Harmony.PatchAll(typeof(HoarderBugPatch));
			}
			if (BoundingConfig.enableRedBees.Value)
			{
				Harmony.PatchAll(typeof(BeeAIPatch));
			}
			if (BoundingConfig.enableGiant.Value)
			{
				Harmony.PatchAll(typeof(ForestGiantPatch));
			}
			if (BoundingConfig.enableSpiderWebs.Value)
			{
				Harmony.PatchAll(typeof(SandSpiderWebTrapPatch));
			}
			if (BoundingConfig.enableSpider.Value)
			{
				Harmony.PatchAll(typeof(SandSpiderAIPatch));
			}
			if (enhancedMonstersPresent)
			{
				Harmony.PatchAll(typeof(EnhancedMonstersCompatibility));
				Logger.LogInfo((object)"Loading compatibility for Enhanced Monsters");
			}
			if (sellBodiesPresent)
			{
				SellBodiesFixedCompatibility.AddTracerScriptToPrefabs();
				Logger.LogInfo((object)"Loading compatibility for SellbodiesFixed");
			}
			if (rexuvinationPresent)
			{
				Harmony.PatchAll(typeof(ReXuvinationPatch));
				Logger.LogInfo((object)"Loading compatibility for Rexuvination");
			}
			if (!stableToggle)
			{
				if (isExperimental)
				{
					if (BoundingConfig.enableNutcracker.Value)
					{
						Harmony.PatchAll(typeof(NutcrackerAIPatch));
					}
					if (BoundingConfig.enableSporeLizard.Value)
					{
						Harmony.PatchAll(typeof(PufferAIPatch));
					}
				}
				else
				{
					Logger.LogWarning((object)"Limited access. Some patches cannot be enabled in stable branch.");
				}
				Logger.LogInfo((object)"Stable mode off. Loaded all patches.");
			}
			else
			{
				Logger.LogInfo((object)"Stable mode on. Excluded unstable and WIP patches from loading.");
			}
			Logger.LogInfo((object)"Finished patching NaturalSelection !");
		}

		internal static void Unpatch()
		{
			Logger.LogDebug((object)"Unpatching...");
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Logger.LogDebug((object)"Finished unpatching!");
		}

		public static void LogNS(LogLevel logLevel, string log, object? source = null, bool toggle = true, bool moreDetail = false)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (toggle && !debugKillSwitchScript)
			{
				Logger.Log(logLevel, (object)(LibraryCalls.DebugStringHead(source, !moreDetail) + " " + log));
			}
		}

		private static void Event_OnConfigSettingChanged(string entryKey, bool value)
		{
			if (entryKey == "debugKillSwitch")
			{
				debugKillSwitchScript = value;
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "fandovec03.NaturalSelection";

		public const string PLUGIN_NAME = "NaturalSelection";

		public const string PLUGIN_VERSION = "0.4.6";
	}
}
namespace NaturalSelection.Generics
{
	internal class InitializeGamePatch
	{
		private static bool finishedLoading = false;

		private static List<string> loadedEnemyNamesFromConfig = new List<string>();

		private static List<string> beeBlacklistLoaded = Script.BoundingConfig.beeBlacklist.Value.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList();

		private static List<string> blobBlacklistLoaded = Script.BoundingConfig.blobBlacklist.Value.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList();

		private static List<string> sandwormBlacklistLoaded = Script.BoundingConfig.sandwormBlacklist.Value.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList();

		private static List<string> spiderWebBlacklistLoaded = Script.BoundingConfig.spiderWebBlacklist.Value.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList();

		private static List<string> speedModifierLoaded = Script.BoundingConfig.speedModifierList.Value.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList();

		private static List<string> spiderBlacklistLoaded = Script.BoundingConfig.spiderBlacklist.Value.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList();

		private static List<string> customSizeOverrideListLoaded = Script.BoundingConfig.customSizeOverrideList.Value.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList();

		internal static List<string> beeBlacklist = new List<string>();

		internal static List<string> blobBlacklist = new List<string>();

		internal static List<string> sandwormBlacklist = new List<string>();

		internal static List<string> spiderWebBlacklist = new List<string>();

		internal static List<string> speedModifier = new List<string>();

		internal static List<string> spiderBlacklist = new List<string>();

		internal static List<string> customSizeOverrideList = new List<string>();

		public static Dictionary<string, float> speedModifierDictionay = new Dictionary<string, float>();

		public static Dictionary<string, int> customSizeOverrideListDictionary = new Dictionary<string, int>();

		public static List<EnemyAI> tryFindLater = new List<EnemyAI>();

		[HarmonyPatch(typeof(InitializeGame), "Start")]
		[HarmonyPostfix]
		public static void InitializeGameStartPatch()
		{
			Script.loadedEnemyList = Resources.FindObjectsOfTypeAll<EnemyAI>().ToList();
			if (!finishedLoading)
			{
				Script.Logger.Log((LogLevel)8, (object)"Reading/Checking/Writing entries for enemies.");
				ReadConfigLists();
				CheckConfigLists(Script.loadedEnemyList);
				WriteToConfigLists();
			}
			LibraryCalls.SubscribeToConfigChanges();
			Networking.SubscribeToConfigChanges();
			finishedLoading = true;
		}

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPostfix]
		public static void StartOfRoundPatch()
		{
			if (tryFindLater.Count > 0)
			{
				Script.Logger.Log((LogLevel)8, (object)"Secondary list is not empty. Checking/Writing entries for skipped enemies");
				try
				{
					CheckConfigLists(tryFindLater);
					WriteToConfigLists();
					tryFindLater.Clear();
				}
				catch
				{
					Script.Logger.Log((LogLevel)2, (object)"An error has occured while working with the list.");
					tryFindLater.Clear();
				}
			}
		}

		public static void ReadConfigLists()
		{
			foreach (string item in speedModifierLoaded)
			{
				try
				{
					string text = item.Split(":")[0];
					float num = float.Parse(item.Split(":")[1].Replace(".", ","));
					speedModifierDictionay.Add(text, num);
					Script.Logger.Log((LogLevel)32, (object)$"Found {text}, {num}");
				}
				catch (Exception ex)
				{
					Script.Logger.Log((LogLevel)2, (object)"Failed to add enemy into speedModifierDictionary");
					Script.Logger.Log((LogLevel)2, (object)item);
					Script.Logger.Log((LogLevel)2, (object)item.Split(":")[0]);
					Script.Logger.Log((LogLevel)2, (object)item.Split(":")[1]);
					Script.Logger.Log((LogLevel)2, (object)ex);
				}
			}
			foreach (string item2 in beeBlacklistLoaded)
			{
				try
				{
					beeBlacklist.Add(item2);
					Script.Logger.Log((LogLevel)32, (object)("Found " + item2));
				}
				catch (Exception ex2)
				{
					Script.Logger.Log((LogLevel)2, (object)"Failed to add enemy into beeBlacklist");
					Script.Logger.Log((LogLevel)2, (object)item2);
					Script.Logger.Log((LogLevel)2, (object)ex2);
				}
			}
			foreach (string item3 in blobBlacklistLoaded)
			{
				try
				{
					blobBlacklist.Add(item3);
					Script.Logger.Log((LogLevel)32, (object)("Found " + item3));
				}
				catch (Exception ex3)
				{
					Script.Logger.Log((LogLevel)2, (object)"Failed to add enemy into blobBlacklist");
					Script.Logger.Log((LogLevel)2, (object)item3);
					Script.Logger.Log((LogLevel)2, (object)ex3);
				}
			}
			foreach (string item4 in sandwormBlacklistLoaded)
			{
				try
				{
					sandwormBlacklist.Add(item4);
					Script.Logger.Log((LogLevel)32, (object)("Found " + item4));
				}
				catch (Exception ex4)
				{
					Script.Logger.Log((LogLevel)2, (object)"Failed to add enemy into sandwormBlacklist");
					Script.Logger.Log((LogLevel)2, (object)item4);
					Script.Logger.Log((LogLevel)2, (object)ex4);
				}
			}
			foreach (string item5 in spiderWebBlacklistLoaded)
			{
				try
				{
					spiderWebBlacklist.Add(item5);
					Script.Logger.Log((LogLevel)32, (object)("Found " + item5));
				}
				catch (Exception ex5)
				{
					Script.Logger.Log((LogLevel)2, (object)"Failed to add enemy into spiderWebBlacklist");
					Script.Logger.Log((LogLevel)2, (object)item5);
					Script.Logger.Log((LogLevel)2, (object)ex5);
				}
			}
			foreach (string item6 in spiderBlacklistLoaded)
			{
				try
				{
					spiderBlacklist.Add(item6);
					Script.Logger.Log((LogLevel)32, (object)("Found " + item6));
				}
				catch (Exception ex6)
				{
					Script.Logger.Log((LogLevel)2, (object)"Failed to add enemy into spiderBlacklist");
					Script.Logger.Log((LogLevel)2, (object)item6);
					Script.Logger.Log((LogLevel)2, (object)ex6);
				}
			}
			foreach (string item7 in customSizeOverrideListLoaded)
			{
				try
				{
					string text2 = item7.Split(":")[0];
					int num2 = int.Parse(item7.Split(":")[1]);
					if (num2 < 0 || num2 > 5)
					{
						Script.Logger.Log((LogLevel)2, (object)$"Invalid size value {num2}. Defaulting to (0 || {CustomEnemySize.Undefined})");
						num2 = 0;
					}
					customSizeOverrideListDictionary.Add(text2, num2);
					Script.Logger.Log((LogLevel)32, (object)$"Found {text2}, {(CustomEnemySize)num2}");
				}
				catch (Exception ex7)
				{
					Script.Logger.Log((LogLevel)2, (object)"Failed to add enemy into customSizeOverrideListList");
					Script.Logger.Log((LogLevel)2, (object)item7);
					Script.Logger.Log((LogLevel)2, (object)item7.Split(":")[0]);
					Script.Logger.Log((LogLevel)2, (object)item7.Split(":")[1]);
					Script.Logger.Log((LogLevel)2, (object)ex7);
				}
			}
		}

		public static void CheckConfigLists(List<EnemyAI> listOfEnemies)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected I4, but got Unknown
			foreach (EnemyAI listOfEnemy in listOfEnemies)
			{
				string enemyName;
				try
				{
					enemyName = listOfEnemy.enemyType.enemyName;
				}
				catch
				{
					Script.Logger.Log((LogLevel)4, (object)("Failed to get enemy name from " + ((Object)listOfEnemy).name + ". Adding to list for 2nd attempt."));
					tryFindLater.Add(listOfEnemy);
					continue;
				}
				if (customSizeOverrideListLoaded.Count < 1)
				{
					EnemySize enemySize = listOfEnemy.enemyType.EnemySize;
					EnemySize val = enemySize;
					switch ((int)val)
					{
					case 0:
						if (!listOfEnemy.enemyType.canDie)
						{
							customSizeOverrideListDictionary[enemyName] = 0;
						}
						else if (listOfEnemy is FlowerSnakeEnemy || listOfEnemy is DoublewingAI || listOfEnemy is RedLocustBees || listOfEnemy is DocileLocustBeesAI || listOfEnemy is ButlerBeesEnemyAI)
						{
							customSizeOverrideListDictionary[enemyName] = 1;
						}
						else if (listOfEnemy.enemyHP <= 3)
						{
							customSizeOverrideListDictionary[enemyName] = 2;
						}
						else if (listOfEnemy.enemyHP <= 15)
						{
							customSizeOverrideListDictionary[enemyName] = 3;
						}
						else if (listOfEnemy.enemyHP <= 30)
						{
							customSizeOverrideListDictionary[enemyName] = 4;
						}
						else if (listOfEnemy.enemyHP > 30)
						{
							customSizeOverrideListDictionary[enemyName] = 5;
						}
						else
						{
							customSizeOverrideListDictionary[enemyName] = 0;
						}
						break;
					case 2:
						customSizeOverrideListDictionary[enemyName] = 3;
						break;
					case 1:
						customSizeOverrideListDictionary[enemyName] = 5;
						break;
					default:
						customSizeOverrideListDictionary[enemyName] = 0;
						break;
					}
				}
				if (!loadedEnemyNamesFromConfig.Contains(enemyName))
				{
					loadedEnemyNamesFromConfig.Add(enemyName);
				}
			}
			foreach (string item in loadedEnemyNamesFromConfig)
			{
				Script.Logger.Log((LogLevel)16, (object)("Checking config entries for enemy: " + item));
				if (!speedModifierDictionay.Keys.Contains(item))
				{
					Script.Logger.Log((LogLevel)32, (object)("Generating new web speed modifier entry for " + item));
					speedModifierDictionay.Add(item, 1f);
				}
				if (beeBlacklist.Count <= 0)
				{
					Script.Logger.Log((LogLevel)32, (object)("Generating new bee blacklist entry for " + item));
					if (beeBlacklist.Contains("Earth Leviathan") || beeBlacklist.Contains("Docile Locust Bees"))
					{
						beeBlacklist.Add(item);
					}
				}
				if (!customSizeOverrideListDictionary.Keys.Contains(item))
				{
					Script.Logger.Log((LogLevel)32, (object)("Generating new custom enemy size entry for " + item));
					customSizeOverrideListDictionary.Add(item, 0);
				}
			}
			if (!Script.BoundingConfig.debugBool.Value)
			{
				return;
			}
			foreach (string item2 in beeBlacklist)
			{
				Script.Logger.Log((LogLevel)32, (object)("checking blacklist beeBlacklist -> " + item2));
			}
			foreach (string item3 in sandwormBlacklist)
			{
				Script.Logger.Log((LogLevel)32, (object)("checking blacklist sandwormBlacklist -> " + item3));
			}
			foreach (string item4 in spiderWebBlacklist)
			{
				Script.Logger.Log((LogLevel)32, (object)("checking blacklist spiderWebBlacklist -> " + item4));
			}
			foreach (string item5 in spiderBlacklist)
			{
				Script.Logger.Log((LogLevel)32, (object)("checking blacklist spiderBlacklist -> " + item5));
			}
			foreach (KeyValuePair<string, float> item6 in speedModifierDictionay)
			{
				Script.Logger.Log((LogLevel)32, (object)string.Format("checking speed modifier dictionary {0} -> {1}, {2}", "speedModifierDictionay", item6.Key, item6.Value));
			}
		}

		public static void WriteToConfigLists()
		{
			string text = "";
			string text2 = "";
			string text3 = "";
			string text4 = "";
			string text5 = "";
			string text6 = "";
			string text7 = "";
			string text8 = "";
			try
			{
				foreach (string item in loadedEnemyNamesFromConfig)
				{
					text = text + item + ",";
				}
				Script.BoundingConfig.enemyNames.Value = text;
				foreach (KeyValuePair<string, float> item2 in speedModifierDictionay)
				{
					text2 = $"{text2}{item2.Key}:{item2.Value},";
				}
				Script.BoundingConfig.speedModifierList.Value = text2;
				foreach (string item3 in beeBlacklist)
				{
					text3 = text3 + item3 + ",";
				}
				Script.BoundingConfig.beeBlacklist.Value = text3;
				foreach (string item4 in blobBlacklist)
				{
					text4 = text4 + item4 + ",";
				}
				Script.BoundingConfig.blobBlacklist.Value = text4;
				foreach (string item5 in sandwormBlacklist)
				{
					text5 = text5 + item5 + ",";
				}
				Script.BoundingConfig.sandwormBlacklist.Value = text5;
				foreach (string item6 in spiderWebBlacklist)
				{
					text6 = text6 + item6 + ",";
				}
				Script.BoundingConfig.spiderWebBlacklist.Value = text6;
				foreach (string item7 in spiderBlacklist)
				{
					text7 = text7 + item7 + ",";
				}
				Script.BoundingConfig.spiderBlacklist.Value = text7;
				foreach (KeyValuePair<string, int> item8 in customSizeOverrideListDictionary)
				{
					text8 = $"{text8}{item8.Key}:{item8.Value},";
				}
				Script.BoundingConfig.customSizeOverrideList.Value = text8;
				Script.Logger.Log((LogLevel)16, (object)"Finished generating configucations.");
			}
			catch (Exception ex)
			{
				Script.Logger.Log((LogLevel)2, (object)"Failed to generate configucations.");
				Script.Logger.Log((LogLevel)2, (object)ex);
			}
		}
	}
	public class LibraryCalls
	{
		private static bool debugSpam = Script.Bools["spammyLogs"];

		private static bool debugLibraryCalls = Script.Bools["debugLibrary"];

		private static void Event_OnConfigSettingChanged(string entryKey, bool value)
		{
			if (entryKey == "spammyLogs")
			{
				debugSpam = value;
				NaturalSelectionLib.SetLibraryLoggers(Script.Logger, value, debugLibraryCalls, false);
			}
			if (entryKey == "debugLibraryTrigger")
			{
				debugLibraryCalls = value;
				NaturalSelectionLib.SetLibraryLoggers(Script.Logger, debugSpam, value, false);
			}
		}

		public static void SubscribeToConfigChanges()
		{
			Script.OnConfigSettingChanged = (Action<string, bool>)Delegate.Combine(Script.OnConfigSettingChanged, new Action<string, bool>(Event_OnConfigSettingChanged));
		}

		public static string DebugStringHead(object? source, bool shortFormat = true)
		{
			if (debugLibraryCalls)
			{
				Script.Logger.Log((LogLevel)16, (object)"Called library DebugStringHead!");
			}
			return NaturalSelectionLib.DebugStringHead(source, shortFormat);
		}

		public static List<EnemyAI> GetCompleteList(EnemyAI instance, bool FilterThemselves = true, int includeOrReturnThedDead = 0)
		{
			if (debugLibraryCalls)
			{
				Script.Logger.Log((LogLevel)16, (object)"Called library GetCompleteList!");
			}
			return NaturalSelectionLib.GetCompleteList(instance, FilterThemselves, includeOrReturnThedDead);
		}

		public static void GetInsideOrOutsideEnemyList(ref List<EnemyAI> importEnemyList, EnemyAI instance)
		{
			if (debugLibraryCalls)
			{
				Script.Logger.Log((LogLevel)16, (object)"Called library GetInsideOrOutsideEnemyList!");
			}
			NaturalSelectionLib.GetInsideOrOutsideEnemyList(ref importEnemyList, instance);
		}

		public static EnemyAI? FindClosestEnemy(ref List<EnemyAI> importEnemyList, EnemyAI? importClosestEnemy, EnemyAI instance, int maxIterations = 6, bool useThreatVisibility = true, bool usePathLenghtAsDistance = false, bool includeTheDead = false)
		{
			if (debugLibraryCalls)
			{
				Script.Logger.Log((LogLevel)16, (object)"Called library findClosestEnemy!");
			}
			return NaturalSelectionLib.FindClosestEnemy(ref importEnemyList, importClosestEnemy, instance, maxIterations, useThreatVisibility, usePathLenghtAsDistance, includeTheDead);
		}

		public static void FilterEnemyList(ref List<EnemyAI> importEnemyList, List<string>? blacklist, EnemyAI instance, bool filterOutImmortal = true, bool filterTheSameType = true)
		{
			if (debugLibraryCalls)
			{
				Script.Logger.LogInfo((object)"Called library filterEnemyList!");
			}
			if (debugLibraryCalls)
			{
				Script.Logger.Log((LogLevel)16, (object)"Called library filterEnemyList!");
			}
			NaturalSelectionLib.FilterEnemyList(ref importEnemyList, blacklist, instance, filterOutImmortal, filterTheSameType);
		}

		public static void FilterEnemySizes(ref Dictionary<EnemyAI, int> importEnemySizeDict, int[] enemySizes, EnemyAI instance, bool inverseToggle = false)
		{
			if (debugLibraryCalls)
			{
				Script.Logger.LogInfo((object)"Called library FilterEnemySizes!");
			}
			if (debugLibraryCalls)
			{
				Script.Logger.Log((LogLevel)16, (object)"Called library FilterEnemySizes!");
			}
			NaturalSelectionLib.FilterEnemySizes(ref importEnemySizeDict, enemySizes, instance, inverseToggle);
		}

		public static void FilterEnemySizes(ref List<EnemyAI> importEnemySizeDict, EnemySize[] enemySizes, EnemyAI instance, bool inverseToggle = false)
		{
			if (debugLibraryCalls)
			{
				Script.Logger.LogInfo((object)"Called library FilterEnemySizes!");
			}
			if (debugLibraryCalls)
			{
				Script.Logger.Log((LogLevel)16, (object)"Called library FilterEnemySizes!");
			}
			NaturalSelectionLib.FilterEnemySizes(ref importEnemySizeDict, enemySizes, instance, inverseToggle);
		}

		public static Dictionary<EnemyAI, float> GetEnemiesInLOS(EnemyAI instance, ref List<EnemyAI> importEnemyList, float width = 45f, int importRange = 0, float proximityAwareness = -1f, float importRadius = 0f, Vector3? importEyePosition = null)
		{
			if (debugLibraryCalls)
			{
				Script.Logger.Log((LogLevel)16, (object)"Called library GetEnemiesInLOS!");
			}
			return NaturalSelectionLib.GetEnemiesInLOS(instance, ref importEnemyList, width, (float)importRange, proximityAwareness, importRadius, importEyePosition);
		}

		public static Dictionary<EnemyAI, float> GetEnemiesInLOS(EnemyAI instance, float width = 45f, int importRange = 0, float proximityAwareness = -1f, float importRadius = 0f, Vector3? importEyePosition = null)
		{
			if (debugLibraryCalls)
			{
				Script.Logger.Log((LogLevel)16, (object)"Called library GetEnemiesInLOS!");
			}
			return NaturalSelectionLib.GetEnemiesInLOS(instance, width, (float)importRange, proximityAwareness, importRadius, importEyePosition);
		}

		public static IEnumerator FindClosestEnemyEnumerator(Action<EnemyAI>? ReturnOwnerResult, List<EnemyAI> importEnemyList, EnemyAI? importClosestEnemy, EnemyAI instance, int maxIterations = 6, bool useThreatVisibility = true, bool usePathLenghtAsDistance = false, bool includeTheDead = false)
		{
			return NaturalSelectionLib.FindClosestEnemy(ReturnOwnerResult, importEnemyList, importClosestEnemy, instance, maxIterations, useThreatVisibility, usePathLenghtAsDistance, includeTheDead);
		}

		public static List<EnemyAI> GetEnemyList(Type type)
		{
			return NaturalSelectionLib.GetEnemyList(type);
		}
	}
	internal class MyModConfig
	{
		public readonly ConfigEntry<bool> useExperimentalCoroutines;

		public readonly ConfigEntry<bool> usePathfindinglibCoroutines;

		public readonly ConfigEntry<bool> usePathToFindClosestEnemy;

		public readonly ConfigEntry<bool> sandwormCollisionOverride;

		public readonly ConfigEntry<float> blobAIOpeningDoorsMultiplier;

		public readonly ConfigEntry<bool> stableMode;

		public readonly ConfigEntry<bool> IgnoreImmortalEnemies;

		public readonly ConfigEntry<float> agentRadiusModifier;

		public readonly ConfigEntry<float> globalListsUpdateInterval;

		public readonly ConfigEntry<string> customSizeOverrideList;

		public readonly ConfigEntry<bool> enableSpider;

		public readonly ConfigEntry<bool> enableSlime;

		public readonly ConfigEntry<bool> enableLeviathan;

		public readonly ConfigEntry<bool> enableSporeLizard;

		public readonly ConfigEntry<bool> enableRedBees;

		public readonly ConfigEntry<bool> enableNutcracker;

		public readonly ConfigEntry<bool> enableGiant;

		public readonly ConfigEntry<bool> enableHoardingBug;

		public readonly ConfigEntry<float> beesSetGiantsOnFireMinChance;

		public readonly ConfigEntry<float> beesSetGiantsOnFireMaxChance;

		public readonly ConfigEntry<int> giantExtinguishChance;

		public readonly ConfigEntry<bool> blobConsumesCorpses;

		public readonly ConfigEntry<bool> blobPathfindToCorpses;

		public readonly ConfigEntry<bool> blobPathfind;

		public readonly ConfigEntry<bool> sandwormDoNotEatPlayersInsideLeavingShip;

		public readonly ConfigEntry<bool> enableSpiderWebs;

		public readonly ConfigEntry<string> speedModifierList;

		public readonly ConfigEntry<float> webStrength;

		public readonly ConfigEntry<float> chaseAfterEnemiesModifier;

		public readonly ConfigEntry<string> enemyNames;

		public readonly ConfigEntry<string> beeBlacklist;

		public readonly ConfigEntry<string> blobBlacklist;

		public readonly ConfigEntry<string> sandwormBlacklist;

		public readonly ConfigEntry<string> spiderWebBlacklist;

		public readonly ConfigEntry<string> spiderBlacklist;

		public ConfigEntry<bool> debugBool;

		public ConfigEntry<bool> debugKillSwitch;

		public ConfigEntry<bool> spammyLogs;

		public ConfigEntry<bool> debugTriggerFlags;

		public ConfigEntry<bool> debugNetworking;

		public ConfigEntry<bool> debugRedBees;

		public ConfigEntry<bool> debugSandworms;

		public ConfigEntry<bool> debugHygrodere;

		public ConfigEntry<bool> debugNutcrackers;

		public ConfigEntry<bool> debugSpiders;

		public ConfigEntry<bool> debugGiants;

		public ConfigEntry<bool> debugUnspecified;

		public ConfigEntry<bool> debugLibrary;

		public ConfigEntry<bool> debugLibraryTrigger;

		public ConfigEntry<bool> debugSpiderWebs;

		public Dictionary<string, ConfigEntry<bool>> debugEntries = new Dictionary<string, ConfigEntry<bool>>();

		public Dictionary<string, ConfigEntry<bool>> CompatibilityEntries = new Dictionary<string, ConfigEntry<bool>>();

		public ConfigEntry<bool> CompatibilityAutoToggle;

		public ConfigEntry<bool> enhancedMonstersCompToggle;

		public ConfigEntry<bool> sellBodiesFixedCompToggle;

		public ConfigEntry<bool> ReXuvinationCompToggle;

		public Dictionary<string, ConfigEntry<string>> enemyDict = new Dictionary<string, ConfigEntry<string>>();

		public MyModConfig(ConfigFile cfg)
		{
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Expected O, but got Unknown
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Expected O, but got Unknown
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Expected O, but got Unknown
			cfg.SaveOnConfigSet = false;
			sandwormCollisionOverride = cfg.Bind<bool>("Experimental Fixes", "Sandworm collision override", false, "Override vanilla sandworm collisions. May fix lag when sandworm collides with multiple enemies at once. \n \n May be removed in the future.");
			useExperimentalCoroutines = cfg.Bind<bool>("Experimental", "Enable experimental library coroutines", false, "Use experimental coroutines for finding closest enemy. May improve performance.");
			usePathfindinglibCoroutines = cfg.Bind<bool>("Experimental", "Enable pathfindinglib coroutines", false, "Use experimental pathfindinglib coroutines.");
			usePathToFindClosestEnemy = cfg.Bind<bool>("Experimental", "Use paths to find closest enemy", false, "Enemies will use pathfinding to find closest enemy. May be performance heavy.");
			stableMode = cfg.Bind<bool>("General Settings", "Toggle stable mode", true, "When true, the mod will exlude patches that are WIP or are experimental from loading. Requires restart.");
			IgnoreImmortalEnemies = cfg.Bind<bool>("General Settings", "Ignore Immortal Enemies", false, "All immortal enemies will be ignored by majority of entities.");
			agentRadiusModifier = cfg.Bind<float>("General Settings", "Agent radius modifier", 0.5f, "Modifies agent radius of entities for more reliable collisions.");
			globalListsUpdateInterval = cfg.Bind<float>("General Settings", "Global lists update interval", 1f, "Set a period how often are global lists updated. Default is one second.");
			customSizeOverrideList = cfg.Bind<string>("DEV", "Custom size override list", "", "Set what size the enemy is considered as. Generates automatically.");
			enableSpider = cfg.Bind<bool>("Entity settings", "Enable spider", true, "Enable changes to apply to to spider and modify it's behavior.");
			enableSlime = cfg.Bind<bool>("Entity settings", "Enable slime", true, "Enable changes to apply to to slime and modify it's behavior.");
			enableLeviathan = cfg.Bind<bool>("Entity settings", "Enable leviathan", true, "Enable changes to apply to to leviathan and modify it's behavior.");
			enableSporeLizard = cfg.Bind<bool>("DEV", "Enable SporeLizard", false, "Enable changes to apply to to spore lizard. \n\n Early build. DEV ONLY");
			enableRedBees = cfg.Bind<bool>("Entity settings", "Enable Red bees (Circuit bees)", true, "Enable changes to apply to red bees and modify it's behavior.");
			enableNutcracker = cfg.Bind<bool>("DEV", "Enable Nutcracker", false, "Enable changes to nutcracker to apply to and modify its behavior. \n\n Early build. DEV ONLY");
			enableGiant = cfg.Bind<bool>("Entity settings", "Enable Giant", true, "Enable changes to apply to to forest giant.");
			enableHoardingBug = cfg.Bind<bool>("DEV", "Enable Hoarding bug", false, "Enable changes to apply to to hoarding bug");
			enableSpiderWebs = cfg.Bind<bool>("Entity settings", "Enable Spider Webs", true, "Enables changes to apply to to spider webs. Webs will stick to and slow down enemies.");
			giantExtinguishChance = cfg.Bind<int>("Entity settings | Giant", "Extinguish chance", 33, new ConfigDescription("Chance of giants extinguishing themselves in percent.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			beesSetGiantsOnFireMinChance = cfg.Bind<float>("Entity settings | Giant", "Ignite giants min chace", 1.5f, new ConfigDescription("The minimum chance bees will set giant on fire on hit in percent. Applies to calm bees.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			beesSetGiantsOnFireMaxChance = cfg.Bind<float>("Entity settings | Giant", "Ignite giants max chace", 8f, new ConfigDescription("The minimum chance bees will set giant on fire on hit in percent. Applies to angry bees.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			blobConsumesCorpses = cfg.Bind<bool>("Entity settings | Hygrodere", "Consume corpses", true, "Hygrodere consume dead enemy corpses.");
			blobPathfindToCorpses = cfg.Bind<bool>("Entity settings | Hygrodere", "Pathfind to corpses", true, "Hygrodere move towards corpses to consume.");
			blobPathfind = cfg.Bind<bool>("Entity settings | Hygrodere", "Pathfind", true, "Pathfind to other entities.");
			blobAIOpeningDoorsMultiplier = cfg.Bind<float>("Entity settings | Hygrodere", "Open door multiplier", 0.7f, "Open door speed multiplier. Default value is vanilla.");
			sandwormDoNotEatPlayersInsideLeavingShip = cfg.Bind<bool>("Entity settings | Sandworm", "Do not eat players inside leaving ship", false, "Worms do not eat players inside ship leaving moon.");
			chaseAfterEnemiesModifier = cfg.Bind<float>("Entity settings | Spider/Spider Web", "Chase after enemies modifier", 3f, "Modifies chase timer for chasing enemies. When chasing another enemy, hunter's chase timer is divided by set number.");
			speedModifierList = cfg.Bind<string>("Entity settings | Spider/Spider Web", "Web speed modifiers", "", "Modifies final speed of enemy caught in web. \n \n [The ',' acts as a separator between each entry. Entry format: EnemyName:Speed ] \n This config generates automatically.");
			webStrength = cfg.Bind<float>("Entity settings | Spider/Spider Web", "Spider Web Strenght", 1.3f, "Strength of spider webs. Stronger spider web slows enemies more.");
			enemyNames = cfg.Bind<string>("Blacklists", "Enemy names", "", "List of enemy names. \n This config generates automatically.");
			beeBlacklist = cfg.Bind<string>("Blacklists", "Bees Blacklist", "", "Any enemy with set value to true will be ignored by circuit bees. \n \n [The Character ',' acts as a separator between each entry.]");
			blobBlacklist = cfg.Bind<string>("Blacklists", "Blob Blacklist", "", "Any enemy with set value to true will be ignored by hygroderes. \n \n [The Character ',' acts as a separator between each entry.]");
			sandwormBlacklist = cfg.Bind<string>("Blacklists", "Sandworm Blacklist", "", "Any enemy with set value to true will be ignored by sandworms. \n \n [The Character ',' acts as a separator between each entry.]");
			spiderWebBlacklist = cfg.Bind<string>("Blacklists", "Web blacklist", "", "Any enemy with set value to true will be ignored by webs. \n \n [The Character ',' acts as a separator between each entry.]");
			spiderBlacklist = cfg.Bind<string>("Blacklists", "Spider blacklist", "", "Any enemy with set value to true will be ignored by spider. \n \n [The Character ',' acts as a separator between each entry.]");
			debugBool = cfg.Bind<bool>("Debug", "Debug mode", false, "Enables debug mode for more debug logs. Can be changed at runtime via config mods.");
			debugEntries.Add("debugBool", debugBool);
			debugKillSwitch = cfg.Bind<bool>("Debug", "Debug killswitch", false, "Kills all debug logs");
			debugEntries.Add("debugKillSwitch", debugKillSwitch);
			spammyLogs = cfg.Bind<bool>("Debug", "Spammy logs", false, "Enables spammy logs for extra logs. Can be changed at runtime via config mods.");
			debugEntries.Add("spammyLogs", spammyLogs);
			debugNetworking = cfg.Bind<bool>("Debug", "Debug networking", false, "Enables debug logs for networking. Can be changed at runtime via config mods.");
			debugEntries.Add("debugNetworking", debugNetworking);
			debugTriggerFlags = cfg.Bind<bool>("Debug", "Trigger flags", false, "Enables logs with trigger flag.");
			debugEntries.Add("debugTriggerFlags", debugTriggerFlags);
			debugUnspecified = cfg.Bind<bool>("Debug", "Log unspecified", false, "Enables logs for unspecified. Can be changed at runtime via config mods.");
			debugEntries.Add("debugUnspecified", debugUnspecified);
			debugLibrary = cfg.Bind<bool>("Debug", "Log library", false, "Enables logs for the library. Can be changed at runtime via config mods.");
			debugEntries.Add("debugLibrary", debugLibrary);
			debugLibraryTrigger = cfg.Bind<bool>("Debug", "Log library trigger", false, "Enables logs for the library calls. Can be changed at runtime via config mods.");
			debugEntries.Add("debugLibraryTrigger", debugLibraryTrigger);
			debugRedBees = cfg.Bind<bool>("Debug", "Log bees", false, "Enables logs for bees. Can be changed at runtime via config mods.");
			debugEntries.Add("debugRedBees", debugRedBees);
			debugSandworms = cfg.Bind<bool>("Debug", "Log sandworms", false, "Enables logs for sandowrms. Can be changed at runtime via config mods.");
			debugEntries.Add("debugSandworms", debugSandworms);
			debugHygrodere = cfg.Bind<bool>("Debug", "Log hydrogere", false, "Enables logs for hydrogere. Can be changed at runtime via config mods.");
			debugEntries.Add("debugHygrodere", debugHygrodere);
			debugNutcrackers = cfg.Bind<bool>("Debug", "Log nutcrackers", false, "Enables logs for nutcrackers. Can be changed at runtime via config mods.");
			debugEntries.Add("debugNutcrackers", debugNutcrackers);
			debugSpiders = cfg.Bind<bool>("Debug", "Log spiders", false, "Enables logs for spiders. Can be changed at runtime via config mods.");
			debugEntries.Add("debugSpiders", debugSpiders);
			debugGiants = cfg.Bind<bool>("Debug", "Log giants", false, "Enables logs for giants. Can be changed at runtime via config mods.");
			debugEntries.Add("debugGiants", debugGiants);
			debugSpiderWebs = cfg.Bind<bool>("Debug", "Log spider webs", false, "Enables logs for spider webs. Can be changed at runtime via config mods.");
			debugEntries.Add("debugSpiderWebs", debugSpiderWebs);
			CompatibilityAutoToggle = cfg.Bind<bool>("Compatibility toggles", "Auto load compatibilities", true, "Automatically load compatibilites for detected mods");
			ReXuvinationCompToggle = cfg.Bind<bool>("Compatibility toggles", "ReXuvination compatibility", false, "Manually toggles compatibility patches for ReXuvination.");
			CompatibilityEntries.Add("XuuXiaolan.ReXuvination", ReXuvinationCompToggle);
			enhancedMonstersCompToggle = cfg.Bind<bool>("Compatibility toggles", "Enhanced monsters compatibility", false, "Manually toggles compatibility patches for Enhanced monsters.");
			CompatibilityEntries.Add("com.velddev.enhancedmonsters", enhancedMonstersCompToggle);
			sellBodiesFixedCompToggle = cfg.Bind<bool>("Compatibility toggles", "Sellbodiesfixed compatibility", false, "Manually toggles compatibility patches for Sellbodiesfixed.");
			CompatibilityEntries.Add("Entity378.sellbodies", sellBodiesFixedCompToggle);
			ClearOrphanedEntries(cfg);
			cfg.Save();
			cfg.SaveOnConfigSet = true;
		}

		public void ClearOrphanedEntries(ConfigFile cfg)
		{
			PropertyInfo propertyInfo = AccessTools.Property(typeof(ConfigFile), "OrphanedEntries");
			Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)propertyInfo.GetValue(cfg);
			foreach (KeyValuePair<ConfigDefinition, string> item in dictionary)
			{
				if (!item.Key.Section.Contains("!ORPHANED ENTRIES!"))
				{
					Script.Logger.LogFatal((object)("Found orphaned entry of " + item.Key.Section + ": " + item.Key.Key + ", " + item.Value + ". Orphaned entries will be cleared on the next bootup! All values in the settings within the orphaned entries will be lost!"));
					cfg.Bind<string>("!ORPHANED ENTRIES!", item.Key.Key, item.Value, "!THIS ORPHANED ENTRY WILL BE DELETED!");
				}
			}
			dictionary.Clear();
		}
	}
	internal class Networking_New : NetworkBehaviour
	{
	}
	public class Networking
	{
		public static Dictionary<string, Type> NetworkingDictionary = new Dictionary<string, Type>();

		private static bool logNetworking = Script.Bools["debugNetworking"];

		private static void Event_OnConfigSettingChanged(string entryKey, bool value)
		{
			if (entryKey == "debugNetworking")
			{
				logNetworking = value;
			}
		}

		public static void SubscribeToConfigChanges()
		{
			Script.OnConfigSettingChanged = (Action<string, bool>)Delegate.Combine(Script.OnConfigSettingChanged, new Action<string, bool>(Event_OnConfigSettingChanged));
		}

		public static LNetworkVariable<T> NSEnemyNetworkVariable<T>(string NWID)
		{
			if (!NetworkingDictionary.ContainsKey(NWID))
			{
				NetworkingDictionary.Add(NWID, typeof(T));
			}
			return LNetworkVariable<T>.Connect(NWID, default(T), (LNetworkVariableWritePerms)0, (Action<T, T>)null);
		}

		public static LNetworkEvent NSEnemyNetworkEvent(string NWID)
		{
			if (!NetworkingDictionary.ContainsKey(NWID))
			{
				NetworkingDictionary.Add(NWID, typeof(LNetworkEvent));
			}
			return LNetworkEvent.Connect(NWID, (Action<ulong>)null, (Action)null, (Action<ulong>)null);
		}

		public static void ClearSubscribtionsInDictionary()
		{
			foreach (KeyValuePair<string, Type> item in NetworkingDictionary)
			{
				if (item.Value == typeof(LNetworkEvent))
				{
					if (logNetworking)
					{
						Script.Logger.Log((LogLevel)32, (object)("Clearing subscriptions of event " + item.Key));
					}
					LNetworkEvent.Connect(item.Key, (Action<ulong>)null, (Action)null, (Action<ulong>)null).ClearSubscriptions();
					continue;
				}
				if (logNetworking)
				{
					Script.Logger.Log((LogLevel)32, (object)$"Disposing of network {item.Value} {item.Key}");
				}
				if (item.Value == typeof(int))
				{
					LNetworkVariable<int>.Connect(item.Key, 0, (LNetworkVariableWritePerms)0, (Action<int, int>)null).Dispose();
				}
				else if (item.Value == typeof(float))
				{
					LNetworkVariable<float>.Connect(item.Key, 0f, (LNetworkVariableWritePerms)0, (Action<float, float>)null).Dispose();
				}
				else if (item.Value == typeof(bool))
				{
					LNetworkVariable<bool>.Connect(item.Key, false, (LNetworkVariableWritePerms)0, (Action<bool, bool>)null).Dispose();
				}
				else
				{
					Script.Logger.Log((LogLevel)4, (object)$"Unsupported type {item.Value}");
				}
			}
			Script.Logger.Log((LogLevel)16, (object)"/Networking/ Finished clearing dictionary.");
			NetworkingDictionary.Clear();
		}
	}
	internal class NetworkingMethods
	{
		[HarmonyPatch(typeof(GameNetworkManager), "ResetGameValuesToDefault")]
		[HarmonyPostfix]
		private static void ResetGameValuesToDefaultPatch()
		{
			Script.Logger.Log((LogLevel)16, (object)"/ResetGameValuesToDefault/ Clearing all subscribtions, globalEnemyLists and data dictionaries.");
			Networking.ClearSubscribtionsInDictionary();
			NaturalSelectionLib.ClearAllEnemyLists();
			EnemyAIPatch.enemyDataDict.Clear();
		}

		[HarmonyPatch(typeof(RoundManager), "ResetEnemyVariables")]
		[HarmonyPostfix]
		private static void ResetEnemyVariablesPatch()
		{
			Script.Logger.Log((LogLevel)16, (object)"/ResetEnemyVariables/ Clearing all subscribtions, globalEnemyLists and data dictionaries.");
			Networking.ClearSubscribtionsInDictionary();
			NaturalSelectionLib.ClearAllEnemyLists();
			EnemyAIPatch.enemyDataDict.Clear();
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal class RoundManagerPatch
	{
		private static float nextUpdate = 0f;

		private static Dictionary<Type, List<EnemyAI>> checkedTypes = new Dictionary<Type, List<EnemyAI>>();

		public static float updateListInterval = Script.BoundingConfig.globalListsUpdateInterval.Value;

		private static bool logSpam = Script.Bools["spammyLogs"];

		private static bool logUnspecified = Script.Bools["debugNetworking"];

		public static List<GameObject> deadEnemiesList = new List<GameObject>();

		private static void Event_OnConfigSettingChanged(string entryKey, bool value)
		{
			if (entryKey == "debugNetworking")
			{
				logUnspecified = value;
			}
			if (entryKey == "spammyLogs")
			{
				logSpam = value;
			}
		}

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePostfixPatch()
		{
			Script.OnConfigSettingChanged = (Action<string, bool>)Delegate.Combine(Script.OnConfigSettingChanged, new Action<string, bool>(Event_OnConfigSettingChanged));
		}

		[HarmonyPatch("Update")]
		[HarmonyPrefix]
		private static void UpdatePatch()
		{
			if (!(Time.realtimeSinceStartup >= nextUpdate))
			{
				return;
			}
			foreach (Type item in checkedTypes.Keys.ToList())
			{
				NaturalSelectionLib.UpdateEnemyList(item, checkedTypes[item]);
			}
			checkedTypes.Clear();
			nextUpdate = Time.realtimeSinceStartup + updateListInterval;
		}

		public static bool RequestUpdate(EnemyAI instance)
		{
			if (!checkedTypes.ContainsKey(((object)instance).GetType()) && ((NetworkBehaviour)instance).IsOwner)
			{
				checkedTypes.Add(((object)instance).GetType(), new List<EnemyAI>());
				if (logUnspecified && logSpam)
				{
					Script.Logger.Log((LogLevel)8, (object)$"/RoundManager/ request was Accepted. Requested by {LibraryCalls.DebugStringHead(instance)} at {Time.realtimeSinceStartup}");
				}
				return true;
			}
			if (logUnspecified && logSpam && !((NetworkBehaviour)instance).IsOwner)
			{
				Script.Logger.Log((LogLevel)32, (object)"/RoundManager/ request was Denied. Not owner of the instance.");
			}
			else if (logUnspecified && logSpam)
			{
				Script.Logger.Log((LogLevel)32, (object)$"/RoundManager/ request was Denied. Requested by {LibraryCalls.DebugStringHead(instance)} at {Time.realtimeSinceStartup}");
			}
			return false;
		}

		public static void ScheduleGlobalListUpdate(EnemyAI instance, ref List<EnemyAI> list)
		{
			if (checkedTypes.ContainsKey(((object)instance).GetType()))
			{
				checkedTypes[((object)instance).GetType()] = list;
			}
			if (!NaturalSelectionLib.EnemyListContainsKey(((object)instance).GetType()))
			{
				Script.LogNS((LogLevel)4, LibraryCalls.DebugStringHead(instance) + " global enemy list for this enemy does not exist! Creating a new one.");
				NaturalSelectionLib.CreateEnemyList(((object)instance).GetType(), checkedTypes[((object)instance).GetType()]);
			}
			else
			{
				NaturalSelectionLib.UpdateEnemyList(((object)instance).GetType(), checkedTypes[((object)instance).GetType()]);
			}
		}
	}
	public enum CustomEnemySize
	{
		Undefined,
		Tiny,
		Small,
		Medium,
		Large,
		Giant
	}
	public class EnemyDataBase
	{
		private object? owner;

		private int CustomBehaviorStateIndex = 0;

		public EnemyAI? closestEnemy;

		public EnemyAI? targetEnemy;

		public CustomEnemySize customEnemySize = CustomEnemySize.Small;

		public string enemyID = "";

		internal Action<EnemyAI?>? ChangeClosestEnemyAction;

		private bool subscribed;

		public float coroutineTimer = 0f;

		public void SetOwner(object owner)
		{
			if (this.owner == null)
			{
				this.owner = owner;
			}
		}

		public void Subscribe()
		{
			if (!subscribed)
			{
				subscribed = true;
				ChangeClosestEnemyAction = (Action<EnemyAI>)Delegate.Combine(ChangeClosestEnemyAction, new Action<EnemyAI>(UpdateClosestEnemy));
			}
		}

		public void Unsubscribe()
		{
			if (subscribed)
			{
				ChangeClosestEnemyAction = (Action<EnemyAI>)Delegate.Remove(ChangeClosestEnemyAction, new Action<EnemyAI>(UpdateClosestEnemy));
			}
		}

		public void UpdateClosestEnemy(EnemyAI? importClosestEnemy)
		{
			if (owner == null)
			{
				Script.LogNS((LogLevel)4, "NULL owner! Unsubscribing...", owner);
				Unsubscribe();
			}
			closestEnemy = importClosestEnemy;
		}

		public void ReactToAttack(EnemyAI owner, EnemyAI attacker, int damage = 0)
		{
			Script.LogNS((LogLevel)16, $"{LibraryCalls.DebugStringHead(attacker)} hit {LibraryCalls.DebugStringHead(attacker)} with {damage} damage");
		}

		public string GetOrSetId(EnemyAI instance)
		{
			if (string.IsNullOrEmpty(enemyID))
			{
				enemyID = instance.enemyType.enemyName + ((NetworkBehaviour)instance).NetworkObjectId;
			}
			return enemyID;
		}

		public string GetOrSetId(string id)
		{
			if (string.IsNullOrEmpty(enemyID))
			{
				enemyID = id;
			}
			return enemyID;
		}

		public string GetOrSetId(SandSpiderWebTrap instance)
		{
			if (string.IsNullOrEmpty(enemyID))
			{
				enemyID = ((EnemyAI)instance.mainScript).enemyType.enemyName + ((NetworkBehaviour)instance.mainScript).NetworkObjectId + instance.trapID;
			}
			return enemyID;
		}

		public string GetOrSetId(GrabbableObject instance)
		{
			if (string.IsNullOrEmpty(enemyID))
			{
				enemyID = instance.itemProperties.itemName + ((NetworkBehaviour)instance).NetworkObjectId;
			}
			return enemyID;
		}
	}
	public class Utilities
	{
		public delegate bool IsEnemyReachableDelegate(EnemyAI enemy);

		public static Dictionary<string, EnemyDataBase> enemyDataDict = new Dictionary<string, EnemyDataBase>();

		public static bool IsEnemyReachable(EnemyAI enemy, IsEnemyReachableDelegate? outputDelegate = null)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if (enemy is CentipedeAI && ((CentipedeAI)enemy).clingingToCeiling)
			{
				return false;
			}
			if (enemy is SandWormAI)
			{
				return false;
			}
			if (enemy is DoublewingAI && ((DoublewingAI)enemy).flyLayerWeight > 0f)
			{
				return false;
			}
			if (enemy is RadMechAI && ((RadMechAI)enemy).inFlyingMode)
			{
				return false;
			}
			if (enemy is SandSpiderAI && ((SandSpiderAI)enemy).onWall)
			{
				return false;
			}
			return outputDelegate?.Invoke(enemy) ?? true;
		}

		public static bool IsEnemyVisible(EnemyAI enemy, Transform? checkFrom = null, IsEnemyReachableDelegate? outputDelegate = null)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (enemy is DressGirlAI)
			{
				return false;
			}
			if (enemy is ClaySurgeonAI)
			{
				if ((Object)(object)checkFrom != (Object)null)
				{
					return Vector3.Distance(((Component)enemy).transform.position, checkFrom.position) < 10f;
				}
				return false;
			}
			return outputDelegate?.Invoke(enemy) ?? true;
		}

		public static bool IsVanilla(EnemyAI checkInput)
		{
			Script.LogNS((LogLevel)32, checkInput.enemyType.enemyName + ">" + ((object)checkInput).GetType().Assembly.FullName, "IsVanillaCheck");
			return ((object)checkInput).GetType().Assembly.FullName == "Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
		}

		public static EnemyDataBase GetEnemyData(object __instance, EnemyDataBase enemyData, bool returnToEnemyAIType = false)
		{
			string dataID = GetDataID(__instance, returnToEnemyAIType);
			if (dataID == "-1" || __instance == null)
			{
				return null;
			}
			if (!enemyDataDict.ContainsKey(dataID))
			{
				Script.LogNS((LogLevel)16, "Missing data container for " + LibraryCalls.DebugStringHead(__instance) + ". Creating new data container...");
				enemyDataDict.Add(dataID, enemyData);
				enemyDataDict[dataID].SetOwner(__instance);
				enemyDataDict[dataID].Subscribe();
			}
			return enemyDataDict[dataID];
		}

		public static void TryGetEnemyData(object __instance, out EnemyDataBase temp, bool returnToEnemyAIType = false)
		{
			string dataID = GetDataID(__instance, returnToEnemyAIType);
			enemyDataDict.TryGetValue(dataID, out temp);
		}

		public static void DeleteData(object instance, bool returnToEnemyAIType = false)
		{
			string dataID = GetDataID(instance, returnToEnemyAIType);
			if (enemyDataDict.ContainsKey(dataID))
			{
				enemyDataDict.Remove(dataID);
			}
		}

		public static string GetDataID(object instance, bool returnToEnemyAIType = false)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			string text = "-1";
			if (instance is EnemyAI)
			{
				text = ((EnemyAI)instance).enemyType.enemyName + ((NetworkBehaviour)(EnemyAI)instance).NetworkObjectId;
				if (returnToEnemyAIType)
				{
					text += ".base";
				}
			}
			else if (instance is SandSpiderWebTrap)
			{
				text = ((EnemyAI)((SandSpiderWebTrap)instance).mainScript).enemyType.enemyName + ((NetworkBehaviour)((SandSpiderWebTrap)instance).mainScript).NetworkObjectId + "SpiderWeb" + ((SandSpiderWebTrap)instance).trapID;
			}
			else if (instance is string)
			{
				text = (string)instance;
			}
			return text;
		}
	}
}
namespace NaturalSelection.EnemyPatches
{
	internal class BeeValues : EnemyDataBase
	{
		internal Vector3 lastKnownEnemyPosition = Vector3.zero;

		internal int customBehaviorStateIndex = 0;

		internal Dictionary<EnemyAI, float> hitRegistry = new Dictionary<EnemyAI, float>();

		internal float LostLOSOfEnemy = 0f;

		internal float delayTimer = 0.2f;
	}
	[HarmonyPatch(typeof(RedLocustBees))]
	internal class BeeAIPatch
	{
		private static bool logBees = Script.Bools["debugRedBees"];

		private static bool debugSpam = Script.Bools["spammyLogs"];

		private static bool debugTriggers = Script.Bools["debugTriggerFlags"];

		private static List<string> beeBlacklist = InitializeGamePatch.beeBlacklist;

		private static void Event_OnConfigSettingChanged(string entryKey, bool value)
		{
			if (entryKey == "debugRedBees")
			{
				logBees = value;
			}
			if (entryKey == "spammyLogs")
			{
				debugSpam = value;
			}
			if (entryKey == "debugTriggerFlags")
			{
				debugTriggers = value;
			}
		}

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPatch(RedLocustBees __instance)
		{
			BeeValues beeValues = (BeeValues)Utilities.GetEnemyData(__instance, new BeeValues());
			Script.OnConfigSettingChanged = (Action<string, bool>)Delegate.Combine(Script.OnConfigSettingChanged, new Action<string, bool>(Event_OnConfigSettingChanged));
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void UpdatePatch(RedLocustBees __instance)
		{
			BeeValues beeValues = (BeeValues)Utilities.GetEnemyData(__instance, new BeeValues());
			if (RoundManagerPatch.RequestUpdate((EnemyAI)(object)__instance))
			{
				List<EnemyAI> importEnemyList = LibraryCalls.GetCompleteList((EnemyAI)(object)__instance);
				LibraryCalls.FilterEnemyList(ref importEnemyList, beeBlacklist, (EnemyAI)(object)__instance, Script.BoundingConfig.IgnoreImmortalEnemies.Value);
				RoundManagerPatch.ScheduleGlobalListUpdate((EnemyAI)(object)__instance, ref importEnemyList);
			}
			foreach (KeyValuePair<EnemyAI, float> item in new Dictionary<EnemyAI, float>(beeValues.hitRegistry))
			{
				if (item.Value > 1.7f)
				{
					beeValues.hitRegistry.Remove(item.Key);
				}
				else
				{
					beeValues.hitRegistry[item.Key] += Time.deltaTime;
				}
			}
		}

		[HarmonyPatch("DoAIInterval")]
		[HarmonyPrefix]
		private static bool DoAIIntervalPrefixPatch(RedLocustBees __instance)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			BeeValues beeValues = (BeeValues)Utilities.GetEnemyData(__instance, new BeeValues());
			if ((Object)(object)beeValues.targetEnemy != (Object)null && !((EnemyAI)__instance).movingTowardsTargetPlayer && beeValues.customBehaviorStateIndex != 0)
			{
				Script.LogNS((LogLevel)32, LibraryCalls.DebugStringHead(__instance) + " DoAIInterval: Prefix triggered false", __instance, logBees && debugSpam && debugTriggers);
				if (((EnemyAI)__instance).moveTowardsDestination)
				{
					((EnemyAI)__instance).agent.SetDestination(((EnemyAI)__instance).destination);
				}
				((EnemyAI)__instance).SyncPositionToClients();
				return false;
			}
			Script.LogNS((LogLevel)32, LibraryCalls.DebugStringHead(__instance) + " DoAIInterval: Prefix triggered true", __instance, logBees && debugSpam && debugTriggers);
			return true;
		}

		[HarmonyPatch("DoAIInterval")]
		[HarmonyPostfix]
		private static void DoAIIntervalPostfixPatch(RedLocustBees __instance)
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			//IL_0466: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Unknown result type (might be due to invalid IL or missing references)
			//IL_0475: Unknown result type (might be due to invalid IL or missing references)
			//IL_047a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0706: Unknown result type (might be due to invalid IL or missing references)
			//IL_0567: Unknown result type (might be due to invalid IL or missing references)
			//IL_0577: Unknown result type (might be due to invalid IL or missing references)
			//IL_0906: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0823: Unknown result type (might be due to invalid IL or missing references)
			//IL_0828: Unknown result type (might be due to invalid IL or missing references)
			//IL_082f: Unknown result type (might be due to invalid IL or missing references)
			//IL_059f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			if (((EnemyAI)__instance).isEnemyDead)
			{
				return;
			}
			BeeValues beeValues = (BeeValues)Utilities.GetEnemyData(__instance, new BeeValues());
			Type type = ((object)__instance).GetType();
			List<EnemyAI> importEnemyList = LibraryCalls.GetEnemyList(type);
			LibraryCalls.GetInsideOrOutsideEnemyList(ref importEnemyList, (EnemyAI)(object)__instance);
			Dictionary<EnemyAI, float> enemyDictionary = new Dictionary<EnemyAI, float>(LibraryCalls.GetEnemiesInLOS((EnemyAI)(object)__instance, ref importEnemyList, 360f, 16, 1f));
			switch (((EnemyAI)__instance).currentBehaviourStateIndex)
			{
			case 0:
				if (enemyDictionary.Count > 0)
				{
					beeValues.targetEnemy = enemyDictionary.Keys.First();
					Script.LogNS((LogLevel)16, LibraryCalls.DebugStringHead(__instance) + " case0: Checked LOS for enemies. Enemy found: " + LibraryCalls.DebugStringHead(beeValues.targetEnemy), __instance, logBees);
				}
				if (__instance.wasInChase)
				{
					__instance.wasInChase = false;
				}
				if (Vector3.Distance(((Component)__instance).transform.position, __instance.lastKnownHivePosition) > 2f)
				{
					((EnemyAI)__instance).SetDestinationToPosition(__instance.lastKnownHivePosition, true);
				}
				if (__instance.IsHiveMissing() || (Object)(object)__instance.hive.parentObject != (Object)null)
				{
					((EnemyAI)__instance).SwitchToBehaviourState(2);
					beeValues.customBehaviorStateIndex = 2;
					Script.LogNS((LogLevel)16, $"{LibraryCalls.DebugStringHead(__instance)} case0: HIVE IS MISSING! CustomBehaviorStateIndex changed: {beeValues.customBehaviorStateIndex}", __instance, logBees);
				}
				else if ((Object)(object)beeValues.targetEnemy != (Object)null && Vector3.Distance(((Component)beeValues.targetEnemy).transform.position, ((Component)__instance.hive).transform.position) < (float)__instance.defenseDistance)
				{
					((EnemyAI)__instance).SetDestinationToPosition(((Component)beeValues.targetEnemy).transform.position, true);
					Script.LogNS((LogLevel)16, $"{LibraryCalls.DebugStringHead(__instance)} case0: Moving towards {beeValues.targetEnemy}", __instance, logBees);
					beeValues.customBehaviorStateIndex = 1;
					((EnemyAI)__instance).SwitchToBehaviourState(1);
					beeValues.LostLOSOfEnemy = 0f;
					Script.LogNS((LogLevel)32, $"{LibraryCalls.DebugStringHead(__instance)} case0: CustomBehaviorStateIndex changed: {beeValues.customBehaviorStateIndex}", __instance, logBees);
				}
				break;
			case 1:
				if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && ((EnemyAI)__instance).movingTowardsTargetPlayer)
				{
					break;
				}
				if ((Object)(object)beeValues.targetEnemy == (Object)null || beeValues.targetEnemy.isEnemyDead || Vector3.Distance(((Component)beeValues.targetEnemy).transform.position, ((Component)__instance.hive).transform.position) > (float)__instance.defenseDistance + 5f)
				{
					beeValues.targetEnemy = null;
					__instance.wasInChase = false;
					if (__instance.IsHiveMissing() || (Object)(object)__instance.hive.parentObject != (Object)null)
					{
						beeValues.customBehaviorStateIndex = 2;
						((EnemyAI)__instance).SwitchToBehaviourState(2);
						Script.LogNS((LogLevel)16, $"{LibraryCalls.DebugStringHead(__instance)} case1: HIVE IS MISSING! CustomBehaviorStateIndex changed: {beeValues.customBehaviorStateIndex}", __instance, logBees);
					}
					else
					{
						beeValues.customBehaviorStateIndex = 0;
						((EnemyAI)__instance).SwitchToBehaviourState(0);
						Script.LogNS((LogLevel)32, $"{LibraryCalls.DebugStringHead(__instance)} case1: CustomBehaviorStateIndex changed: {beeValues.customBehaviorStateIndex}", __instance, logBees);
					}
				}
				else if ((Object)(object)__instance.hive.parentObject != (Object)null)
				{
					beeValues.customBehaviorStateIndex = 2;
					((EnemyAI)__instance).SwitchToBehaviourState(2);
				}
				else
				{
					((EnemyAI)__instance).SetDestinationToPosition(((Component)beeValues.targetEnemy).transform.position, true);
				}
				break;
			case 2:
			{
				if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null || ((EnemyAI)__instance).movingTowardsTargetPlayer)
				{
					Script.LogNS((LogLevel)32, LibraryCalls.DebugStringHead(__instance) + " case2: target player found or moving towards target player", __instance, logBees && debugSpam);
					break;
				}
				if (__instance.IsHivePlacedAndInLOS() && !Object.op_Implicit((Object)(object)__instance.hive.parentObject))
				{
					if (__instance.wasInChase)
					{
						__instance.wasInChase = false;
					}
					__instance.lastKnownHivePosition = ((Component)__instance.hive).transform.position + Vector3.up * 0.5f;
					Script.LogNS((LogLevel)32, LibraryCalls.DebugStringHead(__instance) + " case2: IsHivePlacedAndInLOS triggered", __instance, logBees);
					EnemyAI val = null;
					Collider[] array = Physics.OverlapSphere(((Component)__instance.hive).transform.position, (float)__instance.defenseDistance, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)2);
					if (array != null && array.Length != 0)
					{
						for (int i = 0; i < array.Length; i++)
						{
							EnemyAI component = ((Component)array[i]).gameObject.GetComponent<EnemyAI>();
							if ((Object)(object)component != (Object)null && (Object)(object)component != (Object)(object)__instance)
							{
								val = component;
								Script.LogNS((LogLevel)16, LibraryCalls.DebugStringHead(__instance) + " case2: CollisionArray triggered. Enemy found: " + LibraryCalls.DebugStringHead(val), __instance, logBees);
								break;
							}
						}
					}
					if ((Object)(object)val != (Object)null && Vector3.Distance(((Component)val).transform.position, ((Component)__instance.hive).transform.position) < (float)__instance.defenseDistance)
					{
						((EnemyAI)__instance).SetDestinationToPosition(((Component)val).transform.position, true);
						Script.LogNS((LogLevel)16, $"{LibraryCalls.DebugStringHead(__instance)} case2: Moving towards: {val}", __instance, logBees);
						beeValues.customBehaviorStateIndex = 1;
						((EnemyAI)__instance).SwitchToBehaviourState(1);
						__instance.syncedLastKnownHivePosition = false;
						__instance.SyncLastKnownHivePositionServerRpc(__instance.lastKnownHivePosition);
						beeValues.LostLOSOfEnemy = 0f;
						Script.LogNS((LogLevel)32, $"{LibraryCalls.DebugStringHead(__instance)} case2: CustomBehaviorStateIndex changed: {beeValues.customBehaviorStateIndex}", __instance, logBees);
					}
					else
					{
						beeValues.customBehaviorStateIndex = 0;
						((EnemyAI)__instance).SwitchToBehaviourState(0);
						Script.LogNS((LogLevel)32, $"{LibraryCalls.DebugStringHead(__instance)} case2: CustomBehaviorStateIndex changed: {beeValues.customBehaviorStateIndex}", __instance, logBees);
					}
					break;
				}
				bool flag = false;
				EnemyAI val2 = ChaseEnemyWithPriorities(ref enemyDictionary, __instance);
				Script.LogNS((LogLevel)32, $"{LibraryCalls.DebugStringHead(__instance)} case2: {val2} is closest to hive.", __instance, logBees);
				if ((Object)(object)val2 != (Object)null && (Object)(object)beeValues.targetEnemy != (Object)(object)val2)
				{
					flag = true;
					__instance.wasInChase = false;
					beeValues.targetEnemy = val2;
					((EnemyAI)__instance).SetDestinationToPosition(((Component)beeValues.targetEnemy).transform.position, true);
					((EnemyAI)__instance).StopSearch(__instance.searchForHive, true);
					__instance.syncedLastKnownHivePosition = false;
					beeValues.LostLOSOfEnemy = 0f;
					__instance.SyncLastKnownHivePositionServerRpc(__instance.lastKnownHivePosition);
					Script.LogNS((LogLevel)16, $"{LibraryCalls.DebugStringHead(__instance)} case2: Targeting {val2}. Synced hive position", __instance, logBees);
					break;
				}
				if ((Object)(object)beeValues.targetEnemy != (Object)null)
				{
					((EnemyAI)__instance).agent.acceleration = 16f;
					if (!flag && enemyDictionary.Count == 0)
					{
						Script.LogNS((LogLevel)32, $"{LibraryCalls.DebugStringHead(__instance)} case2: lost LOS of {beeValues.targetEnemy}, started timer.", __instance, logBees && debugSpam);
						beeValues.LostLOSOfEnemy += ((EnemyAI)__instance).AIIntervalTime;
						if (beeValues.LostLOSOfEnemy >= 4.5f)
						{
							beeValues.targetEnemy = null;
							beeValues.LostLOSOfEnemy = 0f;
							Script.LogNS((LogLevel)32, $"{LibraryCalls.DebugStringHead(__instance)} case2: lost LOS of {beeValues.targetEnemy}, Stopped and reset timer.", __instance, logBees);
						}
					}
					else
					{
						__instance.wasInChase = true;
						beeValues.lastKnownEnemyPosition = ((Component)beeValues.targetEnemy).transform.position;
						((EnemyAI)__instance).SetDestinationToPosition(beeValues.lastKnownEnemyPosition, true);
						beeValues.LostLOSOfEnemy = 0f;
						Script.LogNS((LogLevel)32, $"{LibraryCalls.DebugStringHead(__instance)} case2: lost {beeValues.targetEnemy}", __instance, logBees);
					}
					break;
				}
				((EnemyAI)__instance).agent.acceleration = 13f;
				if (!__instance.searchForHive.inProgress)
				{
					Script.LogNS((LogLevel)16, LibraryCalls.DebugStringHead(__instance) + " case2: set new search for hive", __instance, logBees);
					if (__instance.wasInChase)
					{
						((EnemyAI)__instance).StartSearch(beeValues.lastKnownEnemyPosition, __instance.searchForHive);
						Script.LogNS((LogLevel)32, LibraryCalls.DebugStringHead(__instance) + " case2: Started search for hive.", __instance, logBees);
					}
					else
					{
						((EnemyAI)__instance).StartSearch(((Component)__instance).transform.position, __instance.searchForHive);
						Script.LogNS((LogLevel)32, LibraryCalls.DebugStringHead(__instance) + " case2: Started search for hive.", __instance, logBees);
					}
				}
				break;
			}
			}
		}

		private static LNetworkVariable<float> NSSetOnFireChance(RedLocustBees instance)
		{
			string nWID = "NSSetOnFireChance" + ((NetworkBehaviour)instance).NetworkObjectId;
			return Networking.NSEnemyNetworkVariable<float>(nWID);
		}

		private static LNetworkVariable<float> NSSetOnFireMaxChance(RedLocustBees instance)
		{
			string nWID = "NSSetOnFireMaxChance" + ((NetworkBehaviour)instance).NetworkObjectId;
			return Networking.NSEnemyNetworkVariable<float>(nWID);
		}

		private static LNetworkEvent NetworkSetGiantOnFire(ForestGiantAI forestGiantAI)
		{
			string nWID = "NSSetGiantOnFire" + ((NetworkBehaviour)forestGiantAI).NetworkObjectId;
			return Networking.NSEnemyNetworkEvent(nWID);
		}

		public static void OnCustomEnemyCollision(RedLocustBees __instance, EnemyAI mainscript2)
		{
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Expected O, but got Unknown
			if (((object)mainscript2).GetType() == typeof(RedLocustBees))
			{
				return;
			}
			BeeValues beeValues = (BeeValues)Utilities.GetEnemyData(__instance, new BeeValues());
			if (!Utilities.enemyDataDict.ContainsKey(beeValues.enemyID) || beeBlacklist.Contains(mainscript2.enemyType.enemyName) || (((beeValues.hitRegistry.ContainsKey(mainscript2) && !(beeValues.hitRegistry[mainscript2] > 1.7f)) || ((EnemyAI)__instance).currentBehaviourStateIndex <= 0 || mainscript2.isEnemyDead) && ((beeValues.hitRegistry.ContainsKey(mainscript2) && !(beeValues.hitRegistry[mainscript2] > 1.2f)) || ((EnemyAI)__instance).currentBehaviourStateIndex != 2 || mainscript2.isEnemyDead)))
			{
				return;
			}
			mainscript2.HitEnemy(1, (PlayerControllerB)null, true, -1);
			if (!beeValues.hitRegistry.ContainsKey(mainscript2))
			{
				beeValues.hitRegistry.Add(mainscript2, 0f);
			}
			else
			{
				beeValues.hitRegistry[mainscript2] = 0f;
			}
			if (!(mainscript2 is ForestGiantAI) || mainscript2.currentBehaviourStateIndex == 2)
			{
				return;
			}
			if (((NetworkBehaviour)__instance).IsOwner)
			{
				NSSetOnFireChance(__instance).Value = Random.Range(0f, 100f);
				if (((EnemyAI)__instance).currentBehaviourStateIndex != 2)
				{
					NSSetOnFireMaxChance(__instance).Value = Script.BoundingConfig.beesSetGiantsOnFireMinChance.Value;
				}
				else
				{
					NSSetOnFireMaxChance(__instance).Value = Script.BoundingConfig.beesSetGiantsOnFireMaxChance.Value;
				}
				Script.LogNS((LogLevel)16, $"{LibraryCalls.DebugStringHead(__instance)} OnCustomEnemyCollision: Giant hit. Chance to set on fire: {NSSetOnFireMaxChance(__instance).Value} , rolled {NSSetOnFireChance(__instance)}", __instance);
			}
			else
			{
				Script.LogNS((LogLevel)8, "Client not elligible to determine chance to set giant on fire", __instance, logBees);
			}
			if (NSSetOnFireChance(__instance).Value <= NSSetOnFireMaxChance(__instance).Value && ((NetworkBehaviour)__instance).IsOwner)
			{
				Script.LogNS((LogLevel)16, $"{LibraryCalls.DebugStringHead(__instance)} OnCustomEnemyCollision: SET GIANT ON FIRE! Random number: {NSSetOnFireChance(__instance).Value}", __instance);
				ForestGiantAI forestGiantAI = (ForestGiantAI)mainscript2;
				NetworkSetGiantOnFire(forestGiantAI).InvokeServer();
			}
		}

		public static EnemyAI? ChaseEnemyWithPriorities(ref Dictionary<EnemyAI, float> enemyDictionary, RedLocustBees instance)
		{
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			EnemyAI val = null;
			if (enemyDictionary.Count < 1)
			{
				return null;
			}
			foreach (KeyValuePair<EnemyAI, float> item in enemyDictionary)
			{
				if ((Object)(object)item.Key == (Object)(object)instance)
				{
					continue;
				}
				IVisibleThreat component = ((Component)item.Key).GetComponent<IVisibleThreat>();
				if (component != null && (Object)(object)component.GetHeldObject() != (Object)null && (Object)(object)component.GetHeldObject() == (Object)(object)instance.hive && !component.IsThreatDead())
				{
					if (debugTriggers)
					{
						Script.LogNS((LogLevel)16, "ChaseEnemiesWithPriorities: Returning " + LibraryCalls.DebugStringHead(item.Key) + " |threatComp|", instance);
					}
					return item.Key;
				}
				if ((Object)(object)instance.hive.parentObject != (Object)null && (Object)(object)((Component)instance.hive.parentObject).gameObject.GetComponentInParent<EnemyAI>() == (Object)(object)item.Key)
				{
					if (debugTriggers)
					{
						Script.LogNS((LogLevel)16, "ChaseEnemiesWithPriorities: Returning " + LibraryCalls.DebugStringHead(item.Key) + " |GetComponentInParent|", instance);
					}
					return item.Key;
				}
				if (instance.IsHivePlacedAndInLOS() && !item.Key.isEnemyDead)
				{
					if ((Object)(object)val == (Object)null)
					{
						val = item.Key;
					}
					else if (Vector3.Distance(((Component)item.Key).transform.position, ((Component)instance.hive).transform.position) < Vector3.Distance(((Component)val).transform.position, ((Component)instance.hive).transform.position))
					{
						val = item.Key;
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = enemyDictionary.Keys.First();
			}
			if (debugTriggers)
			{
				Script.LogNS((LogLevel)16, "ChaseEnemiesWithPriorities: Returning " + LibraryCalls.DebugStringHead(val) + " |returnEnemy|", instance);
			}
			return val;
		}
	}
	internal class BlobData : EnemyDataBase
	{
		internal bool playSound = false;

		internal Dictionary<EnemyAI, float> hitRegistry = new Dictionary<EnemyAI, float>();
	}
	[HarmonyPatch(typeof(BlobAI))]
	internal class BlobAIPatch
	{
		private static bool logBlob = Script.Bools["debugHygrodere"];

		private static bool triggerFlag = Script.Bools["debugTriggerFlags"];

		private static List<string> blobBlacklist = InitializeGamePatch.blobBlacklist;

		private static LNetworkEvent BlobEatCorpseEvent(BlobAI instance)
		{
			string nWID = "NSSlimeEatEvent" + ((NetworkBehaviour)instance).NetworkObjectId;
			return Networking.NSEnemyNetworkEvent(nWID);
		}

		private static void Event_OnConfigSettingChanged(string entryKey, bool value)
		{
			if (entryKey == "debugHygrodere")
			{
				logBlob = value;
			}
			if (entryKey == "debugTriggerFlags")
			{
				triggerFlag = value;
			}
		}

		[HarmonyPatch("Start")]
		[HarmonyPrefix]
		private static void StartPatch(BlobAI __instance)
		{
			BlobAI __instance2 = __instance;
			BlobData blobData = (BlobData)Utilities.GetEnemyData(__instance2, new BlobData());
			blobData.SetOwner(__instance2);
			blobData.Subscribe();
			((EnemyAI)__instance2).enemyType.doorSpeedMultiplier = Script.BoundingConfig.blobAIOpeningDoorsMultiplier.Value;
			BlobEatCorpseEvent(__instance2).OnClientReceived += EventReceived;
			BlobData blobData2 = blobData;
			blobData2.ChangeClosestEnemyAction = (Action<EnemyAI>)Delegate.Combine(blobData2.ChangeClosestEnemyAction, new Action<EnemyAI>(getClosestEnemyResult));
			Script.OnConfigSettingChanged = (Action<string, bool>)Delegate.Combine(Script.OnConfigSettingChanged, new Action<string, bool>(Event_OnConfigSettingChanged));
			void EventReceived()
			{
				blobData.playSound = true;
			}
			void getClosestEnemyResult(EnemyAI? closestEnemy)
			{
				Script.LogNS((LogLevel)16, $"Set {closestEnemy} as closestEnemy", __instance2);
				Utilities.GetEnemyData(__instance2, new BlobData()).closestEnemy = closestEnemy;
			}
		}

		[HarmonyPatch("DoAIInterval")]
		[HarmonyPrefix]
		private static bool DoAIIntervalPrefixPatch(BlobAI __instance)
		{
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: 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_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			if (((EnemyAI)__instance).isEnemyDead)
			{
				return true;
			}
			BlobData blobData = (BlobData)Utilities.GetEnemyData(__instance, new BlobData());
			if (Script.BoundingConfig.blobPathfind.Value)
			{
				GameObject val = null;
				if (RoundManagerPatch.deadEnemiesList.Count > 0)
				{
					foreach (GameObject deadEnemies in RoundManagerPatch.deadEnemiesList)
					{
						if ((Object)(object)val == (Object)null || Vector3.Distance(val.transform.position, ((Component)__instance).transform.position) > Vector3.Distance(deadEnemies.transform.position, ((Component)__instance).transform.position))
						{
							val = deadEnemies;
						}
					}
				}
				if (((Object)(object)((EnemyAI)__instance).GetClosestPlayer(false, false, false) != (Object)null && (!((EnemyAI)__instance).PlayerIsTargetable(((EnemyAI)__instance).GetClosestPlayer(false, false, false), false, false) || ((Object)(object)blobData.closestEnemy != (Object)null && Vector3.Distance(((Component)blobData.closestEnemy).transform.position, ((Component)__instance).transform.position) < Vector3.Distance(((Component)((EnemyAI)__instance).GetClosestPlayer(false, false, false)).transform.position, ((Component)__instance).transform.position)) || ((Object)(object)val != (Object)null && Vector3.Distance(val.transform.position, ((Component)__instance).transform.position) < Vector3.Distance(((Component)((EnemyAI)__instance).GetClosestPlayer(false, false, false)).transform.position, ((Component)__instance).transform.position)))) || (Object)(object)((EnemyAI)__instance).GetClosestPlayer(false, false, false) == (Object)null)
				{
					if (((EnemyAI)__instance).moveTowardsDestination)
					{
						((EnemyAI)__instance).agent.SetDestination(((EnemyAI)__instance).destination);
					}
					((EnemyAI)__instance).SyncPositionToClients();
					if (__instance.searchForPlayers.inProgress)
					{
						((EnemyAI)__instance).StopSearch(__instance.searchForPlayers, true);
					}
					if ((Object)(object)blobData.closestEnemy != (Object)null)
					{
						float num = Vector3.Distance(((Component)blobData.closestEnemy).transform.position, ((Component)__instance).transform.position);
						float num2 = 0f;
						if ((Object)(object)val != (Object)null)
						{
							num2 = Vector3.Distance(val.transform.position, ((Component)__instance).transform.position);
						}
						if ((Object)(object)val != (Object)null && num > num2)
						{
							((EnemyAI)__instance).SetDestinationToPosition(val.transform.position, true);
						}
						else
						{
							((EnemyAI)__instance).SetDestinationToPosition(((Component)blobData.closestEnemy).transform.position, true);
						}
					}
					else if ((Object)(object)val != (Object)null)
					{
						((EnemyAI)__instance).SetDestinationToPosition(val.transform.position, true);
					}
					return false;
				}
			}
			return true;
		}

		[HarmonyPatch("Update")]
		[HarmonyPrefix]
		private static void BlobUpdatePatch(BlobAI __instance)
		{
			if (((EnemyAI)__instance).isEnemyDead)
			{
				return;
			}
			BlobData blobData = (BlobData)Utilities.GetEnemyData(__instance, new BlobData());
			Type type = ((object)__instance).GetType();
			foreach (KeyValuePair<EnemyAI, float> item in new Dictionary<EnemyAI, float>(blobData.hitRegistry))
			{
				if (item.Value > 1.5f)
				{
					blobData.hitRegistry.Remove(item.Key);
				}
				else
				{
					blobData.hitRegistry[item.Key] += Time.deltaTime;
				}
			}
			if (RoundManagerPatch.RequestUpdate((EnemyAI)(object)__instance))
			{
				List<EnemyAI> importEnemyList = LibraryCalls.GetCompleteList((EnemyAI)(object)__instance, FilterThemselves: true, 1);
				LibraryCalls.FilterEnemyList(ref importEnemyList, blobBlacklist, (EnemyAI)(object)__instance);
				RoundManagerPatch.ScheduleGlobalListUpdate((EnemyAI)(object)__instance, ref importEnemyList);
			}
			if (((NetworkBehaviour)__instance).IsOwner)
			{
				List<EnemyAI> importEnemyList2 = NaturalSelectionLib.GetEnemyList(type);
				LibraryCalls.GetInsideOrOutsideEnemyList(ref importEnemyList2, (EnemyAI)(object)__instance);
				if (Script.BoundingConfig.useExperimentalCoroutines.Value)
				{
					if (blobData.coroutineTimer < Time.realtimeSinceStartup)
					{
						((MonoBehaviour)__instance).StartCoroutine(LibraryCalls.FindClosestEnemyEnumerator(blobData.ChangeClosestEnemyAction, importEnemyList2, blobData.closestEnemy, (EnemyAI)(object)__instance, 6, useThreatVisibility: true, Script.usePathToFindClosestEnemy));
						blobData.coroutineTimer = Time.realtimeSinceStartup + 0.2f;
					}
				}
				else
				{
					blobData.closestEnemy = LibraryCalls.FindClosestEnemy(ref importEnemyList2, blobData.closestEnemy, (EnemyAI)(object)__instance, 6, useThreatVisibility: true, Script.usePathToFindClosestEnemy);
				}
			}
			if (blobData.playSound)
			{
				Script.LogNS((LogLevel)8, "Playing sound.", __instance);
				((EnemyAI)__instance).creatureVoice.PlayOneShot(__instance.killPlayerSFX);
				blobData.playSound = false;
			}
		}

		public static void OnCustomEnemyCollision(BlobAI __instance, EnemyAI mainscript2)
		{
			//IL_005a: 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)
			BlobData blobData = (BlobData)Utilities.GetEnemyData(__instance, new BlobData());
			if (blobData.hitRegistry.ContainsKey(mainscript2) || blobBlacklist.Contains(mainscript2.enemyType.enemyName))
			{
				return;
			}
			if (mainscript2.isEnemyDead && !IsEnemyImmortal.EnemyIsImmortal(mainscript2) && Vector3.Distance(((Component)__instance).transform.position, ((Component)mainscript2).transform.position) <= 2.8f && Script.BoundingConfig.blobConsumesCorpses.Value)
			{
				if (((NetworkBehaviour)__instance).IsOwner && mainscript2.thisNetworkObject.IsSpawned)
				{
					BlobEatCorpseEvent(__instance).InvokeClients();
					Script.LogNS((LogLevel)8, "consumed dead body of " + mainscript2.enemyType.enemyName, __instance);
					mainscript2.thisNetworkObject.Despawn(true);
				}
			}
			else
			{
				if (mainscript2.isEnemyDead || mainscript2 is NutcrackerEnemyAI || mainscript2 is CaveDwellerAI)
				{
					return;
				}
				blobData.hitRegistry.Add(mainscript2, 0f);
				if (mainscript2 is FlowermanAI)
				{
					FlowermanAI val = (FlowermanAI)(object)((mainscript2 is FlowermanAI) ? mainscript2 : null);
					if ((Object)(object)val != (Object)null)
					{
						float angerMeter = val.angerMeter;
						bool isInAngerMode = val.isInAngerMode;
						((EnemyAI)val).HitEnemy(1, (PlayerControllerB)null, true, -1);
						if (mainscript2.enemyHP <= 0)
						{
							mainscript2.KillEnemyOnOwnerClient(false);
						}
						((EnemyAI)val).targetPlayer = null;
						((EnemyAI)val).movingTowardsTargetPlayer = false;
						val.isInAngerMode = false;
						val.angerMeter = angerMeter;
						val.isInAngerMode = isInAngerMode;
						return;
					}
				}
				if (mainscript2 is HoarderBugAI)
				{
					HoarderBugAI val2 = (HoarderBugAI)(object)((mainscript2 is HoarderBugAI) ? mainscript2 : null);
					if ((Object)(object)val2 != (Object)null)
					{
						HoarderBugPatch.CustomOnHit(1, (EnemyAI)(object)__instance, playHitSFX: false, val2);
						if (mainscript2.enemyHP <= 0)
						{
							mainscript2.KillEnemyOnOwnerClient(false);
						}
					}
				}
				else
				{
					mainscript2.HitEnemy(1, (PlayerControllerB)null, true, -1);
					if (mainscript2.enemyHP <= 0)
					{
						mainscript2.KillEnemyOnOwnerClient(false);
					}
				}
			}
		}

		public static void OnEnemyCorpseCollision(BlobAI __instance, GameObject corpse)
		{
			NetworkObject component = corpse.GetComponent<NetworkObject>();
			if (((NetworkBehaviour)__instance).IsOwner && component.IsSpawned)
			{
				BlobEatCorpseEvent(__instance).InvokeClients();
				Script.LogNS((LogLevel)8, "consumed dead body " + LibraryCalls.DebugStringHead(corpse), __instance);
				component.Despawn(true);
			}
		}
	}
	internal class OnCollideWithUniversal
	{
		private class EnemyCollisionData
		{
			internal bool subscribed = false;
		}

		private static bool enableSpider = Script.BoundingConfig.enableSpider.Value;

		private static bool enableSlime = Script.BoundingConfig.enableSlime.Value;

		private static bool enableBees = Script.BoundingConfig.enableRedBees.Value;

		private static bool logUnspecified = Script.Bools["debugUnspecified"];

		private static bool triggerFlag = Script.Bools["debugTriggerFlags"];

		private static bool debugSpam = Script.Bools["spammyLogs"];

		private static void Event_OnConfigSettingChanged()
		{
			logUnspecified = Script.Bools["debugUnspecified"];
			debugSpam = Script.Bools["spammyLogs"];
			triggerFlag = Script.Bools["debugTriggerFlags"];
		}

		public static void Collide(string text, EnemyAI? mainscript, EnemyAI? mainscript2, GameObject? gameObject = null)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Expected O, but got Unknown
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			if (logUnspecified && debugSpam && triggerFlag)
			{
				Script.Logger.Log((LogLevel)32, (object)(LibraryCalls.DebugStringHead(mainscript) + " hit collider of " + LibraryCalls.DebugStringHead(mainscript2) + " Tag: " + text));
			}
			if (!((Object)(object)mainscript != (Object)null) || text == "Player")
			{
			}
			if ((Object)(object)mainscript != (Object)null && text == "Corpse" && mainscript is BlobAI && enableSlime && (Object)(object)gameObject != (Object)null)
			{
				BlobAIPatch.OnEnemyCorpseCollision((BlobAI)mainscript, gameObject);
			}
			if ((Object)(object)mainscript != (Object)null && (Object)(object)mainscript2 != (Object)null)
			{
				if (mainscript is SandSpiderAI && (Object)(object)mainscript2 != (Object)null && enableSpider)
				{
					SandSpiderAIPatch.OnCustomEnemyCollision((SandSpiderAI)mainscript, mainscript2);
				}
				if (mainscript is BlobAI && (Object)(object)mainscript2 != (Object)null && enableSlime)
				{
					BlobAIPatch.OnCustomEnemyCollision((BlobAI)mainscript, mainscript2);
				}
				if (mainscript is RedLocustBees && (Object)(object)mainscript2 != (Object)null && enableBees)
				{
					BeeAIPatch.OnCustomEnemyCollision((RedLocustBees)mainscript, mainscript2);
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyAICollisionDetect))]
	public class AICollisionDetectPatch
	{
		[HarmonyPatch("OnTriggerStay")]
		[HarmonyPrefix]
		private static bool OnTriggerStayPrefix(Collider other, EnemyAICollisionDetect __instance)
		{
			if ((Object)(object)other == (Object)null)
			{
				Script.Logger.Log((LogLevel)2, (object)(LibraryCalls.DebugStringHead(__instance.mainScript) + " Collider is null! Using original function..."));
				return true;
			}
			EnemyAICollisionDetect component = ((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>();
			if ((Object)(object)__instance != (Object)null)
			{
				EnemyAI val = null;
				DeadBodyTrackerScript component2 = ((Component)other).GetComponent<DeadBodyTrackerScript>();
				if ((Object)(object)component2 != (Object)null)
				{
					if (Script.Bools["spammyLogs"] && Script.Bools["debugTriggerFlags"])
					{
						Script.Logger.LogInfo((object)"Collided with corpse");
					}
					OnCollideWithUniversal.Collide("Corpse", __instance.mainScript, null, ((Component)component2).gameObject);
				}
				if (((Component)other).CompareTag("Player") && !__instance.mainScript.isEnemyDead)
				{
					OnCollideWithUniversal.Collide("Player", null, null);
					return true;
				}
				if ((Object)(object)component != (Object)null)
				{
					val = ((!((Object)(object)component?.mainScript == (Object)null)) ? ((Component)other).gameObject.GetComponentInParent<EnemyAI>() : component?.mainScript);
					if (((Component)other).CompareTag("Enemy") && (Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)__instance.mainScript && !IsEnemyImmortal.EnemyIsImmortal(val) && !__instance.mainScript.isEnemyDead)
					{
						OnCollideWithUniversal.Collide("Enemy", __instance.mainScript, val);
						return true;
					}
				}
			}
			return true;
		}
	}
	public class IsEnemyImmortal
	{
		public static bool EnemyIsImmortal(EnemyAI instance)
		{
			if (instance is NutcrackerEnemyAI && instance.currentBehaviourStateIndex == 0)
			{
				return true;
			}
			if (instance is JesterAI)
			{
				return true;
			}
			if (instance is BlobAI)
			{
				return true;
			}
			if (instance is SpringManAI)
			{
				return true;
			}
			if (instance is SandWormAI)
			{
				return true;
			}
			if (instance is ButlerBeesEnemyAI)
			{
				return true;
			}
			return false;
		}
	}
	internal class EnemyData : EnemyDataBase
	{
		internal float originalAgentRadius = 0f;
	}
	[HarmonyPatch(typeof(EnemyAI))]
	internal class EnemyAIPatch
	{
		private static bool debugUnspecified = Script.Bools["debugUnspecified"];

		private static bool debugTriggerFlags = Script.Bools["debugTriggerFlags"];

		public static Dictionary<string, EnemyDataBase> enemyDataDict = new Dictionary<string, EnemyDataBase>();

		private static void Event_OnConfigSettingChanged(string entryKey, bool value)
		{
			if (entryKey == "debugUnspecified")
			{
				debugUnspecified = value;
			}
			if (entryKey == "debugTriggerFlags")
			{
				debugTriggerFlags = value;
			}
		}

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPostfix(EnemyAI __instance)
		{
			EnemyData enemyData = (EnemyData)Utilities.GetEnemyData(__instance, new EnemyData(), returnToEnemyAIType: true);
			enemyData.originalAgentRadius = __instance.agent.radius;
			if (InitializeGamePatch.customSizeOverrideListDictionary.ContainsKey(__instance.enemyType.enemyName))
			{
				enemyData.customEnemySize = (CustomEnemySize)InitializeGamePatch.customSizeOverrideListDictionary[__instance.enemyType.enemyName];
			}
			Script.LogNS((LogLevel)32, $"Final size: {enemyData.customEnemySize}", __instance);
			__instance.agent.radius = __instance.agent.radius * Script.BoundingConfig.agentRadiusModifier.Value;
			Script.LogNS((LogLevel)8, $"Modified agent radius. Original: {enemyData.originalAgentRadius}, Modified: {__instance.agent.radius}", null, debugUnspecified && debugTriggerFlags);
			Script.OnConfigSettingChanged = (Action<string, bool>)Delegate.Combine(Script.OnConfigSettingChanged, new Action<string, bool>(Event_OnConfigSettingChanged));
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPostfix]
		private static void OnDestroyPostfix(EnemyAI __instance)
		{
			Script.LogNS((LogLevel)32, LibraryCalls.DebugStringHead(__instance) + " destroyed. Unsubscribing and destroying data containers...", __instance);
			Utilities.TryGetEnemyData(__instance, out EnemyDataBase temp);
			Utilities.TryGetEnemyData(__instance, out EnemyDataBase temp2, returnToEnemyAIType: true);
			if (temp2 != null)
			{
				temp2.Unsubscribe();
				Utilities.DeleteData(Utilities.GetDataID(__instance, returnToEnemyAIType: true));
			}
			if (temp != null)
			{
				temp.Unsubscribe();
				Utilities.DeleteData(Utilities.GetDataID(__instance));
			}
		}

		public static int ReactToHit(int force = 0, EnemyAI? enemyAI = null, PlayerControllerB? player = null)
		{
			if (force > 0)
			{
				return 1;
			}
			if (force > 1)
			{
				return 2;
			}
			return 0;
		}

		[HarmonyPatch("HitEnemy")]
		[HarmonyPostfix]
		public static void HitEnemyPatch(EnemyAI __instance, int force, PlayerControllerB playerWhoHit, bool playHitSFX, int hitID)
		{
			string text = "unknown";
			if ((Object)(object)playerWhoHit != (Object)null)
			{
				text = $"{playerWhoHit.playerUsername}(SteamID: {playerWhoHit.playerSteamId}, playerClientID: {playerWhoHit.playerClientId})";
			}
			Script.LogNS((LogLevel)16, $"registered hit by {text} with force of {force}. playHitSFX:{playHitSFX}, hitID:{hitID}.", __instance, debugTriggerFlags);
		}

		public static void ReactToAttack(EnemyAI instance, Collider other)
		{
			string _instance = ((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>().mainScript.enemyType.enemyName + ((NetworkBehaviour)((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>().mainScript).NetworkObjectId;
			Utilities.TryGetEnemyData(_instance, out EnemyDataBase temp);
			temp?.ReactToAttack(instance, ((Component)other).gameObject.GetComponent<EnemyAICollisionDetect>().mainScript, 1);
		}
	}
	public class ReversePatchAI
	{
		public static Action<EnemyAI> originalUpdate;

		static ReversePatchAI()
		{
			MethodInfo meth = AccessTools.Method(typeof(EnemyAI), "Update", (Type[])null, (Type[])null);
			DynamicMethod dynamicMethod = new DynamicMethod("Base.Update", null, new Type[1] { typeof(EnemyAI) }, typeof(EnemyAI));
			ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
			iLGenerator.Emit(OpCodes.Ldarg_0);
			iLGenerator.Emit(OpCodes.Call, meth);
			iLGenerator.Emit(OpCodes

DLLs/fandovec03.NaturalSelectionLib.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using NaturalSelectionLib.Comp;
using NaturalSelectionLib.Tools;
using PathfindingLib.API.SmartPathfinding;
using PathfindingLib.Utilities;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Fandovec03")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Personal Library with functions for getting, sorting and filtering enemies")]
[assembly: AssemblyFileVersion("0.7.1.0")]
[assembly: AssemblyInformationalVersion("0.7.1+727149db34d38517c3808c53fda0dd65fc54042b")]
[assembly: AssemblyProduct("NaturalSelectionLib")]
[assembly: AssemblyTitle("fandovec03.NaturalSelectionLib")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Fandovec03/NaturalSelectionLib.git")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.7.1.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 NaturalSelectionLib
{
	[BepInPlugin("fandovec03.NaturalSelectionLib", "NaturalSelectionLib", "0.7.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class NaturalSelectionLib : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <>c__DisplayClass24_0
		{
			public EnemyAI __instance;

			internal float <FindClosestEnemy>b__0(EnemyAI x)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				return Vector3.Distance(((Component)__instance).transform.position, ((Component)x).transform.position);
			}
		}

		[CompilerGenerated]
		private sealed class <FindClosestEnemy>d__24 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Action<EnemyAI?> ReturnOwnerResultPairDelegate;

			public List<EnemyAI> importEnemyList;

			public EnemyAI importClosestEnemy;

			public EnemyAI __instance;

			public int maxIterations;

			public bool useThreatVisibility;

			public bool usePathLengthAsDistance;

			public bool includeTheDead;

			private <>c__DisplayClass24_0 <>8__1;

			private int <iterations>5__2;

			private List<EnemyAI>.Enumerator <>s__3;

			private EnemyAI <enemy>5__4;

			private int <i>5__5;

			private bool <noValidPaths>5__6;

			private float[] <distance>5__7;

			private int <j>5__8;

			private bool[] <validPath>5__9;

			private PathfindingCalculator <calculator>5__10;

			private IVisibleThreat <threatImportEnemyList>5__11;

			private IVisibleThreat <threatImportClosestEnemy>5__12;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <FindClosestEnemy>d__24(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>8__1 = null;
				<>s__3 = default(List<EnemyAI>.Enumerator);
				<enemy>5__4 = null;
				<distance>5__7 = null;
				<validPath>5__9 = null;
				<calculator>5__10 = null;
				<threatImportEnemyList>5__11 = null;
				<threatImportClosestEnemy>5__12 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_07d8: Unknown result type (might be due to invalid IL or missing references)
				//IL_07f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_0815: Unknown result type (might be due to invalid IL or missing references)
				//IL_0825: Unknown result type (might be due to invalid IL or missing references)
				//IL_0657: Unknown result type (might be due to invalid IL or missing references)
				//IL_066e: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					goto IL_069e;
				}
				<>1__state = -1;
				<>8__1 = new <>c__DisplayClass24_0();
				<>8__1.__instance = __instance;
				<>s__3 = importEnemyList.GetEnumerator();
				try
				{
					while (<>s__3.MoveNext())
					{
						<enemy>5__4 = <>s__3.Current;
						if (debugLibrary)
						{
							LibraryLogger.LogInfo((object)$"{DebugStringHead(<>8__1.__instance)}/FindClosestEnemyCoroutine/ item {DebugStringHead(<enemy>5__4)} inside importEnemyList. IsEnemyDead: {<enemy>5__4.isEnemyDead}");
						}
						<enemy>5__4 = null;
					}
				}
				finally
				{
					((IDisposable)<>s__3).Dispose();
				}
				<>s__3 = default(List<EnemyAI>.Enumerator);
				if (debugLibrary && (Object)(object)importClosestEnemy != (Object)null)
				{
					LibraryLogger.LogInfo((object)$"{DebugStringHead(<>8__1.__instance)}/FindClosestEnemyCoroutine/ {DebugStringHead(importClosestEnemy)} inside importClosestEnemy. IsEnemyDead: {importClosestEnemy.isEnemyDead}");
				}
				if (importEnemyList.Count < 1)
				{
					if (debugLibrary)
					{
						LibraryLogger.LogWarning((object)(DebugStringHead(<>8__1.__instance) + "importEnemyList is empty!"));
					}
					if ((Object)(object)importClosestEnemy != (Object)null && importClosestEnemy.isEnemyDead)
					{
						if (!includeTheDead)
						{
							if (debugLibrary && debugSpam)
							{
								LibraryLogger.LogError((object)(DebugStringHead(<>8__1.__instance) + " " + DebugStringHead(importClosestEnemy) + " is dead and importEnemyList is empty! Setting importClosestEnemy to null..."));
							}
							ReturnOwnerResultPairDelegate?.Invoke(null);
							return false;
						}
						if (debugLibrary && debugSpam)
						{
							LibraryLogger.LogInfo((object)(DebugStringHead(<>8__1.__instance) + " " + DebugStringHead(importClosestEnemy) + " is dead and importEnemyList is empty!"));
						}
						ReturnOwnerResultPairDelegate?.Invoke(importClosestEnemy);
						return false;
					}
				}
				importEnemyList.OrderBy((EnemyAI x) => Vector3.Distance(((Component)<>8__1.__instance).transform.position, ((Component)x).transform.position));
				<iterations>5__2 = importEnemyList.Count;
				if (<iterations>5__2 > maxIterations)
				{
					<iterations>5__2 = maxIterations;
				}
				<i>5__5 = 0;
				goto IL_0994;
				IL_069e:
				if (!<calculator>5__10.CalculationnStatus(0, out <distance>5__7[0], out <validPath>5__9[0]) && !<calculator>5__10.CalculationnStatus(1, out <distance>5__7[1], out <validPath>5__9[1]))
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				if (<validPath>5__9[0] == <validPath>5__9[1] && <distance>5__7[0] == -1f)
				{
					<noValidPaths>5__6 = true;
				}
				if (debugLibrary)
				{
					LibraryLogger.LogMessage((object)$"(E) Distance[0] = {<distance>5__7[0]}, Distance[1] = {<distance>5__7[1]}");
				}
				<validPath>5__9 = null;
				<calculator>5__10 = null;
				goto IL_0772;
				IL_0982:
				<i>5__5++;
				goto IL_0994;
				IL_0994:
				if (<i>5__5 < <iterations>5__2)
				{
					if ((Object)(object)importClosestEnemy == (Object)null)
					{
						if (debugLibrary && debugSpam)
						{
							LibraryLogger.LogInfo((object)(DebugStringHead(<>8__1.__instance) + " No enemy assigned. Assigning new closestEnemy..."));
						}
						<j>5__8 = <i>5__5;
						while (<j>5__8 < importEnemyList.Count)
						{
							if (importEnemyList[<j>5__8].isEnemyDead && !includeTheDead)
							{
								if (debugLibrary && debugSpam)
								{
									LibraryLogger.LogWarning((object)(DebugStringHead(<>8__1.__instance) + " Found dead enemy. Skipping..."));
								}
								<j>5__8++;
								continue;
							}
							if (debugLibrary && debugSpam)
							{
								LibraryLogger.LogInfo((object)(DebugStringHead(<>8__1.__instance) + " New closestEnemy found!"));
							}
							importClosestEnemy = importEnemyList[<j>5__8];
							break;
						}
					}
					else
					{
						if (importClosestEnemy.isEnemyDead)
						{
							if (!includeTheDead)
							{
								if (debugLibrary && debugSpam)
								{
									LibraryLogger.LogError((object)(DebugStringHead(<>8__1.__instance) + ", " + DebugStringHead(importClosestEnemy) + " is dead! Assigning new tempClosestEnemy from importEnemyList..."));
								}
								importClosestEnemy = importEnemyList[<i>5__5];
								goto IL_0982;
							}
							if (debugLibrary && debugSpam)
							{
								LibraryLogger.LogInfo((object)(DebugStringHead(<>8__1.__instance) + " " + DebugStringHead(importClosestEnemy) + " is dead! The dead enemy will be included. "));
							}
						}
						if ((Object)(object)importClosestEnemy == (Object)(object)importEnemyList[<i>5__5])
						{
							if (debugLibrary && debugSpam)
							{
								LibraryLogger.LogWarning((object)(DebugStringHead(<>8__1.__instance) + " " + DebugStringHead(importEnemyList[<i>5__5]) + " is already assigned as closestEnemy"));
							}
						}
						else
						{
							if (!((Object)(object)importEnemyList[<i>5__5] == (Object)null))
							{
								<noValidPaths>5__6 = false;
								<distance>5__7 = new float[2];
								if (usePathLengthAsDistance && ((Behaviour)<>8__1.__instance.agent).isActiveAndEnabled)
								{
									<validPath>5__9 = new bool[2];
									<calculator>5__10 = PathfindingCalculator.Create(<>8__1.__instance, new List<Vector3>(2)
									{
										((Component)importEnemyList[<i>5__5]).transform.position,
										((Component)importClosestEnemy).transform.position
									});
									goto IL_069e;
								}
								goto IL_0772;
							}
							if (debugLibrary)
							{
								LibraryLogger.LogError((object)(DebugStringHead(<>8__1.__instance) + " Enemy not found! Skipping..."));
							}
						}
					}
					goto IL_0982;
				}
				if (debugLibrary && debugSpam)
				{
					LibraryLogger.LogWarning((object)(DebugStringHead(<>8__1.__instance) + " FindClosestEnemyCoroutine returning " + DebugStringHead(importClosestEnemy)));
				}
				ReturnOwnerResultPairDelegate?.Invoke(importClosestEnemy);
				return false;
				IL_0772:
				if (!((Object)(object)importClosestEnemy == (Object)null) && !((Object)(object)importEnemyList[<i>5__5] == (Object)null))
				{
					if (<noValidPaths>5__6 || !usePathLengthAsDistance)
					{
						<distance>5__7[0] = Vector3.Distance(((Component)<>8__1.__instance).transform.position, ((Component)importEnemyList[<i>5__5]).transform.position);
						<distance>5__7[1] = Vector3.Distance(((Component)<>8__1.__instance).transform.position, ((Component)importClosestEnemy).transform.position);
					}
					if (useThreatVisibility)
					{
						((Component)importEnemyList[<i>5__5]).TryGetComponent<IVisibleThreat>(ref <threatImportEnemyList>5__11);
						((Component)importClosestEnemy).TryGetComponent<IVisibleThreat>(ref <threatImportClosestEnemy>5__12);
						if (<threatImportEnemyList>5__11 != null)
						{
							<distance>5__7[0] *= <threatImportEnemyList>5__11.GetVisibility();
						}
						if (<threatImportClosestEnemy>5__12 != null)
						{
							<distance>5__7[1] *= <threatImportClosestEnemy>5__12.GetVisibility();
						}
						<threatImportEnemyList>5__11 = null;
						<threatImportClosestEnemy>5__12 = null;
					}
					if (<distance>5__7[0] < <distance>5__7[1])
					{
						importClosestEnemy = importEnemyList[<i>5__5];
						if (debugLibrary)
						{
							LibraryLogger.LogInfo((object)(DebugStringHead(<>8__1.__instance) + " Assigned " + DebugStringHead(importEnemyList[<i>5__5]) + " as new closestEnemy. Distance: " + <distance>5__7[0]));
						}
					}
					<distance>5__7 = null;
				}
				goto IL_0982;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static bool debugLibrary = false;

		public static bool debugSpam = false;

		public static bool usePathfindingLib = false;

		public static ManualLogSource LibraryLogger = new ManualLogSource("NaturalSelectionLib");

		private static Dictionary<Type, List<EnemyAI>> globalEnemyLists = new Dictionary<Type, List<EnemyAI>>();

		public static string ReturnVersion()
		{
			return "0.7.1";
		}

		public static void UpdateEnemyList(Type instanceType, List<EnemyAI> list)
		{
			if (globalEnemyLists[instanceType].SequenceEqual(list))
			{
				if (debugSpam && debugLibrary)
				{
					LibraryLogger.LogInfo((object)("/updateListInsideDictionary/ Sequence in " + instanceType?.ToString() + " is equal. Skipping."));
				}
				return;
			}
			globalEnemyLists[instanceType] = list;
			if (debugSpam && debugLibrary)
			{
				LibraryLogger.LogInfo((object)("/updateListInsideDictionary/ updating list for " + instanceType));
			}
		}

		public static void CreateEnemyList(Type instanceType, List<EnemyAI> list)
		{
			if (!globalEnemyLists.ContainsKey(instanceType))
			{
				globalEnemyLists.Add(instanceType, list);
				if (debugSpam && debugLibrary)
				{
					LibraryLogger.LogInfo((object)("/updateListInsideDictionary/ created new list for " + instanceType));
				}
			}
		}

		public static void DestroyEnemyList(Type instanceType, List<EnemyAI> list)
		{
			if (globalEnemyLists.ContainsKey(instanceType))
			{
				globalEnemyLists.Remove(instanceType);
				if (debugSpam && debugLibrary)
				{
					LibraryLogger.LogInfo((object)("/updateListInsideDictionary/ created new list for " + instanceType));
				}
			}
		}

		public static bool EnemyListContainsKey(Type instanceType)
		{
			return globalEnemyLists.ContainsKey(instanceType);
		}

		public static List<EnemyAI> GetEnemyList(Type instanceType)
		{
			return globalEnemyLists[instanceType];
		}

		public static void ClearAllEnemyLists()
		{
			globalEnemyLists.Clear();
		}

		public static void SetLibraryLoggers(ManualLogSource importLogger, bool spammyLogs = false, bool debuglibrary = false, bool usePathfindinglib = false)
		{
			LibraryLogger = importLogger;
			debugSpam = spammyLogs;
			debugLibrary = debuglibrary;
			usePathfindingLib = usePathfindinglib;
		}

		public static string DebugStringHead(object? source, bool shortFormat = true)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			string result = "";
			if (source != null)
			{
				string text = "";
				if (source is EnemyAI)
				{
					EnemyAI val = (EnemyAI)source;
					text = $"{val.enemyType.enemyName}|ID: {((NetworkBehaviour)val).NetworkObjectId}|ThisEnemyIndex: {val.thisEnemyIndex}";
					if (shortFormat)
					{
						text = $"{val?.enemyType.enemyName}|ID: {((val != null) ? new ulong?(((NetworkBehaviour)val).NetworkObjectId) : null)}";
					}
				}
				else if (source is SandSpiderWebTrap)
				{
					SandSpiderWebTrap val2 = (SandSpiderWebTrap)source;
					text = $"Spider web {val2.trapID}";
					if (!shortFormat)
					{
						text = $"Spider web {val2.trapID}, Owner {DebugStringHead(val2.mainScript)}";
					}
				}
				else if (!(source is GrabbableObject))
				{
					text = ((!(source is string)) ? "Unknown source" : ((string)source));
				}
				else
				{
					GrabbableObject val3 = (GrabbableObject)source;
					text = $"{val3.itemProperties.itemName}, ID: {((NetworkBehaviour)val3).NetworkObjectId}";
					if (!shortFormat)
					{
						text = $"{val3.itemProperties.itemName}|ID: {((NetworkBehaviour)val3).NetworkObjectId}|ItemID: {val3.itemProperties.itemId}";
					}
				}
				result = "(" + text + ")";
			}
			return result;
		}

		public static List<EnemyAI> GetCompleteList(EnemyAI instance, bool filterThemselves = true, int includeOrReturnTheDead = 0)
		{
			List<EnemyAI> list = new List<EnemyAI>(RoundManager.Instance.SpawnedEnemies);
			for (int i = 0; i < list.Count; i++)
			{
				if ((Object)(object)list[i] == (Object)(object)instance)
				{
					if (debugLibrary && debugSpam)
					{
						LibraryLogger.LogWarning((object)(DebugStringHead(instance) + " Found itself in the list. Removing..."));
					}
					list.Remove(list[i]);
				}
				else if (((object)list[i]).GetType() == ((object)instance).GetType() && filterThemselves)
				{
					if (debugLibrary && debugSpam)
					{
						LibraryLogger.LogWarning((object)(DebugStringHead(instance) + " Found its type in the list. Removing..."));
					}
					list.Remove(list[i]);
				}
				else
				{
					if (!list[i].isEnemyDead)
					{
						continue;
					}
					switch (includeOrReturnTheDead)
					{
					case 0:
						if (debugLibrary && debugSpam)
						{
							LibraryLogger.LogInfo((object)(DebugStringHead(instance) + " Found dead enemy in the list. Removing..."));
						}
						list.Remove(list[i]);
						break;
					case 1:
						if (debugLibrary && debugSpam)
						{
							LibraryLogger.LogInfo((object)(DebugStringHead(instance) + " Found dead enemy in the list. Proceeding..."));
						}
						break;
					case 2:
						if (debugLibrary && debugSpam)
						{
							LibraryLogger.LogInfo((object)(DebugStringHead(instance) + " Found living enemy in the list. Removing.."));
						}
						list.Remove(list[i]);
						break;
					}
				}
			}
			return list;
		}

		public static List<EnemyAI> GetNearbyEnemies(EnemyAI instance, float radius = 0f, Vector3? importEyePosition = null, int includeOrReturnTheDead = 0)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_0023: 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)
			List<EnemyAI> list = new List<EnemyAI>();
			Vector3 val = instance.eye.position;
			if (importEyePosition.HasValue)
			{
				val = importEyePosition.Value;
			}
			int mask = LayerMask.GetMask(new string[1] { "Enemies" });
			int num = Physics.OverlapSphereNonAlloc(val, radius, RoundManager.Instance.tempColliderResults, mask, (QueryTriggerInteraction)2);
			EnemyAICollisionDetect val2 = default(EnemyAICollisionDetect);
			for (int i = 0; i < num; i++)
			{
				if (!((Component)RoundManager.Instance.tempColliderResults[i]).gameObject.TryGetComponent<EnemyAICollisionDetect>(ref val2))
				{
					continue;
				}
				EnemyAI mainScript = val2.mainScript;
				if ((Object)(object)mainScript == (Object)(object)instance || list.Contains(mainScript))
				{
					continue;
				}
				if (debugLibrary)
				{
					LibraryLogger.LogWarning((object)(DebugStringHead(instance) + " /GetEnemiesInLOS/: Enemy not found in imported enemy list! Skipping..."));
				}
				switch (includeOrReturnTheDead)
				{
				case 0:
					if (!mainScript.isEnemyDead)
					{
						list.Add(mainScript);
					}
					break;
				case 1:
					list.Add(mainScript);
					break;
				case 2:
					if (mainScript.isEnemyDead)
					{
						list.Add(mainScript);
					}
					break;
				}
			}
			return list;
		}

		public static bool GetPathLength(NavMeshAgent agent, Vector3 targetDestination, out float PathLength, out bool validPathOut)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Invalid comparison between Unknown and I4
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			NavMeshPath val = new NavMeshPath();
			bool flag = false;
			bool flag2 = false;
			Vector3[] array = Array.Empty<Vector3>();
			PathLength = -1f;
			validPathOut = false;
			if (!((Behaviour)agent).enabled || !((Behaviour)agent).isActiveAndEnabled)
			{
				LibraryLogger.LogWarning((object)"Agent is disabled!");
				PathLength = -1f;
				return false;
			}
			flag2 = (validPathOut = agent.CalculatePath(targetDestination, val) && (int)val.status == 0);
			array = val.corners;
			if (flag2)
			{
				float num = 0f;
				for (int i = 1; i < array.Length; i++)
				{
					float num2 = Vector3.Distance(array[i - 1], array[i]);
					num += num2;
				}
				PathLength = num;
				if (debugLibrary)
				{
					LibraryLogger.LogMessage((object)$"Found path length: {PathLength}");
				}
				return true;
			}
			return false;
		}

		public static void GetInsideOrOutsideEnemyList(ref List<EnemyAI> importEnemyList, EnemyAI instance)
		{
			foreach (EnemyAI item in importEnemyList.ToList())
			{
				if ((Object)(object)item == (Object)(object)instance || item.isOutside != instance.isOutside)
				{
					importEnemyList.Remove(item);
					if (debugLibrary && debugSpam)
					{
						LibraryLogger.LogDebug((object)(DebugStringHead(instance) + "/GetInsideOrOutsideEnemyList/ removed " + DebugStringHead(item)));
					}
				}
			}
		}

		public static EnemyAI? FindClosestEnemy(ref List<EnemyAI> importEnemyList, EnemyAI? importClosestEnemy, EnemyAI __instance, int maxIterations = 6, bool useThreatVisibility = true, bool usePathLengthAsDistance = false, bool includeTheDead = false)
		{
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0560: Unknown result type (might be due to invalid IL or missing references)
			//IL_0573: Unknown result type (might be due to invalid IL or missing references)
			//IL_058c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0597: Unknown result type (might be due to invalid IL or missing references)
			EnemyAI __instance2 = __instance;
			foreach (EnemyAI importEnemy in importEnemyList)
			{
				if (debugLibrary)
				{
					LibraryLogger.LogInfo((object)$"{DebugStringHead(__instance2)}/FindClosestEnemy/ item {DebugStringHead(importEnemy)} inside importEnemyList. IsEnemyDead: {importEnemy.isEnemyDead}");
				}
			}
			if (debugLibrary && (Object)(object)importClosestEnemy != (Object)null)
			{
				LibraryLogger.LogInfo((object)$"{DebugStringHead(__instance2)}/FindClosestEnemy/ {DebugStringHead(importClosestEnemy)} inside importClosestEnemy. IsEnemyDead: {importClosestEnemy.isEnemyDead}");
			}
			if (importEnemyList.Count < 1)
			{
				if (debugLibrary)
				{
					LibraryLogger.LogWarning((object)(DebugStringHead(__instance2) + "importEnemyList is empty!"));
				}
				if ((Object)(object)importClosestEnemy != (Object)null && importClosestEnemy.isEnemyDead)
				{
					if (!includeTheDead)
					{
						if (debugLibrary && debugSpam)
						{
							LibraryLogger.LogError((object)(DebugStringHead(__instance2) + " " + DebugStringHead(importClosestEnemy) + " is dead and importEnemyList is empty! Setting importClosestEnemy to null..."));
						}
						return null;
					}
					if (debugLibrary && debugSpam)
					{
						LibraryLogger.LogInfo((object)(DebugStringHead(__instance2) + " " + DebugStringHead(importClosestEnemy) + " is dead and importEnemyList is empty!"));
					}
					return importClosestEnemy;
				}
			}
			importEnemyList.OrderBy((EnemyAI x) => Vector3.Distance(((Component)__instance2).transform.position, ((Component)x).transform.position));
			int num = importEnemyList.Count;
			if (num > maxIterations)
			{
				num = maxIterations;
			}
			IVisibleThreat val = default(IVisibleThreat);
			IVisibleThreat val2 = default(IVisibleThreat);
			for (int i = 0; i < num; i++)
			{
				if ((Object)(object)importClosestEnemy == (Object)null)
				{
					if (debugLibrary && debugSpam)
					{
						LibraryLogger.LogInfo((object)(DebugStringHead(__instance2) + " No enemy assigned. Assigning new closestEnemy..."));
					}
					for (int j = i; j < importEnemyList.Count; j++)
					{
						if (importEnemyList[j].isEnemyDead && !includeTheDead)
						{
							if (debugLibrary && debugSpam)
							{
								LibraryLogger.LogWarning((object)(DebugStringHead(__instance2) + " Found dead enemy. Skipping..."));
							}
							continue;
						}
						if (debugLibrary && debugSpam)
						{
							LibraryLogger.LogInfo((object)(DebugStringHead(__instance2) + " New closestEnemy found!"));
						}
						importClosestEnemy = importEnemyList[j];
						break;
					}
					continue;
				}
				if (importClosestEnemy.isEnemyDead)
				{
					if (!includeTheDead)
					{
						if (debugLibrary && debugSpam)
						{
							LibraryLogger.LogError((object)(DebugStringHead(__instance2) + ", " + DebugStringHead(importClosestEnemy) + " is dead! Assigning new tempClosestEnemy from importEnemyList..."));
						}
						importClosestEnemy = importEnemyList[i];
						continue;
					}
					if (debugLibrary && debugSpam)
					{
						LibraryLogger.LogInfo((object)(DebugStringHead(__instance2) + " " + DebugStringHead(importClosestEnemy) + " is dead! The dead enemy will be included. "));
					}
				}
				if ((Object)(object)importClosestEnemy == (Object)(object)importEnemyList[i])
				{
					if (debugLibrary && debugSpam)
					{
						LibraryLogger.LogWarning((object)(DebugStringHead(__instance2) + " " + DebugStringHead(importEnemyList[i]) + " is already assigned as closestEnemy"));
					}
					continue;
				}
				if ((Object)(object)importEnemyList[i] == (Object)null)
				{
					if (debugLibrary)
					{
						LibraryLogger.LogError((object)(DebugStringHead(__instance2) + " Enemy not found! Skipping..."));
					}
					continue;
				}
				bool flag = false;
				float[] array = new float[2];
				if (usePathLengthAsDistance && ((Behaviour)__instance2.agent).isActiveAndEnabled && GetPathLength(__instance2.agent, ((Component)importEnemyList[i]).transform.position, out array[0], out var _) && GetPathLength(__instance2.agent, ((Component)importClosestEnemy).transform.position, out array[1], out var _))
				{
					if (array[0] == array[1] && array[0] == -777.77f)
					{
						flag = true;
					}
					if (debugLibrary)
					{
						LibraryLogger.LogMessage((object)$"Distance[0] = {array[0]}, Distance[1] = {array[1]}");
					}
				}
				if (flag || !usePathLengthAsDistance)
				{
					array[0] = Vector3.Distance(((Component)__instance2).transform.position, ((Component)importEnemyList[i]).transform.position);
					array[1] = Vector3.Distance(((Component)__instance2).transform.position, ((Component)importClosestEnemy).transform.position);
				}
				if (useThreatVisibility)
				{
					((Component)importEnemyList[i]).TryGetComponent<IVisibleThreat>(ref val);
					((Component)importClosestEnemy).TryGetComponent<IVisibleThreat>(ref val2);
					if (val != null)
					{
						array[0] *= val.GetVisibility();
					}
					if (val2 != null)
					{
						array[1] *= val2.GetVisibility();
					}
				}
				if (array[0] < array[1])
				{
					importClosestEnemy = importEnemyList[i];
					if (debugLibrary)
					{
						LibraryLogger.LogInfo((object)(DebugStringHead(__instance2) + " Assigned " + DebugStringHead(importEnemyList[i]) + " as new closestEnemy. Distance: " + array[0]));
					}
				}
			}
			if (debugLibrary && debugSpam)
			{
				LibraryLogger.LogWarning((object)(DebugStringHead(__instance2) + " findClosestEnemy returning " + DebugStringHead(importClosestEnemy)));
			}
			return importClosestEnemy;
		}

		public static void FilterEnemyList(ref List<EnemyAI> importEnemyList, List<string>? blacklist, EnemyAI instance, bool filterOutImmortal = true, bool filterTheSameType = true)
		{
			List<EnemyAI> list = new List<EnemyAI>(importEnemyList);
			for (int i = 0; i < list.Count; i++)
			{
				if ((Object)(object)list[i] == (Object)(object)instance)
				{
					if (debugLibrary)
					{
						LibraryLogger.LogWarning((object)(DebugStringHead(instance) + " Found itself in importEnemyList! Skipping..."));
					}
					importEnemyList.Remove(list[i]);
					continue;
				}
				if (filterTheSameType && ((object)list[i]).GetType() == ((object)instance).GetType())
				{
					if (debugLibrary)
					{
						LibraryLogger.LogWarning((object)(DebugStringHead(instance) + " Found its own type in importEnemyList! Skipping..."));
					}
					importEnemyList.Remove(list[i]);
					continue;
				}
				try
				{
					if (blacklist != null && (Object)(object)list[i] != (Object)null && (blacklist.Contains(list[i].enemyType.enemyName) || blacklist.Contains(((Object)list[i].enemyType).name) || ((Object)(object)((Component)list[i]).GetComponentInChildren<ScanNodeProperties>() != (Object)null && blacklist.Contains(((Component)list[i]).GetComponentInChildren<ScanNodeProperties>().headerText))))
					{
						if (debugLibrary && blacklist.Contains(list[i].enemyType.enemyName))
						{
							LibraryLogger.LogWarning((object)(DebugStringHead(instance) + " Found blacklisted enemy in importEnemyList by EnemyType enemyName! Skipping..."));
						}
						if (debugLibrary && blacklist.Contains(((Object)list[i].enemyType).name))
						{
							LibraryLogger.LogWarning((object)(DebugStringHead(instance) + " Found blacklisted enemy in importEnemyList by EnemyType name! Skipping..."));
						}
						if (debugLibrary && blacklist.Contains(((Component)list[i]).GetComponentInChildren<ScanNodeProperties>().headerText))
						{
							LibraryLogger.LogWarning((object)(DebugStringHead(instance) + " Found blacklisted enemy in importEnemyList by scan node headertext! Skipping..."));
						}
						importEnemyList.Remove(list[i]);
						continue;
					}
				}
				catch (Exception ex)
				{
					LibraryLogger.LogError((object)(DebugStringHead(instance) + " Something went wrong."));
					LibraryLogger.LogError((object)blacklist);
					LibraryLogger.LogError((object)list[i]);
					LibraryLogger.LogError((object)list[i].enemyType.enemyName.ToUpper());
					LibraryLogger.LogError((object)((Component)list[i]).GetComponentInChildren<ScanNodeProperties>().headerText.ToUpper());
					LibraryLogger.LogError((object)ex.ToString());
				}
				if (filterOutImmortal && !list[i].enemyType.canDie)
				{
					if (debugLibrary)
					{
						LibraryLogger.LogInfo((object)$"{DebugStringHead(instance)} Caught and filtered out immortal Enemy of type {((object)list[i]).GetType()}");
					}
					importEnemyList.Remove(list[i]);
				}
			}
		}

		public static void FilterEnemySizes(ref List<EnemyAI> importEnemyList, EnemySize[] enemySizes, EnemyAI instance, bool inverseToggle = false)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			List<EnemyAI> list = new List<EnemyAI>(importEnemyList);
			for (int i = 0; i < list.Count; i++)
			{
				if (enemySizes != null && enemySizes.Length != 0 && ((!inverseToggle && enemySizes.Contains(list[i].enemyType.EnemySize)) || (inverseToggle && !enemySizes.Contains(list[i].enemyType.EnemySize))))
				{
					if (debugLibrary)
					{
						LibraryLogger.LogDebug((object)$"{DebugStringHead(instance)} Enemy of size {list[i].enemyType.EnemySize} passed the filter. inverseToggle: {inverseToggle}");
					}
				}
				else if (enemySizes != null && enemySizes.Length != 0)
				{
					if (debugLibrary)
					{
						LibraryLogger.LogInfo((object)$"{DebugStringHead(instance)} Caught and filtered out Enemy of size {list[i].enemyType.EnemySize}");
					}
					importEnemyList.Remove(list[i]);
					continue;
				}
				if (enemySizes == null || enemySizes.Length < 1)
				{
					if (debugLibrary && enemySizes != null && enemySizes.Length < 1)
					{
						LibraryLogger.LogInfo((object)$"{DebugStringHead(instance)} enemySizes is empty. Adding enemy of size {list[i].enemyType.EnemySize} by default");
					}
					if (debugLibrary && enemySizes == null)
					{
						LibraryLogger.LogInfo((object)$"{DebugStringHead(instance)} enemySizes is NULL. Adding enemy of size {list[i].enemyType.EnemySize} by default");
					}
				}
			}
		}

		public static void FilterEnemySizes(ref Dictionary<EnemyAI, int> importEnemySizeDict, int[] enemySizes, EnemyAI instance, bool inverseToggle = false)
		{
			Dictionary<EnemyAI, int> dictionary = new Dictionary<EnemyAI, int>(importEnemySizeDict);
			foreach (KeyValuePair<EnemyAI, int> item in dictionary)
			{
				if (enemySizes != null && enemySizes.Length != 0 && ((!inverseToggle && enemySizes.Contains(item.Value)) || (inverseToggle && !enemySizes.Contains(item.Value))))
				{
					if (debugLibrary)
					{
						LibraryLogger.LogDebug((object)$"{DebugStringHead(instance)} Enemy of size {item.Value} passed the filter. inverseToggle: {inverseToggle}");
					}
				}
				else if (enemySizes != null && enemySizes.Length != 0)
				{
					if (debugLibrary)
					{
						LibraryLogger.LogInfo((object)$"{DebugStringHead(instance)} Caught and filtered out Enemy of size {item.Value}");
					}
					importEnemySizeDict.Remove(item.Key);
					continue;
				}
				if (enemySizes == null || enemySizes.Length < 1)
				{
					if (debugLibrary && enemySizes != null && enemySizes.Length < 1)
					{
						LibraryLogger.LogInfo((object)$"{DebugStringHead(instance)} enemySizes is empty. Adding enemy of size {item.Value} by default");
					}
					if (debugLibrary && enemySizes == null)
					{
						LibraryLogger.LogInfo((object)$"{DebugStringHead(instance)} enemySizes is NULL. Adding enemy of size {item.Value} by default");
					}
				}
			}
		}

		public static Dictionary<EnemyAI, float> GetEnemiesInLOS(EnemyAI instance, ref List<EnemyAI> importEnemyList, float width = 45f, float importRange = 0f, float proximityAwareness = -1f, float importRadius = 0f, Vector3? importEyePosition = null)
		{
			//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_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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Invalid comparison between Unknown and I4
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: 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_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<EnemyAI, float> tempDictionary = new Dictionary<EnemyAI, float>();
			float num = importRange;
			float num2 = importRadius;
			Vector3 val = instance.eye.position;
			if (importEyePosition.HasValue)
			{
				val = importEyePosition.Value;
			}
			int mask = LayerMask.GetMask(new string[1] { "Enemies" });
			if (instance.isOutside && !instance.enemyType.canSeeThroughFog && (int)TimeOfDay.Instance.currentLevelWeather == 3)
			{
				num = Mathf.Clamp(importRange, 0f, 30f);
			}
			if (num2 <= 0f)
			{
				num2 = num * 2f;
			}
			int num3 = Physics.OverlapSphereNonAlloc(val, num2, RoundManager.Instance.tempColliderResults, mask, (QueryTriggerInteraction)2);
			EnemyAICollisionDetect val2 = default(EnemyAICollisionDetect);
			for (int i = 0; i < num3; i++)
			{
				if (!((Component)RoundManager.Instance.tempColliderResults[i]).gameObject.TryGetComponent<EnemyAICollisionDetect>(ref val2))
				{
					continue;
				}
				EnemyAI mainScript = val2.mainScript;
				if ((Object)(object)mainScript == (Object)(object)instance)
				{
					continue;
				}
				if (!importEnemyList.Contains(mainScript))
				{
					if (debugLibrary)
					{
						LibraryLogger.LogWarning((object)(DebugStringHead(instance) + " /GetEnemiesInLOS/: Enemy not found in imported enemy list! Skipping..."));
					}
					continue;
				}
				Vector3 position = ((Component)mainScript).transform.position;
				if (!(Vector3.Distance(position, instance.eye.position) < num) || Physics.Linecast(instance.eye.position, position, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1) || !instance.CheckLineOfSightForPosition(position, width, (int)num, proximityAwareness, instance.eye))
				{
					continue;
				}
				if (!tempDictionary.ContainsKey(mainScript))
				{
					tempDictionary.Add(mainScript, Vector3.Distance(((Component)instance).transform.position, position));
					if (debugLibrary && debugSpam)
					{
						LibraryLogger.LogDebug((object)$"{DebugStringHead(instance)} /GetEnemiesInLOS/: Added {mainScript} to tempDictionary");
					}
				}
				if (tempDictionary.ContainsKey(mainScript) && debugLibrary && debugSpam && debugLibrary)
				{
					LibraryLogger.LogWarning((object)$"{DebugStringHead(instance)} /GetEnemiesInLOS/: {mainScript} is already in tempDictionary");
				}
			}
			if (tempDictionary.Count > 1)
			{
				tempDictionary.OrderBy<KeyValuePair<EnemyAI, float>, Dictionary<EnemyAI, float>.ValueCollection>((KeyValuePair<EnemyAI, float> value) => tempDictionary.Values).Reverse();
				if (debugLibrary)
				{
					foreach (KeyValuePair<EnemyAI, float> item in tempDictionary)
					{
						if (debugLibrary && debugSpam)
						{
							LibraryLogger.LogDebug((object)$"{DebugStringHead(instance)} /GetEnemiesInLOS/: Final list: {item.Key}, range: {item.Value}");
						}
					}
				}
			}
			return tempDictionary;
		}

		public static Dictionary<EnemyAI, float> GetEnemiesInLOS(EnemyAI instance, float width = 45f, float importRange = 0f, float proximityAwareness = -1f, float importRadius = 0f, Vector3? importEyePosition = null)
		{
			//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_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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Invalid comparison between Unknown and I4
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<EnemyAI, float> tempDictionary = new Dictionary<EnemyAI, float>();
			float num = importRange;
			float num2 = importRadius;
			Vector3 val = instance.eye.position;
			if (importEyePosition.HasValue)
			{
				val = importEyePosition.Value;
			}
			int mask = LayerMask.GetMask(new string[1] { "Enemies" });
			if (instance.isOutside && !instance.enemyType.canSeeThroughFog && (int)TimeOfDay.Instance.currentLevelWeather == 3)
			{
				num = Mathf.Clamp(importRange, 0f, 30f);
			}
			if (num2 <= 0f)
			{
				num2 = num * 2f;
			}
			int num3 = Physics.OverlapSphereNonAlloc(val, num2, RoundManager.Instance.tempColliderResults, mask, (QueryTriggerInteraction)2);
			EnemyAICollisionDetect val2 = default(EnemyAICollisionDetect);
			for (int i = 0; i < num3; i++)
			{
				if (!((Component)RoundManager.Instance.tempColliderResults[i]).gameObject.TryGetComponent<EnemyAICollisionDetect>(ref val2))
				{
					continue;
				}
				EnemyAI mainScript = val2.mainScript;
				if ((Object)(object)mainScript == (Object)(object)instance)
				{
					continue;
				}
				Vector3 position = ((Component)mainScript).transform.position;
				if (!(Vector3.Distance(position, instance.eye.position) < num) || Physics.Linecast(instance.eye.position, position, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1) || !instance.CheckLineOfSightForPosition(position, width, (int)num, proximityAwareness, instance.eye))
				{
					continue;
				}
				if (!tempDictionary.ContainsKey(mainScript))
				{
					tempDictionary.Add(mainScript, Vector3.Distance(((Component)instance).transform.position, position));
					if (debugLibrary && debugSpam)
					{
						LibraryLogger.LogDebug((object)$"{DebugStringHead(instance)} /GetEnemiesInLOS/: Added {mainScript} to tempDictionary");
					}
				}
				if (tempDictionary.ContainsKey(mainScript) && debugLibrary && debugSpam && debugLibrary)
				{
					LibraryLogger.LogWarning((object)$"{DebugStringHead(instance)} /GetEnemiesInLOS/: {mainScript} is already in tempDictionary");
				}
			}
			if (tempDictionary.Count > 1)
			{
				tempDictionary.OrderBy<KeyValuePair<EnemyAI, float>, Dictionary<EnemyAI, float>.ValueCollection>((KeyValuePair<EnemyAI, float> value) => tempDictionary.Values).Reverse();
				if (debugLibrary)
				{
					foreach (KeyValuePair<EnemyAI, float> item in tempDictionary)
					{
						if (debugLibrary && debugSpam)
						{
							LibraryLogger.LogDebug((object)$"{DebugStringHead(instance)} /GetEnemiesInLOS/: Final list: {item.Key}, range: {item.Value}");
						}
					}
				}
			}
			return tempDictionary;
		}

		[IteratorStateMachine(typeof(<FindClosestEnemy>d__24))]
		public static IEnumerator FindClosestEnemy(Action<EnemyAI?>? ReturnOwnerResultPairDelegate, List<EnemyAI> importEnemyList, EnemyAI? importClosestEnemy, EnemyAI __instance, int maxIterations = 6, bool useThreatVisibility = true, bool usePathLengthAsDistance = false, bool includeTheDead = false)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <FindClosestEnemy>d__24(0)
			{
				ReturnOwnerResultPairDelegate = ReturnOwnerResultPairDelegate,
				importEnemyList = importEnemyList,
				importClosestEnemy = importClosestEnemy,
				__instance = __instance,
				maxIterations = maxIterations,
				useThreatVisibility = useThreatVisibility,
				usePathLengthAsDistance = usePathLengthAsDistance,
				includeTheDead = includeTheDead
			};
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "fandovec03.NaturalSelectionLib";

		public const string PLUGIN_NAME = "NaturalSelectionLib";

		public const string PLUGIN_VERSION = "0.7.1";
	}
}
namespace NaturalSelectionLib.Comp
{
	internal static class PathfindingLibHelper
	{
		public static PathfindingCalculatorAsyncPathfindingLib ReturnPathfindingLibalculator(EnemyAI instance, List<Vector3> destinations)
		{
			return new PathfindingCalculatorAsyncPathfindingLib(instance, destinations);
		}
	}
	internal class PathfindingCalculatorAsyncPathfindingLib : PathfindingCalculator
	{
		private SmartPathTask pathfindingTask = new SmartPathTask();

		internal PathfindingCalculatorAsyncPathfindingLib(EnemyAI instance, List<Vector3> destinations)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			pathfindingTask.StartPathTask(instance.agent, AgentExtensions.GetPathOrigin(instance.agent), destinations, (SmartPathfindingLinkFlags)0);
		}

		public override bool CalculationnStatus(int index, out float pathLengthResult, out bool validPath)
		{
			pathLengthResult = -1f;
			validPath = false;
			if (!pathfindingTask.IsResultReady(index))
			{
				return true;
			}
			if (pathfindingTask.PathSucceeded(index))
			{
				pathLengthResult = pathfindingTask.GetPathLength(index);
				validPath = pathfindingTask.PathSucceeded(index);
				return true;
			}
			return true;
		}

		public override void Dispose()
		{
			base.Dispose();
			pathfindingTask.Dispose();
		}
	}
}
namespace NaturalSelectionLib.Tools
{
	internal abstract class PathfindingCalculator : IDisposable
	{
		internal static PathfindingCalculator Create(EnemyAI instance, List<Vector3> destinations)
		{
			if (Chainloader.PluginInfos.ContainsKey("Zaggy1024.PathfindingLib") && !NaturalSelectionLib.usePathfindingLib)
			{
				return PathfindingLibHelper.ReturnPathfindingLibalculator(instance, destinations);
			}
			return new PathfindingCalculatorAsync(instance, destinations);
		}

		public abstract bool CalculationnStatus(int index, out float pathLengthResult, out bool validPath);

		public virtual void Dispose()
		{
		}
	}
	internal class PathfindingCalculatorAsync : PathfindingCalculator
	{
		[CompilerGenerated]
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private EnemyAI <instance>P;

		[CompilerGenerated]
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private List<Vector3> <destinations>P;

		private NavMeshPath path;

		public PathfindingCalculatorAsync(EnemyAI instance, List<Vector3> destinations)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			<instance>P = instance;
			<destinations>P = destinations;
			path = new NavMeshPath();
			base..ctor();
		}

		public override bool CalculationnStatus(int index, out float pathLengthResult, out bool validPath)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Invalid comparison between Unknown and I4
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			pathLengthResult = -1f;
			validPath = false;
			<instance>P.agent.CalculatePath(<destinations>P[index], path);
			if ((int)path.status > 0)
			{
				return true;
			}
			pathLengthResult = 0f;
			for (int i = 1; i < path.corners.Length; i++)
			{
				validPath = true;
				pathLengthResult += Vector3.Distance(path.corners[i - 1], path.corners[i]);
			}
			return true;
		}
	}
}