Server/project/src/services/RagfairLinkedItemService.ts

124 lines
4.3 KiB
TypeScript
Raw Normal View History

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";
import { inject, injectable } from "tsyringe";
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
public getLinkedItems(linkedSearchId: string): Set<string> {
if (Object.keys(this.linkedItemsCache).length === 0) {
2023-03-03 15:23:46 +00:00
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);
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 {
2023-03-03 15:23:46 +00:00
const linkedItems: Record<string, any> = {};
const getLinkedItems = (id: string) => {
if (!(id in linkedItems)) {
2023-03-03 15:23:46 +00:00
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) {
2023-03-03 15:23:46 +00:00
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) {
2023-03-03 15:23:46 +00:00
// 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 {
const cylinderMod = cylinder._props.Slots?.find((x) => x._name === "mod_magazine");
if (cylinderMod) {
2023-03-03 15:23:46 +00:00
// Get the first cylinder filter tpl
const cylinderTpl = cylinderMod._props.filters[0]?.Filter[0];
if (cylinderTpl) {
2023-03-03 15:23:46 +00:00
// 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
*/
protected getFilters(item: ITemplateItem, slot: string): string[] {
if (!(slot in item._props && item._props[slot].length)) {
2023-03-03 15:23:46 +00:00
// item slot doesnt exist
return [];
}
const filters: string[] = [];
for (const sub of item._props[slot]) {
if (!("_props" in sub && "filters" in sub._props)) {
2023-03-03 15:23:46 +00:00
// not a filter
continue;
}
for (const filter of sub._props.filters) {
for (const f of filter.Filter) {
2023-03-03 15:23:46 +00:00
filters.push(f);
}
}
}
return filters;
}
2023-11-15 20:35:05 -05:00
}