mirror of
https://github.com/sp-tarkov/server.git
synced 2025-02-13 09:50:43 -05:00
Expand filterPlateModsForSlotByLevel to attempt other plate class levels before falling back to default plates (#1086)
Instead of automatically falling back to default plates, this change will allow the bot to attempt the next level higher armor class up to 3 times before falling back to defaults. Through testing this prevents falling back to defaults roughly 95% of the time and retains the ability to roll the lowest level available armor class if the initial armor class level selected is too low for the armor. --------- Co-authored-by: acidphantasm <acidphantasm@acidphantasm.com>
This commit is contained in:
parent
e8a589a2f8
commit
6cbd650330
@ -7,6 +7,7 @@ import { PresetHelper } from "@spt/helpers/PresetHelper";
|
|||||||
import { ProbabilityHelper } from "@spt/helpers/ProbabilityHelper";
|
import { ProbabilityHelper } from "@spt/helpers/ProbabilityHelper";
|
||||||
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||||
import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper";
|
import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper";
|
||||||
|
import { MinMax } from "@spt/models/common/MinMax";
|
||||||
import { IPreset } from "@spt/models/eft/common/IGlobals";
|
import { IPreset } from "@spt/models/eft/common/IGlobals";
|
||||||
import { IMods, IModsChances } from "@spt/models/eft/common/tables/IBotType";
|
import { IMods, IModsChances } from "@spt/models/eft/common/tables/IBotType";
|
||||||
import { IItem } from "@spt/models/eft/common/tables/IItem";
|
import { IItem } from "@spt/models/eft/common/tables/IItem";
|
||||||
@ -284,19 +285,45 @@ export class BotEquipmentModGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Choose a plate level based on weighting
|
// Choose a plate level based on weighting
|
||||||
const 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 = existingPlateTplPool.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
|
||||||
const 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
|
||||||
|
const minMaxArmorPlateClass = this.getMinMaxArmorPlateClass(platesFromDb);
|
||||||
|
|
||||||
|
let fitPlateIntoArmorAttempts = 0;
|
||||||
|
const maxTries = 3;
|
||||||
|
|
||||||
|
// Attempt to increase plate class level to attempt getting minimum plate level useable based on original selection
|
||||||
|
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
|
||||||
|
if (Number(chosenArmorPlateLevel) > minMaxArmorPlateClass.max) {
|
||||||
|
chosenArmorPlateLevel = minMaxArmorPlateClass.min.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
platesOfDesiredLevel = platesFromDb.filter((item) => item._props.armorClass === chosenArmorPlateLevel);
|
||||||
|
|
||||||
|
fitPlateIntoArmorAttempts++;
|
||||||
|
// Break loop if valid plate class is found
|
||||||
|
if (platesOfDesiredLevel.length > 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no valid plate class is found in 3 tries then attempt default plates
|
||||||
|
if (fitPlateIntoArmorAttempts >= maxTries) {
|
||||||
this.logger.debug(
|
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`,
|
`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(
|
||||||
const relatedItemDbModSlot = armorItem._props.Slots.find((slot) => slot._name.toLowerCase() === modSlot);
|
(slot) => slot._name.toLowerCase() === modSlot,
|
||||||
|
);
|
||||||
const defaultPlate = relatedItemDbModSlot._props.filters[0].Plate;
|
const defaultPlate = relatedItemDbModSlot._props.filters[0].Plate;
|
||||||
if (!defaultPlate) {
|
if (!defaultPlate) {
|
||||||
// No relevant plate found after filtering AND no default plate
|
// No relevant plate found after filtering AND no default plate
|
||||||
@ -314,17 +341,19 @@ export class BotEquipmentModGenerator {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Return Default Preset cause didn't have default plates
|
||||||
result.result = Result.NO_DEFAULT_FILTER;
|
result.result = Result.NO_DEFAULT_FILTER;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only return the items ids
|
// Only return the items ids
|
||||||
result.result = Result.SUCCESS;
|
result.result = Result.SUCCESS;
|
||||||
@ -333,6 +362,24 @@ export class BotEquipmentModGenerator {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @returns MinMax of armorClass from plate pool
|
||||||
|
*/
|
||||||
|
protected getMinMaxArmorPlateClass(platePool: ITemplateItem[]): MinMax {
|
||||||
|
platePool.sort((x, y) => {
|
||||||
|
if (x._props.armorClass < y._props.armorClass) return -1;
|
||||||
|
if (x._props.armorClass > y._props.armorClass) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
min: Number(platePool[0]._props.armorClass),
|
||||||
|
max: Number(platePool[platePool.length - 1]._props.armorClass),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add mods to a weapon using the provided mod pool
|
* Add mods to a weapon using the provided mod pool
|
||||||
* @param sessionId Session id
|
* @param sessionId Session id
|
||||||
|
Loading…
x
Reference in New Issue
Block a user