Refactor handleScavCase() to use addItemToStash()

blacklist soft armor inserts from scavcase rewards
This commit is contained in:
Dev 2024-01-21 16:40:14 +00:00
parent 8e232e8250
commit c68c9a72fb
4 changed files with 77 additions and 61 deletions

View File

@ -20,7 +20,8 @@
"5448bf274bdc2dfc2f8b456a",
"5d52cc5ba4b9367408500062",
"5e997f0b86f7741ac73993e2",
"62f109593b54472778797866"
"62f109593b54472778797866",
"65649eb40bf0ed77b8044453"
],
"rewardItemBlacklist": [
"5ede4739e0350d05467f73e8",
@ -43,7 +44,6 @@
"63a0b2eabea67a6d93009e52",
"609e860ebd219504d8507525"
],
"moneyRewards": {
"moneyRewardChancePercent": 10,
"rubCount": {

View File

@ -946,39 +946,32 @@ export class HideoutController
// Create rewards for scav case
const scavCaseRewards = this.scavCaseRewardGenerator.generate(request.recipeId);
// Add scav case rewards to player profile
pmcData.Hideout.Production[prodId].Products = scavCaseRewards;
for (const itemWithChildren of scavCaseRewards)
{
const addToStashRequest: IAddItemDirectRequest = {
itemWithModsToAdd: itemWithChildren,
foundInRaid: true,
callback: null,
useSortingTable: false
}
this.inventoryHelper.addItemToStash(sessionID, addToStashRequest, pmcData, output);
if (output.warnings.length > 0)
{
const errorMessage = "Unable to give scavcase reward to player";
return this.httpResponse.appendErrorToOutput(output, errorMessage);
}
}
// Remove the old production from output object before its sent to client
delete output.profileChanges[sessionID].production[request.recipeId];
// Get array of item created + count of them after completing hideout craft
const itemsToAdd = pmcData.Hideout.Production[prodId].Products.map(
(x: { _tpl: string; upd?: { StackObjectsCount?: number; }; }) =>
{
const itemTpl = this.presetHelper.hasPreset(x._tpl)
? this.presetHelper.getDefaultPreset(x._tpl)._id
: x._tpl;
// Count of items crafted
const numOfItems = !x.upd?.StackObjectsCount ? 1 : x.upd.StackObjectsCount;
// eslint-disable-next-line @typescript-eslint/naming-convention
return { item_id: itemTpl, count: numOfItems };
},
);
const newReq = { items: itemsToAdd, tid: "ragfair" };
const callback = () =>
{
// Flag as complete - will be cleaned up later by hideoutController.update()
pmcData.Hideout.Production[prodId].sptIsComplete = true;
// Crafting complete, flag as such
// Crafting complete, flag
pmcData.Hideout.Production[prodId].inProgress = false;
};
// Add crafted item to player inventory
return this.inventoryHelper.addItem(pmcData, newReq, output, sessionID, callback, true);
return output;
}
/**

View File

@ -1,8 +1,9 @@
import { inject, injectable } from "tsyringe";
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
import { Product } from "@spt-aki/models/eft/common/tables/IBotBase";
import { Upd } from "@spt-aki/models/eft/common/tables/IItem";
import { Item, Upd } from "@spt-aki/models/eft/common/tables/IItem";
import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem";
import { IHideoutScavCase } from "@spt-aki/models/eft/hideout/IHideoutScavCase";
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
@ -19,6 +20,7 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import { ItemFilterService } from "@spt-aki/services/ItemFilterService";
import { RagfairPriceService } from "@spt-aki/services/RagfairPriceService";
import { HashUtil } from "@spt-aki/utils/HashUtil";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
/**
@ -34,8 +36,10 @@ export class ScavCaseRewardGenerator
constructor(
@inject("WinstonLogger") protected logger: ILogger,
@inject("RandomUtil") protected randomUtil: RandomUtil,
@inject("JsonUtil") protected jsonUtil: JsonUtil,
@inject("HashUtil") protected hashUtil: HashUtil,
@inject("ItemHelper") protected itemHelper: ItemHelper,
@inject("PresetHelper") protected presetHelper: PresetHelper,
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService,
@inject("ItemFilterService") protected itemFilterService: ItemFilterService,
@ -50,7 +54,7 @@ export class ScavCaseRewardGenerator
* @param recipeId recipe of the scav case craft
* @returns Product array
*/
public generate(recipeId: string): Product[]
public generate(recipeId: string): Item[][]
{
this.cacheDbItems();
@ -274,44 +278,63 @@ export class ScavCaseRewardGenerator
* @param rewardItems items to convert
* @returns Product array
*/
protected randomiseContainerItemRewards(rewardItems: ITemplateItem[], rarity: string): Product[]
protected randomiseContainerItemRewards(rewardItems: ITemplateItem[], rarity: string): Item[][]
{
const result: Product[] = [];
for (const item of rewardItems)
/** Each array is an item + children */
const result: Item[][] = [];
for (const rewardItemDb of rewardItems)
{
const resultItem = { _id: this.hashUtil.generate(), _tpl: item._id, upd: undefined };
let resultItem: Item[] = [
{
_id: this.hashUtil.generate(),
_tpl: rewardItemDb._id,
upd: undefined
}
];
const rootItem = resultItem[0];
this.addStackCountToAmmoAndMoney(item, resultItem, rarity);
// Clean up upd object if it wasn't used
if (!resultItem.upd)
if (this.itemHelper.isOfBaseclass(rewardItemDb._id, BaseClasses.AMMO_BOX))
{
delete resultItem.upd;
this.itemHelper.addCartridgesToAmmoBox(resultItem, rewardItemDb);
}
// Armor or weapon = use default preset from globals.json
else if (this.itemHelper.armorItemCanHoldMods(rewardItemDb._id)
|| this.itemHelper.isOfBaseclass(rewardItemDb._id, BaseClasses.WEAPON))
{
const preset = this.presetHelper.getDefaultPreset(rewardItemDb._id);
if (!preset)
{
this.logger.warning(`No preset for item: ${rewardItemDb._id} ${rewardItemDb._name}, skipping`);
continue;
}
result.push(resultItem);
// Ensure preset has unique ids and is cloned so we don't alter the preset data stored in memory
const presetAndMods: Item[] = this.itemHelper.replaceIDs(
null,
this.jsonUtil.clone(preset._items),
);
this.itemHelper.remapRootItemId(presetAndMods);
resultItem = presetAndMods;
}
else if (this.itemHelper.isOfBaseclasses(rewardItemDb._id, [BaseClasses.AMMO, BaseClasses.MONEY]))
{
rootItem.upd = { StackObjectsCount: this.getRandomAmountRewardForScavCase(rewardItemDb, rarity) };
}
// Clean up upd object if it wasn't used
if (!rootItem.upd)
{
delete rootItem.upd;
}
result.push(resultItem)
}
return result;
}
/**
* Add a randomised stack count to ammo or money items
* @param item money or ammo item
* @param resultItem money or ammo item with a randomise stack size
*/
protected addStackCountToAmmoAndMoney(
item: ITemplateItem,
resultItem: { _id: string; _tpl: string; upd: Upd; },
rarity: string,
): void
{
if (item._parent === BaseClasses.AMMO || item._parent === BaseClasses.MONEY)
{
resultItem.upd = { StackObjectsCount: this.getRandomAmountRewardForScavCase(item, rarity) };
}
}
/**
* @param dbItems all items from the items.json
* @param itemFilters controls how the dbItems will be filtered and returned (handbook price)

View File

@ -1271,15 +1271,15 @@ export class ItemHelper
continue;
}
const moditemToAdd = {
const modItemToAdd = {
_id: this.hashUtil.generate(),
_tpl: chosenTpl,
parentId: result[0]._id,
slotId: slot._name
};
result.push(moditemToAdd);
result.push(modItemToAdd);
const modItemDbDetails = this.getItem(moditemToAdd._tpl)[1];
const modItemDbDetails = this.getItem(modItemToAdd._tpl)[1];
// Include conflicting items of newly added mod in pool to be used for next mod choice
// biome-ignore lint/complexity/noForEach: <explanation>