Decompiled source of EnemyHighlights v1.1.0

BepInEx/plugins/EnemyHighlights/EnemyHighlights.dll

Decompiled a month 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.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0.0")]
[assembly: AssemblyProduct("EnemyHighlights")]
[assembly: AssemblyTitle("EnemyHighlights")]
[assembly: AssemblyVersion("1.1.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("coruscnium.enemyhighlights", "EnemyHighlights", "1.1.0.0")]
	[BepInProcess("Mycopunk.exe")]
	[MycoMod(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private static class RimPainter
		{
			private static readonly int BaseColorId = Shader.PropertyToID("_BaseColor");

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

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

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

			private static readonly HashSet<EnemyPart> Parts = new HashSet<EnemyPart>();

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

			private static Material RimMat;

			private static RenderParams RimParams;

			internal static void SetSourceMaterial(Material mat)
			{
				//IL_0021: 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)
				RimMat = mat;
				RenderParams rimParams = default(RenderParams);
				((RenderParams)(ref rimParams))..ctor(mat);
				((RenderParams)(ref rimParams)).layer = 0;
				((RenderParams)(ref rimParams)).renderingLayerMask = 1u;
				RimParams = rimParams;
			}

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

			internal static void Render()
			{
				//IL_013b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0140: 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)
				if (!_rimReady || _highlightStrength <= 0f || (Object)(object)RimMat == (Object)null || Parts.Count == 0)
				{
					return;
				}
				ApplyProperties();
				Iter.Clear();
				Iter.AddRange(Parts);
				for (int i = 0; i < Iter.Count; i++)
				{
					EnemyPart val = Iter[i];
					if (val == null || !Object.op_Implicit((Object)(object)val))
					{
						Parts.Remove(val);
					}
					else
					{
						if (!((Behaviour)val).isActiveAndEnabled)
						{
							continue;
						}
						EnemyBrain brain = val.Brain;
						if (brain != null && brain.DigProgress > 0f)
						{
							continue;
						}
						List<TargetMesh> meshes = val.Meshes;
						if (meshes == null)
						{
							continue;
						}
						for (int j = 0; j < meshes.Count; j++)
						{
							TargetMesh val2 = meshes[j];
							if (val2 == null || val2.mesh == null)
							{
								continue;
							}
							Mesh sharedMesh = val2.mesh.sharedMesh;
							if (sharedMesh != null)
							{
								Matrix4x4 localToWorldMatrix = ((Component)val2.mesh).transform.localToWorldMatrix;
								int subMeshCount = sharedMesh.subMeshCount;
								for (int k = 0; k < subMeshCount; k++)
								{
									Graphics.RenderMesh(ref RimParams, sharedMesh, k, localToWorldMatrix, (Matrix4x4?)null);
								}
							}
						}
					}
				}
			}

			private static void ApplyProperties()
			{
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				float num = Mathf.Lerp(0.5f, 20f, _highlightStrength);
				float num2 = Mathf.Lerp(0.8f, 3f, _highlightStrength);
				RimMat.SetColor(BaseColorId, _highlightColor);
				RimMat.SetFloat(PowerId, num2);
				RimMat.SetFloat(IntensityId, num);
				RimMat.SetFloat(AlphaId, 1f);
			}

			internal static void Reapply()
			{
				if (_rimReady)
				{
				}
			}
		}

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

			[HarmonyPatch(typeof(EnemyPart), "SetupRenderersOnAttach")]
			[HarmonyPostfix]
			private static void SetupRenderersOnAttach_Postfix(EnemyPart __instance)
			{
				RimPainter.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_0012: Expected O, but got Unknown
				//IL_001d: 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_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				Gradient val = (Gradient)GradientField.GetValue(__instance);
				Range<float> vanillaOpacity = (Range<float>)OpacityField.GetValue(__instance);
				if (!_captured || !(_targetingStrength > 0f) || !IsOurOverride(val))
				{
					_vanillaGradient = val;
					_vanillaOpacity = vanillaOpacity;
					_captured = true;
				}
				ApplyTargetingOverride();
			}

			private static bool IsOurOverride(Gradient gradient)
			{
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//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)
				if (gradient == null || gradient.colorKeys == null)
				{
					return false;
				}
				GradientColorKey[] colorKeys = gradient.colorKeys;
				if (colorKeys.Length != 2)
				{
					return false;
				}
				return colorKeys[0].color == _targetingColor && colorKeys[1].color == _targetingColor;
			}

			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 = "coruscnium.enemyhighlights";

		public const string PluginName = "EnemyHighlights";

		public const string PluginVersion = "1.1.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 const string BundleFileName = "enemyhighlights_rim";

		private static AssetBundle _bundle;

		private static bool _rimReady;

		private static FileSystemWatcher _configWatcher;

		private static volatile bool _pendingConfigReload;

		private static DateTime _lastWatcherEvent = DateTime.MinValue;

		private const double DebounceSeconds = 0.05;

		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_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			_highlightColorCfg = ((BaseUnityPlugin)this).Config.Bind<string>("Highlight", "HighlightColor", "FF2A00", "Hex color (RRGGBB) for the enemy fresnel rim glow.");
			_highlightIntensityCfg = ((BaseUnityPlugin)this).Config.Bind<int>("Highlight", "HighlightIntensity", 30, new ConfigDescription("0 disables (vanilla). 100 = brightest, tightest rim glow.", (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, "coruscnium.enemyhighlights.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();
			LoadRimBundle();
			Harmony val = new Harmony("coruscnium.enemyhighlights");
			val.PatchAll(typeof(EnemyPartPatches));
			val.PatchAll(typeof(HighlighterPatches));
			Logger.LogInfo((object)"EnemyHighlights 1.1.0.0 loaded.");
		}

		private void LoadRimBundle()
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			if (string.IsNullOrEmpty(directoryName))
			{
				Logger.LogError((object)"[rim] Could not resolve plugin DLL directory. Rim highlight disabled.");
				return;
			}
			string text = Path.Combine(directoryName, "enemyhighlights_rim");
			if (!File.Exists(text))
			{
				Logger.LogError((object)("[rim] AssetBundle not found at '" + text + "'. The rim shader cannot load. Reinstall the mod (ensure enemyhighlights_rim is in BepInEx/plugins/EnemyHighlights/)."));
				return;
			}
			try
			{
				_bundle = AssetBundle.LoadFromFile(text);
				if ((Object)(object)_bundle == (Object)null)
				{
					Logger.LogError((object)("[rim] Failed to load AssetBundle from '" + text + "'. Rim highlight disabled."));
					return;
				}
				Shader val = _bundle.LoadAsset<Shader>("Assets/RimHighlight.shader");
				if ((Object)(object)val == (Object)null)
				{
					Logger.LogError((object)"[rim] Shader not found in bundle. The bundle may be corrupt or missing the shader asset. Rebuild with Unity 6000.4.0f1.");
					return;
				}
				if (((Object)val).name == "Hidden/InternalErrorShader")
				{
					Logger.LogError((object)"[rim] Shader compiled to pink-fallback. The bundle was likely built with a Unity version that doesn't match the game (6000.4.0f1) or with missing shader includes. Rebuild the shader bundle.");
					return;
				}
				Material val2 = new Material(val);
				((Object)val2).name = "RimHighlight [EnemyHighlights]";
				((Object)val2).hideFlags = (HideFlags)61;
				RimPainter.SetSourceMaterial(val2);
				_rimReady = true;
				Logger.LogInfo((object)("[rim] Bundle loaded — shader '" + ((Object)val).name + "', material created."));
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"[rim] Exception loading AssetBundle: {arg}");
			}
		}

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

		private static void OnConfigFileChanged(object sender, FileSystemEventArgs e)
		{
			DateTime utcNow = DateTime.UtcNow;
			if (!((utcNow - _lastWatcherEvent).TotalSeconds < 0.05))
			{
				_lastWatcherEvent = utcNow;
				_pendingConfigReload = true;
			}
		}

		private void Update()
		{
			if (_pendingConfigReload)
			{
				_pendingConfigReload = false;
				try
				{
					((BaseUnityPlugin)this).Config.Reload();
				}
				catch (IOException)
				{
					_pendingConfigReload = true;
				}
				catch (Exception ex2)
				{
					Logger.LogWarning((object)("Config reload failed: " + ex2.Message));
				}
			}
		}

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

		private void OnDestroy()
		{
			if (_configWatcher != null)
			{
				_configWatcher.EnableRaisingEvents = false;
				_configWatcher.Changed -= OnConfigFileChanged;
				_configWatcher.Created -= OnConfigFileChanged;
				_configWatcher.Renamed -= OnConfigFileChanged;
				_configWatcher.Dispose();
				_configWatcher = null;
			}
			if ((Object)(object)_bundle != (Object)null)
			{
				_bundle.Unload(true);
				_bundle = null;
			}
			_rimReady = false;
		}

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