Fix armor in bot backpacks having no soft inserts

centralise code that adds mods to equipment into one location
This commit is contained in:
Dev 2024-01-08 23:27:18 +00:00
parent 0efd2861c7
commit 15d53a2d38
3 changed files with 75 additions and 59 deletions

View File

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

View File

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

View File

@ -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<string, number> = 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