mirror of
https://github.com/sp-tarkov/server.git
synced 2025-02-13 07:10:44 -05:00
Small refactor of armor plate selection code
This commit is contained in:
parent
6cbd650330
commit
91f12715fb
@ -237,14 +237,14 @@ export class BotEquipmentModGenerator {
|
|||||||
* Filter a bots plate pool based on its current level
|
* Filter a bots plate pool based on its current level
|
||||||
* @param settings Bot equipment generation settings
|
* @param settings Bot equipment generation settings
|
||||||
* @param modSlot Armor slot being filtered
|
* @param modSlot Armor slot being filtered
|
||||||
* @param existingPlateTplPool Plates tpls to choose from
|
* @param compatiblePlateTplPool Compatible plate tpl pool to choose from
|
||||||
* @param armorItem The armor items db template
|
* @param armorItem The armor items db template
|
||||||
* @returns Array of plate tpls to choose from
|
* @returns Array of plate tpls to choose from
|
||||||
*/
|
*/
|
||||||
protected filterPlateModsForSlotByLevel(
|
protected filterPlateModsForSlotByLevel(
|
||||||
settings: IGenerateEquipmentProperties,
|
settings: IGenerateEquipmentProperties,
|
||||||
modSlot: string,
|
modSlot: string,
|
||||||
existingPlateTplPool: string[],
|
compatiblePlateTplPool: string[],
|
||||||
armorItem: ITemplateItem,
|
armorItem: ITemplateItem,
|
||||||
): IFilterPlateModsForSlotByLevelResult {
|
): IFilterPlateModsForSlotByLevelResult {
|
||||||
const result: IFilterPlateModsForSlotByLevelResult = {
|
const result: IFilterPlateModsForSlotByLevelResult = {
|
||||||
@ -255,7 +255,7 @@ export class BotEquipmentModGenerator {
|
|||||||
// Not pmc or not a plate slot, return original mod pool array
|
// Not pmc or not a plate slot, return original mod pool array
|
||||||
if (!this.itemHelper.isRemovablePlateSlot(modSlot)) {
|
if (!this.itemHelper.isRemovablePlateSlot(modSlot)) {
|
||||||
result.result = Result.NOT_PLATE_HOLDING_SLOT;
|
result.result = Result.NOT_PLATE_HOLDING_SLOT;
|
||||||
result.plateModTpls = existingPlateTplPool;
|
result.plateModTpls = compatiblePlateTplPool;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -269,7 +269,7 @@ export class BotEquipmentModGenerator {
|
|||||||
if (!plateSlotWeights) {
|
if (!plateSlotWeights) {
|
||||||
// No weights, return original array of plate tpls
|
// No weights, return original array of plate tpls
|
||||||
result.result = Result.LACKS_PLATE_WEIGHTS;
|
result.result = Result.LACKS_PLATE_WEIGHTS;
|
||||||
result.plateModTpls = existingPlateTplPool;
|
result.plateModTpls = compatiblePlateTplPool;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -279,7 +279,7 @@ export class BotEquipmentModGenerator {
|
|||||||
if (!plateWeights) {
|
if (!plateWeights) {
|
||||||
// No weights, return original array of plate tpls
|
// No weights, return original array of plate tpls
|
||||||
result.result = Result.LACKS_PLATE_WEIGHTS;
|
result.result = Result.LACKS_PLATE_WEIGHTS;
|
||||||
result.plateModTpls = existingPlateTplPool;
|
result.plateModTpls = compatiblePlateTplPool;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -288,70 +288,73 @@ export class BotEquipmentModGenerator {
|
|||||||
let chosenArmorPlateLevel = this.weightedRandomHelper.getWeightedValue<string>(plateWeights);
|
let chosenArmorPlateLevel = this.weightedRandomHelper.getWeightedValue<string>(plateWeights);
|
||||||
|
|
||||||
// Convert the array of ids into database items
|
// Convert the array of ids into database items
|
||||||
const platesFromDb = existingPlateTplPool.map((plateTpl) => this.itemHelper.getItem(plateTpl)[1]);
|
const platesFromDb = compatiblePlateTplPool.map((plateTpl) => this.itemHelper.getItem(plateTpl)[1]);
|
||||||
|
|
||||||
// Filter plates to the chosen level based on its armorClass property
|
// Filter plates to the chosen level based on its armorClass property
|
||||||
let platesOfDesiredLevel = platesFromDb.filter((item) => item._props.armorClass === chosenArmorPlateLevel);
|
let platesOfDesiredLevel = platesFromDb.filter((item) => item._props.armorClass === chosenArmorPlateLevel);
|
||||||
if (platesOfDesiredLevel.length === 0) {
|
if (platesOfDesiredLevel.length > 0) {
|
||||||
// Get lowest and highest plate classes available for this armor
|
// Plates found
|
||||||
const minMaxArmorPlateClass = this.getMinMaxArmorPlateClass(platesFromDb);
|
result.result = Result.SUCCESS;
|
||||||
|
result.plateModTpls = platesOfDesiredLevel.map((item) => item._id);
|
||||||
|
|
||||||
let fitPlateIntoArmorAttempts = 0;
|
return result;
|
||||||
const maxTries = 3;
|
}
|
||||||
|
|
||||||
// Attempt to increase plate class level to attempt getting minimum plate level useable based on original selection
|
// no plates found that fit requirements, lets get creative
|
||||||
for (let i = 0; i < maxTries; i++) {
|
|
||||||
chosenArmorPlateLevel = (Number.parseInt(chosenArmorPlateLevel) + 1).toString();
|
|
||||||
|
|
||||||
// If new chosen plate class is higher than max, then set to min and check if valid
|
// Get lowest and highest plate classes available for this armor
|
||||||
if (Number(chosenArmorPlateLevel) > minMaxArmorPlateClass.max) {
|
const minMaxArmorPlateClass = this.getMinMaxArmorPlateClass(platesFromDb);
|
||||||
chosenArmorPlateLevel = minMaxArmorPlateClass.min.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
platesOfDesiredLevel = platesFromDb.filter((item) => item._props.armorClass === chosenArmorPlateLevel);
|
// Increment plate class level in attempt to get useable plate
|
||||||
|
let findCompatiblePlateAttempts = 0;
|
||||||
|
const maxAttempts = 3;
|
||||||
|
for (let i = 0; i < maxAttempts; i++) {
|
||||||
|
chosenArmorPlateLevel = (Number.parseInt(chosenArmorPlateLevel) + 1).toString();
|
||||||
|
|
||||||
fitPlateIntoArmorAttempts++;
|
// New chosen plate class is higher than max, then set to min and check if valid
|
||||||
// Break loop if valid plate class is found
|
if (Number(chosenArmorPlateLevel) > minMaxArmorPlateClass.max) {
|
||||||
if (platesOfDesiredLevel.length > 0) {
|
chosenArmorPlateLevel = minMaxArmorPlateClass.min.toString();
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If no valid plate class is found in 3 tries then attempt default plates
|
findCompatiblePlateAttempts++;
|
||||||
if (fitPlateIntoArmorAttempts >= maxTries) {
|
|
||||||
this.logger.debug(
|
|
||||||
`Plate filter was too restrictive for armor: ${armorItem._name} ${armorItem._id}, unable to find plates of level: ${chosenArmorPlateLevel}. Using mod items default plate`,
|
|
||||||
);
|
|
||||||
const relatedItemDbModSlot = armorItem._props.Slots.find(
|
|
||||||
(slot) => slot._name.toLowerCase() === modSlot,
|
|
||||||
);
|
|
||||||
const defaultPlate = relatedItemDbModSlot._props.filters[0].Plate;
|
|
||||||
if (!defaultPlate) {
|
|
||||||
// No relevant plate found after filtering AND no default plate
|
|
||||||
|
|
||||||
// Last attempt, get default preset and see if it has a plate default
|
platesOfDesiredLevel = platesFromDb.filter((item) => item._props.armorClass === chosenArmorPlateLevel);
|
||||||
const defaultPreset = this.presetHelper.getDefaultPreset(armorItem._id);
|
// Valid plates found, exit
|
||||||
if (defaultPreset) {
|
if (platesOfDesiredLevel.length > 0) {
|
||||||
const relatedPresetSlot = defaultPreset._items.find(
|
break;
|
||||||
(item) => item.slotId?.toLowerCase() === modSlot,
|
}
|
||||||
);
|
|
||||||
if (relatedPresetSlot) {
|
|
||||||
result.result = Result.SUCCESS;
|
|
||||||
result.plateModTpls = [relatedPresetSlot._tpl];
|
|
||||||
|
|
||||||
return result;
|
// No valid plate class found in 3 tries, attempt default plates
|
||||||
}
|
if (findCompatiblePlateAttempts >= maxAttempts) {
|
||||||
}
|
this.logger.debug(
|
||||||
// Return Default Preset cause didn't have default plates
|
`Plate filter too restrictive for armor: ${armorItem._name} ${armorItem._id}, unable to find plates of level: ${chosenArmorPlateLevel}, using items default plate`,
|
||||||
result.result = Result.NO_DEFAULT_FILTER;
|
);
|
||||||
|
|
||||||
return result;
|
const defaultPlate = this.getDefaultPlateTpl(armorItem, modSlot);
|
||||||
}
|
if (defaultPlate) {
|
||||||
// Return Default Plates cause couldn't get lowest level available from original selection
|
// Return Default Plates cause couldn't get lowest level available from original selection
|
||||||
result.result = Result.SUCCESS;
|
result.result = Result.SUCCESS;
|
||||||
result.plateModTpls = [defaultPlate];
|
result.plateModTpls = [defaultPlate];
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No plate found after filtering AND no default plate
|
||||||
|
|
||||||
|
// Last attempt, get default preset and see if it has a plate default
|
||||||
|
const defaultPresetPlateSlot = this.getDefaultPresetArmorSlot(armorItem._id, modSlot);
|
||||||
|
if (defaultPresetPlateSlot) {
|
||||||
|
// Found a plate, exit
|
||||||
|
const plateItem = this.itemHelper.getItem(defaultPresetPlateSlot._tpl);
|
||||||
|
platesOfDesiredLevel = [plateItem[1]];
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everything failed, no default plate or no default preset armor plate
|
||||||
|
result.result = Result.NO_DEFAULT_FILTER;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,6 +365,32 @@ export class BotEquipmentModGenerator {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default plate an armor has in its db item
|
||||||
|
* @param armorItem Item to look up default plate
|
||||||
|
* @param modSlot front/back
|
||||||
|
* @returns Tpl of plate
|
||||||
|
*/
|
||||||
|
protected getDefaultPlateTpl(armorItem: ITemplateItem, modSlot: string): string | undefined {
|
||||||
|
const relatedItemDbModSlot = armorItem._props.Slots?.find(
|
||||||
|
(slot: { _name: string }) => slot._name.toLowerCase() === modSlot,
|
||||||
|
);
|
||||||
|
|
||||||
|
return relatedItemDbModSlot?._props.filters[0].Plate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the matching armor slot from the default preset matching passed in armor tpl
|
||||||
|
* @param presetItemId Id of preset
|
||||||
|
* @param modSlot front/back
|
||||||
|
* @returns Armor IItem
|
||||||
|
*/
|
||||||
|
protected getDefaultPresetArmorSlot(armorItemTpl: string, modSlot: string): IItem | undefined {
|
||||||
|
const defaultPreset = this.presetHelper.getDefaultPreset(armorItemTpl);
|
||||||
|
|
||||||
|
return defaultPreset?._items.find((item) => item.slotId?.toLowerCase() === modSlot);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the minimum and maximum plate class levels from an array of plates
|
* Gets the minimum and maximum plate class levels from an array of plates
|
||||||
* @param platePool Pool of plates to sort by armorClass to get min and max
|
* @param platePool Pool of plates to sort by armorClass to get min and max
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
export interface IFilterPlateModsForSlotByLevelResult {
|
export interface IFilterPlateModsForSlotByLevelResult {
|
||||||
result: Result;
|
result: Result;
|
||||||
plateModTpls: string[];
|
plateModTpls?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Result {
|
export enum Result {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user