Improved bot generation system to allow PMCs to wear NVGs at night more than during day

This commit is contained in:
Dev 2024-09-28 23:29:08 +01:00
parent f5360d0a92
commit 057425b363
6 changed files with 104 additions and 6 deletions

View File

@ -1223,7 +1223,7 @@
"mod_equipment_000": 10, "mod_equipment_000": 10,
"mod_equipment_001": 10, "mod_equipment_001": 10,
"mod_equipment_002": 5, "mod_equipment_002": 5,
"mod_nvg": 15 "mod_nvg": 0
}, },
"weaponMods": { "weaponMods": {
"mod_barrel": 50, "mod_barrel": 50,
@ -1260,6 +1260,11 @@
"mod_tactical_002": 30, "mod_tactical_002": 30,
"mod_tactical_003": 30, "mod_tactical_003": 30,
"mod_tactical_2": 15 "mod_tactical_2": 15
},
"nighttimeChanges": {
"equipmentModsModifiers": {
"mod_nvg": 30
}
} }
}, },
{ {
@ -1271,6 +1276,9 @@
"SecondPrimaryWeapon": 10, "SecondPrimaryWeapon": 10,
"FaceCover": 50 "FaceCover": 50
}, },
"equipmentMods": {
"mod_nvg": 0
},
"randomisedArmorSlots": ["Headwear", "TacticalVest", "ArmorVest"], "randomisedArmorSlots": ["Headwear", "TacticalVest", "ArmorVest"],
"randomisedWeaponModSlots": [ "randomisedWeaponModSlots": [
"mod_scope", "mod_scope",
@ -1314,7 +1322,12 @@
"mod_tactical_003", "mod_tactical_003",
"mod_tactical001", "mod_tactical001",
"mod_tactical002" "mod_tactical002"
] ],
"nighttimeChanges": {
"equipmentModsModifiers": {
"mod_nvg": 50
}
}
}, },
{ {
"levelRange": { "levelRange": {
@ -1332,7 +1345,7 @@
"mod_equipment_000": 80, "mod_equipment_000": 80,
"mod_equipment_001": 75, "mod_equipment_001": 75,
"mod_equipment_002": 90, "mod_equipment_002": 90,
"mod_nvg": 60 "mod_nvg": 5
}, },
"weaponMods": { "weaponMods": {
"mod_scope": 95, "mod_scope": 95,
@ -1383,7 +1396,12 @@
"mod_tactical_003", "mod_tactical_003",
"mod_tactical001", "mod_tactical001",
"mod_tactical002" "mod_tactical002"
] ],
"nighttimeChanges": {
"equipmentModsModifiers": {
"mod_nvg": 90
}
}
} }
], ],
"blacklist": [ "blacklist": [

View File

@ -6187,6 +6187,18 @@
"5a16b8a9fcdbcb00165aa6ca" "5a16b8a9fcdbcb00165aa6ca"
] ]
}, },
"5a16b8a9fcdbcb00165aa6ca": {
"mod_nvg": [
"5c0695860db834001b735461",
"5a16b93dfcdbcbcae6687261",
"5c11046cd174af02a012e42b"
]
},
"5a16b93dfcdbcbcae6687261": {
"mod_nvg": [
"57235b6f24597759bf5a30f1"
]
},
"5a16badafcdbcb001865f72d": { "5a16badafcdbcb001865f72d": {
"mod_equipment": [ "mod_equipment": [
"5a16ba61fcdbcb098008728a" "5a16ba61fcdbcb098008728a"
@ -9720,6 +9732,11 @@
"5c0d56a986f774449d5de529" "5c0d56a986f774449d5de529"
] ]
}, },
"5c0695860db834001b735461": {
"mod_nvg": [
"5c0696830db834001d23f5da"
]
},
"5c06c6a80db834001b735491": { "5c06c6a80db834001b735491": {
"Helmet_back": [ "Helmet_back": [
"657119d49eb8c145180dbb95" "657119d49eb8c145180dbb95"
@ -10405,6 +10422,11 @@
"638612b607dfed1ccb7206ba" "638612b607dfed1ccb7206ba"
] ]
}, },
"5c11046cd174af02a012e42b": {
"mod_nvg": [
"5c110624d174af029e69734c"
]
},
"5c17664f2e2216398b5a7e3c": { "5c17664f2e2216398b5a7e3c": {
"mod_mount_000": [ "mod_mount_000": [
"59e0bed186f774156f04ce84" "59e0bed186f774156f04ce84"

View File

@ -13518,6 +13518,22 @@
"5a16b8a9fcdbcb00165aa6ca" "5a16b8a9fcdbcb00165aa6ca"
] ]
}, },
"5a16b8a9fcdbcb00165aa6ca": {
"mod_nvg": [
"5c0695860db834001b735461",
"5a16b93dfcdbcbcae6687261",
"5c11046cd174af02a012e42b"
]
},
"5c0695860db834001b735461": {
"mod_nvg": ["5c0696830db834001d23f5da"]
},
"5a16b93dfcdbcbcae6687261": {
"mod_nvg": ["57235b6f24597759bf5a30f1"]
},
"5c11046cd174af02a012e42b": {
"mod_nvg": ["5c110624d174af029e69734c"]
},
"5f60c74e3b85f6263c145586": { "5f60c74e3b85f6263c145586": {
"Helmet_back": [ "Helmet_back": [
"657bc2c5a1c61ee0c3036333" "657bc2c5a1c61ee0c3036333"

View File

@ -1,13 +1,17 @@
import { ApplicationContext } from "@spt/context/ApplicationContext";
import { ContextVariableType } from "@spt/context/ContextVariableType";
import { BotEquipmentModGenerator } from "@spt/generators/BotEquipmentModGenerator"; import { BotEquipmentModGenerator } from "@spt/generators/BotEquipmentModGenerator";
import { BotLootGenerator } from "@spt/generators/BotLootGenerator"; import { BotLootGenerator } from "@spt/generators/BotLootGenerator";
import { BotWeaponGenerator } from "@spt/generators/BotWeaponGenerator"; import { BotWeaponGenerator } from "@spt/generators/BotWeaponGenerator";
import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper"; import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper";
import { BotHelper } from "@spt/helpers/BotHelper"; import { BotHelper } from "@spt/helpers/BotHelper";
import { ItemHelper } from "@spt/helpers/ItemHelper"; import { ItemHelper } from "@spt/helpers/ItemHelper";
import { WeatherHelper } from "@spt/helpers/WeatherHelper";
import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper"; import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper";
import { IInventory as PmcInventory } from "@spt/models/eft/common/tables/IBotBase"; import { IInventory as PmcInventory } from "@spt/models/eft/common/tables/IBotBase";
import { IBotType, IChances, IEquipment, IGeneration, IInventory } from "@spt/models/eft/common/tables/IBotType"; import { IBotType, IChances, IEquipment, IGeneration, IInventory } from "@spt/models/eft/common/tables/IBotType";
import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem"; import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem";
import { IGetRaidConfigurationRequestData } from "@spt/models/eft/match/IGetRaidConfigurationRequestData";
import { ConfigTypes } from "@spt/models/enums/ConfigTypes"; import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
import { EquipmentSlots } from "@spt/models/enums/EquipmentSlots"; import { EquipmentSlots } from "@spt/models/enums/EquipmentSlots";
import { GameEditions } from "@spt/models/enums/GameEditions"; import { GameEditions } from "@spt/models/enums/GameEditions";
@ -32,12 +36,14 @@ export class BotInventoryGenerator {
@inject("HashUtil") protected hashUtil: HashUtil, @inject("HashUtil") protected hashUtil: HashUtil,
@inject("RandomUtil") protected randomUtil: RandomUtil, @inject("RandomUtil") protected randomUtil: RandomUtil,
@inject("DatabaseService") protected databaseService: DatabaseService, @inject("DatabaseService") protected databaseService: DatabaseService,
@inject("ApplicationContext") protected applicationContext: ApplicationContext,
@inject("BotWeaponGenerator") protected botWeaponGenerator: BotWeaponGenerator, @inject("BotWeaponGenerator") protected botWeaponGenerator: BotWeaponGenerator,
@inject("BotLootGenerator") protected botLootGenerator: BotLootGenerator, @inject("BotLootGenerator") protected botLootGenerator: BotLootGenerator,
@inject("BotGeneratorHelper") protected botGeneratorHelper: BotGeneratorHelper, @inject("BotGeneratorHelper") protected botGeneratorHelper: BotGeneratorHelper,
@inject("BotHelper") protected botHelper: BotHelper, @inject("BotHelper") protected botHelper: BotHelper,
@inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper, @inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper,
@inject("ItemHelper") protected itemHelper: ItemHelper, @inject("ItemHelper") protected itemHelper: ItemHelper,
@inject("WeatherHelper") protected weatherHelper: WeatherHelper,
@inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocalisationService") protected localisationService: LocalisationService,
@inject("BotEquipmentModPoolService") protected botEquipmentModPoolService: BotEquipmentModPoolService, @inject("BotEquipmentModPoolService") protected botEquipmentModPoolService: BotEquipmentModPoolService,
@inject("BotEquipmentModGenerator") protected botEquipmentModGenerator: BotEquipmentModGenerator, @inject("BotEquipmentModGenerator") protected botEquipmentModGenerator: BotEquipmentModGenerator,
@ -71,6 +77,11 @@ export class BotInventoryGenerator {
// Generate base inventory with no items // Generate base inventory with no items
const botInventory = this.generateInventoryBase(); const botInventory = this.generateInventoryBase();
// Get generated raid details bot will be spawned in
const raidConfig = this.applicationContext
.getLatestValue(ContextVariableType.RAID_CONFIGURATION)
?.getValue<IGetRaidConfigurationRequestData>();
this.generateAndAddEquipmentToBot( this.generateAndAddEquipmentToBot(
templateInventory, templateInventory,
wornItemChances, wornItemChances,
@ -78,6 +89,7 @@ export class BotInventoryGenerator {
botInventory, botInventory,
botLevel, botLevel,
chosenGameVersion, chosenGameVersion,
raidConfig,
); );
// Roll weapon spawns (primary/secondary/holster) and generate a weapon for each roll that passed // Roll weapon spawns (primary/secondary/holster) and generate a weapon for each roll that passed
@ -144,6 +156,7 @@ export class BotInventoryGenerator {
botInventory: PmcInventory, botInventory: PmcInventory,
botLevel: number, botLevel: number,
chosenGameVersion: string, chosenGameVersion: string,
raidConfig: IGetRaidConfigurationRequestData,
): void { ): void {
// These will be handled later // These will be handled later
const excludedSlots: string[] = [ const excludedSlots: string[] = [
@ -160,6 +173,26 @@ export class BotInventoryGenerator {
const botEquipConfig = this.botConfig.equipment[this.botGeneratorHelper.getBotEquipmentRole(botRole)]; const botEquipConfig = this.botConfig.equipment[this.botGeneratorHelper.getBotEquipmentRole(botRole)];
const randomistionDetails = this.botHelper.getBotRandomizationDetails(botLevel, botEquipConfig); const randomistionDetails = this.botHelper.getBotRandomizationDetails(botLevel, botEquipConfig);
// Apply nighttime changes if its nighttime + there's changes to make
if (
randomistionDetails?.nighttimeChanges &&
raidConfig &&
this.weatherHelper.isNightTime(raidConfig.timeVariant)
) {
for (const equipmentSlotKey of Object.keys(randomistionDetails.nighttimeChanges.equipmentModsModifiers)) {
// Never let mod chance go outside of 0 - 100
randomistionDetails.equipmentMods[equipmentSlotKey] = Math.min(
Math.max(
(randomistionDetails.equipmentMods[equipmentSlotKey] ?? 0) +
randomistionDetails.nighttimeChanges.equipmentModsModifiers[equipmentSlotKey],
0,
),
100,
);
}
}
for (const equipmentSlot in templateInventory.equipment) { for (const equipmentSlot in templateInventory.equipment) {
// Weapons have special generation and will be generated separately; ArmorVest should be generated after TactivalVest // Weapons have special generation and will be generated separately; ArmorVest should be generated after TactivalVest
if (excludedSlots.includes(equipmentSlot)) { if (excludedSlots.includes(equipmentSlot)) {

View File

@ -131,7 +131,9 @@ export class BotHelper {
return undefined; return undefined;
} }
return botEquipConfig.randomisation.find((x) => botLevel >= x.levelRange.min && botLevel <= x.levelRange.max); return botEquipConfig.randomisation.find(
(randDetails) => botLevel >= randDetails.levelRange.min && botLevel <= randDetails.levelRange.max,
);
} }
/** /**

View File

@ -162,6 +162,13 @@ export interface RandomisationDetails {
weaponMods?: Record<string, number>; weaponMods?: Record<string, number>;
/** Equipment mod chances */ /** Equipment mod chances */
equipmentMods?: Record<string, number>; equipmentMods?: Record<string, number>;
nighttimeChanges?: INighttimeChanges;
}
export interface INighttimeChanges {
/** Applies changes to values stored in equipmentMods */
equipmentModsModifiers: Record<string, number>;
//weaponModsModifiers: Record<string, number>; //TODO
} }
export interface EquipmentFilterDetails { export interface EquipmentFilterDetails {