using System.Text.Json.Serialization; using Core.Annotations; using Core.Models.Eft.Common; using Core.Models.Eft.Common.Tables; using Core.Models.Enums; using Core.Services; using Core.Utils; using Core.Utils.Cloners; using ILogger = Core.Models.Utils.ILogger; namespace Core.Helpers; [Injectable] public class ItemHelper { private readonly ILogger _logger; private readonly HashUtil _hashUtil; private readonly JsonUtil _jsonUtil; private readonly RandomUtil _randomUtil; private readonly MathUtil _mathUtil; private readonly DatabaseService _databaseService; private readonly HandbookHelper _handbookHelper; private readonly ItemBaseClassService _itemBaseClassService; private readonly ItemFilterService _itemFilterService; private readonly LocalisationService _localisationService; private readonly LocaleService _localeService; private readonly CompareUtil _compareUtil; private readonly ICloner _cloner; private readonly List _defaultInvalidBaseTypes = [ BaseClasses.LOOT_CONTAINER, BaseClasses.MOB_CONTAINER, BaseClasses.STASH, BaseClasses.SORTING_TABLE, BaseClasses.INVENTORY, BaseClasses.STATIONARY_CONTAINER, BaseClasses.POCKETS ]; public ItemHelper ( ILogger logger, HashUtil hashUtil, JsonUtil jsonUtil, RandomUtil randomUtil, MathUtil mathUtil, DatabaseService databaseService, HandbookHelper handbookHelper, ItemBaseClassService itemBaseClassService, ItemFilterService itemFilterService, LocalisationService localisationService, LocaleService localeService, CompareUtil compareUtil, ICloner cloner ) { _logger = logger; _hashUtil = hashUtil; _jsonUtil = jsonUtil; _randomUtil = randomUtil; _mathUtil = mathUtil; _databaseService = databaseService; _handbookHelper = handbookHelper; _itemBaseClassService = itemBaseClassService; _itemFilterService = itemFilterService; _localisationService = localisationService; _localeService = localeService; _compareUtil = compareUtil; _cloner = cloner; } /** * Does the provided pool of items contain the desired item * @param itemPool Item collection to check * @param item Item to look for * @param slotId OPTIONAL - slotid of desired item * @returns True if pool contains item */ public bool hasItemWithTpl(List itemPool, string item, string slotId = null) { throw new NotImplementedException(); } /** * Get the first item from provided pool with the desired tpl * @param itemPool Item collection to search * @param item Item to look for * @param slotId OPTIONAL - slotid of desired item * @returns Item or null */ public Item getItemFromPoolByTpl(List itemPool, string item, string slotId = null) { throw new NotImplementedException(); } /** * This method will compare two items (with all its children) and see if they are equivalent. * This method will NOT compare IDs on the items * @param item1 first item with all its children to compare * @param item2 second item with all its children to compare * @param compareUpdProperties Upd properties to compare between the items * @returns true if they are the same, false if they aren't */ public bool isSameItems(List item1, List item2, HashSet compareUpdProperties = null) { throw new NotImplementedException(); } /** * This method will compare two items and see if they are equivalent. * This method will NOT compare IDs on the items * @param item1 first item to compare * @param item2 second item to compare * @param compareUpdProperties Upd properties to compare between the items * @returns true if they are the same, false if they aren't */ public bool isSameItem(Item item1, Item item2, HashSet compareUpdProperties = null) { throw new NotImplementedException(); } /** * Helper method to generate a Upd based on a template * @param itemTemplate the item template to generate a Upd for * @returns A Upd with all the default properties set */ public Upd generateUpdForItem(TemplateItem itemTemplate) { throw new NotImplementedException(); } /** * Checks if a tpl is a valid item. Valid meaning that it's an item that can be stored in stash * Valid means: * Not quest item * 'Item' type * Not on the invalid base types array * Price above 0 roubles * Not on item config blacklist * @param tpl the template id / tpl * @returns boolean; true for items that may be in player possession and not quest items */ public bool isValidItem(string tpl, List invalidBaseTypes = null) { throw new NotImplementedException(); } // Check if the tpl / template Id provided is a descendent of the baseclass // // @param string tpl the item template id to check // @param string baseClassTpl the baseclass to check for // @return bool is the tpl a descendent? public bool OfBaseclass(string tpl, string baseClassTpl) { throw new NotImplementedException(); } // Check if item has any of the supplied base classes // @param string tpl Item to check base classes of // @param string[] baseClassTpls base classes to check for // @returns true if any supplied base classes match public bool OfBaseclasses(string tpl, List baseClassTpls) { throw new NotImplementedException(); } // Does the provided item have the chance to require soft armor inserts // Only applies to helmets/vest/armors. // Not all head gear needs them // @param string itemTpl item to check // @returns Does item have the possibility ot need soft inserts public bool ArmorItemCanHoldMods(string itemTpl) { throw new NotImplementedException(); } // Does the provided item tpl need soft/removable inserts to function // @param string itemTpl Armor item // @returns True if item needs some kind of insert public bool ArmorItemHasRemovableOrSoftInsertSlots(string itemTpl) { throw new NotImplementedException(); } // Does the pased in tpl have ability to hold removable plate items // @param string itemTpl item tpl to check for plate support // @returns True when armor can hold plates public bool ArmorItemHasRemovablePlateSlots(string itemTpl) { throw new NotImplementedException(); } // Does the provided item tpl require soft inserts to become a valid armor item // @param string itemTpl Item tpl to check // @returns True if it needs armor inserts public bool ItemRequiresSoftInserts(string itemTpl) { throw new NotImplementedException(); } // Get all soft insert slot ids // @returns A List of soft insert ids (e.g. soft_armor_back, helmet_top) public List GetSoftInsertSlotIds() { throw new NotImplementedException(); } // Returns the items total price based on the handbook or as a fallback from the prices.json if the item is not // found in the handbook. If the price can't be found at all return 0 // @param List tpls item tpls to look up the price of // @returns Total price in roubles public decimal GetItemAndChildrenPrice(List tpls) { throw new NotImplementedException(); } /// /// Returns the item price based on the handbook or as a fallback from the prices.json if the item is not /// found in the handbook. If the price can't be found at all return 0 /// /// Item to look price up of /// Price in roubles public decimal GetItemPrice(string tpl) { throw new NotImplementedException(); } /// /// Returns the item price based on the handbook or as a fallback from the prices.json if the item is not /// found in the handbook. If the price can't be found at all return 0 /// /// Item to look price up of /// Price in roubles public decimal GetItemMaxPrice(string tpl) { throw new NotImplementedException(); } /// /// Get the static (handbook) price in roubles for an item by tpl /// /// Items tpl id to look up price /// Price in roubles (0 if not found) public decimal GetStaticItemPrice(string tpl) { throw new NotImplementedException(); } /// /// Get the dynamic (flea) price in roubles for an item by tpl /// /// Items tpl id to look up price /// Price in roubles (undefined if not found) public decimal GetDynamicItemPrice(string tpl) { throw new NotImplementedException(); } /// /// Update items upd.StackObjectsCount to be 1 if its upd is missing or StackObjectsCount is undefined /// /// Item to update /// Fixed item public Item FixItemStackCount(Item item) { throw new NotImplementedException(); } /// /// Get cloned copy of all item data from items.json /// /// List of TemplateItem objects public List GetItems() { throw new NotImplementedException(); } /** * Gets item data from items.json * @param tpl items template id to look up * @returns bool - is valid + template item object as array */ public KeyValuePair GetItem(string tpl) { throw new NotImplementedException(); } /** * Checks if the item has slots * @param itemTpl Template id of the item to check * @returns true if the item has slots */ public bool ItemHasSlots(string itemTpl) { throw new NotImplementedException(); } /** * Checks if the item is in the database * @param tpl Template id of the item to check * @returns true if the item is in the database */ public bool IsItemInDb(string tpl) { throw new NotImplementedException(); } /** * Calculate the average quality of an item and its children * @param items An offers item to process * @param skipArmorItemsWithoutDurability Skip over armor items without durability * @returns % quality modifier between 0 and 1 */ public double GetItemQualityModifierForItems(List items, bool? skipArmorItemsWithoutDurability = null) { throw new NotImplementedException(); } /** * Get normalized value (0-1) based on item condition * Will return -1 for base armor items with 0 durability * @param item Item to check * @param skipArmorItemsWithoutDurability return -1 for armor items that have max durability of 0 * @returns Number between 0 and 1 */ public double GetItemQualityModifier(Item item, bool? skipArmorItemsWithoutDurability = null) { throw new NotImplementedException(); } /** * Get a quality value based on a repairable item's current state between current and max durability * @param itemDetails Db details for item we want quality value for * @param repairable Repairable properties * @param item Item quality value is for * @returns A number between 0 and 1 */ protected double GetRepairableItemQualityValue( Dictionary itemDetails, UpdRepairable repairable, Item item ) { throw new NotImplementedException(); } /** * Recursive function that looks at every item from parameter and gets their children's Ids + includes parent item in results * @param items List of items (item + possible children) * @param baseItemId Parent item's id * @returns a list of strings */ public List FindAndReturnChildrenByItems(List items, string baseItemId) { throw new NotImplementedException(); } /** * A variant of FindAndReturnChildren where the output is list of item objects instead of their ids. * @param items List of items (item + possible children) * @param baseItemId Parent item's id * @param modsOnly Include only mod items, exclude items stored inside root item * @returns A list of Item objects */ public List FindAndReturnChildrenAsItems(List items, string baseItemId, bool modsOnly = false) { throw new NotImplementedException(); } /** * Find children of the item in a given assort (weapons parts for example, need recursive loop function) * @param itemIdToFind Template id of item to check for * @param assort List of items to check in * @returns List of children of requested item */ public List FindAndReturnChildrenByAssort(string itemIdToFind, List assort) { throw new NotImplementedException(); } /** * Check if the passed in item has buy count restrictions * @param itemToCheck Item to check * @returns true if it has buy restrictions */ public bool HasBuyRestrictions(Item itemToCheck) { throw new NotImplementedException(); } /// /// Checks if the passed template id is a dog tag. /// /// Template id to check. /// True if it is a dogtag. public bool IsDogtag(string tpl) { throw new NotImplementedException(); } /// /// Gets the identifier for a child using slotId, locationX and locationY. /// /// Item. /// SlotId OR slotid, locationX, locationY. public string GetChildId(Item item) { throw new NotImplementedException(); } /// /// Checks if the passed item can be stacked. /// /// Item to check. /// True if it can be stacked. public bool IsItemTplStackable(string tpl) { throw new NotImplementedException(); } /// /// Splits the item stack if it exceeds its items StackMaxSize property into child items of the passed parent. /// /// Item to split into smaller stacks. /// List of root item + children. public List SplitStack(Item itemToSplit) { throw new NotImplementedException(); } /// /// Turns items like money into separate stacks that adhere to max stack size. /// /// Item to split into smaller stacks. /// List of separate item stacks. public List> SplitStackIntoSeparateItems(Item itemToSplit) { throw new NotImplementedException(); } /// /// Finds Barter items from a list of items. /// /// Tpl or id. /// Array of items to iterate over. /// Desired barter item ids. /// List of Item objects. public List FindBarterItems(string by, List itemsToSearch, string desiredBarterItemIds) { throw new NotImplementedException(); } /// /// Replaces the _id value for the base item + all children that are children of it. /// REPARENTS ROOT ITEM ID, NOTHING ELSE. /// /// Item with mods to update. /// New id to add on children of base item. public void ReplaceRootItemID(List itemWithChildren, string newId = "") { throw new NotImplementedException(); } /// /// Regenerate all GUIDs with new IDs, for the exception of special item types (e.g. quest, sorting table, etc.) This /// function will not mutate the original items list, but will return a new list with new GUIDs. /// /// Items to adjust the IDs of /// Player profile /// Insured items that should not have their IDs replaced /// Quick slot panel /// List public List ReplaceIDs(List originalItems, PmcData pmcData = null, List insuredItems = null, Dictionary fastPanel = null) { var items = _cloner.Clone(originalItems); var serialisedInventory = _jsonUtil.Serialize(items); var hideoutAreaStashes = pmcData?.Inventory?.HideoutAreaStashes ?? new(); foreach (var item in items) { if (pmcData != null) { // Insured items should not be renamed. Only works for PMCs. if (insuredItems?.FirstOrDefault(i => i.ItemId == item.Id) != null) continue; // Do not replace the IDs of specific types of items. if (item.Id == pmcData?.Inventory?.Equipment || item.Id == pmcData?.Inventory?.QuestRaidItems || item.Id == pmcData?.Inventory?.QuestStashItems || item.Id == pmcData?.Inventory?.SortingTable || item.Id == pmcData?.Inventory?.Stash || item.Id == pmcData?.Inventory?.HideoutCustomizationStashId || (hideoutAreaStashes?.ContainsKey(item.Id) ?? false)) { continue; } } // Replace the ID of the item in the serialised inventory using a regular expression. var oldId = item.Id; var newId = _hashUtil.Generate(); serialisedInventory = serialisedInventory.Replace(oldId, newId); // Node uses regex with "g" flag to replace all instances // Also replace in quick slot if the old ID exists. if (fastPanel != null) { foreach (var itemSlot in fastPanel) { if (fastPanel[itemSlot.Key] == oldId) fastPanel[itemSlot.Key] = fastPanel[itemSlot.Key].Replace(oldId, newId); // Node uses regex with "g" flag to replace all instances } } } items = _jsonUtil.Deserialize>(serialisedInventory); // fix dupe id's var dupes = new Dictionary(); var newParents = new Dictionary>(); var childrenMapping = new Dictionary>(); var oldToNewIds = new Dictionary>(); // Finding duplicate IDs involves scanning the item three times. // First scan - Check which ids are duplicated. // Second scan - Map parents to items. // Third scan - Resolve IDs. foreach (var item in items) { if (!dupes.TryAdd(item.Id, 0)) { dupes[item.Id] += 1; } } foreach (var item in items) { if (!(dupes[item.Id] > 1)) { continue; } var newId = _hashUtil.Generate(); if (!newParents.ContainsKey(item.ParentId)) { newParents.Add(item.ParentId, []); } var newParentsItems = newParents.GetValueOrDefault(item.ParentId); newParentsItems.Add(item); if (!oldToNewIds.ContainsKey(item.Id)) { oldToNewIds.Add(item.Id, []); } var oldToNewIdsItems = oldToNewIds.GetValueOrDefault(item.Id); oldToNewIdsItems.Add(newId); } foreach (var item in items) { if (dupes[item.Id] > 1) { var oldId = item.Id; var newId = oldToNewIds[oldId][0]; oldToNewIds[oldId].RemoveAt(0); item.Id = newId; // Extract one of the children that's also duplicated. if (newParents.ContainsKey(oldId) && newParents[oldId].Count > 0) { childrenMapping[newId] = new(); for (int i = 0; i < newParents[oldId].Count; i++) { // Make sure we haven't already assigned another duplicate child of // same slot and location to this parent. var childId = GetChildId(newParents[oldId][i]); if (!childrenMapping.ContainsKey(childId)) { childrenMapping[newId][childId] = 1; newParents[oldId][i].ParentId = newId; // Some very fucking sketchy stuff on this childIndex // No clue wth was that childIndex supposed to be, but its not newParents[oldId].RemoveAt(i); } } } } } return items; } /// /// Mark the passed in list of items as found in raid. /// Modifies passed in items /// /// The list of items to mark as FiR public void SetFoundInRaid(List items) { foreach (var item in items) { if (item.Upd == null) item.Upd = new(); item.Upd.SpawnedInSession = true; } } /// /// WARNING, SLOW. Recursively loop down through an items hierarchy to see if any of the ids match the supplied list, return true if any do /// /// Items tpl to check parents of /// Tpl values to check if parents of item match /// bool Match found public bool DoesItemOrParentsIdMatch(string tpl, List tplsToCheck) { var itemDetails = GetItem(tpl); var itemExists = itemDetails.Key; var item = itemDetails.Value; // not an item, drop out if (!itemExists) return false; // no parent to check if (item.Parent == null) return false; // Does templateId match any values in tplsToCheck array if (tplsToCheck.Contains(item.Id)) return true; // check items parent with same method if (tplsToCheck.Contains(item.Parent)) return true; return DoesItemOrParentsIdMatch(item.Parent, tplsToCheck); } /// /// Check if item is quest item /// /// Items tpl to check quest status of /// true if item is flagged as quest item public bool IsQuestItem(string tpl) { var itemDetails = GetItem(tpl); if (itemDetails.Key && itemDetails.Value.Properties.QuestItem != null) return true; return false; } /// /// Checks to see if the item is *actually* moddable in-raid. Checks include the items existence in the database, the /// parent items existence in the database, the existence (and value) of the items RaidModdable property, and that /// the parents slot-required property exists, matches that of the item, and its value. /// /// The item to be checked /// The parent of the item to be checked /// True if the item is actually moddable, false if it is not, and null if the check cannot be performed. public bool? IsRaidModdable(Item item, Item parent) { // This check requires the item to have the slotId property populated. if (item.SlotId == null) return null; var itemTemplate = GetItem(item.Template); var parentTemplate = GetItem(parent.Template); // Check for RaidModdable property on the item template. var isNotRaidModdable = false; if (itemTemplate.Key) isNotRaidModdable = itemTemplate.Value?.Properties?.RaidModdable == false; // Check to see if the slot that the item is attached to is marked as required in the parent item's template. var isRequiredSlot = false; if (parentTemplate.Key && parentTemplate.Value?.Properties?.Slots != null) isRequiredSlot = parentTemplate.Value?.Properties?.Slots?.Any(slot => slot?.Name == item?.SlotId && (slot?.Required ?? false) ) ?? false; return itemTemplate.Key && parentTemplate.Key && (isNotRaidModdable || isRequiredSlot); } /// /// Retrieves the main parent item for a given attachment item. /// /// This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the main parent /// item that is not an attached attachment itself. In other words, if you pass it an item id of a suppressor, it /// will traverse up the muzzle brake, barrel, upper receiver, and return the gun that the suppressor is ultimately /// attached to, even if that gun is located within multiple containers. /// /// It's important to note that traversal is expensive, so this method requires that you pass it a Map of the items /// to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates /// some of the performance concerns, as it allows for quick lookups of items by ID. /// /// The unique identifier of the item for which to find the main parent. /// A Dictionary containing item IDs mapped to their corresponding Item objects for quick lookup. /// The Item object representing the top-most parent of the given item, or null if no such parent exists. public Item GetAttachmentMainParent(string itemId, Dictionary itemsMap) { var currentItem = itemsMap.FirstOrDefault(x => x.Key == itemId).Value; while (currentItem != null && IsAttachmentAttached(currentItem)) { currentItem = itemsMap.FirstOrDefault(x => x.Key == currentItem.ParentId).Value; if (currentItem == null) return null; } return currentItem; } /** * Determines if an item is an attachment that is currently attached to its parent item. * * @param item The item to check. * @returns true if the item is attached attachment, otherwise false. */ public bool IsAttachmentAttached(Item item) { // TODO: actually implement return true; } /** * Retrieves the equipment parent item for a given item. * * This method traverses up the hierarchy of items starting from a given `itemId`, until it finds the equipment * parent item. In other words, if you pass it an item id of a suppressor, it will traverse up the muzzle brake, * barrel, upper receiver, gun, nested backpack, and finally return the backpack Item that is equipped. * * It's important to note that traversal is expensive, so this method requires that you pass it a Dictionary of the items * to traverse, where the keys are the item IDs and the values are the corresponding Item objects. This alleviates * some of the performance concerns, as it allows for quick lookups of items by ID. * * @param itemId - The unique identifier of the item for which to find the equipment parent. * @param itemsMap - A Dictionary containing item IDs mapped to their corresponding Item objects for quick lookup. * @returns The Item object representing the equipment parent of the given item, or `null` if no such parent exists. */ public Item GetEquipmentParent(string itemId, Dictionary itemsMap) { throw new NotImplementedException(); } /** * Get the inventory size of an item * @param items Item with children * @param rootItemId * @returns ItemSize object (width and height) */ public ItemSize GetItemSize(List items, string rootItemId) { throw new NotImplementedException(); } /** * Get a random cartridge from an items Filter property * @param item Db item template to look up Cartridge filter values from * @returns Caliber of cartridge */ public string GetRandomCompatibleCaliberTemplateId(TemplateItem item) { throw new NotImplementedException(); } /** * Add cartridges to the ammo box with correct max stack sizes * @param ammoBox Box to add cartridges to * @param ammoBoxDetails Item template from items db */ public void AddCartridgesToAmmoBox(List ammoBox, TemplateItem ammoBoxDetails) { throw new NotImplementedException(); } /** * Add a single stack of cartridges to the ammo box * @param ammoBox Box to add cartridges to * @param ammoBoxDetails Item template from items db */ public void AddSingleStackCartridgesToAmmoBox(List ammoBox, TemplateItem ammoBoxDetails) { throw new NotImplementedException(); } /** * Check if item is stored inside of a container * @param itemToCheck Item to check is inside of container * @param desiredContainerSlotId Name of slot to check item is in e.g. SecuredContainer/Backpack * @param items Inventory with child parent items to check * @returns True when item is in container */ public bool ItemIsInsideContainer(Item itemToCheck, string desiredContainerSlotId, List items) { throw new NotImplementedException(); } /** * Add child items (cartridges) to a magazine * @param magazine Magazine to add child items to * @param magTemplate Db template of magazine * @param staticAmmoDist Cartridge distribution * @param caliber Caliber of cartridge to add to magazine * @param minSizePercent % the magazine must be filled to * @param defaultCartridgeTpl Cartridge to use when none found * @param weapon Weapon the magazine will be used for (if passed in uses Chamber as whitelist) */ public void FillMagazineWithRandomCartridge( List magazine, TemplateItem magTemplate, Dictionary> staticAmmoDist, string caliber = null, double minSizePercent = 0.25, string defaultCartridgeTpl = null, TemplateItem weapon = null) { throw new NotImplementedException(); } /// /// Add child items to a magazine of a specific cartridge /// /// Magazine to add child items to /// Db template of magazine /// Cartridge to add to magazine /// % the magazine must be filled to public void FillMagazineWithCartridge( List magazineWithChildCartridges, TemplateItem magTemplate, string cartridgeTpl, double minSizeMultiplier = 0.25 ) { throw new NotImplementedException(); } /// /// Choose a random bullet type from the list of possible a magazine has /// /// Magazine template from Db /// Tpl of cartridge protected string GetRandomValidCaliber(TemplateItem magTemplate) { throw new NotImplementedException(); } /// /// Chose a randomly weighted cartridge that fits /// /// Desired caliber /// Cartridges and their weights /// If a cartridge cannot be found in the above staticAmmoDist param, use this instead /// OPTIONAL whitelist for cartridges /// Tpl of cartridge protected string? DrawAmmoTpl( string caliber, Dictionary> staticAmmoDist, string fallbackCartridgeTpl, List? cartridgeWhitelist = null ) { throw new NotImplementedException(); } /// /// Create a basic cartridge object /// /// container cartridges will be placed in /// Cartridge to insert /// Count of cartridges inside parent /// Location inside parent (e.g. 0, 1) /// OPTIONAL - Are cartridges found in raid (SpawnedInSession) /// Item public Item CreateCartridges( string parentId, string ammoTpl, int stackCount, int location, bool foundInRaid = false ) { throw new NotImplementedException(); } /// /// Get the size of a stack, return 1 if no stack object count property found /// /// Item to get stack size of /// size of stack public int GetItemStackSize(Item item) { throw new NotImplementedException(); } /// /// Get the name of an item from the locale file using the item tpl /// /// Tpl of item to get name of /// Full name, short name if not found public string GetItemName(string itemTpl) { throw new NotImplementedException(); } /// /// Get all item tpls with a desired base type /// /// Item base type wanted /// Array of tpls public List GetItemTplsOfBaseType(string desiredBaseType) { throw new NotImplementedException(); } /// /// Add child slot items to an item, chooses random child item if multiple choices exist /// /// array with single object (root item) /// Db template for root item /// Optional dictionary of mod name + % chance mod will be included in item (e.g. front_plate: 100) /// Only add required mods /// Item with children public List AddChildSlotItems( List itemToAdd, TemplateItem itemToAddTemplate, Dictionary? modSpawnChanceDict = null, bool requiredOnly = false ) { throw new NotImplementedException(); } /// /// Get a compatible tpl from the array provided where it is not found in the provided incompatible mod tpls parameter /// /// Tpls to randomly choose from /// Incompatible tpls to not allow /// Chosen tpl or undefined public string? GetCompatibleTplFromArray(List possibleTpls, HashSet incompatibleModTpls) { throw new NotImplementedException(); } /// /// Is the provided item._props.Slots._name property a plate slot /// /// Name of slot (_name) of Items Slot array /// True if its a slot that holds a removable plate public bool IsRemovablePlateSlot(string slotName) { throw new NotImplementedException(); } // Get a list of slot names that hold removable plates // Returns Array of slot ids (e.g. front_plate) public List GetRemovablePlateSlotIds() { throw new NotImplementedException(); } // Generate new unique ids for child items while preserving hierarchy // Base/primary item // Primary item + children of primary item // Returns Item array with updated IDs public List ReparentItemAndChildren(Item rootItem, List itemWithChildren) { throw new NotImplementedException(); } // Update a root items _id property value to be unique // Item to update root items _id property // Optional: new id to use // Returns New root id public string RemapRootItemId(List itemWithChildren, string newId) // TODO: string newId = this.hashUtil.Generate() { throw new NotImplementedException(); } // Adopts orphaned items by resetting them as root "hideout" items. Helpful in situations where a parent has been // deleted from a group of items and there are children still referencing the missing parent. This method will // remove the reference from the children to the parent and set item properties to root values. // // The ID of the "root" of the container. // Array of Items that should be adjusted. // Returns Array of Items that have been adopted. public List AdoptOrphanedItems(string rootId, List items) { throw new NotImplementedException(); } // Populate a Map object of items for quick lookup using their ID. // // An array of Items that should be added to a Map. // Returns A Map where the keys are the item IDs and the values are the corresponding Item objects. public Dictionary GenerateItemsMap(List items) { throw new NotImplementedException(); } // Add a blank upd object to passed in item if it does not exist already // item to add upd to // text to write to log when upd object was not found // Returns True when upd object was added public bool AddUpdObjectToItem(Item item, string warningMessageWhenMissing = null) { throw new NotImplementedException(); } // Return all tpls from Money enum // Returns string tpls public List GetMoneyTpls() { throw new NotImplementedException(); } // Get a randomised stack size for the passed in ammo // Ammo to get stack size for // Default: Limit to 60 to prevent crazy values when players use stack increase mods // Returns number public int GetRandomisedAmmoStackSize(TemplateItem ammoItemTemplate, int maxLimit = 60) { throw new NotImplementedException(); } public void GetItemBaseType(string tpl, bool rootOnly = true) { throw new NotImplementedException(); } // Remove FiR status from passed in items // Items to update FiR status of public void RemoveSpawnedInSessionPropertyFromItems(List items) { throw new NotImplementedException(); } public bool IsOfBaseclass(string valueEncyclopedia, string weapon) { throw new NotImplementedException(); } } public class ItemSize { [JsonPropertyName("width")] public double Width { get; set; } [JsonPropertyName("height")] public double Height { get; set; } }