0
0
mirror of https://github.com/sp-tarkov/server.git synced 2025-02-13 09:50:43 -05:00

Improved comments inside BotEquipmentModGenerator class

This commit is contained in:
Dev 2024-06-19 10:41:55 +01:00
parent 416ef74902
commit f7e42cae5d
2 changed files with 95 additions and 64 deletions

View File

@ -629,16 +629,28 @@ export class BotEquipmentModGenerator
} }
} }
protected modSlotCanHoldMuzzleDevices(modSlot: string, modsParentId: string): boolean /**
* Does the provided modSlot allow muzzle-related items
* @param modSlot Slot id to check
* @param modsParentId OPTIONAL: parent id of modslot being checked
* @returns True if modSlot can have muzzle-related items
*/
protected modSlotCanHoldMuzzleDevices(modSlot: string, modsParentId?: string): boolean
{ {
return ["mod_muzzle", "mod_muzzle_000", "mod_muzzle_001"].includes(modSlot.toLowerCase()); return ["mod_muzzle", "mod_muzzle_000", "mod_muzzle_001"].includes(modSlot.toLowerCase());
} }
protected sortModKeys(unsortedKeys: string[]): string[] /**
* Sort mod slots into an ordering that maximises chance of a successful weapon generation
* @param unsortedSlotKeys Array of mod slot strings to sort
* @returns Sorted array
*/
protected sortModKeys(unsortedSlotKeys: string[]): string[]
{ {
if (unsortedKeys.length <= 1) // No need to sort with only 1 item in array
if (unsortedSlotKeys.length <= 1)
{ {
return unsortedKeys; return unsortedSlotKeys;
} }
const sortedKeys: string[] = []; const sortedKeys: string[] = [];
@ -652,61 +664,61 @@ export class BotEquipmentModGenerator
const modMountKey = "mod_mount"; const modMountKey = "mod_mount";
const modScopeKey = "mod_scope"; const modScopeKey = "mod_scope";
if (unsortedKeys.includes(modHandguardKey)) if (unsortedSlotKeys.includes(modHandguardKey))
{ {
sortedKeys.push(modHandguardKey); sortedKeys.push(modHandguardKey);
unsortedKeys.splice(unsortedKeys.indexOf(modHandguardKey), 1); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modHandguardKey), 1);
} }
if (unsortedKeys.includes(modBarrelKey)) if (unsortedSlotKeys.includes(modBarrelKey))
{ {
sortedKeys.push(modBarrelKey); sortedKeys.push(modBarrelKey);
unsortedKeys.splice(unsortedKeys.indexOf(modBarrelKey), 1); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modBarrelKey), 1);
} }
if (unsortedKeys.includes(modMount001Key)) if (unsortedSlotKeys.includes(modMount001Key))
{ {
sortedKeys.push(modMount001Key); sortedKeys.push(modMount001Key);
unsortedKeys.splice(unsortedKeys.indexOf(modMount001Key), 1); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modMount001Key), 1);
} }
if (unsortedKeys.includes(modRecieverKey)) if (unsortedSlotKeys.includes(modRecieverKey))
{ {
sortedKeys.push(modRecieverKey); sortedKeys.push(modRecieverKey);
unsortedKeys.splice(unsortedKeys.indexOf(modRecieverKey), 1); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modRecieverKey), 1);
} }
if (unsortedKeys.includes(modPistolGrip)) if (unsortedSlotKeys.includes(modPistolGrip))
{ {
sortedKeys.push(modPistolGrip); sortedKeys.push(modPistolGrip);
unsortedKeys.splice(unsortedKeys.indexOf(modPistolGrip), 1); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modPistolGrip), 1);
} }
if (unsortedKeys.includes(modGasBlockKey)) if (unsortedSlotKeys.includes(modGasBlockKey))
{ {
sortedKeys.push(modGasBlockKey); sortedKeys.push(modGasBlockKey);
unsortedKeys.splice(unsortedKeys.indexOf(modGasBlockKey), 1); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modGasBlockKey), 1);
} }
if (unsortedKeys.includes(modStockKey)) if (unsortedSlotKeys.includes(modStockKey))
{ {
sortedKeys.push(modStockKey); sortedKeys.push(modStockKey);
unsortedKeys.splice(unsortedKeys.indexOf(modStockKey), 1); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modStockKey), 1);
} }
if (unsortedKeys.includes(modMountKey)) if (unsortedSlotKeys.includes(modMountKey))
{ {
sortedKeys.push(modMountKey); sortedKeys.push(modMountKey);
unsortedKeys.splice(unsortedKeys.indexOf(modMountKey), 1); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modMountKey), 1);
} }
if (unsortedKeys.includes(modScopeKey)) if (unsortedSlotKeys.includes(modScopeKey))
{ {
sortedKeys.push(modScopeKey); sortedKeys.push(modScopeKey);
unsortedKeys.splice(unsortedKeys.indexOf(modScopeKey), 1); unsortedSlotKeys.splice(unsortedSlotKeys.indexOf(modScopeKey), 1);
} }
sortedKeys.push(...unsortedKeys); sortedKeys.push(...unsortedSlotKeys);
return sortedKeys; return sortedKeys;
} }
@ -882,12 +894,21 @@ export class BotEquipmentModGenerator
return this.itemHelper.getItem(chosenModResult.chosenTpl!); return this.itemHelper.getItem(chosenModResult.chosenTpl!);
} }
/**
*
* @param modPool Pool of mods that can be picked from
* @param parentSlot Slot the picked mod will have as a parent
* @param choiceTypeEnum How should chosen tpl be treated: DEFAULT_MOD/SPAWN/SKIP
* @param weapon Array of weapon items chosen item will be added to
* @param modSlotName Name of slot picked mod will be placed into
* @returns Chosen weapon details
*/
protected pickWeaponModTplForSlotFromPool( protected pickWeaponModTplForSlotFromPool(
modPool: string[], modPool: string[],
parentSlot: Slot, parentSlot: Slot,
modSpawnResult: ModSpawn, choiceTypeEnum: ModSpawn,
weapon: Item[], weapon: Item[],
modSlotname: string, modSlotName: string,
): IChooseRandomCompatibleModResult ): IChooseRandomCompatibleModResult
{ {
let chosenTpl: string; let chosenTpl: string;
@ -901,7 +922,7 @@ export class BotEquipmentModGenerator
while (exhaustableModPool.hasValues()) while (exhaustableModPool.hasValues())
{ {
chosenTpl = exhaustableModPool.getRandomValue()!; chosenTpl = exhaustableModPool.getRandomValue()!;
if (modSpawnResult === ModSpawn.DEFAULT_MOD && modPool.length === 1) if (choiceTypeEnum === ModSpawn.DEFAULT_MOD && modPool.length === 1)
{ {
// Default mod wanted and only one choice in pool // Default mod wanted and only one choice in pool
chosenModResult.found = true; chosenModResult.found = true;
@ -922,7 +943,7 @@ export class BotEquipmentModGenerator
chosenModResult = this.botGeneratorHelper.isWeaponModIncompatibleWithCurrentMods( chosenModResult = this.botGeneratorHelper.isWeaponModIncompatibleWithCurrentMods(
weapon, weapon,
chosenTpl, chosenTpl,
modSlotname, modSlotName,
); );
if (chosenModResult.slotBlocked) if (chosenModResult.slotBlocked)
@ -961,17 +982,17 @@ export class BotEquipmentModGenerator
* Is slot required * Is slot required
* Is slot flagged as default mod only * Is slot flagged as default mod only
* @param itemModPool Existing pool of mods to choose * @param itemModPool Existing pool of mods to choose
* @param modSpawnResult outcome of random roll to select if mod should be added * @param itemSpawnCategory How should slot be handled
* @param parentTemplate Mods parent * @param parentTemplate Mods parent
* @param weaponTemplate Mods root parent (weapon/equipment) * @param weaponTemplate Mods root parent (weapon/equipment)
* @param modSlot name of mod slot to choose for * @param modSlot name of mod slot to choose for
* @param botEquipBlacklist * @param botEquipBlacklist A blacklist of items not allowed to be picked
* @param isRandomisableSlot is flagged as a randomisable slot * @param isRandomisableSlot Slot is flagged as a randomisable slot
* @returns * @returns Array of mod tpls
*/ */
protected getModPoolForSlot( protected getModPoolForSlot(
itemModPool: Record<string, string[]>, itemModPool: Record<string, string[]>,
modSpawnResult: ModSpawn, itemSpawnCategory: ModSpawn,
parentTemplate: ITemplateItem, parentTemplate: ITemplateItem,
weaponTemplate: ITemplateItem, weaponTemplate: ITemplateItem,
modSlot: string, modSlot: string,
@ -980,7 +1001,7 @@ export class BotEquipmentModGenerator
): string[] ): string[]
{ {
// Mod is flagged as being default only, try and find it in globals // Mod is flagged as being default only, try and find it in globals
if (modSpawnResult === ModSpawn.DEFAULT_MOD) if (itemSpawnCategory === ModSpawn.DEFAULT_MOD)
{ {
const matchingPreset = this.getMatchingPreset(weaponTemplate, parentTemplate._id); const matchingPreset = this.getMatchingPreset(weaponTemplate, parentTemplate._id);
const matchingModFromPreset = matchingPreset?._items.find( const matchingModFromPreset = matchingPreset?._items.find(
@ -1037,9 +1058,9 @@ export class BotEquipmentModGenerator
} }
/** /**
* Get default preset for weapon, get specific weapon presets for edge cases (mp5/silenced dvl) * Get default preset for weapon OR get specific weapon presets for edge cases (mp5/silenced dvl)
* @param weaponTemplate * @param weaponTemplate Weapons db template
* @param parentItemTpl * @param parentItemTpl Tpl of the parent item
* @returns Default preset found * @returns Default preset found
*/ */
protected getMatchingPreset(weaponTemplate: ITemplateItem, parentItemTpl: string): IPreset | undefined protected getMatchingPreset(weaponTemplate: ITemplateItem, parentItemTpl: string): IPreset | undefined
@ -1063,7 +1084,7 @@ export class BotEquipmentModGenerator
/** /**
* Temp fix to prevent certain combinations of weapons with mods that are known to be incompatible * Temp fix to prevent certain combinations of weapons with mods that are known to be incompatible
* @param weapon Weapon * @param weapon Array of items that make up a weapon
* @param modTpl Mod to check compatibility with weapon * @param modTpl Mod to check compatibility with weapon
* @returns True if incompatible * @returns True if incompatible
*/ */
@ -1079,12 +1100,13 @@ export class BotEquipmentModGenerator
} }
/** /**
* Create a mod item with parameters as properties * Create a mod item with provided parameters as properties + add upd property
* @param modId _id * @param modId _id
* @param modTpl _tpl * @param modTpl _tpl
* @param parentId parentId * @param parentId parentId
* @param modSlot slotId * @param modSlot slotId
* @param modTemplate Used to add additional properties in the upd object * @param modTemplate Used to add additional properties in the upd object
* @param botRole The bots role mod is being created for
* @returns Item object * @returns Item object
*/ */
protected createModItem( protected createModItem(
@ -1117,14 +1139,14 @@ export class BotEquipmentModGenerator
/** /**
* Get a random mod from an items compatible mods Filter array * Get a random mod from an items compatible mods Filter array
* @param modTpl ???? default value to return if nothing found * @param fallbackModTpl Default value to return if parentSlot Filter is empty
* @param parentSlot item mod will go into, used to get compatible items * @param parentSlot Item mod will go into, used to get compatible items
* @param modSlot Slot to get mod to fill * @param modSlot Slot to get mod to fill
* @param items items to ensure picked mod is compatible with * @param items Items to ensure picked mod is compatible with
* @returns item tpl * @returns Item tpl
*/ */
protected getRandomModTplFromItemDb( protected getRandomModTplFromItemDb(
modTpl: string, fallbackModTpl: string,
parentSlot: Slot, parentSlot: Slot,
modSlot: string, modSlot: string,
items: Item[], items: Item[],
@ -1135,7 +1157,7 @@ export class BotEquipmentModGenerator
// Find mod item that fits slot from sorted mod array // Find mod item that fits slot from sorted mod array
const exhaustableModPool = new ExhaustableArray(allowedItems, this.randomUtil, this.cloner); const exhaustableModPool = new ExhaustableArray(allowedItems, this.randomUtil, this.cloner);
let tmpModTpl = modTpl; let tmpModTpl = fallbackModTpl;
while (exhaustableModPool.hasValues()) while (exhaustableModPool.hasValues())
{ {
tmpModTpl = exhaustableModPool.getRandomValue()!; tmpModTpl = exhaustableModPool.getRandomValue()!;
@ -1155,8 +1177,8 @@ export class BotEquipmentModGenerator
* @param slotAddedToTemplate Slot object the item will be placed as child into * @param slotAddedToTemplate Slot object the item will be placed as child into
* @param modSlot Slot the mod will fill * @param modSlot Slot the mod will fill
* @param parentTemplate Db template of the mods being added * @param parentTemplate Db template of the mods being added
* @param botRole Bots wildspawntype (assault/pmcBot etc) * @param botRole Bots wildspawntype (assault/pmcBot/exUsec etc)
* @returns true if valid * @returns True if valid for slot
*/ */
protected isModValidForSlot( protected isModValidForSlot(
modToAdd: [boolean, ITemplateItem], modToAdd: [boolean, ITemplateItem],
@ -1207,9 +1229,10 @@ export class BotEquipmentModGenerator
/** /**
* Find mod tpls of a provided type and add to modPool * Find mod tpls of a provided type and add to modPool
* @param desiredSlotName slot to look up and add we are adding tpls for (e.g mod_scope) * @param desiredSlotName Slot to look up and add we are adding tpls for (e.g mod_scope)
* @param modTemplate db object for modItem we get compatible mods from * @param modTemplate db object for modItem we get compatible mods from
* @param modPool Pool of mods we are adding to * @param modPool Pool of mods we are adding to
* @param botEquipBlacklist A blacklist of items that cannot be picked
*/ */
protected addCompatibleModsForProvidedMod( protected addCompatibleModsForProvidedMod(
desiredSlotName: string, desiredSlotName: string,
@ -1255,8 +1278,8 @@ export class BotEquipmentModGenerator
* Get the possible items that fit a slot * Get the possible items that fit a slot
* @param parentItemId item tpl to get compatible items for * @param parentItemId item tpl to get compatible items for
* @param modSlot Slot item should fit in * @param modSlot Slot item should fit in
* @param botEquipBlacklist equipment that should not be picked * @param botEquipBlacklist Equipment that should not be picked
* @returns array of compatible items for that slot * @returns Array of compatible items for that slot
*/ */
protected getDynamicModPool( protected getDynamicModPool(
parentItemId: string, parentItemId: string,
@ -1282,9 +1305,9 @@ export class BotEquipmentModGenerator
/** /**
* Take a list of tpls and filter out blacklisted values using itemFilterService + botEquipmentBlacklist * Take a list of tpls and filter out blacklisted values using itemFilterService + botEquipmentBlacklist
* @param allowedMods base mods to filter * @param allowedMods Base mods to filter
* @param botEquipBlacklist equipment blacklist * @param botEquipBlacklist Equipment blacklist
* @param modSlot slot mods belong to * @param modSlot Slot mods belong to
* @returns Filtered array of mod tpls * @returns Filtered array of mod tpls
*/ */
protected filterWeaponModsByBlacklist( protected filterWeaponModsByBlacklist(
@ -1293,6 +1316,7 @@ export class BotEquipmentModGenerator
modSlot: string, modSlot: string,
): string[] ): string[]
{ {
// No blacklist, nothing to filter out
if (!botEquipBlacklist) if (!botEquipBlacklist)
{ {
return allowedMods; return allowedMods;
@ -1315,30 +1339,34 @@ export class BotEquipmentModGenerator
* Ammo is not put into the magazine directly but assigned to the magazine's slots: The "camora_xxx" slots. * Ammo is not put into the magazine directly but assigned to the magazine's slots: The "camora_xxx" slots.
* This function is a helper called by generateModsForItem for mods with parent type "CylinderMagazine" * This function is a helper called by generateModsForItem for mods with parent type "CylinderMagazine"
* @param items The items where the CylinderMagazine's camora are appended to * @param items The items where the CylinderMagazine's camora are appended to
* @param modPool modPool which should include available cartridges * @param modPool ModPool which should include available cartridges
* @param parentId The CylinderMagazine's UID * @param cylinderMagParentId The CylinderMagazine's UID
* @param parentTemplate The CylinderMagazine's template * @param cylinderMagTemplate The CylinderMagazine's template
*/ */
protected fillCamora(items: Item[], modPool: Mods, parentId: string, parentTemplate: ITemplateItem): void protected fillCamora(
items: Item[],
modPool: Mods,
cylinderMagParentId: string,
cylinderMagTemplate: ITemplateItem): void
{ {
let itemModPool = modPool[parentTemplate._id]; let itemModPool = modPool[cylinderMagTemplate._id];
if (!itemModPool) if (!itemModPool)
{ {
this.logger.warning( this.logger.warning(
this.localisationService.getText("bot-unable_to_fill_camora_slot_mod_pool_empty", { this.localisationService.getText("bot-unable_to_fill_camora_slot_mod_pool_empty", {
weaponId: parentTemplate._id, weaponId: cylinderMagTemplate._id,
weaponName: parentTemplate._name, weaponName: cylinderMagTemplate._name,
}), }),
); );
const camoraSlots = parentTemplate._props.Slots.filter((slot) => slot._name.startsWith("camora")); const camoraSlots = cylinderMagTemplate._props.Slots.filter((slot) => slot._name.startsWith("camora"));
// Attempt to generate camora slots for item // Attempt to generate camora slots for item
modPool[parentTemplate._id] = {}; modPool[cylinderMagTemplate._id] = {};
for (const camora of camoraSlots) for (const camora of camoraSlots)
{ {
modPool[parentTemplate._id][camora._name] = camora._props.filters[0].Filter; modPool[cylinderMagTemplate._id][camora._name] = camora._props.filters[0].Filter;
} }
itemModPool = modPool[parentTemplate._id]; itemModPool = modPool[cylinderMagTemplate._id];
} }
let exhaustableModPool = undefined; let exhaustableModPool = undefined;
@ -1359,7 +1387,7 @@ export class BotEquipmentModGenerator
} }
else else
{ {
this.logger.error(this.localisationService.getText("bot-missing_cartridge_slot", parentTemplate._id)); this.logger.error(this.localisationService.getText("bot-missing_cartridge_slot", cylinderMagTemplate._id));
return; return;
} }

View File

@ -1,6 +1,9 @@
export enum ModSpawn export enum ModSpawn
{ {
/** Chosen mod should be the tpl from the default weapon template */
DEFAULT_MOD = 0, DEFAULT_MOD = 0,
/** Normal behaviour */
SPAWN = 1, SPAWN = 1,
/** Item should not be chosen */
SKIP = 2, SKIP = 2,
} }