Finalise fence changes
This commit is contained in:
parent
42b915990e
commit
80fdaf65e6
@ -39,7 +39,7 @@
|
||||
"discountOptions": {
|
||||
"assortSize": 50,
|
||||
"itemPriceMult": 0.8,
|
||||
"presetPriceMult": 1.5
|
||||
"presetPriceMult": 1.3
|
||||
},
|
||||
"partialRefreshTimeSeconds": 240,
|
||||
"partialRefreshChangePercent": 15,
|
||||
@ -168,7 +168,11 @@
|
||||
"62f10b79e7ee985f386b2f47",
|
||||
"633ffb5d419dbf4bea7004c6",
|
||||
"543be5dd4bdc2deb348b4569",
|
||||
"65649eb40bf0ed77b8044453"
|
||||
"65649eb40bf0ed77b8044453",
|
||||
"5448e54d4bdc2dcc718b4568",
|
||||
"5a341c4086f77401f2541505",
|
||||
"5422acb9af1c889c16000029",
|
||||
"5448e5284bdc2dcb718b4567"
|
||||
],
|
||||
"coopExtractGift": {
|
||||
"sendGift": true,
|
||||
|
@ -40,7 +40,7 @@ export class FenceBaseAssortGenerator
|
||||
}
|
||||
|
||||
/**
|
||||
* Create base fence assorts dynamically and store in db
|
||||
* Create base fence assorts dynamically and store in memory
|
||||
*/
|
||||
public generateFenceBaseAssorts(): void
|
||||
{
|
||||
@ -84,17 +84,9 @@ export class FenceBaseAssortGenerator
|
||||
_tpl: rootItemDb._id,
|
||||
parentId: "hideout",
|
||||
slotId: "hideout",
|
||||
upd: { StackObjectsCount: 9999999, UnlimitedCount: true },
|
||||
upd: { StackObjectsCount: 9999999 },
|
||||
}];
|
||||
|
||||
// Need to add mods to armors so they dont show as red in the trade screen
|
||||
let price = this.handbookHelper.getTemplatePrice(rootItemDb._id);
|
||||
if (this.itemHelper.itemRequiresSoftInserts(rootItemDb._id))
|
||||
{
|
||||
this.addChildrenToArmorModSlots(itemWithChildrenToAdd, rootItemDb);
|
||||
price = this.getHandbookItemPriceWithChildren(itemWithChildrenToAdd);
|
||||
}
|
||||
|
||||
// Ensure IDs are unique
|
||||
this.itemHelper.remapRootItemId(itemWithChildrenToAdd);
|
||||
if (itemWithChildrenToAdd.length > 1)
|
||||
@ -136,6 +128,7 @@ export class FenceBaseAssortGenerator
|
||||
this.jsonUtil.clone(defaultPreset._items),
|
||||
);
|
||||
|
||||
// Find root item and add some properties to it
|
||||
for (let i = 0; i < presetAndMods.length; i++)
|
||||
{
|
||||
const mod = presetAndMods[i];
|
||||
@ -143,13 +136,10 @@ export class FenceBaseAssortGenerator
|
||||
// Build root Item info
|
||||
if (!("parentId" in mod))
|
||||
{
|
||||
mod._id = presetAndMods[0]._id;
|
||||
mod.parentId = "hideout";
|
||||
mod.slotId = "hideout";
|
||||
mod.upd = {
|
||||
UnlimitedCount: false,
|
||||
StackObjectsCount: 1,
|
||||
BuyRestrictionCurrent: 0,
|
||||
sptPresetId: defaultPreset._id, // Store preset id here so we can check it later to prevent preset dupes
|
||||
};
|
||||
|
||||
@ -158,21 +148,15 @@ export class FenceBaseAssortGenerator
|
||||
}
|
||||
}
|
||||
|
||||
const presetDbItem = this.itemHelper.getItem(presetAndMods[0]._tpl)[1];
|
||||
|
||||
// Add constructed preset to assorts
|
||||
baseFenceAssort.items.push(...presetAndMods);
|
||||
|
||||
// Calculate preset price
|
||||
let rub = 0;
|
||||
for (const it of presetAndMods)
|
||||
{
|
||||
rub += this.handbookHelper.getTemplatePrice(it._tpl);
|
||||
}
|
||||
const price = this.getHandbookItemPriceWithChildren(presetAndMods);
|
||||
|
||||
// Multiply weapon+mods rouble price by multipler in config
|
||||
baseFenceAssort.barter_scheme[presetAndMods[0]._id] = [[]];
|
||||
baseFenceAssort.barter_scheme[presetAndMods[0]._id][0][0] = { _tpl: Money.ROUBLES, count: Math.round(rub) };
|
||||
baseFenceAssort.barter_scheme[presetAndMods[0]._id][0][0] = { _tpl: Money.ROUBLES, count: Math.round(price) * this.traderConfig.fence.presetPriceMult };
|
||||
|
||||
baseFenceAssort.loyal_level_items[presetAndMods[0]._id] = 1;
|
||||
}
|
||||
|
@ -4,14 +4,13 @@ import { HandbookHelper } from "@spt-aki/helpers/HandbookHelper";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
||||
import { MinMax } from "@spt-aki/models/common/MinMax";
|
||||
import { IFenceLevel, IPreset } from "@spt-aki/models/eft/common/IGlobals";
|
||||
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 { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
|
||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||
import { Money } from "@spt-aki/models/enums/Money";
|
||||
import { Traders } from "@spt-aki/models/enums/Traders";
|
||||
import { ITraderConfig } from "@spt-aki/models/spt/config/ITraderConfig";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
@ -33,7 +32,7 @@ export class FenceService
|
||||
{
|
||||
/** Main assorts you see at all rep levels */
|
||||
protected fenceAssort: ITraderAssort = undefined;
|
||||
/** Assorts shown on a separte tab when you max out fence rep */
|
||||
/** Assorts shown on a separate tab when you max out fence rep */
|
||||
protected fenceDiscountAssort: ITraderAssort = undefined;
|
||||
protected traderConfig: ITraderConfig;
|
||||
protected nextMiniRefreshTimestamp: number;
|
||||
@ -67,11 +66,11 @@ export class FenceService
|
||||
|
||||
/**
|
||||
* Replace high rep level fence assort with new assort
|
||||
* @param assort New assorts to replace old with
|
||||
* @param discountAssort New assorts to replace old with
|
||||
*/
|
||||
public setFenceDiscountAssort(assort: ITraderAssort): void
|
||||
public setFenceDiscountAssort(discountAssort: ITraderAssort): void
|
||||
{
|
||||
this.fenceDiscountAssort = assort;
|
||||
this.fenceDiscountAssort = discountAssort;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -238,8 +237,8 @@ export class FenceService
|
||||
|
||||
itemCountToReplace = this.getCountOfItemsToGenerate(itemCountToReplace);
|
||||
|
||||
const newItems = this.createBaseTraderAssortItem();
|
||||
const newDiscountItems = this.createBaseTraderAssortItem();
|
||||
const newItems = this.createFenceAssortSkeleton();
|
||||
const newDiscountItems = this.createFenceAssortSkeleton();
|
||||
this.createAssorts(itemCountToReplace, newItems, 1);
|
||||
this.createAssorts(discountItemCountToReplace, newDiscountItems, 2);
|
||||
|
||||
@ -366,21 +365,22 @@ export class FenceService
|
||||
|
||||
/**
|
||||
* Create trader assorts for fence and store in fenceService cache
|
||||
* Uses fence base cache generatedon server start as a base
|
||||
*/
|
||||
public generateFenceAssorts(): void
|
||||
{
|
||||
// Reset refresh time now assorts are being generated
|
||||
this.incrementPartialRefreshTime();
|
||||
|
||||
const assorts = this.createBaseTraderAssortItem();
|
||||
const discountAssorts = this.createBaseTraderAssortItem();
|
||||
const assorts = this.createFenceAssortSkeleton();
|
||||
const discountAssorts = this.createFenceAssortSkeleton();
|
||||
// Create basic fence assort
|
||||
this.createAssorts(this.traderConfig.fence.assortSize, assorts, 1);
|
||||
|
||||
// Create level 2 assorts accessible at rep level 6
|
||||
this.createAssorts(this.traderConfig.fence.discountOptions.assortSize, discountAssorts, 2);
|
||||
|
||||
// store in fenceAssort class property
|
||||
// store in fenceAssort class properties
|
||||
this.setFenceAssort(assorts);
|
||||
this.setFenceDiscountAssort(discountAssorts);
|
||||
}
|
||||
@ -389,7 +389,7 @@ export class FenceService
|
||||
* Create skeleton to hold assort items
|
||||
* @returns ITraderAssort object
|
||||
*/
|
||||
protected createBaseTraderAssortItem(): ITraderAssort
|
||||
protected createFenceAssortSkeleton(): ITraderAssort
|
||||
{
|
||||
return {
|
||||
items: [],
|
||||
@ -414,38 +414,7 @@ export class FenceService
|
||||
// Add presets
|
||||
const maxPresetCount = Math.round(assortCount * (this.traderConfig.fence.maxPresetsPercent / 100));
|
||||
const randomisedPresetCount = this.randomUtil.getInt(0, maxPresetCount);
|
||||
this.addPresetsToAssort(randomisedPresetCount, assorts, baseFenceAssort);
|
||||
}
|
||||
|
||||
protected addPresetsToAssort(desiredPresetCount: number, assorts: ITraderAssort, baseFenceAssort: ITraderAssort): void
|
||||
{
|
||||
let presetsAddedCount = 0;
|
||||
if (desiredPresetCount <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const presetRootItems = baseFenceAssort.items.filter(item => item.upd?.sptPresetId);
|
||||
while (presetsAddedCount < desiredPresetCount)
|
||||
{
|
||||
const randomPresetRoot = this.randomUtil.getArrayValue(presetRootItems);
|
||||
const rootItemDb = this.itemHelper.getItem(randomPresetRoot._tpl)[1];
|
||||
const presetWithChildrenClone = this.jsonUtil.clone(this.itemHelper.findAndReturnChildrenAsItems(baseFenceAssort.items, randomPresetRoot._id));
|
||||
|
||||
this.removeRandomModsOfItem(presetWithChildrenClone);
|
||||
|
||||
// Need to add mods to armors so they dont show as red in the trade screen
|
||||
if (this.itemHelper.itemRequiresSoftInserts(randomPresetRoot._tpl))
|
||||
{
|
||||
this.randomiseArmorModDurability(presetWithChildrenClone, rootItemDb);
|
||||
}
|
||||
|
||||
assorts.items.push(...presetWithChildrenClone);
|
||||
assorts.barter_scheme[randomPresetRoot._id] = baseFenceAssort.barter_scheme[randomPresetRoot._id];
|
||||
assorts.loyal_level_items[randomPresetRoot._id] = baseFenceAssort.loyal_level_items[randomPresetRoot._id];
|
||||
|
||||
presetsAddedCount++;
|
||||
}
|
||||
this.addPresetsToAssort(randomisedPresetCount, assorts, baseFenceAssort, loyaltyLevel);
|
||||
}
|
||||
|
||||
protected addItemAssorts(
|
||||
@ -457,7 +426,7 @@ export class FenceService
|
||||
): void
|
||||
{
|
||||
const priceLimits = this.traderConfig.fence.itemCategoryRoublePriceLimit;
|
||||
const assortRootItems = fenceAssort.items.filter(x => x.parentId === "hideout");
|
||||
const assortRootItems = fenceAssort.items.filter(x => x.parentId === "hideout" && !x.upd?.sptPresetId);
|
||||
for (let i = 0; i < assortCount; i++)
|
||||
{
|
||||
const chosenAssortRoot = this.randomUtil.getArrayValue(assortRootItems);
|
||||
@ -500,12 +469,16 @@ export class FenceService
|
||||
itemLimitCount.current++;
|
||||
}
|
||||
|
||||
// MUST randomise Ids as its possible to add the same base fence assort twice = duplicate IDs = dead client
|
||||
this.itemHelper.remapRootItemId(desiredAssortItemAndChildrenClone);
|
||||
this.itemHelper.replaceIDs(null, desiredAssortItemAndChildrenClone);
|
||||
|
||||
const rootItemBeingAdded = desiredAssortItemAndChildrenClone[0];
|
||||
this.randomiseItemUpdProperties(itemDbDetails, rootItemBeingAdded);
|
||||
|
||||
rootItemBeingAdded.upd.StackObjectsCount = this.getSingleItemStackCount(itemDbDetails);
|
||||
rootItemBeingAdded.upd.BuyRestrictionCurrent = 0;
|
||||
rootItemBeingAdded.upd.UnlimitedCount = false;
|
||||
//rootItemBeingAdded.upd.BuyRestrictionCurrent = 0;
|
||||
//rootItemBeingAdded.upd.UnlimitedCount = false;
|
||||
|
||||
// Need to add mods to armors so they dont show as red in the trade screen
|
||||
if (this.itemHelper.itemRequiresSoftInserts(rootItemBeingAdded._tpl))
|
||||
@ -519,6 +492,55 @@ export class FenceService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find presets in base fence assort and add desired number to 'assorts' parameter
|
||||
* @param desiredPresetCount
|
||||
* @param assorts
|
||||
* @param baseFenceAssort
|
||||
* @param loyaltyLevel Which loyalty level is required to see/buy item
|
||||
*/
|
||||
protected addPresetsToAssort(desiredPresetCount: number, assorts: ITraderAssort, baseFenceAssort: ITraderAssort, loyaltyLevel: number): void
|
||||
{
|
||||
let presetsAddedCount = 0;
|
||||
if (desiredPresetCount <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const presetRootItems = baseFenceAssort.items.filter(item => item.upd?.sptPresetId);
|
||||
while (presetsAddedCount < desiredPresetCount)
|
||||
{
|
||||
const randomPresetRoot = this.randomUtil.getArrayValue(presetRootItems);
|
||||
const rootItemDb = this.itemHelper.getItem(randomPresetRoot._tpl)[1];
|
||||
const presetWithChildrenClone = this.jsonUtil.clone(this.itemHelper.findAndReturnChildrenAsItems(baseFenceAssort.items, randomPresetRoot._id));
|
||||
|
||||
// Need to add mods to armors so they dont show as red in the trade screen
|
||||
if (this.itemHelper.itemRequiresSoftInserts(randomPresetRoot._tpl))
|
||||
{
|
||||
this.randomiseArmorModDurability(presetWithChildrenClone, rootItemDb);
|
||||
}
|
||||
|
||||
if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.WEAPON))
|
||||
{
|
||||
this.randomiseItemUpdProperties(rootItemDb, presetWithChildrenClone[0]);
|
||||
}
|
||||
|
||||
this.removeRandomModsOfItem(presetWithChildrenClone);
|
||||
|
||||
// MUST randomise Ids as its possible to add the same base fence assort twice = duplicate IDs = dead client
|
||||
this.itemHelper.remapRootItemId(presetWithChildrenClone);
|
||||
this.itemHelper.replaceIDs(null, presetWithChildrenClone);
|
||||
|
||||
assorts.items.push(...presetWithChildrenClone);
|
||||
|
||||
// Must be careful to use correct id as the item has had its IDs regenerated
|
||||
assorts.barter_scheme[presetWithChildrenClone[0]._id] = baseFenceAssort.barter_scheme[randomPresetRoot._id];
|
||||
assorts.loyal_level_items[presetWithChildrenClone[0]._id] = loyaltyLevel;
|
||||
|
||||
presetsAddedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust plate / soft insert durability values
|
||||
* @param armor Armor item array to add mods into
|
||||
@ -552,7 +574,7 @@ export class FenceService
|
||||
}
|
||||
|
||||
// Find items mod to apply dura changes to
|
||||
const modItemToAdjust = armor.find(mod => mod.slotId === requiredSlot._name);
|
||||
const modItemToAdjust = armor.find(mod => mod.slotId.toLowerCase() === requiredSlot._name.toLowerCase());
|
||||
if (!modItemToAdjust.upd)
|
||||
{
|
||||
modItemToAdjust.upd = {}
|
||||
@ -604,7 +626,7 @@ export class FenceService
|
||||
this.traderConfig.fence.armorMaxDurabilityPercentMinMax);
|
||||
|
||||
// Find items mod to apply dura changes to
|
||||
const modItemToAdjust = armor.find(mod => mod.slotId === plateSlot._name);
|
||||
const modItemToAdjust = armor.find(mod => mod.slotId.toLowerCase() === plateSlot._name.toLowerCase());
|
||||
if (!modItemToAdjust.upd)
|
||||
{
|
||||
modItemToAdjust.upd = {}
|
||||
@ -649,90 +671,6 @@ export class FenceService
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add weapon/armor presets to fence
|
||||
* @param assortCount how many assorts to add to assorts
|
||||
* @param defaultPresets a dictionary of default weapon presets
|
||||
* @param assorts Trader assort object to add preset to
|
||||
* @param loyaltyLevel loyalty level to requre item at
|
||||
*/
|
||||
protected addPresets(
|
||||
desiredPresetCount: number,
|
||||
defaultPresets: Record<string, IPreset>,
|
||||
assorts: ITraderAssort,
|
||||
loyaltyLevel: number,
|
||||
): void
|
||||
{
|
||||
let presetCount = 0;
|
||||
const presetKeys = Object.keys(defaultPresets);
|
||||
for (let index = 0; index < desiredPresetCount; index++)
|
||||
{
|
||||
const presetId = presetKeys[this.randomUtil.getInt(0, presetKeys.length - 1)];
|
||||
const preset = defaultPresets[presetId];
|
||||
|
||||
// Check we're under preset limit
|
||||
if (presetCount > desiredPresetCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip presets we've already added
|
||||
if (assorts.items.some((i) => i.upd && i.upd.sptPresetId === preset._id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Construct preset + mods
|
||||
const presetAndMods: Item[] = this.itemHelper.replaceIDs(
|
||||
null,
|
||||
this.jsonUtil.clone(preset._items),
|
||||
);
|
||||
this.removeRandomModsOfItem(presetAndMods);
|
||||
for (let i = 0; i < presetAndMods.length; i++)
|
||||
{
|
||||
const mod = presetAndMods[i];
|
||||
|
||||
// Build root Item info
|
||||
if (!("parentId" in mod))
|
||||
{
|
||||
mod._id = presetAndMods[0]._id;
|
||||
mod.parentId = "hideout";
|
||||
mod.slotId = "hideout";
|
||||
mod.upd = {
|
||||
UnlimitedCount: false,
|
||||
StackObjectsCount: 1,
|
||||
BuyRestrictionCurrent: 0,
|
||||
sptPresetId: preset._id, // Store preset id here so we can check it later to prevent preset dupes
|
||||
};
|
||||
|
||||
// Updated root item, exit loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const presetDbItem = this.itemHelper.getItem(presetAndMods[0]._tpl)[1];
|
||||
this.randomiseItemUpdProperties(presetDbItem, presetAndMods[0]);
|
||||
|
||||
// Add constructed preset to assorts
|
||||
assorts.items.push(...presetAndMods);
|
||||
|
||||
// Calculate preset price
|
||||
let rub = 0;
|
||||
for (const it of presetAndMods)
|
||||
{
|
||||
rub += this.handbookHelper.getTemplatePrice(it._tpl);
|
||||
}
|
||||
|
||||
// Multiply weapon+mods rouble price by multipler in config
|
||||
assorts.barter_scheme[presetAndMods[0]._id] = [[]];
|
||||
assorts.barter_scheme[presetAndMods[0]._id][0][0] = { _tpl: Money.ROUBLES, count: Math.round(rub) };
|
||||
|
||||
assorts.loyal_level_items[presetAndMods[0]._id] = loyaltyLevel;
|
||||
|
||||
presetCount++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove parts of a weapon prior to being listed on flea
|
||||
* @param itemAndMods Weapon to remove parts from
|
||||
|
Loading…
Reference in New Issue
Block a user