Improve emulation of fence item prices
Specifically medical items with < 100% usages remaining
This commit is contained in:
parent
75584633c3
commit
7406ee389e
@ -8,7 +8,7 @@ import { IFenceLevel } from "@spt-aki/models/eft/common/IGlobals";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
import { Item, Repairable } from "@spt-aki/models/eft/common/tables/IItem";
|
||||
import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem";
|
||||
import { ITraderAssort } from "@spt-aki/models/eft/common/tables/ITrader";
|
||||
import { IBarterScheme, ITraderAssort } from "@spt-aki/models/eft/common/tables/ITrader";
|
||||
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
|
||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||
import { Traders } from "@spt-aki/models/enums/Traders";
|
||||
@ -99,17 +99,13 @@ export class FenceService
|
||||
|
||||
// Clone assorts so we can adjust prices before sending to client
|
||||
const assort = this.jsonUtil.clone(this.fenceAssort);
|
||||
this.adjustAssortItemPrices(
|
||||
assort,
|
||||
this.getFenceInfo(pmcProfile).PriceModifier,
|
||||
this.traderConfig.fence.presetPriceMult,
|
||||
);
|
||||
this.adjustAssortItemPricesByConfigMultiplier(assort, 1, this.traderConfig.fence.presetPriceMult);
|
||||
|
||||
// merge normal fence assorts + discount assorts if player standing is large enough
|
||||
if (pmcProfile.TradersInfo[Traders.FENCE].standing >= 6)
|
||||
{
|
||||
const discountAssort = this.jsonUtil.clone(this.fenceDiscountAssort);
|
||||
this.adjustAssortItemPrices(
|
||||
this.adjustAssortItemPricesByConfigMultiplier(
|
||||
discountAssort,
|
||||
this.traderConfig.fence.discountOptions.itemPriceMult,
|
||||
this.traderConfig.fence.discountOptions.presetPriceMult,
|
||||
@ -128,7 +124,11 @@ export class FenceService
|
||||
* @param itemMultipler multipler to use on items
|
||||
* @param presetMultiplier preset multipler to use on presets
|
||||
*/
|
||||
protected adjustAssortItemPrices(assort: ITraderAssort, itemMultipler: number, presetMultiplier: number): void
|
||||
protected adjustAssortItemPricesByConfigMultiplier(
|
||||
assort: ITraderAssort,
|
||||
itemMultipler: number,
|
||||
presetMultiplier: number,
|
||||
): void
|
||||
{
|
||||
for (const item of assort.items)
|
||||
{
|
||||
@ -200,13 +200,6 @@ export class FenceService
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Adjust price based on durability
|
||||
if (item.upd?.Repairable)
|
||||
{
|
||||
const itemQualityModifier = this.itemHelper.getItemQualityModifier(item);
|
||||
assort.barter_scheme[item._id][0][0].count *= itemQualityModifier;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -543,20 +536,22 @@ export class FenceService
|
||||
* Add item assorts to existing assort data
|
||||
* @param assortCount Number to add
|
||||
* @param assorts Assorts data to add to
|
||||
* @param baseFenceAssort Base data to draw from
|
||||
* @param baseFenceAssortClone Base data to draw from
|
||||
* @param itemTypeLimits
|
||||
* @param loyaltyLevel Loyalty level to set new item to
|
||||
*/
|
||||
protected addItemAssorts(
|
||||
assortCount: number,
|
||||
assorts: ITraderAssort,
|
||||
baseFenceAssort: ITraderAssort,
|
||||
baseFenceAssortClone: ITraderAssort,
|
||||
itemTypeLimits: Record<string, { current: number; max: number; }>,
|
||||
loyaltyLevel: number,
|
||||
): void
|
||||
{
|
||||
const priceLimits = this.traderConfig.fence.itemCategoryRoublePriceLimit;
|
||||
const assortRootItems = baseFenceAssort.items.filter((x) => x.parentId === "hideout" && !x.upd?.sptPresetId);
|
||||
const assortRootItems = baseFenceAssortClone.items.filter((x) =>
|
||||
x.parentId === "hideout" && !x.upd?.sptPresetId
|
||||
);
|
||||
|
||||
// Clear cache of multi-stack items
|
||||
this.multiStackItems = {};
|
||||
@ -573,7 +568,7 @@ export class FenceService
|
||||
continue;
|
||||
}
|
||||
let desiredAssortItemAndChildrenClone = this.jsonUtil.clone(
|
||||
this.itemHelper.findAndReturnChildrenAsItems(baseFenceAssort.items, chosenBaseAssortRoot._id),
|
||||
this.itemHelper.findAndReturnChildrenAsItems(baseFenceAssortClone.items, chosenBaseAssortRoot._id),
|
||||
);
|
||||
|
||||
const itemDbDetails = this.itemHelper.getItem(chosenBaseAssortRoot._tpl)[1];
|
||||
@ -587,7 +582,7 @@ export class FenceService
|
||||
|
||||
const itemIsPreset = this.presetHelper.isPreset(chosenBaseAssortRoot._id);
|
||||
|
||||
const price = baseFenceAssort.barter_scheme[chosenBaseAssortRoot._id][0][0].count;
|
||||
const price = baseFenceAssortClone.barter_scheme[chosenBaseAssortRoot._id][0][0].count;
|
||||
if (price === 0 || (price === 1 && !itemIsPreset) || price === 100)
|
||||
{
|
||||
// Don't allow "special" items / presets
|
||||
@ -619,7 +614,8 @@ export class FenceService
|
||||
// rootItemBeingAdded.upd.UnlimitedCount = false;
|
||||
|
||||
// Only randomise single items
|
||||
if (rootItemBeingAdded.upd.StackObjectsCount === 1)
|
||||
const isSingleStack = rootItemBeingAdded.upd.StackObjectsCount === 1;
|
||||
if (isSingleStack)
|
||||
{
|
||||
this.randomiseItemUpdProperties(itemDbDetails, rootItemBeingAdded);
|
||||
}
|
||||
@ -632,7 +628,7 @@ export class FenceService
|
||||
continue;
|
||||
}
|
||||
|
||||
// Flag item as added as multi stack
|
||||
// Flag item as added as multi-stack
|
||||
this.multiStackItems[itemDbDetails._id] = true;
|
||||
}
|
||||
|
||||
@ -643,11 +639,63 @@ export class FenceService
|
||||
}
|
||||
|
||||
assorts.items.push(...desiredAssortItemAndChildrenClone);
|
||||
assorts.barter_scheme[rootItemBeingAdded._id] = baseFenceAssort.barter_scheme[chosenBaseAssortRoot._id];
|
||||
|
||||
assorts.barter_scheme[rootItemBeingAdded._id] = this.jsonUtil.clone(
|
||||
baseFenceAssortClone.barter_scheme[chosenBaseAssortRoot._id],
|
||||
);
|
||||
|
||||
// Only adjust item price by quality for solo items, enver multi-stack
|
||||
if (isSingleStack)
|
||||
{
|
||||
this.adjustItemPriceByQuality(assorts.barter_scheme, rootItemBeingAdded, itemDbDetails);
|
||||
}
|
||||
|
||||
assorts.loyal_level_items[rootItemBeingAdded._id] = loyaltyLevel;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 itemRoot Root item having price adjusted
|
||||
* @param itemTemplate Db template of item
|
||||
*/
|
||||
protected adjustItemPriceByQuality(
|
||||
barterSchemes: Record<string, IBarterScheme[][]>,
|
||||
itemRoot: Item,
|
||||
itemTemplate: ITemplateItem,
|
||||
): void
|
||||
{
|
||||
// Healing items
|
||||
if (itemRoot.upd?.MedKit)
|
||||
{
|
||||
const itemTotalMax = itemTemplate._props.MaxHpResource;
|
||||
const current = itemRoot.upd.MedKit.HpResource;
|
||||
|
||||
// Current and max match, no adjustment necessary
|
||||
if (itemTotalMax === current)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const multipler = current / itemTotalMax;
|
||||
|
||||
// Multiply item cost by desired multiplier
|
||||
const basePrice = barterSchemes[itemRoot._id][0][0].count;
|
||||
barterSchemes[itemRoot._id][0][0].count = Math.round(basePrice * multipler);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Adjust price based on durability
|
||||
if (itemRoot.upd?.Repairable)
|
||||
{
|
||||
const itemQualityModifier = this.itemHelper.getItemQualityModifier(itemRoot);
|
||||
const basePrice = barterSchemes[itemRoot._id][0][0].count;
|
||||
barterSchemes[itemRoot._id][0][0].count = Math.round(basePrice * itemQualityModifier);
|
||||
}
|
||||
}
|
||||
|
||||
protected getMatchingItemLimit(
|
||||
itemTypeLimits: Record<string, { current: number; max: number; }>,
|
||||
itemTpl: string,
|
||||
|
Loading…
Reference in New Issue
Block a user