2023-03-03 15:23:46 +00:00
|
|
|
import { inject, injectable } from "tsyringe";
|
|
|
|
|
2023-10-19 17:21:17 +00:00
|
|
|
import { BotWeaponGenerator } from "@spt-aki/generators/BotWeaponGenerator";
|
|
|
|
import { BotGeneratorHelper } from "@spt-aki/helpers/BotGeneratorHelper";
|
2024-02-22 16:34:15 +00:00
|
|
|
import { BotHelper } from "@spt-aki/helpers/BotHelper";
|
2023-10-19 17:21:17 +00:00
|
|
|
import { HandbookHelper } from "@spt-aki/helpers/HandbookHelper";
|
2024-02-22 13:52:59 +00:00
|
|
|
import { InventoryHelper } from "@spt-aki/helpers/InventoryHelper";
|
2023-10-19 17:21:17 +00:00
|
|
|
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
|
|
|
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
|
|
|
|
import { Inventory as PmcInventory } from "@spt-aki/models/eft/common/tables/IBotBase";
|
|
|
|
import { IBotType, Inventory, ModsChances } from "@spt-aki/models/eft/common/tables/IBotType";
|
|
|
|
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
|
|
|
|
import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem";
|
|
|
|
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
|
|
|
|
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
|
|
|
import { EquipmentSlots } from "@spt-aki/models/enums/EquipmentSlots";
|
|
|
|
import { ItemAddedResult } from "@spt-aki/models/enums/ItemAddedResult";
|
|
|
|
import { LootCacheType } from "@spt-aki/models/spt/bots/IBotLootCache";
|
2024-02-22 16:34:15 +00:00
|
|
|
import { IItemSpawnLimitSettings } from "@spt-aki/models/spt/bots/IItemSpawnLimitSettings";
|
2023-10-19 17:21:17 +00:00
|
|
|
import { IBotConfig } from "@spt-aki/models/spt/config/IBotConfig";
|
|
|
|
import { IPmcConfig } from "@spt-aki/models/spt/config/IPmcConfig";
|
|
|
|
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
|
|
|
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
|
|
|
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
|
|
|
import { BotLootCacheService } from "@spt-aki/services/BotLootCacheService";
|
|
|
|
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
|
|
|
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
2024-02-22 13:52:59 +00:00
|
|
|
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
2023-10-19 17:21:17 +00:00
|
|
|
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
2023-03-03 15:23:46 +00:00
|
|
|
|
|
|
|
@injectable()
|
|
|
|
export class BotLootGenerator
|
|
|
|
{
|
|
|
|
protected botConfig: IBotConfig;
|
2023-10-10 11:03:20 +00:00
|
|
|
protected pmcConfig: IPmcConfig;
|
2023-11-16 21:42:06 +00:00
|
|
|
|
2023-03-03 15:23:46 +00:00
|
|
|
constructor(
|
|
|
|
@inject("WinstonLogger") protected logger: ILogger,
|
|
|
|
@inject("HashUtil") protected hashUtil: HashUtil,
|
|
|
|
@inject("RandomUtil") protected randomUtil: RandomUtil,
|
|
|
|
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
2024-02-22 13:52:59 +00:00
|
|
|
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
|
|
|
@inject("InventoryHelper") protected inventoryHelper: InventoryHelper,
|
2023-03-03 15:23:46 +00:00
|
|
|
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
|
|
|
@inject("HandbookHelper") protected handbookHelper: HandbookHelper,
|
|
|
|
@inject("BotGeneratorHelper") protected botGeneratorHelper: BotGeneratorHelper,
|
|
|
|
@inject("BotWeaponGenerator") protected botWeaponGenerator: BotWeaponGenerator,
|
2023-10-10 11:03:20 +00:00
|
|
|
@inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper,
|
2024-02-22 16:34:15 +00:00
|
|
|
@inject("BotHelper") protected botHelper: BotHelper,
|
2023-03-03 15:23:46 +00:00
|
|
|
@inject("BotLootCacheService") protected botLootCacheService: BotLootCacheService,
|
|
|
|
@inject("LocalisationService") protected localisationService: LocalisationService,
|
2023-11-16 21:42:06 +00:00
|
|
|
@inject("ConfigServer") protected configServer: ConfigServer,
|
2023-03-03 15:23:46 +00:00
|
|
|
)
|
|
|
|
{
|
|
|
|
this.botConfig = this.configServer.getConfig(ConfigTypes.BOT);
|
2023-10-10 11:03:20 +00:00
|
|
|
this.pmcConfig = this.configServer.getConfig(ConfigTypes.PMC);
|
2023-03-03 15:23:46 +00:00
|
|
|
}
|
|
|
|
|
2024-02-22 16:34:15 +00:00
|
|
|
protected getItemSpawnLimitsForBot(botRole: string): IItemSpawnLimitSettings
|
|
|
|
{
|
|
|
|
// Init item limits
|
|
|
|
const limitsForBotDict: Record<string, number> = {};
|
|
|
|
this.initItemLimitArray(botRole, limitsForBotDict);
|
|
|
|
|
|
|
|
return { currentLimits: limitsForBotDict, globalLimits: this.getItemSpawnLimitsForBotType(botRole) };
|
|
|
|
}
|
|
|
|
|
2023-03-03 15:23:46 +00:00
|
|
|
/**
|
|
|
|
* Add loot to bots containers
|
|
|
|
* @param sessionId Session id
|
2023-03-17 18:20:16 +00:00
|
|
|
* @param botJsonTemplate Base json db file for the bot having its loot generated
|
2023-03-03 15:23:46 +00:00
|
|
|
* @param isPmc Will bot be a pmc
|
|
|
|
* @param botRole Role of bot, e.g. asssult
|
|
|
|
* @param botInventory Inventory to add loot to
|
|
|
|
* @param botLevel Level of bot
|
|
|
|
*/
|
2023-11-16 21:42:06 +00:00
|
|
|
public generateLoot(
|
|
|
|
sessionId: string,
|
|
|
|
botJsonTemplate: IBotType,
|
|
|
|
isPmc: boolean,
|
|
|
|
botRole: string,
|
|
|
|
botInventory: PmcInventory,
|
|
|
|
botLevel: number,
|
|
|
|
): void
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
2023-03-17 18:20:16 +00:00
|
|
|
// Limits on item types to be added as loot
|
|
|
|
const itemCounts = botJsonTemplate.generation.items;
|
2023-11-16 21:42:06 +00:00
|
|
|
|
2024-02-21 17:36:27 +00:00
|
|
|
const backpackLootCount = Number(
|
|
|
|
this.weightedRandomHelper.getWeightedValue<number>(itemCounts.backpackLoot.weights),
|
|
|
|
);
|
|
|
|
const pocketLootCount = Number(
|
|
|
|
this.weightedRandomHelper.getWeightedValue<number>(itemCounts.pocketLoot.weights),
|
|
|
|
);
|
2023-10-10 11:03:20 +00:00
|
|
|
const vestLootCount = this.weightedRandomHelper.getWeightedValue<number>(itemCounts.vestLoot.weights);
|
2024-02-21 17:36:27 +00:00
|
|
|
const specialLootItemCount = Number(
|
|
|
|
this.weightedRandomHelper.getWeightedValue<number>(itemCounts.specialItems.weights),
|
2023-11-16 21:42:06 +00:00
|
|
|
);
|
2024-02-21 17:36:27 +00:00
|
|
|
const healingItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.healing.weights));
|
|
|
|
const drugItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.drugs.weights));
|
|
|
|
const stimItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.stims.weights));
|
|
|
|
const grenadeCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.grenades.weights));
|
2023-03-03 15:23:46 +00:00
|
|
|
|
2023-07-27 12:15:06 +01:00
|
|
|
// Forced pmc healing loot
|
2023-10-10 11:03:20 +00:00
|
|
|
if (isPmc && this.pmcConfig.forceHealingItemsIntoSecure)
|
2023-07-27 12:15:06 +01:00
|
|
|
{
|
|
|
|
this.addForcedMedicalItemsToPmcSecure(botInventory, botRole);
|
|
|
|
}
|
|
|
|
|
2024-02-22 16:34:15 +00:00
|
|
|
const botItemLimits = this.getItemSpawnLimitsForBot(botRole);
|
|
|
|
|
2023-10-10 11:03:20 +00:00
|
|
|
const containersBotHasAvailable = this.getAvailableContainersBotCanStoreItemsIn(botInventory);
|
|
|
|
|
2023-03-03 15:23:46 +00:00
|
|
|
// Special items
|
|
|
|
this.addLootFromPool(
|
2023-03-17 18:20:16 +00:00
|
|
|
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SPECIAL, botJsonTemplate),
|
2023-10-10 11:03:20 +00:00
|
|
|
containersBotHasAvailable,
|
2023-03-03 15:23:46 +00:00
|
|
|
specialLootItemCount,
|
|
|
|
botInventory,
|
2023-11-16 21:42:06 +00:00
|
|
|
botRole,
|
2024-02-22 16:34:15 +00:00
|
|
|
botItemLimits,
|
2023-11-16 21:42:06 +00:00
|
|
|
);
|
2023-03-03 15:23:46 +00:00
|
|
|
|
2023-10-12 13:25:13 +01:00
|
|
|
// Healing items / Meds
|
2023-03-03 15:23:46 +00:00
|
|
|
this.addLootFromPool(
|
2023-03-17 18:20:16 +00:00
|
|
|
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.HEALING_ITEMS, botJsonTemplate),
|
2023-10-10 11:03:20 +00:00
|
|
|
containersBotHasAvailable,
|
2023-03-03 15:23:46 +00:00
|
|
|
healingItemCount,
|
|
|
|
botInventory,
|
|
|
|
botRole,
|
2024-02-22 16:34:15 +00:00
|
|
|
null,
|
2023-03-03 15:23:46 +00:00
|
|
|
0,
|
2023-11-16 21:42:06 +00:00
|
|
|
isPmc,
|
|
|
|
);
|
2023-03-03 15:23:46 +00:00
|
|
|
|
|
|
|
// Drugs
|
|
|
|
this.addLootFromPool(
|
2023-03-17 18:20:16 +00:00
|
|
|
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.DRUG_ITEMS, botJsonTemplate),
|
2023-10-10 11:03:20 +00:00
|
|
|
containersBotHasAvailable,
|
2023-03-03 15:23:46 +00:00
|
|
|
drugItemCount,
|
|
|
|
botInventory,
|
|
|
|
botRole,
|
2024-02-22 16:34:15 +00:00
|
|
|
null,
|
2023-03-03 15:23:46 +00:00
|
|
|
0,
|
2023-11-16 21:42:06 +00:00
|
|
|
isPmc,
|
|
|
|
);
|
2023-03-03 15:23:46 +00:00
|
|
|
|
|
|
|
// Stims
|
|
|
|
this.addLootFromPool(
|
2023-03-17 18:20:16 +00:00
|
|
|
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.STIM_ITEMS, botJsonTemplate),
|
2023-10-10 11:03:20 +00:00
|
|
|
containersBotHasAvailable,
|
2023-03-03 15:23:46 +00:00
|
|
|
stimItemCount,
|
|
|
|
botInventory,
|
|
|
|
botRole,
|
2024-02-22 16:34:15 +00:00
|
|
|
botItemLimits,
|
2023-03-03 15:23:46 +00:00
|
|
|
0,
|
2023-11-16 21:42:06 +00:00
|
|
|
isPmc,
|
|
|
|
);
|
2023-03-03 15:23:46 +00:00
|
|
|
|
|
|
|
// Grenades
|
|
|
|
this.addLootFromPool(
|
2023-03-17 18:20:16 +00:00
|
|
|
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.GRENADE_ITEMS, botJsonTemplate),
|
2023-10-10 11:03:20 +00:00
|
|
|
[EquipmentSlots.POCKETS, EquipmentSlots.TACTICAL_VEST], // Can't use containersBotHasEquipped as we dont want grenades added to backpack
|
2023-03-03 15:23:46 +00:00
|
|
|
grenadeCount,
|
|
|
|
botInventory,
|
|
|
|
botRole,
|
2024-02-22 16:34:15 +00:00
|
|
|
null,
|
2023-03-03 15:23:46 +00:00
|
|
|
0,
|
2023-11-16 21:42:06 +00:00
|
|
|
isPmc,
|
|
|
|
);
|
2023-03-03 15:23:46 +00:00
|
|
|
|
2023-07-24 13:20:17 +01:00
|
|
|
// Backpack - generate loot if they have one
|
2023-10-10 11:03:20 +00:00
|
|
|
if (containersBotHasAvailable.includes(EquipmentSlots.BACKPACK))
|
2023-07-24 13:20:17 +01:00
|
|
|
{
|
|
|
|
// Add randomly generated weapon to PMC backpacks
|
2023-10-10 11:03:20 +00:00
|
|
|
if (isPmc && this.randomUtil.getChance100(this.pmcConfig.looseWeaponInBackpackChancePercent))
|
2023-07-24 13:20:17 +01:00
|
|
|
{
|
2023-11-16 21:42:06 +00:00
|
|
|
this.addLooseWeaponsToInventorySlot(
|
|
|
|
sessionId,
|
|
|
|
botInventory,
|
|
|
|
EquipmentSlots.BACKPACK,
|
|
|
|
botJsonTemplate.inventory,
|
2024-01-09 15:31:56 +00:00
|
|
|
botJsonTemplate.chances.weaponMods,
|
2023-11-16 21:42:06 +00:00
|
|
|
botRole,
|
|
|
|
isPmc,
|
|
|
|
botLevel,
|
|
|
|
);
|
2023-07-24 13:20:17 +01:00
|
|
|
}
|
2023-03-03 15:23:46 +00:00
|
|
|
|
2023-07-24 13:20:17 +01:00
|
|
|
this.addLootFromPool(
|
|
|
|
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.BACKPACK, botJsonTemplate),
|
|
|
|
[EquipmentSlots.BACKPACK],
|
2023-10-10 11:03:20 +00:00
|
|
|
backpackLootCount,
|
2023-07-24 13:20:17 +01:00
|
|
|
botInventory,
|
|
|
|
botRole,
|
2024-02-22 16:34:15 +00:00
|
|
|
botItemLimits,
|
2023-10-10 11:03:20 +00:00
|
|
|
this.pmcConfig.maxBackpackLootTotalRub,
|
2023-11-16 21:42:06 +00:00
|
|
|
isPmc,
|
|
|
|
);
|
2023-07-24 13:20:17 +01:00
|
|
|
}
|
2023-11-16 21:42:06 +00:00
|
|
|
|
2023-10-10 11:03:20 +00:00
|
|
|
// TacticalVest - generate loot if they have one
|
|
|
|
if (containersBotHasAvailable.includes(EquipmentSlots.TACTICAL_VEST))
|
|
|
|
{
|
|
|
|
// Vest
|
|
|
|
this.addLootFromPool(
|
|
|
|
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.VEST, botJsonTemplate),
|
|
|
|
[EquipmentSlots.TACTICAL_VEST],
|
|
|
|
vestLootCount,
|
|
|
|
botInventory,
|
|
|
|
botRole,
|
2024-02-22 16:34:15 +00:00
|
|
|
botItemLimits,
|
2023-10-10 11:03:20 +00:00
|
|
|
this.pmcConfig.maxVestLootTotalRub,
|
2023-11-16 21:42:06 +00:00
|
|
|
isPmc,
|
|
|
|
);
|
2023-10-10 11:03:20 +00:00
|
|
|
}
|
|
|
|
|
2023-03-03 15:23:46 +00:00
|
|
|
// Pockets
|
|
|
|
this.addLootFromPool(
|
2023-03-17 18:20:16 +00:00
|
|
|
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.POCKET, botJsonTemplate),
|
2023-03-03 15:23:46 +00:00
|
|
|
[EquipmentSlots.POCKETS],
|
|
|
|
pocketLootCount,
|
|
|
|
botInventory,
|
|
|
|
botRole,
|
2024-02-22 16:34:15 +00:00
|
|
|
botItemLimits,
|
2023-10-10 11:03:20 +00:00
|
|
|
this.pmcConfig.maxPocketLootTotalRub,
|
2023-11-16 21:42:06 +00:00
|
|
|
isPmc,
|
|
|
|
);
|
2024-01-18 12:07:32 +00:00
|
|
|
|
|
|
|
// Secure
|
|
|
|
this.addLootFromPool(
|
|
|
|
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SECURE, botJsonTemplate),
|
|
|
|
[EquipmentSlots.SECURED_CONTAINER],
|
2024-01-19 19:21:51 +00:00
|
|
|
50,
|
2024-01-18 12:07:32 +00:00
|
|
|
botInventory,
|
|
|
|
botRole,
|
2024-02-22 16:34:15 +00:00
|
|
|
null,
|
2024-01-18 12:07:32 +00:00
|
|
|
-1,
|
|
|
|
isPmc,
|
|
|
|
);
|
2023-03-03 15:23:46 +00:00
|
|
|
}
|
|
|
|
|
2023-10-10 11:03:20 +00:00
|
|
|
/**
|
|
|
|
* Get an array of the containers a bot has on them (pockets/backpack/vest)
|
|
|
|
* @param botInventory Bot to check
|
|
|
|
* @returns Array of available slots
|
|
|
|
*/
|
|
|
|
protected getAvailableContainersBotCanStoreItemsIn(botInventory: PmcInventory): EquipmentSlots[]
|
|
|
|
{
|
|
|
|
const result = [EquipmentSlots.POCKETS];
|
|
|
|
|
2024-02-21 17:36:27 +00:00
|
|
|
if (botInventory.items.find((item) => item.slotId === EquipmentSlots.TACTICAL_VEST))
|
2023-10-10 11:03:20 +00:00
|
|
|
{
|
|
|
|
result.push(EquipmentSlots.TACTICAL_VEST);
|
|
|
|
}
|
|
|
|
|
2024-02-21 17:36:27 +00:00
|
|
|
if (botInventory.items.find((item) => item.slotId === EquipmentSlots.BACKPACK))
|
2023-10-10 11:03:20 +00:00
|
|
|
{
|
|
|
|
result.push(EquipmentSlots.BACKPACK);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-07-27 12:15:06 +01:00
|
|
|
/**
|
|
|
|
* Force healing items onto bot to ensure they can heal in-raid
|
|
|
|
* @param botInventory Inventory to add items to
|
|
|
|
* @param botRole Role of bot (sptBear/sptUsec)
|
|
|
|
*/
|
|
|
|
protected addForcedMedicalItemsToPmcSecure(botInventory: PmcInventory, botRole: string): void
|
|
|
|
{
|
2024-02-21 17:36:27 +00:00
|
|
|
// Grizzly
|
|
|
|
this.addLootFromPool(
|
|
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
|
|
{ "590c657e86f77412b013051d": 1 },
|
|
|
|
[EquipmentSlots.SECURED_CONTAINER],
|
|
|
|
1,
|
|
|
|
botInventory,
|
|
|
|
botRole,
|
2024-02-22 16:34:15 +00:00
|
|
|
null,
|
2024-02-21 17:36:27 +00:00
|
|
|
0,
|
|
|
|
true,
|
|
|
|
);
|
2023-07-27 12:15:06 +01:00
|
|
|
|
2024-02-21 17:36:27 +00:00
|
|
|
// surv12
|
|
|
|
this.addLootFromPool(
|
|
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
|
|
{ "5d02797c86f774203f38e30a": 1 },
|
|
|
|
[EquipmentSlots.SECURED_CONTAINER],
|
|
|
|
1,
|
|
|
|
botInventory,
|
|
|
|
botRole,
|
2024-02-22 16:34:15 +00:00
|
|
|
null,
|
2024-02-21 17:36:27 +00:00
|
|
|
0,
|
|
|
|
true,
|
|
|
|
);
|
2023-07-27 12:15:06 +01:00
|
|
|
|
2024-02-21 17:36:27 +00:00
|
|
|
// Morphine
|
|
|
|
this.addLootFromPool(
|
|
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
|
|
{ "544fb3f34bdc2d03748b456a": 1 },
|
|
|
|
[EquipmentSlots.SECURED_CONTAINER],
|
|
|
|
2,
|
|
|
|
botInventory,
|
|
|
|
botRole,
|
2024-02-22 16:34:15 +00:00
|
|
|
null,
|
2024-02-21 17:36:27 +00:00
|
|
|
0,
|
|
|
|
true,
|
|
|
|
);
|
2023-07-27 15:01:08 +01:00
|
|
|
|
2024-02-21 17:36:27 +00:00
|
|
|
// AFAK
|
|
|
|
this.addLootFromPool(
|
|
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
|
|
{ "60098ad7c2240c0fe85c570a": 1 },
|
|
|
|
[EquipmentSlots.SECURED_CONTAINER],
|
|
|
|
2,
|
|
|
|
botInventory,
|
|
|
|
botRole,
|
2024-02-22 16:34:15 +00:00
|
|
|
null,
|
2024-02-21 17:36:27 +00:00
|
|
|
0,
|
|
|
|
true,
|
|
|
|
);
|
2023-07-27 12:15:06 +01:00
|
|
|
}
|
|
|
|
|
2023-10-10 11:03:20 +00:00
|
|
|
/**
|
|
|
|
* Get a biased random number
|
|
|
|
* @param min Smallest size
|
|
|
|
* @param max Biggest size
|
|
|
|
* @param nValue Value to bias choice
|
|
|
|
* @returns Chosen number
|
|
|
|
*/
|
2023-03-03 15:23:46 +00:00
|
|
|
protected getRandomisedCount(min: number, max: number, nValue: number): number
|
|
|
|
{
|
|
|
|
const range = max - min;
|
|
|
|
return this.randomUtil.getBiasedRandomNumber(min, max, range, nValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-01-19 11:57:25 +00:00
|
|
|
* Take random items from a pool and add to an inventory until totalItemCount or totalValueLimit or space limit is reached
|
2024-02-21 17:36:27 +00:00
|
|
|
* @param pool Pool of items to pick from with weight
|
2023-10-10 11:03:20 +00:00
|
|
|
* @param equipmentSlots What equipment slot will the loot items be added to
|
2023-03-03 15:23:46 +00:00
|
|
|
* @param totalItemCount Max count of items to add
|
2023-10-10 11:03:20 +00:00
|
|
|
* @param inventoryToAddItemsTo Bot inventory loot will be added to
|
|
|
|
* @param botRole Role of the bot loot is being generated for (assault/pmcbot)
|
2024-02-22 16:34:15 +00:00
|
|
|
* @param itemSpawnLimits Item spawn limits the bot must adhere to
|
2023-10-10 11:03:20 +00:00
|
|
|
* @param totalValueLimitRub Total value of loot allowed in roubles
|
|
|
|
* @param isPmc Is bot being generated for a pmc
|
2023-03-03 15:23:46 +00:00
|
|
|
*/
|
|
|
|
protected addLootFromPool(
|
2024-02-21 17:36:27 +00:00
|
|
|
pool: Record<string, number>,
|
2023-03-03 15:23:46 +00:00
|
|
|
equipmentSlots: string[],
|
|
|
|
totalItemCount: number,
|
|
|
|
inventoryToAddItemsTo: PmcInventory,
|
|
|
|
botRole: string,
|
2024-02-22 16:34:15 +00:00
|
|
|
itemSpawnLimits: IItemSpawnLimitSettings = null,
|
2023-03-03 15:23:46 +00:00
|
|
|
totalValueLimitRub = 0,
|
2023-11-16 21:42:06 +00:00
|
|
|
isPmc = false,
|
|
|
|
): void
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
|
|
|
// Loot pool has items
|
2024-02-22 16:34:15 +00:00
|
|
|
const poolSize = Object.keys(pool).length;
|
|
|
|
if (poolSize > 0)
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
|
|
|
let currentTotalRub = 0;
|
2024-02-22 16:34:15 +00:00
|
|
|
|
2023-07-27 13:14:09 +01:00
|
|
|
let fitItemIntoContainerAttempts = 0;
|
2023-03-03 15:23:46 +00:00
|
|
|
for (let i = 0; i < totalItemCount; i++)
|
|
|
|
{
|
2024-02-22 21:48:57 +00:00
|
|
|
// Pool can become empty if item spawn limits keep removing items
|
|
|
|
if (Object.keys(pool).length === 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-02-21 17:36:27 +00:00
|
|
|
const weightedItemTpl = this.weightedRandomHelper.getWeightedValue<string>(pool);
|
|
|
|
const itemResult = this.itemHelper.getItem(weightedItemTpl);
|
|
|
|
const itemToAddTemplate = itemResult[1];
|
|
|
|
if (!itemResult[0])
|
|
|
|
{
|
|
|
|
this.logger.warning(
|
|
|
|
`Unable to process item tpl: ${weightedItemTpl} for slots: ${equipmentSlots} on bot: ${botRole}`,
|
|
|
|
);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2024-02-22 16:34:15 +00:00
|
|
|
if (itemSpawnLimits)
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
2024-02-22 16:34:15 +00:00
|
|
|
if (this.itemHasReachedSpawnLimit(itemToAddTemplate, botRole, itemSpawnLimits))
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
2024-02-22 21:51:44 +00:00
|
|
|
// Remove item from pool to prevent it being picked again
|
2024-02-22 21:48:57 +00:00
|
|
|
delete pool[weightedItemTpl];
|
2023-03-03 15:23:46 +00:00
|
|
|
|
|
|
|
i--;
|
|
|
|
continue;
|
2023-11-16 21:42:06 +00:00
|
|
|
}
|
2023-03-03 15:23:46 +00:00
|
|
|
}
|
|
|
|
|
2024-02-22 21:48:57 +00:00
|
|
|
const newRootItemId = this.hashUtil.generate();
|
|
|
|
const itemWithChildrenToAdd: Item[] = [{
|
|
|
|
_id: newRootItemId,
|
|
|
|
_tpl: itemToAddTemplate._id,
|
|
|
|
...this.botGeneratorHelper.generateExtraPropertiesForItem(itemToAddTemplate, botRole),
|
|
|
|
}];
|
|
|
|
|
2024-02-21 18:36:45 +00:00
|
|
|
// Is Simple-Wallet
|
|
|
|
if (weightedItemTpl === "5783c43d2459774bbe137486")
|
|
|
|
{
|
|
|
|
const addCurrency = this.randomUtil.getChance100(25);
|
2024-02-21 18:37:24 +00:00
|
|
|
if (addCurrency)
|
2024-02-21 18:36:45 +00:00
|
|
|
{
|
2024-02-22 13:55:57 +00:00
|
|
|
// Create the currency items we want to add to wallet
|
2024-02-22 13:52:59 +00:00
|
|
|
const itemsToAdd = this.createWalletLoot(newRootItemId);
|
2024-02-22 13:55:57 +00:00
|
|
|
|
|
|
|
// Get the container grid for the wallet
|
|
|
|
const containerGrid = this.inventoryHelper.getContainerSlotMap(weightedItemTpl);
|
|
|
|
|
|
|
|
// Check if all the chosen currency items fit into wallet
|
2024-02-22 13:52:59 +00:00
|
|
|
const canAddToContainer = this.inventoryHelper.canPlaceItemsInContainer(
|
2024-02-22 13:55:57 +00:00
|
|
|
this.jsonUtil.clone(containerGrid), // MUST clone grid before passing in as function modifies grid
|
2024-02-22 13:52:59 +00:00
|
|
|
itemsToAdd,
|
|
|
|
);
|
|
|
|
if (canAddToContainer)
|
|
|
|
{
|
2024-02-22 13:55:57 +00:00
|
|
|
// Add each currency to wallet
|
2024-02-22 13:52:59 +00:00
|
|
|
for (const itemToAdd of itemsToAdd)
|
|
|
|
{
|
|
|
|
this.inventoryHelper.placeItemInContainer(
|
2024-02-22 13:55:57 +00:00
|
|
|
containerGrid,
|
2024-02-22 13:52:59 +00:00
|
|
|
itemToAdd,
|
|
|
|
itemWithChildrenToAdd[0]._id,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
itemWithChildrenToAdd.push(...itemsToAdd.flatMap((x) => x));
|
|
|
|
}
|
2024-02-21 18:36:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-19 11:57:25 +00:00
|
|
|
this.addRequiredChildItemsToParent(itemToAddTemplate, itemWithChildrenToAdd, isPmc);
|
2023-03-03 15:23:46 +00:00
|
|
|
|
2023-07-27 13:14:09 +01:00
|
|
|
// Attempt to add item to container(s)
|
2024-02-25 11:45:34 +00:00
|
|
|
const itemAddedResult = this.botGeneratorHelper.addItemWithChildrenToEquipmentSlot(
|
2023-11-16 21:42:06 +00:00
|
|
|
equipmentSlots,
|
2024-01-19 11:57:25 +00:00
|
|
|
newRootItemId,
|
2023-11-16 21:42:06 +00:00
|
|
|
itemToAddTemplate._id,
|
2024-01-19 11:57:25 +00:00
|
|
|
itemWithChildrenToAdd,
|
2023-11-16 21:42:06 +00:00
|
|
|
inventoryToAddItemsTo,
|
|
|
|
);
|
2023-12-08 16:27:34 +00:00
|
|
|
|
|
|
|
// Handle when item cannot be added
|
2023-11-24 16:05:58 +00:00
|
|
|
if (itemAddedResult !== ItemAddedResult.SUCCESS)
|
2023-07-27 13:14:09 +01:00
|
|
|
{
|
2023-11-24 16:05:58 +00:00
|
|
|
if (itemAddedResult === ItemAddedResult.NO_CONTAINERS)
|
|
|
|
{
|
|
|
|
// Bot has no container to put item in, exit
|
2024-02-02 13:54:07 -05:00
|
|
|
this.logger.debug(
|
|
|
|
`Unable to add: ${totalItemCount} items to bot as it lacks a container to include them`,
|
|
|
|
);
|
2023-11-24 16:05:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-07-27 13:14:09 +01:00
|
|
|
fitItemIntoContainerAttempts++;
|
|
|
|
if (fitItemIntoContainerAttempts >= 4)
|
|
|
|
{
|
2023-11-16 21:42:06 +00:00
|
|
|
this.logger.debug(
|
2024-02-02 13:54:07 -05:00
|
|
|
`Failed to place item ${i} of ${totalItemCount} items into ${botRole} containers: ${
|
|
|
|
equipmentSlots.join(",")
|
|
|
|
}. Tried ${fitItemIntoContainerAttempts} times, reason: ${
|
|
|
|
ItemAddedResult[itemAddedResult]
|
|
|
|
}, skipping`,
|
2023-11-16 21:42:06 +00:00
|
|
|
);
|
2023-07-27 13:14:09 +01:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2023-12-08 16:27:34 +00:00
|
|
|
|
2024-01-19 11:57:25 +00:00
|
|
|
// Try again, failed but still under attempt limit
|
2023-12-08 16:27:34 +00:00
|
|
|
continue;
|
2023-07-27 13:14:09 +01:00
|
|
|
}
|
2024-01-08 23:27:18 +00:00
|
|
|
|
|
|
|
// Item added okay, reset counter for next item
|
|
|
|
fitItemIntoContainerAttempts = 0;
|
2023-03-03 15:23:46 +00:00
|
|
|
|
|
|
|
// Stop adding items to bots pool if rolling total is over total limit
|
2023-10-12 13:25:13 +01:00
|
|
|
if (totalValueLimitRub > 0)
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
|
|
|
currentTotalRub += this.handbookHelper.getTemplatePrice(itemToAddTemplate._id);
|
|
|
|
if (currentTotalRub > totalValueLimitRub)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-22 13:52:59 +00:00
|
|
|
protected createWalletLoot(walletId: string): Item[][]
|
2024-02-21 18:36:45 +00:00
|
|
|
{
|
2024-02-22 13:52:59 +00:00
|
|
|
const result: Item[][] = [];
|
2024-02-21 18:36:45 +00:00
|
|
|
|
|
|
|
// Choose how many stacks of currency will be added to wallet
|
|
|
|
const itemCount = this.randomUtil.getInt(1, this.botConfig.walletLoot.itemCount);
|
|
|
|
for (let index = 0; index < itemCount; index++)
|
|
|
|
{
|
|
|
|
// Choose the size of the currency stack
|
|
|
|
const chosenStackCount = Number(
|
|
|
|
this.weightedRandomHelper.getWeightedValue<string>(this.botConfig.walletLoot.stackSizeWeight),
|
|
|
|
);
|
2024-02-22 13:52:59 +00:00
|
|
|
result.push([{
|
2024-02-21 18:36:45 +00:00
|
|
|
_id: this.hashUtil.generate(),
|
|
|
|
_tpl: "5449016a4bdc2d6f028b456f", // TODO - extend to be more than just roubles
|
|
|
|
parentId: walletId,
|
|
|
|
upd: { StackObjectsCount: chosenStackCount },
|
2024-02-22 13:52:59 +00:00
|
|
|
}]);
|
2024-02-21 18:36:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2024-01-19 11:57:25 +00:00
|
|
|
/**
|
|
|
|
* Some items need child items to function, add them to the itemToAddChildrenTo array
|
|
|
|
* @param itemToAddTemplate Db template of item to check
|
|
|
|
* @param itemToAddChildrenTo Item to add children to
|
|
|
|
* @param isPmc Is the item being generated for a pmc (affects money/ammo stack sizes)
|
|
|
|
*/
|
2024-02-02 13:54:07 -05:00
|
|
|
protected addRequiredChildItemsToParent(
|
|
|
|
itemToAddTemplate: ITemplateItem,
|
|
|
|
itemToAddChildrenTo: Item[],
|
|
|
|
isPmc: boolean,
|
|
|
|
): void
|
2024-01-19 11:57:25 +00:00
|
|
|
{
|
|
|
|
// Fill ammo box
|
|
|
|
if (this.itemHelper.isOfBaseclass(itemToAddTemplate._id, BaseClasses.AMMO_BOX))
|
|
|
|
{
|
2024-02-11 12:12:27 +00:00
|
|
|
this.itemHelper.addCartridgesToAmmoBox(itemToAddChildrenTo, itemToAddTemplate);
|
2024-01-19 11:57:25 +00:00
|
|
|
}
|
|
|
|
// Make money a stack
|
|
|
|
else if (this.itemHelper.isOfBaseclass(itemToAddTemplate._id, BaseClasses.MONEY))
|
|
|
|
{
|
|
|
|
this.randomiseMoneyStackSize(isPmc, itemToAddTemplate, itemToAddChildrenTo[0]);
|
|
|
|
}
|
|
|
|
// Make ammo a stack
|
|
|
|
else if (this.itemHelper.isOfBaseclass(itemToAddTemplate._id, BaseClasses.AMMO))
|
|
|
|
{
|
|
|
|
this.randomiseAmmoStackSize(isPmc, itemToAddTemplate, itemToAddChildrenTo[0]);
|
|
|
|
}
|
|
|
|
// Must add soft inserts/plates
|
|
|
|
else if (this.itemHelper.itemRequiresSoftInserts(itemToAddTemplate._id))
|
|
|
|
{
|
2024-02-06 10:53:08 +00:00
|
|
|
this.itemHelper.addChildSlotItems(itemToAddChildrenTo, itemToAddTemplate, null, false);
|
2024-01-19 11:57:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-03 15:23:46 +00:00
|
|
|
/**
|
|
|
|
* Add generated weapons to inventory as loot
|
|
|
|
* @param botInventory inventory to add preset to
|
|
|
|
* @param equipmentSlot slot to place the preset in (backpack)
|
|
|
|
* @param templateInventory bots template, assault.json
|
|
|
|
* @param modChances chances for mods to spawn on weapon
|
2023-11-04 09:08:33 +00:00
|
|
|
* @param botRole bots role .e.g. pmcBot
|
2023-03-03 15:23:46 +00:00
|
|
|
* @param isPmc are we generating for a pmc
|
|
|
|
*/
|
2023-11-16 21:42:06 +00:00
|
|
|
protected addLooseWeaponsToInventorySlot(
|
|
|
|
sessionId: string,
|
|
|
|
botInventory: PmcInventory,
|
|
|
|
equipmentSlot: string,
|
|
|
|
templateInventory: Inventory,
|
|
|
|
modChances: ModsChances,
|
|
|
|
botRole: string,
|
|
|
|
isPmc: boolean,
|
|
|
|
botLevel: number,
|
|
|
|
): void
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
2023-11-16 21:42:06 +00:00
|
|
|
const chosenWeaponType = this.randomUtil.getArrayValue([
|
|
|
|
EquipmentSlots.FIRST_PRIMARY_WEAPON,
|
|
|
|
EquipmentSlots.FIRST_PRIMARY_WEAPON,
|
|
|
|
EquipmentSlots.FIRST_PRIMARY_WEAPON,
|
|
|
|
EquipmentSlots.HOLSTER,
|
|
|
|
]);
|
|
|
|
const randomisedWeaponCount = this.randomUtil.getInt(
|
|
|
|
this.pmcConfig.looseWeaponInBackpackLootMinMax.min,
|
|
|
|
this.pmcConfig.looseWeaponInBackpackLootMinMax.max,
|
|
|
|
);
|
2023-03-03 15:23:46 +00:00
|
|
|
if (randomisedWeaponCount > 0)
|
|
|
|
{
|
|
|
|
for (let i = 0; i < randomisedWeaponCount; i++)
|
|
|
|
{
|
2023-11-16 21:42:06 +00:00
|
|
|
const generatedWeapon = this.botWeaponGenerator.generateRandomWeapon(
|
|
|
|
sessionId,
|
|
|
|
chosenWeaponType,
|
|
|
|
templateInventory,
|
|
|
|
botInventory.equipment,
|
|
|
|
modChances,
|
|
|
|
botRole,
|
|
|
|
isPmc,
|
|
|
|
botLevel,
|
|
|
|
);
|
2024-02-25 11:45:34 +00:00
|
|
|
const result = this.botGeneratorHelper.addItemWithChildrenToEquipmentSlot(
|
2023-11-16 21:42:06 +00:00
|
|
|
[equipmentSlot],
|
|
|
|
generatedWeapon.weapon[0]._id,
|
|
|
|
generatedWeapon.weapon[0]._tpl,
|
|
|
|
[...generatedWeapon.weapon],
|
|
|
|
botInventory,
|
|
|
|
);
|
2023-11-24 15:26:41 +00:00
|
|
|
|
|
|
|
if (result !== ItemAddedResult.SUCCESS)
|
|
|
|
{
|
2024-02-02 13:54:07 -05:00
|
|
|
this.logger.debug(
|
|
|
|
`Failed to add additional weapon ${generatedWeapon.weapon[0]._id} to bot backpack, reason: ${
|
|
|
|
ItemAddedResult[result]
|
|
|
|
}`,
|
|
|
|
);
|
2023-11-24 15:26:41 +00:00
|
|
|
}
|
2023-03-03 15:23:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-10-10 11:03:20 +00:00
|
|
|
* Hydrate item limit array to contain items that have a limit for a specific bot type
|
2023-03-03 15:23:46 +00:00
|
|
|
* All values are set to 0
|
2023-10-10 11:03:20 +00:00
|
|
|
* @param botRole Role the bot has
|
2023-11-16 21:42:06 +00:00
|
|
|
* @param limitCount
|
2023-03-03 15:23:46 +00:00
|
|
|
*/
|
2024-02-22 16:34:15 +00:00
|
|
|
protected initItemLimitArray(botRole: string, limitCount: Record<string, number>): void
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
|
|
|
// Init current count of items we want to limit
|
2024-02-22 16:34:15 +00:00
|
|
|
const spawnLimits = this.getItemSpawnLimitsForBotType(botRole);
|
2023-03-03 15:23:46 +00:00
|
|
|
for (const limit in spawnLimits)
|
|
|
|
{
|
|
|
|
limitCount[limit] = 0;
|
|
|
|
}
|
|
|
|
}
|
2023-11-16 21:42:06 +00:00
|
|
|
|
2023-03-03 15:23:46 +00:00
|
|
|
/**
|
|
|
|
* Check if an item has reached its bot-specific spawn limit
|
|
|
|
* @param itemTemplate Item we check to see if its reached spawn limit
|
|
|
|
* @param botRole Bot type
|
2024-02-22 16:34:15 +00:00
|
|
|
* @param itemSpawnLimits
|
2023-03-03 15:23:46 +00:00
|
|
|
* @returns true if item has reached spawn limit
|
|
|
|
*/
|
2023-11-16 21:42:06 +00:00
|
|
|
protected itemHasReachedSpawnLimit(
|
|
|
|
itemTemplate: ITemplateItem,
|
|
|
|
botRole: string,
|
2024-02-22 16:34:15 +00:00
|
|
|
itemSpawnLimits: IItemSpawnLimitSettings,
|
2023-11-16 21:42:06 +00:00
|
|
|
): boolean
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
|
|
|
// PMCs and scavs have different sections of bot config for spawn limits
|
2024-02-22 16:34:15 +00:00
|
|
|
if (!!itemSpawnLimits && Object.keys(itemSpawnLimits.globalLimits).length === 0)
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
|
|
|
// No items found in spawn limit, drop out
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// No spawn limits, skipping
|
|
|
|
if (!itemSpawnLimits)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-02-22 16:34:15 +00:00
|
|
|
const idToCheckFor = this.getMatchingIdFromSpawnLimits(itemTemplate, itemSpawnLimits.globalLimits);
|
2023-03-03 15:23:46 +00:00
|
|
|
if (!idToCheckFor)
|
|
|
|
{
|
|
|
|
// ParentId or tplid not found in spawnLimits, not a spawn limited item, skip
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Increment item count with this bot type
|
2024-02-22 16:34:15 +00:00
|
|
|
itemSpawnLimits.currentLimits[idToCheckFor]++;
|
2023-03-03 15:23:46 +00:00
|
|
|
|
2024-02-22 16:34:15 +00:00
|
|
|
// Check if over limit
|
|
|
|
if (itemSpawnLimits.currentLimits[idToCheckFor] > itemSpawnLimits.globalLimits[idToCheckFor])
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
2023-06-27 17:23:21 +01:00
|
|
|
// Prevent edge-case of small loot pools + code trying to add limited item over and over infinitely
|
2024-02-22 16:34:15 +00:00
|
|
|
if (itemSpawnLimits.currentLimits[idToCheckFor] > itemSpawnLimits[idToCheckFor] * 10)
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
2023-11-16 21:42:06 +00:00
|
|
|
this.logger.debug(
|
|
|
|
this.localisationService.getText("bot-item_spawn_limit_reached_skipping_item", {
|
|
|
|
botRole: botRole,
|
|
|
|
itemName: itemTemplate._name,
|
2024-02-22 16:34:15 +00:00
|
|
|
attempts: itemSpawnLimits.currentLimits[idToCheckFor],
|
2023-11-16 21:42:06 +00:00
|
|
|
}),
|
|
|
|
);
|
2023-03-03 15:23:46 +00:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Randomise the stack size of a money object, uses different values for pmc or scavs
|
2023-11-04 09:08:33 +00:00
|
|
|
* @param isPmc Is money on a PMC bot
|
|
|
|
* @param itemTemplate item details from db
|
|
|
|
* @param moneyItem Money item to randomise
|
2023-03-03 15:23:46 +00:00
|
|
|
*/
|
|
|
|
protected randomiseMoneyStackSize(isPmc: boolean, itemTemplate: ITemplateItem, moneyItem: Item): void
|
|
|
|
{
|
2023-11-04 09:08:33 +00:00
|
|
|
// PMCs have a different stack max size
|
|
|
|
const minStackSize = itemTemplate._props.StackMinRandom;
|
2023-11-16 21:42:06 +00:00
|
|
|
const maxStackSize = isPmc
|
2023-11-04 09:08:33 +00:00
|
|
|
? this.pmcConfig.dynamicLoot.moneyStackLimits[itemTemplate._id]
|
|
|
|
: itemTemplate._props.StackMaxRandom;
|
|
|
|
const randomSize = this.randomUtil.getInt(minStackSize, maxStackSize);
|
|
|
|
|
|
|
|
if (!moneyItem.upd)
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
2023-11-04 09:08:33 +00:00
|
|
|
moneyItem.upd = {};
|
2023-03-03 15:23:46 +00:00
|
|
|
}
|
2023-11-04 09:08:33 +00:00
|
|
|
|
2023-11-16 21:42:06 +00:00
|
|
|
moneyItem.upd.StackObjectsCount = randomSize;
|
2023-03-03 15:23:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Randomise the size of an ammo stack
|
2023-11-04 09:08:33 +00:00
|
|
|
* @param isPmc Is ammo on a PMC bot
|
|
|
|
* @param itemTemplate item details from db
|
|
|
|
* @param ammoItem Ammo item to randomise
|
2023-03-03 15:23:46 +00:00
|
|
|
*/
|
|
|
|
protected randomiseAmmoStackSize(isPmc: boolean, itemTemplate: ITemplateItem, ammoItem: Item): void
|
|
|
|
{
|
2023-11-04 09:08:33 +00:00
|
|
|
const randomSize = itemTemplate._props.StackMaxSize === 1
|
|
|
|
? 1
|
2024-02-02 13:54:07 -05:00
|
|
|
: this.randomUtil.getInt(
|
|
|
|
itemTemplate._props.StackMinRandom,
|
|
|
|
Math.min(itemTemplate._props.StackMaxRandom, 60),
|
|
|
|
);
|
2023-03-03 15:23:46 +00:00
|
|
|
|
2023-11-04 09:08:33 +00:00
|
|
|
if (!ammoItem.upd)
|
|
|
|
{
|
|
|
|
ammoItem.upd = {};
|
2023-03-03 15:23:46 +00:00
|
|
|
}
|
2023-11-04 09:08:33 +00:00
|
|
|
|
2023-11-16 21:42:06 +00:00
|
|
|
ammoItem.upd.StackObjectsCount = randomSize;
|
2023-03-03 15:23:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get spawn limits for a specific bot type from bot.json config
|
|
|
|
* If no limit found for a non pmc bot, fall back to defaults
|
|
|
|
* @param botRole what role does the bot have
|
|
|
|
* @returns Dictionary of tplIds and limit
|
|
|
|
*/
|
2024-02-22 16:34:15 +00:00
|
|
|
protected getItemSpawnLimitsForBotType(botRole: string): Record<string, number>
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
2024-02-22 16:34:15 +00:00
|
|
|
if (this.botHelper.isBotPmc(botRole))
|
2023-03-03 15:23:46 +00:00
|
|
|
{
|
2023-11-16 21:42:06 +00:00
|
|
|
return this.botConfig.itemSpawnLimits.pmc;
|
2023-03-03 15:23:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.botConfig.itemSpawnLimits[botRole.toLowerCase()])
|
|
|
|
{
|
|
|
|
return this.botConfig.itemSpawnLimits[botRole.toLowerCase()];
|
|
|
|
}
|
|
|
|
|
2023-11-16 21:42:06 +00:00
|
|
|
this.logger.warning(
|
|
|
|
this.localisationService.getText("bot-unable_to_find_spawn_limits_fallback_to_defaults", botRole),
|
|
|
|
);
|
2023-03-03 15:23:46 +00:00
|
|
|
|
2023-11-16 21:42:06 +00:00
|
|
|
return this.botConfig.itemSpawnLimits.default;
|
2023-03-03 15:23:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the parentId or tplId of item inside spawnLimits object if it exists
|
|
|
|
* @param itemTemplate item we want to look for in spawn limits
|
|
|
|
* @param spawnLimits Limits to check for item
|
|
|
|
* @returns id as string, otherwise undefined
|
|
|
|
*/
|
|
|
|
protected getMatchingIdFromSpawnLimits(itemTemplate: ITemplateItem, spawnLimits: Record<string, number>): string
|
|
|
|
{
|
|
|
|
if (itemTemplate._id in spawnLimits)
|
|
|
|
{
|
|
|
|
return itemTemplate._id;
|
|
|
|
}
|
|
|
|
|
|
|
|
// tplId not found in spawnLimits, check if parentId is
|
|
|
|
if (itemTemplate._parent in spawnLimits)
|
|
|
|
{
|
|
|
|
return itemTemplate._parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
// parentId and tplid not found
|
|
|
|
return undefined;
|
|
|
|
}
|
2023-11-16 21:42:06 +00:00
|
|
|
}
|