2023-07-08 23:42:42 +03:00
|
|
|
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
|
2023-07-08 23:42:42 +03:00
|
|
|
{
|
2024-03-05 22:48:21 +02:00
|
|
|
private const byte ALPHA = 38;
|
|
|
|
private static readonly Dictionary<ColorName, Color> Cache = new()
|
2023-07-08 23:42:42 +03:00
|
|
|
{
|
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
|
|
|
|
{
|
2024-07-10 23:03:39 +03:00
|
|
|
ArmorDamage, FragmentationChance, RicochetChance
|
2024-03-05 22:48:21 +02:00
|
|
|
}
|
2023-07-08 23:42:42 +03:00
|
|
|
|
2024-03-05 22:48:21 +02:00
|
|
|
internal static class ImageExtensions
|
|
|
|
{
|
|
|
|
public static Sprite ToSprite(this System.Drawing.Image instance)
|
2023-07-08 23:42:42 +03:00
|
|
|
{
|
2024-03-05 22:48:21 +02:00
|
|
|
using MemoryStream ms = new();
|
|
|
|
instance.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
|
2024-07-10 23:03:39 +03:00
|
|
|
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);
|
2023-07-08 23:42:42 +03:00
|
|
|
}
|
2024-03-05 22:48:21 +02:00
|
|
|
}
|
2023-07-08 23:42:42 +03:00
|
|
|
|
2024-03-05 22:48:21 +02:00
|
|
|
internal static class IconCache
|
|
|
|
{
|
|
|
|
private static readonly Dictionary<Enum, Sprite> Cache = new()
|
2023-07-08 23:42:42 +03:00
|
|
|
{
|
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
|
|
|
};
|
2023-07-08 23:42:42 +03:00
|
|
|
|
2024-03-05 22:48:21 +02:00
|
|
|
public static Sprite Get(Enum id) => Cache.TryGetValue(id, out Sprite sprite) ? sprite : default;
|
|
|
|
}
|
2023-07-08 23:42:42 +03:00
|
|
|
|
2024-03-05 22:48:21 +02:00
|
|
|
internal static class AmmoTemplateExtensions
|
|
|
|
{
|
2024-10-23 00:49:39 +03:00
|
|
|
private static readonly float MaxMalfMisfireChance = (float)
|
|
|
|
typeof(AmmoTemplate).GetField("MaxMalfMisfireChance", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
|
|
|
|
|
|
|
|
private static readonly float MaxMalfFeedChance = (float)
|
|
|
|
typeof(AmmoTemplate).GetField("MaxMalfFeedChance", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
|
|
|
|
|
|
|
|
private static readonly string[] MalfChancesKeys = (string[])
|
|
|
|
typeof(AmmoTemplate).GetField("MalfChancesKeys", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
|
|
|
|
|
2024-03-05 22:48:21 +02:00
|
|
|
private static readonly FieldInfo CachedQualitiesField =
|
|
|
|
typeof(AmmoTemplate).GetField("_cachedQualities", BindingFlags.NonPublic | BindingFlags.Instance);
|
2023-07-08 23:42:42 +03:00
|
|
|
|
2024-03-05 22:48:21 +02:00
|
|
|
public static List<ItemAttributeClass> GetCachedQualities(this AmmoTemplate instance) =>
|
|
|
|
CachedQualitiesField.GetValue(instance) as List<ItemAttributeClass>;
|
2023-07-08 23:42:42 +03:00
|
|
|
|
2024-03-05 22:48:21 +02:00
|
|
|
public static void AddExtraAttributes(this AmmoTemplate instance)
|
|
|
|
{
|
|
|
|
instance.SafelyAddQualityToList(new ItemAttributeClass(EAmmoExtraAttributeId.ArmorDamage)
|
2023-07-08 23:42:42 +03:00
|
|
|
{
|
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)
|
2023-07-08 23:42:42 +03:00
|
|
|
{
|
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 = () =>
|
|
|
|
{
|
|
|
|
string value;
|
|
|
|
if (instance.MalfMisfireChance <= 0f)
|
|
|
|
value = MalfChancesKeys[0];
|
|
|
|
else if (instance.MalfMisfireChance < 3f * MaxMalfMisfireChance / 7f)
|
|
|
|
value = MalfChancesKeys[1];
|
|
|
|
else if (instance.MalfMisfireChance < 4f * MaxMalfMisfireChance / 7f)
|
|
|
|
value = MalfChancesKeys[2];
|
|
|
|
else if (instance.MalfMisfireChance < 5f * MaxMalfMisfireChance / 7f)
|
|
|
|
value = MalfChancesKeys[3];
|
|
|
|
else if (instance.MalfMisfireChance < 6f * MaxMalfMisfireChance / 7f)
|
|
|
|
value = MalfChancesKeys[4];
|
|
|
|
else
|
|
|
|
value = MalfChancesKeys[5];
|
|
|
|
return value.Localized();
|
|
|
|
},
|
|
|
|
DisplayType = () => EItemAttributeDisplayType.Compact,
|
|
|
|
});
|
|
|
|
|
|
|
|
instance.SafelyAddQualityToList(new ItemAttributeClass(EItemAttributeId.MalfFeedChance)
|
|
|
|
{
|
|
|
|
Name = EItemAttributeId.MalfFeedChance.GetName(),
|
|
|
|
Base = () => instance.MalfFeedChance,
|
|
|
|
StringValue = () =>
|
|
|
|
{
|
|
|
|
string value;
|
|
|
|
if (instance.MalfFeedChance <= 0f)
|
|
|
|
value = MalfChancesKeys[0];
|
|
|
|
else if (instance.MalfFeedChance < 1f * MaxMalfFeedChance / 7f)
|
|
|
|
value = MalfChancesKeys[1];
|
|
|
|
else if (instance.MalfFeedChance < 3f * MaxMalfFeedChance / 7f)
|
|
|
|
value = MalfChancesKeys[2];
|
|
|
|
else if (instance.MalfFeedChance < 5f * MaxMalfFeedChance / 7f)
|
|
|
|
value = MalfChancesKeys[3];
|
|
|
|
else if (instance.MalfFeedChance < 6f * MaxMalfFeedChance / 7f)
|
|
|
|
value = MalfChancesKeys[4];
|
|
|
|
else
|
|
|
|
value = MalfChancesKeys[5];
|
|
|
|
return value.Localized();
|
|
|
|
},
|
|
|
|
DisplayType = () => EItemAttributeDisplayType.Compact,
|
2024-03-05 22:48:21 +02:00
|
|
|
});
|
2023-07-08 23:42:42 +03:00
|
|
|
}
|
|
|
|
|
2024-03-05 22:48:21 +02:00
|
|
|
public static int GetPenetrationArmorClass(this AmmoTemplate instance)
|
2023-07-08 23:42:42 +03:00
|
|
|
{
|
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;
|
2023-07-08 23:42:42 +03:00
|
|
|
}
|
2024-03-05 22:48:21 +02:00
|
|
|
}
|