Add system to flag weapon slot ids as required.

Applies to stocks/recievers for PMCs
recievers for exusec/raider
This commit is contained in:
Dev 2024-02-05 22:02:03 +00:00
parent 32862866aa
commit b7d74f1dec
3 changed files with 43 additions and 20 deletions

View File

@ -459,7 +459,8 @@
"weaponModLimits": { "weaponModLimits": {
"scopeLimit": 1, "scopeLimit": 1,
"lightLaserLimit": 1 "lightLaserLimit": 1
} },
"forceStock": true
}, },
"cursedassault": { "cursedassault": {
"faceShieldIsActiveChancePercent": 90, "faceShieldIsActiveChancePercent": 90,
@ -473,7 +474,9 @@
"faceShieldIsActiveChancePercent": 100, "faceShieldIsActiveChancePercent": 100,
"lightIsActiveDayChancePercent": 25, "lightIsActiveDayChancePercent": 25,
"lightIsActiveNightChancePercent": 90, "lightIsActiveNightChancePercent": 90,
"laserIsActiveChancePercent": 85 "laserIsActiveChancePercent": 85,
"forceStock": true,
"weaponSlotIdsToMakeRequired": ["mod_reciever"]
}, },
"bossbully": { "bossbully": {
"nvgIsActiveChanceDayPercent": 10, "nvgIsActiveChanceDayPercent": 10,
@ -508,13 +511,15 @@
"weaponModLimits": { "weaponModLimits": {
"scopeLimit": 1, "scopeLimit": 1,
"lightLaserLimit": 1 "lightLaserLimit": 1
} },
"forceStock": true
}, },
"bosssanitar": { "bosssanitar": {
"faceShieldIsActiveChancePercent": 100, "faceShieldIsActiveChancePercent": 100,
"lightIsActiveDayChancePercent": 25, "lightIsActiveDayChancePercent": 25,
"lightIsActiveNightChancePercent": 75, "lightIsActiveNightChancePercent": 75,
"laserIsActiveChancePercent": 85 "laserIsActiveChancePercent": 85,
"forceStock": true
}, },
"bosstagilla": { "bosstagilla": {
"faceShieldIsActiveChancePercent": 100, "faceShieldIsActiveChancePercent": 100,
@ -562,19 +567,22 @@
"faceShieldIsActiveChancePercent": 100, "faceShieldIsActiveChancePercent": 100,
"lightIsActiveDayChancePercent": 25, "lightIsActiveDayChancePercent": 25,
"lightIsActiveNightChancePercent": 75, "lightIsActiveNightChancePercent": 75,
"laserIsActiveChancePercent": 75 "laserIsActiveChancePercent": 75,
"forceStock": true
}, },
"followerkolontaysecurity": { "followerkolontaysecurity": {
"faceShieldIsActiveChancePercent": 100, "faceShieldIsActiveChancePercent": 100,
"lightIsActiveDayChancePercent": 25, "lightIsActiveDayChancePercent": 25,
"lightIsActiveNightChancePercent": 75, "lightIsActiveNightChancePercent": 75,
"laserIsActiveChancePercent": 75 "laserIsActiveChancePercent": 75,
"forceStock": true
}, },
"followerbully": { "followerbully": {
"faceShieldIsActiveChancePercent": 100, "faceShieldIsActiveChancePercent": 100,
"lightIsActiveDayChancePercent": 25, "lightIsActiveDayChancePercent": 25,
"lightIsActiveNightChancePercent": 75, "lightIsActiveNightChancePercent": 75,
"laserIsActiveChancePercent": 75 "laserIsActiveChancePercent": 75,
"forceStock": true
}, },
"followergluharassault": { "followergluharassault": {
"nvgIsActiveChanceDayPercent": 10, "nvgIsActiveChanceDayPercent": 10,
@ -582,7 +590,8 @@
"faceShieldIsActiveChancePercent": 100, "faceShieldIsActiveChancePercent": 100,
"lightIsActiveDayChancePercent": 25, "lightIsActiveDayChancePercent": 25,
"lightIsActiveNightChancePercent": 75, "lightIsActiveNightChancePercent": 75,
"laserIsActiveChancePercent": 75 "laserIsActiveChancePercent": 75,
"forceStock": true
}, },
"followergluharscout": { "followergluharscout": {
"faceShieldIsActiveChancePercent": 100, "faceShieldIsActiveChancePercent": 100,
@ -656,7 +665,8 @@
"weaponModLimits": { "weaponModLimits": {
"scopeLimit": 2, "scopeLimit": 2,
"lightLaserLimit": 1 "lightLaserLimit": 1
} },
"forceStock": true
}, },
"followerboarclose1": { "followerboarclose1": {
"nvgIsActiveChanceDayPercent": 20, "nvgIsActiveChanceDayPercent": 20,
@ -668,7 +678,8 @@
"weaponModLimits": { "weaponModLimits": {
"scopeLimit": 2, "scopeLimit": 2,
"lightLaserLimit": 1 "lightLaserLimit": 1
} },
"forceStock": true
}, },
"followerboarclose2": { "followerboarclose2": {
"nvgIsActiveChanceDayPercent": 20, "nvgIsActiveChanceDayPercent": 20,
@ -680,7 +691,8 @@
"weaponModLimits": { "weaponModLimits": {
"scopeLimit": 2, "scopeLimit": 2,
"lightLaserLimit": 1 "lightLaserLimit": 1
} },
"forceStock": true
}, },
"bossboarsniper": { "bossboarsniper": {
"nvgIsActiveChanceDayPercent": 20, "nvgIsActiveChanceDayPercent": 20,
@ -737,7 +749,8 @@
"weaponModLimits": { "weaponModLimits": {
"scopeLimit": 1, "scopeLimit": 1,
"lightLaserLimit": 1 "lightLaserLimit": 1
} },
"weaponSlotIdsToMakeRequired": ["mod_reciever"]
}, },
"arenafighterevent": { "arenafighterevent": {
"nvgIsActiveChanceDayPercent": 10, "nvgIsActiveChanceDayPercent": 10,
@ -773,7 +786,8 @@
"weaponModLimits": { "weaponModLimits": {
"scopeLimit": 1, "scopeLimit": 1,
"lightLaserLimit": 1 "lightLaserLimit": 1
} },
"forceStock": true
}, },
"assaultgroup": {}, "assaultgroup": {},
"gifter": { "gifter": {
@ -855,6 +869,7 @@
"laserIsActiveChancePercent": 85, "laserIsActiveChancePercent": 85,
"forceOnlyArmoredRigWhenNoArmor": true, "forceOnlyArmoredRigWhenNoArmor": true,
"filterPlatesByLevel": true, "filterPlatesByLevel": true,
"weaponSlotIdsToMakeRequired": ["mod_reciever", "mod_stock"],
"randomisation": [ "randomisation": [
{ {
"levelRange": { "levelRange": {

View File

@ -16,7 +16,7 @@ import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes"; import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
import { ModSpawn } from "@spt-aki/models/enums/ModSpawn"; import { ModSpawn } from "@spt-aki/models/enums/ModSpawn";
import { IChooseRandomCompatibleModResult } from "@spt-aki/models/spt/bots/IChooseRandomCompatibleModResult"; import { IChooseRandomCompatibleModResult } from "@spt-aki/models/spt/bots/IChooseRandomCompatibleModResult";
import { EquipmentFilterDetails, IBotConfig } from "@spt-aki/models/spt/config/IBotConfig"; import { EquipmentFilterDetails, EquipmentFilters, IBotConfig } from "@spt-aki/models/spt/config/IBotConfig";
import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import { ConfigServer } from "@spt-aki/servers/ConfigServer"; import { ConfigServer } from "@spt-aki/servers/ConfigServer";
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
@ -386,7 +386,7 @@ export class BotEquipmentModGenerator
} }
// Check spawn chance of mod // Check spawn chance of mod
const modSpawnResult = this.shouldModBeSpawned(modsParentSlot, modSlot, modSpawnChances); const modSpawnResult = this.shouldModBeSpawned(modsParentSlot, modSlot, modSpawnChances, botEquipConfig);
if (modSpawnResult === ModSpawn.SKIP) if (modSpawnResult === ModSpawn.SKIP)
{ {
continue; continue;
@ -707,9 +707,15 @@ export class BotEquipmentModGenerator
* @param itemSlot slot the item sits in * @param itemSlot slot the item sits in
* @param modSlot slot the mod sits in * @param modSlot slot the mod sits in
* @param modSpawnChances Chances for various mod spawns * @param modSpawnChances Chances for various mod spawns
* @param botEquipConfig Various config settings for generating this type of bot
* @returns ModSpawn.SPAWN when mod should be spawned, ModSpawn.DEFAULT_MOD when default mod should spawn, ModSpawn.SKIP when mod is skipped * @returns ModSpawn.SPAWN when mod should be spawned, ModSpawn.DEFAULT_MOD when default mod should spawn, ModSpawn.SKIP when mod is skipped
*/ */
protected shouldModBeSpawned(itemSlot: Slot, modSlot: string, modSpawnChances: ModsChances): ModSpawn protected shouldModBeSpawned(
itemSlot: Slot,
modSlot: string,
modSpawnChances: ModsChances,
botEquipConfig: EquipmentFilters,
): ModSpawn
{ {
const slotRequired = itemSlot._required; const slotRequired = itemSlot._required;
if (this.getAmmoContainers().includes(modSlot)) if (this.getAmmoContainers().includes(modSlot))
@ -717,7 +723,7 @@ export class BotEquipmentModGenerator
return ModSpawn.SPAWN; return ModSpawn.SPAWN;
} }
const spawnMod = this.probabilityHelper.rollChance(modSpawnChances[modSlot]); const spawnMod = this.probabilityHelper.rollChance(modSpawnChances[modSlot]);
if (!spawnMod && slotRequired) if (!spawnMod && (slotRequired || botEquipConfig.weaponSlotIdsToMakeRequired.includes(modSlot)))
{ {
// Mod is required but spawn chance roll failed, choose default mod spawn for slot // Mod is required but spawn chance roll failed, choose default mod spawn for slot
return ModSpawn.DEFAULT_MOD; return ModSpawn.DEFAULT_MOD;

View File

@ -102,13 +102,15 @@ export interface EquipmentFilters
lightIsActiveNightChancePercent?: number; lightIsActiveNightChancePercent?: number;
/** Chance gun laser is active during the day */ /** Chance gun laser is active during the day */
laserIsActiveChancePercent?: number; laserIsActiveChancePercent?: number;
/** Should plates be filtered by level */
filterPlatesByLevel?: boolean;
/** Chance NODS are down/active during the day */ /** Chance NODS are down/active during the day */
nvgIsActiveChanceDayPercent?: number; nvgIsActiveChanceDayPercent?: number;
/** Chance NODS are down/active during the night */ /** Chance NODS are down/active during the night */
nvgIsActiveChanceNightPercent?: number; nvgIsActiveChanceNightPercent?: number;
forceOnlyArmoredRigWhenNoArmor?: boolean; forceOnlyArmoredRigWhenNoArmor?: boolean;
/** Should plates be filtered by level */
filterPlatesByLevel?: boolean;
/** What additional slot ids should be seen as required when choosing a mod to add to a weapon */
weaponSlotIdsToMakeRequired?: string[];
/** Adjust weighting/chances of items on bot by level of bot */ /** Adjust weighting/chances of items on bot by level of bot */
randomisation: RandomisationDetails[]; randomisation: RandomisationDetails[];
/** Blacklist equipment by level of bot */ /** Blacklist equipment by level of bot */
@ -120,7 +122,7 @@ export interface EquipmentFilters
/** Same as weightingAdjustments but based on player level instead of bot level */ /** Same as weightingAdjustments but based on player level instead of bot level */
weightingAdjustmentsByPlayerLevel?: WeightingAdjustmentDetails[]; weightingAdjustmentsByPlayerLevel?: WeightingAdjustmentDetails[];
/** Should the stock mod be forced to spawn on bot */ /** Should the stock mod be forced to spawn on bot */
forceStock: boolean; forceStock?: boolean;
armorPlateWeighting?: IArmorPlateWeights[]; armorPlateWeighting?: IArmorPlateWeights[];
} }