Add loop to try multiple armor pieces to find one that's compatible with bots current loadout

This commit is contained in:
Dev 2024-01-18 22:36:14 +00:00
parent 01b608d8b2
commit ea0d8224e6
2 changed files with 66 additions and 39 deletions

View File

@ -9,6 +9,7 @@ import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper"; import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
import { Inventory as PmcInventory } from "@spt-aki/models/eft/common/tables/IBotBase"; import { Inventory as PmcInventory } from "@spt-aki/models/eft/common/tables/IBotBase";
import { Chances, Generation, IBotType, Inventory, Mods } from "@spt-aki/models/eft/common/tables/IBotType"; import { Chances, Generation, IBotType, Inventory, Mods } from "@spt-aki/models/eft/common/tables/IBotType";
import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem";
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes"; import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
import { EquipmentSlots } from "@spt-aki/models/enums/EquipmentSlots"; import { EquipmentSlots } from "@spt-aki/models/enums/EquipmentSlots";
import { EquipmentFilterDetails, EquipmentFilters, IBotConfig, RandomisationDetails } from "@spt-aki/models/spt/config/IBotConfig"; import { EquipmentFilterDetails, EquipmentFilters, IBotConfig, RandomisationDetails } from "@spt-aki/models/spt/config/IBotConfig";
@ -240,13 +241,7 @@ export class BotInventoryGenerator
/** /**
* Add a piece of equipment with mods to inventory from the provided pools * Add a piece of equipment with mods to inventory from the provided pools
* @param equipmentSlot Slot to select an item for * @param settings Values to adjust how item is chosen and added to bot
* @param equipmentPool Possible items to choose from
* @param modPool Possible mods to apply to item chosen
* @param spawnChances Chances items will be chosen to be added
* @param botRole Role of bot e.g. assault
* @param inventory Inventory to add item into
* @param randomisationDetails
*/ */
protected generateEquipment(settings: IGenerateEquipmentProperties): void protected generateEquipment(settings: IGenerateEquipmentProperties): void
{ {
@ -264,66 +259,96 @@ export class BotInventoryGenerator
} }
const shouldSpawn = this.randomUtil.getChance100(spawnChance); const shouldSpawn = this.randomUtil.getChance100(spawnChance);
if (Object.keys(settings.rootEquipmentPool).length && shouldSpawn) if (shouldSpawn && Object.keys(settings.rootEquipmentPool).length)
{ {
let pickedItemDb: ITemplateItem;
let found = false;
let attempts = 0;
while (!found)
{
if (Object.values(settings.rootEquipmentPool).length === 0)
{
return;
}
const chosenItemTpl = this.weightedRandomHelper.getWeightedValue<string>(settings.rootEquipmentPool);
const dbResult = this.itemHelper.getItem(chosenItemTpl);
if (!dbResult[0])
{
this.logger.error(this.localisationService.getText("bot-missing_item_template", chosenItemTpl));
this.logger.info(`EquipmentSlot -> ${settings.rootEquipmentSlot}`);
// remove picked item
delete settings.rootEquipmentPool[chosenItemTpl];
attempts++;
continue;
}
if (
this.botGeneratorHelper.isItemIncompatibleWithCurrentItems(
settings.inventory.items,
chosenItemTpl,
settings.rootEquipmentSlot,
).incompatible)
{
if (attempts >= 8)
{
return;
}
// remove picked item
delete settings.rootEquipmentPool[chosenItemTpl];
attempts++;
}
else
{
// Success
found = true;
pickedItemDb = dbResult[1];
}
}
// Create root item
const id = this.hashUtil.generate(); const id = this.hashUtil.generate();
const equipmentItemTpl = this.weightedRandomHelper.getWeightedValue<string>(settings.rootEquipmentPool);
const itemTemplate = this.itemHelper.getItem(equipmentItemTpl);
if (!itemTemplate[0])
{
this.logger.error(this.localisationService.getText("bot-missing_item_template", equipmentItemTpl));
this.logger.info(`EquipmentSlot -> ${settings.rootEquipmentSlot}`);
return;
}
if (
this.botGeneratorHelper.isItemIncompatibleWithCurrentItems(
settings.inventory.items,
equipmentItemTpl,
settings.rootEquipmentSlot,
).incompatible
)
{
// Bad luck - randomly picked item was not compatible with current gear
return;
}
const item = { const item = {
_id: id, _id: id,
_tpl: equipmentItemTpl, _tpl: pickedItemDb._id,
parentId: settings.inventory.equipment, parentId: settings.inventory.equipment,
slotId: settings.rootEquipmentSlot, slotId: settings.rootEquipmentSlot,
...this.botGeneratorHelper.generateExtraPropertiesForItem(itemTemplate[1], settings.botRole), ...this.botGeneratorHelper.generateExtraPropertiesForItem(pickedItemDb, settings.botRole),
}; };
// use dynamic mod pool if enabled in config // Use dynamic mod pool if enabled in config for this bot
const botEquipmentRole = this.botGeneratorHelper.getBotEquipmentRole(settings.botRole); const botEquipmentRole = this.botGeneratorHelper.getBotEquipmentRole(settings.botRole);
if ( if (
this.botConfig.equipment[botEquipmentRole] this.botConfig.equipment[botEquipmentRole]
&& settings.randomisationDetails?.randomisedArmorSlots?.includes(settings.rootEquipmentSlot) && settings.randomisationDetails?.randomisedArmorSlots?.includes(settings.rootEquipmentSlot)
) )
{ {
settings.modPool[equipmentItemTpl] = this.getFilteredDynamicModsForItem( settings.modPool[pickedItemDb._id] = this.getFilteredDynamicModsForItem(
equipmentItemTpl, pickedItemDb._id,
this.botConfig.equipment[botEquipmentRole].blacklist, this.botConfig.equipment[botEquipmentRole].blacklist,
); );
} }
// Item has slots // Item has slots
if ( itemTemplate[1]._props.Slots?.length > 0 ) if ( pickedItemDb._props.Slots?.length > 0 )
{ {
const items = this.botEquipmentModGenerator.generateModsForEquipment( const items = this.botEquipmentModGenerator.generateModsForEquipment(
[item], [item],
id, id,
itemTemplate[1], pickedItemDb,
settings settings
); );
settings.inventory.items.push(...items); settings.inventory.items.push(...items);
} }
else else
{ {
// No slots, push root item only
settings.inventory.items.push(item); settings.inventory.items.push(item);
} }
} }

View File

@ -200,7 +200,9 @@ export class ProbabilityObject<K, V = undefined>
@injectable() @injectable()
export class RandomUtil export class RandomUtil
{ {
constructor(@inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("WinstonLogger") protected logger: ILogger) constructor(
@inject("JsonUtil") protected jsonUtil: JsonUtil,
@inject("WinstonLogger") protected logger: ILogger)
{ {
} }