using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyCompany("LethalEscape")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("A template for Lethal Company")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LethalEscape")] [assembly: AssemblyTitle("LethalEscape")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace UpdatedEscape; internal class LETimerFunctions : MonoBehaviour { public static float MinuteEscapeTimerPuffer; public static float MinuteEscapeTimerBracken; public static float MinuteEscapeTimerHoardingBug; public static float MinuteEscapeTimerCoilHead; public static LETimerFunctions instance; private void Awake() { instance = this; } private void Update() { MinuteEscapeTimerBracken += Time.deltaTime; MinuteEscapeTimerHoardingBug += Time.deltaTime; MinuteEscapeTimerPuffer += Time.deltaTime; MinuteEscapeTimerCoilHead += Time.deltaTime; } } [BepInPlugin("xCeezy.LethalEscape", "Lethal Escape", "2.5.0")] public class Plugin : BaseUnityPlugin { public static class AIBridge { private static readonly Dictionary transitioningEnemies = new Dictionary(); public static bool IsTransitioning(EnemyAI enemy) { return transitioningEnemies.ContainsKey(enemy); } public static void RequestTransition(EnemyAI enemy) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (!transitioningEnemies.ContainsKey(enemy)) { bool flag = !enemy.isOutside; float maxPathDistance = (flag ? 150f : 40f); EntranceTeleport val = FindClosestReachableEntrance(((Component)enemy).transform.position, !flag, maxPathDistance, enemy.agent); if ((Object)(object)val != (Object)null) { enemy.SetDestinationToPosition(val.entrancePoint.position, false); transitioningEnemies[enemy] = val; mls.LogInfo((object)("AIBridge: " + enemy.enemyType.enemyName + " requested transition to " + (flag ? "Outside" : "Inside") + ". Pathing to " + ((Object)val).name + ".")); } else { mls.LogWarning((object)("AIBridge: " + enemy.enemyType.enemyName + " could not find a reachable entrance to transition " + (flag ? "Outside" : "Inside") + ".")); } } } public static void UpdateTransitions() { //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) if (transitioningEnemies.Count == 0) { return; } List list = new List(); foreach (KeyValuePair item in transitioningEnemies.ToList()) { EnemyAI key = item.Key; EntranceTeleport value = item.Value; if ((Object)(object)key == (Object)null || key.isEnemyDead) { list.Add(key); } else if (!key.agent.hasPath && ((Behaviour)key.agent).enabled) { mls.LogInfo((object)("AIBridge: " + key.enemyType.enemyName + " path to " + ((Object)value).name + " invalidated. Cancelling transition.")); list.Add(key); } else if (Vector3.Distance(((Component)key).transform.position, value.entrancePoint.position) < 2.5f) { mls.LogInfo((object)("AIBridge: " + key.enemyType.enemyName + " reached " + ((Object)value).name + ". Performing transition.")); if (key.isOutside) { SendEnemyInside(key, value); } else { SendEnemyOutside(key, spawnOnDoor: true, value); } list.Add(key); } } foreach (EnemyAI item2 in list) { if ((Object)(object)item2 != (Object)null && transitioningEnemies.ContainsKey(item2)) { transitioningEnemies.Remove(item2); } } } } private static Dictionary baboonsPathingToDoor = new Dictionary(); private static Dictionary baboonDoorTargets = new Dictionary(); private static Dictionary butlerPendingLeaveFacilityInfo = new Dictionary(); private static Dictionary baboonPathingCooldowns = new Dictionary(); private static Dictionary baboonDecisionTimers = new Dictionary(); private static Dictionary brackenOriginalNests = new Dictionary(); private static Dictionary brackenNestOutside = new Dictionary(); private static Dictionary brackenPathingCooldowns = new Dictionary(); private static Dictionary brackenDecisionTimers = new Dictionary(); private static Dictionary kiwiRevengeTargets = new Dictionary(); public static Vector3 LastButlerDeathPositionOutside; public static float LastButlerDeathTimeOutside = -1f; public static bool ButlerRecentlyDiedOutside = false; public static GameObject ExtraValues; private const string modGUID = "xCeezy.LethalEscape"; private const string modName = "Lethal Escape"; private const string modVersion = "1.0.7"; private Harmony _harmony = new Harmony("LethalEscape"); public static ManualLogSource mls; public static float TimeStartTeleport; public static ConfigEntry CanThumperEscape; public static ConfigEntry CanCaveDwellerEscape; public static ConfigEntry CanBrackenEscape; public static ConfigEntry CanJesterEscape; public static ConfigEntry CanHoardingBugEscape; public static ConfigEntry CanCoilHeadEscape; public static ConfigEntry CanSpiderEscape; public static ConfigEntry CanButlerReturnInside; public static ConfigEntry CanBrackenReturnInside; public static ConfigEntry CanThumperReturnInside; public static ConfigEntry CanJesterReturnInside; public static ConfigEntry CanHoardingBugReturnInside; public static ConfigEntry CanCoilHeadReturnInside; public static ConfigEntry CanSpiderReturnInside; public static ConfigEntry CanNutCrackerReturnInside; public static ConfigEntry CanClaySurgeonReturnInside; public static ConfigEntry CanHygrodereReturnInside; public static ConfigEntry CanPufferReturnInside; public static ConfigEntry CanCaveDwellerReturnInside; public static ConfigEntry CanNutCrackerEscape; public static ConfigEntry CanHygrodereEscape; public static ConfigEntry goofyahh; public static ConfigEntry BrackenChanceToGoInside; public static ConfigEntry BrackenInteriorPathRange; public static ConfigEntry BrackenExteriorPathRange; public static ConfigEntry BrackenPathCooldown; public static ConfigEntry CanBrackenMakeNestOutside; public static ConfigEntry BrackenNestOutsideChance; public static ConfigEntry CanKiwiEnterFacility; public static ConfigEntry KiwiChanceToEnterFacilityPerMinute; public static ConfigEntry KiwiChanceToExitFacilityPerMinute; public static ConfigEntry KiwiPathingCooldownConfig; public static ConfigEntry KiwiInteriorPathRangeConfig; public static ConfigEntry KiwiExteriorPathRangeConfig; public static ConfigEntry KiwiCanCarryEggsInOut; public static ConfigEntry KiwiCanMakeNestInside; public static ConfigEntry KiwiNestInsideChance; public static ConfigEntry ThumperChanceToEscapeEveryMinute; public static ConfigEntry JesterChanceToEscapeEveryMinute; public static ConfigEntry CaveDwellerChanceToEscapeEveryMinute; public static ConfigEntry CoilHeadChanceToEscapeEveryMinute; public static ConfigEntry SpiderChanceToEscapeEveryMinute; public static ConfigEntry NutCrackerChanceToEscapeEveryMinute; public static ConfigEntry HygrodereChanceToEscapeEveryMinute; public static ConfigEntry ButlerChanceToEscapeEveryMinute; public static ConfigEntry ClaySurgeonEscapeChance; public static ConfigEntry CanPufferEscape; public static ConfigEntry CanButlerEscape; public static ConfigEntry ButlerChanceToSpawnOutside; public static ConfigEntry CaveDwellerChanceToSpawnOutside; public static ConfigEntry CanClaySurgeonEscape; public static ConfigEntry ClaySurgeonChanceToSpawnOutside; public static ConfigEntry ButlerEscapeDelay; private static Dictionary kiwiPathingCooldowns = new Dictionary(); private static Dictionary kiwiDecisionTimers = new Dictionary(); private static Dictionary kiwiEnemyTargets = new Dictionary(); private static Dictionary kiwiLastTransitionTime = new Dictionary(); private static Dictionary oldBirdsPathingToDoor = new Dictionary(); private static Dictionary oldBirdPathingCooldowns = new Dictionary(); private static Dictionary oldBirdDecisionTimers = new Dictionary(); public static float JesterSpeedWindup; public static ConfigEntry BrackenChanceToEscapeEveryMinute; public static ConfigEntry PufferChanceToEscapeEveryMinute; public static ConfigEntry HoardingBugChanceToEscapeEveryMinute; public static ConfigEntry HoardingBugChanceToNestNearShip; public static ConfigEntry HoardingBugChanceToSpawnOutside; public static ConfigEntry BrackenChanceToSpawnOutside; public static ConfigEntry PufferChanceToSpawnOutside; public static ConfigEntry JesterChanceToSpawnOutside; public static ConfigEntry HygrodereChanceToSpawnOutside; public static ConfigEntry CanBaboonEnterFacility; public static ConfigEntry BaboonChanceToEnterFacilityPerMinute; public static ConfigEntry BaboonChanceToExitFacilityPerMinute; public static ConfigEntry BaboonPathingCooldownConfig; public static ConfigEntry BaboonInteriorPathRangeConfig; public static ConfigEntry BaboonExteriorPathRangeConfig; public static ConfigEntry BaboonCanCarryScrapInOut; public static ConfigEntry CanOldBirdEnterFacility; public static ConfigEntry OldBirdChanceToEnterFacilityPerMinute; public static ConfigEntry OldBirdChanceToExitFacilityPerMinute; public static ConfigEntry OldBirdPathingCooldownConfig; public static ConfigEntry OldBirdInteriorPathRangeConfig; public static ConfigEntry OldBirdExteriorPathRangeConfig; public static ConfigEntry NutCrackerChanceToSpawnOutside; public static ConfigEntry ThumperChanceToSpawnOutside; public static ConfigEntry SpiderChanceToSpawnOutside; public static ConfigEntry JesterSpeedIncreasePerSecond; public static ConfigEntry MaxJesterOutsideSpeed; public static ConfigEntry BrackenEscapeDelay; public static ConfigEntry ThumperEscapeDelay; public static ConfigEntry SpiderMinWebsOutside; public static ConfigEntry SpiderMaxWebsOutside; private void Awake() { //IL_0b3f: Unknown result type (might be due to invalid IL or missing references) //IL_0b49: Expected O, but got Unknown CanThumperEscape = ((BaseUnityPlugin)this).Config.Bind("Can Monster Escape", "ThumperEscape", true, "Whether or not the Thumper can escape"); CanBrackenEscape = ((BaseUnityPlugin)this).Config.Bind("Can Monster Escape", "BrackenEscape", true, "Whether or not the Bracken can escape"); CanJesterEscape = ((BaseUnityPlugin)this).Config.Bind("Can Monster Escape", "JesterEscape", true, "Whether or not the Jester can escape"); CanBrackenReturnInside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "BrackenCanReturnInside", true, "Whether or not the Bracken can return inside the facility after escaping"); CanThumperReturnInside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "ThumperCanReturnInside", true, "Whether or not the Thumper can return inside the facility after escaping"); CanJesterReturnInside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "JesterCanReturnInside", true, "Whether or not the Jester can return inside the facility after escaping"); CanHoardingBugReturnInside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "HoardingBugCanReturnInside", true, "Whether or not the Hoarding Bug can return inside the facility after escaping"); CanCoilHeadReturnInside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "CoilHeadCanReturnInside", true, "Whether or not the Coil Head can return inside the facility after escaping"); CanSpiderReturnInside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "SpiderCanReturnInside", true, "Whether or not the Spider can return inside the facility after escaping"); CanNutCrackerReturnInside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "NutCrackerCanReturnInside", true, "Whether or not the Nutcracker can return inside the facility after escaping"); CanClaySurgeonReturnInside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "ClaySurgeonCanReturnInside", true, "Whether or not the Clay Surgeon can return inside the facility after escaping"); CanHygrodereReturnInside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "HygrodereCanReturnInside", true, "Whether or not the Hygrodere/Slime can return inside the facility after escaping"); CanPufferReturnInside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "PufferCanReturnInside", true, "Whether or not the Puffer/Spore Lizard can return inside the facility after escaping"); CanCaveDwellerReturnInside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "CaveDwellerCanReturnInside", true, "Whether or not the Cave Dweller can return inside the facility after escaping"); CanHoardingBugEscape = ((BaseUnityPlugin)this).Config.Bind("Can Monster Escape", "HoardingBugEscape", true, "Whether or not the Hoarding Bugs can escape"); CanCaveDwellerEscape = ((BaseUnityPlugin)this).Config.Bind("Can Monster Escape", "CaveDwellerEscape", true, "Whether or not the Cave Dweller can escape"); CaveDwellerChanceToSpawnOutside = ((BaseUnityPlugin)this).Config.Bind("Spawn Escape Settings", "CaveDwellerSpawnOutsideChance", 10f, "The chance that the Cave Dweller will spawn outside"); CanCoilHeadEscape = ((BaseUnityPlugin)this).Config.Bind("Can Monster Escape", "CoilHeadEscape", true, "Whether or not Coil Head can escape"); CanSpiderEscape = ((BaseUnityPlugin)this).Config.Bind("Can Monster Escape", "SpiderEscape", true, "Whether or not the Spider can escape"); CanClaySurgeonEscape = ((BaseUnityPlugin)this).Config.Bind("Can Monster Escape", "ClaySurgeonEscape", true, "Whether or not the Clay Surgeon can escape"); ClaySurgeonChanceToSpawnOutside = ((BaseUnityPlugin)this).Config.Bind("Spawn Escape Settings", "ClaySurgeonSpawnOutsideChance", 10f, "The chance that the Clay Surgeon will spawn outside"); CanNutCrackerEscape = ((BaseUnityPlugin)this).Config.Bind("Can Monster Escape", "NutCrackerEscape", true, "Whether or not the Nut Cracker can escape"); CanHygrodereEscape = ((BaseUnityPlugin)this).Config.Bind("Can Monster Escape", "HygrodereEscape", false, "Whether or not the Hygrodere/Slime can escape"); CanPufferEscape = ((BaseUnityPlugin)this).Config.Bind("Can Monster Escape", "CanPufferEscape", true, "Whether or not the Puffer/Spore Lizard can escape"); ThumperChanceToSpawnOutside = ((BaseUnityPlugin)this).Config.Bind("Spawn Escape Settings", "ThumperSpawnOutsideChance", 5f, "The chance that the Thumper will spawn outside"); BrackenChanceToSpawnOutside = ((BaseUnityPlugin)this).Config.Bind("Spawn Escape Settings", "BrackenSpawnOutsideChance", 5f, "The chance that the Bracken will spawn outside"); JesterChanceToSpawnOutside = ((BaseUnityPlugin)this).Config.Bind("Spawn Escape Settings", "JesterSpawnOutsideChance", 0f, "The chance that the Jester will spawn outside"); HoardingBugChanceToSpawnOutside = ((BaseUnityPlugin)this).Config.Bind("Spawn Escape Settings", "HoardingBugSpawnOutsideChance", 15f, "The chance that the Hoarding Bug will spawn outside"); SpiderChanceToSpawnOutside = ((BaseUnityPlugin)this).Config.Bind("Spawn Escape Settings", "SpiderSpawnOutsideChance", 5f, "The chance that the Spider will spawn outside"); NutCrackerChanceToSpawnOutside = ((BaseUnityPlugin)this).Config.Bind("Spawn Escape Settings", "NutCrackerSpawnOutsideChance", 5f, "The chance that the NutCracker will spawn outside"); HygrodereChanceToSpawnOutside = ((BaseUnityPlugin)this).Config.Bind("Spawn Escape Settings", "HygrodereSpawnOutsideChance", 0f, "The chance that the Hygrodere will spawn outside"); PufferChanceToSpawnOutside = ((BaseUnityPlugin)this).Config.Bind("Spawn Escape Settings", "PufferSpawnOutsideChance", 5f, "The chance that the Puffer will spawn outside"); CanButlerReturnInside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "ButlerCanReturnInside", true, "Whether or not the Butler can return inside the facility after escaping to follow its target."); CanButlerEscape = ((BaseUnityPlugin)this).Config.Bind("Can Monster Escape", "ButlerEscape", true, "Whether or not the Butler can escape"); ButlerChanceToSpawnOutside = ((BaseUnityPlugin)this).Config.Bind("Spawn Escape Settings", "ButlerSpawnOutsideChance", 5f, "The chance that the Butler will spawn outside"); ButlerEscapeDelay = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Butler Escape Delay", 7f, "Time it takes for the Butler to follow a player outside"); ClaySurgeonEscapeChance = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "ClaySurgeonEscapeChance", 5f, "The chance that the Clay Surgeon will escape randomly every minute"); PufferChanceToEscapeEveryMinute = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Puffer Escape Chance", 5f, "The chance that the Puffer/Spore Lizard will escape randomly every minute"); BrackenChanceToEscapeEveryMinute = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Bracken Escape Chance", 6f, "The chance that the Bracken will escape randomly every minute"); HoardingBugChanceToEscapeEveryMinute = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "HoardingBug Escape Chance", 8f, "The chance that the Hoarding Bug will escape randomly every minute"); HoardingBugChanceToNestNearShip = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "HoardingBugShipNestChance", 25f, "The chance that the Hoarding Bug will make their nest at/near the ship"); BrackenEscapeDelay = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Bracken Escape Delay", 7f, "Time it takes for the Bracken to follow a player outside"); ThumperEscapeDelay = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Thumper Escape Delay", -5f, "Time it takes for the Thumper to follow a player outside which is based on how long the player was seen minus this value (Might break when under -15 and will force thumper outside when it sees someone when above 0)"); SpiderMaxWebsOutside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Max Spider Webs Outside", 15, "The maximum amount of spider webs the game will allow the spider to create webs outside (Vanilla game is 7 or 9 if update 47)"); SpiderMinWebsOutside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Min Spider Webs Outside", 10, "The minimum amount of spider webs the game will allow the spider to create webs outside (Vanilla game is 4 or 6 if update 47)"); goofyahh = ((BaseUnityPlugin)this).Config.Bind("General", "Message Settings", true, "Enable or disable the message when the ship lands."); JesterSpeedIncreasePerSecond = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Jester Speed Increase", 1f, "How much speed the jester gets per second"); MaxJesterOutsideSpeed = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Jester Outside Speed", 8f, "The max speed the Jester moves while outside (5 is the speed its at while in the box and 18 is jesters max speed inside the facility)"); BrackenChanceToGoInside = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Bracken Chance To Go Inside", 5f, "The chance that the Bracken will go back inside randomly every minute"); BrackenInteriorPathRange = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Bracken Interior Path Range", 20, "Range at which Bracken can detect entrances while inside"); BrackenExteriorPathRange = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Bracken Exterior Path Range", 120, "Range at which Bracken can detect entrances while outside"); BrackenPathCooldown = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Bracken Path Cooldown", 30f, "Cooldown between Bracken pathing attempts"); CanBrackenMakeNestOutside = ((BaseUnityPlugin)this).Config.Bind("Bracken Settings", "BrackenCanMakeNestOutside", true, "Whether a Bracken can choose an exterior nest at the start of a round."); BrackenNestOutsideChance = ((BaseUnityPlugin)this).Config.Bind("Bracken Settings", "BrackenNestOutsideChance", 12f, "Chance for a Bracken to establish its nest outside. Interior nests remain the common case."); CanKiwiEnterFacility = ((BaseUnityPlugin)this).Config.Bind("Giant Sapsucker Settings", "KiwiCanEnterFacility", true, "Whether or not the Giant Sapsucker can enter the facility."); KiwiChanceToEnterFacilityPerMinute = ((BaseUnityPlugin)this).Config.Bind("Giant Sapsucker Settings", "KiwiChanceToEnterFacilityPerMinute", 5f, "Chance per minute for a Kiwi (with no other objective) to try and enter the facility."); KiwiChanceToExitFacilityPerMinute = ((BaseUnityPlugin)this).Config.Bind("Giant Sapsucker Settings", "KiwiChanceToExitFacilityPerMinute", 15f, "Chance per minute for a Kiwi inside (with no other objective) to try and exit the facility."); KiwiPathingCooldownConfig = ((BaseUnityPlugin)this).Config.Bind("Giant Sapsucker Settings", "KiwiPathingCooldown", 25f, "Cooldown in seconds between a Kiwi attempting to find an entrance/exit."); KiwiInteriorPathRangeConfig = ((BaseUnityPlugin)this).Config.Bind("Giant Sapsucker Settings", "KiwiInteriorPathRange", 40, "Max NavMesh path distance (in units) a Kiwi can be from an exit to path to it while inside."); KiwiExteriorPathRangeConfig = ((BaseUnityPlugin)this).Config.Bind("Giant Sapsucker Settings", "KiwiExteriorPathRange", 70, "Max NavMesh path distance (in units) a Kiwi can be from an entrance to path to it while outside."); KiwiCanCarryEggsInOut = ((BaseUnityPlugin)this).Config.Bind("Giant Sapsucker Settings", "KiwiCanCarryEggsInOut", true, "If true, Kiwis will attempt to carry eggs into/out of the facility to return them to their nest (if nest is outside)."); KiwiCanMakeNestInside = ((BaseUnityPlugin)this).Config.Bind("Giant Sapsucker Settings", "KiwiCanMakeNestInside", false, "Whether the Giant Sapsucker can make its primary nest inside the facility."); KiwiNestInsideChance = ((BaseUnityPlugin)this).Config.Bind("Giant Sapsucker Settings", "KiwiNestInsideChance", 0f, "If KiwiCanMakeNestInside is true, this is the chance it will choose to do so at the start of a round."); CanBaboonEnterFacility = ((BaseUnityPlugin)this).Config.Bind("Baboon Hawk Settings", "BaboonCanEnterFacility", true, "Whether or not the Baboon Hawk can enter the facility."); BaboonChanceToEnterFacilityPerMinute = ((BaseUnityPlugin)this).Config.Bind("Baboon Hawk Settings", "BaboonChanceToEnterFacilityPerMinute", 3f, "Chance per minute for a Baboon Hawk (with no other objective) to try and enter the facility."); BaboonChanceToExitFacilityPerMinute = ((BaseUnityPlugin)this).Config.Bind("Baboon Hawk Settings", "BaboonChanceToExitFacilityPerMinute", 10f, "Chance per minute for a Baboon Hawk inside (with no other objective) to try and exit the facility."); BaboonPathingCooldownConfig = ((BaseUnityPlugin)this).Config.Bind("Baboon Hawk Settings", "BaboonPathingCooldown", 30f, "Cooldown in seconds between a Baboon Hawk attempting to find an entrance/exit."); BaboonInteriorPathRangeConfig = ((BaseUnityPlugin)this).Config.Bind("Baboon Hawk Settings", "BaboonInteriorPathRange", 50, "Max NavMesh path distance (in units) a Baboon Hawk can be from an exit to path to it while inside."); BaboonExteriorPathRangeConfig = ((BaseUnityPlugin)this).Config.Bind("Baboon Hawk Settings", "BaboonExteriorPathRange", 80, "Max NavMesh path distance (in units) a Baboon Hawk can be from an entrance to path to it while outside."); CanOldBirdEnterFacility = ((BaseUnityPlugin)this).Config.Bind("Old Bird Settings", "CanOldBirdEnterFacility", true, "Whether or not the Old Bird can enter the facility."); OldBirdChanceToEnterFacilityPerMinute = ((BaseUnityPlugin)this).Config.Bind("Old Bird Settings", "OldBirdChanceToEnterFacilityPerMinute", 2f, "Chance per minute for an Old Bird (with no other objective) to try and enter the facility."); OldBirdChanceToExitFacilityPerMinute = ((BaseUnityPlugin)this).Config.Bind("Old Bird Settings", "OldBirdChanceToExitFacilityPerMinute", 8f, "Chance per minute for an Old Bird inside (with no other objective) to try and exit the facility."); OldBirdPathingCooldownConfig = ((BaseUnityPlugin)this).Config.Bind("Old Bird Settings", "OldBirdPathingCooldown", 35f, "Cooldown in seconds between an Old Bird attempting to find an entrance/exit."); OldBirdInteriorPathRangeConfig = ((BaseUnityPlugin)this).Config.Bind("Old Bird Settings", "OldBirdInteriorPathRange", 60, "Max NavMesh path distance (in units) an Old Bird can be from an exit to path to it while inside."); OldBirdExteriorPathRangeConfig = ((BaseUnityPlugin)this).Config.Bind("Old Bird Settings", "OldBirdExteriorPathRange", 90, "Max NavMesh path distance (in units) an Old Bird can be from an entrance to path to it while outside."); BaboonCanCarryScrapInOut = ((BaseUnityPlugin)this).Config.Bind("Baboon Hawk Settings", "BaboonCanCarryScrapInOut", true, "If true, Baboon Hawks will attempt to carry scrap into/out of the facility to return them to their camp (if camp is outside)."); ThumperChanceToEscapeEveryMinute = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Thumper Escape Chance", 5f, "The chance that the Thumper will escape randomly every minute"); JesterChanceToEscapeEveryMinute = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Jester Escape Chance", 0f, "The chance that the Jester will escape randomly every minute."); CaveDwellerChanceToEscapeEveryMinute = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Cave Dweller Escape Chance", 5f, "The chance that the Cave Dweller will escape randomly every minute"); CoilHeadChanceToEscapeEveryMinute = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Coil Head Escape Chance", 5f, "The chance that the Coil Head will escape randomly every minute"); SpiderChanceToEscapeEveryMinute = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Spider Escape Chance", 5f, "The chance that the Spider will escape randomly every minute"); NutCrackerChanceToEscapeEveryMinute = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "NutCracker Escape Chance", 5f, "The chance that the Nutcracker will escape randomly every minute"); HygrodereChanceToEscapeEveryMinute = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Hygrodere Escape Chance", 0f, "The chance that the Hygrodere/Slime will escape randomly every minute"); ButlerChanceToEscapeEveryMinute = ((BaseUnityPlugin)this).Config.Bind("Escape Settings", "Butler Escape Chance", 5f, "The chance that the Butler will escape randomly every minute"); if ((Object)(object)ExtraValues == (Object)null) { ExtraValues = new GameObject(); Object.DontDestroyOnLoad((Object)(object)ExtraValues); ((Object)ExtraValues).hideFlags = (HideFlags)61; ExtraValues.AddComponent(); } mls = ((BaseUnityPlugin)this).Logger; mls.LogInfo((object)"Loaded xCeezy.LethalEscape. Patching."); _harmony.PatchAll(typeof(Plugin)); } [HarmonyPatch(typeof(CrawlerAI), "Update")] [HarmonyPrefix] private static bool CrawlerLEPrefixAI(CrawlerAI __instance) { if (((EnemyAI)__instance).isEnemyDead) { return true; } if (AIBridge.IsTransitioning((EnemyAI)(object)__instance)) { return false; } if (CanThumperEscape.Value && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { if (!((EnemyAI)__instance).isOutside) { if (((EnemyAI)__instance).currentBehaviourStateIndex != 0 && __instance.noticePlayerTimer < ThumperEscapeDelay.Value && (Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && !((EnemyAI)__instance).targetPlayer.isInsideFactory) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } } else { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && ((EnemyAI)__instance).targetPlayer.isInsideFactory && CanThumperReturnInside.Value) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } } } return true; } [HarmonyPatch(typeof(CrawlerAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void ThumperAILEOutsideAttack(CrawlerAI __instance, ref Collider other) { //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) if (!((EnemyAI)__instance).isEnemyDead && ((EnemyAI)__instance).isOutside && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && !component.isPlayerDead && component.isPlayerControlled && (Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController && !(Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").GetValue() <= 0.65f) && !(((EnemyAI)__instance).stunNormalizedTimer > 0f)) { Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").SetValue((object)0f); ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); component.DamagePlayer(40, true, true, (CauseOfDeath)6, 0, false, default(Vector3)); component.DamagePlayerFromOtherClientServerRpc(40, Vector3.zero, -1); ((EnemyAI)__instance).agent.speed = 0f; __instance.HitPlayerServerRpc((int)component.playerClientId); component.JumpToFearLevel(1f, true); } } } [HarmonyPatch(typeof(CrawlerAI), "Start")] [HarmonyPostfix] private static void CrawlerAILEPostfixStart(CrawlerAI __instance) { if (((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && ThumperChanceToSpawnOutside.Value != 0f && (float)Random.Range(1, 100) <= ThumperChanceToSpawnOutside.Value) { SendEnemyOutside((EnemyAI)(object)__instance); } } [HarmonyPatch(typeof(JesterAI), "Update")] [HarmonyPrefix] private static bool JesterLEPrefixAI(JesterAI __instance) { if (((EnemyAI)__instance).isEnemyDead) { return true; } if (AIBridge.IsTransitioning((EnemyAI)(object)__instance)) { return false; } if (CanJesterEscape.Value && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { if (!((EnemyAI)__instance).isOutside) { if (((EnemyAI)__instance).currentBehaviourStateIndex == 2 && (Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && !((EnemyAI)__instance).targetPlayer.isInsideFactory) { JesterSpeedWindup = 0f; AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } } else { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && ((EnemyAI)__instance).targetPlayer.isInsideFactory && CanJesterReturnInside.Value) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } } } return true; } [HarmonyPatch(typeof(JesterAI), "Update")] [HarmonyPostfix] private static void JesterLEPostfixAI(JesterAI __instance) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) if (!CanJesterEscape.Value || !((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost || !((EnemyAI)__instance).isOutside) { return; } if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } bool flag = false; PlayerControllerB val = null; float num = float.MaxValue; for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++) { PlayerControllerB val2 = StartOfRound.Instance.allPlayerScripts[i]; if (val2.isPlayerControlled && !val2.isInsideFactory) { flag = true; float num2 = Vector3.Distance(((Component)__instance).transform.position, ((Component)val2).transform.position); if (num2 < num) { num = num2; val = val2; } } } NavMeshHit val3 = default(NavMeshHit); if (flag && (Object)(object)val != (Object)null) { ((EnemyAI)__instance).SwitchToBehaviourState(2); ((EnemyAI)__instance).agent.stoppingDistance = 0f; ((EnemyAI)__instance).targetPlayer = val; ((EnemyAI)__instance).SetMovingTowardsTargetPlayer(val); ((EnemyAI)__instance).agent.isStopped = false; } if (NavMesh.SamplePosition(((Component)__instance).transform.position + Random.insideUnitSphere * 10f, ref val3, 10f, -1)) { ((EnemyAI)__instance).agent.SetDestination(((NavMeshHit)(ref val3)).position); } JesterSpeedWindup = Mathf.Clamp(JesterSpeedWindup + Time.deltaTime * JesterSpeedIncreasePerSecond.Value, 0f, MaxJesterOutsideSpeed.Value); ((EnemyAI)__instance).agent.speed = JesterSpeedWindup; } [HarmonyPatch(typeof(JesterAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void JesterAILEOutsideAttack(JesterAI __instance, ref Collider other) { if (!((EnemyAI)__instance).isEnemyDead && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && ((EnemyAI)__instance).isOutside) { if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && !component.isPlayerDead && component.isPlayerControlled && (Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController && ((EnemyAI)__instance).currentBehaviourStateIndex == 2) { __instance.KillPlayerServerRpc((int)component.playerClientId); } } } [HarmonyPatch(typeof(JesterAI), "Start")] [HarmonyPostfix] private static void JesterAILEPostfixStart(JesterAI __instance) { if (((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && JesterChanceToSpawnOutside.Value != 0f && (float)Random.Range(1, 100) <= JesterChanceToSpawnOutside.Value) { SendEnemyOutside((EnemyAI)(object)__instance); } } [HarmonyPatch(typeof(HoarderBugAI), "Update")] [HarmonyPrefix] private static bool HoardingBugAILEPrefixAI(HoarderBugAI __instance) { //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) if (((EnemyAI)__instance).isEnemyDead) { return true; } if (AIBridge.IsTransitioning((EnemyAI)(object)__instance)) { return false; } if (CanHoardingBugEscape.Value && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { if (!((EnemyAI)__instance).isOutside) { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && !((EnemyAI)__instance).targetPlayer.isInsideFactory && __instance.searchForPlayer.inProgress) { AIBridge.RequestTransition((EnemyAI)(object)__instance); Traverse.Create((object)__instance).Field("choseNestPosition").SetValue((object)false); return false; } if (LETimerFunctions.MinuteEscapeTimerHoardingBug >= 60f && (Object)(object)((EnemyAI)__instance).targetPlayer == (Object)null) { LETimerFunctions.MinuteEscapeTimerHoardingBug = 0f; Object[] array = Object.FindObjectsOfType(typeof(HoarderBugAI)); float num = ((array.Length != 0) ? ((float)array.Length) : 1f); if (num == 0f) { num = 1f; } if ((float)Random.Range(1, 100) <= HoardingBugChanceToEscapeEveryMinute.Value / num) { AIBridge.RequestTransition((EnemyAI)(object)__instance); if (HoardingBugChanceToNestNearShip.Value != 0f && (float)Random.Range(1, 100) <= HoardingBugChanceToNestNearShip.Value) { Vector3 val = RoundManager.FindMainEntrancePosition(true, true); if (val == Vector3.zero) { if ((Object)(object)StartOfRound.Instance.shipDoorNode != (Object)null) { val = ((Component)StartOfRound.Instance.shipDoorNode).transform.position; } else { val = StartOfRound.Instance.elevatorTransform.position; mls.LogWarning((object)"HoardingBugAILEPrefixAI: shipDoorNode is null, using elevatorTransform as fallback for ship reference."); } } Transform val2 = ((EnemyAI)__instance).ChooseClosestNodeToPosition(val, true, 2); if ((Object)(object)val2 != (Object)null) { __instance.nestPosition = val2.position; Traverse.Create((object)__instance).Field("choseNestPosition").SetValue((object)true); Traverse.Create((object)__instance).Method("SyncNestPositionServerRpc", new object[1] { __instance.nestPosition }).GetValue(); mls.LogInfo((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (escaped) set OUTSIDE nest near ship at: {__instance.nestPosition}"); } else { mls.LogWarning((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (escaped) failed to find OUTSIDE nest node near ship. `choseNestPosition` set to false."); Traverse.Create((object)__instance).Field("choseNestPosition").SetValue((object)false); } } else { Traverse.Create((object)__instance).Field("choseNestPosition").SetValue((object)false); } return false; } } } else { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && ((EnemyAI)__instance).targetPlayer.isInsideFactory && CanHoardingBugReturnInside.Value) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } } } return true; } [HarmonyPatch(typeof(HoarderBugAI), "Update")] [HarmonyPostfix] private static void HoardingBugAILEFleeFromKiwi(HoarderBugAI __instance) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost || ((EnemyAI)__instance).isEnemyDead) { return; } GiantKiwiAI[] array = Object.FindObjectsOfType(); foreach (GiantKiwiAI val in array) { if (!((EnemyAI)val).isEnemyDead && !(Vector3.Distance(((Component)__instance).transform.position, ((Component)val).transform.position) > 25f) && (Traverse.Create((object)val).Field("attacking").Value || kiwiEnemyTargets.TryGetValue(val, out var _))) { Vector3 val2 = ((Component)__instance).transform.position - ((Component)val).transform.position; val2.y = 0f; if (((Vector3)(ref val2)).magnitude < 0.1f) { val2 = ((Component)__instance).transform.forward; } Vector3 val3 = ((Component)__instance).transform.position + ((Vector3)(ref val2)).normalized * 15f; ((EnemyAI)__instance).agent.speed = 8f; ((EnemyAI)__instance).SetDestinationToPosition(val3, false); Traverse.Create((object)__instance).Field("inChase").SetValue((object)false); mls.LogInfo((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} is fleeing from angry Kiwi {((Object)val).GetInstanceID()}!"); break; } } } [HarmonyPatch(typeof(HoarderBugAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void HoardingBugAILEOutsideAttack(HoarderBugAI __instance, ref Collider other) { //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) if (((EnemyAI)__instance).isEnemyDead || !((EnemyAI)__instance).isOutside || !((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { return; } PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && !component.isPlayerDead && component.isPlayerControlled && (Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController) { float value = Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").GetValue(); bool value2 = Traverse.Create((object)__instance).Field("inChase").GetValue(); if (!(value <= 0.5f) && !(((EnemyAI)__instance).stunNormalizedTimer > 0f) && value2) { Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").SetValue((object)0f); component.DamagePlayer(30, true, true, (CauseOfDeath)6, 0, false, default(Vector3)); component.DamagePlayerFromOtherClientServerRpc(30, Vector3.zero, -1); __instance.HitPlayerServerRpc(); } } } [HarmonyPatch(typeof(EnemyAI), "ChooseFarthestNodeFromPosition")] [HarmonyPrefix] private static bool ChooseFarthestNodeFromPosition_Prefix(EnemyAI __instance, ref Transform __result, Vector3 pos, bool avoidLineOfSight = false, int offset = 0, bool doAsync = false, int maxAsyncIterations = 50, bool capDistance = false) { if (__instance.allAINodes.Any((GameObject node) => (Object)(object)node == (Object)null)) { __instance.allAINodes = __instance.allAINodes.Where((GameObject node) => (Object)(object)node != (Object)null).ToArray(); mls.LogWarning((object)("LethalEscape: Cleaned null entries from AINode array for " + ((object)__instance).GetType().Name + ". This prevented a crash.")); } return true; } [HarmonyPatch(typeof(EnemyAI), "ChooseClosestNodeToPosition")] [HarmonyPrefix] private static bool ChooseClosestNodeToPosition_Prefix(EnemyAI __instance, ref Transform __result, Vector3 pos, bool avoidLineOfSight = false, int offset = 0) { if (__instance.allAINodes.Any((GameObject node) => (Object)(object)node == (Object)null)) { __instance.allAINodes = __instance.allAINodes.Where((GameObject node) => (Object)(object)node != (Object)null).ToArray(); mls.LogWarning((object)("LethalEscape: Cleaned null entries from AINode array for " + ((object)__instance).GetType().Name + ". This prevented a crash.")); } return true; } [HarmonyPatch(typeof(HoarderBugAI), "Start")] [HarmonyPostfix] private static void HoardingBugAILEPostfixStart(HoarderBugAI __instance) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost || HoardingBugChanceToSpawnOutside.Value == 0f || !((float)Random.Range(1, 100) <= HoardingBugChanceToSpawnOutside.Value)) { return; } SendEnemyOutside((EnemyAI)(object)__instance); if (((EnemyAI)__instance).isOutside && HoardingBugChanceToNestNearShip.Value != 0f && (float)Random.Range(1, 100) <= HoardingBugChanceToNestNearShip.Value) { Vector3 val = RoundManager.FindMainEntrancePosition(true, true); if (val == Vector3.zero) { if ((Object)(object)StartOfRound.Instance.shipDoorNode != (Object)null) { val = ((Component)StartOfRound.Instance.shipDoorNode).transform.position; } else { val = StartOfRound.Instance.elevatorTransform.position; mls.LogWarning((object)"HoardingBugAILEPostfixStart: shipDoorNode is null, using elevatorTransform as fallback for ship reference."); } } Transform val2 = ((EnemyAI)__instance).ChooseClosestNodeToPosition(val, true, 2); if ((Object)(object)val2 != (Object)null) { __instance.nestPosition = val2.position; Traverse.Create((object)__instance).Field("choseNestPosition").SetValue((object)true); Traverse.Create((object)__instance).Method("SyncNestPositionServerRpc", new object[1] { __instance.nestPosition }).GetValue(); mls.LogInfo((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (spawned outside) set OUTSIDE nest near ship at: {__instance.nestPosition}"); } else { mls.LogWarning((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (spawned outside) failed to set OUTSIDE nest near ship. `choseNestPosition` = false."); Traverse.Create((object)__instance).Field("choseNestPosition").SetValue((object)false); } } else if (((EnemyAI)__instance).isOutside) { Traverse.Create((object)__instance).Field("choseNestPosition").SetValue((object)false); } } [HarmonyPatch(typeof(HoarderBugAI), "ChooseNestPosition")] [HarmonyPostfix] private static void HoarderBugAI_ChooseNestPosition_Postfix(HoarderBugAI __instance) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: 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_01af: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_0447: 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_03be: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Expected O, but got Unknown //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Unknown result type (might be due to invalid IL or missing references) //IL_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_03e8: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_0398: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_049c: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Invalid comparison between Unknown and I4 //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost || !((EnemyAI)__instance).isOutside || ((EnemyAI)__instance).isEnemyDead) { return; } bool flag = false; int areaFromName = NavMesh.GetAreaFromName("Terrain"); int num = ((areaFromName != -1) ? (1 << areaFromName) : (-1)); if (__instance.nestPosition == Vector3.zero) { flag = true; mls.LogWarning((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (outside): Nest position is zero after vanilla ChooseNestPosition. Forcing new outside nest choice."); } else { NavMeshPath val = new NavMeshPath(); int areaMask = ((EnemyAI)__instance).agent.areaMask; if (num != -1) { ((EnemyAI)__instance).agent.areaMask = num; } bool num2 = ((EnemyAI)__instance).agent.CalculatePath(__instance.nestPosition, val); ((EnemyAI)__instance).agent.areaMask = areaMask; if (!num2 || (int)val.status != 0) { flag = true; mls.LogInfo((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (outside): Current nest at {__instance.nestPosition} is not pathable on OUTSIDE NavMesh (Path status: {val.status}). Choosing new outside nest."); } else { mls.LogInfo((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (outside): Current nest at {__instance.nestPosition} is pathable on OUTSIDE NavMesh. Postfix deems it valid."); } } if (!flag) { return; } mls.LogInfo((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (outside) needs a new OUTSIDE nest."); Vector3 val2 = Vector3.zero; HoarderBugAI[] array = Object.FindObjectsOfType(); float num3 = float.MaxValue; Vector3 val3 = Vector3.zero; HoarderBugAI[] array2 = array; foreach (HoarderBugAI val4 in array2) { if (!((Object)(object)val4 != (Object)(object)__instance) || !((EnemyAI)val4).isOutside || !Traverse.Create((object)val4).Field("choseNestPosition").GetValue() || !(val4.nestPosition != Vector3.zero)) { continue; } NavMeshPath val5 = new NavMeshPath(); int areaMask2 = ((EnemyAI)__instance).agent.areaMask; if (num != -1) { ((EnemyAI)__instance).agent.areaMask = num; } bool num4 = ((EnemyAI)__instance).agent.CalculatePath(val4.nestPosition, val5) && (int)val5.status == 0; ((EnemyAI)__instance).agent.areaMask = areaMask2; if (num4) { float num5 = Vector3.Distance(((Component)__instance).transform.position, val4.nestPosition); if (num5 < num3) { num3 = num5; val3 = val4.nestPosition; } } } if (val3 != Vector3.zero) { val2 = val3; mls.LogInfo((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (outside) will share OUTSIDE nest at {val2}."); } else { Transform val6 = ((EnemyAI)__instance).ChooseClosestNodeToPosition(((Component)__instance).transform.position, true, Random.Range(0, 3)); if ((Object)(object)val6 != (Object)null) { val2 = val6.position; mls.LogInfo((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (outside) chose new personal OUTSIDE nest at {val2}."); } else { mls.LogError((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (outside) FAILED to find any suitable outside node for its nest! This is problematic."); Vector3 val7 = RoundManager.FindMainEntrancePosition(true, true); if (val7 == Vector3.zero) { val7 = ((!((Object)(object)StartOfRound.Instance.shipDoorNode != (Object)null)) ? StartOfRound.Instance.elevatorTransform.position : ((Component)StartOfRound.Instance.shipDoorNode).transform.position); } val6 = ((EnemyAI)__instance).ChooseClosestNodeToPosition(val7, true, 0); if ((Object)(object)val6 != (Object)null) { val2 = val6.position; } else { mls.LogError((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (outside) FAILED even fallback nest selection."); } if (val2 == Vector3.zero) { return; } } } if (val2 != Vector3.zero && Vector3.Distance(__instance.nestPosition, val2) > 0.1f) { __instance.nestPosition = val2; Traverse.Create((object)__instance).Method("SyncNestPositionServerRpc", new object[1] { __instance.nestPosition }).GetValue(); Traverse.Create((object)__instance).Field("choseNestPosition").SetValue((object)true); mls.LogInfo((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (outside) nest updated by postfix to: {__instance.nestPosition}"); } else if (val2 != Vector3.zero && !Traverse.Create((object)__instance).Field("choseNestPosition").Value) { Traverse.Create((object)__instance).Field("choseNestPosition").SetValue((object)true); mls.LogInfo((object)$"Hoarding bug {((Object)__instance).GetInstanceID()} (outside) nest position {__instance.nestPosition} confirmed and flagged as chosen by postfix."); } } [HarmonyPatch(typeof(SpringManAI), "Update")] [HarmonyPrefix] private static bool CoilHeadAILEPrefixAI(SpringManAI __instance) { if (((EnemyAI)__instance).isEnemyDead) { return true; } if (AIBridge.IsTransitioning((EnemyAI)(object)__instance)) { return false; } if (CanCoilHeadEscape.Value && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { if (!((EnemyAI)__instance).isOutside) { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && !((EnemyAI)__instance).targetPlayer.isInsideFactory) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } } else { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && ((EnemyAI)__instance).targetPlayer.isInsideFactory && CanCoilHeadReturnInside.Value) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } } } return true; } [HarmonyPatch(typeof(SpringManAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void CoilHeadAILEOutsideAttack(SpringManAI __instance, ref Collider other) { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) if (((EnemyAI)__instance).isEnemyDead || !((EnemyAI)__instance).isOutside || !((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { return; } PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && !component.isPlayerDead && component.isPlayerControlled && (Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController) { bool value = Traverse.Create((object)__instance).Field("stoppingMovement").GetValue(); float value2 = Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").GetValue(); if (!value && ((EnemyAI)__instance).currentBehaviourStateIndex == 1 && !(value2 >= 0f) && !(((EnemyAI)__instance).stunNormalizedTimer > 0f)) { Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").SetValue((object)0.2f); component.DamagePlayer(90, true, true, (CauseOfDeath)6, 2, false, default(Vector3)); component.DamagePlayerFromOtherClientServerRpc(90, Vector3.zero, -1); component.JumpToFearLevel(1f, true); } } } [HarmonyPatch(typeof(SandSpiderAI), "Update")] [HarmonyPrefix] private static bool SpiderAILEPrefixAI(SandSpiderAI __instance) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if (((EnemyAI)__instance).isEnemyDead) { return true; } if (AIBridge.IsTransitioning((EnemyAI)(object)__instance)) { return false; } if (CanSpiderEscape.Value && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { if (!((EnemyAI)__instance).isOutside) { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && !((EnemyAI)__instance).targetPlayer.isInsideFactory) { AIBridge.RequestTransition((EnemyAI)(object)__instance); __instance.meshContainerPosition = ((EnemyAI)__instance).serverPosition; __instance.meshContainerTarget = ((EnemyAI)__instance).serverPosition; __instance.maxWebTrapsToPlace += Random.Range(SpiderMinWebsOutside.Value, SpiderMaxWebsOutside.Value); return false; } } else { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && ((EnemyAI)__instance).targetPlayer.isInsideFactory && CanSpiderReturnInside.Value) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } } } return true; } [HarmonyPatch(typeof(SandSpiderAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void SpiderAILEOutsideAttack(SandSpiderAI __instance, ref Collider other) { //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) if (((EnemyAI)__instance).isEnemyDead || !((EnemyAI)__instance).isOutside || !((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { return; } PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && !component.isPlayerDead && component.isPlayerControlled && (Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController) { bool value = Traverse.Create((object)__instance).Field("onWall").GetValue(); float value2 = Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").GetValue(); if (!value && !(value2 <= 1f) && !(((EnemyAI)__instance).stunNormalizedTimer > 0f)) { Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").SetValue((object)0f); component.DamagePlayer(90, true, true, (CauseOfDeath)6, 0, false, default(Vector3)); component.DamagePlayerFromOtherClientServerRpc(90, Vector3.zero, -1); __instance.HitPlayerServerRpc((int)component.playerClientId); } } } [HarmonyPatch(typeof(SandSpiderAI), "Start")] [HarmonyPostfix] private static void SpiderAILEPostfixStart(SandSpiderAI __instance) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && SpiderChanceToSpawnOutside.Value != 0f && (float)Random.Range(1, 100) <= SpiderChanceToSpawnOutside.Value) { SendEnemyOutside((EnemyAI)(object)__instance); __instance.meshContainerPosition = ((EnemyAI)__instance).serverPosition; __instance.meshContainerTarget = ((EnemyAI)__instance).serverPosition; __instance.maxWebTrapsToPlace = Random.Range(SpiderMinWebsOutside.Value, SpiderMaxWebsOutside.Value); } } [HarmonyPatch(typeof(NutcrackerEnemyAI), "Update")] [HarmonyPrefix] private static bool NutCrackerAILEPrefixAI(NutcrackerEnemyAI __instance) { if (((EnemyAI)__instance).isEnemyDead) { return true; } if (AIBridge.IsTransitioning((EnemyAI)(object)__instance)) { return false; } if (CanNutCrackerEscape.Value && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { if (!((EnemyAI)__instance).isOutside) { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && !((EnemyAI)__instance).targetPlayer.isInsideFactory) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } } else { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && ((EnemyAI)__instance).targetPlayer.isInsideFactory && CanNutCrackerReturnInside.Value) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } } } return true; } [HarmonyPatch(typeof(NutcrackerEnemyAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void NutCrackerAILEOutsideAttack(NutcrackerEnemyAI __instance, ref Collider other) { if (((EnemyAI)__instance).isEnemyDead || !((EnemyAI)__instance).isOutside || !((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { return; } PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && !component.isPlayerDead && component.isPlayerControlled && (Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController) { float value = Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").GetValue(); if (!(((EnemyAI)__instance).stunNormalizedTimer >= 0f) && !(value < 1f)) { Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").SetValue((object)0f); __instance.LegKickPlayerServerRpc((int)component.playerClientId); } } } [HarmonyPatch(typeof(NutcrackerEnemyAI), "Start")] [HarmonyPostfix] private static void NutCrackerAILEPostfixStart(NutcrackerEnemyAI __instance) { if (((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && NutCrackerChanceToSpawnOutside.Value != 0f && (float)Random.Range(1, 100) <= NutCrackerChanceToSpawnOutside.Value) { SendEnemyOutside((EnemyAI)(object)__instance); } } [HarmonyPatch(typeof(ClaySurgeonAI), "Update")] [HarmonyPrefix] private static bool ClaySurgeonLEPrefixAI(ClaySurgeonAI __instance) { Traverse val = Traverse.Create((object)__instance); if (val.Field("isEnemyDead").GetValue()) { return true; } if (AIBridge.IsTransitioning((EnemyAI)(object)__instance)) { return false; } if (CanClaySurgeonEscape.Value && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { if (!val.Field("isOutside").GetValue()) { PlayerControllerB value = val.Field("targetPlayer").GetValue(); if ((Object)(object)value != (Object)null && !value.isInsideFactory && (float)Random.Range(1, 100) <= ClaySurgeonEscapeChance.Value) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } } else { PlayerControllerB value2 = val.Field("targetPlayer").GetValue(); if ((Object)(object)value2 != (Object)null && value2.isInsideFactory && CanClaySurgeonReturnInside.Value) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { val.Method("ChangeOwnershipOfEnemy", new object[1] { GameNetworkManager.Instance.localPlayerController.actualClientId }).GetValue(); } } } return true; } [HarmonyPatch(typeof(ClaySurgeonAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void ClaySurgeonAILEOutsideAttack(ClaySurgeonAI __instance, ref Collider other) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) Traverse val = Traverse.Create((object)__instance); if (!val.Field("isEnemyDead").GetValue() && val.Field("isOutside").GetValue() && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && !component.isPlayerDead && component.isPlayerControlled && (Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController && !(val.Field("timeSinceHittingPlayer").GetValue() < 0.4f)) { val.Field("timeSinceHittingPlayer").SetValue((object)0f); component.DamagePlayer(50, true, true, (CauseOfDeath)0, 0, false, default(Vector3)); component.DamagePlayerFromOtherClientServerRpc(50, Vector3.zero, -1); val.Method("HitPlayerServerRpc", new object[1] { (int)component.playerClientId }).GetValue(); } } } [HarmonyPatch(typeof(ClaySurgeonAI), "Start")] [HarmonyPostfix] private static void ClaySurgeonAILEPostfixStart(ClaySurgeonAI __instance) { if (((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && ClaySurgeonChanceToSpawnOutside.Value != 0f && (float)Random.Range(1, 100) <= ClaySurgeonChanceToSpawnOutside.Value) { SendEnemyOutside((EnemyAI)(object)__instance); } } [HarmonyPatch(typeof(BlobAI), "Update")] [HarmonyPrefix] private static bool BlobAILEPrefixAI(BlobAI __instance) { if (((EnemyAI)__instance).isEnemyDead) { return true; } if (AIBridge.IsTransitioning((EnemyAI)(object)__instance)) { return false; } if (CanHygrodereEscape.Value && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { if (!((EnemyAI)__instance).isOutside) { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && !((EnemyAI)__instance).targetPlayer.isInsideFactory) { AIBridge.RequestTransition((EnemyAI)(object)__instance); __instance.centerPoint = ((Component)__instance).transform; return false; } } else { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && ((EnemyAI)__instance).targetPlayer.isInsideFactory && CanHygrodereReturnInside.Value) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } } } return true; } [HarmonyPatch(typeof(BlobAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void BlobAILEOutsideAttack(BlobAI __instance, ref Collider other) { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) if (((EnemyAI)__instance).isEnemyDead || !((EnemyAI)__instance).isOutside || !((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { return; } PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if (!((Object)(object)component != (Object)null) || component.isPlayerDead || !component.isPlayerControlled || !((Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController)) { return; } float value = Traverse.Create((object)__instance).Field("timeSinceHittingLocalPlayer").GetValue(); float value2 = Traverse.Create((object)__instance).Field("tamedTimer").GetValue(); float value3 = Traverse.Create((object)__instance).Field("angeredTimer").GetValue(); if (!(value < 0.25f) && (!(value2 > 0f) || !(value3 < 0f))) { Traverse.Create((object)__instance).Field("timeSinceHittingLocalPlayer").SetValue((object)0f); component.DamagePlayerFromOtherClientServerRpc(35, Vector3.zero, -1); component.DamagePlayer(35, true, true, (CauseOfDeath)0, 0, false, default(Vector3)); if (component.isPlayerDead) { __instance.SlimeKillPlayerEffectServerRpc((int)component.playerClientId); } } } [HarmonyPatch(typeof(BlobAI), "Start")] [HarmonyPostfix] private static void HygrodereAILEPostfixStart(BlobAI __instance) { if (((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && HygrodereChanceToSpawnOutside.Value != 0f && (float)Random.Range(1, 100) <= HygrodereChanceToSpawnOutside.Value) { SendEnemyOutside((EnemyAI)(object)__instance); __instance.centerPoint = ((Component)__instance).transform; } } [HarmonyPatch(typeof(FlowermanAI), "DoAIInterval")] [HarmonyPrefix] private static bool DoAIInterval_BrackenCarryBodyFix(FlowermanAI __instance) { //IL_0039: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) if (!__instance.carryingPlayerBody || !((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost || !brackenNestOutside.TryGetValue(__instance, out var value) || ((EnemyAI)__instance).isOutside == value) { return true; } EntranceTeleport val = FindClosestReachableEntrance(((Component)__instance).transform.position, ((EnemyAI)__instance).isOutside, ((EnemyAI)__instance).isOutside ? ((float)BrackenExteriorPathRange.Value) : ((float)BrackenInteriorPathRange.Value), ((EnemyAI)__instance).agent); if ((Object)(object)val == (Object)null) { return true; } if (Vector3.Distance(((Component)__instance).transform.position, val.entrancePoint.position) < 4.5f) { mls.LogInfo((object)string.Format("Bracken {0} crossed {1} while carrying a body to its {2} nest.", ((Object)__instance).GetInstanceID(), ((Object)val).name, value ? "outside" : "inside")); if (((EnemyAI)__instance).isOutside) { SendEnemyInside((EnemyAI)(object)__instance, val); } else { SendEnemyOutside((EnemyAI)(object)__instance, spawnOnDoor: true, val); } return false; } ((EnemyAI)__instance).SetDestinationToPosition(val.entrancePoint.position, false); return false; } [HarmonyPatch(typeof(FlowermanAI), "Update")] [HarmonyPrefix] private static bool FlowermanAILEPrefixAI(FlowermanAI __instance) { //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Unknown result type (might be due to invalid IL or missing references) if (((EnemyAI)__instance).isEnemyDead) { if (brackenOriginalNests.ContainsKey(__instance)) { brackenOriginalNests.Remove(__instance); } if (brackenPathingCooldowns.ContainsKey(__instance)) { brackenPathingCooldowns.Remove(__instance); } if (brackenDecisionTimers.ContainsKey(__instance)) { brackenDecisionTimers.Remove(__instance); } brackenNestOutside.Remove(__instance); return true; } if (!CanBrackenEscape.Value || !((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { return true; } bool value; bool flag = brackenNestOutside.TryGetValue(__instance, out value) && value; if (!((EnemyAI)__instance).isOutside) { if ((Object)(object)((EnemyAI)__instance).favoriteSpot != (Object)null && !((EnemyAI)__instance).isOutside && !brackenOriginalNests.ContainsKey(__instance)) { brackenOriginalNests[__instance] = ((EnemyAI)__instance).favoriteSpot; mls.LogInfo((object)$"LethalEscape: Stored Bracken nest for {((Object)__instance).GetInstanceID()}"); } if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && !((EnemyAI)__instance).targetPlayer.isInsideFactory && (((EnemyAI)__instance).currentBehaviourStateIndex == 1 || __instance.evadeStealthTimer > 0f) && Time.time - TimeStartTeleport >= BrackenEscapeDelay.Value + 5f) { TimeStartTeleport = Time.time; } if (Time.time - TimeStartTeleport > BrackenEscapeDelay.Value && Time.time - TimeStartTeleport < BrackenEscapeDelay.Value + 5f) { SendEnemyOutside((EnemyAI)(object)__instance); brackenPathingCooldowns[__instance] = BrackenPathCooldown.Value; } else if (LETimerFunctions.MinuteEscapeTimerBracken >= 60f && (Object)(object)((EnemyAI)__instance).targetPlayer == (Object)null) { LETimerFunctions.MinuteEscapeTimerBracken = 0f; if (BrackenChanceToEscapeEveryMinute.Value != 0f && (float)Random.Range(1, 100) <= BrackenChanceToEscapeEveryMinute.Value) { SendEnemyOutside((EnemyAI)(object)__instance, spawnOnDoor: false); brackenPathingCooldowns[__instance] = BrackenPathCooldown.Value; } } return true; } if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } if (!flag && brackenOriginalNests.ContainsKey(__instance)) { ((EnemyAI)__instance).favoriteSpot = brackenOriginalNests[__instance]; } if (brackenPathingCooldowns.TryGetValue(__instance, out var value2) && value2 > 0f) { brackenPathingCooldowns[__instance] -= Time.deltaTime; return true; } if (brackenPathingCooldowns.ContainsKey(__instance) && brackenPathingCooldowns[__instance] <= 0f) { brackenPathingCooldowns.Remove(__instance); } bool flag2 = false; string arg = ""; if (!flag && CanBrackenReturnInside.Value && (Object)(object)((EnemyAI)__instance).targetPlayer == (Object)null) { if ((Object)(object)((EnemyAI)__instance).favoriteSpot != (Object)null && (Object)(object)((EnemyAI)__instance).targetNode == (Object)(object)((EnemyAI)__instance).favoriteSpot) { flag2 = true; arg = "returning to its nest"; } if (!brackenDecisionTimers.ContainsKey(__instance)) { brackenDecisionTimers[__instance] = 60f; } brackenDecisionTimers[__instance] -= Time.deltaTime; if (!flag2 && brackenDecisionTimers[__instance] <= 0f) { if (BrackenChanceToGoInside.Value > 0f && Random.Range(0f, 100f) < BrackenChanceToGoInside.Value) { flag2 = true; arg = "randomly deciding to go back inside"; } brackenDecisionTimers[__instance] = 60f; } } if (!flag2) { return true; } EntranceTeleport val = FindClosestReachableEntrance(((Component)__instance).transform.position, findEntranceToBuilding: true, BrackenExteriorPathRange.Value, ((EnemyAI)__instance).agent); if ((Object)(object)val != (Object)null) { mls.LogInfo((object)$"Bracken {((Object)__instance).GetInstanceID()} is {arg}. Pathing to entrance {((Object)val).name}."); ((EnemyAI)__instance).SetDestinationToPosition(val.entrancePoint.position, false); return false; } mls.LogInfo((object)$"Bracken {((Object)__instance).GetInstanceID()} wants to {arg}, but no reachable entrance found. Starting cooldown."); brackenPathingCooldowns[__instance] = BrackenPathCooldown.Value; return true; } [HarmonyPatch(typeof(FlowermanAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void FlowerManAILEOutsideAttack(FlowermanAI __instance, ref Collider other, bool ___startingKillAnimationLocalClient) { if (!((EnemyAI)__instance).isEnemyDead && ((EnemyAI)__instance).isOutside && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && !component.isPlayerDead && component.isPlayerControlled && (Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController && !Traverse.Create((object)__instance).Field("inKillAnimation").GetValue() && !___startingKillAnimationLocalClient) { __instance.KillPlayerAnimationServerRpc((int)component.playerClientId); ___startingKillAnimationLocalClient = true; } } } [HarmonyPatch(typeof(FlowermanAI), "Start")] [HarmonyPostfix] private static void FlowermanAILEPostfixStart(FlowermanAI __instance) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) TimeStartTeleport = 0f; if (!((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { return; } bool flag = CanBrackenMakeNestOutside.Value && Random.Range(0f, 100f) < BrackenNestOutsideChance.Value; brackenNestOutside[__instance] = flag; if (flag) { Transform val = null; float num = float.MaxValue; GameObject[] array = GameObject.FindGameObjectsWithTag("OutsideAINode"); foreach (GameObject val2 in array) { float num2 = Vector3.Distance(((Component)__instance).transform.position, val2.transform.position); if (num2 < num) { num = num2; val = val2.transform; } } if ((Object)(object)val != (Object)null) { ((EnemyAI)__instance).favoriteSpot = val; mls.LogInfo((object)$"Bracken {((Object)__instance).GetInstanceID()} chose an outside nest at {val.position}."); } else { brackenNestOutside[__instance] = false; mls.LogWarning((object)$"Bracken {((Object)__instance).GetInstanceID()} could not find an outside nest node; keeping its interior nest."); } } if (flag || (BrackenChanceToSpawnOutside.Value != 0f && Random.Range(0f, 100f) < BrackenChanceToSpawnOutside.Value)) { SendEnemyOutside((EnemyAI)(object)__instance); } } [HarmonyPatch(typeof(ButlerEnemyAI), "Update")] [HarmonyPrefix] private static void ButlerLEPrefixAI(ButlerEnemyAI __instance) { if (((EnemyAI)__instance).isEnemyDead || !CanButlerEscape.Value || !((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { if (((EnemyAI)__instance).isEnemyDead && butlerPendingLeaveFacilityInfo.ContainsKey(__instance)) { butlerPendingLeaveFacilityInfo.Remove(__instance); } return; } PlayerControllerB targetPlayer = ((EnemyAI)__instance).targetPlayer; int value = Traverse.Create((object)__instance).Field("currentBehaviourStateIndex").GetValue(); if ((Object)(object)targetPlayer == (Object)null || targetPlayer.isPlayerDead || (value != 1 && value != 2)) { if (butlerPendingLeaveFacilityInfo.ContainsKey(__instance)) { mls.LogInfo((object)string.Format("Butler {0} no longer meets criteria for following (Target: {1}, State: {2}). Clearing pending leave timer.", ((Object)__instance).GetInstanceID(), ((Object)(object)targetPlayer == (Object)null) ? "null" : (targetPlayer.isPlayerDead ? (targetPlayer.playerUsername + "(Dead)") : targetPlayer.playerUsername), value)); butlerPendingLeaveFacilityInfo.Remove(__instance); } return; } if (!((EnemyAI)__instance).isOutside) { if (!targetPlayer.isInsideFactory) { if (!butlerPendingLeaveFacilityInfo.ContainsKey(__instance)) { butlerPendingLeaveFacilityInfo[__instance] = Time.time; mls.LogInfo((object)$"Butler {((Object)__instance).GetInstanceID()} (State: {value}) target {targetPlayer.playerUsername} is outside. Initiating escape timer with delay: {ButlerEscapeDelay.Value}s."); } if (Time.time - butlerPendingLeaveFacilityInfo[__instance] >= ButlerEscapeDelay.Value) { mls.LogInfo((object)$"Butler {((Object)__instance).GetInstanceID()} escape delay ({ButlerEscapeDelay.Value}s) met. Sending Butler outside to follow {targetPlayer.playerUsername}."); SendEnemyOutside((EnemyAI)(object)__instance); butlerPendingLeaveFacilityInfo.Remove(__instance); } } else if (butlerPendingLeaveFacilityInfo.ContainsKey(__instance)) { mls.LogInfo((object)$"Butler {((Object)__instance).GetInstanceID()} target {targetPlayer.playerUsername} is back inside. Cancelling Butler's pending leave."); butlerPendingLeaveFacilityInfo.Remove(__instance); } return; } if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } if (!targetPlayer.isInsideFactory) { return; } if (CanButlerReturnInside.Value) { mls.LogInfo((object)$"Butler {((Object)__instance).GetInstanceID()} (State: {value}) is outside, its target {targetPlayer.playerUsername} is inside. Config allows return. Sending Butler back inside immediately."); SendEnemyInside((EnemyAI)(object)__instance); if (butlerPendingLeaveFacilityInfo.ContainsKey(__instance)) { butlerPendingLeaveFacilityInfo.Remove(__instance); } } else { mls.LogInfo((object)$"Butler {((Object)__instance).GetInstanceID()} (State: {value}) is outside, target {targetPlayer.playerUsername} is inside, but CanButlerReturnInside is false. Butler will not return."); if (butlerPendingLeaveFacilityInfo.ContainsKey(__instance)) { butlerPendingLeaveFacilityInfo.Remove(__instance); } } } [HarmonyPatch(typeof(ButlerEnemyAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void ButlerAILEOutsideAttack(ButlerEnemyAI __instance, ref Collider other) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) if (((EnemyAI)__instance).isEnemyDead) { return; } Traverse val = Traverse.Create((object)__instance); if (val.Field("isOutside").GetValue() && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && !component.isPlayerDead && component.isPlayerControlled && (Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController && !(val.Field("timeSinceHittingPlayer").GetValue() <= 0.65f) && !(val.Field("stunNormalizedTimer").GetValue() > 0f)) { val.Field("timeSinceHittingPlayer").SetValue((object)0f); ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); component.DamagePlayer(50, true, true, (CauseOfDeath)14, 0, false, default(Vector3)); component.DamagePlayerFromOtherClientServerRpc(50, Vector3.zero, -1); val.Field("agent").Field("speed").SetValue((object)0f); __instance.StabPlayerServerRpc((int)component.playerClientId, true); } } } [HarmonyPatch(typeof(ButlerEnemyAI), "Start")] [HarmonyPostfix] private static void ButlerAILEPostfixStart(ButlerEnemyAI __instance) { if (((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && ButlerChanceToSpawnOutside.Value != 0f && (float)Random.Range(1, 100) <= ButlerChanceToSpawnOutside.Value) { SendEnemyOutside((EnemyAI)(object)__instance); } } [HarmonyPatch(typeof(ButlerEnemyAI), "KillEnemy", new Type[] { typeof(bool) })] [HarmonyPrefix] private static void PrefixButlerKillEnemy(ButlerEnemyAI __instance) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && ((EnemyAI)__instance).isOutside && !((EnemyAI)__instance).isEnemyDead) { LastButlerDeathPositionOutside = ((Component)__instance).transform.position; LastButlerDeathTimeOutside = Time.realtimeSinceStartup; ButlerRecentlyDiedOutside = true; mls.LogInfo((object)$"Butler flagged as dying outside at {LastButlerDeathPositionOutside}. Timestamp: {LastButlerDeathTimeOutside}"); } } [HarmonyPatch(typeof(ButlerBeesEnemyAI), "Start")] [HarmonyPostfix] private static void PostfixBeeStart(ButlerBeesEnemyAI __instance) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost || ((EnemyAI)__instance).isOutside) { return; } float num = Time.realtimeSinceStartup - LastButlerDeathTimeOutside; if (ButlerRecentlyDiedOutside && num < 2f && Vector3.Distance(((Component)__instance).transform.position, LastButlerDeathPositionOutside) < 5f) { mls.LogInfo((object)$"ButlerBee at {((Component)__instance).transform.position} spawned by Butler that recently died outside. Configuring for outside environment."); ((EnemyAI)__instance).isOutside = true; bool flag = true; if ((Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null) { flag = !StartOfRound.Instance.hangarDoorsClosed || !GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom; } ((EnemyAI)__instance).EnableEnemyMesh(flag, false, false); Vector3 position = ((Component)__instance).transform.position; NavMeshHit val = default(NavMeshHit); if (NavMesh.SamplePosition(position, ref val, 2f, ((EnemyAI)__instance).agent.areaMask)) { position = ((NavMeshHit)(ref val)).position; } else { mls.LogWarning((object)$"ButlerBee (Outside): Failed to sample NavMesh at initial spawn {((Component)__instance).transform.position}. Attempting to find closest outside AI node."); Transform val2 = ((EnemyAI)__instance).ChooseClosestNodeToPosition(position, true, 0); if ((Object)(object)val2 != (Object)null) { position = val2.position; } else { mls.LogWarning((object)"ButlerBee (Outside): No close outside AINode found. Bee might be stuck or out of NavMesh bounds."); } } ((EnemyAI)__instance).serverPosition = position; ((Component)__instance).transform.position = position; if (!((Behaviour)((EnemyAI)__instance).agent).enabled) { ((Behaviour)((EnemyAI)__instance).agent).enabled = true; } if (!((EnemyAI)__instance).agent.Warp(position)) { mls.LogWarning((object)$"ButlerBee (Outside): NavMeshAgent failed to warp to {position}. The NavMesh might not be baked correctly for this area, or the agent is in an invalid state."); } ((EnemyAI)__instance).SyncPositionToClients(); if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } mls.LogInfo((object)"ButlerBee successfully configured for outside."); } if (ButlerRecentlyDiedOutside && num >= 2f) { ButlerRecentlyDiedOutside = false; } } [HarmonyPatch(typeof(ButlerBeesEnemyAI), "OnCollideWithPlayer")] [HarmonyPrefix] public static bool ButlerBeesAILEOutsideAttackPrefix(ButlerBeesEnemyAI __instance, Collider other) { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) if (((EnemyAI)__instance).isEnemyDead) { return true; } if (!((EnemyAI)__instance).isOutside) { return true; } if (!((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { return false; } Traverse val = Traverse.Create((object)__instance); float value = val.Field("timeAtSpawning").GetValue(); float value2 = val.Field("timeAtLastHurtingPlayer").GetValue(); if (Time.realtimeSinceStartup - value < 1.7f) { return false; } if (Time.realtimeSinceStartup - value2 < 0.5f) { return false; } PlayerControllerB val2 = ((EnemyAI)__instance).MeetsStandardPlayerCollisionConditions(other, false, false); if ((Object)(object)val2 != (Object)null) { val.Field("timeAtLastHurtingPlayer").SetValue((object)Time.realtimeSinceStartup); if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } mls.LogInfo((object)("Host: Outside Butler Bee attacking player " + val2.playerUsername + ".")); val2.DamagePlayer(10, true, true, (CauseOfDeath)14, 0, false, default(Vector3)); if ((Object)(object)val2 != (Object)(object)GameNetworkManager.Instance.localPlayerController) { val2.DamagePlayerFromOtherClientServerRpc(10, Vector3.zero, -1); } return false; } return false; } [HarmonyPatch(typeof(RoundManager), "LoadNewLevel")] [HarmonyPrefix] [HarmonyWrapSafe] public static bool LoadNewLevel(SelectableLevel newLevel) { if (!goofyahh.Value) { return true; } if (!((NetworkBehaviour)StartOfRound.Instance.localPlayerController).IsHost) { return true; } HUDManager.Instance.AddTextToChatOnServer("Lethal Escape 2.5.0 is active, monsters can escape the facility now!", -1); return true; } [HarmonyPatch(typeof(CaveDwellerAI), "Update")] [HarmonyPrefix] private static bool CaveDwellerLEPrefixAI(CaveDwellerAI __instance) { if (((EnemyAI)__instance).isEnemyDead) { return true; } if (AIBridge.IsTransitioning((EnemyAI)(object)__instance)) { return false; } if (CanCaveDwellerEscape.Value && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { if (!((EnemyAI)__instance).isOutside) { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && !((EnemyAI)__instance).targetPlayer.isInsideFactory) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } } else { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && ((EnemyAI)__instance).targetPlayer.isInsideFactory && CanCaveDwellerReturnInside.Value) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } } } return true; } [HarmonyPatch(typeof(CaveDwellerAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void CaveDwellerAILEOutsideAttack(CaveDwellerAI __instance, ref Collider other) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (!((EnemyAI)__instance).isEnemyDead && ((EnemyAI)__instance).isOutside && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && !component.isPlayerDead && component.isPlayerControlled && (Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController && !(Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").GetValue() <= 1f)) { Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").SetValue((object)0f); component.DamagePlayer(30, true, true, (CauseOfDeath)6, 0, false, default(Vector3)); component.DamagePlayerFromOtherClientServerRpc(30, Vector3.zero, -1); __instance.KillPlayerAnimationServerRpc((int)component.playerClientId); } } } [HarmonyPatch(typeof(CaveDwellerAI), "Start")] [HarmonyPostfix] private static void CaveDwellerAILEPostfixStart(CaveDwellerAI __instance) { if (((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && CaveDwellerChanceToSpawnOutside.Value != 0f && (float)Random.Range(1, 100) <= CaveDwellerChanceToSpawnOutside.Value) { SendEnemyOutside((EnemyAI)(object)__instance); } } [HarmonyPatch(typeof(PufferAI), "Update")] [HarmonyPrefix] private static bool PufferAILEPrefixAI(PufferAI __instance) { if (((EnemyAI)__instance).isEnemyDead) { return true; } if (AIBridge.IsTransitioning((EnemyAI)(object)__instance)) { return false; } if (CanPufferEscape.Value && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { if (!((EnemyAI)__instance).isOutside) { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && !((EnemyAI)__instance).targetPlayer.isInsideFactory) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } if (LETimerFunctions.MinuteEscapeTimerPuffer >= 60f && (Object)(object)((EnemyAI)__instance).targetPlayer == (Object)null) { LETimerFunctions.MinuteEscapeTimerPuffer = 0f; if (PufferChanceToEscapeEveryMinute.Value != 0f && (float)Random.Range(1, 100) <= PufferChanceToEscapeEveryMinute.Value) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } } } else { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && ((EnemyAI)__instance).targetPlayer.isInsideFactory && CanPufferReturnInside.Value) { AIBridge.RequestTransition((EnemyAI)(object)__instance); return false; } if (((NetworkBehaviour)__instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { ((EnemyAI)__instance).ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } } } return true; } [HarmonyPatch(typeof(PufferAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void PufferAILEOutsideAttack(PufferAI __instance, ref Collider other) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (!((EnemyAI)__instance).isEnemyDead && ((EnemyAI)__instance).isOutside && ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && !component.isPlayerDead && component.isPlayerControlled && (Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController && !(Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").GetValue() <= 1f)) { Traverse.Create((object)__instance).Field("timeSinceHittingPlayer").SetValue((object)0f); component.DamagePlayer(20, true, true, (CauseOfDeath)6, 0, false, default(Vector3)); component.DamagePlayerFromOtherClientServerRpc(20, Vector3.zero, -1); __instance.BitePlayerServerRpc((int)component.playerClientId); } } } [HarmonyPatch(typeof(PufferAI), "Start")] [HarmonyPostfix] private static void PufferAILEPostfixStart(PufferAI __instance) { if (((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && PufferChanceToSpawnOutside.Value != 0f && (float)Random.Range(1, 100) <= PufferChanceToSpawnOutside.Value) { SendEnemyOutside((EnemyAI)(object)__instance); } } [HarmonyPatch(typeof(BaboonBirdAI), "Update")] [HarmonyPrefix] public static bool BaboonBirdAI_Update_Prefix(BaboonBirdAI __instance) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Invalid comparison between Unknown and I4 //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_047c: Unknown result type (might be due to invalid IL or missing references) //IL_050b: Unknown result type (might be due to invalid IL or missing references) //IL_04af: Unknown result type (might be due to invalid IL or missing references) //IL_053b: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost || ((EnemyAI)__instance).isEnemyDead || ((EnemyAI)__instance).inSpecialAnimation || ((EnemyAI)__instance).stunNormalizedTimer > 0f) { if (baboonsPathingToDoor.ContainsKey(__instance)) { baboonsPathingToDoor.Remove(__instance); } baboonDoorTargets.Remove(__instance); return true; } if (!baboonsPathingToDoor.ContainsKey(__instance)) { baboonsPathingToDoor[__instance] = false; } if (baboonsPathingToDoor.TryGetValue(__instance, out var value) && value) { if (!baboonDoorTargets.TryGetValue(__instance, out var value2) || (Object)(object)value2 == (Object)null || (int)((EnemyAI)__instance).agent.pathStatus == 2) { mls.LogInfo((object)$"Baboon ({((Object)__instance).GetInstanceID()}) lost its path to the door. Resetting state."); baboonsPathingToDoor.Remove(__instance); baboonDoorTargets.Remove(__instance); baboonPathingCooldowns[__instance] = BaboonPathingCooldownConfig.Value; return true; } if (Vector3.Distance(((Component)__instance).transform.position, value2.entrancePoint.position) < 4.5f) { bool flag = (Object)(object)__instance.heldScrap != (Object)null; if (((EnemyAI)__instance).isOutside) { mls.LogInfo((object)$"Baboon ({((Object)__instance).GetInstanceID()}) has arrived at entrance, sending inside."); if (flag && BaboonCanCarryScrapInOut.Value && (Object)(object)__instance.heldScrap != (Object)null) { __instance.heldScrap.isInFactory = true; } SendEnemyInside((EnemyAI)(object)__instance, value2); } else { mls.LogInfo((object)$"Baboon ({((Object)__instance).GetInstanceID()}) has arrived at exit, sending outside."); if (flag && BaboonCanCarryScrapInOut.Value && (Object)(object)__instance.heldScrap != (Object)null) { __instance.heldScrap.isInFactory = false; } SendEnemyOutside((EnemyAI)(object)__instance, spawnOnDoor: true, value2); } baboonsPathingToDoor.Remove(__instance); baboonDoorTargets.Remove(__instance); baboonPathingCooldowns[__instance] = BaboonPathingCooldownConfig.Value; return true; } ((EnemyAI)__instance).SetDestinationToPosition(value2.entrancePoint.position, false); return true; } if (!baboonDecisionTimers.ContainsKey(__instance)) { baboonDecisionTimers[__instance] = 60f; } if (!baboonPathingCooldowns.ContainsKey(__instance)) { baboonPathingCooldowns[__instance] = 0f; } if (baboonPathingCooldowns[__instance] > 0f) { baboonPathingCooldowns[__instance] -= Time.deltaTime; return true; } bool flag2 = false; Traverse obj = Traverse.Create((object)__instance); PlayerControllerB val = null; Threat value3 = obj.Field("focusedThreat").Value; if (value3 != null && value3.threatScript != null) { Transform threatTransform = value3.threatScript.GetThreatTransform(); val = (((Object)(object)threatTransform != (Object)null) ? ((Component)threatTransform).GetComponent() : null); flag2 = true; } baboonDecisionTimers[__instance] -= Time.deltaTime; bool flag3 = baboonDecisionTimers[__instance] <= 0f; if (flag3) { flag2 = true; baboonDecisionTimers[__instance] = 60f; } if (!flag2) { return true; } bool flag4 = (Object)(object)__instance.heldScrap != (Object)null; bool flag5 = false; string arg = ""; bool flag6 = false; string arg2 = ""; if (((EnemyAI)__instance).isOutside) { if (CanBaboonEnterFacility.Value && (Object)(object)val != (Object)null && val.isInsideFactory && !val.isPlayerDead) { flag5 = true; arg = "Target player " + val.playerUsername + " is inside."; } else if (CanBaboonEnterFacility.Value && flag3 && Random.Range(0f, 100f) < BaboonChanceToEnterFacilityPerMinute.Value) { flag5 = true; arg = "Random decision to explore inside."; } } else if ((Object)(object)val != (Object)null && !val.isInsideFactory && !val.isPlayerDead) { flag6 = true; arg2 = "Target player " + val.playerUsername + " is outside."; } else if (flag4 && BaboonCanCarryScrapInOut.Value) { flag6 = true; arg2 = "Carrying scrap '" + ((Object)__instance.heldScrap).name + "' and its camp is outside."; } else if (flag3 && Random.Range(0f, 100f) < BaboonChanceToExitFacilityPerMinute.Value) { flag6 = true; arg2 = "Random decision to explore outside."; } if (flag5) { EntranceTeleport val2 = FindClosestReachableEntrance(((Component)__instance).transform.position, findEntranceToBuilding: true, BaboonExteriorPathRangeConfig.Value, ((EnemyAI)__instance).agent); if ((Object)(object)val2 != (Object)null) { ((EnemyAI)__instance).SetDestinationToPosition(val2.entrancePoint.position, false); mls.LogInfo((object)$"Baboon ({((Object)__instance).GetInstanceID()}) decided to enter ({arg}). Pathing to {((Object)val2).name}."); baboonsPathingToDoor[__instance] = true; baboonDoorTargets[__instance] = val2; return true; } } else if (flag6) { EntranceTeleport val3 = FindClosestReachableEntrance(((Component)__instance).transform.position, findEntranceToBuilding: false, BaboonInteriorPathRangeConfig.Value, ((EnemyAI)__instance).agent); if ((Object)(object)val3 != (Object)null) { ((EnemyAI)__instance).SetDestinationToPosition(val3.entrancePoint.position, false); mls.LogInfo((object)$"Baboon ({((Object)__instance).GetInstanceID()}) decided to exit ({arg2}). Pathing to {((Object)val3).name}."); baboonsPathingToDoor[__instance] = true; baboonDoorTargets[__instance] = val3; return true; } } return true; } [HarmonyPatch(typeof(BaboonBirdAI), "Update")] [HarmonyPostfix] public static void BaboonBirdAI_Update_Postfix(BaboonBirdAI __instance) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && !((EnemyAI)__instance).isEnemyDead && !((EnemyAI)__instance).inSpecialAnimation && !(((EnemyAI)__instance).stunNormalizedTimer > 0f) && baboonsPathingToDoor.TryGetValue(__instance, out var value) && value && baboonDoorTargets.TryGetValue(__instance, out var value2) && (Object)(object)value2 != (Object)null) { ((EnemyAI)__instance).SetDestinationToPosition(value2.entrancePoint.position, false); } } [HarmonyPatch(typeof(BaboonBirdAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void BaboonBirdAI_OnCollideWithPlayer_Postfix(BaboonBirdAI __instance, Collider other) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost || ((EnemyAI)__instance).isEnemyDead || ((EnemyAI)__instance).stunNormalizedTimer > 0f || ((EnemyAI)__instance).isOutside) { return; } PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if (!((Object)(object)component != (Object)null) || !((Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController) || component.isPlayerDead || !component.isPlayerControlled) { return; } Traverse val = Traverse.Create((object)__instance); if (val.Field("timeSinceHitting").Value < 0.5f) { return; } Vector3 val2 = Vector3.Normalize(((Component)__instance).transform.position + Vector3.up * 0.7f - (((Component)other).transform.position + Vector3.up * 0.4f)) * 0.5f; if (!Physics.Linecast(((Component)__instance).transform.position + Vector3.up * 0.7f + val2, ((Component)other).transform.position + Vector3.up * 0.4f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1)) { mls.LogInfo((object)("Host-controlled Baboon (inside) attacking non-host player " + component.playerUsername + ".")); val.Field("timeSinceHitting").SetValue((object)0f); component.DamagePlayer(20, true, true, (CauseOfDeath)0, 0, false, default(Vector3)); component.DamagePlayerFromOtherClientServerRpc(20, Vector3.zero, -1); if (component.isPlayerDead) { __instance.StabPlayerDeathAnimServerRpc((int)component.playerClientId); } } } [HarmonyPatch(typeof(GiantKiwiAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void GiantKiwiAILEOutsideAttack(GiantKiwiAI __instance, Collider other) { //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) if (((EnemyAI)__instance).isEnemyDead || __instance.inKillAnimation || !((EnemyAI)__instance).isOutside || !((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { return; } PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && component.isPlayerControlled && !component.isPlayerDead && (Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController) { Traverse obj = Traverse.Create((object)__instance); bool value = obj.Field("attacking").Value; float value2 = obj.Field("timeSinceHittingGround").Value; if (value && value2 < 0.2f) { mls.LogInfo((object)("LethalEscape: Host-controlled Kiwi (outside) attacking non-host player " + component.playerUsername + " based on attack conditions.")); int num = 10; CauseOfDeath val = (CauseOfDeath)14; component.DamagePlayer(num, true, true, val, 0, false, default(Vector3)); component.DamagePlayerFromOtherClientServerRpc(num, Vector3.zero, -1); component.JumpToFearLevel(1f, true); } } } [HarmonyPatch(typeof(GiantKiwiAI), "SpawnEggsClientRpc")] [HarmonyPostfix] public static void Kiwi_SpawnEggsClientRpc_Postfix(GiantKiwiAI __instance) { //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { return; } if ((Object)(object)__instance.birdNest == (Object)null) { mls.LogWarning((object)$"Kiwi ({((Object)__instance).GetInstanceID()}): SpawnEggsClientRpc_Postfix: Bird nest is null. Cannot correct egg 'isInFactory' states."); return; } if (!((EnemyAI)__instance).isOutside) { foreach (KiwiBabyItem egg in __instance.eggs) { if ((Object)(object)egg != (Object)null && !((GrabbableObject)egg).isInFactory) { mls.LogWarning((object)$"Kiwi ({((Object)__instance).GetInstanceID()}) SpawnEggsClientRpc_Postfix: Egg '{((Object)((Component)egg).gameObject).name}' was 'isInFactory=false'. Forcing to 'true' as nest is inside."); ((GrabbableObject)egg).isInFactory = true; } } return; } foreach (KiwiBabyItem egg2 in __instance.eggs) { if ((Object)(object)egg2 != (Object)null) { float num = Vector3.Distance(((Component)egg2).transform.position, __instance.birdNest.transform.position); if (((GrabbableObject)egg2).isInFactory && num < 8f) { mls.LogWarning((object)$"Kiwi ({((Object)__instance).GetInstanceID()}) SpawnEggsClientRpc_Postfix: Egg '{((Object)((Component)egg2).gameObject).name}' (at {((Component)egg2).transform.position}, dist to nest: {num:F1}m) was 'isInFactory=true'. Forcing to 'false' as nest is outside."); ((GrabbableObject)egg2).isInFactory = false; } } } } [HarmonyPatch(typeof(GiantKiwiAI), "SpawnBirdNest")] [HarmonyPrefix] private unsafe static bool SpawnBirdNest_KiwiNestInside_Prefix(GiantKiwiAI __instance) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { return true; } if (!KiwiCanMakeNestInside.Value || (float)Random.Range(0, 100) > KiwiNestInsideChance.Value) { mls.LogInfo((object)"Kiwi nest chance did not pass, or is disabled. Spawning outside."); return true; } mls.LogInfo((object)"Attempting to spawn Giant Kiwi nest INSIDE the facility."); GameObject[] array = GameObject.FindGameObjectsWithTag("AINode"); if (array == null || array.Length == 0) { mls.LogError((object)"Kiwi Nest Inside: Error. Spawning outside instead."); return true; } Vector3 mainEntrancePos = RoundManager.FindMainEntrancePosition(false, false); GameObject[] array2 = array.OrderBy((GameObject node) => Vector3.Distance(node.transform.position, mainEntrancePos)).ToArray(); int num = Mathf.Min(15, array2.Length); GameObject val = array2[Random.Range(0, num)]; Random random = new Random(StartOfRound.Instance.randomMapSeed + 288); Vector3 randomNavMeshPositionInBoxPredictable = RoundManager.Instance.GetRandomNavMeshPositionInBoxPredictable(val.transform.position, 10f, default(NavMeshHit), random, -1, 1f); if (randomNavMeshPositionInBoxPredictable == Vector3.zero) { mls.LogError((object)"Kiwi Nest Inside: Failed to find a valid NavMesh position near the chosen AINode. Spawning outside instead."); return true; } GameObject val2 = Object.Instantiate(__instance.birdNestPrefab, randomNavMeshPositionInBoxPredictable, Quaternion.Euler(Vector3.zero), RoundManager.Instance.mapPropsContainer.transform); val2.transform.Rotate(Vector3.up, (float)random.Next(-180, 180), (Space)0); NetworkObject componentInChildren = val2.GetComponentInChildren(); if ((Object)(object)componentInChildren == (Object)null) { mls.LogError((object)"Kiwi Nest Inside: No NetworkObject found in the nest prefab! Spawning outside instead."); Object.Destroy((Object)(object)val2); return true; } componentInChildren.Spawn(true); Traverse.Create((object)__instance).Field("birdNestAmbience").SetValue((object)val2.GetComponent()); __instance.birdNest = val2; ((EnemyAI)__instance).isOutside = false; ((EnemyAI)__instance).allAINodes = GameObject.FindGameObjectsWithTag("AINode"); ((Behaviour)((EnemyAI)__instance).agent).enabled = false; Vector3 val3 = randomNavMeshPositionInBoxPredictable; NavMeshHit val4 = default(NavMeshHit); Vector3 val5; if (NavMesh.SamplePosition(val3, ref val4, 5f, ((EnemyAI)__instance).agent.areaMask)) { val3 = ((NavMeshHit)(ref val4)).position; ((Component)__instance).transform.position = val3; ((Component)__instance).transform.rotation = __instance.birdNest.transform.rotation; ((Behaviour)((EnemyAI)__instance).agent).enabled = true; if (!((EnemyAI)__instance).agent.Warp(val3)) { ManualLogSource obj = mls; val5 = val3; obj.LogWarning((object)("Kiwi Nest Inside: Agent.Warp failed at " + ((object)(*(Vector3*)(&val5))/*cast due to .constrained prefix*/).ToString() + ".")); } mls.LogInfo((object)$"Kiwi nest successfully spawned INSIDE at {val3}."); return false; } ManualLogSource obj2 = mls; val5 = val3; obj2.LogWarning((object)("Kiwi Nest Inside: NavMesh.SamplePosition failed for " + ((object)(*(Vector3*)(&val5))/*cast due to .constrained prefix*/).ToString() + ". Spawning outside instead.")); Object.Destroy((Object)(object)val2); return true; } [HarmonyPatch(typeof(GiantKiwiAI), "Update")] [HarmonyPostfix] public static void GiantKiwi_Update_Postfix(GiantKiwiAI __instance) { //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_04e3: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Unknown result type (might be due to invalid IL or missing references) //IL_0509: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Unknown result type (might be due to invalid IL or missing references) //IL_03ee: Unknown result type (might be due to invalid IL or missing references) //IL_072d: Unknown result type (might be due to invalid IL or missing references) //IL_0648: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Unknown result type (might be due to invalid IL or missing references) //IL_075e: Unknown result type (might be due to invalid IL or missing references) //IL_076a: Unknown result type (might be due to invalid IL or missing references) //IL_0679: Unknown result type (might be due to invalid IL or missing references) //IL_0685: Unknown result type (might be due to invalid IL or missing references) //IL_0800: Unknown result type (might be due to invalid IL or missing references) //IL_071a: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0880: Unknown result type (might be due to invalid IL or missing references) //IL_0ba7: Unknown result type (might be due to invalid IL or missing references) //IL_0c06: Unknown result type (might be due to invalid IL or missing references) //IL_0bda: Unknown result type (might be due to invalid IL or missing references) //IL_0b47: Unknown result type (might be due to invalid IL or missing references) //IL_0c36: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost || ((EnemyAI)__instance).isEnemyDead || __instance.inKillAnimation || ((EnemyAI)__instance).stunNormalizedTimer > 0f) { return; } Traverse val = Traverse.Create((object)__instance); bool value = val.Field("carryingEgg").Value; if (kiwiRevengeTargets.TryGetValue(__instance, out var value2)) { if ((Object)(object)value2 != (Object)null && !value2.isPlayerDead && value2.isPlayerControlled) { if (!value) { IVisibleThreat value3 = val.Field("attackingThreat").Value; if (((EnemyAI)__instance).currentBehaviourStateIndex != 2 || (Object)(object)((value3 != null) ? value3.GetThreatTransform() : null) != (Object)(object)((Component)value2).transform) { mls.LogInfo((object)$"Kiwi ({((Object)__instance).GetInstanceID()}) is in REVENGE MODE. Overriding other behaviors to attack {value2.playerUsername}."); val.Field("watchingThreat").SetValue((object)((Component)value2).GetComponent()); val.Method("StartAttackingAndSync", Array.Empty()).GetValue(); } return; } } else { kiwiRevengeTargets.Remove(__instance); } } if (!((EnemyAI)__instance).isOutside && ((EnemyAI)__instance).currentBehaviourStateIndex == 2 && !value && (Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && !kiwiRevengeTargets.ContainsKey(__instance)) { PlayerControllerB targetPlayer = ((EnemyAI)__instance).targetPlayer; _ = val.Field>("LostEggs").Value; foreach (KiwiBabyItem egg in __instance.eggs) { if ((Object)(object)egg != (Object)null && !((GrabbableObject)egg).deactivated && !((GrabbableObject)egg).isHeld && !((GrabbableObject)egg).isHeldByEnemy && Vector3.Distance(((Component)__instance).transform.position, ((Component)egg).transform.position) < 20f && (Object)(object)__instance.birdNest != (Object)null && Vector3.Distance(((Component)egg).transform.position, __instance.birdNest.transform.position) > 8f) { mls.LogInfo((object)$"Kiwi ({((Object)__instance).GetInstanceID()}) grabbed dropped egg {((Object)((Component)egg).gameObject).name} while chasing {targetPlayer.playerUsername}. Returning to nest."); val.Method("PickUpEgg", new object[1] { egg }).GetValue(); ((EnemyAI)__instance).SwitchToBehaviourState(1); val.Field("takeEggBackToNest").SetValue((object)egg); return; } } } if (kiwiEnemyTargets.TryGetValue(__instance, out var value4)) { if ((Object)(object)value4 != (Object)null && (Object)(object)value4 != (Object)(object)__instance && !value4.isEnemyDead) { val.Field("attacking").SetValue((object)true); ((EnemyAI)__instance).SetDestinationToPosition(((Component)value4).transform.position, false); if (Vector3.Distance(((Component)__instance).transform.position, ((Component)value4).transform.position) < 3.5f) { value4.KillEnemy(true); kiwiEnemyTargets.Remove(__instance); mls.LogInfo((object)$"Kiwi ({((Object)__instance).GetInstanceID()}) killed egg thief {value4.enemyType.enemyName}."); } return; } kiwiEnemyTargets.Remove(__instance); } foreach (KiwiBabyItem egg2 in __instance.eggs) { if (!((Object)(object)egg2 != (Object)null) || ((GrabbableObject)egg2).deactivated || !((GrabbableObject)egg2).isHeldByEnemy) { continue; } EnemyAI[] array = Object.FindObjectsOfType(); foreach (EnemyAI val2 in array) { if ((Object)(object)val2 != (Object)(object)__instance && !val2.isEnemyDead && Vector3.Distance(((Component)val2).transform.position, ((Component)egg2).transform.position) < 3f) { mls.LogInfo((object)$"Kiwi ({((Object)__instance).GetInstanceID()}) detected egg thief {val2.enemyType.enemyName} holding egg {((Object)((Component)egg2).gameObject).name}. Hunting it down!"); kiwiEnemyTargets[__instance] = val2; val.Field("attacking").SetValue((object)true); ((EnemyAI)__instance).SetDestinationToPosition(((Component)val2).transform.position, false); return; } } } if (value && ((EnemyAI)__instance).isOutside && (Object)(object)__instance.birdNest != (Object)null && (Object)(object)val.Field("takeEggBackToNest").Value != (Object)null) { float num = Vector3.Distance(((Component)__instance).transform.position, __instance.birdNest.transform.position); ((EnemyAI)__instance).SetDestinationToPosition(__instance.birdNest.transform.position, false); if (num < 3f) { mls.LogInfo((object)$"Kiwi ({((Object)__instance).GetInstanceID()}) returned egg to nest."); val.Method("DropEgg", new object[1] { true }).GetValue(); val.Field("takeEggBackToNest").SetValue((object)null); } return; } if (!kiwiDecisionTimers.ContainsKey(__instance)) { kiwiDecisionTimers[__instance] = 60f; } if (!kiwiPathingCooldowns.ContainsKey(__instance)) { kiwiPathingCooldowns[__instance] = 0f; } if (kiwiLastTransitionTime.TryGetValue(__instance, out var value5) && Time.time - value5 < 10f) { return; } kiwiDecisionTimers[__instance] -= Time.deltaTime; if (kiwiPathingCooldowns[__instance] > 0f) { kiwiPathingCooldowns[__instance] -= Time.deltaTime; bool flag = kiwiPathingCooldowns[__instance] <= 5f; if (((EnemyAI)__instance).isOutside) { EntranceTeleport val3 = FindClosestReachableEntrance(((Component)__instance).transform.position, findEntranceToBuilding: true, KiwiExteriorPathRangeConfig.Value, ((EnemyAI)__instance).agent); if ((Object)(object)val3 != (Object)null) { float num2 = Vector3.Distance(((Component)__instance).transform.position, val3.entrancePoint.position); if (flag && num2 < 5f && (!kiwiLastTransitionTime.TryGetValue(__instance, out var value6) || Time.time - value6 > 10f)) { mls.LogInfo((object)$"Kiwi ({((Object)__instance).GetInstanceID()}) arrived at entrance {((Object)val3).name} (dist {num2}). Sending inside."); SendEnemyInside((EnemyAI)(object)__instance, val3); kiwiPathingCooldowns[__instance] = 0f; kiwiLastTransitionTime[__instance] = Time.time; } else { ((EnemyAI)__instance).SetDestinationToPosition(val3.entrancePoint.position, false); } } return; } EntranceTeleport val4 = FindClosestReachableEntrance(((Component)__instance).transform.position, findEntranceToBuilding: false, KiwiInteriorPathRangeConfig.Value, ((EnemyAI)__instance).agent); if ((Object)(object)val4 != (Object)null) { float num3 = Vector3.Distance(((Component)__instance).transform.position, val4.entrancePoint.position); if (flag && num3 < 5f && (!kiwiLastTransitionTime.TryGetValue(__instance, out var value7) || Time.time - value7 > 10f)) { mls.LogInfo((object)$"Kiwi ({((Object)__instance).GetInstanceID()}) arrived at exit {((Object)val4).name} (dist {num3}). Sending outside."); SendEnemyOutside((EnemyAI)(object)__instance, spawnOnDoor: true, val4); kiwiPathingCooldowns[__instance] = 0f; kiwiLastTransitionTime[__instance] = Time.time; } else { ((EnemyAI)__instance).SetDestinationToPosition(val4.entrancePoint.position, false); } } return; } PlayerControllerB val5 = null; IVisibleThreat value8 = val.Field("attackingThreat").Value; if (value8 != null) { Transform threatTransform = value8.GetThreatTransform(); val5 = (((Object)(object)threatTransform != (Object)null) ? ((Component)threatTransform).GetComponent() : null); } PlayerControllerB val6 = ((EnemyAI)__instance).targetPlayer ?? val5; bool flag2 = false; bool flag3 = false; if (((EnemyAI)__instance).isOutside) { if (value && (Object)(object)__instance.birdNest != (Object)null && __instance.birdNest.transform.position.y < -80f) { flag2 = true; } if (CanKiwiEnterFacility.Value && !flag2) { if ((Object)(object)val6 != (Object)null && val6.isInsideFactory && !val6.isPlayerDead) { flag2 = true; mls.LogInfo((object)("LethalEscape Kiwi: Target player " + val6.playerUsername + " is inside.")); } else if ((Object)(object)val6 == (Object)null) { for (int j = 0; j < StartOfRound.Instance.allPlayerScripts.Length; j++) { PlayerControllerB val7 = StartOfRound.Instance.allPlayerScripts[j]; if ((Object)(object)val7 != (Object)null && val7.isPlayerControlled && !val7.isPlayerDead && val7.isInsideFactory) { flag2 = true; mls.LogInfo((object)("LethalEscape Kiwi: Player " + val7.playerUsername + " is inside (fallback scan).")); break; } } } else if (KiwiCanCarryEggsInOut.Value && !value) { foreach (KiwiBabyItem egg3 in __instance.eggs) { if ((Object)(object)egg3 != (Object)null && !((GrabbableObject)egg3).deactivated && !((GrabbableObject)egg3).isHeldByEnemy && ((GrabbableObject)egg3).isInFactory) { flag2 = true; mls.LogInfo((object)("LethalEscape Kiwi: An egg (" + ((Object)((Component)egg3).gameObject).name + ") is inside the facility.")); break; } } } if (!flag2 && kiwiDecisionTimers[__instance] <= 0f) { if (Random.Range(0f, 100f) < KiwiChanceToEnterFacilityPerMinute.Value) { flag2 = true; } kiwiDecisionTimers[__instance] = 60f; } } } else if ((Object)(object)val6 != (Object)null && !val6.isInsideFactory && !val6.isPlayerDead) { flag3 = true; mls.LogInfo((object)("LethalEscape Kiwi: Target player " + val6.playerUsername + " is outside.")); } else if ((Object)(object)val6 == (Object)null) { for (int k = 0; k < StartOfRound.Instance.allPlayerScripts.Length; k++) { PlayerControllerB val8 = StartOfRound.Instance.allPlayerScripts[k]; if ((Object)(object)val8 != (Object)null && val8.isPlayerControlled && !val8.isPlayerDead && !val8.isInsideFactory) { flag3 = true; mls.LogInfo((object)("LethalEscape Kiwi: Player " + val8.playerUsername + " is outside (fallback scan).")); break; } } } else if (value && KiwiCanCarryEggsInOut.Value && (Object)(object)__instance.birdNest != (Object)null && __instance.birdNest.transform.position.y > -80f) { flag3 = true; } else if (kiwiDecisionTimers[__instance] <= 0f) { if (Random.Range(0f, 100f) < KiwiChanceToExitFacilityPerMinute.Value) { flag3 = true; } kiwiDecisionTimers[__instance] = 60f; } if (flag2) { EntranceTeleport val9 = FindClosestReachableEntrance(((Component)__instance).transform.position, findEntranceToBuilding: true, KiwiExteriorPathRangeConfig.Value, ((EnemyAI)__instance).agent); if ((Object)(object)val9 != (Object)null) { ((EnemyAI)__instance).SetDestinationToPosition(val9.entrancePoint.position, false); kiwiPathingCooldowns[__instance] = KiwiPathingCooldownConfig.Value; } } else if (flag3) { EntranceTeleport val10 = FindClosestReachableEntrance(((Component)__instance).transform.position, findEntranceToBuilding: false, KiwiInteriorPathRangeConfig.Value, ((EnemyAI)__instance).agent); if ((Object)(object)val10 != (Object)null) { ((EnemyAI)__instance).SetDestinationToPosition(val10.entrancePoint.position, false); kiwiPathingCooldowns[__instance] = KiwiPathingCooldownConfig.Value; } } } [HarmonyPatch(typeof(GiantKiwiAI), "DropEgg")] [HarmonyPostfix] public static void KiwiRevengeLogic_DropEggPostfix(GiantKiwiAI __instance, bool dropInNest) { if (((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost && dropInNest && kiwiRevengeTargets.TryGetValue(__instance, out var value)) { if ((Object)(object)value != (Object)null && !value.isPlayerDead && value.isPlayerControlled) { mls.LogInfo((object)$"Kiwi ({((Object)__instance).GetInstanceID()}) has secured its egg. Now seeking revenge on {value.playerUsername}!"); Traverse obj = Traverse.Create((object)__instance); obj.Field("watchingThreat").SetValue((object)((Component)value).GetComponent()); obj.Method("StartAttackingAndSync", Array.Empty()).GetValue(); } else { mls.LogInfo((object)$"Kiwi ({((Object)__instance).GetInstanceID()}) wanted revenge, but its target is no longer valid."); } kiwiRevengeTargets.Remove(__instance); } } [HarmonyPatch(typeof(BaboonBirdAI), "Update")] [HarmonyPrefix] public static bool RadMechAI_Update_Prefix(RadMechAI __instance) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Invalid comparison between Unknown and I4 //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) if (!((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost || ((EnemyAI)__instance).isEnemyDead || ((EnemyAI)__instance).inSpecialAnimation || ((EnemyAI)__instance).stunNormalizedTimer > 0f) { if (oldBirdsPathingToDoor.ContainsKey(__instance)) { oldBirdsPathingToDoor.Remove(__instance); } return true; } if (!oldBirdsPathingToDoor.ContainsKey(__instance)) { oldBirdsPathingToDoor[__instance] = false; } if (!oldBirdPathingCooldowns.ContainsKey(__instance)) { oldBirdPathingCooldowns[__instance] = 0f; } if (!oldBirdDecisionTimers.ContainsKey(__instance)) { oldBirdDecisionTimers[__instance] = 60f; } if (oldBirdsPathingToDoor.TryGetValue(__instance, out var value) && value) { if (!((EnemyAI)__instance).agent.hasPath || (int)((EnemyAI)__instance).agent.pathStatus == 2) { mls.LogInfo((object)$"Old Bird ({((Object)__instance).GetInstanceID()}) lost its path to the door. Resetting state."); oldBirdsPathingToDoor[__instance] = false; oldBirdPathingCooldowns[__instance] = OldBirdPathingCooldownConfig.Value; return true; } if (((EnemyAI)__instance).agent.remainingDistance < 3.5f) { if (((EnemyAI)__instance).isOutside) { mls.LogInfo((object)$"Old Bird ({((Object)__instance).GetInstanceID()}) has arrived at entrance, sending inside."); SendEnemyInside((EnemyAI)(object)__instance); } else { mls.LogInfo((object)$"Old Bird ({((Object)__instance).GetInstanceID()}) has arrived at exit, sending outside."); SendEnemyOutside((EnemyAI)(object)__instance); } oldBirdsPathingToDoor[__instance] = false; oldBirdPathingCooldowns[__instance] = OldBirdPathingCooldownConfig.Value; return true; } return false; } if (oldBirdPathingCooldowns[__instance] > 0f) { oldBirdPathingCooldowns[__instance] -= Time.deltaTime; return true; } oldBirdDecisionTimers[__instance] -= Time.deltaTime; if (oldBirdDecisionTimers[__instance] > 0f) { return true; } oldBirdDecisionTimers[__instance] = 60f; bool flag = false; string arg = ""; bool flag2 = false; string arg2 = ""; PlayerControllerB val = null; IVisibleThreat threatScript = __instance.targetedThreat.threatScript; if (threatScript != null && (Object)(object)threatScript.GetThreatTransform() != (Object)null) { val = ((Component)threatScript.GetThreatTransform()).GetComponent(); } if (((EnemyAI)__instance).isOutside) { if (CanOldBirdEnterFacility.Value) { if ((Object)(object)val != (Object)null && val.isInsideFactory && !val.isPlayerDead) { flag = true; arg = "Target player " + val.playerUsername + " is inside."; } else if (Random.Range(0f, 100f) < OldBirdChanceToEnterFacilityPerMinute.Value) { flag = true; arg = "Random decision to explore inside."; } } } else if ((Object)(object)val != (Object)null && !val.isInsideFactory && !val.isPlayerDead) { flag2 = true; arg2 = "Target player " + val.playerUsername + " is outside."; } else if (Random.Range(0f, 100f) < OldBirdChanceToExitFacilityPerMinute.Value) { flag2 = true; arg2 = "Random decision to explore outside."; } if (flag) { EntranceTeleport val2 = FindClosestReachableEntrance(((Component)__instance).transform.position, findEntranceToBuilding: true, OldBirdExteriorPathRangeConfig.Value, ((EnemyAI)__instance).agent); if ((Object)(object)val2 != (Object)null) { ((EnemyAI)__instance).StopSearch(__instance.searchForPlayers, true); ((EnemyAI)__instance).SetDestinationToPosition(val2.entrancePoint.position, false); mls.LogInfo((object)$"Old Bird ({((Object)__instance).GetInstanceID()}) decided to enter ({arg}). Pathing to {((Object)val2).name}."); oldBirdsPathingToDoor[__instance] = true; return false; } } else if (flag2) { EntranceTeleport val3 = FindClosestReachableEntrance(((Component)__instance).transform.position, findEntranceToBuilding: false, OldBirdInteriorPathRangeConfig.Value, ((EnemyAI)__instance).agent); if ((Object)(object)val3 != (Object)null) { ((EnemyAI)__instance).StopSearch(__instance.searchForPlayers, true); ((EnemyAI)__instance).SetDestinationToPosition(val3.entrancePoint.position, false); mls.LogInfo((object)$"Old Bird ({((Object)__instance).GetInstanceID()}) decided to exit ({arg2}). Pathing to {((Object)val3).name}."); oldBirdsPathingToDoor[__instance] = true; return false; } } return true; } private static void ApplyOldBirdStompDamageToClients(RadMechAI instance, Transform stompTransform, float radius) { //IL_0079: 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_00de: Unknown result type (might be due to invalid IL or missing references) if (((EnemyAI)instance).isOutside || !((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { return; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if ((Object)(object)val == (Object)null || !val.isPlayerControlled || val.isPlayerDead || (Object)(object)val == (Object)(object)GameNetworkManager.Instance.localPlayerController || !((EnemyAI)instance).PlayerIsTargetable(val, false, true, true)) { continue; } float num = Vector3.Distance(((Component)val).transform.position, stompTransform.position); if (num < radius) { int num2 = 0; if ((double)num < (double)radius * 0.175) { num2 = 70; } else if (num < radius * 0.5f) { num2 = 30; } if (num2 > 0) { mls.LogInfo((object)$"Old Bird stomping non-host player {val.playerUsername} for {num2} damage."); val.DamagePlayerFromOtherClientServerRpc(num2, Vector3.zero, -1); } } } } [HarmonyPatch(typeof(RadMechAI), "StompLeftFoot")] [HarmonyPostfix] public static void RadMechAI_StompLeftFoot_Postfix(RadMechAI __instance) { ApplyOldBirdStompDamageToClients(__instance, __instance.leftFootPoint, 5f); } [HarmonyPatch(typeof(RadMechAI), "StompRightFoot")] [HarmonyPostfix] public static void RadMechAI_StompRightFoot_Postfix(RadMechAI __instance) { ApplyOldBirdStompDamageToClients(__instance, __instance.rightFootPoint, 5f); } [HarmonyPatch(typeof(RadMechAI), "StompBothFeet")] [HarmonyPostfix] public static void RadMechAI_StompBothFeet_Postfix(RadMechAI __instance) { ApplyOldBirdStompDamageToClients(__instance, ((Component)__instance).transform, 10f); } [HarmonyPatch(typeof(RadMechAI), "OnCollideWithPlayer")] [HarmonyPostfix] public static void RadMechAI_OnCollideWithPlayer_Postfix(RadMechAI __instance, Collider other) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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) if (((EnemyAI)__instance).isOutside || !((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost) { return; } Traverse val = Traverse.Create((object)__instance); if (!(val.Field("timeSinceGrabbingPlayer").Value < 1f) && __instance.attemptingGrab && !((EnemyAI)__instance).inSpecialAnimation) { PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && component.isPlayerControlled && !component.isPlayerDead && (Object)(object)component != (Object)(object)GameNetworkManager.Instance.localPlayerController && ((EnemyAI)__instance).PlayerIsTargetable(component, false, true, true) && !Physics.Linecast(__instance.centerPosition.position, ((Component)component).transform.position + Vector3.up * 0.6f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1)) { mls.LogInfo((object)("Host-controlled Old Bird (inside) initiating grab on non-host player " + component.playerUsername + ".")); val.Field("timeSinceGrabbingPlayer").SetValue((object)0f); __instance.GrabPlayerServerRpc((int)component.playerClientId); } } } public static Vector3 GetRandomPositionAroundKiwiObject(Vector3 objectPos, float radius, NavMeshAgent agent) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_010c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)agent == (Object)null || !agent.isOnNavMesh) { mls.LogWarning((object)"GetRandomPositionAroundKiwiObject: Agent is null or not on NavMesh."); return Vector3.zero; } Vector3 randomNavMeshPositionInBoxPredictable = RoundManager.Instance.GetRandomNavMeshPositionInBoxPredictable(objectPos, radius, default(NavMeshHit), (Random)null, agent.areaMask, 0.5f); if (randomNavMeshPositionInBoxPredictable == Vector3.zero) { mls.LogWarning((object)$"GetRandomPositionAroundKiwiObject: GetRandomNavMeshPositionInBoxPredictable failed for {objectPos}. Trying fallback."); EnemyAI component = ((Component)agent).GetComponent(); if ((Object)(object)component != (Object)null && component.allAINodes != null && component.allAINodes.Length != 0) { Transform val = null; float num = float.MaxValue; GameObject[] allAINodes = component.allAINodes; foreach (GameObject val2 in allAINodes) { if (!((Object)(object)val2 == (Object)null)) { float num2 = Vector3.Distance(val2.transform.position, objectPos); if (num2 < num && num2 < radius * 2f) { num = num2; val = val2.transform; } } } if ((Object)(object)val != (Object)null) { return val.position; } return component.allAINodes[Random.Range(0, component.allAINodes.Length)].transform.position; } mls.LogError((object)"GetRandomPositionAroundKiwiObject: Fallback to find any AI node also failed."); } return randomNavMeshPositionInBoxPredictable; } [HarmonyPatch(typeof(LETimerFunctions), "Update")] [HarmonyPostfix] public static void AiBridgeUpdater() { AIBridge.UpdateTransitions(); } public static EntranceTeleport FindClosestEntranceToPoint(Vector3 position, bool findEntranceToBuilding) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) EntranceTeleport[] array = Object.FindObjectsOfType(false); EntranceTeleport result = null; float num = float.MaxValue; EntranceTeleport[] array2 = array; foreach (EntranceTeleport val in array2) { if (val.isEntranceToBuilding == findEntranceToBuilding) { float num2 = Vector3.Distance(position, val.entrancePoint.position); if (num2 < num) { num = num2; result = val; } } } return result; } public static EntranceTeleport FindClosestReachableEntrance(Vector3 currentPosition, bool findEntranceToBuilding, float maxPathDistance, NavMeshAgent agent) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) EntranceTeleport[] array = Object.FindObjectsOfType(false); EntranceTeleport val = null; float num = float.MaxValue; if ((Object)(object)agent == (Object)null || !agent.isOnNavMesh) { mls.LogWarning((object)"FindClosestReachableEntrance: Agent is null or not on NavMesh."); return null; } EntranceTeleport[] array2 = array; foreach (EntranceTeleport val2 in array2) { if (val2.isEntranceToBuilding != findEntranceToBuilding) { continue; } NavMeshPath val3 = new NavMeshPath(); if (agent.CalculatePath(val2.entrancePoint.position, val3) && (int)val3.status == 0) { float num2 = 0f; for (int j = 0; j < val3.corners.Length - 1; j++) { num2 += Vector3.Distance(val3.corners[j], val3.corners[j + 1]); } if (num2 < num) { num = num2; val = val2; } } } if ((Object)(object)val != (Object)null) { mls.LogInfo((object)$"FindClosestReachableEntrance found a valid door: {((Object)val).name} with path length: {num}"); } return val; } public static void SendEnemyInside(EnemyAI instance, EntranceTeleport specificDoor = null) { //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) if (!instance.agent.isOnNavMesh && ((Behaviour)instance.agent).enabled) { mls.LogWarning((object)("SendEnemyInside: " + instance.enemyType.enemyName + " agent was enabled but not on NavMesh. Will attempt to warp.")); } else if (!((Behaviour)instance.agent).enabled) { mls.LogWarning((object)("SendEnemyInside: " + instance.enemyType.enemyName + " agent was disabled. Enabling and will attempt to warp.")); ((Behaviour)instance.agent).enabled = true; } instance.isOutside = false; instance.allAINodes = GameObject.FindGameObjectsWithTag("AINode"); instance.EnableEnemyMesh(true, false, false); Vector3 val; if ((Object)(object)specificDoor != (Object)null && specificDoor.FindExitPoint() && (Object)(object)specificDoor.exitScript != (Object)null) { val = specificDoor.exitScript.entrancePoint.position; Transform val2 = instance.ChooseClosestNodeToPosition(val, false, 0); NavMeshHit val3 = default(NavMeshHit); if ((Object)(object)val2 != (Object)null) { val = val2.position; } else if (NavMesh.SamplePosition(val, ref val3, 8f, instance.agent.areaMask)) { val = ((NavMeshHit)(ref val3)).position; } mls.LogInfo((object)$"{instance.enemyType.enemyName} using paired entrance '{((Object)specificDoor.exitScript).name}' at {val} (inside)."); } else { val = RoundManager.FindMainEntrancePosition(false, false); mls.LogInfo((object)$"{instance.enemyType.enemyName} being sent inside. Using main entrance interior position: {val}"); } if (val == Vector3.zero) { mls.LogError((object)("CRITICAL: Could not determine a valid warp position for " + instance.enemyType.enemyName + " to go inside. Aborting SendEnemyInside.")); instance.isOutside = true; instance.EnableEnemyMesh(true, false, false); return; } ((Component)instance).transform.position = val; instance.serverPosition = val; if (!instance.agent.Warp(val)) { mls.LogWarning((object)$"SendEnemyInside: Agent.Warp failed for {instance.enemyType.enemyName} at {val}. Agent status: enabled={((Behaviour)instance.agent).enabled}, isOnNavMesh={instance.agent.isOnNavMesh}, pathPending={instance.agent.pathPending}"); } if (((NetworkBehaviour)instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { instance.ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } instance.SyncPositionToClients(); FlowermanAI val4 = (FlowermanAI)(object)((instance is FlowermanAI) ? instance : null); if ((Object)(object)val4 != (Object)null) { ((EnemyAI)val4).StartSearch(((Component)val4).transform.position, (AISearchRoutine)null); } GiantKiwiAI val5 = (GiantKiwiAI)(object)((instance is GiantKiwiAI) ? instance : null); if ((Object)(object)val5 != (Object)null) { ((EnemyAI)val5).isInsidePlayerShip = false; } BaboonBirdAI val6 = (BaboonBirdAI)(object)((instance is BaboonBirdAI) ? instance : null); if ((Object)(object)val6 != (Object)null) { ((EnemyAI)val6).isInsidePlayerShip = false; } MaskedPlayerEnemy val7 = (MaskedPlayerEnemy)(object)((instance is MaskedPlayerEnemy) ? instance : null); if ((Object)(object)val7 != (Object)null) { Traverse.Create((object)val7).Field("mainEntrancePosition").SetValue((object)RoundManager.FindMainEntrancePosition(true, false)); } mls.LogInfo((object)$"{instance.enemyType.enemyName} sent inside. isOutside: {instance.isOutside}, NavMesh AreaMask: {instance.agent.areaMask}"); } public static void SendEnemyOutside(EnemyAI instance, bool spawnOnDoor = true, EntranceTeleport specificDoor = null) { //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0388: Unknown result type (might be due to invalid IL or missing references) //IL_047b: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Unknown result type (might be due to invalid IL or missing references) if (!instance.agent.isOnNavMesh && ((Behaviour)instance.agent).enabled) { mls.LogWarning((object)("SendEnemyOutside: " + instance.enemyType.enemyName + " agent was enabled but not on NavMesh. Will attempt to warp.")); } else if (!((Behaviour)instance.agent).enabled) { mls.LogWarning((object)("SendEnemyOutside: " + instance.enemyType.enemyName + " agent was disabled. Enabling and will attempt to warp.")); ((Behaviour)instance.agent).enabled = true; } instance.isOutside = true; instance.allAINodes = GameObject.FindGameObjectsWithTag("OutsideAINode"); instance.EnableEnemyMesh(true, false, false); Vector3 val; if ((Object)(object)specificDoor != (Object)null && specificDoor.FindExitPoint() && (Object)(object)specificDoor.exitScript != (Object)null) { val = specificDoor.exitScript.entrancePoint.position; Transform val2 = instance.ChooseClosestNodeToPosition(val, true, 0); NavMeshHit val3 = default(NavMeshHit); if ((Object)(object)val2 != (Object)null) { val = val2.position; } else if (NavMesh.SamplePosition(val, ref val3, 8f, instance.agent.areaMask)) { val = ((NavMeshHit)(ref val3)).position; } mls.LogInfo((object)$"{instance.enemyType.enemyName} using paired exit '{((Object)specificDoor.exitScript).name}' at {val} (outside)."); } else { val = RoundManager.FindMainEntrancePosition(true, true); mls.LogInfo((object)$"{instance.enemyType.enemyName} being sent outside. Using main entrance exterior position: {val}"); } if (val == Vector3.zero) { mls.LogError((object)("CRITICAL: Could not determine a valid warp position for " + instance.enemyType.enemyName + " to go outside. Aborting SendEnemyOutside.")); instance.isOutside = false; instance.EnableEnemyMesh(true, false, false); return; } int areaFromName = NavMesh.GetAreaFromName("Terrain"); if (areaFromName != -1) { instance.agent.areaMask = 1 << areaFromName; } else { mls.LogWarning((object)$"Agent areaMask remains {instance.agent.areaMask}."); } NavMeshHit val4 = default(NavMeshHit); NavMeshHit val7 = default(NavMeshHit); if (!spawnOnDoor || (NavMesh.SamplePosition(val, ref val4, 2f, instance.agent.areaMask) && Vector3.Distance(((NavMeshHit)(ref val4)).position, val) > 1.5f)) { Transform val5 = instance.ChooseClosestNodeToPosition(val, true, 0); if ((Object)(object)val5 != (Object)null) { mls.LogInfo((object)$"SendEnemyOutside: Warping {instance.enemyType.enemyName} to closest outside node: {val5.position} (spawnOnDoor: {spawnOnDoor})"); val = val5.position; } else { mls.LogWarning((object)$"SendEnemyOutside: Could not find a close outside node for {instance.enemyType.enemyName} near {val}. Attempting to sample NavMesh at original warpPosition."); NavMeshHit val6 = default(NavMeshHit); if (NavMesh.SamplePosition(val, ref val6, 5f, instance.agent.areaMask)) { val = ((NavMeshHit)(ref val6)).position; } else { mls.LogError((object)$"CRITICAL: SendEnemyOutside: Failed to sample NavMesh around {val} for {instance.enemyType.enemyName}. May get stuck."); } } } else if (NavMesh.SamplePosition(val, ref val7, 1f, instance.agent.areaMask)) { val = ((NavMeshHit)(ref val7)).position; mls.LogInfo((object)$"SendEnemyOutside: Warping {instance.enemyType.enemyName} near door at sampled position: {val}"); } else { mls.LogWarning((object)$"SendEnemyOutside: Could not sample NavMesh directly at door exit {val} for {instance.enemyType.enemyName}. Will use a nearby node search fallback."); Transform val8 = instance.ChooseClosestNodeToPosition(val, true, 0); if ((Object)(object)val8 != (Object)null) { val = val8.position; } } ((Component)instance).transform.position = val; instance.serverPosition = val; if (!instance.agent.Warp(val)) { mls.LogWarning((object)$"SendEnemyOutside: Agent.Warp failed for {instance.enemyType.enemyName} at {val}. Agent status: enabled={((Behaviour)instance.agent).enabled}, isOnNavMesh={instance.agent.isOnNavMesh}, pathPending={instance.agent.pathPending}"); } if (((NetworkBehaviour)instance).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { instance.ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } instance.SyncPositionToClients(); BaboonBirdAI val9 = (BaboonBirdAI)(object)((instance is BaboonBirdAI) ? instance : null); if ((Object)(object)val9 != (Object)null) { ((EnemyAI)val9).isInsidePlayerShip = false; } FlowermanAI val10 = (FlowermanAI)(object)((instance is FlowermanAI) ? instance : null); if ((Object)(object)val10 != (Object)null) { ((EnemyAI)val10).StartSearch(((Component)val10).transform.position, (AISearchRoutine)null); } MaskedPlayerEnemy val11 = (MaskedPlayerEnemy)(object)((instance is MaskedPlayerEnemy) ? instance : null); if ((Object)(object)val11 != (Object)null) { Traverse.Create((object)val11).Field("mainEntrancePosition").SetValue((object)RoundManager.FindMainEntrancePosition(true, true)); } mls.LogInfo((object)$"{instance.enemyType.enemyName} sent outside. isOutside: {instance.isOutside}, NavMesh AreaMask: {instance.agent.areaMask}"); } }