Decompiled source of No Ghost Scares v1.0.1

No Ghost Scares.dll

Decompiled 2 weeks ago
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("No Ghost Scares")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("No Ghost Scares")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("7d9b1509-8e9d-4dcd-9c8f-d9bd2c037790")]
[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 NoGhostScares;

[BepInPlugin("kumo.sulfur.no_ghost_scares", "No Ghost Scares", "1.0.0")]
public sealed class Plugin : BaseUnityPlugin
{
	private sealed class GhostRecord
	{
		public string TimeText;

		public string Action;

		public string Category;

		public string ObjectName;

		public string Path;

		public bool ActiveSelf;

		public bool ActiveInHierarchy;
	}

	[CompilerGenerated]
	private sealed class <ScanLoop>d__18 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Plugin <>4__this;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <ScanLoop>d__18(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				break;
			case 1:
				<>1__state = -1;
				break;
			}
			<>4__this.ScanLoadedScenes();
			<>2__current = (object)new WaitForSeconds(Mathf.Max(0.2f, <>4__this.scanInterval.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<bool> enableBlocking;

	private ConfigEntry<bool> showDebugOverlay;

	private ConfigEntry<bool> logActions;

	private ConfigEntry<bool> detectBroadGhostNames;

	private ConfigEntry<float> scanInterval;

	private ConfigEntry<float> overlayKeepSeconds;

	private ConfigEntry<int> maxOverlayItems;

	private readonly HashSet<int> processedStrongGhostScareIds = new HashSet<int>();

	private readonly HashSet<int> reportedBroadGhostIds = new HashSet<int>();

	private readonly List<GhostRecord> recentRecords = new List<GhostRecord>();

	private float lastRecordTime = -9999f;

	private GUIStyle titleStyle;

	private GUIStyle textStyle;

	private GUIStyle smallTextStyle;

	private GUIStyle boxStyle;

	private static readonly string[] BroadGhostKeywords = new string[8] { "Ghost", "Wraith", "Poltergeist", "Apparition", "Scare", "Haunt", "Specter", "Spectre" };

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		enableBlocking = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableBlocking", true, "If true, disables Ability_Ghost_*_Scare objects. If false, only detects them.");
		showDebugOverlay = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "ShowDebugOverlay", false, "Show detected or blocked ghost scare objects on screen.");
		logActions = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogActions", false, "Write detected or blocked ghost scare objects to BepInEx/LogOutput.log.");
		detectBroadGhostNames = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DetectBroadGhostNames", false, "Debug only. Also show broad ghost-related names like GhostParticles or Unit_Enemy_Ghost. These are never blocked.");
		scanInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Performance", "ScanInterval", 1f, "How often to scan loaded scenes for ghost scare triggers.");
		overlayKeepSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Overlay", "OverlayKeepSeconds", 12f, "How long the on-screen overlay remains visible after the latest detection or block.");
		maxOverlayItems = ((BaseUnityPlugin)this).Config.Bind<int>("Overlay", "MaxOverlayItems", 8, "Maximum number of recent records shown on screen.");
		((MonoBehaviour)this).StartCoroutine(ScanLoop());
		((BaseUnityPlugin)this).Logger.LogInfo((object)"No Ghost Scares 1.0.0 loaded.");
	}

	[IteratorStateMachine(typeof(<ScanLoop>d__18))]
	private IEnumerator ScanLoop()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <ScanLoop>d__18(0)
		{
			<>4__this = this
		};
	}

	private void ScanLoadedScenes()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		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)
				{
					ScanTransform(val.transform);
				}
			}
		}
	}

	private void ScanTransform(Transform transform)
	{
		if ((Object)(object)transform == (Object)null)
		{
			return;
		}
		GameObject gameObject = ((Component)transform).gameObject;
		if ((Object)(object)gameObject == (Object)null)
		{
			return;
		}
		string name = ((Object)gameObject).name;
		if (IsStrongGhostScareObject(name))
		{
			ProcessStrongGhostScare(gameObject);
			return;
		}
		if (detectBroadGhostNames.Value && IsBroadGhostRelatedObject(name))
		{
			ReportBroadGhostRelatedObject(gameObject);
		}
		for (int i = 0; i < transform.childCount; i++)
		{
			ScanTransform(transform.GetChild(i));
		}
	}

	private void ProcessStrongGhostScare(GameObject go)
	{
		if ((Object)(object)go == (Object)null)
		{
			return;
		}
		int instanceID = ((Object)go).GetInstanceID();
		if (processedStrongGhostScareIds.Contains(instanceID))
		{
			return;
		}
		processedStrongGhostScareIds.Add(instanceID);
		if (enableBlocking.Value)
		{
			AddRecord("BLOCKED", "StrongGhostScare", ((Object)go).name, GetPath(go), go.activeSelf, go.activeInHierarchy);
			if (logActions.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Blocked ghost scare object: " + GetPath(go)));
			}
			go.SetActive(false);
			Object.Destroy((Object)(object)go);
		}
		else
		{
			AddRecord("DETECTED_ONLY", "StrongGhostScare", ((Object)go).name, GetPath(go), go.activeSelf, go.activeInHierarchy);
			if (logActions.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Detected ghost scare object, blocking disabled: " + GetPath(go)));
			}
		}
	}

	private void ReportBroadGhostRelatedObject(GameObject go)
	{
		if ((Object)(object)go == (Object)null)
		{
			return;
		}
		int instanceID = ((Object)go).GetInstanceID();
		if (!reportedBroadGhostIds.Contains(instanceID))
		{
			reportedBroadGhostIds.Add(instanceID);
			AddRecord("DEBUG_ONLY", "BroadGhostRelated", ((Object)go).name, GetPath(go), go.activeSelf, go.activeInHierarchy);
			if (logActions.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Debug-only broad ghost related object: " + GetPath(go)));
			}
		}
	}

	private void AddRecord(string action, string category, string objectName, string path, bool activeSelf, bool activeInHierarchy)
	{
		GhostRecord item = new GhostRecord
		{
			TimeText = DateTime.Now.ToString("HH:mm:ss"),
			Action = action,
			Category = category,
			ObjectName = objectName,
			Path = path,
			ActiveSelf = activeSelf,
			ActiveInHierarchy = activeInHierarchy
		};
		recentRecords.Insert(0, item);
		int num = Mathf.Max(12, maxOverlayItems.Value * 3);
		while (recentRecords.Count > num)
		{
			recentRecords.RemoveAt(recentRecords.Count - 1);
		}
		lastRecordTime = Time.realtimeSinceStartup;
	}

	private static bool IsStrongGhostScareObject(string objectName)
	{
		if (string.IsNullOrEmpty(objectName))
		{
			return false;
		}
		return objectName.IndexOf("Ability_Ghost_", StringComparison.OrdinalIgnoreCase) >= 0 && objectName.IndexOf("_Scare", StringComparison.OrdinalIgnoreCase) >= 0;
	}

	private static bool IsBroadGhostRelatedObject(string objectName)
	{
		if (string.IsNullOrEmpty(objectName))
		{
			return false;
		}
		string[] broadGhostKeywords = BroadGhostKeywords;
		foreach (string value in broadGhostKeywords)
		{
			if (objectName.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private void OnGUI()
	{
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		if (!showDebugOverlay.Value || recentRecords.Count == 0)
		{
			return;
		}
		float num = Time.realtimeSinceStartup - lastRecordTime;
		if (!(num > overlayKeepSeconds.Value))
		{
			EnsureGuiStyles();
			int num2 = Mathf.Min(Mathf.Max(1, maxOverlayItems.Value), recentRecords.Count);
			float num3 = 820f;
			float num4 = 22f;
			float num5 = 112f + (float)num2 * 58f;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(20f, 20f, num3, num5);
			GUI.Box(val, GUIContent.none, boxStyle);
			float num6 = ((Rect)(ref val)).x + 14f;
			float num7 = ((Rect)(ref val)).y + 12f;
			string text = (enableBlocking.Value ? "BLOCKING ON" : "BLOCKING OFF / DETECT ONLY");
			GUI.Label(new Rect(num6, num7, num3 - 28f, 26f), "NO GHOST SCARES DEBUG - " + text, titleStyle);
			num7 += 28f;
			string text2 = (enableBlocking.Value ? "Detected Ability_Ghost_*_Scare objects are being blocked." : "Detected Ability_Ghost_*_Scare objects are only shown. They are not blocked.");
			GUI.Label(new Rect(num6, num7, num3 - 28f, 22f), text2, smallTextStyle);
			num7 += 28f;
			GUI.Label(new Rect(num6, num7, num3 - 28f, 22f), "Recent records: " + recentRecords.Count + " | Showing: " + num2, textStyle);
			num7 += 28f;
			for (int i = 0; i < num2; i++)
			{
				GhostRecord ghostRecord = recentRecords[i];
				string text3 = "[" + ghostRecord.TimeText + "] " + ghostRecord.Action + " | " + ghostRecord.Category + " | " + ghostRecord.ObjectName + " | active=" + ghostRecord.ActiveInHierarchy;
				string text4 = ShortenPath(ghostRecord.Path, 120);
				GUI.Label(new Rect(num6, num7, num3 - 28f, num4), text3, textStyle);
				num7 += num4;
				GUI.Label(new Rect(num6, num7, num3 - 28f, 34f), text4, smallTextStyle);
				num7 += 36f;
			}
		}
	}

	private void EnsureGuiStyles()
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Expected O, but got Unknown
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Expected O, but got Unknown
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Expected O, but got Unknown
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Expected O, but got Unknown
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		if (titleStyle == null)
		{
			titleStyle = new GUIStyle(GUI.skin.label);
			titleStyle.fontSize = 18;
			titleStyle.normal.textColor = Color.white;
			textStyle = new GUIStyle(GUI.skin.label);
			textStyle.fontSize = 14;
			textStyle.normal.textColor = Color.white;
			smallTextStyle = new GUIStyle(GUI.skin.label);
			smallTextStyle.fontSize = 12;
			smallTextStyle.wordWrap = true;
			smallTextStyle.normal.textColor = Color.white;
			boxStyle = new GUIStyle(GUI.skin.box);
			boxStyle.normal.textColor = Color.white;
		}
	}

	private static string ShortenPath(string path, int maxLength)
	{
		if (string.IsNullOrEmpty(path))
		{
			return string.Empty;
		}
		if (path.Length <= maxLength)
		{
			return path;
		}
		int num = maxLength / 2 - 4;
		int num2 = maxLength - num - 6;
		if (num <= 0 || num2 <= 0)
		{
			return path.Substring(0, maxLength);
		}
		return path.Substring(0, num) + " ... " + path.Substring(path.Length - num2);
	}

	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;
	}
}