ClientMods/MunitionsExpert/MunitionsExpert.cs

181 lines
7.8 KiB
C#
Raw Permalink Normal View History

using Comfort.Common;
using EFT.InventoryLogic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEngine;
2024-03-05 22:48:21 +02:00
namespace IcyClawz.MunitionsExpert;
internal enum ColorName
{
Blue, Brown, Cyan, Gray, Green, Magenta, Orange, Pink, Purple, Red, Silver, Tan, Violet, Yellow
}
internal static class ColorCache
{
2024-03-05 22:48:21 +02:00
private const byte ALPHA = 38;
private static readonly Dictionary<ColorName, Color> Cache = new()
{
2024-03-05 22:48:21 +02:00
[ColorName.Blue] = new Color32(0, 60, 170, ALPHA),
[ColorName.Brown] = new Color32(140, 85, 30, ALPHA),
[ColorName.Cyan] = new Color32(0, 150, 150, ALPHA),
[ColorName.Gray] = new Color32(70, 70, 70, ALPHA),
[ColorName.Green] = new Color32(70, 140, 0, ALPHA),
[ColorName.Magenta] = new Color32(215, 0, 100, ALPHA),
[ColorName.Orange] = new Color32(140, 70, 0, ALPHA),
[ColorName.Pink] = new Color32(215, 120, 150, ALPHA),
[ColorName.Purple] = new Color32(120, 40, 135, ALPHA),
[ColorName.Red] = new Color32(170, 20, 0, ALPHA),
[ColorName.Silver] = new Color32(150, 150, 150, ALPHA),
[ColorName.Tan] = new Color32(175, 145, 100, ALPHA),
[ColorName.Violet] = new Color32(80, 50, 180, ALPHA),
2024-10-23 00:49:39 +03:00
[ColorName.Yellow] = new Color32(170, 170, 0, ALPHA),
2024-03-05 22:48:21 +02:00
};
public static Color Get(ColorName name) => Cache.TryGetValue(name, out Color color) ? color : default;
}
internal enum EAmmoExtraAttributeId
{
ArmorDamage, FragmentationChance, RicochetChance
2024-03-05 22:48:21 +02:00
}
2024-03-05 22:48:21 +02:00
internal static class ImageExtensions
{
public static Sprite ToSprite(this System.Drawing.Image instance)
{
2024-03-05 22:48:21 +02:00
using MemoryStream ms = new();
instance.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
Texture2D texture = new(instance.Width, instance.Height, TextureFormat.RGBA32, false);
texture.LoadImage(ms.ToArray());
2024-03-05 22:48:21 +02:00
return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
}
2024-03-05 22:48:21 +02:00
}
2024-03-05 22:48:21 +02:00
internal static class IconCache
{
private static readonly Dictionary<Enum, Sprite> Cache = new()
{
2024-03-05 22:48:21 +02:00
[EAmmoExtraAttributeId.ArmorDamage] = Properties.Resources.ArmorDamage.ToSprite(),
[EAmmoExtraAttributeId.FragmentationChance] = Properties.Resources.FragmentationChance.ToSprite(),
2024-10-23 00:49:39 +03:00
[EAmmoExtraAttributeId.RicochetChance] = Properties.Resources.RicochetChance.ToSprite(),
2024-03-05 22:48:21 +02:00
};
2024-03-05 22:48:21 +02:00
public static Sprite Get(Enum id) => Cache.TryGetValue(id, out Sprite sprite) ? sprite : default;
}
2024-03-05 22:48:21 +02:00
internal static class AmmoTemplateExtensions
{
2024-10-23 00:49:39 +03:00
private static readonly string[] MalfChancesKeys = (string[])
typeof(AmmoTemplate).GetField("MalfChancesKeys", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
2024-10-23 17:07:49 +03:00
private static readonly FieldInfo MaxMalfMisfireChance =
typeof(AmmoTemplate).GetField("MaxMalfMisfireChance", BindingFlags.NonPublic | BindingFlags.Static);
private static readonly FieldInfo MaxMalfFeedChance =
typeof(AmmoTemplate).GetField("MaxMalfFeedChance", BindingFlags.NonPublic | BindingFlags.Static);
2024-03-05 22:48:21 +02:00
private static readonly FieldInfo CachedQualitiesField =
typeof(AmmoTemplate).GetField("_cachedQualities", BindingFlags.NonPublic | BindingFlags.Instance);
2024-03-05 22:48:21 +02:00
public static List<ItemAttributeClass> GetCachedQualities(this AmmoTemplate instance) =>
CachedQualitiesField.GetValue(instance) as List<ItemAttributeClass>;
2024-03-05 22:48:21 +02:00
public static void AddExtraAttributes(this AmmoTemplate instance)
{
instance.SafelyAddQualityToList(new ItemAttributeClass(EAmmoExtraAttributeId.ArmorDamage)
{
2024-03-05 22:48:21 +02:00
Name = EAmmoExtraAttributeId.ArmorDamage.ToString(),
DisplayNameFunc = () => "Armor damage",
Base = () => instance.ArmorDamage,
StringValue = () => $"{instance.ArmorDamage}%",
2024-10-23 00:49:39 +03:00
DisplayType = () => EItemAttributeDisplayType.Compact,
});
instance.SafelyAddQualityToList(new ItemAttributeClass(EItemAttributeId.DurabilityBurn)
{
Name = EItemAttributeId.DurabilityBurn.GetName(),
Base = () => instance.DurabilityBurnModificator - 1f,
StringValue = () => $"{(instance.DurabilityBurnModificator - 1f) * 100f:F1}%",
DisplayType = () => EItemAttributeDisplayType.Compact,
LabelVariations = EItemAttributeLabelVariations.Colored,
LessIsGood = true,
});
instance.SafelyAddQualityToList(new ItemAttributeClass(EItemAttributeId.HeatFactor)
{
Name = EItemAttributeId.HeatFactor.GetName(),
Base = () => instance.HeatFactor - 1f,
StringValue = () => $"{(instance.HeatFactor - 1f) * 100f:F1}%",
DisplayType = () => EItemAttributeDisplayType.Compact,
LabelVariations = EItemAttributeLabelVariations.Colored,
LessIsGood = true,
2024-03-05 22:48:21 +02:00
});
instance.SafelyAddQualityToList(new ItemAttributeClass(EAmmoExtraAttributeId.FragmentationChance)
{
2024-03-05 22:48:21 +02:00
Name = EAmmoExtraAttributeId.FragmentationChance.ToString(),
DisplayNameFunc = () => "Fragmentation chance",
Base = () => instance.FragmentationChance,
2024-10-23 00:49:39 +03:00
StringValue = () => $"{instance.FragmentationChance * 100f:F1}%",
DisplayType = () => EItemAttributeDisplayType.Compact,
2024-03-05 22:48:21 +02:00
});
instance.SafelyAddQualityToList(new ItemAttributeClass(EAmmoExtraAttributeId.RicochetChance)
{
Name = EAmmoExtraAttributeId.RicochetChance.ToString(),
DisplayNameFunc = () => "Ricochet chance",
Base = () => instance.RicochetChance,
2024-10-23 00:49:39 +03:00
StringValue = () => $"{(instance.RicochetChance * 100f):F1}%",
DisplayType = () => EItemAttributeDisplayType.Compact,
});
instance.SafelyAddQualityToList(new ItemAttributeClass(EItemAttributeId.MalfMisfireChance)
{
Name = EItemAttributeId.MalfMisfireChance.GetName(),
Base = () => instance.MalfMisfireChance,
StringValue = () =>
{
2024-10-23 17:07:49 +03:00
float maxMalfMisfireChance = (float)MaxMalfMisfireChance.GetValue(null);
int index = instance.MalfMisfireChance <= 0f ? 0
: instance.MalfMisfireChance < 3f * maxMalfMisfireChance / 7f ? 1
: instance.MalfMisfireChance < 4f * maxMalfMisfireChance / 7f ? 2
: instance.MalfMisfireChance < 5f * maxMalfMisfireChance / 7f ? 3
: instance.MalfMisfireChance < 6f * maxMalfMisfireChance / 7f ? 4
: 5;
return MalfChancesKeys[index].Localized();
2024-10-23 00:49:39 +03:00
},
DisplayType = () => EItemAttributeDisplayType.Compact,
});
instance.SafelyAddQualityToList(new ItemAttributeClass(EItemAttributeId.MalfFeedChance)
{
Name = EItemAttributeId.MalfFeedChance.GetName(),
Base = () => instance.MalfFeedChance,
StringValue = () =>
{
2024-10-23 17:07:49 +03:00
float maxMalfFeedChance = (float)MaxMalfFeedChance.GetValue(null);
int index = instance.MalfFeedChance <= 0f ? 0
: instance.MalfFeedChance < 1f * maxMalfFeedChance / 7f ? 1
: instance.MalfFeedChance < 3f * maxMalfFeedChance / 7f ? 2
: instance.MalfFeedChance < 5f * maxMalfFeedChance / 7f ? 3
: instance.MalfFeedChance < 6f * maxMalfFeedChance / 7f ? 4
: 5;
return MalfChancesKeys[index].Localized();
2024-10-23 00:49:39 +03:00
},
DisplayType = () => EItemAttributeDisplayType.Compact,
2024-03-05 22:48:21 +02:00
});
}
2024-03-05 22:48:21 +02:00
public static int GetPenetrationArmorClass(this AmmoTemplate instance)
{
2024-03-05 22:48:21 +02:00
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;
}
2024-03-05 22:48:21 +02:00
}