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; }
}