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,
|
||||
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++;
|
||||
if (fitItemIntoContainerAttempts >= 4)
|
||||
{
|
||||
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;
|
||||
@ -436,7 +444,7 @@ export class BotLootGenerator
|
||||
|
||||
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 { AccountTypes } from "@spt-aki/models/enums/AccountTypes";
|
||||
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 { Traders } from "@spt-aki/models/enums/Traders";
|
||||
import { IPlayerScavConfig, KarmaLevel } from "@spt-aki/models/spt/config/IPlayerScavConfig";
|
||||
@ -125,13 +126,18 @@ export class PlayerScavGenerator
|
||||
_tpl: labsCard._id,
|
||||
...this.botGeneratorHelper.generateExtraPropertiesForItem(labsCard),
|
||||
}];
|
||||
this.botWeaponGeneratorHelper.addItemWithChildrenToEquipmentSlot(
|
||||
const result = this.botWeaponGeneratorHelper.addItemWithChildrenToEquipmentSlot(
|
||||
["TacticalVest", "Pockets", "Backpack"],
|
||||
itemsToAdd[0]._id,
|
||||
labsCard._id,
|
||||
itemsToAdd,
|
||||
scavData.Inventory,
|
||||
);
|
||||
|
||||
if (result !== ItemAddedResult.SUCCESS)
|
||||
{
|
||||
this.logger.debug(`Unable to add keycard to bot. Reason: ${ItemAddedResult[result]}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove secure container
|
||||
|
@ -4,10 +4,12 @@ import { IInventoryMagGen } from "@spt-aki/generators/weapongen/IInventoryMagGen
|
||||
import { InventoryMagGen } from "@spt-aki/generators/weapongen/InventoryMagGen";
|
||||
import { BotWeaponGeneratorHelper } from "@spt-aki/helpers/BotWeaponGeneratorHelper";
|
||||
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 { ItemAddedResult } from "@spt-aki/models/enums/ItemAddedResult";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
|
||||
@injectable()
|
||||
export class ExternalInventoryMagGen implements IInventoryMagGen
|
||||
@ -17,6 +19,7 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("BotWeaponGeneratorHelper") protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper,
|
||||
@inject("RandomUtil") protected randomUtil: RandomUtil
|
||||
)
|
||||
{}
|
||||
|
||||
@ -33,8 +36,15 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
|
||||
|
||||
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 magazineTpl = magTemplate._id;
|
||||
const weapon = inventoryMagGen.getWeaponTemplate();
|
||||
const attemptedMagBlacklist: string[] = [];
|
||||
const defaultMagazineTpl = this.botWeaponGeneratorHelper.getWeaponsDefaultMagazineTpl(weapon);
|
||||
const randomizedMagazineCount = Number(
|
||||
this.botWeaponGeneratorHelper.getRandomizedMagazineCount(inventoryMagGen.getMagCount()),
|
||||
);
|
||||
@ -46,7 +56,7 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
|
||||
magTemplate,
|
||||
);
|
||||
|
||||
const ableToFitMagazinesIntoBotInventory = this.botWeaponGeneratorHelper.addItemWithChildrenToEquipmentSlot(
|
||||
const fitsIntoInventory = this.botWeaponGeneratorHelper.addItemWithChildrenToEquipmentSlot(
|
||||
[EquipmentSlots.TACTICAL_VEST, EquipmentSlots.POCKETS],
|
||||
magazineWithAmmo[0]._id,
|
||||
magazineTpl,
|
||||
@ -54,43 +64,104 @@ export class ExternalInventoryMagGen implements IInventoryMagGen
|
||||
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,
|
||||
* 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 (
|
||||
magazineTpl
|
||||
=== this.botWeaponGeneratorHelper.getWeaponsDefaultMagazineTpl(
|
||||
inventoryMagGen.getWeaponTemplate(),
|
||||
)
|
||||
)
|
||||
if (magazineTpl === defaultMagazineTpl)
|
||||
{
|
||||
// We were already on default - stop here to prevent infinite looping
|
||||
break;
|
||||
}
|
||||
|
||||
// Get default magazine tpl, reset loop counter by 1 and try again
|
||||
magazineTpl = this.botWeaponGeneratorHelper.getWeaponsDefaultMagazineTpl(
|
||||
inventoryMagGen.getWeaponTemplate(),
|
||||
);
|
||||
// Add failed magazine tpl to blacklist
|
||||
attemptedMagBlacklist.push(magazineTpl);
|
||||
|
||||
// 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];
|
||||
if (!magTemplate)
|
||||
{
|
||||
this.logger.error(
|
||||
this.localisationService.getText("bot-unable_to_find_default_magazine_item", magazineTpl),
|
||||
);
|
||||
|
||||
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")
|
||||
{
|
||||
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--;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -173,6 +173,7 @@ export class BotWeaponGeneratorHelper
|
||||
inventory: Inventory,
|
||||
): ItemAddedResult
|
||||
{
|
||||
let missingContainerCount = 0;
|
||||
for (const slot of equipmentSlots)
|
||||
{
|
||||
// Get container to put item into
|
||||
@ -183,8 +184,15 @@ export class BotWeaponGeneratorHelper
|
||||
this.logger.debug(
|
||||
`Unable to add item: ${
|
||||
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;
|
||||
}
|
||||
|
||||
@ -205,6 +213,9 @@ export class BotWeaponGeneratorHelper
|
||||
// Get x/y grid size of item
|
||||
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)
|
||||
{
|
||||
// Grid is empty, skip
|
||||
@ -267,11 +278,18 @@ export class BotWeaponGeneratorHelper
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
return ItemAddedResult.NO_SPACE;
|
||||
return ItemAddedResult.UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,6 @@
|
||||
export enum ItemAddedResult
|
||||
{
|
||||
export enum ItemAddedResult {
|
||||
UNKNOWN = -1,
|
||||
SUCCESS = 1,
|
||||
NO_SPACE = 2,
|
||||
NO_CONTAINERS = 3
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user