195 lines
8.0 KiB
C#
195 lines
8.0 KiB
C#
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);
|
||
}
|
||
}
|
||
}
|
||
} |