using EFT.InventoryLogic;
using SPT.Reflection.Utils;
using System.Text;
using KeycardTemplate = GClass2623;
using ArmorTemplate = GClass2550;
using ArmoredRigTemplate = GClass2602;
using MagazineTemplate = GClass2586;
namespace LootValueEX.Extensions
{
internal static class ItemExtensions
{
///
/// Checks if an item has been examined by the player.
///
/// The item to check.
/// True if the item has been examined, false otherwise.
internal static bool IsExamined(this Item? item) => item != null && ClientAppUtils.GetMainApp().GetClientBackEndSession().Profile.Examined(item);
internal static bool IsStacked(this Item? item) => item != null && (item.StackObjectsCount > 1 || item.UnlimitedCount);
internal static string PrehashTemplate(this Item? item) => string.Format("{0}|{1}|{2}", item?.TemplateId, item.GetDurability(), item.GetUses());
internal static Item? UnstackItem(this Item? item)
{
if (item == null)
return null;
if (!item.IsStacked())
return item;
Item? itemClone = item.CloneItem();
itemClone.StackObjectsCount = 1;
itemClone.UnlimitedCount = false;
return itemClone;
}
///
/// Retrieves the value of a specific attribute from an item.
///
/// The item to retrieve the attribute from.
/// The ID of the attribute to retrieve.
/// The value of the attribute, or -1f if the item is null or the attribute is not found.
internal static float GetItemAttribute(this Item? item, EItemAttributeId attributeId)
{
if (item == null)
return -1f;
try
{
return item.Attributes.Single(att => att.Id.Equals(attributeId)).Base();
}
catch (InvalidOperationException)
{
return -1f;
}
}
///
/// Generates a custom hash for the given item.
///
/// This function takes an optional Item as a parameter and returns its custom hash.
/// If the item is null, it returns an empty string. The custom hash is determined by the item's template, durability, and uses.
///
/// The item to retrieve the custom hash for.
/// The custom hash of the item, or an empty string if the item is null.
internal static async Task GetCustomHashAsync(this Item? item)
{
if (item == null)
return string.Empty;
StringBuilder prehashString = new StringBuilder();
item.GetAllItems().Where(i => !i.Equals(item)).DoMap(i => prehashString.Append(i.PrehashTemplate()));
if (item.Template.Equals(typeof(MagazineTemplate)))
{
MagazineTemplate magTemplate = (MagazineTemplate)item.Template;
magTemplate.Cartridges.DoMap(s => s.Items.DoMap(i => prehashString.Append(i.PrehashTemplate())));
}
prehashString.Append(item.PrehashTemplate());
return await Task.Run(() => Utils.HashingUtils.ConvertToSha256(prehashString.ToString()));
}
internal static string GetCustomHash(this Item? item) => Task.Run(() => item?.GetCustomHashAsync()).Result ?? string.Empty;
#if DEBUG
internal static string AttributesToString(this Item? item)
{
if (item == null)
return String.Empty;
if (item.Attributes.IsNullOrEmpty())
return String.Empty;
StringBuilder sb = new StringBuilder();
item.Attributes.ForEach(attr => sb.Append($"\n{attr.Id}\n\tName: {attr.Name}\n\tBase Value: {attr.Base()}\n\tString value: {attr.StringValue()}\n\tDisplay Type: {attr.DisplayType()}"));
return sb.ToString();
}
#endif
///
/// Retrieves the durability of a given item.
///
/// This function takes an optional Item as a parameter and returns its durability.
/// If the item is null, it returns -1f. The durability is determined by the item's template.
///
/// The item to retrieve the durability for.
/// The durability of the item, or -1f if the item is null.
internal static float GetDurability(this Item? item)
{
if (item == null)
return -1f;
switch (item.Template)
{
case ArmoredRigTemplate armoredRig:
case ArmorTemplate armor:
return Utils.ItemUtils.GetArmorDurability(item.GetItemComponentsInChildren(true));
default:
return item.GetItemAttribute(EItemAttributeId.Durability);
}
}
///
/// Retrieves the number of uses remaining for a given item.
///
/// This function takes an optional Item as a parameter and returns the number of uses remaining.
/// If the item is null, it returns -1f. The number of uses is determined by the item's template.
///
/// The item to retrieve the number of uses for.
/// The number of uses remaining for the item, or -1f if the item is null.
internal static float GetUses(this Item? item)
{
if (item == null)
return -1f;
switch (item.Template)
{
case KeycardTemplate:
KeyComponent keyComponent = item.GetItemComponent();
return keyComponent.Template.MaximumNumberOfUsage - keyComponent.NumberOfUsages;
case Meds2Class:
if (item.TryGetItemComponent(out MedKitComponent medKitComponent))
return medKitComponent.HpResource;
return -1f;
case MagazineTemplate:
MagazineClass? magazineClass = item as MagazineClass;
return magazineClass?.Count ?? -1f;
case AmmoBoxTemplate:
AmmoBox? ammoBox = item as AmmoBox;
return ammoBox?.Count ?? -1f;
default:
return -1f;
}
}
}
}