Decompiled source of LethalOptimizer v1.4.0
LethalOptimizer.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.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 LethalOptimizer.Config; using LethalOptimizer.Core; using LethalOptimizer.Patches; using LethalOptimizer.Patches.AI; using LethalOptimizer.Patches.Interior; using LethalOptimizer.Patches.Traps; using LethalOptimizer.ShipItemOptimizer; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.AI; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LethalOptimizer { [BepInPlugin("com.lethal.optimizer", "LethalOptimizer", "1.4.0")] public class Plugin : BaseUnityPlugin { private Harmony _harmony; public static Plugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } private void Awake() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; PluginConfig.Initialize(((BaseUnityPlugin)this).Config); if (!PluginConfig.EnableAllOptimizations.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"LethalOptimizer is disabled via config"); return; } _harmony = new Harmony("com.lethal.optimizer"); _harmony.PatchAll(typeof(EnemyAIPatches)); _harmony.PatchAll(typeof(RoundManagerPatches)); _harmony.PatchAll(typeof(GrabbableObjectPatches)); _harmony.PatchAll(typeof(HUDManagerPatches)); _harmony.PatchAll(typeof(PlayerPatches)); _harmony.PatchAll(typeof(JesterPatches)); _harmony.PatchAll(typeof(CrawlerPatches)); _harmony.PatchAll(typeof(SpringManPatches)); _harmony.PatchAll(typeof(BaboonPatches)); _harmony.PatchAll(typeof(FlowermanPatches)); _harmony.PatchAll(typeof(GhostGirlPatches)); _harmony.PatchAll(typeof(HoarderBugPatches)); _harmony.PatchAll(typeof(SporeLizardPatches)); _harmony.PatchAll(typeof(ForestGiantPatches)); _harmony.PatchAll(typeof(NutcrackerPatches)); _harmony.PatchAll(typeof(MouthDogPatches)); _harmony.PatchAll(typeof(SandSpiderPatches)); _harmony.PatchAll(typeof(MaskedPatches)); _harmony.PatchAll(typeof(BlobPatches)); _harmony.PatchAll(typeof(RadMechPatches)); _harmony.PatchAll(typeof(ButlerPatches)); _harmony.PatchAll(typeof(FlowerSnakePatches)); _harmony.PatchAll(typeof(CaveDwellerPatches)); _harmony.PatchAll(typeof(TurretPatches)); _harmony.PatchAll(typeof(LandminePatches)); _harmony.PatchAll(typeof(SpikeRoofTrapPatches)); _harmony.PatchAll(typeof(RigidbodyFreezerPatches)); _harmony.PatchAll(typeof(ItemCollisionPatches)); _harmony.PatchAll(typeof(ItemLODPatches)); _harmony.PatchAll(typeof(ShipDistancePatches)); _harmony.PatchAll(typeof(RoomCullingPatches)); _harmony.PatchAll(typeof(PortalCullingPatches)); _harmony.PatchAll(typeof(InteriorLODPatches)); _harmony.PatchAll(typeof(LightCullingPatches)); _harmony.PatchAll(typeof(InteriorPhysicsCullingPatches)); _harmony.PatchAll(typeof(TimeOfDayPatches)); ObjectPool.Initialize(); AINodeCache.Initialize(); GraphicsOptimizer.Initialize(); ShipOptimizer.Initialize(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"LethalOptimizer v1.4.0 loaded!"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"18 AI + 3 trap + distance + NavMesh cache optimizations active"); } private void Update() { if (PluginConfig.EnableShipItemOptimizations.Value) { if (PluginConfig.EnableRigidbodyFreezing.Value) { RigidbodyFreezer.Update(); } if (PluginConfig.EnableItemLOD.Value) { ItemLODOptimizer.Update(); } if (PluginConfig.EnableShipDistanceOptimization.Value) { ShipDistanceOptimizer.Update(); } } if (PluginConfig.EnableInteriorOptimizations.Value) { if (PluginConfig.EnableRoomCulling.Value) { RoomCulling.Update(); } if (PluginConfig.EnablePortalCulling.Value) { PortalCulling.Update(); } if (PluginConfig.EnableInteriorLOD.Value) { InteriorLOD.Update(); } if (PluginConfig.EnableLightCulling.Value) { LightCulling.Update(); } if (PluginConfig.EnableInteriorPhysicsCulling.Value) { InteriorPhysicsCulling.Update(); } } if (PluginConfig.EnableLogging.Value) { PerformanceMonitor.LogMetrics(); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } ObjectPool.Cleanup(); ComponentCache.Clear(); NetworkThrottle.Clear(); PerformanceMonitor.Clear(); NavMeshCache.Clear(); DistanceOptimizer.Clear(); ParticleOptimizer.Clear(); RigidbodyFreezer.Clear(); ItemCollisionOptimizer.Restore(); ItemCollisionOptimizer.Clear(); ItemLODOptimizer.Clear(); ShipDistanceOptimizer.Clear(); RoomCulling.Clear(); PortalCulling.Clear(); InteriorLOD.Clear(); LightCulling.Clear(); InteriorPhysicsCulling.Clear(); } } public static class PluginInfo { public const string PLUGIN_GUID = "com.lethal.optimizer"; public const string PLUGIN_NAME = "LethalOptimizer"; public const string PLUGIN_VERSION = "1.4.0"; } } namespace LethalOptimizer.ShipItemOptimizer { public static class ItemCollisionOptimizer { private static readonly HashSet<int> _trackedItems = new HashSet<int>(); private static readonly List<Collider> _itemColliders = new List<Collider>(); private static bool _initialized; private const int PROPS_LAYER = 6; public static void Initialize() { if (!_initialized) { Physics.IgnoreLayerCollision(6, 6, true); _initialized = true; Plugin.Log.LogInfo((object)"Item collision optimizer initialized - item-to-item collisions disabled"); } } public static void Restore() { if (_initialized) { Physics.IgnoreLayerCollision(6, 6, false); _initialized = false; Plugin.Log.LogInfo((object)"Item collision optimizer restored - item-to-item collisions enabled"); } } public static void TrackItem(GrabbableObject item) { if ((Object)(object)item == (Object)null) { return; } int instanceID = ((Object)item).GetInstanceID(); if (_trackedItems.Contains(instanceID)) { return; } _trackedItems.Add(instanceID); Collider[] componentsInChildren = ((Component)item).GetComponentsInChildren<Collider>(); foreach (Collider val in componentsInChildren) { if ((Object)(object)val != (Object)null && !_itemColliders.Contains(val)) { _itemColliders.Add(val); } } } public static void UntrackItem(GrabbableObject item) { if (!((Object)(object)item == (Object)null)) { int instanceID = ((Object)item).GetInstanceID(); _trackedItems.Remove(instanceID); Collider[] componentsInChildren = ((Component)item).GetComponentsInChildren<Collider>(); foreach (Collider item2 in componentsInChildren) { _itemColliders.Remove(item2); } } } public static void DisableCollisionsForItem(GrabbableObject item) { if ((Object)(object)item == (Object)null) { return; } Collider[] componentsInChildren = ((Component)item).GetComponentsInChildren<Collider>(); foreach (Collider val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } foreach (Collider itemCollider in _itemColliders) { if (!((Object)(object)itemCollider == (Object)null) && !((Object)(object)itemCollider == (Object)(object)val)) { Physics.IgnoreCollision(val, itemCollider, true); } } } } public static void EnableCollisionsForItem(GrabbableObject item) { if ((Object)(object)item == (Object)null) { return; } Collider[] componentsInChildren = ((Component)item).GetComponentsInChildren<Collider>(); foreach (Collider val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } foreach (Collider itemCollider in _itemColliders) { if (!((Object)(object)itemCollider == (Object)null) && !((Object)(object)itemCollider == (Object)(object)val)) { Physics.IgnoreCollision(val, itemCollider, false); } } } } public static int GetTrackedCount() { return _trackedItems.Count; } public static void Clear() { _trackedItems.Clear(); _itemColliders.Clear(); } } [HarmonyPatch] public static class ItemCollisionPatches { [HarmonyPatch(typeof(StartOfRound), "Start")] [HarmonyPostfix] public static void StartOfRound_Start_Postfix() { if (PluginConfig.EnableShipItemOptimizations.Value && PluginConfig.EnableItemCollisionOptimization.Value) { ItemCollisionOptimizer.Initialize(); } } [HarmonyPatch(typeof(GrabbableObject), "OnBroughtToShip")] [HarmonyPostfix] public static void OnBroughtToShip_Postfix(GrabbableObject __instance) { if (PluginConfig.EnableShipItemOptimizations.Value && PluginConfig.EnableItemCollisionOptimization.Value) { ItemCollisionOptimizer.TrackItem(__instance); } } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] public static void Disconnect_Postfix() { ItemCollisionOptimizer.Restore(); ItemCollisionOptimizer.Clear(); } } public static class ItemLODOptimizer { private class TrackedItem { public GrabbableObject Item; public Renderer[] Renderers; public ScanNodeProperties ScanNode; public bool RenderersDisabled; public bool ScanNodeDisabled; } private static readonly Dictionary<int, TrackedItem> _trackedItems = new Dictionary<int, TrackedItem>(); private static float _lastUpdateTime; private static PlayerControllerB _localPlayer; private const float UPDATE_INTERVAL = 0.5f; private const float DISABLE_RENDER_DISTANCE = 30f; private const float DISABLE_SCANNODE_DISTANCE = 20f; public static void TrackItem(GrabbableObject item) { if (!((Object)(object)item == (Object)null)) { int instanceID = ((Object)item).GetInstanceID(); if (!_trackedItems.ContainsKey(instanceID)) { TrackedItem value = new TrackedItem { Item = item, Renderers = ((Component)item).GetComponentsInChildren<Renderer>(), ScanNode = ((Component)item).GetComponentInChildren<ScanNodeProperties>(), RenderersDisabled = false, ScanNodeDisabled = false }; _trackedItems[instanceID] = value; } } } public static void UntrackItem(GrabbableObject item) { if ((Object)(object)item == (Object)null) { return; } int instanceID = ((Object)item).GetInstanceID(); if (_trackedItems.TryGetValue(instanceID, out var value)) { if (value.RenderersDisabled) { SetRenderersEnabled(value, enabled: true); } if (value.ScanNodeDisabled && (Object)(object)value.ScanNode != (Object)null) { ((Component)value.ScanNode).gameObject.SetActive(true); } _trackedItems.Remove(instanceID); } } public static void Update() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) if (Time.time - _lastUpdateTime < 0.5f) { return; } _lastUpdateTime = Time.time; if ((Object)(object)_localPlayer == (Object)null || _localPlayer.isPlayerDead) { _localPlayer = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)_localPlayer == (Object)null) { return; } } Vector3 position = ((Component)_localPlayer).transform.position; List<int> list = null; foreach (KeyValuePair<int, TrackedItem> trackedItem in _trackedItems) { TrackedItem value = trackedItem.Value; if ((Object)(object)value.Item == (Object)null) { if (list == null) { list = new List<int>(); } list.Add(trackedItem.Key); continue; } if (value.Item.isHeld) { if (value.RenderersDisabled) { SetRenderersEnabled(value, enabled: true); } if (value.ScanNodeDisabled && (Object)(object)value.ScanNode != (Object)null) { ((Component)value.ScanNode).gameObject.SetActive(true); value.ScanNodeDisabled = false; } continue; } float num = Vector3.Distance(position, ((Component)value.Item).transform.position); if (num > 30f) { if (!value.RenderersDisabled) { SetRenderersEnabled(value, enabled: false); } } else if (value.RenderersDisabled) { SetRenderersEnabled(value, enabled: true); } if (!((Object)(object)value.ScanNode != (Object)null)) { continue; } if (num > 20f) { if (!value.ScanNodeDisabled) { ((Component)value.ScanNode).gameObject.SetActive(false); value.ScanNodeDisabled = true; } } else if (value.ScanNodeDisabled) { ((Component)value.ScanNode).gameObject.SetActive(true); value.ScanNodeDisabled = false; } } if (list == null) { return; } foreach (int item in list) { _trackedItems.Remove(item); } } private static void SetRenderersEnabled(TrackedItem tracked, bool enabled) { Renderer[] renderers = tracked.Renderers; foreach (Renderer val in renderers) { if ((Object)(object)val != (Object)null) { val.enabled = enabled; } } tracked.RenderersDisabled = !enabled; } public static void RestoreAll() { foreach (TrackedItem value in _trackedItems.Values) { if (value.RenderersDisabled) { SetRenderersEnabled(value, enabled: true); } if (value.ScanNodeDisabled && (Object)(object)value.ScanNode != (Object)null) { ((Component)value.ScanNode).gameObject.SetActive(true); value.ScanNodeDisabled = false; } } } public static (int total, int renderDisabled, int scanDisabled) GetStats() { int num = 0; int num2 = 0; foreach (TrackedItem value in _trackedItems.Values) { if (value.RenderersDisabled) { num++; } if (value.ScanNodeDisabled) { num2++; } } return (_trackedItems.Count, num, num2); } public static void Clear() { RestoreAll(); _trackedItems.Clear(); _localPlayer = null; } } [HarmonyPatch] public static class ItemLODPatches { [HarmonyPatch(typeof(GrabbableObject), "OnBroughtToShip")] [HarmonyPostfix] public static void OnBroughtToShip_Postfix(GrabbableObject __instance) { if (PluginConfig.EnableShipItemOptimizations.Value && PluginConfig.EnableItemLOD.Value) { ItemLODOptimizer.TrackItem(__instance); } } [HarmonyPatch(typeof(GrabbableObject), "GrabItem")] [HarmonyPrefix] public static void GrabItem_Prefix(GrabbableObject __instance) { if (PluginConfig.EnableShipItemOptimizations.Value && PluginConfig.EnableItemLOD.Value) { ItemLODOptimizer.UntrackItem(__instance); } } [HarmonyPatch(typeof(GrabbableObject), "DiscardItem")] [HarmonyPostfix] public static void DiscardItem_Postfix(GrabbableObject __instance) { if (PluginConfig.EnableShipItemOptimizations.Value && PluginConfig.EnableItemLOD.Value && __instance.isInShipRoom) { ItemLODOptimizer.TrackItem(__instance); } } [HarmonyPatch(typeof(StartOfRound), "ResetShip")] [HarmonyPostfix] public static void ResetShip_Postfix() { ItemLODOptimizer.Clear(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] public static void Disconnect_Postfix() { ItemLODOptimizer.Clear(); } } public static class RigidbodyFreezer { private class TrackedItem { public Rigidbody Rigidbody; public Vector3 LastPosition; public float StationaryTime; public bool IsFrozen; } private static readonly Dictionary<int, TrackedItem> _trackedItems = new Dictionary<int, TrackedItem>(); private static float _lastCheckTime; private const float CHECK_INTERVAL = 0.5f; private const float FREEZE_AFTER_SECONDS = 2f; private const float VELOCITY_THRESHOLD = 0.01f; public static void TrackItem(GrabbableObject item) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null) { return; } Rigidbody component = ((Component)item).GetComponent<Rigidbody>(); if (!((Object)(object)component == (Object)null)) { int instanceID = ((Object)item).GetInstanceID(); if (!_trackedItems.ContainsKey(instanceID)) { _trackedItems[instanceID] = new TrackedItem { Rigidbody = component, LastPosition = ((Component)item).transform.position, StationaryTime = 0f, IsFrozen = false }; } } } public static void UntrackItem(GrabbableObject item) { if ((Object)(object)item == (Object)null) { return; } int instanceID = ((Object)item).GetInstanceID(); if (_trackedItems.TryGetValue(instanceID, out var value)) { if (value.IsFrozen && (Object)(object)value.Rigidbody != (Object)null) { value.Rigidbody.isKinematic = false; value.Rigidbody.WakeUp(); } _trackedItems.Remove(instanceID); } } public static void UnfreezeItem(GrabbableObject item) { if (!((Object)(object)item == (Object)null)) { int instanceID = ((Object)item).GetInstanceID(); if (_trackedItems.TryGetValue(instanceID, out var value) && value.IsFrozen && (Object)(object)value.Rigidbody != (Object)null) { value.Rigidbody.isKinematic = false; value.Rigidbody.WakeUp(); value.IsFrozen = false; value.StationaryTime = 0f; } } } public static void Update() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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 (Time.time - _lastCheckTime < 0.5f) { return; } _lastCheckTime = Time.time; List<int> list = null; foreach (KeyValuePair<int, TrackedItem> trackedItem in _trackedItems) { TrackedItem value = trackedItem.Value; if ((Object)(object)value.Rigidbody == (Object)null) { if (list == null) { list = new List<int>(); } list.Add(trackedItem.Key); } else { if (value.IsFrozen) { continue; } Vector3 position = value.Rigidbody.position; if (Vector3.Distance(position, value.LastPosition) < 0.01f) { value.StationaryTime += 0.5f; if (value.StationaryTime >= 2f) { value.Rigidbody.Sleep(); value.Rigidbody.isKinematic = true; value.IsFrozen = true; } } else { value.StationaryTime = 0f; value.LastPosition = position; } } } if (list == null) { return; } foreach (int item in list) { _trackedItems.Remove(item); } } public static void UnfreezeAll() { foreach (TrackedItem value in _trackedItems.Values) { if (value.IsFrozen && (Object)(object)value.Rigidbody != (Object)null) { value.Rigidbody.isKinematic = false; value.Rigidbody.WakeUp(); value.IsFrozen = false; } value.StationaryTime = 0f; } } public static (int total, int frozen) GetStats() { int num = 0; foreach (TrackedItem value in _trackedItems.Values) { if (value.IsFrozen) { num++; } } return (_trackedItems.Count, num); } public static void Clear() { UnfreezeAll(); _trackedItems.Clear(); } } [HarmonyPatch] public static class RigidbodyFreezerPatches { [HarmonyPatch(typeof(GrabbableObject), "OnBroughtToShip")] [HarmonyPostfix] public static void OnBroughtToShip_Postfix(GrabbableObject __instance) { if (PluginConfig.EnableShipItemOptimizations.Value) { RigidbodyFreezer.TrackItem(__instance); } } [HarmonyPatch(typeof(GrabbableObject), "GrabItem")] [HarmonyPrefix] public static void GrabItem_Prefix(GrabbableObject __instance) { if (PluginConfig.EnableShipItemOptimizations.Value) { RigidbodyFreezer.UnfreezeItem(__instance); } } [HarmonyPatch(typeof(GrabbableObject), "DiscardItem")] [HarmonyPostfix] public static void DiscardItem_Postfix(GrabbableObject __instance) { if (PluginConfig.EnableShipItemOptimizations.Value) { if (__instance.isInShipRoom) { RigidbodyFreezer.TrackItem(__instance); } else { RigidbodyFreezer.UntrackItem(__instance); } } } [HarmonyPatch(typeof(GrabbableObject), "ItemInteractLeftRight")] [HarmonyPrefix] public static void ItemInteract_Prefix(GrabbableObject __instance) { if (PluginConfig.EnableShipItemOptimizations.Value) { RigidbodyFreezer.UnfreezeItem(__instance); } } [HarmonyPatch(typeof(StartOfRound), "ResetShip")] [HarmonyPostfix] public static void ResetShip_Postfix() { RigidbodyFreezer.Clear(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] public static void Disconnect_Postfix() { RigidbodyFreezer.Clear(); } } public static class ShipDistanceOptimizer { private static readonly List<GrabbableObject> _shipItems = new List<GrabbableObject>(); private static readonly List<Rigidbody> _frozenRigidbodies = new List<Rigidbody>(); private static readonly List<Renderer> _disabledRenderers = new List<Renderer>(); private static Transform _shipTransform; private static PlayerControllerB _localPlayer; private static float _lastCheckTime; private static bool _isFrozen; private const float CHECK_INTERVAL = 1f; private const float FREEZE_DISTANCE = 50f; private const float UNFREEZE_DISTANCE = 40f; public static bool IsFrozen => _isFrozen; public static int TrackedCount => _shipItems.Count; public static void Update() { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) if (Time.time - _lastCheckTime < 1f) { return; } _lastCheckTime = Time.time; if ((Object)(object)_localPlayer == (Object)null || _localPlayer.isPlayerDead) { _localPlayer = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)_localPlayer == (Object)null) { return; } } if ((Object)(object)_shipTransform == (Object)null) { if ((Object)(object)Object.FindObjectOfType<StartOfRound>() != (Object)null) { HangarShipDoor val = Object.FindObjectOfType<HangarShipDoor>(); if ((Object)(object)val != (Object)null) { _shipTransform = ((Component)val).transform; } } if ((Object)(object)_shipTransform == (Object)null) { return; } } float num = Vector3.Distance(((Component)_localPlayer).transform.position, _shipTransform.position); if (!_isFrozen && num > 50f) { FreezeAllShipItems(); } else if (_isFrozen && num < 40f) { UnfreezeAllShipItems(); } } public static void TrackItem(GrabbableObject item) { if (!((Object)(object)item == (Object)null) && !_shipItems.Contains(item)) { _shipItems.Add(item); if (_isFrozen) { FreezeItem(item); } } } public static void UntrackItem(GrabbableObject item) { if (!((Object)(object)item == (Object)null)) { _shipItems.Remove(item); UnfreezeItem(item); } } private static void FreezeAllShipItems() { if (_isFrozen) { return; } foreach (GrabbableObject shipItem in _shipItems) { if (!((Object)(object)shipItem == (Object)null) && !shipItem.isHeld) { FreezeItem(shipItem); } } _isFrozen = true; Plugin.Log.LogDebug((object)$"Ship items frozen - player distance > {50f}m"); } private static void UnfreezeAllShipItems() { if (!_isFrozen) { return; } foreach (Rigidbody frozenRigidbody in _frozenRigidbodies) { if ((Object)(object)frozenRigidbody != (Object)null) { frozenRigidbody.isKinematic = false; frozenRigidbody.WakeUp(); } } _frozenRigidbodies.Clear(); foreach (Renderer disabledRenderer in _disabledRenderers) { if ((Object)(object)disabledRenderer != (Object)null) { disabledRenderer.enabled = true; } } _disabledRenderers.Clear(); _isFrozen = false; Plugin.Log.LogDebug((object)$"Ship items unfrozen - player distance < {40f}m"); } private static void FreezeItem(GrabbableObject item) { if ((Object)(object)item == (Object)null) { return; } Rigidbody component = ((Component)item).GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null && !component.isKinematic) { component.Sleep(); component.isKinematic = true; _frozenRigidbodies.Add(component); } Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>(); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val != (Object)null && val.enabled) { val.enabled = false; _disabledRenderers.Add(val); } } } private static void UnfreezeItem(GrabbableObject item) { if ((Object)(object)item == (Object)null) { return; } Rigidbody component = ((Component)item).GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null) { component.isKinematic = false; component.WakeUp(); _frozenRigidbodies.Remove(component); } Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>(); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val != (Object)null) { val.enabled = true; _disabledRenderers.Remove(val); } } } public static void Clear() { UnfreezeAllShipItems(); _shipItems.Clear(); _frozenRigidbodies.Clear(); _disabledRenderers.Clear(); _shipTransform = null; _localPlayer = null; _isFrozen = false; } } [HarmonyPatch] public static class ShipDistancePatches { [HarmonyPatch(typeof(GrabbableObject), "OnBroughtToShip")] [HarmonyPostfix] public static void OnBroughtToShip_Postfix(GrabbableObject __instance) { if (PluginConfig.EnableShipItemOptimizations.Value && PluginConfig.EnableShipDistanceOptimization.Value) { ShipDistanceOptimizer.TrackItem(__instance); } } [HarmonyPatch(typeof(GrabbableObject), "GrabItem")] [HarmonyPrefix] public static void GrabItem_Prefix(GrabbableObject __instance) { if (PluginConfig.EnableShipItemOptimizations.Value && PluginConfig.EnableShipDistanceOptimization.Value) { ShipDistanceOptimizer.UntrackItem(__instance); } } [HarmonyPatch(typeof(GrabbableObject), "DiscardItem")] [HarmonyPostfix] public static void DiscardItem_Postfix(GrabbableObject __instance) { if (PluginConfig.EnableShipItemOptimizations.Value && PluginConfig.EnableShipDistanceOptimization.Value && __instance.isInShipRoom) { ShipDistanceOptimizer.TrackItem(__instance); } } [HarmonyPatch(typeof(StartOfRound), "ResetShip")] [HarmonyPostfix] public static void ResetShip_Postfix() { ShipDistanceOptimizer.Clear(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] public static void Disconnect_Postfix() { ShipDistanceOptimizer.Clear(); } } } namespace LethalOptimizer.Patches { [HarmonyPatch] public static class AudioPatches { private static readonly Dictionary<int, float> _lastPlayTimes = new Dictionary<int, float>(); private const float MIN_AUDIO_INTERVAL = 0.05f; [HarmonyPatch(typeof(RoundManager), "PlayAudibleNoise")] [HarmonyPrefix] public static bool PlayAudibleNoise_Prefix(Vector3 noisePosition, float noiseRange, float noiseLoudness) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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 (noiseLoudness < 0.05f) { return false; } PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return true; } bool result = false; float num = noiseRange * noiseRange; for (int i = 0; i < array.Length; i++) { if (array[i].isPlayerControlled && !array[i].isPlayerDead) { Vector3 val = ((Component)array[i]).transform.position - noisePosition; if (((Vector3)(ref val)).sqrMagnitude < num) { result = true; break; } } } return result; } [HarmonyPatch(typeof(WalkieTalkie), "TransmitOneShotAudio")] [HarmonyPrefix] public static bool TransmitAudio_Prefix(AudioSource audioSource, AudioClip clip) { if ((Object)(object)audioSource == (Object)null || (Object)(object)clip == (Object)null) { return false; } int instanceID = ((Object)audioSource).GetInstanceID(); float valueOrDefault = _lastPlayTimes.GetValueOrDefault(instanceID, 0f); if (Time.time - valueOrDefault < 0.05f) { return false; } _lastPlayTimes[instanceID] = Time.time; return true; } public static void ClearCache() { _lastPlayTimes.Clear(); } } [HarmonyPatch(typeof(EnemyAI))] public static class EnemyAIPatches { [HarmonyPatch("SetEnemyOutside")] [HarmonyPrefix] public static bool SetEnemyOutside_Prefix(EnemyAI __instance, bool outside) { __instance.isOutside = outside; GameObject[] nodes = AINodeCache.GetNodes(outside); if (nodes != null && nodes.Length != 0) { __instance.allAINodes = nodes; return false; } return true; } [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(EnemyAI __instance) { if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (__instance.isEnemyDead) { return false; } if (!DistanceOptimizer.ShouldUpdateEnemy(__instance)) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(EnemyAI __instance) { if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (__instance.isEnemyDead) { return false; } return true; } [HarmonyPatch("SetDestinationToPosition")] [HarmonyPrefix] public static void SetDestination_Prefix(EnemyAI __instance, Vector3 position) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.agent != (Object)null && PluginConfig.EnableNavMeshCache.Value && NavMeshCache.TryGetPath(__instance.agent, position, out var path)) { __instance.agent.SetPath(path); } } [HarmonyPatch("KillEnemy")] [HarmonyPostfix] public static void KillEnemy_Postfix(EnemyAI __instance) { DistanceOptimizer.ClearEnemy(((Object)__instance).GetInstanceID()); if ((Object)(object)__instance.agent != (Object)null) { NavMeshCache.InvalidateAgent(__instance.agent); } } } [HarmonyPatch(typeof(GrabbableObject))] public static class GrabbableObjectPatches { private static readonly Collider[] _groundCheckResults = (Collider[])(object)new Collider[10]; private static readonly Dictionary<int, Transform> _parentCache = new Dictionary<int, Transform>(); [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(GrabbableObject __instance) { if (__instance.isHeld && (Object)(object)__instance.playerHeldBy != (Object)null) { return false; } if (__instance.isInShipRoom && !__instance.isHeld && Time.frameCount % 3 != 0) { return false; } return true; } [HarmonyPatch("FallToGround")] [HarmonyPrefix] public static bool FallToGround_Prefix(GrabbableObject __instance, bool randomizePosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (__instance.targetFloorPosition == Vector3.zero) { Physics.OverlapSphereNonAlloc(((Component)__instance).transform.position, 2f, _groundCheckResults, LayerMask.GetMask(new string[2] { "Room", "Default" }), (QueryTriggerInteraction)1); _ = 0; return true; } return true; } [HarmonyPatch("LateUpdate")] [HarmonyPrefix] public static bool LateUpdate_Prefix(GrabbableObject __instance) { if (!((Component)__instance).gameObject.activeInHierarchy) { return false; } if (!__instance.isHeld && Time.frameCount % 2 != 0) { return false; } return true; } } [HarmonyPatch(typeof(HUDManager))] public static class HUDManagerPatches { private static float _tipUpdateTimer; private static float _clockUpdateTimer; private static string _lastTipText; private const float TIP_UPDATE_INTERVAL = 0.1f; private const float CLOCK_UPDATE_INTERVAL = 1f; [HarmonyPatch("DisplayTip")] [HarmonyPrefix] public static bool DisplayTip_Prefix(string headerText, string bodyText) { string text = headerText + ":" + bodyText; if (text == _lastTipText && _tipUpdateTimer > 0f) { return false; } _lastTipText = text; _tipUpdateTimer = 0.1f; return true; } [HarmonyPatch("Update")] [HarmonyPostfix] public static void Update_Postfix() { if (_tipUpdateTimer > 0f) { _tipUpdateTimer -= Time.deltaTime; } } [HarmonyPatch("SetClock")] [HarmonyPrefix] public static bool SetClock_Prefix(float timeNormalized, float numberOfHours) { _clockUpdateTimer -= Time.deltaTime; if (_clockUpdateTimer > 0f) { return false; } _clockUpdateTimer = 1f; return true; } } [HarmonyPatch] public static class PhysicsPatches { private static readonly RaycastHit[] _raycastHits = (RaycastHit[])(object)new RaycastHit[20]; private static readonly Collider[] _overlapResults = (Collider[])(object)new Collider[30]; public static int OverlapSphereNonAlloc(Vector3 position, float radius, int layerMask) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Physics.OverlapSphereNonAlloc(position, radius, _overlapResults, layerMask); } public static Collider[] GetOverlapResults() { return _overlapResults; } public static int RaycastNonAlloc(Vector3 origin, Vector3 direction, float maxDistance, int layerMask) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Physics.RaycastNonAlloc(origin, direction, _raycastHits, maxDistance, layerMask); } public static RaycastHit[] GetRaycastResults() { return _raycastHits; } public static bool IsWithinDistance(Vector3 a, Vector3 b, float distance) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) Vector3 val = a - b; return ((Vector3)(ref val)).sqrMagnitude <= distance * distance; } public static void ClearResults() { Array.Clear(_raycastHits, 0, _raycastHits.Length); Array.Clear(_overlapResults, 0, _overlapResults.Length); } } [HarmonyPatch(typeof(PlayerControllerB))] public static class PlayerPatches { private static readonly Dictionary<int, Vector3> _lastPositions = new Dictionary<int, Vector3>(); private static readonly Dictionary<int, float> _syncTimers = new Dictionary<int, float>(); private const float POSITION_SYNC_INTERVAL = 0.05f; private const float POSITION_THRESHOLD = 0.01f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(PlayerControllerB __instance) { if (__instance.isPlayerDead && !__instance.isPlayerControlled) { return false; } return true; } [HarmonyPatch("LateUpdate")] [HarmonyPrefix] public static bool LateUpdate_Prefix(PlayerControllerB __instance) { if (!__instance.isPlayerControlled) { return false; } return true; } public static bool ShouldSyncPosition(PlayerControllerB player) { //IL_008f: 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_007d: 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) int instanceID = ((Object)player).GetInstanceID(); if (!_syncTimers.ContainsKey(instanceID)) { _syncTimers[instanceID] = 0f; } _syncTimers[instanceID] -= Time.deltaTime; if (_syncTimers[instanceID] > 0f) { return false; } _syncTimers[instanceID] = 0.05f; if (!_lastPositions.ContainsKey(instanceID)) { _lastPositions[instanceID] = ((Component)player).transform.position; return true; } if (Vector3.Distance(((Component)player).transform.position, _lastPositions[instanceID]) < 0.01f) { return false; } _lastPositions[instanceID] = ((Component)player).transform.position; return true; } public static void ClearCache() { _lastPositions.Clear(); _syncTimers.Clear(); } } [HarmonyPatch(typeof(RoundManager))] public static class RoundManagerPatches { private static float _spawnCheckTimer; private const float SPAWN_CHECK_INTERVAL = 0.5f; [HarmonyPatch("LoadNewLevel")] [HarmonyPostfix] public static void LoadNewLevel_Postfix() { AINodeCache.CacheNodes(); TurretPatches.ResetTimers(); LandminePatches.ResetCache(); SpikeRoofTrapPatches.ResetCache(); NavMeshCache.Clear(); DistanceOptimizer.Clear(); ParticleOptimizer.OptimizeAllParticles(); Plugin.Log.LogDebug((object)"Level loaded - caches reset, particles optimized"); } [HarmonyPatch("SpawnEnemyGameObject")] [HarmonyPrefix] public static void SpawnEnemy_Prefix(RoundManager __instance) { if (AINodeCache.InsideNodes == null) { AINodeCache.CacheNodes(); } } [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(RoundManager __instance) { _spawnCheckTimer -= Time.deltaTime; if (_spawnCheckTimer > 0f) { return true; } _spawnCheckTimer = 0.5f; return true; } } [HarmonyPatch(typeof(TimeOfDay))] public static class TimeOfDayPatches { private static float _lightingUpdateTimer; private const float LIGHTING_UPDATE_INTERVAL = 0.1f; [HarmonyPatch("SetInsideLightingDimness")] [HarmonyPrefix] public static bool SetInsideLightingDimness_Prefix(TimeOfDay __instance, bool doNotLerp) { if (!PluginConfig.EnableUIOptimizations.Value) { return true; } if (doNotLerp) { return true; } _lightingUpdateTimer += Time.deltaTime; if (_lightingUpdateTimer < 0.1f) { return false; } _lightingUpdateTimer = 0f; return true; } } } namespace LethalOptimizer.Patches.Traps { [HarmonyPatch(typeof(Landmine))] public static class LandminePatches { private static RoundManager _cachedRoundManager; private static bool _roundManagerCached; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(Landmine __instance, ref float ___pressMineDebounceTimer, bool ___localPlayerOnMine) { if (!PluginConfig.EnableTrapOptimizations.Value) { return true; } if (!PluginConfig.OptimizeLandmine.Value) { return true; } if (__instance.hasExploded) { return false; } if (___pressMineDebounceTimer > 0f) { ___pressMineDebounceTimer -= Time.deltaTime; } if (___localPlayerOnMine) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null && val.teleportedLastFrame) { return true; } } return false; } [HarmonyPatch("Start")] [HarmonyPostfix] public static void Start_Postfix(Landmine __instance) { if (PluginConfig.EnableTrapOptimizations.Value && PluginConfig.OptimizeLandmine.Value && !_roundManagerCached) { _cachedRoundManager = RoundManager.Instance; _roundManagerCached = true; } } [HarmonyPatch("OnTriggerEnter")] [HarmonyPrefix] public static bool OnTriggerEnter_Prefix(Landmine __instance, Collider other, bool ___hasExploded, float ___pressMineDebounceTimer) { if (!PluginConfig.EnableTrapOptimizations.Value) { return true; } if (!PluginConfig.OptimizeLandmine.Value) { return true; } if (___hasExploded || ___pressMineDebounceTimer > 0f) { return false; } string tag = ((Component)other).tag; if (tag != "Player" && tag != "PhysicsProp" && !tag.StartsWith("PlayerRagdoll")) { return false; } return true; } [HarmonyPatch("OnTriggerExit")] [HarmonyPrefix] public static bool OnTriggerExit_Prefix(Landmine __instance, bool ___hasExploded, bool ___mineActivated) { if (!PluginConfig.EnableTrapOptimizations.Value) { return true; } if (!PluginConfig.OptimizeLandmine.Value) { return true; } if (___hasExploded || !___mineActivated) { return false; } return true; } public static void ResetCache() { _cachedRoundManager = null; _roundManagerCached = false; } } [HarmonyPatch(typeof(SpikeRoofTrap))] public static class SpikeRoofTrapPatches { private const float UPDATE_INTERVAL = 0.1f; private static float _updateTimer; private static EntranceTeleport[] _cachedEntrances; private static bool _entrancesCached; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(SpikeRoofTrap __instance, bool ___trapActive, bool ___slammingDown, bool ___slamOnIntervals, float ___slamInterval, ref float ___timeSinceMovingUp, EntranceTeleport ___nearEntrance, Transform ___laserEye, ref RaycastHit ___hit) { if (!PluginConfig.EnableTrapOptimizations.Value) { return true; } if (!PluginConfig.OptimizeSpikeTrap.Value) { return true; } if (!___trapActive || ___slammingDown) { return false; } _updateTimer += Time.deltaTime; if (_updateTimer < 0.1f) { return false; } _updateTimer = 0f; if ((Object)(object)___nearEntrance != (Object)null && Time.realtimeSinceStartup - ___nearEntrance.timeAtLastUse < 1.2f) { ___timeSinceMovingUp = Time.realtimeSinceStartup; return false; } if (___slamOnIntervals) { return true; } if (Time.realtimeSinceStartup - ___timeSinceMovingUp < 1.2f) { return false; } return true; } [HarmonyPatch("OnTriggerStay")] [HarmonyPrefix] public static bool OnTriggerStay_Prefix(SpikeRoofTrap __instance, Collider other, bool ___trapActive, bool ___slammingDown, float ___timeSinceMovingUp) { if (!PluginConfig.EnableTrapOptimizations.Value) { return true; } if (!PluginConfig.OptimizeSpikeTrap.Value) { return true; } if (!___trapActive || !___slammingDown) { return false; } if (Time.realtimeSinceStartup - ___timeSinceMovingUp < 0.75f) { return false; } int layer = ((Component)other).gameObject.layer; if (layer != 3 && layer != 19 && layer != 6) { return false; } return true; } [HarmonyPatch("GetNearEntrance")] [HarmonyPrefix] public static bool GetNearEntrance_Prefix(SpikeRoofTrap __instance, ref bool __result, ref EntranceTeleport ___nearEntrance, AudioSource ___spikeTrapAudio) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_0084: Unknown result type (might be due to invalid IL or missing references) if (!PluginConfig.EnableTrapOptimizations.Value) { return true; } if (!PluginConfig.OptimizeSpikeTrap.Value) { return true; } if (!_entrancesCached) { _cachedEntrances = Object.FindObjectsByType<EntranceTeleport>((FindObjectsSortMode)0); _entrancesCached = true; } if (_cachedEntrances == null || _cachedEntrances.Length == 0) { __result = false; return false; } Vector3 position = ((Component)___spikeTrapAudio).transform.position; EntranceTeleport val = null; for (int i = 0; i < _cachedEntrances.Length; i++) { EntranceTeleport val2 = _cachedEntrances[i]; if (!((Object)(object)val2 == (Object)null) && !val2.isEntranceToBuilding) { Vector3 val3 = position - val2.entrancePoint.position; if (((Vector3)(ref val3)).sqrMagnitude < 49f) { val = val2; break; } } } if ((Object)(object)val == (Object)null) { __result = false; return false; } for (int j = 0; j < _cachedEntrances.Length; j++) { EntranceTeleport val4 = _cachedEntrances[j]; if ((Object)(object)val4 != (Object)null && (Object)(object)val4.entrancePoint == (Object)(object)val.exitPoint) { ___nearEntrance = val4; __result = true; return false; } } __result = false; return false; } public static void ResetCache() { _cachedEntrances = null; _entrancesCached = false; _updateTimer = 0f; } } [HarmonyPatch(typeof(Turret))] public static class TurretPatches { private const float DETECTION_INTERVAL = 0.3f; private const float FIRING_INTERVAL = 0.25f; private const float ROTATION_SWITCH_INTERVAL = 8f; private static float _detectionTimer; private static float _losCheckTimer; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(Turret __instance, ref float ___turretInterval, ref float ___switchRotationTimer, bool ___turretActive, TurretMode ___turretMode) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!PluginConfig.EnableTrapOptimizations.Value) { return true; } if (!PluginConfig.OptimizeTurret.Value) { return true; } if (!___turretActive) { return true; } if ((int)___turretMode == 0) { _detectionTimer += Time.deltaTime; if (_detectionTimer < 0.3f) { return true; } _detectionTimer = 0f; } return true; } [HarmonyPatch("CheckForPlayersInLineOfSight")] [HarmonyPrefix] public static bool CheckForPlayersInLOS_Prefix(Turret __instance, ref PlayerControllerB __result, float radius, bool angleRangeCheck) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //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_008a: Unknown result type (might be due to invalid IL or missing references) if (!PluginConfig.EnableTrapOptimizations.Value) { return true; } if (!PluginConfig.OptimizeTurret.Value) { return true; } _losCheckTimer += Time.deltaTime; if (_losCheckTimer < 0.1f) { __result = null; return false; } _losCheckTimer = 0f; PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null || val.isPlayerDead) { __result = null; return false; } Vector3 val2 = ((Component)val).transform.position - __instance.centerPoint.position; if (((Vector3)(ref val2)).sqrMagnitude > 900f) { __result = null; return false; } return true; } [HarmonyPatch("TurnTowardsTargetIfHasLOS")] [HarmonyPrefix] public static bool TurnTowardsTarget_Prefix(Turret __instance, PlayerControllerB ___targetPlayerWithRotation, bool ___targetingDeadPlayer) { if (!PluginConfig.EnableTrapOptimizations.Value) { return true; } if (!PluginConfig.OptimizeTurret.Value) { return true; } if ((Object)(object)___targetPlayerWithRotation == (Object)null) { return false; } if (___targetingDeadPlayer && (Object)(object)___targetPlayerWithRotation.deadBody == (Object)null) { return false; } return true; } [HarmonyPatch("SwitchRotationOnInterval")] [HarmonyPrefix] public static void SwitchRotation_Prefix(ref float ___switchRotationTimer) { if (PluginConfig.EnableTrapOptimizations.Value) { ___switchRotationTimer = 0f; } } public static void ResetTimers() { _detectionTimer = 0f; _losCheckTimer = 0f; } } } namespace LethalOptimizer.Patches.Interior { [HarmonyPatch] public static class InteriorLODPatches { [CompilerGenerated] private sealed class <InitializeDelayed>d__1 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitializeDelayed>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = null; <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = null; <>1__state = 3; return true; case 3: <>1__state = -1; InteriorLOD.Initialize(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")] [HarmonyPostfix] public static void SpawnScrapInLevel_Postfix() { if (PluginConfig.EnableInteriorOptimizations.Value && PluginConfig.EnableInteriorLOD.Value) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(InitializeDelayed()); } } [IteratorStateMachine(typeof(<InitializeDelayed>d__1))] private static IEnumerator InitializeDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitializeDelayed>d__1(0); } [HarmonyPatch(typeof(StartOfRound), "ShipHasLeft")] [HarmonyPostfix] public static void ShipHasLeft_Postfix() { InteriorLOD.Clear(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] public static void EndOfGame_Postfix() { InteriorLOD.Clear(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] public static void Disconnect_Postfix() { InteriorLOD.Clear(); } } [HarmonyPatch] public static class InteriorPhysicsCullingPatches { [CompilerGenerated] private sealed class <InitializeDelayed>d__1 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitializeDelayed>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = null; <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = null; <>1__state = 3; return true; case 3: <>1__state = -1; InteriorPhysicsCulling.Initialize(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")] [HarmonyPostfix] public static void SpawnScrapInLevel_Postfix() { if (PluginConfig.EnableInteriorOptimizations.Value && PluginConfig.EnableInteriorPhysicsCulling.Value) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(InitializeDelayed()); } } [IteratorStateMachine(typeof(<InitializeDelayed>d__1))] private static IEnumerator InitializeDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitializeDelayed>d__1(0); } [HarmonyPatch(typeof(StartOfRound), "ShipHasLeft")] [HarmonyPostfix] public static void ShipHasLeft_Postfix() { InteriorPhysicsCulling.Clear(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] public static void EndOfGame_Postfix() { InteriorPhysicsCulling.Clear(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] public static void Disconnect_Postfix() { InteriorPhysicsCulling.Clear(); } } [HarmonyPatch] public static class LightCullingPatches { [CompilerGenerated] private sealed class <InitializeDelayed>d__1 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitializeDelayed>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = null; <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = null; <>1__state = 3; return true; case 3: <>1__state = -1; LightCulling.Initialize(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")] [HarmonyPostfix] public static void SpawnScrapInLevel_Postfix() { if (PluginConfig.EnableInteriorOptimizations.Value && PluginConfig.EnableLightCulling.Value) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(InitializeDelayed()); } } [IteratorStateMachine(typeof(<InitializeDelayed>d__1))] private static IEnumerator InitializeDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitializeDelayed>d__1(0); } [HarmonyPatch(typeof(StartOfRound), "ShipHasLeft")] [HarmonyPostfix] public static void ShipHasLeft_Postfix() { LightCulling.Clear(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] public static void EndOfGame_Postfix() { LightCulling.Clear(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] public static void Disconnect_Postfix() { LightCulling.Clear(); } } [HarmonyPatch] public static class PortalCullingPatches { [CompilerGenerated] private sealed class <InitializeDelayed>d__1 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitializeDelayed>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = null; <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = null; <>1__state = 3; return true; case 3: <>1__state = -1; PortalCulling.Initialize(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")] [HarmonyPostfix] public static void SpawnScrapInLevel_Postfix() { if (PluginConfig.EnableInteriorOptimizations.Value && PluginConfig.EnablePortalCulling.Value) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(InitializeDelayed()); } } [IteratorStateMachine(typeof(<InitializeDelayed>d__1))] private static IEnumerator InitializeDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitializeDelayed>d__1(0); } [HarmonyPatch(typeof(StartOfRound), "ShipHasLeft")] [HarmonyPostfix] public static void ShipHasLeft_Postfix() { PortalCulling.Clear(); } [HarmonyPatch(typeof(StartOfRound), "ResetShip")] [HarmonyPostfix] public static void ResetShip_Postfix() { PortalCulling.Clear(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] public static void Disconnect_Postfix() { PortalCulling.Clear(); } } [HarmonyPatch] public static class RoomCullingPatches { [CompilerGenerated] private sealed class <InitializeDelayed>d__1 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitializeDelayed>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = null; <>1__state = 2; return true; case 2: <>1__state = -1; RoomCulling.Initialize(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")] [HarmonyPostfix] public static void SpawnScrapInLevel_Postfix() { if (PluginConfig.EnableInteriorOptimizations.Value && PluginConfig.EnableRoomCulling.Value) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(InitializeDelayed()); } } [IteratorStateMachine(typeof(<InitializeDelayed>d__1))] private static IEnumerator InitializeDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitializeDelayed>d__1(0); } [HarmonyPatch(typeof(StartOfRound), "ShipHasLeft")] [HarmonyPostfix] public static void ShipHasLeft_Postfix() { RoomCulling.Clear(); } [HarmonyPatch(typeof(StartOfRound), "ResetShip")] [HarmonyPostfix] public static void ResetShip_Postfix() { RoomCulling.Clear(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] public static void Disconnect_Postfix() { RoomCulling.Clear(); } } } namespace LethalOptimizer.Patches.AI { [HarmonyPatch(typeof(BaboonBirdAI))] public static class BaboonPatches { private static readonly Dictionary<int, float> _lastThreatCheck = new Dictionary<int, float>(); private static readonly Dictionary<int, float> _lastLosCheck = new Dictionary<int, float>(); private const float THREAT_CHECK_INTERVAL = 0.3f; private const float LOS_CHECK_INTERVAL = 0.5f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(BaboonBirdAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeBaboon.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(BaboonBirdAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeBaboon.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastThreatCheck.TryGetValue(instanceID, out var value) && time - value < 0.3f) { return false; } _lastThreatCheck[instanceID] = time; } return true; } [HarmonyPatch("DoLOSCheck")] [HarmonyPrefix] public static bool DoLOSCheck_Prefix(BaboonBirdAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeBaboon.Value) { return true; } int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastLosCheck.TryGetValue(instanceID, out var value) && time - value < 0.5f) { return false; } _lastLosCheck[instanceID] = time; return true; } public static void ClearCache() { _lastThreatCheck.Clear(); _lastLosCheck.Clear(); } } [HarmonyPatch(typeof(BlobAI))] public static class BlobPatches { private static readonly Dictionary<int, float> _lastUpdateTime = new Dictionary<int, float>(); private const float UPDATE_INTERVAL = 0.2f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(BlobAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeBlob.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (Time.frameCount % 2 != 0) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(BlobAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeBlob.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastUpdateTime.TryGetValue(instanceID, out var value) && time - value < 0.2f) { return false; } _lastUpdateTime[instanceID] = time; return true; } public static void ClearCache() { _lastUpdateTime.Clear(); } } [HarmonyPatch(typeof(ButlerEnemyAI))] public static class ButlerPatches { private static readonly Dictionary<int, float> _lastUpdateTime = new Dictionary<int, float>(); private const float UPDATE_INTERVAL = 0.15f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(ButlerEnemyAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeButler.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(ButlerEnemyAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeButler.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastUpdateTime.TryGetValue(instanceID, out var value) && time - value < 0.15f) { return false; } _lastUpdateTime[instanceID] = time; } return true; } public static void ClearCache() { _lastUpdateTime.Clear(); } } [HarmonyPatch(typeof(CaveDwellerAI))] public static class CaveDwellerPatches { private static readonly Dictionary<int, float> _lastUpdateTime = new Dictionary<int, float>(); private const float UPDATE_INTERVAL = 0.1f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(CaveDwellerAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeCaveDweller.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastUpdateTime.TryGetValue(instanceID, out var value) && time - value < 0.1f) { return false; } _lastUpdateTime[instanceID] = time; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(CaveDwellerAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeCaveDweller.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } return true; } public static void ClearCache() { _lastUpdateTime.Clear(); } } [HarmonyPatch(typeof(CrawlerAI))] public static class CrawlerPatches { private static readonly Dictionary<int, float> _lastUpdateTime = new Dictionary<int, float>(); private const float UPDATE_INTERVAL = 0.2f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(CrawlerAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeCrawler.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(CrawlerAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeCrawler.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastUpdateTime.TryGetValue(instanceID, out var value) && time - value < 0.2f) { return false; } _lastUpdateTime[instanceID] = time; } return true; } [HarmonyPatch("MakeScreechNoiseServerRpc")] [HarmonyPrefix] public static bool MakeScreechServerRpc_Prefix(CrawlerAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeCrawler.Value) { return true; } if ((Object)(object)((EnemyAI)__instance).targetPlayer == (Object)null) { return false; } return true; } public static void ClearCache() { _lastUpdateTime.Clear(); } } [HarmonyPatch(typeof(FlowermanAI))] public static class FlowermanPatches { private static readonly Dictionary<int, float> _lastUpdateTime = new Dictionary<int, float>(); private const float UPDATE_INTERVAL = 0.2f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(FlowermanAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeFlowerman.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(FlowermanAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeFlowerman.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastUpdateTime.TryGetValue(instanceID, out var value) && time - value < 0.2f) { return false; } _lastUpdateTime[instanceID] = time; } return true; } [HarmonyPatch("LookAtPlayerOfInterest")] [HarmonyPrefix] public static bool LookAtPlayer_Prefix(FlowermanAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeFlowerman.Value) { return true; } if ((Object)(object)((EnemyAI)__instance).targetPlayer == (Object)null) { return false; } if (Time.frameCount % 2 != 0) { return false; } return true; } public static void ClearCache() { _lastUpdateTime.Clear(); } } [HarmonyPatch(typeof(FlowerSnakeEnemy))] public static class FlowerSnakePatches { private static readonly Dictionary<int, float> _lastUpdateTime = new Dictionary<int, float>(); private const float UPDATE_INTERVAL = 0.1f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(FlowerSnakeEnemy __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeFlowerSnake.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (!Object.op_Implicit((Object)(object)__instance.clingingToPlayer)) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastUpdateTime.TryGetValue(instanceID, out var value) && time - value < 0.1f) { return false; } _lastUpdateTime[instanceID] = time; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(FlowerSnakeEnemy __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeFlowerSnake.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } return true; } public static void ClearCache() { _lastUpdateTime.Clear(); } } [HarmonyPatch(typeof(ForestGiantAI))] public static class ForestGiantPatches { private static readonly Dictionary<int, float> _lastSearchTime = new Dictionary<int, float>(); private static readonly Dictionary<int, float> _lastLosTime = new Dictionary<int, float>(); private const float SEARCH_INTERVAL = 0.4f; private const float LOS_INTERVAL = 0.15f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(ForestGiantAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeForestGiant.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(ForestGiantAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeForestGiant.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastSearchTime.TryGetValue(instanceID, out var value) && time - value < 0.4f) { return false; } _lastSearchTime[instanceID] = time; } return true; } [HarmonyPatch("LookForPlayers")] [HarmonyPrefix] public static bool LookForPlayers_Prefix(ForestGiantAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeForestGiant.Value) { return true; } int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastLosTime.TryGetValue(instanceID, out var value) && time - value < 0.15f) { return false; } _lastLosTime[instanceID] = time; return true; } public static void ClearCache() { _lastSearchTime.Clear(); _lastLosTime.Clear(); } } [HarmonyPatch(typeof(DressGirlAI))] public static class GhostGirlPatches { private static readonly Dictionary<int, float> _lastHauntCheck = new Dictionary<int, float>(); private const float HAUNT_CHECK_INTERVAL = 0.5f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(DressGirlAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeGhostGirl.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if ((Object)(object)__instance.hauntingPlayer == (Object)null && Time.frameCount % 3 != 0) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(DressGirlAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeGhostGirl.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if ((Object)(object)__instance.hauntingPlayer == (Object)null) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastHauntCheck.TryGetValue(instanceID, out var value) && time - value < 0.5f) { return false; } _lastHauntCheck[instanceID] = time; } return true; } public static void ClearCache() { _lastHauntCheck.Clear(); } } [HarmonyPatch(typeof(HoarderBugAI))] public static class HoarderBugPatches { private static readonly Dictionary<int, float> _lastSearchTime = new Dictionary<int, float>(); private static float _lastRefreshTime; private const float SEARCH_INTERVAL = 0.3f; private const float REFRESH_INTERVAL = 0.5f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(HoarderBugAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeHoarderBug.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (__instance.heldItem != null && ((EnemyAI)__instance).currentBehaviourStateIndex == 0 && Time.frameCount % 2 != 0) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(HoarderBugAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeHoarderBug.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (__instance.heldItem == null && ((EnemyAI)__instance).currentBehaviourStateIndex == 0) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastSearchTime.TryGetValue(instanceID, out var value) && time - value < 0.3f) { return false; } _lastSearchTime[instanceID] = time; } return true; } [HarmonyPatch("RefreshGrabbableObjectsInMapList")] [HarmonyPrefix] public static bool RefreshObjects_Prefix(HoarderBugAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeHoarderBug.Value) { return true; } float time = Time.time; if (time - _lastRefreshTime < 0.5f) { return false; } _lastRefreshTime = time; return true; } public static void ClearCache() { _lastSearchTime.Clear(); } } [HarmonyPatch(typeof(JesterAI))] public static class JesterPatches { private static readonly Dictionary<int, float> _lastUpdateTime = new Dictionary<int, float>(); private const float UPDATE_INTERVAL = 0.25f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(JesterAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeJester.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0 && Time.frameCount % 4 != 0) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(JesterAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeJester.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 1) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastUpdateTime.TryGetValue(instanceID, out var value) && time - value < 0.25f) { return false; } _lastUpdateTime[instanceID] = time; } return true; } public static void ClearCache() { _lastUpdateTime.Clear(); } } [HarmonyPatch(typeof(MaskedPlayerEnemy))] public static class MaskedPatches { private static readonly Dictionary<int, float> _lastUpdateTime = new Dictionary<int, float>(); private const float UPDATE_INTERVAL = 0.3f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(MaskedPlayerEnemy __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeMasked.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(MaskedPlayerEnemy __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeMasked.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastUpdateTime.TryGetValue(instanceID, out var value) && time - value < 0.3f) { return false; } _lastUpdateTime[instanceID] = time; } return true; } [HarmonyPatch("LookAtPlayerServerRpc")] [HarmonyPrefix] public static bool LookAtPlayer_Prefix(MaskedPlayerEnemy __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.OptimizeMasked.Value) { return true; } if (!NetworkThrottle.CanSendForObject("animation", ((Object)__instance).GetInstanceID())) { return false; } return true; } public static void ClearCache() { _lastUpdateTime.Clear(); } } [HarmonyPatch(typeof(MouthDogAI))] public static class MouthDogPatches { private static readonly Dictionary<int, float> _lastNoiseCheck = new Dictionary<int, float>(); private const float NOISE_CHECK_INTERVAL = 0.1f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(MouthDogAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeMouthDog.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(MouthDogAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeMouthDog.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0 && Time.frameCount % 2 != 0) { return false; } return true; } [HarmonyPatch("DetectNoise")] [HarmonyPrefix] public static bool DetectNoise_Prefix(MouthDogAI __instance, Vector3 noisePosition, float noiseLoudness) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeMouthDog.Value) { return true; } if (noiseLoudness < 0.1f) { return false; } int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastNoiseCheck.TryGetValue(instanceID, out var value) && time - value < 0.1f) { return false; } _lastNoiseCheck[instanceID] = time; return true; } public static void ClearCache() { _lastNoiseCheck.Clear(); } } [HarmonyPatch(typeof(NutcrackerEnemyAI))] public static class NutcrackerPatches { private static readonly Dictionary<int, float> _lastPatrolTime = new Dictionary<int, float>(); private static readonly Dictionary<int, float> _lastAimTime = new Dictionary<int, float>(); private const float PATROL_INTERVAL = 0.3f; private const float AIM_INTERVAL = 0.15f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(NutcrackerEnemyAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeNutcracker.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(NutcrackerEnemyAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeNutcracker.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastPatrolTime.TryGetValue(instanceID, out var value) && time - value < 0.3f) { return false; } _lastPatrolTime[instanceID] = time; } return true; } [HarmonyPatch("AimGunServerRpc")] [HarmonyPrefix] public static bool AimGunServerRpc_Prefix(NutcrackerEnemyAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeNutcracker.Value) { return true; } int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastAimTime.TryGetValue(instanceID, out var value) && time - value < 0.15f) { return false; } _lastAimTime[instanceID] = time; return true; } [HarmonyPatch("CheckLineOfSightForLocalPlayer")] [HarmonyPrefix] public static bool CheckLOS_Prefix(NutcrackerEnemyAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.OptimizeNutcracker.Value) { return true; } if ((Object)(object)((EnemyAI)__instance).targetPlayer == (Object)null) { return false; } return true; } public static void ClearCache() { _lastPatrolTime.Clear(); _lastAimTime.Clear(); } } [HarmonyPatch(typeof(RadMechAI))] public static class RadMechPatches { private static readonly Dictionary<int, float> _lastThreatCheck = new Dictionary<int, float>(); private static readonly Dictionary<int, float> _lastLateUpdate = new Dictionary<int, float>(); private const float THREAT_CHECK_INTERVAL = 0.2f; private const float LATE_UPDATE_INTERVAL = 0.05f; [HarmonyPatch("LateUpdate")] [HarmonyPrefix] public static bool LateUpdate_Prefix(RadMechAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeRadMech.Value) { return true; } int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastLateUpdate.TryGetValue(instanceID, out var value) && time - value < 0.05f) { return false; } _lastLateUpdate[instanceID] = time; return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(RadMechAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeRadMech.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (!__instance.isAlerted) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastThreatCheck.TryGetValue(instanceID, out var value) && time - value < 0.2f) { return false; } _lastThreatCheck[instanceID] = time; } return true; } [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(RadMechAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeRadMech.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } return true; } public static void ClearCache() { _lastThreatCheck.Clear(); _lastLateUpdate.Clear(); } } [HarmonyPatch(typeof(SandSpiderAI))] public static class SandSpiderPatches { private static readonly Dictionary<int, float> _lastPatrolTime = new Dictionary<int, float>(); private const float PATROL_INTERVAL = 0.25f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(SandSpiderAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeSandSpider.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0 && Time.frameCount % 3 != 0) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(SandSpiderAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeSandSpider.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastPatrolTime.TryGetValue(instanceID, out var value) && time - value < 0.25f) { return false; } _lastPatrolTime[instanceID] = time; } return true; } public static void ClearCache() { _lastPatrolTime.Clear(); } } [HarmonyPatch(typeof(PufferAI))] public static class SporeLizardPatches { private static readonly Dictionary<int, float> _lastUpdateTime = new Dictionary<int, float>(); private const float UPDATE_INTERVAL = 0.2f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(PufferAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeSporeLizard.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0 && Time.frameCount % 3 != 0) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(PufferAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeSporeLizard.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } if (((EnemyAI)__instance).currentBehaviourStateIndex == 0) { int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastUpdateTime.TryGetValue(instanceID, out var value) && time - value < 0.2f) { return false; } _lastUpdateTime[instanceID] = time; } return true; } public static void ClearCache() { _lastUpdateTime.Clear(); } } [HarmonyPatch(typeof(SpringManAI))] public static class SpringManPatches { private static readonly Dictionary<int, float> _lastLosCheck = new Dictionary<int, float>(); private const float LOS_CHECK_INTERVAL = 0.1f; [HarmonyPatch("Update")] [HarmonyPrefix] public static bool Update_Prefix(SpringManAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeSpringMan.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } return true; } [HarmonyPatch("DoAIInterval")] [HarmonyPrefix] public static bool DoAIInterval_Prefix(SpringManAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.EnableAIOptimizations.Value) { return true; } if (!PluginConfig.OptimizeSpringMan.Value) { return true; } if (((EnemyAI)__instance).isEnemyDead) { return false; } int instanceID = ((Object)__instance).GetInstanceID(); float time = Time.time; if (_lastLosCheck.TryGetValue(instanceID, out var value) && time - value < 0.1f) { return true; } _lastLosCheck[instanceID] = time; return true; } [HarmonyPatch("SetAnimationStopServerRpc")] [HarmonyPrefix] public static bool SetAnimationStop_Prefix(SpringManAI __instance) { if ((Object)(object)__instance == (Object)null) { return false; } if (!PluginConfig.OptimizeSpringMan.Value) { return true; } if (!NetworkThrottle.CanSendForObject("animation", ((Object)__instance).GetInstanceID())) { return false; } return true; } public static void ClearCache() { _lastLosCheck.Clear(); } } } namespace LethalOptimizer.Core { public static class AINodeCache { public static GameObject[] InsideNodes { get; private set; } public static GameObject[] OutsideNodes { get; private set; } public static void Initialize() { InsideNodes = null; OutsideNodes = null; } public static void CacheNodes() { InsideNodes = GameObject.FindGameObjectsWithTag("AINode"); OutsideNodes = GameObject.FindGameObjectsWithTag("OutsideAINode"); ManualLogSource log = Plugin.Log; GameObject[] insideNodes = InsideNodes; object arg = ((insideNodes != null) ? insideNodes.Length : 0); GameObject[] outsideNodes = OutsideNodes; log.LogInfo((object)$"Cached {arg} inside, {((outsideNodes != null) ? outsideNodes.Length : 0)} outside AI nodes"); } public static GameObject[] GetNodes(bool outside) { if (!outside) { return InsideNodes; } return OutsideNodes; } } public static class ComponentCache { public struct CachedComponents { public NavMeshAgent Agent; public Animator Animator; public AudioSource AudioSource; public Rigidbody Rigidbody; public Collider Collider; } private static readonly Dictionary<int, CachedComponents> _cache = new Dictionary<int, CachedComponents>(); public static T Get<T>(GameObject obj) where T : Component { if ((Object)(object)obj == (Object)null) { return default(T); } int instanceID = ((Object)obj).GetInstanceID(); if (!_cache.TryGetValue(instanceID, out var value)) { value = default(CachedComponents); _cache[instanceID] = value; } if (typeof(T) == typeof(NavMeshAgent)) { if ((Object)(object)value.Agent == (Object)null) { value.Agent = obj.GetComponent<NavMeshAgent>(); _cache[instanceID] = value; } NavMeshAgent agent = value.Agent; return (T)(object)((agent is T) ? agent : null); } if (typeof(T) == typeof(Animator)) { if ((Object)(object)value.Animator == (Object)null) { value.Animator = obj.GetComponent<Animator>(); _cache[instanceID] = value; } Animator animator = value.Animator; return (T)(object)((animator is T) ? animator : null); } if (typeof(T) == typeof(AudioSource)) { if ((Object)(object)value.AudioSource == (Object)null) { value.AudioSource = obj.GetComponent<AudioSource>(); _cache[instanceID] = value; } AudioSource audioSource = value.AudioSource; return (T)(object)((audioSource is T) ? audioSource : null); } if (typeof(T) == typeof(Rigidbody)) { if ((Object)(object)value.Rigidbody == (Object)null) { value.Rigidbody = obj.GetComponent<Rigidbody>(); _cache[instanceID] = value; } Rigidbody rigidbody = value.Rigidbody; return (T)(object)((rigidbody is T) ? rigidbody : null); } if (typeof(T) == typeof(Collider)) { if ((Object)(object)value.Collider == (Object)null) { value.Collider = obj.GetComponent<Collider>(); _cache[instanceID] = value; } Collider collider = value.Collider; return (T)(object)((collider is T) ? collider : null); } return obj.GetComponent<T>(); } public static void Remove(GameObject obj) { if ((Object)(object)obj != (Object)null) { _cache.Remove(((Object)obj).GetInstanceID()); } } public static void Clear() { _cache.Clear(); } } public static class DistanceOptimizer { private static readonly Dictionary<int, float> _lastUpdateTime = new Dictionary<int, float>(); private static Vector3[] _playerPositions = (Vector3[])(object)new Vector3[4]; private static int _playerCount; private static float _lastPlayerUpdateTime; private const float PLAYER_UPDATE_INTERVAL = 0.5f; private const float CLOSE_DISTANCE = 20f; private const float MEDIUM_DISTANCE = 40f; private const float FAR_DISTANCE = 60f; private const float CLOSE_INTERVAL = 0f; private const float MEDIUM_INTERVAL = 0.1f; private const float FAR_INTERVAL = 0.25f; private const float VERY_FAR_INTERVAL = 0.5f; public static bool ShouldUpdateEnemy(EnemyAI enemy) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (!PluginConfig.EnableDistanceOptimization.Value) { return true; } if ((Object)(object)enemy == (Object)null || enemy.isEnemyDead) { return false; } UpdatePlayerPositions(); if (_playerCount == 0) { return true; } float updateInterval = GetUpdateInterval(GetClosestPlayerDistance(((Component)enemy).transform.position)); int instanceID = ((Object)enemy).GetInstanceID(); float time = Time.time; if (!_lastUpdateTime.TryGetValue(instanceID, out var value)) { _lastUpdateTime[instanceID] = time; return true; } if (time - value >= updateInterval) { _lastUpdateTime[instanceID] = time; return true; } return false; } public static float GetUpdateMultiplier(EnemyAI enemy) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (!PluginConfig.EnableDistanceOptimization.Value) { return 1f; } if ((Object)(object)enemy == (Object)null) { return 1f; } UpdatePlayerPositions(); if (_playerCount == 0) { return 1f; } float closestPlayerDistance = GetClosestPlayerDistance(((Component)enemy).transform.position); if (closestPlayerDistance < 20f) { return 1f; } if (closestPlayerDistance < 40f) { return 0.5f; } if (closestPlayerDistance < 60f) { return 0.25f; } return 0.1f; } private static void UpdatePlayerPositions() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invali