Feature: Add ability to whitelist items inside each bots generation object + filter per bot level inside bot.json equipment.randomisation section (!73)

(cherry picked from commit 253b4d0120db8245e6c2e863ab7d2fbdc5196128)

Co-authored-by: Dev <dev@noreply.dev.sp-tarkov.com>
Reviewed-on: https://dev.sp-tarkov.com/SPT-AKI/Server/pulls/73
This commit is contained in:
chomp 2023-03-17 18:20:16 +00:00
parent 611b63a4cd
commit ed4dfc201d
9 changed files with 120 additions and 71 deletions

View File

@ -454,7 +454,12 @@
}, },
"grenades": { "grenades": {
"min": 0, "min": 0,
"max": 1 "max": 1,
"whitelist": [
"5710c24ad2720bc3458b45a3",
"58d3db5386f77426186285a0",
"5448be9a4bdc2dfd2f8b456a"
]
}, },
"healing": { "healing": {
"min": 0, "min": 0,

View File

@ -2396,31 +2396,38 @@
"items": { "items": {
"drugs": { "drugs": {
"max": 2, "max": 2,
"min": 0 "min": 0,
"whitelist": []
}, },
"grenades": { "grenades": {
"max": 3, "max": 3,
"min": 0 "min": 0,
"whitelist": []
}, },
"healing": { "healing": {
"max": 3, "max": 3,
"min": 1 "min": 1,
"whitelist": []
}, },
"looseLoot": { "looseLoot": {
"max": 23, "max": 23,
"min": 0 "min": 0,
"whitelist": []
}, },
"magazines": { "magazines": {
"max": 4, "max": 4,
"min": 2 "min": 2,
"whitelist": []
}, },
"specialItems": { "specialItems": {
"max": 0, "max": 0,
"min": 0 "min": 0,
"whitelist": []
}, },
"stims": { "stims": {
"max": 1, "max": 1,
"min": 0 "min": 0,
"whitelist": []
} }
} }
}, },

View File

@ -2417,31 +2417,38 @@
"items": { "items": {
"drugs": { "drugs": {
"max": 2, "max": 2,
"min": 0 "min": 0,
"whitelist": []
}, },
"grenades": { "grenades": {
"max": 3, "max": 3,
"min": 0 "min": 0,
"whitelist": []
}, },
"healing": { "healing": {
"max": 3, "max": 3,
"min": 1 "min": 1,
"whitelist": []
}, },
"looseLoot": { "looseLoot": {
"max": 23, "max": 23,
"min": 0 "min": 0,
"whitelist": []
}, },
"magazines": { "magazines": {
"max": 4, "max": 4,
"min": 2 "min": 2,
"whitelist": []
}, },
"specialItems": { "specialItems": {
"max": 0, "max": 0,
"min": 0 "min": 0,
"whitelist": []
}, },
"stims": { "stims": {
"max": 1, "max": 1,
"min": 0 "min": 0,
"whitelist": []
} }
} }
}, },

View File

