Decompiled source of EnemyHighlights v1.0.0

BepInEx/plugins/EnemyHighlights.dll

Decompiled 10 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Coruscnium")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Warframe-style enemy highlight, outline, and target tint with configurable colors and intensity")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0.0")]
[assembly: AssemblyProduct("EnemyHighlights")]
[assembly: AssemblyTitle("EnemyHighlights")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 EnemyHighlights
{
	[BepInPlugin("enemyhighlights.mycopunk", "EnemyHighlights", "1.0.0.0")]
	[BepInProcess("Mycopunk.exe")]
	[MycoMod(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private static class HighlightOverlay
		{
			private static readonly HashSet<EnemyPart> _parts = new HashSet<EnemyPart>();

			private static readonly List<EnemyPart> _iter = new List<EnemyPart>();

			private static Material _overlayMat;

			private static RenderParams _renderParams;

			private static readonly int _LineRotation = Shader.PropertyToID("_LineRotation");

			internal static void Register(EnemyPart part)
			{
				if (part != null)
				{
					_parts.Add(part);
				}
			}

			internal static void Render()
			{
				//IL_0037: 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)
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_0184: Unknown result type (might be due to invalid IL or missing references)
				//IL_0189: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
				if (_highlightStrength <= 0f || _parts.Count == 0 || !EnsureMaterial())
				{
					return;
				}
				Color val = _highlightColor * (1f + 0.6f * _highlightStrength);
				val.a = Mathf.Lerp(0.15f, 1f, _highlightStrength);
				_overlayMat.SetColor(Global._BaseColor, val);
				_iter.Clear();
				_iter.AddRange(_parts);
				for (int i = 0; i < _iter.Count; i++)
				{
					EnemyPart val2 = _iter[i];
					if (val2 == null || !Object.op_Implicit((Object)(object)val2))
					{
						_parts.Remove(val2);
					}
					else
					{
						if (!((Behaviour)val2).isActiveAndEnabled)
						{
							continue;
						}
						EnemyBrain brain = val2.Brain;
						if (brain == null || brain.DigProgress > 0f)
						{
							continue;
						}
						List<TargetMesh> meshes = val2.Meshes;
						if (meshes == null)
						{
							continue;
						}
						for (int j = 0; j < meshes.Count; j++)
						{
							TargetMesh val3 = meshes[j];
							if (val3 == null || val3.mesh == null)
							{
								continue;
							}
							Mesh sharedMesh = val3.mesh.sharedMesh;
							if (sharedMesh != null)
							{
								Matrix4x4 localToWorldMatrix = ((Component)val3.mesh).transform.localToWorldMatrix;
								int subMeshCount = sharedMesh.subMeshCount;
								for (int k = 0; k < subMeshCount; k++)
								{
									Graphics.RenderMesh(ref _renderParams, sharedMesh, k, localToWorldMatrix, (Matrix4x4?)null);
								}
							}
						}
					}
				}
			}

			private static bool EnsureMaterial()
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Expected O, but got Unknown
				//IL_01be: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
				//IL_0109: Expected O, but got Unknown
				if (_overlayMat != null)
				{
					return true;
				}
				Shader val = Shader.Find("Universal Render Pipeline/Unlit");
				if (val != null)
				{
					_overlayMat = new Material(val);
					_overlayMat.SetFloat("_Surface", 1f);
					_overlayMat.SetOverrideTag("RenderType", "Transparent");
					_overlayMat.SetInt("_SrcBlend", 5);
					_overlayMat.SetInt("_DstBlend", 10);
					_overlayMat.SetInt("_ZWrite", 0);
					_overlayMat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
					_overlayMat.renderQueue = 3000;
					Logger.LogInfo((object)"[highlight] overlay using URP/Unlit (depth-tested)");
				}
				else
				{
					Highlighter val2 = default(Highlighter);
					if (!Highlighter.TryGetInstance(ref val2))
					{
						return false;
					}
					Material highlightMaterial = val2.HighlightMaterial;
					if (highlightMaterial == null)
					{
						return false;
					}
					_overlayMat = new Material(highlightMaterial);
					_overlayMat.SetFloat(_LineRotation, 1f);
					if (!_overlayMat.HasProperty("_ZTest"))
					{
						Logger.LogError((object)("[highlight] URP/Unlit stripped from build and Highlighter shader '" + ((Object)highlightMaterial.shader).name + "' has no _ZTest property — overlay would draw through walls, DISABLING highlight"));
						_overlayMat = null;
						return false;
					}
					_overlayMat.SetInt("_ZTest", 4);
					Logger.LogInfo((object)("[highlight] overlay cloned from Highlighter ('" + ((Object)highlightMaterial.shader).name + "'), _ZTest forced to LessEqual"));
				}
				RenderParams renderParams = default(RenderParams);
				((RenderParams)(ref renderParams))..ctor(_overlayMat);
				((RenderParams)(ref renderParams)).layer = 0;
				((RenderParams)(ref renderParams)).renderingLayerMask = 1u;
				_renderParams = renderParams;
				return true;
			}
		}

		private static class EnemyPartPatches
		{
			[HarmonyPatch(typeof(EnemyPart), "Initialize")]
			[HarmonyPostfix]
			private static void Initialize_Postfix(EnemyPart __instance)
			{
				HighlightOverlay.Register(__instance);
			}

			[HarmonyPatch(typeof(EnemyPart), "SetupRenderersOnAttach")]
			[HarmonyPostfix]
			private static void SetupRenderersOnAttach_Postfix(EnemyPart __instance)
			{
				HighlightOverlay.Register(__instance);
			}
		}

		private static class HighlighterPatches
		{
			private static readonly FieldInfo GradientField = AccessTools.Field(typeof(Highlighter), "highlightHealthColor");

			private static readonly FieldInfo OpacityField = AccessTools.Field(typeof(Highlighter), "highlightOpacity");

			private static Gradient _vanillaGradient;

			private static Range<float> _vanillaOpacity;

			private static bool _captured;

			[HarmonyPatch(typeof(Highlighter), "Setup")]
			[HarmonyPostfix]
			private static void Setup_Postfix(Highlighter __instance)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Expected O, but got Unknown
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				_vanillaGradient = (Gradient)GradientField.GetValue(__instance);
				_vanillaOpacity = (Range<float>)OpacityField.GetValue(__instance);
				_captured = true;
				ApplyTargetingOverride();
			}

			internal static void ApplyTargetingOverride()
			{
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Expected O, but got Unknown
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0079: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: 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_008f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0094: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				Highlighter obj = default(Highlighter);
				if (_captured && Highlighter.TryGetInstance(ref obj))
				{
					if (_targetingStrength <= 0f)
					{
						GradientField.SetValue(obj, _vanillaGradient);
						OpacityField.SetValue(obj, _vanillaOpacity);
						return;
					}
					Gradient val = new Gradient();
					val.colorKeys = (GradientColorKey[])(object)new GradientColorKey[2]
					{
						new GradientColorKey(_targetingColor, 0f),
						new GradientColorKey(_targetingColor, 1f)
					};
					val.alphaKeys = (GradientAlphaKey[])(object)new GradientAlphaKey[2]
					{
						new GradientAlphaKey(1f, 0f),
						new GradientAlphaKey(1f, 1f)
					};
					Gradient value = val;
					GradientField.SetValue(obj, value);
					OpacityField.SetValue(obj, new Range<float>(_targetingStrength, _targetingStrength));
				}
			}
		}

		public const string PluginGUID = "enemyhighlights.mycopunk";

		public const string PluginName = "EnemyHighlights";

		public const string PluginVersion = "1.0.0.0";

		internal static ManualLogSource Logger;

		private static ConfigEntry<string> _highlightColorCfg;

		private static ConfigEntry<int> _highlightIntensityCfg;

		private static ConfigEntry<string> _targetingColorCfg;

		private static ConfigEntry<int> _targetingIntensityCfg;

		private static Color _highlightColor = Color.red;

		private static float _highlightStrength;

		private static Color _targetingColor = Color.red;

		private static float _targetingStrength;

		private static FileSystemWatcher _configWatcher;

		private static volatile bool _pendingConfigReload;

		private void Awake()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			_highlightColorCfg = ((BaseUnityPlugin)this).Config.Bind<string>("Highlight", "HighlightColor", "FF2A00", "Hex color (RRGGBB) for the whole-enemy overlay.");
			_highlightIntensityCfg = ((BaseUnityPlugin)this).Config.Bind<int>("Highlight", "HighlightIntensity", 30, new ConfigDescription("0 disables (vanilla). 100 = solid, super-bright color coat.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			_targetingColorCfg = ((BaseUnityPlugin)this).Config.Bind<string>("Targeting", "TargetingColor", "FF2A00", "Hex color (RRGGBB) for the pointed-at part overlay.");
			_targetingIntensityCfg = ((BaseUnityPlugin)this).Config.Bind<int>("Targeting", "TargetingIntensity", 0, new ConfigDescription("0 disables (vanilla health-gradient overlay). 100 = fully opaque overlay.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged;
			((BaseUnityPlugin)this).Config.Save();
			try
			{
				_configWatcher = new FileSystemWatcher(Paths.ConfigPath, "enemyhighlights.mycopunk.cfg")
				{
					NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite),
					EnableRaisingEvents = true
				};
				_configWatcher.Changed += OnConfigFileChanged;
				_configWatcher.Created += OnConfigFileChanged;
				_configWatcher.Renamed += OnConfigFileChanged;
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Could not start config file watcher: " + ex.Message));
			}
			RefreshCachedValues();
			Harmony val = new Harmony("enemyhighlights.mycopunk");
			val.PatchAll(typeof(EnemyPartPatches));
			val.PatchAll(typeof(HighlighterPatches));
			Logger.LogInfo((object)"EnemyHighlights 1.0.0.0 loaded.");
		}

		private static void OnSettingChanged(object sender, SettingChangedEventArgs args)
		{
			RefreshCachedValues();
			HighlighterPatches.ApplyTargetingOverride();
		}

		private static void OnConfigFileChanged(object sender, FileSystemEventArgs e)
		{
			_pendingConfigReload = true;
		}

		private void Update()
		{
			if (_pendingConfigReload)
			{
				_pendingConfigReload = false;
				((BaseUnityPlugin)this).Config.Reload();
			}
		}

		private void LateUpdate()
		{
			HighlightOverlay.Render();
		}

		private void OnDestroy()
		{
			if (_configWatcher != null)
			{
				_configWatcher.EnableRaisingEvents = false;
				_configWatcher.Changed -= OnConfigFileChanged;
				_configWatcher.Created -= OnConfigFileChanged;
				_configWatcher.Renamed -= OnConfigFileChanged;
				_configWatcher.Dispose();
				_configWatcher = null;
			}
		}

		private static void RefreshCachedValues()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//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)
			_highlightColor = ParseHex(_highlightColorCfg.Value, Color.red);
			_highlightStrength = (float)Mathf.Clamp(_highlightIntensityCfg.Value, 0, 100) / 100f;
			_targetingColor = ParseHex(_targetingColorCfg.Value, Color.red);
			_targetingStrength = (float)Mathf.Clamp(_targetingIntensityCfg.Value, 0, 100) / 100f;
		}

		private static Color ParseHex(string hex, Color fallback)
		{
			//IL_000b: 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)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrWhiteSpace(hex))
			{
				return fallback;
			}
			string text = hex.Trim();
			if (!text.StartsWith("#"))
			{
				text = "#" + text;
			}
			Color val = default(Color);
			return ColorUtility.TryParseHtmlString(text, ref val) ? val : fallback;
		}
	}
}