using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("NoAbomination")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("NoAbomination")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("455c9416-1048-44be-96cf-cd45598d67b4")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace NoForestAmbush; [BepInPlugin("kumo.sulfur.no_forest_ambush", "No Forest Ambush", "1.3.0")] public sealed class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class d__14 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string reason; public Plugin <>4__this; private int 5__1; private float 5__2; private int 5__3; private int 5__4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__14(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>4__this.cleanupBurstRunning = true; if (<>4__this.logActions.Value) { ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)("Starting Forest Ambush cleanup burst: " + reason)); } 5__1 = Mathf.Max(1, <>4__this.cleanupBurstIterations.Value); 5__2 = Mathf.Max(0.05f, <>4__this.cleanupBurstInterval.Value); 5__3 = 0; break; case 1: <>1__state = -1; 5__3++; break; } if (5__3 < 5__1) { 5__4 = <>4__this.NeutralizeForestAmbushObjectsInLoadedScenes(); if (<>4__this.logActions.Value && 5__4 > 0) { ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)("Cleanup pass neutralized Forest Ambush objects: " + 5__4)); } <>2__current = (object)new WaitForSeconds(5__2); <>1__state = 1; return true; } <>4__this.cleanupBurstRunning = false; if (<>4__this.logActions.Value) { ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)("Finished Forest Ambush cleanup burst: " + reason)); } 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(); } } [CompilerGenerated] private sealed class d__11 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Plugin <>4__this; private int 5__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__11(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; 5__1 = <>4__this.ComputeSceneSignature(); if (5__1 != <>4__this.lastSceneSignature) { <>4__this.lastSceneSignature = 5__1; <>4__this.StartCleanupBurst("scene hierarchy changed"); } break; } <>2__current = (object)new WaitForSeconds(Mathf.Max(0.25f, <>4__this.sceneSignatureCheckInterval.Value)); <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static ManualLogSource Log; private ConfigEntry logActions; private ConfigEntry sceneSignatureCheckInterval; private ConfigEntry cleanupBurstIterations; private ConfigEntry cleanupBurstInterval; private int lastSceneSignature; private bool cleanupBurstRunning; private readonly HashSet neutralizedAmbushIds = new HashSet(); private void Awake() { Log = ((BaseUnityPlugin)this).Logger; logActions = ((BaseUnityPlugin)this).Config.Bind("General", "LogActions", false, "Log neutralized Forest Ambush objects."); sceneSignatureCheckInterval = ((BaseUnityPlugin)this).Config.Bind("Performance", "SceneSignatureCheckInterval", 1f, "How often to cheaply check whether the loaded scene hierarchy changed."); cleanupBurstIterations = ((BaseUnityPlugin)this).Config.Bind("Performance", "CleanupBurstIterations", 24, "How many cleanup passes to run after a scene hierarchy change."); cleanupBurstInterval = ((BaseUnityPlugin)this).Config.Bind("Performance", "CleanupBurstInterval", 0.2f, "Delay between cleanup passes during a cleanup burst."); SceneManager.sceneLoaded += OnSceneLoaded; lastSceneSignature = ComputeSceneSignature(); StartCleanupBurst("startup"); ((MonoBehaviour)this).StartCoroutine(SceneSignatureWatchLoop()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"No Forest Ambush 1.3.0 loaded."); } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { neutralizedAmbushIds.Clear(); lastSceneSignature = ComputeSceneSignature(); StartCleanupBurst("scene loaded"); } [IteratorStateMachine(typeof(d__11))] private IEnumerator SceneSignatureWatchLoop() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__11(0) { <>4__this = this }; } private int ComputeSceneSignature() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) int num = 17; num = num * 31 + SceneManager.sceneCount; for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); if (((Scene)(ref sceneAt)).IsValid() && ((Scene)(ref sceneAt)).isLoaded) { num = num * 31 + ((Scene)(ref sceneAt)).name.GetHashCode(); num = num * 31 + ((Scene)(ref sceneAt)).rootCount; } } return num; } private void StartCleanupBurst(string reason) { if (!cleanupBurstRunning) { ((MonoBehaviour)this).StartCoroutine(CleanupBurst(reason)); } } [IteratorStateMachine(typeof(d__14))] private IEnumerator CleanupBurst(string reason) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__14(0) { <>4__this = this, reason = reason }; } private int NeutralizeForestAmbushObjectsInLoadedScenes() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) int num = 0; for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); if (((Scene)(ref sceneAt)).IsValid() && ((Scene)(ref sceneAt)).isLoaded) { GameObject[] rootGameObjects = ((Scene)(ref sceneAt)).GetRootGameObjects(); GameObject[] array = rootGameObjects; foreach (GameObject val in array) { num += ScanTransformForForestAmbush(val.transform); } } } return num; } private int ScanTransformForForestAmbush(Transform transform) { if ((Object)(object)transform == (Object)null) { return 0; } GameObject gameObject = ((Component)transform).gameObject; if ((Object)(object)gameObject == (Object)null) { return 0; } if (IsForestAmbushRootName(((Object)gameObject).name)) { int instanceID = ((Object)gameObject).GetInstanceID(); if (neutralizedAmbushIds.Contains(instanceID)) { return 0; } neutralizedAmbushIds.Add(instanceID); NeutralizeForestAmbushRoot(gameObject); return 1; } int num = 0; for (int num2 = transform.childCount - 1; num2 >= 0; num2--) { num += ScanTransformForForestAmbush(transform.GetChild(num2)); } return num; } private void NeutralizeForestAmbushRoot(GameObject ambushRoot) { if ((Object)(object)ambushRoot == (Object)null) { return; } Transform val = ambushRoot.transform.Find("Contents"); if ((Object)(object)val == (Object)null) { if (logActions.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Forest Ambush has no Contents: " + GetPath(ambushRoot))); } return; } GameObject gameObject = ((Component)val).gameObject; DisableBehaviourComponentByTypeName(gameObject, "Animator"); DisableBehaviourComponentByTypeName(gameObject, "AudioSource"); for (int num = val.childCount - 1; num >= 0; num--) { Transform child = val.GetChild(num); if (!((Object)(object)child == (Object)null)) { GameObject gameObject2 = ((Component)child).gameObject; string name = ((Object)gameObject2).name; if (ShouldDisableAmbushVisualObject(name)) { if (logActions.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Disabled Forest Ambush visual object: " + GetPath(gameObject2))); } gameObject2.SetActive(false); } } } if (logActions.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Neutralized Forest Ambush visuals only: " + GetPath(ambushRoot))); } } private static bool ShouldDisableAmbushVisualObject(string objectName) { if (string.IsNullOrEmpty(objectName)) { return false; } if (objectName.StartsWith("Tree", StringComparison.OrdinalIgnoreCase)) { return true; } if (objectName.IndexOf("Particles", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } return false; } private static bool IsForestAmbushRootName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return false; } return objectName.IndexOf("Event_Forest_Ambush", StringComparison.OrdinalIgnoreCase) >= 0 || objectName.IndexOf("Forest_Ambush", StringComparison.OrdinalIgnoreCase) >= 0; } private static void DisableBehaviourComponentByTypeName(GameObject go, string typeName) { if ((Object)(object)go == (Object)null || string.IsNullOrEmpty(typeName)) { return; } Component[] components = go.GetComponents(); Component[] array = components; foreach (Component val in array) { if ((Object)(object)val == (Object)null) { continue; } Type type = ((object)val).GetType(); if (string.Equals(type.Name, typeName, StringComparison.OrdinalIgnoreCase)) { Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null); if ((Object)(object)val2 != (Object)null) { val2.enabled = false; } } } } private static string GetPath(GameObject go) { if ((Object)(object)go == (Object)null) { return string.Empty; } string text = ((Object)go).name; Transform parent = go.transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } }