Improved pickWeaponModTplForSlotFromPool(), now pre-sorts mod pool prior to adding it to exhaustableModPool and processing

This commit is contained in:
Dev 2024-07-28 00:12:04 +01:00
parent 0c42a38306
commit af33625a5c
2 changed files with 43 additions and 26 deletions

View File

@ -847,12 +847,29 @@ export class BotEquipmentModGenerator {
modSlotName: string,
): IChooseRandomCompatibleModResult {
let chosenTpl: string;
const exhaustableModPool = new ExhaustableArray(modPool, this.randomUtil, this.cloner);
// Filter out incompatable mods from pool
let preFilteredModPool = this.getFilteredModPool(modPool, weapon);
if (preFilteredModPool.length === 0) {
return {
incompatible: true,
found: false,
reason: `Unable to add mod to ${ModSpawn[choiceTypeEnum]} slot: ${modSlotName}. All: ${modPool.length} had conflicts`,
};
}
// Filter mod pool to only items that appear in parents allowed list
preFilteredModPool = preFilteredModPool.filter((tpl) => parentSlot._props.filters[0].Filter.includes(tpl));
if (preFilteredModPool.length === 0) {
return { incompatible: true, found: false, reason: "No mods found in parents allowed list" };
}
// Create pool to pick mod item from
const exhaustableModPool = new ExhaustableArray(preFilteredModPool, this.randomUtil, this.cloner);
let chosenModResult: IChooseRandomCompatibleModResult = { incompatible: true, found: false, reason: "unknown" };
const modParentFilterList = parentSlot._props.filters[0].Filter;
// How many times can a mod for the slot be blocked before we stop trying
const maxBlockedAttempts = Math.round(modPool.length * 0.75); // Roughly 75% of pool size
const maxBlockedAttempts = Math.round(modPool.length * 0.75); // 75% of pool size
let blockedAttemptCount = 0;
while (exhaustableModPool.hasValues()) {
chosenTpl = exhaustableModPool.getRandomValue();
@ -865,13 +882,6 @@ export class BotEquipmentModGenerator {
break;
}
// Check chosen item is on the allowed list of the parent
const isOnModParentFilterList = modParentFilterList.includes(chosenTpl);
if (!isOnModParentFilterList) {
// Try again
continue;
}
chosenModResult = this.botGeneratorHelper.isWeaponModIncompatibleWithCurrentMods(
weapon,
chosenTpl,
@ -905,6 +915,19 @@ export class BotEquipmentModGenerator {
return chosenModResult;
}
/**
* Get a list of mod tpls that are compatible with the current weapon
* @param initialModPool
* @param weapon
* @returns string array of compatible mod tpls with weapon
*/
protected getFilteredModPool(initialModPool: string[], weapon: Item[]): string[] {
const equippedItemsDb = weapon.map((item) => this.itemHelper.getItem(item._tpl)[1]);
const conflicingItemsList = equippedItemsDb.flatMap((item) => item._props.ConflictingItems);
return initialModPool.filter((tpl) => !conflicingItemsList.includes(tpl));
}
/**
* Filter mod pool down based on various criteria:
* Is slot flagged as randomisable

View File

@ -250,13 +250,18 @@ export class BotGeneratorHelper {
return { Durability: currentDurability, MaxDurability: maxDurability };
}
/**
* Perform validation checks on mod tpl against rest of weapon child items
* @param weapon all items in weapon
* @param tplToCheck Chosen tpl
* @param modSlot Slot mod will be placed in
* @returns IChooseRandomCompatibleModResult
*/
public isWeaponModIncompatibleWithCurrentMods(
itemsEquipped: Item[],
weapon: Item[],
tplToCheck: string,
modSlot: string,
): IChooseRandomCompatibleModResult {
// TODO: Can probably be optimized to cache itemTemplates as items are added to inventory
const equippedItemsDb = itemsEquipped.map((item) => this.itemHelper.getItem(item._tpl)[1]);
const itemToEquipDb = this.itemHelper.getItem(tplToCheck);
const itemToEquip = itemToEquipDb[1];
@ -284,19 +289,8 @@ export class BotGeneratorHelper {
return { incompatible: true, found: false, reason: `item: ${tplToCheck} does not have a _props field` };
}
// Check if any of the current weapon mod templates have the incoming item defined as incompatible
const blockingItem = equippedItemsDb.find((x) => x._props.ConflictingItems?.includes(tplToCheck));
if (blockingItem) {
return {
incompatible: true,
found: false,
reason: `Cannot add: ${tplToCheck} ${itemToEquip._name} to slot: ${modSlot}. Blocked by: ${blockingItem._id} ${blockingItem._name}`,
slotBlocked: true,
};
}
// Check inverse to above, if the incoming item has any existing mods in its conflicting items array
const blockingModItem = itemsEquipped.find((item) => itemToEquip._props.ConflictingItems?.includes(item._tpl));
// Check for existing weapon mods being incompatable with new item
const blockingModItem = weapon.find((item) => itemToEquip._props.ConflictingItems?.includes(item._tpl));
if (blockingModItem) {
return {
incompatible: true,