Improve addItemWithChildrenToEquipmentSlot()
, Make it return different result when:
There are no containers to add item to Unknown reason Improved handling of when container has no space for item Improve `ExternalInventoryMagGen.process()`, Handle edge case when a weapon with a default internal magazine but weapon uses external magazine Improve most locations that call `addItemWithChildrenToEquipmentSlot()` to log failure reason
This commit is contained in:
parent
8c7b5da9ff
commit
3c0e6a34f2
@ -352,13 +352,21 @@ export class BotLootGenerator
|
|||||||
itemsToAdd,
|
itemsToAdd,
|
||||||
inventoryToAddItemsTo,
|
inventoryToAddItemsTo,
|
||||||
);
|
);
|
||||||
if (itemAddedResult === ItemAddedResult.NO_SPACE)
|
if (itemAddedResult !== ItemAddedResult.SUCCESS)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (itemAddedResult === ItemAddedResult.NO_CONTAINERS)
|
||||||
|
{
|
||||||
|
// Bot has no container to put item in, exit
|
||||||
|
this.logger.debug(`Unable to add ${totalItemCount} items to bot as it lacks a container to include them`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
fitItemIntoContainerAttempts++;
|
fitItemIntoContainerAttempts++;
|
||||||
if (fitItemIntoContainerAttempts >= 4)
|
if (fitItemIntoContainerAttempts >= 4)
|
||||||
{
|
{
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Failed to place item ${i} of ${totalItemCount} item into ${botRole} container: ${equipmentSlots}, ${fitItemIntoContainerAttempts} times. No space, skipping`,
|
`Failed to place item ${i} of ${totalItemCount} item into ${botRole} container: ${equipmentSlots}, ${fitItemIntoContainerAttempts} times. ${ItemAddedResult[itemAddedResult]}, skipping`,
|
||||||
);
|
);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -436,7 +444,7 @@ export class BotLootGenerator
|
|||||||
|
|
||||||
if (result !== ItemAddedResult.SUCCESS)
|
if (result !== ItemAddedResult.SUCCESS)
|
||||||
{
|
{
|
||||||
this.logger.debug(`Failed to add additional weapon ${generatedWeapon.weapon[0]._id} to bot backpack, reason: ${result}`);
|
this.logger.debug(`Failed to add additional weapon ${generatedWeapon.weapon[0]._id} to bot backpack, reason: ${ItemAddedResult[result]}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import { IBotType } from "@spt-aki/models/eft/common/tables/IBotType";
|
|||||||
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
|
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
|
||||||
import { AccountTypes } from "@spt-aki/models/enums/AccountTypes";
|
import { AccountTypes } from "@spt-aki/models/enums/AccountTypes";
|
||||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||||
|
import { ItemAddedResult } from "@spt-aki/models/enums/ItemAddedResult";
|
||||||
import { MemberCategory } from "@spt-aki/models/enums/MemberCategory";
|
import { MemberCategory } from "@spt-aki/models/enums/MemberCategory";
|
||||||
import { Traders } from "@spt-aki/models/enums/Traders";
|
import { Traders } from "@spt-aki/models/enums/Traders";
|
||||||
import { IPlayerScavConfig, KarmaLevel } from "@spt-aki/models/spt/config/IPlayerScavConfig";
|
import { IPlayerScavConfig, KarmaLevel } from "@spt-aki/models/spt/config/IPlayerScavConfig";
|
||||||
@ -125,13 +126,18 @@ export class PlayerScavGenerator
|
|||||||
_tpl: labsCard._id,
|
_tpl: labsCard._id,
|
||||||
...this.botGeneratorHelper.generateExtraPropertiesForItem(labsCard),
|
...this.botGeneratorHelper.generateExtraPropertiesForItem(labsCard),
|
||||||
}];
|
}];
|
||||||
this.botWeaponGeneratorHelper.addItemWithChildrenToEquipmentSlot(
|
const result = this.botWeaponGeneratorHelper.addItemWithChildrenToEquipmentSlot(
|
||||||
["TacticalVest", "Pockets", "Backpack"],
|
["TacticalVest", "Pockets", "Backpack"],
|
||||||
itemsToAdd[0]._id,
|
itemsToAdd[0]._id,
|
||||||
labsCard._id,
|
labsCard._id,
|
||||||
itemsToAdd,
|
itemsToAdd,
|
||||||
scavData.Inventory,
|
scavData.Inventory,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (result !== ItemAddedResult.SUCCESS)
|
||||||
|
{
|
||||||
|
this.logger.debug(`Unable to add keycard to bot. Reason: ${ItemAddedResult[result]}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove secure container
|
// Remove secure container
|
||||||
|
@ -4,10 +4,12 @@ import { IInventoryMagGen } from "@spt-aki/generators/weapongen/IInventoryMagGen
|
|||||||
import { InventoryMagGen } from "@spt-aki/generators/weapongen/InventoryMagGen";
|
import { InventoryMagGen } from "@spt-aki/generators/weapongen/InventoryMagGen";
|
||||||
import { BotWeaponGeneratorHelper } from "@spt-aki/helpers/BotWeaponGeneratorHelper";
|
import { BotWeaponGeneratorHelper } from "@spt-aki/helpers/BotWeaponGeneratorHelper";
|
||||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||||
|
import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem";
|
||||||
import { EquipmentSlots } from "@spt-aki/models/enums/EquipmentSlots";
|
import { EquipmentSlots } from "@spt-aki/models/enums/EquipmentSlots";
|
||||||
import { ItemAddedResult } from "@spt-aki/models/enums/ItemAddedResult";
|
import { ItemAddedResult } from "@spt-aki/models/enums/ItemAddedResult";
|
||||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||||
|
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class ExternalInventoryMagGen implements IInventoryMagGen
|
export class ExternalInventoryMagGen implements IInventoryMagGen
|
||||||
@ -17,6 +19,7 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
|
|||||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||||
@inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper,
|
@inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper,
|
||||||
|
@inject("RandomUtil") protected randomUtil: RandomUtil
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -33,8 +36,15 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
|
|||||||
|
|
||||||
process(inventoryMagGen: InventoryMagGen): void
|
process(inventoryMagGen: InventoryMagGen): void
|
||||||
{
|
{
|
||||||
|
// Cout of attempts to fit a magazine into bot inventory
|
||||||
|
let fitAttempts = 0;
|
||||||
|
|
||||||
|
// Magazine Db template
|
||||||
let magTemplate = inventoryMagGen.getMagazineTemplate();
|
let magTemplate = inventoryMagGen.getMagazineTemplate();
|
||||||
let magazineTpl = magTemplate._id;
|
let magazineTpl = magTemplate._id;
|
||||||
|
const weapon = inventoryMagGen.getWeaponTemplate();
|
||||||
|
const attemptedMagBlacklist: string[] = [];
|
||||||
|
const defaultMagazineTpl = this.botWeaponGeneratorHelper.getWeaponsDefaultMagazineTpl(weapon);
|
||||||
const randomizedMagazineCount = Number(
|
const randomizedMagazineCount = Number(
|
||||||
this.botWeaponGeneratorHelper.getRandomizedMagazineCount(inventoryMagGen.getMagCount()),
|
this.botWeaponGeneratorHelper.getRandomizedMagazineCount(inventoryMagGen.getMagCount()),
|
||||||
);
|
);
|
||||||
@ -46,7 +56,7 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
|
|||||||
magTemplate,
|
magTemplate,
|
||||||
);
|
);
|
||||||
|
|
||||||
const ableToFitMagazinesIntoBotInventory = this.botWeaponGeneratorHelper.addItemWithChildrenToEquipmentSlot(
|
const fitsIntoInventory = this.botWeaponGeneratorHelper.addItemWithChildrenToEquipmentSlot(
|
||||||
[EquipmentSlots.TACTICAL_VEST, EquipmentSlots.POCKETS],
|
[EquipmentSlots.TACTICAL_VEST, EquipmentSlots.POCKETS],
|
||||||
magazineWithAmmo[0]._id,
|
magazineWithAmmo[0]._id,
|
||||||
magazineTpl,
|
magazineTpl,
|
||||||
@ -54,43 +64,104 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
|
|||||||
inventoryMagGen.getPmcInventory(),
|
inventoryMagGen.getPmcInventory(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (ableToFitMagazinesIntoBotInventory === ItemAddedResult.NO_SPACE && i < randomizedMagazineCount)
|
if (fitsIntoInventory === ItemAddedResult.NO_CONTAINERS)
|
||||||
{
|
{
|
||||||
|
// No containers to fit magazines, stop trying
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// No space for magazine and we haven't reached desired magazine count
|
||||||
|
else if (fitsIntoInventory === ItemAddedResult.NO_SPACE && i < randomizedMagazineCount)
|
||||||
|
{
|
||||||
|
// Prevent infinite loop by only allowing 5 attempts at fitting a magazine into inventory
|
||||||
|
if (fitAttempts > 5)
|
||||||
|
{
|
||||||
|
this.logger.debug(`Failed ${fitAttempts} times to add magazine ${magazineTpl} to bot inventory, stopping`);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* We were unable to fit at least the minimum amount of magazines,
|
/* We were unable to fit at least the minimum amount of magazines,
|
||||||
* so we fallback to default magazine and try again.
|
* so we fallback to default magazine and try again.
|
||||||
* Temporary workaround to Killa spawning with no extras if he spawns with a drum mag */
|
* Temporary workaround to Killa spawning with no extra mags if he spawns with a drum mag */
|
||||||
|
|
||||||
if (
|
if (magazineTpl === defaultMagazineTpl)
|
||||||
magazineTpl
|
|
||||||
=== this.botWeaponGeneratorHelper.getWeaponsDefaultMagazineTpl(
|
|
||||||
inventoryMagGen.getWeaponTemplate(),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// We were already on default - stop here to prevent infinite looping
|
// We were already on default - stop here to prevent infinite looping
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get default magazine tpl, reset loop counter by 1 and try again
|
// Add failed magazine tpl to blacklist
|
||||||
magazineTpl = this.botWeaponGeneratorHelper.getWeaponsDefaultMagazineTpl(
|
attemptedMagBlacklist.push(magazineTpl);
|
||||||
inventoryMagGen.getWeaponTemplate(),
|
|
||||||
);
|
// Set chosen magazine tpl to the weapons default magazine tpl and try to fit into inventory next loop
|
||||||
|
magazineTpl = defaultMagazineTpl;
|
||||||
magTemplate = this.itemHelper.getItem(magazineTpl)[1];
|
magTemplate = this.itemHelper.getItem(magazineTpl)[1];
|
||||||
if (!magTemplate)
|
if (!magTemplate)
|
||||||
{
|
{
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
this.localisationService.getText("bot-unable_to_find_default_magazine_item", magazineTpl),
|
this.localisationService.getText("bot-unable_to_find_default_magazine_item", magazineTpl),
|
||||||
);
|
);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Edge case - some weapons (SKS) have an internal magazine as default, choose random non-internal magazine to add to bot instead
|
||||||
if (magTemplate._props.ReloadMagType === "InternalMagazine")
|
if (magTemplate._props.ReloadMagType === "InternalMagazine")
|
||||||
{
|
{
|
||||||
break;
|
const result = this.getRandomExternalMagazineForInternalMagazineGun(inventoryMagGen.getWeaponTemplate()._id, attemptedMagBlacklist);
|
||||||
|
if (!result?._id)
|
||||||
|
{
|
||||||
|
this.logger.debug(`Unable to add additional magazine into bot inventory for weapon: ${weapon._name}, attempted: ${fitAttempts} times`);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
magazineTpl = result._id;
|
||||||
|
magTemplate = result;
|
||||||
|
fitAttempts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reduce loop counter by 1 to ensure we get full cout of desired magazines
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fitsIntoInventory === ItemAddedResult.SUCCESS)
|
||||||
|
{
|
||||||
|
// Reset fit counter now it succeeded
|
||||||
|
fitAttempts = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a random compatible external magazine for a weapon, excluses internal magazines from possible pool
|
||||||
|
* @param weaponTpl Weapon to get mag for
|
||||||
|
* @returns tpl of magazine
|
||||||
|
*/
|
||||||
|
protected getRandomExternalMagazineForInternalMagazineGun(weaponTpl: string, magazineBlacklist: string[]): ITemplateItem
|
||||||
|
{
|
||||||
|
// The mag Slot data for the weapon
|
||||||
|
const magSlot = this.itemHelper.getItem(weaponTpl)[1]._props.Slots.find(x => x._name === "mod_magazine");
|
||||||
|
if (!magSlot)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All possible mags that fit into the weapon excluding blacklisted
|
||||||
|
const magazinePool = magSlot._props.filters[0].Filter.filter(x => !magazineBlacklist.includes(x)).map((x) => this.itemHelper.getItem(x)[1]);
|
||||||
|
if (!magazinePool)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-internal magazines that fit into the weapon
|
||||||
|
const externalMagazineOnlyPool = magazinePool.filter(x => x._props.ReloadMagType !== "InternalMagazine");
|
||||||
|
if (!externalMagazineOnlyPool || externalMagazineOnlyPool?.length === 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Randomly chosen external magazine
|
||||||
|
return this.randomUtil.getArrayValue(externalMagazineOnlyPool);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ export class BotWeaponGeneratorHelper
|
|||||||
|
|
||||||
if (result !== ItemAddedResult.SUCCESS)
|
if (result !== ItemAddedResult.SUCCESS)
|
||||||
{
|
{
|
||||||
this.logger.debug(`Unable to add ammo: ${ammoItem._tpl} to bot equipment, ${ItemAddedResult[result]}`);
|
this.logger.debug(`Unable to add ammo: ${ammoItem._tpl} to bot inventory, ${ItemAddedResult[result]}`);
|
||||||
|
|
||||||
if (result === ItemAddedResult.NO_SPACE)
|
if (result === ItemAddedResult.NO_SPACE)
|
||||||
{
|
{
|
||||||
@ -173,6 +173,7 @@ export class BotWeaponGeneratorHelper
|
|||||||
inventory: Inventory,
|
inventory: Inventory,
|
||||||
): ItemAddedResult
|
): ItemAddedResult
|
||||||
{
|
{
|
||||||
|
let missingContainerCount = 0;
|
||||||
for (const slot of equipmentSlots)
|
for (const slot of equipmentSlots)
|
||||||
{
|
{
|
||||||
// Get container to put item into
|
// Get container to put item into
|
||||||
@ -183,8 +184,15 @@ export class BotWeaponGeneratorHelper
|
|||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Unable to add item: ${
|
`Unable to add item: ${
|
||||||
itemWithChildren[0]._tpl
|
itemWithChildren[0]._tpl
|
||||||
} to: ${slot}, slot missing/bot generated without equipment`,
|
} to: ${slot}, slot missing/bot generated without item in slot`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
missingContainerCount++;
|
||||||
|
if (missingContainerCount === equipmentSlots.length)
|
||||||
|
{
|
||||||
|
return ItemAddedResult.NO_CONTAINERS
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,6 +213,9 @@ export class BotWeaponGeneratorHelper
|
|||||||
// Get x/y grid size of item
|
// Get x/y grid size of item
|
||||||
const itemSize = this.inventoryHelper.getItemSize(parentTpl, parentId, itemWithChildren);
|
const itemSize = this.inventoryHelper.getItemSize(parentTpl, parentId, itemWithChildren);
|
||||||
|
|
||||||
|
// Iterate over each grid in the container and look for a big enough space for the item to be placed in
|
||||||
|
let currentGridCount = 1;
|
||||||
|
const slotGridCount = containerTemplate[1]._props.Grids.length;
|
||||||
for (const slotGrid of containerTemplate[1]._props.Grids)
|
for (const slotGrid of containerTemplate[1]._props.Grids)
|
||||||
{
|
{
|
||||||
// Grid is empty, skip
|
// Grid is empty, skip
|
||||||
@ -267,11 +278,18 @@ export class BotWeaponGeneratorHelper
|
|||||||
return ItemAddedResult.SUCCESS;
|
return ItemAddedResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we've checked all grids in container and reached this point, there's no space for item
|
||||||
|
if (slotGridCount >= currentGridCount)
|
||||||
|
{
|
||||||
|
return ItemAddedResult.NO_SPACE;
|
||||||
|
}
|
||||||
|
currentGridCount++;
|
||||||
|
|
||||||
// Start loop again in next grid of container
|
// Start loop again in next grid of container
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ItemAddedResult.NO_SPACE;
|
return ItemAddedResult.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
export enum ItemAddedResult
|
export enum ItemAddedResult {
|
||||||
{
|
UNKNOWN = -1,
|
||||||
SUCCESS = 1,
|
SUCCESS = 1,
|
||||||
NO_SPACE = 2,
|
NO_SPACE = 2,
|
||||||
|
NO_CONTAINERS = 3
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user