ClientMods/MunitionsExpert/MunitionsExpert.cs

195 lines
8.0 KiB
C#
Raw Normal View History

using Comfort.Common;
using EFT.HandBook;
using EFT.InventoryLogic;
using EFT.UI.DragAndDrop;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
namespace IcyClawz.MunitionsExpert
{
internal enum EAmmoExtraAttributeId
{
Damage,
PenetrationPower,
ArmorDamage,
FragmentationChance,
RicochetChance
}
internal static class ImageExtensions
{
public static Sprite ToSprite(this System.Drawing.Image instance)
{
byte[] data;
using (MemoryStream ms = new MemoryStream())
{
instance.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
data = ms.ToArray();
}
Texture2D texture = new Texture2D(instance.Width, instance.Height);
ImageConversion.LoadImage(texture, data);
return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
}
}
internal static class IconCache
{
private static readonly Dictionary<EAmmoExtraAttributeId, Sprite> Cache = new Dictionary<EAmmoExtraAttributeId, Sprite>(5);
public static void Initialize()
{
Cache.Add(EAmmoExtraAttributeId.Damage, Properties.Resources.Damage.ToSprite());
Cache.Add(EAmmoExtraAttributeId.PenetrationPower, Properties.Resources.PenetrationPower.ToSprite());
Cache.Add(EAmmoExtraAttributeId.ArmorDamage, Properties.Resources.ArmorDamage.ToSprite());
Cache.Add(EAmmoExtraAttributeId.FragmentationChance, Properties.Resources.FragmentationChance.ToSprite());
Cache.Add(EAmmoExtraAttributeId.RicochetChance, Properties.Resources.RicochetChance.ToSprite());
}
public static Sprite Get(Enum id) =>
id is EAmmoExtraAttributeId extraId ? Cache[extraId] : null;
}
internal static class AmmoTemplateExtensions
{
private static readonly FieldInfo CachedQualitiesField =
typeof(AmmoTemplate).GetField("_cachedQualities", BindingFlags.NonPublic | BindingFlags.Instance);
public static List<ItemAttributeClass> GetCachedQualities(this AmmoTemplate instance) =>
CachedQualitiesField.GetValue(instance) as List<ItemAttributeClass>;
public static void AddExtraAttributes(this AmmoTemplate instance)
{
instance.SafelyAddQualityToList(new ItemAttributeClass(EAmmoExtraAttributeId.Damage)
{
Name = EAmmoExtraAttributeId.Damage.ToString(),
DisplayNameFunc = () => "Damage",
Base = () => instance.Damage * instance.ProjectileCount,
StringValue = () =>
{
int totalDamage = instance.Damage * instance.ProjectileCount;
if (instance.ProjectileCount > 1)
{
return $"{instance.ProjectileCount} <20> {instance.Damage} = {totalDamage}";
}
else
{
return totalDamage.ToString();
}
},
DisplayType = () => EItemAttributeDisplayType.Compact
});
instance.SafelyAddQualityToList(new ItemAttributeClass(EAmmoExtraAttributeId.PenetrationPower)
{
Name = EAmmoExtraAttributeId.PenetrationPower.ToString(),
DisplayNameFunc = () => "Penetration power",
Base = () => instance.PenetrationPower,
StringValue = () =>
{
int armorClass = instance.GetPenetrationArmorClass();
string armorClassStr = armorClass > 0 ? $"Class {armorClass}" : "Unarmored";
return $"{armorClassStr} ({instance.PenetrationPower})";
},
DisplayType = () => EItemAttributeDisplayType.Compact
});
instance.SafelyAddQualityToList(new ItemAttributeClass(EAmmoExtraAttributeId.ArmorDamage)
{
Name = EAmmoExtraAttributeId.ArmorDamage.ToString(),
DisplayNameFunc = () => "Armor damage",
Base = () => instance.ArmorDamage,
StringValue = () => $"{instance.ArmorDamage}%",
DisplayType = () => EItemAttributeDisplayType.Compact
});
instance.SafelyAddQualityToList(new ItemAttributeClass(EAmmoExtraAttributeId.FragmentationChance)
{
Name = EAmmoExtraAttributeId.FragmentationChance.ToString(),
DisplayNameFunc = () => "Fragmentation chance",
Base = () => instance.FragmentationChance,
StringValue = () => $"{Math.Round(instance.FragmentationChance * 100, 1)}%",
DisplayType = () => EItemAttributeDisplayType.Compact
});
instance.SafelyAddQualityToList(new ItemAttributeClass(EAmmoExtraAttributeId.RicochetChance)
{
Name = EAmmoExtraAttributeId.RicochetChance.ToString(),
DisplayNameFunc = () => "Ricochet chance",
Base = () => instance.RicochetChance,
StringValue = () => $"{Math.Round(instance.RicochetChance * 100, 1)}%",
DisplayType = () => EItemAttributeDisplayType.Compact
});
}
public static int GetPenetrationArmorClass(this AmmoTemplate instance)
{
var armorClasses = Singleton<BackendConfigSettingsClass>.Instance.Armor.ArmorClass;
for (int i = armorClasses.Length - 1; i >= 0; i--)
{
if (armorClasses[i].Resistance <= instance.PenetrationPower)
{
return i;
}
}
return 0;
}
}
internal static class ColorUtils
{
private const byte ALPHA = 38;
private static readonly Color[] ArmorClassColors = new Color[]
{
new Color32(120, 40, 135, ALPHA), // Unarmored => Violet
new Color32(0, 60, 170, ALPHA), // Class 1 => Blue
new Color32(0, 150, 150, ALPHA), // Class 2 => Cyan
new Color32(70, 140, 0, ALPHA), // Class 3 => Green
new Color32(170, 170, 0, ALPHA), // Class 4 => Yellow
new Color32(140, 70, 0, ALPHA), // Class 5 => Orange
new Color32(170, 20, 0, ALPHA) // Class 6+ => Red
};
public static Color GetArmorClassColor(int armorClass) =>
ArmorClassColors[Mathf.Clamp(armorClass, 0, ArmorClassColors.Length - 1)];
}
internal static class ItemViewExtensions
{
private static readonly FieldInfo BackgroundColorField =
typeof(ItemView).GetField("BackgroundColor", BindingFlags.NonPublic | BindingFlags.Instance);
private static void SetBackgroundColor(this ItemView instance, Color color) =>
BackgroundColorField.SetValue(instance, color);
public static void OverrideColor(this ItemView instance, Item item)
{
if (item is BulletClass bullet && bullet.PenetrationPower > 0)
{
int armorClass = bullet.AmmoTemplate.GetPenetrationArmorClass();
instance.SetBackgroundColor(ColorUtils.GetArmorClassColor(armorClass));
}
}
}
internal static class EntityIconExtensions
{
private static readonly FieldInfo ColorPanelField =
typeof(EntityIcon).GetField("_colorPanel", BindingFlags.NonPublic | BindingFlags.Instance);
private static Image GetColorPanel(this EntityIcon instance) =>
ColorPanelField.GetValue(instance) as Image;
public static void OverrideColor(this EntityIcon instance, Item item)
{
if (item is BulletClass bullet && bullet.PenetrationPower > 0)
{
int armorClass = bullet.AmmoTemplate.GetPenetrationArmorClass();
instance.GetColorPanel().color = ColorUtils.GetArmorClassColor(armorClass);
}
}
}
}