@ -50,7 +50,7 @@ export class BotInventoryGenerator
/** /**
* Add equipment/weapons/loot to bot * Add equipment/weapons/loot to bot
* @param sessionId Session id * @param sessionId Session id
* @param botJsonTemplate bot/x.json data from db * @param botJsonTemplate Base json db file for the bot having its loot generated
* @param botRole Role bot has (assault/pmcBot) * @param botRole Role bot has (assault/pmcBot)
* @param isPmc Is bot being converted into a pmc * @param isPmc Is bot being converted into a pmc
* @param botLevel Level of bot being generated * @param botLevel Level of bot being generated
@ -70,7 +70,7 @@ export class BotInventoryGenerator
// Roll weapon spawns and generate a weapon for each roll that passed // Roll weapon spawns and generate a weapon for each roll that passed
this.generateAndAddWeaponsToBot(templateInventory, equipmentChances, sessionId, botInventory, botRole, isPmc, itemGenerationLimitsMinMax, botLevel); this.generateAndAddWeaponsToBot(templateInventory, equipmentChances, sessionId, botInventory, botRole, isPmc, itemGenerationLimitsMinMax, botLevel);
this.botLootGenerator.generateLoot(sessionId, templateInventory, itemGenerationLimitsMinMax.items, isPmc, botRole, botInventory, equipmentChances, botLevel); this.botLootGenerator.generateLoot(sessionId, botJsonTemplate, isPmc, botRole, botInventory, botLevel);
return botInventory; return botInventory;
} }

View File

@ -5,7 +5,7 @@ import { BotWeaponGeneratorHelper } from "../helpers/BotWeaponGeneratorHelper";
import { HandbookHelper } from "../helpers/HandbookHelper"; import { HandbookHelper } from "../helpers/HandbookHelper";
import { ItemHelper } from "../helpers/ItemHelper"; import { ItemHelper } from "../helpers/ItemHelper";
import { Inventory as PmcInventory } from "../models/eft/common/tables/IBotBase"; import { Inventory as PmcInventory } from "../models/eft/common/tables/IBotBase";
import { Chances, Inventory, ItemMinMax, ModsChances } from "../models/eft/common/tables/IBotType"; import { IBotType, Inventory, ModsChances } from "../models/eft/common/tables/IBotType";
import { Item } from "../models/eft/common/tables/IItem"; import { Item } from "../models/eft/common/tables/IItem";
import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem";
import { BaseClasses } from "../models/enums/BaseClasses"; import { BaseClasses } from "../models/enums/BaseClasses";
@ -48,17 +48,16 @@ export class BotLootGenerator
/** /**
* Add loot to bots containers * Add loot to bots containers
* @param sessionId Session id * @param sessionId Session id
* @param templateInventory x.json from database/bots * @param botJsonTemplate Base json db file for the bot having its loot generated
* @param itemCounts Liits on item types to be added as loot
* @param isPmc Will bot be a pmc * @param isPmc Will bot be a pmc
* @param botRole Role of bot, e.g. asssult * @param botRole Role of bot, e.g. asssult
* @param botInventory Inventory to add loot to * @param botInventory Inventory to add loot to
* @param equipmentChances
* @param botLevel Level of bot * @param botLevel Level of bot
*/ */
public generateLoot(sessionId: string, templateInventory: Inventory, itemCounts: ItemMinMax, isPmc: boolean, botRole: string, botInventory: PmcInventory, equipmentChances: Chances, botLevel: number): void public generateLoot(sessionId: string, botJsonTemplate: IBotType, isPmc: boolean, botRole: string, botInventory: PmcInventory, botLevel: number): void
{ {
const lootPool = templateInventory.items; // Limits on item types to be added as loot
const itemCounts = botJsonTemplate.generation.items;
const nValue = this.getBotLootNValue(isPmc); const nValue = this.getBotLootNValue(isPmc);
const looseLootMin = itemCounts.looseLoot.min; const looseLootMin = itemCounts.looseLoot.min;
@ -76,7 +75,7 @@ export class BotLootGenerator
// Special items // Special items
this.addLootFromPool( this.addLootFromPool(
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SPECIAL, lootPool), this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SPECIAL, botJsonTemplate),
[EquipmentSlots.POCKETS, EquipmentSlots.BACKPACK, EquipmentSlots.TACTICAL_VEST], [EquipmentSlots.POCKETS, EquipmentSlots.BACKPACK, EquipmentSlots.TACTICAL_VEST],
specialLootItemCount, specialLootItemCount,
botInventory, botInventory,
@ -84,7 +83,7 @@ export class BotLootGenerator
// Meds // Meds
this.addLootFromPool( this.addLootFromPool(
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.HEALING_ITEMS, lootPool), this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.HEALING_ITEMS, botJsonTemplate),
[EquipmentSlots.TACTICAL_VEST, EquipmentSlots.POCKETS, EquipmentSlots.BACKPACK, EquipmentSlots.SECURED_CONTAINER], [EquipmentSlots.TACTICAL_VEST, EquipmentSlots.POCKETS, EquipmentSlots.BACKPACK, EquipmentSlots.SECURED_CONTAINER],
healingItemCount, healingItemCount,
botInventory, botInventory,
@ -95,7 +94,7 @@ export class BotLootGenerator
// Drugs // Drugs
this.addLootFromPool( this.addLootFromPool(
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.DRUG_ITEMS, lootPool), this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.DRUG_ITEMS, botJsonTemplate),
[EquipmentSlots.TACTICAL_VEST, EquipmentSlots.POCKETS, EquipmentSlots.BACKPACK, EquipmentSlots.SECURED_CONTAINER], [EquipmentSlots.TACTICAL_VEST, EquipmentSlots.POCKETS, EquipmentSlots.BACKPACK, EquipmentSlots.SECURED_CONTAINER],
drugItemCount, drugItemCount,
botInventory, botInventory,
@ -106,7 +105,7 @@ export class BotLootGenerator
// Stims // Stims
this.addLootFromPool( this.addLootFromPool(
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.STIM_ITEMS, lootPool), this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.STIM_ITEMS, botJsonTemplate),
[EquipmentSlots.TACTICAL_VEST, EquipmentSlots.POCKETS, EquipmentSlots.BACKPACK, EquipmentSlots.SECURED_CONTAINER], [EquipmentSlots.TACTICAL_VEST, EquipmentSlots.POCKETS, EquipmentSlots.BACKPACK, EquipmentSlots.SECURED_CONTAINER],
stimItemCount, stimItemCount,
botInventory, botInventory,
@ -117,7 +116,7 @@ export class BotLootGenerator
// Grenades // Grenades
this.addLootFromPool( this.addLootFromPool(
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.GRENADE_ITEMS, lootPool), this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.GRENADE_ITEMS, botJsonTemplate),
[EquipmentSlots.TACTICAL_VEST, EquipmentSlots.POCKETS], [EquipmentSlots.TACTICAL_VEST, EquipmentSlots.POCKETS],
grenadeCount, grenadeCount,
botInventory, botInventory,
@ -128,12 +127,12 @@ export class BotLootGenerator
if (isPmc && this.randomUtil.getChance100(this.botConfig.pmc.looseWeaponInBackpackChancePercent)) if (isPmc && this.randomUtil.getChance100(this.botConfig.pmc.looseWeaponInBackpackChancePercent))
{ {
this.addLooseWeaponsToInventorySlot(sessionId, botInventory, "Backpack", templateInventory, equipmentChances.mods, botRole, isPmc, botLevel); this.addLooseWeaponsToInventorySlot(sessionId, botInventory, "Backpack", botJsonTemplate.inventory, botJsonTemplate.chances.mods, botRole, isPmc, botLevel);
} }
// Backpack // Backpack
this.addLootFromPool( this.addLootFromPool(
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.BACKPACK, lootPool), this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.BACKPACK, botJsonTemplate),
[EquipmentSlots.BACKPACK], [EquipmentSlots.BACKPACK],
lootItemCount, lootItemCount,
botInventory, botInventory,
@ -144,7 +143,7 @@ export class BotLootGenerator
// Vest // Vest
this.addLootFromPool( this.addLootFromPool(
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.VEST, lootPool), this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.VEST, botJsonTemplate),
[EquipmentSlots.TACTICAL_VEST], [EquipmentSlots.TACTICAL_VEST],
vestLootCount, vestLootCount,
botInventory, botInventory,
@ -155,7 +154,7 @@ export class BotLootGenerator
// Pockets // Pockets
this.addLootFromPool( this.addLootFromPool(
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.POCKET, lootPool), this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.POCKET, botJsonTemplate),
[EquipmentSlots.POCKETS], [EquipmentSlots.POCKETS],
pocketLootCount, pocketLootCount,
botInventory, botInventory,

View File

@ -1,5 +1,5 @@
import { MinMax } from "../../../common/MinMax" import { MinMax } from "../../../common/MinMax";
import { Skills } from "./IBotBase" import { Skills } from "./IBotBase";
export interface IBotType export interface IBotType
{ {
@ -125,13 +125,19 @@ export interface Generation
export interface ItemMinMax export interface ItemMinMax
{ {
grenades: MinMax grenades: MinMaxWithWhitelist
healing: MinMax healing: MinMaxWithWhitelist
drugs: MinMax drugs: MinMaxWithWhitelist
stims: MinMax stims: MinMaxWithWhitelist
looseLoot: MinMax looseLoot: MinMaxWithWhitelist
magazines: MinMax magazines: MinMaxWithWhitelist
specialItems: MinMax specialItems: MinMaxWithWhitelist
}
export interface MinMaxWithWhitelist extends MinMax
{
/** Array of item tpls */
whitelist: string[]
} }
export interface Health export interface Health

View File

@ -1,3 +1,4 @@
import { MinMaxWithWhitelist } from "../../../models/eft/common/tables/IBotType";
import { MinMax } from "../../common/MinMax"; import { MinMax } from "../../common/MinMax";
import { IBaseConfig } from "./IBaseConfig"; import { IBaseConfig } from "./IBaseConfig";
import { IBotDurability } from "./IBotDurability"; import { IBotDurability } from "./IBotDurability";
@ -97,7 +98,7 @@ export interface ModLimits
export interface RandomisationDetails export interface RandomisationDetails
{ {
levelRange: MinMax levelRange: MinMax
generation?: Record<string, MinMax> generation?: Record<string, MinMaxWithWhitelist>
randomisedWeaponModSlots?: string[] randomisedWeaponModSlots?: string[]
randomisedArmorSlots?: string[] randomisedArmorSlots?: string[]
/** Equipment chances */ /** Equipment chances */

View File

@ -1,11 +1,15 @@
import { inject, injectable } from "tsyringe"; import { inject, injectable } from "tsyringe";
import { BotHelper } from "../helpers/BotHelper"; import { BotHelper } from "../helpers/BotHelper";
import { MinMax } from "../models/common/MinMax"; import {
import { EquipmentChances, Generation, IBotType, ModsChances } from "../models/eft/common/tables/IBotType"; EquipmentChances, Generation, IBotType, MinMaxWithWhitelist, ModsChances
} from "../models/eft/common/tables/IBotType";
import { ConfigTypes } from "../models/enums/ConfigTypes"; import { ConfigTypes } from "../models/enums/ConfigTypes";
import { BotGenerationDetails } from "../models/spt/bots/BotGenerationDetails"; import { BotGenerationDetails } from "../models/spt/bots/BotGenerationDetails";
import { AdjustmentDetails, EquipmentFilterDetails, EquipmentFilters, IBotConfig, WeightingAdjustmentDetails } from "../models/spt/config/IBotConfig"; import {
AdjustmentDetails, EquipmentFilterDetails, EquipmentFilters, IBotConfig,
WeightingAdjustmentDetails
} from "../models/spt/config/IBotConfig";
import { ILogger } from "../models/spt/utils/ILogger"; import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer"; import { ConfigServer } from "../servers/ConfigServer";
@ -78,7 +82,7 @@ export class BotEquipmentFilterService
* @param generationChanges Changes to apply * @param generationChanges Changes to apply
* @param baseBotGeneration dictionary to update * @param baseBotGeneration dictionary to update
*/ */
protected adjustGenerationChances(generationChanges: Record<string, MinMax>, baseBotGeneration: Generation): void protected adjustGenerationChances(generationChanges: Record<string, MinMaxWithWhitelist>, baseBotGeneration: Generation): void
{ {
if (!generationChanges) if (!generationChanges)
{ {
@ -89,6 +93,8 @@ export class BotEquipmentFilterService
{ {
baseBotGeneration.items[itemKey].min = generationChanges[itemKey].min; baseBotGeneration.items[itemKey].min = generationChanges[itemKey].min;
baseBotGeneration.items[itemKey].max = generationChanges[itemKey].max; baseBotGeneration.items[itemKey].max = generationChanges[itemKey].max;
baseBotGeneration.items[itemKey].whitelist = generationChanges[itemKey].whitelist;
} }
} }

View File

@ -1,7 +1,8 @@
import { inject, injectable } from "tsyringe"; import { inject, injectable } from "tsyringe";
import { PMCLootGenerator } from "../generators/PMCLootGenerator"; import { PMCLootGenerator } from "../generators/PMCLootGenerator";
import { Items } from "../models/eft/common/tables/IBotType"; import { ItemHelper } from "../helpers/ItemHelper";
import { IBotType } from "../models/eft/common/tables/IBotType";
import { ITemplateItem, Props } from "../models/eft/common/tables/ITemplateItem"; import { ITemplateItem, Props } from "../models/eft/common/tables/ITemplateItem";
import { BaseClasses } from "../models/enums/BaseClasses"; import { BaseClasses } from "../models/enums/BaseClasses";
import { BotLootCache, LootCacheType } from "../models/spt/bots/BotLootCache"; import { BotLootCache, LootCacheType } from "../models/spt/bots/BotLootCache";
@ -19,6 +20,7 @@ export class BotLootCacheService
constructor( constructor(
@inject("WinstonLogger") protected logger: ILogger, @inject("WinstonLogger") protected logger: ILogger,
@inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("JsonUtil") protected jsonUtil: JsonUtil,
@inject("ItemHelper") protected itemHelper: ItemHelper,
@inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("DatabaseServer") protected databaseServer: DatabaseServer,
@inject("PMCLootGenerator") protected pmcLootGenerator: PMCLootGenerator, @inject("PMCLootGenerator") protected pmcLootGenerator: PMCLootGenerator,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@ -41,15 +43,15 @@ export class BotLootCacheService
* @param botRole bot to get loot for * @param botRole bot to get loot for
* @param isPmc is the bot a pmc * @param isPmc is the bot a pmc
* @param lootType what type of loot is needed (backpack/pocket/stim/vest etc) * @param lootType what type of loot is needed (backpack/pocket/stim/vest etc)
* @param lootPool the full pool of loot (needed when cache is empty) * @param botJsonTemplate Base json db file for the bot having its loot generated
* @returns ITemplateItem array * @returns ITemplateItem array
*/ */
public getLootFromCache(botRole: string, isPmc: boolean, lootType: LootCacheType, lootPool: Items): ITemplateItem[] public getLootFromCache(botRole: string, isPmc: boolean, lootType: LootCacheType, botJsonTemplate: IBotType): ITemplateItem[]
{ {
if (!this.botRoleExistsInCache(botRole)) if (!this.botRoleExistsInCache(botRole))
{ {
this.initCacheForBotRole(botRole); this.initCacheForBotRole(botRole);
this.addLootToCache(botRole, isPmc, lootPool); this.addLootToCache(botRole, isPmc, botJsonTemplate);
} }
switch (lootType) switch (lootType)
@ -81,11 +83,14 @@ export class BotLootCacheService
/** /**
* Generate loot for a bot and store inside a private class property * Generate loot for a bot and store inside a private class property
* @param botRole bots role (assault / pmcBot etc) * @param botRole bots role (assault / pmcBot etc)
* @param lootPool the full pool of loot we use to create the various sub-categories with
* @param isPmc Is the bot a PMC (alteres what loot is cached) * @param isPmc Is the bot a PMC (alteres what loot is cached)
* @param botJsonTemplate db template for bot having its loot generated
*/ */
protected addLootToCache(botRole: string, isPmc: boolean, lootPool: Items): void protected addLootToCache(botRole: string, isPmc: boolean, botJsonTemplate: IBotType): void
{ {
// the full pool of loot we use to create the various sub-categories with
const lootPool = botJsonTemplate.inventory.items;
// Flatten all individual slot loot pools into one big pool, while filtering out potentially missing templates // Flatten all individual slot loot pools into one big pool, while filtering out potentially missing templates
const specialLootTemplates: ITemplateItem[] = []; const specialLootTemplates: ITemplateItem[] = [];
const backpackLootTemplates: ITemplateItem[] = []; const backpackLootTemplates: ITemplateItem[] = [];
@ -103,32 +108,34 @@ export class BotLootCacheService
for (const [slot, pool] of Object.entries(lootPool)) for (const [slot, pool] of Object.entries(lootPool))
{ {
// No items to add, skip
if (!pool?.length) if (!pool?.length)
{ {
continue; continue;
} }
// Sort loot pool into separate buckets
let itemsToAdd: ITemplateItem[] = []; let itemsToAdd: ITemplateItem[] = [];
const items = this.databaseServer.getTables().templates.items; const items = this.databaseServer.getTables().templates.items;
switch (slot.toLowerCase()) switch (slot.toLowerCase())
{ {
case "specialloot": case "specialloot":
itemsToAdd = pool.map(lootTpl => items[lootTpl]); itemsToAdd = pool.map((lootTpl: string) => items[lootTpl]);
this.addUniqueItemsToPool(specialLootTemplates, itemsToAdd); this.addUniqueItemsToPool(specialLootTemplates, itemsToAdd);
break; break;
case "pockets": case "pockets":
itemsToAdd = pool.map(lootTpl => items[lootTpl]); itemsToAdd = pool.map((lootTpl: string) => items[lootTpl]);
this.addUniqueItemsToPool(pocketLootTemplates, itemsToAdd); this.addUniqueItemsToPool(pocketLootTemplates, itemsToAdd);
break; break;
case "tacticalvest": case "tacticalvest":
itemsToAdd = pool.map(lootTpl => items[lootTpl]); itemsToAdd = pool.map((lootTpl: string) => items[lootTpl]);
this.addUniqueItemsToPool(vestLootTemplates, itemsToAdd); this.addUniqueItemsToPool(vestLootTemplates, itemsToAdd);
break; break;
case "securedcontainer": case "securedcontainer":
// Don't add these items to loot pool // Don't add these items to loot pool
break; break;
default: default:
itemsToAdd = pool.map(lootTpl => items[lootTpl]); itemsToAdd = pool.map((lootTpl: string) => items[lootTpl]);
this.addUniqueItemsToPool(backpackLootTemplates, itemsToAdd); this.addUniqueItemsToPool(backpackLootTemplates, itemsToAdd);
} }
@ -146,25 +153,36 @@ export class BotLootCacheService
this.sortPoolByRagfairPrice(vestLootTemplates); this.sortPoolByRagfairPrice(vestLootTemplates);
this.sortPoolByRagfairPrice(combinedPoolTemplates); this.sortPoolByRagfairPrice(combinedPoolTemplates);
const specialLootItems = specialLootTemplates.filter(template => // use whitelist if array has values, otherwise process above sorted pools
!(this.isBulletOrGrenade(template._props) const specialLootItems = (botJsonTemplate.generation.items.specialItems.whitelist?.length > 0)
|| this.isMagazine(template._props))); ? botJsonTemplate.generation.items.specialItems.whitelist.map(x => this.itemHelper.getItem(x)[1])
: specialLootTemplates.filter(template =>
!(this.isBulletOrGrenade(template._props)
|| this.isMagazine(template._props)));
const healingItems = combinedPoolTemplates.filter(template => const healingItems = (botJsonTemplate.generation.items.healing.whitelist?.length > 0)
this.isMedicalItem(template._props) ? botJsonTemplate.generation.items.healing.whitelist.map(x => this.itemHelper.getItem(x)[1])
&& template._parent !== BaseClasses.STIMULATOR : combinedPoolTemplates.filter(template =>
&& template._parent !== BaseClasses.DRUGS); this.isMedicalItem(template._props)
&& template._parent !== BaseClasses.STIMULATOR
&& template._parent !== BaseClasses.DRUGS);
const drugItems = combinedPoolTemplates.filter(template => const drugItems = (botJsonTemplate.generation.items.drugs.whitelist?.length > 0)
this.isMedicalItem(template._props) ? botJsonTemplate.generation.items.drugs.whitelist.map(x => this.itemHelper.getItem(x)[1])
&& template._parent === BaseClasses.DRUGS); : combinedPoolTemplates.filter(template =>
this.isMedicalItem(template._props)
&& template._parent === BaseClasses.DRUGS);
const stimItems = combinedPoolTemplates.filter(template => const stimItems = (botJsonTemplate.generation.items.stims.whitelist?.length > 0)
this.isMedicalItem(template._props) ? botJsonTemplate.generation.items.stims.whitelist.map(x => this.itemHelper.getItem(x)[1])
&& template._parent === BaseClasses.STIMULATOR); : combinedPoolTemplates.filter(template =>
this.isMedicalItem(template._props)
&& template._parent === BaseClasses.STIMULATOR);
const grenadeItems = combinedPoolTemplates.filter(template => const grenadeItems = (botJsonTemplate.generation.items.grenades.whitelist?.length > 0)
this.isGrenade(template._props)); ? botJsonTemplate.generation.items.grenades.whitelist.map(x => this.itemHelper.getItem(x)[1])
: combinedPoolTemplates.filter(template =>
this.isGrenade(template._props));
// Get loot items (excluding magazines, bullets, grenades and healing items) // Get loot items (excluding magazines, bullets, grenades and healing items)
const backpackLootItems = backpackLootTemplates.filter(template => const backpackLootItems = backpackLootTemplates.filter(template =>