Server/project/src/services/RagfairLinkedItemService.ts

146 lines
4.5 KiB
TypeScript
Raw Normal View History

2023-03-03 15:23:46 +00:00
import { inject, injectable } from "tsyringe";
import { ItemHelper } from "@spt/helpers/ItemHelper";
import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem";
import { BaseClasses } from "@spt/models/enums/BaseClasses";
import { DatabaseService } from "@spt/services/DatabaseService";
2023-03-03 15:23:46 +00:00
@injectable()
export class RagfairLinkedItemService
{
protected linkedItemsCache: Record<string, Set<string>> = {};
2023-03-03 15:23:46 +00:00
constructor(
@inject("DatabaseService") protected databaseService: DatabaseService,
2023-11-15 20:35:05 -05:00
@inject("ItemHelper") protected itemHelper: ItemHelper,
2023-03-03 15:23:46 +00:00
)
2023-11-15 20:35:05 -05:00
{}
2023-03-03 15:23:46 +00:00
public getLinkedItems(linkedSearchId: string): Set<string>
2023-03-03 15:23:46 +00:00
{
if (Object.keys(this.linkedItemsCache).length === 0)
{
this.buildLinkedItemTable();
}
return this.linkedItemsCache[linkedSearchId];
}
/**
* Use ragfair linked item service to get an array of items that can fit on or in designated itemtpl
* @param itemTpl Item to get sub-items for
* @returns ITemplateItem array
*/
public getLinkedDbItems(itemTpl: string): ITemplateItem[]
{
const linkedItemsToWeaponTpls = this.getLinkedItems(itemTpl);
2023-11-15 20:35:05 -05:00
return [...linkedItemsToWeaponTpls].map((x) =>
{
const itemDetails = this.itemHelper.getItem(x);
return itemDetails[1];
});
}
2023-03-03 15:23:46 +00:00
/**
* Create Dictionary of every item and the items associated with it
*/
protected buildLinkedItemTable(): void
{
const linkedItems: Record<string, any> = {};
const getLinkedItems = (id: string) =>
{
if (!(id in linkedItems))
{
linkedItems[id] = new Set();
}
return linkedItems[id];
};
for (const item of Object.values(this.databaseService.getItems()))
2023-03-03 15:23:46 +00:00
{
const itemLinkedSet = getLinkedItems(item._id);
// TODO - move into own protected function
const applyLinkedItems = (items: string[]) =>
{
for (const linkedItemId of items)
{
itemLinkedSet.add(linkedItemId);
getLinkedItems(linkedItemId).add(item._id);
}
};
applyLinkedItems(this.getFilters(item, "Slots"));
applyLinkedItems(this.getFilters(item, "Chambers"));
applyLinkedItems(this.getFilters(item, "Cartridges"));
// Edge case, ensure ammo for revolves is included
if (item._parent === BaseClasses.REVOLVER)
{
// Find magazine for revolver
this.addRevolverCylinderAmmoToLinkedItems(item, applyLinkedItems);
}
}
this.linkedItemsCache = linkedItems;
}
/**
* Add ammo to revolvers linked item dictionary
* @param cylinder Revolvers cylinder
2023-11-15 20:35:05 -05:00
* @param applyLinkedItems
2023-03-03 15:23:46 +00:00
*/
2023-11-15 20:35:05 -05:00
protected addRevolverCylinderAmmoToLinkedItems(
cylinder: ITemplateItem,
applyLinkedItems: (items: string[]) => void,
): void
2023-03-03 15:23:46 +00:00
{
const cylinderMod = cylinder._props.Slots?.find((x) => x._name === "mod_magazine");
2023-03-03 15:23:46 +00:00
if (cylinderMod)
{
// Get the first cylinder filter tpl
const cylinderTpl = cylinderMod._props.filters[0]?.Filter[0];
if (cylinderTpl)
{
// Get db data for cylinder tpl, add found slots info (camora_xxx) to linked items on revolver weapon
const cylinderItem = this.itemHelper.getItem(cylinderTpl)[1];
applyLinkedItems(this.getFilters(cylinderItem, "Slots"));
}
}
}
/**
* Scans a given slot type for filters and returns them as a Set
2023-11-15 20:35:05 -05:00
* @param item
* @param slot
* @returns array of ids
*/
2023-03-03 15:23:46 +00:00
protected getFilters(item: ITemplateItem, slot: string): string[]
{
if (!(slot in item._props && item._props[slot].length))
{
// item slot doesnt exist
return [];
}
const filters: string[] = [];
2023-03-03 15:23:46 +00:00
for (const sub of item._props[slot])
{
if (!("_props" in sub && "filters" in sub._props))
{
// not a filter
continue;
}
for (const filter of sub._props.filters)
{
for (const f of filter.Filter)
{
filters.push(f);
}
}
}
return filters;
}
2023-11-15 20:35:05 -05:00
}