diff --git a/project/src/generators/BotLootGenerator.ts b/project/src/generators/BotLootGenerator.ts index fbc28bf8..df647cc3 100644 --- a/project/src/generators/BotLootGenerator.ts +++ b/project/src/generators/BotLootGenerator.ts @@ -295,7 +295,7 @@ export class BotLootGenerator { const itemToAddTemplate = this.getRandomItemFromPoolByRole(pool, botRole); const id = this.hashUtil.generate(); - const itemsToAdd: Item[] = [{ + let itemsToAdd: Item[] = [{ _id: id, _tpl: itemToAddTemplate._id, ...this.botGeneratorHelper.generateExtraPropertiesForItem(itemToAddTemplate, botRole), @@ -343,6 +343,19 @@ export class BotLootGenerator { this.randomiseAmmoStackSize(isPmc, itemToAddTemplate, itemsToAdd[0]); } + // Must add soft inserts/plates + else if (this.itemHelper.isOfBaseclasses(itemToAddTemplate._id, [BaseClasses.ARMOR, BaseClasses.HEADWEAR, BaseClasses.VEST])) + { + // TODO - replace with config values + const modIncludeedChances = { + mod_nvg: 10, + front_plate: 10, + back_plate: 10, + side_plate: 10 + + } + itemsToAdd = this.itemHelper.addChildSlotItems(itemsToAdd, itemToAddTemplate, modIncludeedChances); + } // Attempt to add item to container(s) const itemAddedResult = this.botWeaponGeneratorHelper.addItemWithChildrenToEquipmentSlot( @@ -376,11 +389,9 @@ export class BotLootGenerator // Reset loop, try again continue; } - else - { - // Item added okay, reset counter for next item - fitItemIntoContainerAttempts = 0; - } + + // Item added okay, reset counter for next item + fitItemIntoContainerAttempts = 0; // Stop adding items to bots pool if rolling total is over total limit if (totalValueLimitRub > 0) diff --git a/project/src/generators/LocationGenerator.ts b/project/src/generators/LocationGenerator.ts index f23c0e62..1414cbc1 100644 --- a/project/src/generators/LocationGenerator.ts +++ b/project/src/generators/LocationGenerator.ts @@ -826,7 +826,7 @@ export class LocationGenerator const itemTemplate = this.itemHelper.getItem(chosenTpl)[1]; // Item array to return - const itemWithMods: Item[] = []; + let itemWithMods: Item[] = []; // Money/Ammo - don't rely on items in spawnPoint.template.Items so we can randomise it ourselves if (this.itemHelper.isOfBaseclasses(chosenTpl, [BaseClasses.MONEY, BaseClasses.AMMO])) @@ -869,7 +869,7 @@ export class LocationGenerator }); if (itemTemplate._props.Slots?.length > 0) { - this.addModsToEquipmentItem(itemWithMods, itemTemplate) + itemWithMods = this.itemHelper.addChildSlotItems(itemWithMods, itemTemplate, this.locationConfig.equipmentLootSettings.modSpawnChancePercent); } } else @@ -1075,7 +1075,7 @@ export class LocationGenerator { if (itemTemplate._props.Slots?.length > 0) { - this.addModsToEquipmentItem(items, itemTemplate) + items = this.itemHelper.addChildSlotItems(items, itemTemplate, this.locationConfig.equipmentLootSettings.modSpawnChancePercent); } } @@ -1085,44 +1085,4 @@ export class LocationGenerator height: height }; } - - /** - * Add mod componenets to an equipment item (head/rig/armor) - * @param modItem - * @param itemTemplate - */ - protected addModsToEquipmentItem(modItem: Item[], itemTemplate: ITemplateItem): void - { - // Add armor plates - for (const slot of itemTemplate._props.Slots) - { - // Check if mod has % chance to be added - const modSpawnChance = this.locationConfig.equipmentLootSettings.modSpawnChancePercent[slot._name.toLowerCase()]; - if (modSpawnChance && !slot._required) - { - // only run chance to not add item if its not a required mod - if (this.randomUtil.getChance100(modSpawnChance)) - { - continue; - } - } - - const possibleTplsForSlot = slot._props.filters[0].Filter ?? []; - if (possibleTplsForSlot.length === 0) - { - this.logger.warning(`Unable to add mod to item: ${itemTemplate._id} ${itemTemplate._name} slot: ${slot._name} as the db pool is empty, skipping`); - - continue; - } - - modItem.push( - { - _id: this.hashUtil.generate(), - _tpl: this.randomUtil.getArrayValue(possibleTplsForSlot), // Choose random tpl from array of compatible - parentId: modItem[0]._id, - slotId: slot._name - } - ) - } - } } diff --git a/project/src/helpers/ItemHelper.ts b/project/src/helpers/ItemHelper.ts index 4929afde..b00ddfa9 100644 --- a/project/src/helpers/ItemHelper.ts +++ b/project/src/helpers/ItemHelper.ts @@ -392,30 +392,30 @@ export class ItemHelper /** * Recursive function that looks at every item from parameter and gets their childrens Ids + includes parent item in results * @param items Array of items (item + possible children) - * @param itemId Parent items id + * @param baseItemId Parent items id * @returns an array of strings */ - public findAndReturnChildrenByItems(items: Item[], itemId: string): string[] + public findAndReturnChildrenByItems(items: Item[], baseItemId: string): string[] { const list: string[] = []; for (const childitem of items) { - if (childitem.parentId === itemId) + if (childitem.parentId === baseItemId) { list.push(...this.findAndReturnChildrenByItems(items, childitem._id)); } } - list.push(itemId); // Required, push original item id onto array + list.push(baseItemId); // Required, push original item id onto array return list; } /** * A variant of findAndReturnChildren where the output is list of item objects instead of their ids. - * @param items - * @param baseItemId + * @param items Array of items (item + possible children) + * @param baseItemId Parent items id * @returns An array of Item objects */ public findAndReturnChildrenAsItems(items: Item[], baseItemId: string): Item[] @@ -974,10 +974,8 @@ export class ItemHelper { return true; } - else - { - return this.itemIsInsideContainer(parent, desiredContainerSlotId, items); - } + + return this.itemIsInsideContainer(parent, desiredContainerSlotId, items); } /** @@ -1169,6 +1167,53 @@ export class ItemHelper x._parent === desiredBaseType ).map((x) => x._id); } + + /** + * Add child slot items to an item, chooses random child item if multiple choices exist + * @param itemToAdd array with single object (root item) + * @param itemToAddTemplate Db tempalte for root item + * @param modSpawnChanceDict Optional dictionary of mod name + % chance mod will be included in item (e.g. front_plate: 100) + * @returns + */ + public addChildSlotItems(itemToAdd: Item[], itemToAddTemplate: ITemplateItem, modSpawnChanceDict: Record = null): Item[] + { + const result = itemToAdd; + for (const slot of itemToAddTemplate._props.Slots) + { + // Roll chance for non-required slot mods + if (modSpawnChanceDict && !slot._required) + { + // only roll chance to not include mod if dict exists and has value for this mod type (e.g. front_plate) + const modSpawnChance = modSpawnChanceDict[slot._name.toLowerCase()]; + if (modSpawnChance) + { + if (!this.randomUtil.getChance100(modSpawnChanceDict[slot._name])) + { + continue; + } + } + } + + const possibleTplsForSlot = slot._props.filters[0].Filter ?? []; + if (possibleTplsForSlot.length === 0) + { + this.logger.warning(`Unable to add mod to item: ${itemToAddTemplate._id} ${itemToAddTemplate._name} slot: ${slot._name} as the db pool is empty, skipping`); + + continue; + } + + result.push( + { + _id: this.hashUtil.generate(), + _tpl: this.randomUtil.getArrayValue(possibleTplsForSlot), // Choose random tpl from array of compatible + parentId: result[0]._id, + slotId: slot._name + } + ) + } + + return result; + } } namespace ItemHelper