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.19.0")]
[assembly: AssemblyInformationalVersion("0.4.19+8609b5f5d89031bc791709eaaf73117893ea343c")]
[assembly: AssemblyProduct("NaturalSelection")]
[assembly: AssemblyTitle("fandovec03.NaturalSelection")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.19.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.19")]
[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.19".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.19"));
}
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.19";
}
}
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 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 an interval how often are internal global enemy lists updated. Default is one second.");
customSizeOverrideList = cfg.Bind<string>("DEV", "Custom size override list", "", "Set what size the enemy is considered as by the mod. Generates automatically empty.");
enableSpider = cfg.Bind<bool>("Entity settings", "Enable spider", true, "Apply changes to spider and modify it's behavior.");
enableSlime = cfg.Bind<bool>("Entity settings", "Enable slime", true, "Apply changes to slime and modify it's behavior.");
enableLeviathan = cfg.Bind<bool>("Entity settings", "Enable leviathan", true, "Apply changes to to leviathan and modify it's behavior.");
enableSporeLizard = cfg.Bind<bool>("DEV", "Enable SporeLizard", false, "Apply changes to spore lizard. \n\n Early build. DEV ONLY");
enableRedBees = cfg.Bind<bool>("Entity settings", "Enable Red bees (Circuit bees)", true, "Apply changes to red bees and modify it's behavior.");
enableNutcracker = cfg.Bind<bool>("DEV", "Enable Nutcracker", false, "Apply changes to apply to and modify its behavior. \n\n Early build. DEV ONLY");
enableGiant = cfg.Bind<bool>("Entity settings", "Enable Giant", true, "Apply changes to to forest giant.");
enableHoardingBug = cfg.Bind<bool>("DEV", "Enable Hoarding bug", false, "Apply changes to hoarding bug");
enableSpiderWebs = cfg.Bind<bool>("Entity settings", "Enable Spider Webs", true, "Apply changes to spider webs. Webs will stick to and slow enemies down.");
giantExtinguishChance = cfg.Bind<int>("Entity settings | Giant", "Extinguish chance", 33, new ConfigDescription("Chance of giants extinguishing themselves. Values are 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("Default chance bees will set giant on fire.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
beesSetGiantsOnFireMaxChance = cfg.Bind<float>("Entity settings | Giant", "Ignite giants max chace", 8f, new ConfigDescription("Chance bees will set giant on fire when bees are enraged.", (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, "Hygrodere will move towards other organisms to consume.");
blobAIOpeningDoorsMultiplier = cfg.Bind<float>("Entity settings | Hygrodere", "Open door multiplier", 0.7f, "Multiplier opening doors speed. 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 when leaving the moon.");
chaseAfterEnemiesModifier = cfg.Bind<float>("Entity settings | Spider/Spider Web", "Enemy chase timer modifier", 3f, "Set the chase timer for enemies from player chase timer by dividing it with set number. \n Formula: [Player chase timer : set number = Enemy chase timer]");
speedModifierList = cfg.Bind<string>("Entity settings | Spider/Spider Web", "Web speed modifiers", "", "Modify the final speed for enemy when stuck in spider webs. \n Formula: [Enemy speed when touching spider web : ((1 + number of web enemy is stuck in) * web strength) * set number] \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 web slow downs. Stronger spider webs slow enemies more. \n Formula: [Enemy speed when touching spider web : ((1 + number of web enemy is stuck in) * set number ) * web speed modifier]");
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_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_0144: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: 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_016c: Unknown result type (might be due to invalid IL or missing references)
//IL_0177: Unknown result type (might be due to invalid IL or missing references)
//IL_018f: 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_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_022b: Unknown result type (might be due to invalid IL or missing references)
//IL_0236: Unknown result type (might be due to invalid IL or missing references)
//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
//IL_025e: Unknown result type (might be due to invalid IL or missing references)
//IL_0269: Unknown result type (might be due to invalid IL or missing references)
//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
//IL_0297: 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, true) || ((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 && ((NetworkBehaviour)mainscript2).IsOwner)
{
if (((NetworkBehaviour)__instance).IsOwner && mainscript2.thisNetworkObject.IsSpawned)
{
BlobEatCorpseEvent(__instance).InvokeClients();
Script.LogNS((LogLevel)8, "consumed dead body of " + mainscript2.enemyType.enemyName, __instance);
if (((NetworkBehaviour)mainscript2).IsServer)
{
mainscript2.KillEnemy(true);
}
else
{
mainscript2.KillEnemyServerRpc(true);
}
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, debugTrigge