using Aki.Reflection.Patching; using BepInEx; using BepInEx.Configuration; using EFT.HandBook; using EFT.InventoryLogic; using EFT.UI; using EFT.UI.DragAndDrop; using System; using System.Collections.Generic; using System.Reflection; using UnityEngine; using UnityEngine.UI; namespace IcyClawz.MunitionsExpert; [BepInPlugin("com.IcyClawz.MunitionsExpert", "IcyClawz.MunitionsExpert", "1.3.0")] public class Plugin : BaseUnityPlugin { private static ConfigEntry ColorizeSwitch { get; set; } private static ConfigEntry[] ArmorClassColors { get; set; } private void Awake() { const string COLORIZE = "Colorize Icon Backgrounds"; ColorizeSwitch = Config.Bind(COLORIZE, "", true, new ConfigurationManagerAttributes { Order = 7 }); ArmorClassColors = [ Config.Bind(COLORIZE, "Unarmored", ColorName.Purple, new ConfigurationManagerAttributes { Order = 6 }), Config.Bind(COLORIZE, "Class 1", ColorName.Blue, new ConfigurationManagerAttributes { Order = 5 }), Config.Bind(COLORIZE, "Class 2", ColorName.Cyan, new ConfigurationManagerAttributes { Order = 4 }), Config.Bind(COLORIZE, "Class 3", ColorName.Green, new ConfigurationManagerAttributes { Order = 3 }), Config.Bind(COLORIZE, "Class 4", ColorName.Yellow, new ConfigurationManagerAttributes { Order = 2 }), Config.Bind(COLORIZE, "Class 5", ColorName.Orange, new ConfigurationManagerAttributes { Order = 1 }), Config.Bind(COLORIZE, "Class 6+", ColorName.Red, new ConfigurationManagerAttributes { Order = 0 }) ]; new StaticIconsPatch().Enable(); new AmmoTemplatePatch().Enable(); new ItemViewPatch().Enable(); new EntityIconPatch().Enable(); } internal static bool Colorize => ColorizeSwitch.Value; internal static Color GetArmorClassColor(int index) { index = Mathf.Clamp(index, 0, ArmorClassColors.Length - 1); return ColorCache.Get(ArmorClassColors[index].Value); } } internal class StaticIconsPatch : ModulePatch { protected override MethodBase GetTargetMethod() => typeof(StaticIcons).GetMethod("GetAttributeIcon", BindingFlags.Public | BindingFlags.Instance); [PatchPrefix] private static bool PatchPrefix(ref Sprite __result, Enum id) => (__result = IconCache.Get(id)) is null; } internal class AmmoTemplatePatch : ModulePatch { protected override MethodBase GetTargetMethod() => typeof(AmmoTemplate).GetMethod("GetCachedReadonlyQualities", BindingFlags.Public | BindingFlags.Instance); [PatchPrefix] private static bool PatchPrefix(ref AmmoTemplate __instance) => __instance.GetCachedQualities() is null; [PatchPostfix] private static void PatchPostfix(ref List __result, ref AmmoTemplate __instance) { if (__result is null) __result = __instance.GetCachedQualities(); else __instance.AddExtraAttributes(); } } internal class ItemViewPatch : ModulePatch { private static readonly FieldInfo BackgroundColorField = typeof(ItemView).GetField("BackgroundColor", BindingFlags.NonPublic | BindingFlags.Instance); protected override MethodBase GetTargetMethod() => typeof(ItemView).GetMethod("UpdateColor", BindingFlags.Public | BindingFlags.Instance); [PatchPrefix] private static void PatchPrefix(ref ItemView __instance) { if (!Plugin.Colorize || __instance.Item is not BulletClass bullet || bullet.PenetrationPower <= 0) return; int armorClass = bullet.AmmoTemplate.GetPenetrationArmorClass(); BackgroundColorField.SetValue(__instance, Plugin.GetArmorClassColor(armorClass)); } } internal class EntityIconPatch : ModulePatch { private static readonly FieldInfo ColorPanelField = typeof(EntityIcon).GetField("_colorPanel", BindingFlags.NonPublic | BindingFlags.Instance); protected override MethodBase GetTargetMethod() => typeof(EntityIcon).GetMethod("Show", BindingFlags.Public | BindingFlags.Instance); [PatchPostfix] private static void PatchPostfix(ref EntityIcon __instance, Item item) { if (!Plugin.Colorize || item is not BulletClass bullet || bullet.PenetrationPower <= 0) return; int armorClass = bullet.AmmoTemplate.GetPenetrationArmorClass(); if (ColorPanelField.GetValue(__instance) is Image image) image.color = Plugin.GetArmorClassColor(armorClass); } }