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 Parts = new HashSet(); private static readonly List Iter = new List(); 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 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 _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 vanillaOpacity = (Range)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(_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 _highlightColorCfg; private static ConfigEntry _highlightIntensityCfg; private static ConfigEntry _targetingColorCfg; private static ConfigEntry _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("Highlight", "HighlightColor", "FF2A00", "Hex color (RRGGBB) for the enemy fresnel rim glow."); _highlightIntensityCfg = ((BaseUnityPlugin)this).Config.Bind("Highlight", "HighlightIntensity", 30, new ConfigDescription("0 disables (vanilla). 100 = brightest, tightest rim glow.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); _targetingColorCfg = ((BaseUnityPlugin)this).Config.Bind("Targeting", "TargetingColor", "FF2A00", "Hex color (RRGGBB) for the pointed-at part overlay."); _targetingIntensityCfg = ((BaseUnityPlugin)this).Config.Bind("Targeting", "TargetingIntensity", 0, new ConfigDescription("0 disables (vanilla health-gradient overlay). 100 = fully opaque overlay.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ((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("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; } } }