0
0
mirror of https://github.com/sp-tarkov/server.git synced 2025-02-13 09:50:43 -05:00

Added ability to filter out PMC loot items from pool based on its value, configured via pmc.json/lootItemLimitsRub

This commit is contained in:
Chomp 2025-01-07 20:28:41 +00:00
parent 2d7fdc0dc2
commit 6a2afe2fa7
5 changed files with 102 additions and 6 deletions

View File

@ -1149,7 +1149,7 @@
"backpackLoot": {
"weights": {
"0": 3,
"1": 5,
"1": 7,
"2": 12,
"3": 20,
"4": 8,

View File

@ -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": {

View File

@ -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

View File

@ -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<string, Record<string, Record<string, number>>>;
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;
}

View File

@ -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<string, number> {
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);
}