From c6135802bea91846cd1ab51f1a55b3104ea663d4 Mon Sep 17 00:00:00 2001 From: Dev Date: Sun, 7 Jan 2024 14:46:25 +0000 Subject: [PATCH] Refactor equipment mod parameters --- .../generators/BotEquipmentModGenerator.ts | 45 +++-- .../src/generators/BotInventoryGenerator.ts | 183 ++++++++++-------- project/src/models/spt/config/IBotConfig.ts | 18 +- .../src/services/BotEquipmentFilterService.ts | 4 +- 4 files changed, 146 insertions(+), 104 deletions(-) diff --git a/project/src/generators/BotEquipmentModGenerator.ts b/project/src/generators/BotEquipmentModGenerator.ts index 41f48976..da20a64a 100644 --- a/project/src/generators/BotEquipmentModGenerator.ts +++ b/project/src/generators/BotEquipmentModGenerator.ts @@ -23,6 +23,7 @@ import { LocalisationService } from "@spt-aki/services/LocalisationService"; import { HashUtil } from "@spt-aki/utils/HashUtil"; import { JsonUtil } from "@spt-aki/utils/JsonUtil"; import { RandomUtil } from "@spt-aki/utils/RandomUtil"; +import { IGenerateEquipmentProperties } from "./BotInventoryGenerator"; @injectable() export class BotEquipmentModGenerator @@ -65,18 +66,16 @@ export class BotEquipmentModGenerator */ public generateModsForEquipment( equipment: Item[], - modPool: Mods, parentId: string, parentTemplate: ITemplateItem, - modSpawnChances: ModsChances, - botRole: string, + settings: IGenerateEquipmentProperties, forceSpawn = false, ): Item[] { - const compatibleModsPool = modPool[parentTemplate._id]; + const compatibleModsPool = settings.modPool[parentTemplate._id]; if (!compatibleModsPool) { - this.logger.warning(`bot: ${botRole} lacks a mod slot pool for item: ${parentTemplate._id} ${parentTemplate._name}`); + this.logger.warning(`bot: ${settings.botRole} lacks a mod slot pool for item: ${parentTemplate._id} ${parentTemplate._name}`); } // Iterate over mod pool and choose mods to add to item @@ -90,13 +89,13 @@ export class BotEquipmentModGenerator modSlot: modSlot, parentId: parentTemplate._id, parentName: parentTemplate._name, - botRole: botRole + botRole: settings.botRole }), ); continue; } - if (!(this.shouldModBeSpawned(itemSlot, modSlot, modSpawnChances) || forceSpawn)) + if (!(this.shouldModBeSpawned(itemSlot, modSlot, settings.spawnChances.mods) || forceSpawn)) { continue; } @@ -107,12 +106,14 @@ export class BotEquipmentModGenerator forceSpawn = true; } + const modPoolToChooseFrom = this.filterPlateModsForSlot(settings.botRole, modSlot, compatibleModsPool[modSlot]); + let modTpl: string; let found = false; // Find random mod and check its compatible const exhaustableModPool = new ExhaustableArray( - compatibleModsPool[modSlot], + modPoolToChooseFrom, this.randomUtil, this.jsonUtil, ); @@ -144,24 +145,22 @@ export class BotEquipmentModGenerator } const modTemplate = this.itemHelper.getItem(modTpl); - if (!this.isModValidForSlot(modTemplate, itemSlot, modSlot, parentTemplate, botRole)) + if (!this.isModValidForSlot(modTemplate, itemSlot, modSlot, parentTemplate, settings.botRole)) { continue; } const modId = this.hashUtil.generate(); - equipment.push(this.createModItem(modId, modTpl, parentId, modSlot, modTemplate[1], botRole)); + equipment.push(this.createModItem(modId, modTpl, parentId, modSlot, modTemplate[1], settings.botRole)); - if (Object.keys(modPool).includes(modTpl)) + if (Object.keys(settings.modPool).includes(modTpl)) { // Call self recursively this.generateModsForEquipment( equipment, - modPool, modId, modTemplate[1], - modSpawnChances, - botRole, + settings, forceSpawn, ); } @@ -170,6 +169,24 @@ export class BotEquipmentModGenerator return equipment; } + protected filterPlateModsForSlot(botRole: string, modSlot: string, modPool: string[]): string[] + { + // Not pmc or not a plate slot, return original mod pool array + if (!this.botHelper.isBotPmc(botRole) || !this.slotIsPlate(modSlot)) + { + return modPool; + } + + const filteredModPool = []; + + + } + + protected slotIsPlate(modSlot: string): boolean + { + return ["front_plate", "back_plate", "side_plate"].includes(modSlot.toLowerCase()); + } + /** * Add mods to a weapon using the provided mod pool * @param sessionId session id diff --git a/project/src/generators/BotInventoryGenerator.ts b/project/src/generators/BotInventoryGenerator.ts index 266771bf..f4d0da2d 100644 --- a/project/src/generators/BotInventoryGenerator.ts +++ b/project/src/generators/BotInventoryGenerator.ts @@ -11,7 +11,7 @@ import { Inventory as PmcInventory } from "@spt-aki/models/eft/common/tables/IBo import { Chances, Generation, IBotType, Inventory, Mods } from "@spt-aki/models/eft/common/tables/IBotType"; import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes"; import { EquipmentSlots } from "@spt-aki/models/enums/EquipmentSlots"; -import { EquipmentFilterDetails, IBotConfig, RandomisationDetails } from "@spt-aki/models/spt/config/IBotConfig"; +import { EquipmentFilterDetails, EquipmentFilters, IBotConfig, RandomisationDetails } from "@spt-aki/models/spt/config/IBotConfig"; import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; import { ConfigServer } from "@spt-aki/servers/ConfigServer"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; @@ -159,7 +159,6 @@ export class BotInventoryGenerator const botEquipConfig = this.botConfig.equipment[this.botGeneratorHelper.getBotEquipmentRole(botRole)]; const randomistionDetails = this.botHelper.getBotRandomizationDetails(botLevel, botEquipConfig); - for (const equipmentSlot in templateInventory.equipment) { // Weapons have special generation and will be generated separately; ArmorVest should be generated after TactivalVest @@ -168,63 +167,75 @@ export class BotInventoryGenerator continue; } - this.generateEquipment( - equipmentSlot, - templateInventory.equipment[equipmentSlot], - templateInventory.mods, - equipmentChances, - botRole, - botInventory, - randomistionDetails, - ); + this.generateEquipment({ + equipmentSlot: equipmentSlot, + equipmentPool: templateInventory.equipment[equipmentSlot], + modPool: templateInventory.mods, + spawnChances: equipmentChances, + botRole: botRole, + botLevel: botLevel, + inventory: botInventory, + botEquipmentConfig: botEquipConfig, + randomisationDetails: randomistionDetails + }); } // Generate below in specific order - this.generateEquipment( - EquipmentSlots.FACE_COVER, - templateInventory.equipment.FaceCover, - templateInventory.mods, - equipmentChances, - botRole, - botInventory, - randomistionDetails, - ); - this.generateEquipment( - EquipmentSlots.HEADWEAR, - templateInventory.equipment.Headwear, - templateInventory.mods, - equipmentChances, - botRole, - botInventory, - randomistionDetails, - ); - this.generateEquipment( - EquipmentSlots.EARPIECE, - templateInventory.equipment.Earpiece, - templateInventory.mods, - equipmentChances, - botRole, - botInventory, - randomistionDetails, - ); - this.generateEquipment( - EquipmentSlots.TACTICAL_VEST, - templateInventory.equipment.TacticalVest, - templateInventory.mods, - equipmentChances, - botRole, - botInventory, - randomistionDetails, - ); - this.generateEquipment( - EquipmentSlots.ARMOR_VEST, - templateInventory.equipment.ArmorVest, - templateInventory.mods, - equipmentChances, - botRole, - botInventory, - randomistionDetails, - ); + this.generateEquipment({ + equipmentSlot: EquipmentSlots.FACE_COVER, + equipmentPool: templateInventory.equipment.FaceCover, + modPool: templateInventory.mods, + spawnChances: equipmentChances, + botRole: botRole, + botLevel: botLevel, + inventory: botInventory, + botEquipmentConfig: botEquipConfig, + randomisationDetails: randomistionDetails + }); + this.generateEquipment({ + equipmentSlot: EquipmentSlots.HEADWEAR, + equipmentPool: templateInventory.equipment.Headwear, + modPool: templateInventory.mods, + spawnChances: equipmentChances, + botRole: botRole, + botLevel: botLevel, + inventory: botInventory, + botEquipmentConfig: botEquipConfig, + randomisationDetails: randomistionDetails + }); + this.generateEquipment({ + equipmentSlot: EquipmentSlots.EARPIECE, + equipmentPool: templateInventory.equipment.Earpiece, + modPool: templateInventory.mods, + spawnChances: equipmentChances, + botRole: botRole, + botLevel: botLevel, + inventory: botInventory, + botEquipmentConfig: botEquipConfig, + randomisationDetails: randomistionDetails + }); + this.generateEquipment({ + equipmentSlot: EquipmentSlots.TACTICAL_VEST, + equipmentPool: templateInventory.equipment.TacticalVest, + modPool: templateInventory.mods, + spawnChances: equipmentChances, + botRole: botRole, + botLevel: botLevel, + inventory: botInventory, + botEquipmentConfig: botEquipConfig, + randomisationDetails: randomistionDetails + }); + this.generateEquipment({ + equipmentSlot: EquipmentSlots.ARMOR_VEST, + equipmentPool: templateInventory.equipment.ArmorVest, + modPool: templateInventory.mods, + spawnChances: equipmentChances, + botRole: botRole, + botLevel: botLevel, + inventory: botInventory, + botEquipmentConfig: botEquipConfig, + randomisationDetails: randomistionDetails + }); } /** @@ -237,49 +248,41 @@ export class BotInventoryGenerator * @param inventory Inventory to add item into * @param randomisationDetails settings from bot.json to adjust how item is generated */ - protected generateEquipment( - equipmentSlot: string, - equipmentPool: Record, - modPool: Mods, - spawnChances: Chances, - botRole: string, - inventory: PmcInventory, - randomisationDetails: RandomisationDetails, - ): void + protected generateEquipment(settings: IGenerateEquipmentProperties): void { const spawnChance = - ([EquipmentSlots.POCKETS, EquipmentSlots.SECURED_CONTAINER] as string[]).includes(equipmentSlot) + ([EquipmentSlots.POCKETS, EquipmentSlots.SECURED_CONTAINER] as string[]).includes(settings.equipmentSlot) ? 100 - : spawnChances.equipment[equipmentSlot]; + : settings.spawnChances.equipment[settings.equipmentSlot]; if (typeof spawnChance === "undefined") { this.logger.warning( - this.localisationService.getText("bot-no_spawn_chance_defined_for_equipment_slot", equipmentSlot), + this.localisationService.getText("bot-no_spawn_chance_defined_for_equipment_slot", settings.equipmentSlot), ); return; } const shouldSpawn = this.randomUtil.getChance100(spawnChance); - if (Object.keys(equipmentPool).length && shouldSpawn) + if (Object.keys(settings.equipmentPool).length && shouldSpawn) { const id = this.hashUtil.generate(); - const equipmentItemTpl = this.weightedRandomHelper.getWeightedValue(equipmentPool); + const equipmentItemTpl = this.weightedRandomHelper.getWeightedValue(settings.equipmentPool); const itemTemplate = this.itemHelper.getItem(equipmentItemTpl); if (!itemTemplate[0]) { this.logger.error(this.localisationService.getText("bot-missing_item_template", equipmentItemTpl)); - this.logger.info(`EquipmentSlot -> ${equipmentSlot}`); + this.logger.info(`EquipmentSlot -> ${settings.equipmentSlot}`); return; } if ( this.botGeneratorHelper.isItemIncompatibleWithCurrentItems( - inventory.items, + settings.inventory.items, equipmentItemTpl, - equipmentSlot, + settings.equipmentSlot, ).incompatible ) { @@ -290,19 +293,19 @@ export class BotInventoryGenerator const item = { _id: id, _tpl: equipmentItemTpl, - parentId: inventory.equipment, - slotId: equipmentSlot, - ...this.botGeneratorHelper.generateExtraPropertiesForItem(itemTemplate[1], botRole), + parentId: settings.inventory.equipment, + slotId: settings.equipmentSlot, + ...this.botGeneratorHelper.generateExtraPropertiesForItem(itemTemplate[1], settings.botRole), }; // use dynamic mod pool if enabled in config - const botEquipmentRole = this.botGeneratorHelper.getBotEquipmentRole(botRole); + const botEquipmentRole = this.botGeneratorHelper.getBotEquipmentRole(settings.botRole); if ( this.botConfig.equipment[botEquipmentRole] - && randomisationDetails?.randomisedArmorSlots?.includes(equipmentSlot) + && settings.randomisationDetails?.randomisedArmorSlots?.includes(settings.equipmentSlot) ) { - modPool[equipmentItemTpl] = this.getFilteredDynamicModsForItem( + settings.modPool[equipmentItemTpl] = this.getFilteredDynamicModsForItem( equipmentItemTpl, this.botConfig.equipment[botEquipmentRole].blacklist, ); @@ -313,17 +316,16 @@ export class BotInventoryGenerator { const items = this.botEquipmentModGenerator.generateModsForEquipment( [item], - modPool, + settings.modPool, id, itemTemplate[1], - spawnChances.mods, - botRole, + settings ); - inventory.items.push(...items); + settings.inventory.items.push(...items); } else { - inventory.items.push(item); + settings.inventory.items.push(item); } } } @@ -462,3 +464,16 @@ export class BotInventoryGenerator ); } } + +export interface IGenerateEquipmentProperties + { + equipmentSlot: string, + equipmentPool: Record, + modPool: Mods, + spawnChances: Chances, + botRole: string, + botLevel: number, + inventory: PmcInventory, + botEquipmentConfig: EquipmentFilters, + randomisationDetails: RandomisationDetails + } diff --git a/project/src/models/spt/config/IBotConfig.ts b/project/src/models/spt/config/IBotConfig.ts index 99fe8268..931516e2 100644 --- a/project/src/models/spt/config/IBotConfig.ts +++ b/project/src/models/spt/config/IBotConfig.ts @@ -116,6 +116,7 @@ export interface EquipmentFilters weightingAdjustmentsByPlayerLevel?: WeightingAdjustmentDetails[]; /** Should the stock mod be forced to spawn on bot */ forceStock: boolean; + armorPlateWeighting?: IArmorPlateWeights[] } export interface ModLimits @@ -156,19 +157,28 @@ export interface WeightingAdjustmentDetails /** Between what levels do these weight settings apply to */ levelRange: MinMax; /** Key: ammo type e.g. Caliber556x45NATO, value: item tpl + weight */ - ammo?: AdjustmentDetails; + ammo?: IAdjustmentDetails; /** Key: equipment slot e.g. TacticalVest, value: item tpl + weight */ - equipment?: AdjustmentDetails; + equipment?: IAdjustmentDetails; /** Key: clothing slot e.g. feet, value: item tpl + weight */ - clothing?: AdjustmentDetails; + clothing?: IAdjustmentDetails; + } -export interface AdjustmentDetails +export interface IAdjustmentDetails { add: Record>; edit: Record>; } +export interface IArmorPlateWeights +{ + levelRange: MinMax; + frontPlateWeights: Record; + backPlateWeights: Record; + sidePlateWeights: Record; +} + export interface IRandomisedResourceDetails { food: IRandomisedResourceValues; diff --git a/project/src/services/BotEquipmentFilterService.ts b/project/src/services/BotEquipmentFilterService.ts index a96efa24..5083fe62 100644 --- a/project/src/services/BotEquipmentFilterService.ts +++ b/project/src/services/BotEquipmentFilterService.ts @@ -12,9 +12,9 @@ import { import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes"; import { BotGenerationDetails } from "@spt-aki/models/spt/bots/BotGenerationDetails"; import { - AdjustmentDetails, EquipmentFilterDetails, EquipmentFilters, + IAdjustmentDetails, IBotConfig, WeightingAdjustmentDetails, } from "@spt-aki/models/spt/config/IBotConfig"; @@ -393,7 +393,7 @@ export class BotEquipmentFilterService * @param botItemPool Bot item dictionary to adjust */ protected adjustWeighting( - weightingAdjustments: AdjustmentDetails, + weightingAdjustments: IAdjustmentDetails, botItemPool: Record, showEditWarnings = true, ): void