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