Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ExperimentalEnemyInteractions v0.5.31
DLLs/fandovec03.NaturalSelection.dll
Decompiled 7 months ago
The result has been truncated due to the large size, download it to view full contents!
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.14.0")] [assembly: AssemblyInformationalVersion("0.4.14+7281b0065fd16eef9aaf7f42d39e8583a0affa6e")] [assembly: AssemblyProduct("NaturalSelection")] [assembly: AssemblyTitle("fandovec03.NaturalSelection")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.4.14.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.14")] [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 usePathToFindClosestEnemy = false; internal static bool useCoroutines = 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 object[] loggerBlacklist = Array.Empty<object>(); 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; usePathToFindClosestEnemy = BoundingConfig.usePathToFindClosestEnemy.Value; useCoroutines = BoundingConfig.useCoroutines.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.14".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.14")); } 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 { Library.SetLibraryLoggers(Logger, spammyLogs, debugLibrary, usePathToFindClosestEnemy); Logger.LogMessage((object)("Library successfully setup! Version " + Library.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_0098: Unknown result type (might be due to invalid IL or missing references) if (toggle && !loggerBlacklist.Contains<object>(source) && !debugKillSwitchScript) { if (source != null && !(source is EnemyAI) && !(source is SandSpiderWebTrap) && !(source is GrabbableObject) && !(source is Item) && !(source is string)) { Logger.LogError((object)$"! Unsupported type {source.GetType()} found in LogNS! Blacklisting source: {source}"); CollectionExtensions.AddItem<object>((IEnumerable<object>)loggerBlacklist, source); } Logger.Log(logLevel, (object)(LibraryCalls.DebugStringHead(source, !moreDetail) + " " + log)); } } public static void ClearLogBlacklist() { Array.Clear(loggerBlacklist, 0, loggerBlacklist.Length); } 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.14"; } } 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; Library.SetLibraryLoggers(Script.Logger, value, debugLibraryCalls, false); } if (entryKey == "debugLibraryTrigger") { debugLibraryCalls = value; Library.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 LibraryMethods.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 LibraryMethods.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!"); } LibraryMethods.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 LibraryMethods.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!"); } LibraryMethods.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!"); } LibraryMethods.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!"); } LibraryMethods.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 LibraryMethods.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 LibraryMethods.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 LibraryMethods.FindClosestEnemy(ReturnOwnerResult, importEnemyList, importClosestEnemy, instance, maxIterations, useThreatVisibility, usePathLenghtAsDistance, includeTheDead); } public static List<EnemyAI> GetEnemyList(Type type) { return Library.GetEnemyList(type); } } internal class MyModConfig { public readonly ConfigEntry<bool> useCoroutines; 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_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Expected O, but got Unknown //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: 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."); useCoroutines = cfg.Bind<bool>("Beta", "Enable experimental library coroutines", false, "Use coroutines to closest enemy. Might improve performance slightly."); usePathToFindClosestEnemy = cfg.Bind<bool>("Beta", "Use pathfinding to find closest enemy", false, "Enemies will use pathfinding to find closest enemy. Uses PathfindingLib if present. \n \n [Might cause performance drops without PathfindingLib]"); 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(); Library.ClearAllEnemyLists(); EnemyAIPatch.enemyDataDict.Clear(); Script.ClearLogBlacklist(); } [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(); Library.ClearAllEnemyLists(); EnemyAIPatch.enemyDataDict.Clear(); Script.ClearLogBlacklist(); } } [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()) { Library.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 (!Library.EnemyListContainsKey(((object)instance).GetType())) { Script.LogNS((LogLevel)4, LibraryCalls.DebugStringHead(instance) + " global enemy list for this enemy does not exist! Creating a new one."); Library.CreateEnemyList(((object)instance).GetType(), checkedTypes[((object)instance).GetType()]); } else { Library.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); temp = null; if (dataID != "-1") { 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) string text = "-1"; if (instance == null) { return text; } if (instance is EnemyAI) { text = ((EnemyAI)instance).enemyType.enemyName + ((NetworkBehaviour)(EnemyAI)instance).NetworkObjectId; if (returnToEnemyAIType) { text += ".base"; } } else if (instance is SandSpiderWebTrap && (Object)(object)((SandSpiderWebTrap)instance).mainScript != (Object)null) { 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_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Expected O, but got Unknown if (((object)mainscript2).GetType() == typeof(RedLocustBees)) { return; } BeeValues beeValues = (BeeValues)Utilities.GetEnemyData(__instance, new BeeValues()); if (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 bool spammyLogs = Script.Bools["spammyLogs"]; 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 == "spammyLogs") { spammyLogs = 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, logBlob && spammyLogs); 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 = LibraryCalls.GetEnemyList(type); LibraryCalls.GetInsideOrOutsideEnemyList(ref importEnemyList2, (EnemyAI)(object)__instance); if (Script.useCoroutines) { 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(insta
DLLs/fandovec03.NaturalSelectionLib.dll
Decompiled 7 months agousing 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.8.0.0")] [assembly: AssemblyInformationalVersion("0.8.0+2377ba0a81e08e1aab64f88d010752a8c8e16a67")] [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.8.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.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.8.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Library : BaseUnityPlugin { 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.8.0"; } public static void UpdateEnemyList(Type instanceType, List<EnemyAI> list) { if (!globalEnemyLists.ContainsKey(instanceType)) { LibraryLogger.LogError((object)$"EnemyLists does not contain {instanceType}!"); CreateEnemyList(instanceType, list); return; } 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; LibraryMethods.LibraryLogger = importLogger; LibraryMethods.debugLibrary = debuglibrary; LibraryMethods.debugSpam = spammyLogs; LibraryMethods.usePathfindingLib = usePathfindinglib; } } public class LibraryMethods { [CompilerGenerated] private sealed class <>c__DisplayClass15_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__15 : 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__DisplayClass15_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__15(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_064c: Unknown result type (might be due to invalid IL or missing references) //IL_0663: Unknown result type (might be due to invalid IL or missing references) //IL_07cd: Unknown result type (might be due to invalid IL or missing references) //IL_07e8: Unknown result type (might be due to invalid IL or missing references) //IL_080a: Unknown result type (might be due to invalid IL or missing references) //IL_081a: 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_0693; } <>1__state = -1; <>8__1 = new <>c__DisplayClass15_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_0989; IL_0693: 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_0767; IL_0977: <i>5__5++; goto IL_0989; IL_0989: 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_0977; } 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 ((<>8__1.__instance != null) & usePathLengthAsDistance) { <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_0693; } goto IL_0767; } if (debugLibrary) { LibraryLogger.LogError((object)(DebugStringHead(<>8__1.__instance) + " Enemy not found! Skipping...")); } } } goto IL_0977; } if (debugLibrary && debugSpam) { LibraryLogger.LogWarning((object)(DebugStringHead(<>8__1.__instance) + " FindClosestEnemyCoroutine returning " + DebugStringHead(importClosestEnemy))); } ReturnOwnerResultPairDelegate?.Invoke(importClosestEnemy); return false; IL_0767: 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_0977; } 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"); 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 //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) 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) { 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}"; } } else if (!(source is GameObject)) { text = ((source is Item) ? $"{((Item)source).itemName}, ID: {((Item)source).itemId}" : ((!(source is string)) ? "Unknown source" : ((string)source))); } else { EnemyAI source2 = default(EnemyAI); if (((GameObject)source).TryGetComponent<EnemyAI>(ref source2)) { return DebugStringHead(source2, shortFormat); } SandSpiderWebTrap source3 = default(SandSpiderWebTrap); if (((GameObject)source).TryGetComponent<SandSpiderWebTrap>(ref source3)) { return DebugStringHead(source3, shortFormat); } GrabbableObject source4 = default(GrabbableObject); if (((GameObject)source).TryGetComponent<GrabbableObject>(ref source4)) { return DebugStringHead(source4, shortFormat); } text = ((Object)(GameObject)source).name; } 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__15))] 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__15(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.8.0"; } } 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") && !Library.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; } } }