Decompiled source of DestructibleHighlights v1.1.0

plugins/CryptidLabs-DestructibleHighlights/DestructibleHighlights.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using RiskOfOptions;
using RiskOfOptions.Options;
using RoR2;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CryptidLabs")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DestructibleHighlights")]
[assembly: AssemblyTitle("DestructibleHighlights")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 DestructibleHighlights
{
	[BepInPlugin("com.cryptidlabs.destructiblehighlights", "Destructible Highlights", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class HighlightCleanup : MonoBehaviour
		{
			public Renderer TargetRenderer { get; set; }

			private void LateUpdate()
			{
				if (!((Object)(object)TargetRenderer != (Object)null) || !TargetRenderer.enabled || !((Component)TargetRenderer).gameObject.activeInHierarchy)
				{
					Highlight component = ((Component)this).GetComponent<Highlight>();
					if ((Object)(object)component != (Object)null)
					{
						Object.Destroy((Object)(object)component);
					}
					Object.Destroy((Object)(object)this);
				}
			}
		}

		private sealed class DestructibleCategory
		{
			private readonly ConfigEntry<bool> enabled;

			private readonly ConfigEntry<string> filters;

			private readonly string name;

			private string[] cachedFilters;

			public ConfigEntry<bool> Enabled => enabled;

			public ConfigEntry<string> Filters => filters;

			public string Name => name;

			public bool IsSirensCallEgg => string.Equals(name, "Sirens Call Eggs", StringComparison.Ordinal);

			public DestructibleCategory(ConfigFile config, string name, bool defaultEnabled, string defaultFilters, string description)
			{
				this.name = name;
				enabled = config.Bind<bool>("Destructible Categories", name, defaultEnabled, description);
				filters = config.Bind<string>("Destructible Category Filters", name, defaultFilters, "Comma-separated object-name fragments for the " + name + " category.");
				RefreshFilters();
				filters.SettingChanged += delegate
				{
					RefreshFilters();
				};
			}

			public bool Matches(string objectName)
			{
				if (!enabled.Value)
				{
					return false;
				}
				if (IsSirensCallEgg)
				{
					return MatchesSirensCallEgg(objectName);
				}
				for (int i = 0; i < cachedFilters.Length; i++)
				{
					if (objectName.Contains(cachedFilters[i]))
					{
						return true;
					}
				}
				return false;
			}

			private bool MatchesSirensCallEgg(string objectName)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				Scene activeScene = SceneManager.GetActiveScene();
				bool flag = ((Scene)(ref activeScene)).name.ToLowerInvariant().Contains("shipgraveyard") || objectName.Contains("shipgraveyard") || objectName.Contains("siren");
				bool flag2 = objectName.Contains("roboball") || objectName.Contains("superroboball") || objectName.Contains("alloy") || objectName.Contains("worship");
				bool flag3 = false;
				for (int i = 0; i < cachedFilters.Length; i++)
				{
					if (objectName.Contains(cachedFilters[i]))
					{
						flag3 = true;
						break;
					}
				}
				if (flag3)
				{
					return flag || flag2;
				}
				return false;
			}

			private void RefreshFilters()
			{
				cachedFilters = (from filter in filters.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
					select filter.Trim().ToLowerInvariant() into filter
					where filter.Length > 0
					select filter).Distinct().ToArray();
			}
		}

		public const string PluginGuid = "com.cryptidlabs.destructiblehighlights";

		public const string PluginName = "Destructible Highlights";

		public const string PluginVersion = "1.1.0";

		private static ConfigEntry<bool> highlightDestructibles;

		private static ConfigEntry<bool> broadScan;

		private static ConfigEntry<bool> debugLogging;

		private static ConfigEntry<bool> debugUnmatchedCandidates;

		private static ConfigEntry<int> scanPasses;

		private static ConfigEntry<float> scanDuration;

		private static ConfigEntry<float> scanInterval;

		private static ConfigEntry<Color> highlightColor;

		private static ConfigEntry<string> highlightColorHexOverride;

		private static ConfigEntry<float> highlightBrightness;

		private static ConfigEntry<float> highlightStrength;

		private static Sprite modIcon;

		private static DestructibleCategory[] categories = Array.Empty<DestructibleCategory>();

		private void Awake()
		{
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			highlightDestructibles = ((BaseUnityPlugin)this).Config.Bind<bool>("Highlight", "Destructibles", true, "Master toggle for destructible scene object highlights.");
			categories = new DestructibleCategory[8]
			{
				new DestructibleCategory(((BaseUnityPlugin)this).Config, "Eggs", defaultEnabled: true, "egg", "Highlight destructible eggs."),
				new DestructibleCategory(((BaseUnityPlugin)this).Config, "Sirens Call Eggs", defaultEnabled: true, "shipgraveyard,roboball,superroboball,alloy,worship,egg,nest,sulfur", "Highlight Siren's Call Alloy Worship Unit eggs."),
				new DestructibleCategory(((BaseUnityPlugin)this).Config, "Pots and Urns", defaultEnabled: false, "pot,urn,vase", "Highlight pots, urns, and vase-like breakables."),
				new DestructibleCategory(((BaseUnityPlugin)this).Config, "Crystals", defaultEnabled: true, "crystal", "Highlight destructible crystals."),
				new DestructibleCategory(((BaseUnityPlugin)this).Config, "Explosives", defaultEnabled: true, "explosive,barrel,tank", "Highlight explosive destructible props."),
				new DestructibleCategory(((BaseUnityPlugin)this).Config, "Pods and Nests", defaultEnabled: true, "pod,nest", "Highlight destructible pods, nests, and similar objects."),
				new DestructibleCategory(((BaseUnityPlugin)this).Config, "Rocks and Generic Breakables", defaultEnabled: false, "rock,destruct,break", "Highlight generic rock or breakable/destructible props."),
				new DestructibleCategory(((BaseUnityPlugin)this).Config, "Trees and Plants", defaultEnabled: false, "tree,plant,root,shrub,bush,grass", "Highlight destructible trees, plants, roots, shrubs, and similar scenery.")
			};
			broadScan = ((BaseUnityPlugin)this).Config.Bind<bool>("Highlight", "Broad Destructible Scan", false, "Also highlight non-character objects with health even when their name does not match any enabled category. Enable this only if a destructible is missed.");
			debugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Highlight", "Debug Log Highlighted Object Names", false, "Log every object that receives a destructible highlight. Useful for tuning category filters.");
			debugUnmatchedCandidates = ((BaseUnityPlugin)this).Config.Bind<bool>("Highlight", "Debug Log Unmatched Health Object Names", false, "Log non-character health objects that did not match an enabled category. This can be noisy, but helps discover object names.");
			scanPasses = ((BaseUnityPlugin)this).Config.Bind<int>("Highlight", "Stage Start Scan Passes", 6, "Legacy setting. Kept for config compatibility; timed scan settings below are used instead.");
			scanDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Highlight", "Stage Scan Duration", 45f, "How many seconds after stage load to keep scanning for late-spawned destructibles.");
			scanInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Highlight", "Stage Scan Interval", 1f, "How many seconds to wait between destructible scans during the stage scan duration.");
			highlightColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Highlight", "Destructible Color", new Color(0.47058824f, 27f / 85f, 0.6627451f, 1f), "Highlight color for destructibles. RiskOfOptions shows this as a color wheel.");
			highlightColorHexOverride = ((BaseUnityPlugin)this).Config.Bind<string>("Highlight", "Destructible Color Hex Override", "", "Optional exact highlight color. Use #RRGGBB or #RRGGBBAA. Leave blank to use the color wheel.");
			highlightBrightness = ((BaseUnityPlugin)this).Config.Bind<float>("Highlight", "Destructible Brightness", 2f, "Color brightness multiplier for destructible highlights. Lower values are dimmer; higher values are brighter.");
			highlightStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Highlight", "Destructible Strength", 1f, "Highlight strength for destructibles.");
			SceneManager.sceneLoaded += OnSceneLoaded;
			RegisterRiskOfOptions();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Destructible Highlights loaded.");
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			int passesRemaining;
			float stopTime;
			float nextScanTime;
			if (highlightDestructibles.Value)
			{
				passesRemaining = Mathf.Max(1, scanPasses.Value);
				stopTime = Time.unscaledTime + Mathf.Max(1f, scanDuration.Value);
				nextScanTime = 0f;
				RoR2Application.onUpdate += ScanOnUpdate;
			}
			void ScanOnUpdate()
			{
				if (!(Time.unscaledTime < nextScanTime))
				{
					AddHighlights();
					passesRemaining--;
					nextScanTime = Time.unscaledTime + Mathf.Max(0.1f, scanInterval.Value);
					if (passesRemaining <= 0 && Time.unscaledTime >= stopTime)
					{
						RoR2Application.onUpdate -= ScanOnUpdate;
					}
				}
			}
		}

		private static void AddHighlights()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			HealthComponent[] array = Object.FindObjectsOfType<HealthComponent>();
			HealthComponent[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				if (TryHighlightDestructible(array2[i]))
				{
					num++;
				}
			}
			num += AddSirensCallRendererHighlights();
			if (debugLogging.Value)
			{
				object[] obj = new object[4] { "Destructible Highlights", null, null, null };
				Scene activeScene = SceneManager.GetActiveScene();
				obj[1] = ((Scene)(ref activeScene)).name;
				obj[2] = array.Length;
				obj[3] = num;
				Debug.Log((object)string.Format("[{0}] Scan stage=\"{1}\" healthObjects={2} added={3}.", obj));
			}
			if (num > 0)
			{
				Debug.Log((object)string.Format("[{0}] Added {1} destructible highlights.", "Destructible Highlights", num));
			}
		}

		private static int AddSirensCallRendererHighlights()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			DestructibleCategory sirensCallCategory = GetSirensCallCategory();
			if (sirensCallCategory == null || !sirensCallCategory.Enabled.Value)
			{
				return 0;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (!name.Equals("shipgraveyard", StringComparison.OrdinalIgnoreCase))
			{
				return 0;
			}
			int num = 0;
			Renderer[] array = Object.FindObjectsOfType<Renderer>();
			foreach (Renderer val in array)
			{
				if ((Object)(object)val == (Object)null || !IsRendererUsable(val) || !IsSirensCallEggRenderer(val))
				{
					continue;
				}
				GameObject rendererHighlightObject = GetRendererHighlightObject(val);
				if (!((Object)(object)rendererHighlightObject == (Object)null) && !((Object)(object)rendererHighlightObject.GetComponent<Highlight>() != (Object)null))
				{
					Highlight obj = rendererHighlightObject.AddComponent<Highlight>();
					obj.targetRenderer = val;
					obj.strength = Mathf.Max(0f, highlightStrength.Value);
					obj.highlightColor = (HighlightColor)3;
					obj.CustomColor = GetConfiguredColor();
					obj.isOn = true;
					rendererHighlightObject.AddComponent<HighlightCleanup>().TargetRenderer = val;
					num++;
					if (debugLogging.Value)
					{
						Debug.Log((object)("[Destructible Highlights] Highlighted category=\"" + sirensCallCategory.Name + "\" stage=\"" + name + "\" health=\"<renderer scan>\" highlight=\"" + GetObjectPath(rendererHighlightObject.transform) + "\" renderer=\"" + GetObjectPath(((Component)val).transform) + "\"."));
					}
				}
			}
			if (debugLogging.Value)
			{
				Debug.Log((object)string.Format("[{0}] Sirens renderer scan stage=\"{1}\" renderers={2} added={3}.", "Destructible Highlights", name, array.Length, num));
			}
			return num;
		}

		private static bool TryHighlightDestructible(HealthComponent healthComponent)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)healthComponent == (Object)null || (Object)(object)((Component)healthComponent).gameObject == (Object)null)
			{
				return false;
			}
			GameObject gameObject = ((Component)healthComponent).gameObject;
			if (!TryResolveDestructibleCategory(gameObject, out var category, out var _))
			{
				return false;
			}
			GameObject highlightObject = GetHighlightObject(gameObject);
			if ((Object)(object)highlightObject == (Object)null || (Object)(object)highlightObject.GetComponent<Highlight>() != (Object)null)
			{
				return false;
			}
			Renderer val = FindTargetRenderer(highlightObject, category);
			if ((Object)(object)val == (Object)null)
			{
				val = FindTargetRenderer(gameObject, category);
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Highlight obj = highlightObject.AddComponent<Highlight>();
			obj.targetRenderer = val;
			obj.strength = Mathf.Max(0f, highlightStrength.Value);
			obj.highlightColor = (HighlightColor)3;
			obj.CustomColor = GetConfiguredColor();
			obj.isOn = true;
			if (debugLogging.Value)
			{
				string[] obj2 = new string[11]
				{
					"[Destructible Highlights] Highlighted category=\"",
					GetCategoryName(category),
					"\" stage=\"",
					null,
					null,
					null,
					null,
					null,
					null,
					null,
					null
				};
				Scene activeScene = SceneManager.GetActiveScene();
				obj2[3] = ((Scene)(ref activeScene)).name;
				obj2[4] = "\" health=\"";
				obj2[5] = GetObjectPath(gameObject.transform);
				obj2[6] = "\" highlight=\"";
				obj2[7] = GetObjectPath(highlightObject.transform);
				obj2[8] = "\" renderer=\"";
				obj2[9] = GetObjectPath(((Component)val).transform);
				obj2[10] = "\".";
				Debug.Log((object)string.Concat(obj2));
			}
			return true;
		}

		private static Color GetConfiguredColor()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			Color val = ((!TryParseHexColor(highlightColorHexOverride.Value, out var color)) ? highlightColor.Value : color);
			float a = val.a;
			float num = default(float);
			float num2 = default(float);
			float num3 = default(float);
			Color.RGBToHSV(val, ref num, ref num2, ref num3);
			num3 = Mathf.Clamp01(num3 * Mathf.Max(0f, highlightBrightness.Value));
			val = Color.HSVToRGB(num, num2, num3);
			val.a = a;
			return val;
		}

		private static void RegisterRiskOfOptions()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"))
			{
				modIcon = LoadSprite(Path.Combine(GetPluginDirectory(), "icon.png"), "DestructibleHighlightsIcon");
				if ((Object)(object)modIcon != (Object)null)
				{
					ModSettingsManager.SetModIcon(modIcon, "com.cryptidlabs.destructiblehighlights", "Destructible Highlights");
				}
				ModSettingsManager.SetModDescription("Adds configurable highlights for destructible scene objects such as eggs, crystals, explosive props, pods, optional urns, and optional plants.", "com.cryptidlabs.destructiblehighlights", "Destructible Highlights");
				AddRiskOfOptionsOption((BaseOption)new ColorOption(highlightColor));
				AddRiskOfOptionsOption((BaseOption)new StringInputFieldOption(highlightColorHexOverride));
				AddRiskOfOptionsOption((BaseOption)new CheckBoxOption(highlightDestructibles));
				AddRiskOfOptionsOption((BaseOption)new CheckBoxOption(broadScan));
				AddRiskOfOptionsOption((BaseOption)new CheckBoxOption(debugLogging));
				AddRiskOfOptionsOption((BaseOption)new CheckBoxOption(debugUnmatchedCandidates));
				AddRiskOfOptionsOption((BaseOption)new IntSliderOption(scanPasses));
				AddRiskOfOptionsOption((BaseOption)new StepSliderOption(scanDuration));
				AddRiskOfOptionsOption((BaseOption)new StepSliderOption(scanInterval));
				AddRiskOfOptionsOption((BaseOption)new StepSliderOption(highlightBrightness));
				AddRiskOfOptionsOption((BaseOption)new StepSliderOption(highlightStrength));
				for (int i = 0; i < categories.Length; i++)
				{
					AddRiskOfOptionsOption((BaseOption)new CheckBoxOption(categories[i].Enabled));
					AddRiskOfOptionsOption((BaseOption)new StringInputFieldOption(categories[i].Filters));
				}
			}
		}

		private static void AddRiskOfOptionsOption(BaseOption option)
		{
			ModSettingsManager.AddOption(option, "com.cryptidlabs.destructiblehighlights", "Destructible Highlights");
		}

		private static Sprite LoadSprite(string path, string spriteName)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if (!File.Exists(path))
			{
				return null;
			}
			byte[] array = File.ReadAllBytes(path);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, array))
			{
				return null;
			}
			((Object)val).name = spriteName;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), (float)((Texture)val).width);
		}

		private static string GetPluginDirectory()
		{
			return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Paths.PluginPath;
		}

		private static Color ParseHexColor(string value)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (!TryParseHexColor(value, out var color))
			{
				return Color.yellow;
			}
			return color;
		}

		private static bool TryParseHexColor(string value, out Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			color = default(Color);
			if (string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			string text = value.Trim();
			if (!text.StartsWith("#", StringComparison.Ordinal))
			{
				text = "#" + text;
			}
			Color val = default(Color);
			if (ColorUtility.TryParseHtmlString(text, ref val))
			{
				color = val;
				return true;
			}
			return false;
		}

		private static bool TryResolveDestructibleCategory(GameObject entityObject, out DestructibleCategory category, out string searchText)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			category = null;
			searchText = string.Empty;
			if ((Object)(object)entityObject.GetComponent<CharacterBody>() != (Object)null || (Object)(object)entityObject.GetComponent<CharacterMaster>() != (Object)null || (Object)(object)entityObject.GetComponent<PurchaseInteraction>() != (Object)null || (Object)(object)entityObject.GetComponent<ChestBehavior>() != (Object)null || (Object)(object)entityObject.GetComponent<ShopTerminalBehavior>() != (Object)null || (Object)(object)entityObject.GetComponent<GenericPickupController>() != (Object)null)
			{
				return false;
			}
			searchText = BuildSearchText(entityObject);
			category = GetEnabledCategoryMatch(searchText);
			if (category != null)
			{
				return true;
			}
			if (broadScan.Value)
			{
				return true;
			}
			if (debugUnmatchedCandidates.Value)
			{
				string[] obj = new string[7] { "[Destructible Highlights] Unmatched health object stage=\"", null, null, null, null, null, null };
				Scene activeScene = SceneManager.GetActiveScene();
				obj[1] = ((Scene)(ref activeScene)).name;
				obj[2] = "\" path=\"";
				obj[3] = GetObjectPath(entityObject.transform);
				obj[4] = "\" hints=\"";
				obj[5] = GetComponentHints(entityObject);
				obj[6] = "\".";
				Debug.Log((object)string.Concat(obj));
			}
			return false;
		}

		private static string GetObjectPath(Transform transform)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return "<null>";
			}
			string text = ((Object)transform).name;
			Transform parent = transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return text;
		}

		private static string BuildSearchText(GameObject entityObject)
		{
			string text = GetObjectPath(entityObject.transform);
			ModelLocator component = entityObject.GetComponent<ModelLocator>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.modelTransform != (Object)null)
			{
				text = text + " " + GetObjectPath(component.modelTransform);
			}
			Transform val = entityObject.transform;
			while ((Object)(object)val != (Object)null)
			{
				text = text + " " + ((Object)val).name + " " + GetComponentHints(((Component)val).gameObject);
				val = val.parent;
			}
			return text.ToLowerInvariant();
		}

		private static DestructibleCategory GetEnabledCategoryMatch(string searchText)
		{
			for (int i = 0; i < categories.Length; i++)
			{
				if (categories[i].IsSirensCallEgg && categories[i].Matches(searchText))
				{
					return categories[i];
				}
			}
			for (int j = 0; j < categories.Length; j++)
			{
				if (!categories[j].IsSirensCallEgg && categories[j].Matches(searchText))
				{
					return categories[j];
				}
			}
			return null;
		}

		private static DestructibleCategory GetSirensCallCategory()
		{
			for (int i = 0; i < categories.Length; i++)
			{
				if (categories[i].IsSirensCallEgg)
				{
					return categories[i];
				}
			}
			return null;
		}

		private static string GetCategoryName(DestructibleCategory category)
		{
			if (category != null)
			{
				return category.Name;
			}
			return "Broad Scan";
		}

		private static string GetComponentHints(GameObject gameObject)
		{
			try
			{
				return string.Join(",", (from component in gameObject.GetComponents<Component>()
					where (Object)(object)component != (Object)null
					select ((object)component).GetType().Name).Distinct().ToArray());
			}
			catch
			{
				return "<components unavailable>";
			}
		}

		private static GameObject GetHighlightObject(GameObject entityObject)
		{
			ModelLocator component = entityObject.GetComponent<ModelLocator>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.modelTransform != (Object)null)
			{
				return ((Component)component.modelTransform).gameObject;
			}
			return entityObject;
		}

		private static GameObject GetRendererHighlightObject(Renderer renderer)
		{
			Transform val = ((Component)renderer).transform;
			while ((Object)(object)val != (Object)null)
			{
				string text = ((Object)val).name.ToLowerInvariant();
				if (text.Contains("egg") || text.Contains("sulfur") || text.Contains("alloy") || text.Contains("roboball") || text.Contains("worship"))
				{
					return ((Component)val).gameObject;
				}
				val = val.parent;
			}
			return ((Component)renderer).gameObject;
		}

		private static Renderer FindTargetRenderer(GameObject gameObject, DestructibleCategory category)
		{
			Renderer[] componentsInChildren = gameObject.GetComponentsInChildren<Renderer>(true);
			if (category != null && category.IsSirensCallEgg)
			{
				Renderer val = ((IEnumerable<Renderer>)componentsInChildren).FirstOrDefault((Func<Renderer, bool>)((Renderer renderer) => (Object)(object)renderer != (Object)null && IsRendererUsable(renderer) && IsSirensCallEggRenderer(renderer)));
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
				val = ((IEnumerable<Renderer>)componentsInChildren).FirstOrDefault((Func<Renderer, bool>)((Renderer renderer) => (Object)(object)renderer != (Object)null && IsSirensCallEggRenderer(renderer)));
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			foreach (Renderer val2 in componentsInChildren)
			{
				if ((Object)(object)val2 != (Object)null && IsRendererUsable(val2))
				{
					return val2;
				}
			}
			return ((IEnumerable<Renderer>)componentsInChildren).FirstOrDefault((Func<Renderer, bool>)((Renderer renderer) => (Object)(object)renderer != (Object)null));
		}

		private static bool IsRendererUsable(Renderer renderer)
		{
			if (renderer.enabled)
			{
				return ((Component)renderer).gameObject.activeInHierarchy;
			}
			return false;
		}

		private static bool IsSirensCallEggRenderer(Renderer renderer)
		{
			string text = GetObjectPath(((Component)renderer).transform).ToLowerInvariant();
			if (!text.Contains("egg") && !text.Contains("sulfur") && !text.Contains("alloy") && !text.Contains("roboball"))
			{
				return text.Contains("worship");
			}
			return true;
		}
	}
}