Expand fence item force stacking system

Remove redundant multi-stack tracking system
Expand `getSingleItemStackCount()` to check for parent ids too
This commit is contained in:
Dev 2024-03-05 10:43:47 +00:00
parent 8f4df131ac
commit 095fcf08fd
2 changed files with 71 additions and 28 deletions

View File

@ -125,7 +125,11 @@
}, },
"preventDuplicateOffersOfCategory": [ "preventDuplicateOffersOfCategory": [
"543be5cb4bdc2deb348b4568", "543be5cb4bdc2deb348b4568",
"5485a8684bdc2da71d8b4567" "5485a8684bdc2da71d8b4567",
"5448f3ac4bdc2dce718b4569",
"5448f39d4bdc2d0a728b4568",
"5448f3a14bdc2d27728b4569",
"5448bc234bdc2d3c308b4569"
], ],
"weaponDurabilityPercentMinMax": { "weaponDurabilityPercentMinMax": {
"current": { "current": {
@ -180,6 +184,14 @@
"544fb3364bdc2d34748b456a": { "544fb3364bdc2d34748b456a": {
"min": 1, "min": 1,
"max": 800 "max": 800
},
"5448bc234bdc2d3c308b4569": {
"min": 1,
"max": 50
},
"5448f3a14bdc2d27728b4569": {
"min": 1,
"max": 25
} }
}, },
"itemCategoryRoublePriceLimit": { "itemCategoryRoublePriceLimit": {

View File

@ -46,9 +46,6 @@ export class FenceService
/** Hydrated on initial assort generation as part of generateFenceAssorts() */ /** Hydrated on initial assort generation as part of generateFenceAssorts() */
protected desiredAssortCounts: IFenceAssortGenerationValues; protected desiredAssortCounts: IFenceAssortGenerationValues;
/** Items that have a multi-stack */
protected multiStackItems: Record<string, boolean> = {};
constructor( constructor(
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("JsonUtil") protected jsonUtil: JsonUtil,
@ -553,9 +550,6 @@ export class FenceService
x.parentId === "hideout" && !x.upd?.sptPresetId x.parentId === "hideout" && !x.upd?.sptPresetId
); );
// Clear cache of multi-stack items
this.multiStackItems = {};
for (let i = 0; i < assortCount; i++) for (let i = 0; i < assortCount; i++)
{ {
const chosenBaseAssortRoot = this.randomUtil.getArrayValue(assortRootItems); const chosenBaseAssortRoot = this.randomUtil.getArrayValue(assortRootItems);
@ -611,15 +605,11 @@ export class FenceService
rootItemBeingAdded.upd.StackObjectsCount = this.getSingleItemStackCount(itemDbDetails); rootItemBeingAdded.upd.StackObjectsCount = this.getSingleItemStackCount(itemDbDetails);
// Skip items already in the assort if it exists in the prevent duplicate list // Skip items already in the assort if it exists in the prevent duplicate list
if ( const existingItem = assorts.items.find((item) => item._tpl === rootItemBeingAdded._tpl);
assorts.items.some((item) => item._tpl === rootItemBeingAdded._tpl) if (this.itemShouldBeForceStacked(existingItem, itemDbDetails))
&& this.itemHelper.isOfBaseclasses(
rootItemBeingAdded._tpl,
this.traderConfig.fence.preventDuplicateOffersOfCategory,
)
)
{ {
i--; i--;
continue; continue;
} }
@ -629,20 +619,8 @@ export class FenceService
{ {
this.randomiseItemUpdProperties(itemDbDetails, rootItemBeingAdded); this.randomiseItemUpdProperties(itemDbDetails, rootItemBeingAdded);
} }
else
{
// Already have multi-stack, skip
if (this.multiStackItems[itemDbDetails._id])
{
i--;
continue;
}
// Flag item as added as multi-stack // Add mods to armors so they dont show as red in the trade screen
this.multiStackItems[itemDbDetails._id] = true;
}
// Need to add mods to armors so they dont show as red in the trade screen
if (this.itemHelper.itemRequiresSoftInserts(rootItemBeingAdded._tpl)) if (this.itemHelper.itemRequiresSoftInserts(rootItemBeingAdded._tpl))
{ {
this.randomiseArmorModDurability(desiredAssortItemAndChildrenClone, itemDbDetails); this.randomiseArmorModDurability(desiredAssortItemAndChildrenClone, itemDbDetails);
@ -664,6 +642,52 @@ export class FenceService
} }
} }
/**
* Should this item be forced into only 1 stack on fence
* @param existingItem Existing item from fence assort
* @param itemDbDetails Item we want to add db details
* @returns True item should be force stacked
*/
protected itemShouldBeForceStacked(existingItem: Item, itemDbDetails: ITemplateItem): boolean
{
// No existing item in assort
if (!existingItem)
{
return false;
}
// Item type not in config list
if (
!this.itemHelper.isOfBaseclasses(
itemDbDetails._id,
this.traderConfig.fence.preventDuplicateOffersOfCategory,
)
)
{
return false;
}
// Don't stack armored rigs
if (this.itemHelper.isOfBaseclass(itemDbDetails._id, BaseClasses.VEST) && itemDbDetails._props.Slots.length > 0)
{
return false;
}
// Don't stack meds (e.g. bandages) with unequal usages remaining
// TODO - Doesnt look beyond the first matching fence item, e.g. bandage A has 1 usage left = not a match, but bandage B has 2 uses, would have matched
if (
this.itemHelper.isOfBaseclasses(itemDbDetails._id, [BaseClasses.MEDICAL, BaseClasses.MEDKIT])
&& existingItem.upd.MedKit?.HpResource // null medkit object means its brand new/max resource
&& (itemDbDetails._props.MaxHpResource !== existingItem.upd.MedKit.HpResource)
)
{
return false;
}
// Passed all checks, will be forced stacked
return true;
}
/** /**
* Adjust price of item based on what is left to buy (resource/uses left) * Adjust price of item based on what is left to buy (resource/uses left)
* @param barterSchemes All barter scheme for item having price adjusted * @param barterSchemes All barter scheme for item having price adjusted
@ -987,7 +1011,14 @@ export class FenceService
} }
// Check for override in config, use values if exists // Check for override in config, use values if exists
const overrideValues = this.traderConfig.fence.itemStackSizeOverrideMinMax[itemDbDetails._id]; let overrideValues = this.traderConfig.fence.itemStackSizeOverrideMinMax[itemDbDetails._id];
if (overrideValues)
{
return this.randomUtil.getInt(overrideValues.min, overrideValues.max);
}
// Check for parent override
overrideValues = this.traderConfig.fence.itemStackSizeOverrideMinMax[itemDbDetails._parent];
if (overrideValues) if (overrideValues)
{ {
return this.randomUtil.getInt(overrideValues.min, overrideValues.max); return this.randomUtil.getInt(overrideValues.min, overrideValues.max);