diff --git a/project/assets/configs/bot.json b/project/assets/configs/bot.json index bfaa1ca9..e0e120de 100644 --- a/project/assets/configs/bot.json +++ b/project/assets/configs/bot.json @@ -1149,7 +1149,7 @@ "backpackLoot": { "weights": { "0": 3, - "1": 5, + "1": 7, "2": 12, "3": 20, "4": 8, diff --git a/project/assets/configs/pmc.json b/project/assets/configs/pmc.json index aee1e1c9..26e509a0 100644 --- a/project/assets/configs/pmc.json +++ b/project/assets/configs/pmc.json @@ -717,6 +717,40 @@ "value": 2500000 } ], + "lootItemLimitsRub": [ + { + "min": 46, + "max": 64, + "backpack": { + "min": 5000, + "max": 0 + }, + "pocket": { + "min": 5000, + "max": 0 + }, + "vest": { + "min": 5000, + "max": 0 + } + }, + { + "min": 65, + "max": 100, + "backpack": { + "min": 10000, + "max": 0 + }, + "pocket": { + "min": 10000, + "max": 0 + }, + "vest": { + "min": 10000, + "max": 0 + } + } + ], "maxPocketLootTotalRub": 50000, "maxVestLootTotalRub": 50000, "convertIntoPmcChance": { diff --git a/project/src/generators/BotLootGenerator.ts b/project/src/generators/BotLootGenerator.ts index 2565653f..9f28a754 100644 --- a/project/src/generators/BotLootGenerator.ts +++ b/project/src/generators/BotLootGenerator.ts @@ -16,7 +16,7 @@ import { ItemAddedResult } from "@spt/models/enums/ItemAddedResult"; import { LootCacheType } from "@spt/models/spt/bots/IBotLootCache"; import { IItemSpawnLimitSettings } from "@spt/models/spt/bots/IItemSpawnLimitSettings"; import { IBotConfig } from "@spt/models/spt/config/IBotConfig"; -import { IPmcConfig } from "@spt/models/spt/config/IPmcConfig"; +import { IMinMaxLootItemValue, IPmcConfig } from "@spt/models/spt/config/IPmcConfig"; import type { ILogger } from "@spt/models/spt/utils/ILogger"; import { ConfigServer } from "@spt/servers/ConfigServer"; import { BotLootCacheService } from "@spt/services/BotLootCacheService"; @@ -243,6 +243,8 @@ export class BotLootGenerator { containersIdFull, ); + const itemPriceLimits = this.getSingleItemLootPriceLimits(botLevel, isPmc); + // Backpack - generate loot if they have one if (containersBotHasAvailable.includes(EquipmentSlots.BACKPACK)) { // Add randomly generated weapon to PMC backpacks @@ -262,7 +264,13 @@ export class BotLootGenerator { const backpackLootRoubleTotal = this.getBackpackRoubleTotalByLevel(botLevel, isPmc); this.addLootFromPool( - this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.BACKPACK, botJsonTemplate), + this.botLootCacheService.getLootFromCache( + botRole, + isPmc, + LootCacheType.BACKPACK, + botJsonTemplate, + itemPriceLimits?.backpack, + ), [EquipmentSlots.BACKPACK], backpackLootCount, botInventory, @@ -278,7 +286,13 @@ export class BotLootGenerator { if (containersBotHasAvailable.includes(EquipmentSlots.TACTICAL_VEST)) { // Vest this.addLootFromPool( - this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.VEST, botJsonTemplate), + this.botLootCacheService.getLootFromCache( + botRole, + isPmc, + LootCacheType.VEST, + botJsonTemplate, + itemPriceLimits?.vest, + ), [EquipmentSlots.TACTICAL_VEST], vestLootCount, botInventory, @@ -292,7 +306,13 @@ export class BotLootGenerator { // Pockets this.addLootFromPool( - this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.POCKET, botJsonTemplate), + this.botLootCacheService.getLootFromCache( + botRole, + isPmc, + LootCacheType.POCKET, + botJsonTemplate, + itemPriceLimits?.pocket, + ), [EquipmentSlots.POCKETS], pocketLootCount, botInventory, @@ -333,12 +353,23 @@ export class BotLootGenerator { const matchingValue = this.pmcConfig.maxBackpackLootTotalRub.find( (minMaxValue) => botLevel >= minMaxValue.min && botLevel <= minMaxValue.max, ); - return matchingValue.value; + return matchingValue?.value; } return 0; } + protected getSingleItemLootPriceLimits(botLevel: number, isPmc: boolean): IMinMaxLootItemValue | undefined { + if (isPmc) { + const matchingValue = this.pmcConfig.lootItemLimitsRub.find( + (minMaxValue) => botLevel >= minMaxValue.min && botLevel <= minMaxValue.max, + ); + return matchingValue; + } + + return undefined; + } + /** * Get an array of the containers a bot has on them (pockets/backpack/vest) * @param botInventory Bot to check diff --git a/project/src/models/spt/config/IPmcConfig.ts b/project/src/models/spt/config/IPmcConfig.ts index b665cb5d..2d7a1b5f 100644 --- a/project/src/models/spt/config/IPmcConfig.ts +++ b/project/src/models/spt/config/IPmcConfig.ts @@ -35,6 +35,7 @@ export interface IPmcConfig extends IBaseConfig { /** What 'brain' does a PMC use, keyed by map and side (USEC/BEAR) key: map location, value: type for usec/bear */ pmcType: Record>>; maxBackpackLootTotalRub: IMinMaxLootValue[]; + lootItemLimitsRub: IMinMaxLootItemValue[]; maxPocketLootTotalRub: number; maxVestLootTotalRub: number; /** Percentage chance a bot from a wave is converted into a PMC, first key = map, second key = bot wildspawn type (assault/exusec), value: min+max chance to be converted */ @@ -80,3 +81,9 @@ export interface ISlotLootSettings { export interface IMinMaxLootValue extends MinMax { value: number; } + +export interface IMinMaxLootItemValue extends MinMax { + backpack: MinMax; + pocket: MinMax; + vest: MinMax; +} diff --git a/project/src/services/BotLootCacheService.ts b/project/src/services/BotLootCacheService.ts index e18766ac..dce38ed9 100644 --- a/project/src/services/BotLootCacheService.ts +++ b/project/src/services/BotLootCacheService.ts @@ -1,5 +1,6 @@ import { PMCLootGenerator } from "@spt/generators/PMCLootGenerator"; import { ItemHelper } from "@spt/helpers/ItemHelper"; +import { MinMax } from "@spt/models/common/MinMax"; import { IBotType } from "@spt/models/eft/common/tables/IBotType"; import { IProps, ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; import { BaseClasses } from "@spt/models/enums/BaseClasses"; @@ -40,6 +41,7 @@ export class BotLootCacheService { * @param isPmc is the bot a pmc * @param lootType what type of loot is needed (backpack/pocket/stim/vest etc) * @param botJsonTemplate Base json db file for the bot having its loot generated + * @param itemPriceMinMax OPTIONAL - min max limit of loot item price * @returns ITemplateItem array */ public getLootFromCache( @@ -47,6 +49,7 @@ export class BotLootCacheService { isPmc: boolean, lootType: LootCacheType, botJsonTemplate: IBotType, + itemPriceMinMax?: MinMax, ): Record { if (!this.botRoleExistsInCache(botRole)) { this.initCacheForBotRole(botRole); @@ -105,6 +108,27 @@ export class BotLootCacheService { break; } + if (itemPriceMinMax) { + const filteredResult = Object.entries(result).filter(([key, val]) => { + const itemPrice = this.itemHelper.getItemPrice(key); + if (itemPriceMinMax?.min && itemPriceMinMax?.max) { + return itemPrice >= itemPriceMinMax?.min && itemPrice <= itemPriceMinMax?.max; + } + + if (itemPriceMinMax?.min && !itemPriceMinMax?.max) { + return itemPrice >= itemPriceMinMax?.min; + } + + if (!itemPriceMinMax?.min && itemPriceMinMax?.max) { + return itemPrice <= itemPriceMinMax?.max; + } + + return false; + }); + + return this.cloner.clone(Object.fromEntries(filteredResult)); + } + return this.cloner.clone(result); }