using System.Text.Json.Serialization; using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; namespace SPTarkov.Server.Core.Models.Spt.Config; public record BotConfig : BaseConfig { [JsonPropertyName("kind")] public override string Kind { get; set; } = "spt-bot"; /// /// How many variants of each bot should be generated on raid start /// [JsonPropertyName("presetBatch")] public required Dictionary PresetBatch { get; set; } /// /// What bot types should be classified as bosses /// [JsonPropertyName("bosses")] public required List Bosses { get; set; } /// /// Control weapon/armor durability min/max values for each bot type /// [JsonPropertyName("durability")] public required BotDurability Durability { get; set; } /// /// Controls the percentage values of randomization item resources /// [JsonPropertyName("lootItemResourceRandomization")] public required Dictionary< string, RandomisedResourceDetails > LootItemResourceRandomization { get; set; } /// /// Control how many items are allowed to spawn on a bot
/// key: bottype, value:
/// key: itemTpl: value: max item count> ///
[JsonPropertyName("itemSpawnLimits")] public required Dictionary> ItemSpawnLimits { get; set; } /// /// Blacklist/whitelist items on a bot /// [JsonPropertyName("equipment")] public required Dictionary Equipment { get; set; } /// /// Show a bots botType value after their name /// [JsonPropertyName("showTypeInNickname")] public bool ShowTypeInNickname { get; set; } /// /// What ai brain should a normal scav use per map /// [JsonPropertyName("assaultBrainType")] public required Dictionary> AssaultBrainType { get; set; } /// /// What ai brain should a player scav use per map /// [JsonPropertyName("playerScavBrainType")] public required Dictionary> PlayerScavBrainType { get; set; } /// /// Max number of bots that can be spawned in a raid at any one time /// [JsonPropertyName("maxBotCap")] public required Dictionary MaxBotCap { get; set; } /// /// Chance scav has fake pscav name e.g. Scav name (player name) /// [JsonPropertyName("chanceAssaultScavHasPlayerScavName")] public int ChanceAssaultScavHasPlayerScavName { get; set; } /// /// How many stacks of secret ammo should a bot have in its bot secure container /// [JsonPropertyName("secureContainerAmmoStackCount")] public int SecureContainerAmmoStackCount { get; set; } /// /// Bot roles in this array will be given a dog tag on generation /// [JsonPropertyName("botRolesWithDogTags")] public required HashSet BotRolesWithDogTags { get; set; } /// /// Settings to control the items that get added into wallets on bots /// [JsonPropertyName("walletLoot")] public required WalletLootSettings WalletLoot { get; set; } /// /// Currency weights, Keyed by botrole / currency /// [JsonPropertyName("currencyStackSize")] public required Dictionary< string, Dictionary> > CurrencyStackSize { get; set; } /// /// Tpls for low profile gas blocks /// [JsonPropertyName("lowProfileGasBlockTpls")] public required HashSet LowProfileGasBlockTpls { get; set; } /// /// What bottypes should be excluded from having loot generated on them (backpack/pocket/vest) does not disable food/drink/special/ /// [JsonPropertyName("disableLootOnBotTypes")] public required HashSet DisableLootOnBotTypes { get; set; } /// /// Max length a bots name can be /// [JsonPropertyName("botNameLengthLimit")] public int BotNameLengthLimit { get; set; } /// /// Bot roles that must have a unique name when generated vs other bots in raid /// [JsonPropertyName("botRolesThatMustHaveUniqueName")] public required HashSet BotRolesThatMustHaveUniqueName { get; set; } /// /// Bot roles that must have a unique name when generated vs other bots in raid /// [JsonPropertyName("weeklyBoss")] public required WeeklyBossSettings WeeklyBoss { get; set; } } public record WeeklyBossSettings { [JsonExtensionData] public Dictionary? ExtensionData { get; set; } /// /// Should a weekly boss be picked to 100% spawn /// [JsonPropertyName("enabled")] public bool Enabled { get; set; } /// /// Bosses that can be picked /// [JsonPropertyName("bossPool")] public required List BossPool { get; set; } /// /// Day of week boss choice resets /// [JsonPropertyName("resetDay")] [JsonConverter(typeof(JsonStringEnumConverter))] public DayOfWeek ResetDay { get; set; } } public record WalletLootSettings { [JsonExtensionData] public Dictionary? ExtensionData { get; set; } /// /// Chance wallets have loot in them /// [JsonPropertyName("chancePercent")] public float ChancePercent { get; set; } [JsonPropertyName("itemCount")] public required MinMax ItemCount { get; set; } [JsonPropertyName("stackSizeWeight")] public required Dictionary StackSizeWeight { get; set; } [JsonPropertyName("currencyWeight")] public required Dictionary CurrencyWeight { get; set; } /// /// What wallets will have money in them /// [JsonPropertyName("walletTplPool")] public required List WalletTplPool { get; set; } } public record EquipmentFilters { [JsonExtensionData] public Dictionary? ExtensionData { get; set; } /// /// Limits for mod types per weapon .e.g. scopes /// [JsonPropertyName("weaponModLimits")] public ModLimits? WeaponModLimits { get; set; } /// /// Whitelist for weapon sight types allowed per gun /// [JsonPropertyName("weaponSightWhitelist")] public Dictionary>? WeaponSightWhitelist { get; set; } [JsonPropertyName("forceOnlyArmoredRigWhenNoArmor")] public bool? ForceOnlyArmoredRigWhenNoArmor { get; set; } /// /// Should plates be filtered by level /// [JsonPropertyName("filterPlatesByLevel")] public bool? FilterPlatesByLevel { get; set; } /// /// What additional slot ids should be seen as required when choosing a mod to add to a weapon /// [JsonPropertyName("weaponSlotIdsToMakeRequired")] public HashSet? WeaponSlotIdsToMakeRequired { get; set; } /// /// Adjust weighting/chances of items on bot by level of bot /// [JsonPropertyName("randomisation")] public List? Randomisation { get; set; } /// /// Blacklist equipment by level of bot /// [JsonPropertyName("blacklist")] public List? Blacklist { get; set; } /// /// Whitelist equipment by level of bot /// [JsonPropertyName("whitelist")] public List? Whitelist { get; set; } /// /// Adjust equipment/ammo /// [JsonPropertyName("weightingAdjustmentsByBotLevel")] public List? WeightingAdjustmentsByBotLevel { get; set; } /// /// Should the stock mod be forced to spawn on bot /// [JsonPropertyName("forceStock")] public bool? ForceStock { get; set; } [JsonPropertyName("armorPlateWeighting")] public List? ArmorPlateWeighting { get; set; } /// /// Chance face shield is down/active /// [JsonPropertyName("faceShieldIsActiveChancePercent")] public double? FaceShieldIsActiveChancePercent { get; set; } /// /// Chance gun flashlight is active during the day /// [JsonPropertyName("lightIsActiveDayChancePercent")] public double? LightIsActiveDayChancePercent { get; set; } /// /// Chance gun flashlight is active during the night /// [JsonPropertyName("lightIsActiveNightChancePercent")] public double? LightIsActiveNightChancePercent { get; set; } /// /// Chance gun laser is active during the day /// [JsonPropertyName("laserIsActiveChancePercent")] public double? LaserIsActiveChancePercent { get; set; } /// /// Chance NODS are down/active during the day /// [JsonPropertyName("nvgIsActiveChanceDayPercent")] public double? NvgIsActiveChanceDayPercent { get; set; } /// /// Chance NODS are down/active during the night /// [JsonPropertyName("nvgIsActiveChanceNightPercent")] public double? NvgIsActiveChanceNightPercent { get; set; } [JsonPropertyName("forceRigWhenNoVest")] public bool? ForceRigWhenNoVest { get; set; } } public record ModLimits { [JsonExtensionData] public Dictionary? ExtensionData { get; set; } /// /// How many scopes are allowed on a weapon - hard coded to work with OPTIC_SCOPE, ASSAULT_SCOPE, COLLIMATOR, COMPACT_COLLIMATOR /// [JsonPropertyName("scopeLimit")] public int? ScopeLimit { get; set; } /// /// How many lasers or lights are allowed on a weapon - hard coded to work with TACTICAL_COMBO, and FLASHLIGHT /// [JsonPropertyName("lightLaserLimit")] public int? LightLaserLimit { get; set; } } public record RandomisationDetails { [JsonExtensionData] public Dictionary? ExtensionData { get; set; } /// /// Between what levels do these randomisation setting apply to /// [JsonPropertyName("levelRange")] public required MinMax LevelRange { get; set; } [JsonPropertyName("generation")] public Dictionary? Generation { get; set; } /// /// Mod slots that should be fully randomised -ignores mods from bottype.json and instead creates a pool using items.json /// [JsonPropertyName("randomisedWeaponModSlots")] public List? RandomisedWeaponModSlots { get; set; } /// /// Armor slots that should be randomised e.g. 'Headwear, Armband' /// [JsonPropertyName("randomisedArmorSlots")] public List? RandomisedArmorSlots { get; set; } /// /// Equipment chances /// [JsonPropertyName("equipment")] public Dictionary? Equipment { get; set; } /// /// Weapon mod chances /// [JsonPropertyName("weaponMods")] public Dictionary? WeaponMods { get; set; } /// /// Equipment mod chances /// [JsonPropertyName("equipmentMods")] public Dictionary? EquipmentMods { get; set; } [JsonPropertyName("nighttimeChanges")] public NighttimeChanges? NighttimeChanges { get; set; } /// /// Key = weapon tpl, value = min size of magazine allowed /// [JsonPropertyName("minimumMagazineSize")] public Dictionary? MinimumMagazineSize { get; set; } } public record NighttimeChanges { [JsonExtensionData] public Dictionary? ExtensionData { get; set; } /// /// Applies changes to values stored in equipmentMods /// [JsonPropertyName("equipmentModsModifiers")] public required Dictionary EquipmentModsModifiers { get; set; } } public record EquipmentFilterDetails { [JsonExtensionData] public Dictionary? ExtensionData { get; set; } /// /// Between what levels do these equipment filter setting apply to /// [JsonPropertyName("levelRange")] public MinMax LevelRange { get; set; } /// /// Key: mod slot name e.g. mod_magazine, value: item tpls /// [JsonPropertyName("equipment")] public Dictionary>? Equipment { get; set; } /// /// Key: cartridge type e.g. Caliber23x75, value: item tpls /// [JsonPropertyName("cartridge")] public Dictionary>? Cartridge { get; set; } } public record WeightingAdjustmentDetails { [JsonExtensionData] public Dictionary? ExtensionData { get; set; } /// /// Between what levels do these weight settings apply to /// [JsonPropertyName("levelRange")] public required MinMax LevelRange { get; set; } /// /// Key: ammo type e.g. Caliber556x45NATO, value: item tpl + weight /// [JsonPropertyName("ammo")] public AdjustmentDetails? Ammo { get; set; } /// /// Key: equipment slot e.g. TacticalVest, value: item tpl + weight /// [JsonPropertyName("equipment")] public AdjustmentDetails? Equipment { get; set; } /// /// Key: clothing slot e.g. feet, value: item tpl + weight /// [JsonPropertyName("clothing")] public AdjustmentDetails? Clothing { get; set; } } public record AdjustmentDetails { [JsonExtensionData] public Dictionary? ExtensionData { get; set; } [JsonPropertyName("add")] public Dictionary>? Add { get; set; } [JsonPropertyName("edit")] public Dictionary>? Edit { get; set; } } public class ArmorPlateWeights { [JsonExtensionData] public Dictionary? ExtensionData { get; set; } [JsonPropertyName("levelRange")] public required MinMax LevelRange { get; set; } [JsonPropertyName("values")] public required Dictionary> Values { get; set; } } public record RandomisedResourceDetails { [JsonExtensionData] public Dictionary? ExtensionData { get; set; } [JsonPropertyName("food")] public RandomisedResourceValues? Food { get; set; } [JsonPropertyName("meds")] public RandomisedResourceValues? Meds { get; set; } } public record RandomisedResourceValues { [JsonExtensionData] public Dictionary? ExtensionData { get; set; } /// /// Minimum percent of item to randomized between min and max resource /// [JsonPropertyName("resourcePercent")] public float ResourcePercent { get; set; } /// /// Chance for randomization to not occur /// [JsonPropertyName("chanceMaxResourcePercent")] public float ChanceMaxResourcePercent { get; set; } }