Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LethalEscapeThrottle v1.1.0
LethalEscapeThrottle.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.AI; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace Erskine.LethalEscapeThrottle; [BepInPlugin("Erskine.LethalEscapeThrottle", "LethalEscapeThrottle", "1.1.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry<bool> cEnabled; internal static ConfigEntry<float> cCooldown; internal static ConfigEntry<float> cMaxBackoff; internal static ConfigEntry<bool> cDiag; internal static readonly Dictionary<int, float> BlockedUntil = new Dictionary<int, float>(); internal static readonly Dictionary<int, int> Fails = new Dictionary<int, int>(); internal static int DiagBlocked = 0; internal static int DiagSearched = 0; internal static int DiagFailed = 0; private const float DiagInterval = 30f; private float _diagTimer = 0f; private void Awake() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_0167: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; cEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master toggle for the throttle patch."); cCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("General", "CooldownSeconds", 2f, new ConfigDescription("Base seconds to skip the escape-exit search for an enemy that just failed to find any reachable exit. The search (a full scene scan plus a NavMesh path to every entrance) is what causes the lag, so this is the main dial.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 30f), new object[0])); cMaxBackoff = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MaxBackoffSeconds", 15f, new ConfigDescription("Adaptive back-off cap. An enemy that keeps failing waits longer and longer between searches, up to this many seconds. Higher = less lag but slower to notice a newly-opened path.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 120f), new object[0])); cDiag = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DiagnosticLogging", true, "Log a short summary every 30 seconds (only when active) showing how many exit searches were skipped vs actually run. Handy to confirm the throttle is doing something; turn off once you're satisfied."); try { Harmony val = new Harmony("Erskine.LethalEscapeThrottle"); Type type = AccessTools.TypeByName("UpdatedEscape.Plugin"); if (type == null) { Log.LogWarning((object)"Couldn't find UpdatedEscape.Plugin. Is LethalEscapeUpdated installed and enabled? Throttle not applied."); return; } MethodInfo methodInfo = AccessTools.Method(type, "FindClosestReachableEntrance", (Type[])null, (Type[])null); if (methodInfo == null) { Log.LogWarning((object)"Couldn't find FindClosestReachableEntrance (mod version changed?). Throttle not applied."); return; } val.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Patches).GetMethod("Prefix")), new HarmonyMethod(typeof(Patches).GetMethod("Postfix")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)("LethalEscapeThrottle v1.1.0: throttling FindClosestReachableEntrance (cooldown " + cCooldown.Value + "s, cap " + cMaxBackoff.Value + "s).")); } catch (Exception ex) { Log.LogError((object)("Setup failed, throttle not applied: " + ex)); } } private void Update() { if (cDiag == null || !cDiag.Value) { return; } _diagTimer += Time.deltaTime; if (!(_diagTimer < 30f)) { _diagTimer = 0f; if (DiagBlocked > 0 || DiagSearched > 0) { Log.LogInfo((object)("[throttle] last " + 30 + "s: skipped " + DiagBlocked + " exit searches, ran " + DiagSearched + " (" + DiagFailed + " found no exit). Currently backing off " + BlockedUntil.Count + " enemy agent(s).")); } DiagBlocked = 0; DiagSearched = 0; DiagFailed = 0; } } } public static class Patches { public static bool Prefix(NavMeshAgent agent, ref EntranceTeleport __result, out bool __state) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown __state = false; if (Plugin.cEnabled == null || !Plugin.cEnabled.Value) { __state = true; return true; } if ((Object)agent == (Object)null) { __state = true; return true; } int instanceID = ((Object)agent).GetInstanceID(); if (Plugin.BlockedUntil.TryGetValue(instanceID, out var value) && Time.time < value) { __result = null; Plugin.DiagBlocked++; return false; } __state = true; return true; } public static void Postfix(NavMeshAgent agent, EntranceTeleport __result, bool __state) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown if (!__state || (Object)agent == (Object)null) { return; } int instanceID = ((Object)agent).GetInstanceID(); Plugin.DiagSearched++; if ((Object)__result == (Object)null) { Plugin.DiagFailed++; int value; int num = ((!Plugin.Fails.TryGetValue(instanceID, out value)) ? 1 : (value + 1)); Plugin.Fails[instanceID] = num; float num2 = Mathf.Min(Plugin.cCooldown.Value * Mathf.Pow(2f, (float)(num - 1)), Plugin.cMaxBackoff.Value); Plugin.BlockedUntil[instanceID] = Time.time + num2; if (Plugin.BlockedUntil.Count > 512) { Plugin.BlockedUntil.Clear(); Plugin.Fails.Clear(); } } else { Plugin.BlockedUntil.Remove(instanceID); Plugin.Fails.Remove(instanceID); } } }