using System.Text.Json.Serialization; using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Enums; using SPTarkov.Server.Core.Utils.Collections; using SPTarkov.Server.Core.Utils.Json.Converters; namespace SPTarkov.Server.Core.Models.Spt.Config; public record QuestConfig : BaseConfig { [JsonPropertyName("kind")] public override string Kind { get; set; } = "spt-quest"; /// /// Hours to get/redeem items from quest mail keyed by profile type /// [JsonPropertyName("mailRedeemTimeHours")] public required Dictionary MailRedeemTimeHours { get; set; } /// /// Collection of quests by id only available to usec /// [JsonPropertyName("usecOnlyQuests")] public required HashSet UsecOnlyQuests { get; set; } /// /// Collection of quests by id only available to bears /// [JsonPropertyName("bearOnlyQuests")] public required HashSet BearOnlyQuests { get; set; } /// /// Quests that the keyed game version do not see/access /// [JsonPropertyName("profileBlacklist")] public required Dictionary> ProfileBlacklist { get; set; } /// /// key=questid, gameversions that can see/access quest /// [JsonPropertyName("profileWhitelist")] public required Dictionary> ProfileWhitelist { get; set; } /// /// Holds repeatable quest template ids for pmc's and scav's /// [JsonPropertyName("repeatableQuestTemplateIds")] public required RepeatableQuestTemplates RepeatableQuestTemplates { get; set; } /// /// Show non-seasonal quests be shown to players /// [JsonPropertyName("showNonSeasonalEventQuests")] public required bool ShowNonSeasonalEventQuests { get; set; } /// /// Collection of event quest data keyed by quest id. /// [JsonPropertyName("eventQuests")] public required Dictionary EventQuests { get; set; } /// /// List of repeatable quest configs for; daily, weekly, and daily scav. /// [JsonPropertyName("repeatableQuests")] public required List RepeatableQuests { get; set; } /// /// Maps internal map names to their mongoId: Key - internal :: val - Mongoid /// [JsonPropertyName("locationIdMap")] public required Dictionary LocationIdMap { get; set; } } public record RepeatableQuestTemplates { [JsonExtensionData] public Dictionary ExtensionData { get; set; } /// /// Pmc repeatable quest template ids keyed by type of quest /// Keys: elimination, completion, exploration /// [JsonPropertyName("pmc")] public required Dictionary Pmc { get; set; } /// /// Scav repeatable quest template ids keyed by type of quest /// Keys: elimination, completion, exploration, pickup /// [JsonPropertyName("scav")] public required Dictionary Scav { get; set; } } public record EventQuestData { [JsonExtensionData] public Dictionary ExtensionData { get; set; } /// /// Name of the event quest /// [JsonPropertyName("name")] public required string Name { get; set; } /// /// Season to which this quest belongs /// [JsonPropertyName("season")] public required SeasonalEventType Season { get; set; } /// /// Start timestamp /// [JsonPropertyName("startTimestamp")] public required long StartTimestamp { get; set; } /// /// End timestamp /// [JsonPropertyName("endTimestamp")] [JsonConverter(typeof(StringToNumberFactoryConverter))] public required long EndTimestamp { get; set; } /// /// Is this quest part of a yearly event, ex: Christmas /// [JsonPropertyName("yearly")] public required bool Yearly { get; set; } } public record RepeatableQuestConfig { [JsonExtensionData] public Dictionary ExtensionData { get; set; } /// /// Id for type of repeatable quest /// [JsonPropertyName("id")] public required string Id { get; set; } /// /// Human-readable name for repeatable quest type /// [JsonPropertyName("name")] public required string Name { get; set; } /// /// Side this config belongs to. Note: Random not implemented, do not use! /// [JsonPropertyName("side")] [JsonConverter(typeof(JsonStringEnumConverter))] public required PlayerGroup Side { get; set; } /// /// Types of tasks this config can generate; ex: Elimination /// [JsonPropertyName("types")] public required List Types { get; set; } /// /// How long does the task stay active for after accepting it /// [JsonPropertyName("resetTime")] public required long ResetTime { get; set; } /// /// How many quests should we provide per ResetTime /// [JsonPropertyName("numQuests")] public required int NumQuests { get; set; } /// /// Min player level required to receive a quest from this config /// [JsonPropertyName("minPlayerLevel")] public required int MinPlayerLevel { get; set; } /// /// Reward scaling config /// [JsonPropertyName("rewardScaling")] public required RewardScaling RewardScaling { get; set; } /// /// Location map /// [JsonPropertyName("locations")] public required Dictionary> Locations { get; set; } /// /// Traders that are allowed to generate tasks from this config. /// Includes quest types, reward whitelist, and whether rewards can be weapons. /// [JsonPropertyName("traderWhitelist")] public required List TraderWhitelist { get; set; } /// /// Quest config, holds information on how a task should be generated /// [JsonPropertyName("questConfig")] public RepeatableQuestTypesConfig QuestConfig { get; set; } /// /// Item base types to block when generating rewards /// [JsonPropertyName("rewardBaseTypeBlacklist")] public required HashSet RewardBaseTypeBlacklist { get; set; } /// /// Item tplIds to ignore when generating rewards /// [JsonPropertyName("rewardBlacklist")] public required HashSet RewardBlacklist { get; set; } /// /// Minimum stack size that an ammo reward should be generated with /// [JsonPropertyName("rewardAmmoStackMinSize")] public required int RewardAmmoStackMinSize { get; set; } /// /// How many free task changes are available from this config /// [JsonPropertyName("freeChangesAvailable")] public required int FreeChangesAvailable { get; set; } /// /// How many free task changes remain from this config /// [JsonPropertyName("freeChanges")] public required int FreeChanges { get; set; } /// /// Should the task replacement category be the same as the one its replacing /// [JsonPropertyName("keepDailyQuestTypeOnReplacement")] public required bool KeepDailyQuestTypeOnReplacement { get; set; } /// /// Reputation standing price for replacing a repeatable /// [JsonPropertyName("standingChangeCost")] public required IList StandingChangeCost { get; set; } } public record RewardScaling { [JsonExtensionData] public Dictionary ExtensionData { get; set; } [JsonPropertyName("levels")] public List? Levels { get; set; } [JsonPropertyName("experience")] public List? Experience { get; set; } [JsonPropertyName("roubles")] public List? Roubles { get; set; } [JsonPropertyName("gpCoins")] public List? GpCoins { get; set; } [JsonPropertyName("items")] public List? Items { get; set; } [JsonPropertyName("reputation")] public List? Reputation { get; set; } [JsonPropertyName("rewardSpread")] public double? RewardSpread { get; set; } [JsonPropertyName("skillRewardChance")] public List? SkillRewardChance { get; set; } [JsonPropertyName("skillPointReward")] public List? SkillPointReward { get; set; } } public record TraderWhitelist { [JsonExtensionData] public Dictionary ExtensionData { get; set; } [JsonPropertyName("name")] public string? Name { get; set; } [JsonPropertyName("traderId")] public string? TraderId { get; set; } [JsonPropertyName("questTypes")] public List? QuestTypes { get; set; } [JsonPropertyName("rewardBaseWhitelist")] public List? RewardBaseWhitelist { get; set; } [JsonPropertyName("rewardCanBeWeapon")] public bool? RewardCanBeWeapon { get; set; } [JsonPropertyName("weaponRewardChancePercent")] public double? WeaponRewardChancePercent { get; set; } } public record RepeatableQuestTypesConfig { [JsonExtensionData] public Dictionary ExtensionData { get; set; } [JsonPropertyName("Exploration")] public Exploration? Exploration { get; set; } [JsonPropertyName("Completion")] public Completion? Completion { get; set; } [JsonPropertyName("Pickup")] public Pickup? Pickup { get; set; } [JsonPropertyName("Elimination")] public List? Elimination { get; set; } } public record Exploration : BaseQuestConfig { [JsonPropertyName("maxExtracts")] public int? MaximumExtracts { get; set; } [JsonPropertyName("maxExtractsWithSpecificExit")] public int? MaximumExtractsWithSpecificExit { get; set; } [JsonPropertyName("specificExits")] public SpecificExits? SpecificExits { get; set; } } public record SpecificExits { [JsonExtensionData] public Dictionary ExtensionData { get; set; } [JsonPropertyName("probability")] public double? Probability { get; set; } [JsonPropertyName("passageRequirementWhitelist")] public List? PassageRequirementWhitelist { get; set; } } public record Completion : BaseQuestConfig { [JsonPropertyName("minRequestedAmount")] public int? MinimumRequestedAmount { get; set; } [JsonPropertyName("maxRequestedAmount")] public int? MaximumRequestedAmount { get; set; } [JsonPropertyName("uniqueItemCount")] public int? UniqueItemCount { get; set; } [JsonPropertyName("minRequestedBulletAmount")] public int? MinimumRequestedBulletAmount { get; set; } [JsonPropertyName("maxRequestedBulletAmount")] public int? MaximumRequestedBulletAmount { get; set; } [JsonPropertyName("useWhitelist")] public bool? UseWhitelist { get; set; } [JsonPropertyName("useBlacklist")] public bool? UseBlacklist { get; set; } /// /// Should supplied items be required FiR /// [JsonPropertyName("requiredItemsAreFiR")] public bool? RequiredItemsAreFiR { get; set; } /// /// Should supplied items be required FiR /// [JsonPropertyName("requiredItemMinDurabilityMinMax")] public MinMax? RequiredItemMinDurabilityMinMax { get; set; } /// /// Blacklisted item types to not collect /// [JsonPropertyName("requiredItemTypeBlacklist")] public HashSet? RequiredItemTypeBlacklist { get; set; } } public record Pickup : BaseQuestConfig { [JsonPropertyName("ItemTypeToFetchWithMaxCount")] public List? ItemTypeToFetchWithMaxCount { get; set; } public List? ItemTypesToFetch { get; set; } [JsonPropertyName("maxItemFetchCount")] public int? MaxItemFetchCount { get; set; } } public record PickupTypeWithMaxCount { [JsonExtensionData] public Dictionary ExtensionData { get; set; } [JsonPropertyName("itemType")] public string? ItemType { get; set; } [JsonPropertyName("maxPickupCount")] public int? MaximumPickupCount { get; set; } [JsonPropertyName("minPickupCount")] public int? MinimumPickupCount { get; set; } } public record EliminationConfig : BaseQuestConfig { [JsonPropertyName("levelRange")] public MinMax? LevelRange { get; set; } [JsonPropertyName("targets")] public List>? Targets { get; set; } [JsonPropertyName("bodyPartProb")] public double? BodyPartProbability { get; set; } [JsonPropertyName("bodyParts")] public List>>? BodyParts { get; set; } [JsonPropertyName("specificLocationProb")] public double? SpecificLocationProbability { get; set; } [JsonPropertyName("distLocationBlacklist")] public List? DistLocationBlacklist { get; set; } [JsonPropertyName("distProb")] public double? DistanceProbability { get; set; } [JsonPropertyName("maxDist")] public double? MaxDistance { get; set; } [JsonPropertyName("minDist")] public double? MinDistance { get; set; } [JsonPropertyName("maxKills")] public int? MaxKills { get; set; } [JsonPropertyName("minKills")] public int? MinKills { get; set; } [JsonPropertyName("minBossKills")] public int? MinBossKills { get; set; } [JsonPropertyName("maxBossKills")] public int? MaxBossKills { get; set; } [JsonPropertyName("minPmcKills")] public int? MinPmcKills { get; set; } [JsonPropertyName("maxPmcKills")] public int? MaxPmcKills { get; set; } [JsonPropertyName("weaponCategoryRequirementProb")] public double? WeaponCategoryRequirementProbability { get; set; } [JsonPropertyName("weaponCategoryRequirements")] public List>>? WeaponCategoryRequirements { get; set; } [JsonPropertyName("weaponRequirementProb")] public double? WeaponRequirementProbability { get; set; } [JsonPropertyName("weaponRequirements")] public List>>? WeaponRequirements { get; set; } } public record BaseQuestConfig { [JsonExtensionData] public Dictionary ExtensionData { get; set; } [JsonPropertyName("possibleSkillRewards")] public List? PossibleSkillRewards { get; set; } } public record BossInfo { [JsonExtensionData] public Dictionary ExtensionData { get; set; } [JsonPropertyName("isBoss")] public bool? IsBoss { get; set; } [JsonPropertyName("isPmc")] public bool? IsPmc { get; set; } }