Refactor of RagfairAssortGenerator
and associated code that touches it
This commit is contained in:
parent
86d34e3efe
commit
4ce26ea870
@ -16,7 +16,7 @@ import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
|||||||
@injectable()
|
@injectable()
|
||||||
export class RagfairAssortGenerator
|
export class RagfairAssortGenerator
|
||||||
{
|
{
|
||||||
protected generatedAssortItems: Item[] = [];
|
protected generatedAssortItems: Item[][] = [];
|
||||||
protected ragfairConfig: IRagfairConfig;
|
protected ragfairConfig: IRagfairConfig;
|
||||||
|
|
||||||
protected ragfairItemInvalidBaseTypes: string[] = [
|
protected ragfairItemInvalidBaseTypes: string[] = [
|
||||||
@ -43,10 +43,11 @@ export class RagfairAssortGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an array of unique items that can be sold on the flea
|
* Get an array of arrays that can be sold on the flea
|
||||||
* @returns array of unique items
|
* Each sub array contains item + children (if any)
|
||||||
|
* @returns array of arrays
|
||||||
*/
|
*/
|
||||||
public getAssortItems(): Item[]
|
public getAssortItems(): Item[][]
|
||||||
{
|
{
|
||||||
if (!this.assortsAreGenerated())
|
if (!this.assortsAreGenerated())
|
||||||
{
|
{
|
||||||
@ -66,16 +67,17 @@ export class RagfairAssortGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate an array of items the flea can sell
|
* Generate an array of arrays (item + children) the flea can sell
|
||||||
* @returns array of unique items
|
* @returns array of arrays (item + children)
|
||||||
*/
|
*/
|
||||||
protected generateRagfairAssortItems(): Item[]
|
protected generateRagfairAssortItems(): Item[][]
|
||||||
{
|
{
|
||||||
const results: Item[] = [];
|
const results: Item[][] = [];
|
||||||
|
|
||||||
/** Get cloned items from db */
|
/** Get cloned items from db */
|
||||||
const dbItemsClone = this.itemHelper.getItems().filter(item => item._type !== "Node");
|
const dbItemsClone = this.itemHelper.getItems().filter(item => item._type !== "Node");
|
||||||
|
|
||||||
|
/** Store processed preset tpls so we dont add them when procesing non-preset items */
|
||||||
const processedArmorItems: string[] = [];
|
const processedArmorItems: string[] = [];
|
||||||
const seasonalEventActive = this.seasonalEventService.seasonalEventEnabled();
|
const seasonalEventActive = this.seasonalEventService.seasonalEventEnabled();
|
||||||
const seasonalItemTplBlacklist = this.seasonalEventService.getInactiveSeasonalEventItems();
|
const seasonalItemTplBlacklist = this.seasonalEventService.getInactiveSeasonalEventItems();
|
||||||
@ -83,13 +85,21 @@ export class RagfairAssortGenerator
|
|||||||
const presets = this.getPresetsToAdd();
|
const presets = this.getPresetsToAdd();
|
||||||
for (const preset of presets)
|
for (const preset of presets)
|
||||||
{
|
{
|
||||||
const presetItemTpl = preset._items[0]._tpl;
|
// Update Ids and clone
|
||||||
|
const presetAndMods: Item[] = this.itemHelper.replaceIDs(
|
||||||
|
null,
|
||||||
|
this.jsonUtil.clone(preset._items),
|
||||||
|
);
|
||||||
|
this.itemHelper.remapRootItemId(presetAndMods);
|
||||||
|
|
||||||
// Add presets base item tpl to the processed list so its skipped later on when processing items
|
// Add presets base item tpl to the processed list so its skipped later on when processing items
|
||||||
processedArmorItems.push(presetItemTpl)
|
processedArmorItems.push(preset._items[0]._tpl);
|
||||||
|
|
||||||
// Preset id must be passed through to ensure flea shows preset
|
presetAndMods[0].parentId = "hideout";
|
||||||
results.push(this.createRagfairAssortItem(presetItemTpl, preset._id));
|
presetAndMods[0].slotId = "hideout";
|
||||||
|
presetAndMods[0].upd = { StackObjectsCount: 99999999, UnlimitedCount: true, sptPresetId: preset._id};
|
||||||
|
|
||||||
|
results.push(presetAndMods);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const item of dbItemsClone)
|
for (const item of dbItemsClone)
|
||||||
@ -114,7 +124,9 @@ export class RagfairAssortGenerator
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
results.push(this.createRagfairAssortItem(item._id, item._id)); // tplid and id must be the same so hideout recipe rewards work
|
const ragfairAssort = this.createRagfairAssortRootItem(item._id, item._id); // tplid and id must be the same so hideout recipe rewards work
|
||||||
|
|
||||||
|
results.push([ragfairAssort]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
@ -136,9 +148,9 @@ export class RagfairAssortGenerator
|
|||||||
* Create a base assort item and return it with populated values + 999999 stack count + unlimited count = true
|
* Create a base assort item and return it with populated values + 999999 stack count + unlimited count = true
|
||||||
* @param tplId tplid to add to item
|
* @param tplId tplid to add to item
|
||||||
* @param id id to add to item
|
* @param id id to add to item
|
||||||
* @returns hydrated Item object
|
* @returns Hydrated Item object
|
||||||
*/
|
*/
|
||||||
protected createRagfairAssortItem(tplId: string, id = this.hashUtil.generate()): Item
|
protected createRagfairAssortRootItem(tplId: string, id = this.hashUtil.generate()): Item
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
_id: id,
|
_id: id,
|
||||||
|
@ -312,21 +312,22 @@ export class RagfairOfferGenerator
|
|||||||
* Create multiple offers for items by using a unique list of items we've generated previously
|
* Create multiple offers for items by using a unique list of items we've generated previously
|
||||||
* @param expiredOffers optional, expired offers to regenerate
|
* @param expiredOffers optional, expired offers to regenerate
|
||||||
*/
|
*/
|
||||||
public async generateDynamicOffers(expiredOffers: Item[] = null): Promise<void>
|
public async generateDynamicOffers(expiredOffers: Item[][] = null): Promise<void>
|
||||||
{
|
{
|
||||||
|
const replacingExpiredOffers = expiredOffers?.length > 0;
|
||||||
const config = this.ragfairConfig.dynamic;
|
const config = this.ragfairConfig.dynamic;
|
||||||
|
|
||||||
// get assort items from param if they exist, otherwise grab freshly generated assorts
|
// get assort items from param if they exist, otherwise grab freshly generated assorts
|
||||||
const assortItemsToProcess: Item[] = expiredOffers
|
const assortItemsToProcess: Item[][] = replacingExpiredOffers
|
||||||
? expiredOffers
|
? expiredOffers
|
||||||
: this.ragfairAssortGenerator.getAssortItems();
|
: this.ragfairAssortGenerator.getAssortItems();
|
||||||
|
|
||||||
// Store all functions to create an offer for every item and pass into Promise.all to run async
|
// Store all functions to create an offer for every item and pass into Promise.all to run async
|
||||||
const assorOffersForItemsProcesses = [];
|
const assorOffersForItemsProcesses = [];
|
||||||
for (const assortItemIndex in assortItemsToProcess)
|
for (const assortItemWithChildren of assortItemsToProcess)
|
||||||
{
|
{
|
||||||
assorOffersForItemsProcesses.push(
|
assorOffersForItemsProcesses.push(
|
||||||
this.createOffersForItems(assortItemIndex, assortItemsToProcess, expiredOffers, config),
|
this.createOffersFromAssort(assortItemWithChildren, replacingExpiredOffers, config),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,47 +335,34 @@ export class RagfairOfferGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param assortItemIndex Index of assort item
|
* @param assortItemWithChildren Item with its children to process into offers
|
||||||
* @param assortItemsToProcess Item array containing index
|
* @param isExpiredOffer is an expired offer
|
||||||
* @param expiredOffers Currently expired offers on flea
|
|
||||||
* @param config Ragfair dynamic config
|
* @param config Ragfair dynamic config
|
||||||
*/
|
*/
|
||||||
protected async createOffersForItems(
|
protected async createOffersFromAssort(
|
||||||
assortItemIndex: string,
|
assortItemWithChildren: Item[],
|
||||||
assortItemsToProcess: Item[],
|
isExpiredOffer: boolean,
|
||||||
expiredOffers: Item[],
|
|
||||||
config: Dynamic,
|
config: Dynamic,
|
||||||
): Promise<void>
|
): Promise<void>
|
||||||
{
|
{
|
||||||
const assortItem = assortItemsToProcess[assortItemIndex];
|
const itemDetails = this.itemHelper.getItem(assortItemWithChildren[0]._tpl);
|
||||||
const itemDetails = this.itemHelper.getItem(assortItem._tpl);
|
const isPreset = this.presetHelper.isPreset(assortItemWithChildren[0].upd.sptPresetId);
|
||||||
|
|
||||||
const isPreset = this.presetHelper.isPreset(assortItem._id);
|
|
||||||
|
|
||||||
// Only perform checks on newly generated items, skip expired items being refreshed
|
// Only perform checks on newly generated items, skip expired items being refreshed
|
||||||
if (!(expiredOffers || this.ragfairServerHelper.isItemValidRagfairItem(itemDetails)))
|
if (!(isExpiredOffer || this.ragfairServerHelper.isItemValidRagfairItem(itemDetails)))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get item + sub-items (weapons + armors), otherwise just get item
|
|
||||||
const itemWithChildren: Item[] = isPreset
|
|
||||||
? this.ragfairServerHelper.getPresetItems(assortItem)
|
|
||||||
: [
|
|
||||||
...[assortItem],
|
|
||||||
...this.itemHelper.findAndReturnChildrenByAssort(assortItem._id, this.ragfairAssortGenerator.getAssortItems(),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
// Armor presets can hold plates above the allowed flea level, remove if necessary
|
// Armor presets can hold plates above the allowed flea level, remove if necessary
|
||||||
if (isPreset && this.ragfairConfig.dynamic.blacklist.enableBsgList)
|
if (isPreset && this.ragfairConfig.dynamic.blacklist.enableBsgList)
|
||||||
{
|
{
|
||||||
this.removeBannedPlatesFromPreset(itemWithChildren, this.ragfairConfig.dynamic.blacklist.armorPlateMaxProtectionLevel);
|
this.removeBannedPlatesFromPreset(assortItemWithChildren, this.ragfairConfig.dynamic.blacklist.armorPlateMaxProtectionLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get number of offers to create
|
// Get number of offers to create
|
||||||
// Limit to 1 offer when processing expired
|
// Limit to 1 offer when processing expired - like-for-like replacement
|
||||||
const offerCount = expiredOffers
|
const offerCount = isExpiredOffer
|
||||||
? 1
|
? 1
|
||||||
: Math.round(this.randomUtil.getInt(config.offerItemCount.min, config.offerItemCount.max));
|
: Math.round(this.randomUtil.getInt(config.offerItemCount.min, config.offerItemCount.max));
|
||||||
|
|
||||||
@ -385,13 +373,13 @@ export class RagfairOfferGenerator
|
|||||||
if (!isPreset)
|
if (!isPreset)
|
||||||
{
|
{
|
||||||
// Presets get unique id generated during getPresetItems() earlier + would require regenerating all children to match
|
// Presets get unique id generated during getPresetItems() earlier + would require regenerating all children to match
|
||||||
itemWithChildren[0]._id = this.hashUtil.generate();
|
assortItemWithChildren[0]._id = this.hashUtil.generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
delete itemWithChildren[0].parentId;
|
delete assortItemWithChildren[0].parentId;
|
||||||
delete itemWithChildren[0].slotId;
|
delete assortItemWithChildren[0].slotId;
|
||||||
|
|
||||||
assortSingleOfferProcesses.push(this.createSingleOfferForItem(itemWithChildren, isPreset, itemDetails));
|
assortSingleOfferProcesses.push(this.createSingleOfferForItem(assortItemWithChildren, isPreset, itemDetails));
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(assortSingleOfferProcesses);
|
await Promise.all(assortSingleOfferProcesses);
|
||||||
|
@ -261,7 +261,7 @@ export class TraderAssortHelper
|
|||||||
protected getRagfairDataAsTraderAssort(): ITraderAssort
|
protected getRagfairDataAsTraderAssort(): ITraderAssort
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
items: this.ragfairAssortGenerator.getAssortItems(),
|
items: this.ragfairAssortGenerator.getAssortItems().flat(),
|
||||||
barter_scheme: {},
|
barter_scheme: {},
|
||||||
loyal_level_items: {},
|
loyal_level_items: {},
|
||||||
nextResupply: null,
|
nextResupply: null,
|
||||||
|
@ -47,27 +47,27 @@ export class RagfairServer
|
|||||||
|
|
||||||
// Generate trader offers
|
// Generate trader offers
|
||||||
const traders = this.getUpdateableTraders();
|
const traders = this.getUpdateableTraders();
|
||||||
for (const traderID of traders)
|
for (const traderId of traders)
|
||||||
{
|
{
|
||||||
// Skip generating fence offers
|
// Skip generating fence offers
|
||||||
if (traderID === Traders.FENCE)
|
if (traderId === Traders.FENCE)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.ragfairOfferService.traderOffersNeedRefreshing(traderID))
|
if (this.ragfairOfferService.traderOffersNeedRefreshing(traderId))
|
||||||
{
|
{
|
||||||
this.ragfairOfferGenerator.generateFleaOffersForTrader(traderID);
|
this.ragfairOfferGenerator.generateFleaOffersForTrader(traderId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regen expired offers when over threshold count
|
// Regenerate expired offers when over threshold limit
|
||||||
if (this.ragfairOfferService.getExpiredOfferCount() >= this.ragfairConfig.dynamic.expiredOfferThreshold)
|
if (this.ragfairOfferService.getExpiredOfferCount() >= this.ragfairConfig.dynamic.expiredOfferThreshold)
|
||||||
{
|
{
|
||||||
const expiredOfferItems = this.ragfairOfferService.getExpiredOfferItems();
|
const expiredAssortsWithChildren = this.ragfairOfferService.getExpiredOfferAssorts();
|
||||||
await this.ragfairOfferGenerator.generateDynamicOffers(expiredOfferItems);
|
await this.ragfairOfferGenerator.generateDynamicOffers(expiredAssortsWithChildren);
|
||||||
|
|
||||||
// reset expired offers now we've genned them
|
// Clear out expired offers now we've generated them
|
||||||
this.ragfairOfferService.resetExpiredOffers();
|
this.ragfairOfferService.resetExpiredOffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
|||||||
export class RagfairOfferService
|
export class RagfairOfferService
|
||||||
{
|
{
|
||||||
protected playerOffersLoaded = false;
|
protected playerOffersLoaded = false;
|
||||||
|
/** Offer id + offer object */
|
||||||
protected expiredOffers: Record<string, IRagfairOffer> = {};
|
protected expiredOffers: Record<string, IRagfairOffer> = {};
|
||||||
|
|
||||||
protected ragfairConfig: IRagfairConfig;
|
protected ragfairConfig: IRagfairConfig;
|
||||||
@ -71,27 +72,35 @@ export class RagfairOfferService
|
|||||||
this.expiredOffers[staleOffer._id] = staleOffer;
|
this.expiredOffers[staleOffer._id] = staleOffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get total count of current expired offers
|
||||||
|
* @returns Number of expired offers
|
||||||
|
*/
|
||||||
public getExpiredOfferCount(): number
|
public getExpiredOfferCount(): number
|
||||||
{
|
{
|
||||||
return Object.keys(this.expiredOffers).length;
|
return Object.keys(this.expiredOffers).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an array of expired items not yet processed into new offers
|
* Get an array of arrays of expired offer items + children
|
||||||
* @returns items that need to be turned into offers
|
* @returns Expired offer assorts
|
||||||
*/
|
*/
|
||||||
public getExpiredOfferItems(): Item[]
|
public getExpiredOfferAssorts(): Item[][]
|
||||||
{
|
{
|
||||||
const expiredItems: Item[] = [];
|
const expiredItems: Item[][] = [];
|
||||||
|
|
||||||
for (const expiredOfferId in this.expiredOffers)
|
for (const expiredOfferId in this.expiredOffers)
|
||||||
{
|
{
|
||||||
expiredItems.push(this.expiredOffers[expiredOfferId].items[0]);
|
const expiredOffer = this.expiredOffers[expiredOfferId];
|
||||||
|
expiredItems.push(expiredOffer.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
return expiredItems;
|
return expiredItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear out internal expiredOffers dictionary of all items
|
||||||
|
*/
|
||||||
public resetExpiredOffers(): void
|
public resetExpiredOffers(): void
|
||||||
{
|
{
|
||||||
this.expiredOffers = {};
|
this.expiredOffers = {};
|
||||||
|
Loading…
Reference in New Issue
Block a user