diff --git a/Core/Annotations/Injectable.cs b/Core/Annotations/Injectable.cs index 667d0fb2..86b1d906 100644 --- a/Core/Annotations/Injectable.cs +++ b/Core/Annotations/Injectable.cs @@ -1,4 +1,4 @@ -namespace Types.Annotations; +namespace Core.Annotations; [AttributeUsage(AttributeTargets.Class)] public class Injectable(InjectionType injectionType = InjectionType.Scoped, Type? type = null) : Attribute diff --git a/Core/Context/ApplicationContext.cs b/Core/Context/ApplicationContext.cs index 51f2ce84..05b10522 100644 --- a/Core/Context/ApplicationContext.cs +++ b/Core/Context/ApplicationContext.cs @@ -1,6 +1,6 @@ -using Types.Annotations; +using Core.Annotations; -namespace Types.Context; +namespace Core.Context; [Injectable(InjectionType.Singleton)] public class ApplicationContext diff --git a/Core/Context/ContextVariable.cs b/Core/Context/ContextVariable.cs index 7bea953c..3e79b5f0 100644 --- a/Core/Context/ContextVariable.cs +++ b/Core/Context/ContextVariable.cs @@ -1,4 +1,4 @@ -namespace Types.Context; +namespace Core.Context; public class ContextVariable(object value, ContextVariableType contextVariableType) { diff --git a/Core/Context/ContextVariableType.cs b/Core/Context/ContextVariableType.cs index 0f64ca1b..409e7656 100644 --- a/Core/Context/ContextVariableType.cs +++ b/Core/Context/ContextVariableType.cs @@ -1,4 +1,4 @@ -namespace Types.Context; +namespace Core.Context; public enum ContextVariableType { diff --git a/Core/Models/Common/MinMax.cs b/Core/Models/Common/MinMax.cs new file mode 100644 index 00000000..2ed8cae1 --- /dev/null +++ b/Core/Models/Common/MinMax.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace Core.Models.Common; + +public class MinMax +{ + [JsonPropertyName("max")] + public double Max { get; set; } + + [JsonPropertyName("min")] + public double Min { get; set; } +} \ No newline at end of file diff --git a/Core/Models/Eft/Common/Location.cs b/Core/Models/Eft/Common/Location.cs new file mode 100644 index 00000000..d9ccba3a --- /dev/null +++ b/Core/Models/Eft/Common/Location.cs @@ -0,0 +1,187 @@ +using System.Text.Json.Serialization; +using Core.Models.Eft.Common.Tables; + +namespace Core.Models.Eft.Common; + +public class Location +{ + /** Map meta-data */ + [JsonPropertyName("base")] + public LocationBase Base { get; set; } + + /** Loose loot positions and item weights */ + [JsonPropertyName("looseLoot")] + public LooseLoot LooseLoot { get; set; } + + /** Static loot item weights */ + [JsonPropertyName("staticLoot")] + public Dictionary StaticLoot { get; set; } + + /** Static container positions and item weights */ + [JsonPropertyName("staticContainers")] + public StaticContainerDetails StaticContainers { get; set; } + + [JsonPropertyName("staticAmmo")] + public Dictionary StaticAmmo { get; set; } + + /** All possible static containers on map + their assign groupings */ + [JsonPropertyName("statics")] + public StaticContainer StaticContainer { get; set; } + + /** All possible map extracts */ + [JsonPropertyName("allExtracts")] + public Exit[] AllExtracts { get; set; } +} + +public class StaticContainer +{ + [JsonPropertyName("containersGroups")] + public Dictionary ContainersGroups { get; set; } + + [JsonPropertyName("containers")] + public Dictionary Containers { get; set; } +} + +public class ContainerMinMax +{ + [JsonPropertyName("minContainers")] + public int MinContainers { get; set; } + + [JsonPropertyName("maxContainers")] + public int MaxContainers { get; set; } + + [JsonPropertyName("current")] + public int? Current { get; set; } + + [JsonPropertyName("chosenCount")] + public int? ChosenCount { get; set; } +} + +public class ContainerData +{ + [JsonPropertyName("groupId")] + public string GroupId { get; set; } +} + +public class StaticLootDetails +{ + [JsonPropertyName("itemcountDistribution")] + public ItemCountDistribution[] ItemCountDistribution { get; set; } + + [JsonPropertyName("itemDistribution")] + public ItemDistribution[] ItemDistribution { get; set; } +} + +public class ItemCountDistribution +{ + [JsonPropertyName("count")] + public int Count { get; set; } + + [JsonPropertyName("relativeProbability")] + public float RelativeProbability { get; set; } +} + +public class ItemDistribution +{ + [JsonPropertyName("tpl")] + public string Tpl { get; set; } + + [JsonPropertyName("relativeProbability")] + public float RelativeProbability { get; set; } +} + +public class StaticPropsBase +{ + [JsonPropertyName("Id")] + public string Id { get; set; } + + [JsonPropertyName("IsContainer")] + public bool IsContainer { get; set; } + + [JsonPropertyName("useGravity")] + public bool UseGravity { get; set; } + + [JsonPropertyName("randomRotation")] + public bool RandomRotation { get; set; } + + [JsonPropertyName("Position")] + public XYZ Position { get; set; } + + [JsonPropertyName("Rotation")] + public XYZ Rotation { get; set; } + + [JsonPropertyName("IsGroupPosition")] + public bool IsGroupPosition { get; set; } + + [JsonPropertyName("IsAlwaysSpawn")] + public bool IsAlwaysSpawn { get; set; } + + [JsonPropertyName("GroupPositions")] + public GroupPosition[] GroupPositions { get; set; } + + [JsonPropertyName("Root")] + public string Root { get; set; } + + [JsonPropertyName("Items")] + public Item[] Items { get; set; } +} + +public class StaticWeaponProps : StaticPropsBase +{ + [JsonPropertyName("Items")] + public Item[] Items { get; set; } +} + +public class StaticContainerDetails +{ + [JsonPropertyName("staticWeapons")] + public StaticWeaponProps[] StaticWeapons { get; set; } + + [JsonPropertyName("staticContainers")] + public StaticContainerData[] StaticContainers { get; set; } + + [JsonPropertyName("staticForced")] + public StaticForcedProps[] StaticForced { get; set; } +} + +public class StaticContainerData +{ + [JsonPropertyName("probability")] + public float Probability { get; set; } + + [JsonPropertyName("template")] + public StaticContainerProps Template { get; set; } +} + +public class StaticAmmoDetails +{ + [JsonPropertyName("tpl")] + public string Tpl { get; set; } + + [JsonPropertyName("relativeProbability")] + public float RelativeProbability { get; set; } +} + +public class StaticForcedProps +{ + [JsonPropertyName("containerId")] + public string ContainerId { get; set; } + + [JsonPropertyName("itemTpl")] + public string ItemTpl { get; set; } +} + +public class StaticContainerProps : StaticPropsBase +{ + [JsonPropertyName("Items")] + public StaticItem[] Items { get; set; } +} + +public class StaticItem +{ + [JsonPropertyName("_id")] + public string Id { get; set; } + + [JsonPropertyName("_tpl")] + public string Tpl { get; set; } +} \ No newline at end of file diff --git a/Core/Models/Eft/Common/LocationBase.cs b/Core/Models/Eft/Common/LocationBase.cs new file mode 100644 index 00000000..74b6d106 --- /dev/null +++ b/Core/Models/Eft/Common/LocationBase.cs @@ -0,0 +1,842 @@ +using System.Text.Json.Serialization; +using Core.Models.Common; + +namespace Core.Models.Eft.Common; + +public class LocationBase +{ + [JsonPropertyName("AccessKeys")] + public List AccessKeys { get; set; } + + [JsonPropertyName("AccessKeysPvE")] + public List AccessKeysPvE { get; set; } + + [JsonPropertyName("AirdropParameters")] + public List AirdropParameters { get; set; } + + [JsonPropertyName("Area")] + public int Area { get; set; } + + [JsonPropertyName("AveragePlayTime")] + public double AveragePlayTime { get; set; } + + [JsonPropertyName("AveragePlayerLevel")] + public double AveragePlayerLevel { get; set; } + + [JsonPropertyName("Banners")] + public List Banners { get; set; } + + [JsonPropertyName("BossLocationSpawn")] + public List BossLocationSpawn { get; set; } + + [JsonPropertyName("BotAssault")] + public int BotAssault { get; set; } + + /** Weighting on how likely a bot will be Easy difficulty */ + [JsonPropertyName("BotEasy")] + public int BotEasy { get; set; } + + /** Weighting on how likely a bot will be Hard difficulty */ + [JsonPropertyName("BotHard")] + public int BotHard { get; set; } + + /** Weighting on how likely a bot will be Impossible difficulty */ + [JsonPropertyName("BotImpossible")] + public int BotImpossible { get; set; } + + [JsonPropertyName("BotLocationModifier")] + public BotLocationModifier BotLocationModifier { get; set; } + + [JsonPropertyName("BotMarksman")] + public int BotMarksman { get; set; } + + /** Maximum Number of bots that are currently alive/loading/delayed */ + [JsonPropertyName("BotMax")] + public int BotMax { get; set; } + + /** Is not used in 33420 */ + [JsonPropertyName("BotMaxPlayer")] + public int BotMaxPlayer { get; set; } + + /** Is not used in 33420 */ + [JsonPropertyName("BotMaxTimePlayer")] + public int BotMaxTimePlayer { get; set; } + + /** Does not even exist in the client in 33420 */ + [JsonPropertyName("BotMaxPvE")] + public int BotMaxPvE { get; set; } + + /** Weighting on how likely a bot will be Normal difficulty */ + [JsonPropertyName("BotNormal")] + public int BotNormal { get; set; } + + /** How many bot slots that need to be open before trying to spawn new bots. */ + [JsonPropertyName("BotSpawnCountStep")] + public int BotSpawnCountStep { get; set; } + + /** How often to check if bots are spawn-able. In seconds */ + [JsonPropertyName("BotSpawnPeriodCheck")] + public int BotSpawnPeriodCheck { get; set; } + + /** The bot spawn will toggle on and off in intervals of Off(Min/Max) and On(Min/Max) */ + [JsonPropertyName("BotSpawnTimeOffMax")] + public int BotSpawnTimeOffMax { get; set; } + + [JsonPropertyName("BotSpawnTimeOffMin")] + public int BotSpawnTimeOffMin { get; set; } + + [JsonPropertyName("BotSpawnTimeOnMax")] + public int BotSpawnTimeOnMax { get; set; } + + [JsonPropertyName("BotSpawnTimeOnMin")] + public int BotSpawnTimeOnMin { get; set; } + + /** How soon bots will be allowed to spawn */ + [JsonPropertyName("BotStart")] + public int BotStart { get; set; } + + /** After this long bots will no longer spawn */ + [JsonPropertyName("BotStop")] + public int BotStop { get; set; } + + [JsonPropertyName("Description")] + public string Description { get; set; } + + [JsonPropertyName("DisabledForScav")] + public bool DisabledForScav { get; set; } + + [JsonPropertyName("DisabledScavExits")] + public string DisabledScavExits { get; set; } + + [JsonPropertyName("Enabled")] + public bool Enabled { get; set; } + + [JsonPropertyName("EnableCoop")] + public bool EnableCoop { get; set; } + + [JsonPropertyName("GlobalLootChanceModifier")] + public double GlobalLootChanceModifier { get; set; } + + [JsonPropertyName("GlobalLootChanceModifierPvE")] + public double GlobalLootChanceModifierPvE { get; set; } + + [JsonPropertyName("GlobalContainerChanceModifier")] + public double GlobalContainerChanceModifier { get; set; } + + [JsonPropertyName("IconX")] + public int IconX { get; set; } + + [JsonPropertyName("IconY")] + public int IconY { get; set; } + + [JsonPropertyName("Id")] + public string Id { get; set; } + + [JsonPropertyName("Insurance")] + public bool Insurance { get; set; } + + [JsonPropertyName("IsSecret")] + public bool IsSecret { get; set; } + + [JsonPropertyName("Locked")] + public bool Locked { get; set; } + + [JsonPropertyName("Loot")] + public List Loot { get; set; } + + [JsonPropertyName("MatchMakerMinPlayersByWaitTime")] + public List MatchMakerMinPlayersByWaitTime { get; set; } + + [JsonPropertyName("MaxBotPerZone")] + public int MaxBotPerZone { get; set; } + + [JsonPropertyName("MaxDistToFreePoint")] + public double MaxDistToFreePoint { get; set; } + + [JsonPropertyName("MaxPlayers")] + public int MaxPlayers { get; set; } + + [JsonPropertyName("MinDistToExitPoint")] + public double MinDistToExitPoint { get; set; } + + [JsonPropertyName("MinDistToFreePoint")] + public double MinDistToFreePoint { get; set; } + + [JsonPropertyName("MinMaxBots")] + public List MinMaxBots { get; set; } + + [JsonPropertyName("MinPlayers")] + public int MinPlayers { get; set; } + + [JsonPropertyName("MaxCoopGroup")] + public int MaxCoopGroup { get; set; } + + [JsonPropertyName("Name")] + public string Name { get; set; } + + [JsonPropertyName("NonWaveGroupScenario")] + public NonWaveGroupScenario NonWaveGroupScenario { get; set; } + + [JsonPropertyName("NewSpawn")] + public bool NewSpawn { get; set; } + + [JsonPropertyName("OcculsionCullingEnabled")] + public bool OcculsionCullingEnabled { get; set; } + + [JsonPropertyName("OldSpawn")] + public bool OldSpawn { get; set; } + + [JsonPropertyName("OpenZones")] + public string OpenZones { get; set; } + + [JsonPropertyName("Preview")] + public Preview Preview { get; set; } + + [JsonPropertyName("PlayersRequestCount")] + public int PlayersRequestCount { get; set; } + + [JsonPropertyName("RequiredPlayerLevel")] + public int? RequiredPlayerLevel { get; set; } + + [JsonPropertyName("RequiredPlayerLevelMin")] + public int? RequiredPlayerLevelMin { get; set; } + + [JsonPropertyName("RequiredPlayerLevelMax")] + public int? RequiredPlayerLevelMax { get; set; } + + [JsonPropertyName("MinPlayerLvlAccessKeys")] + public int MinPlayerLvlAccessKeys { get; set; } + + [JsonPropertyName("PmcMaxPlayersInGroup")] + public int PmcMaxPlayersInGroup { get; set; } + + [JsonPropertyName("ScavMaxPlayersInGroup")] + public int ScavMaxPlayersInGroup { get; set; } + + [JsonPropertyName("Rules")] + public string Rules { get; set; } + + [JsonPropertyName("SafeLocation")] + public bool SafeLocation { get; set; } + + [JsonPropertyName("Scene")] + public Scene Scene { get; set; } + + [JsonPropertyName("SpawnPointParams")] + public List SpawnPointParams { get; set; } + + [JsonPropertyName("UnixDateTime")] + public long UnixDateTime { get; set; } + + [JsonPropertyName("_Id")] + public string IdField { get; set; } + + [JsonPropertyName("doors")] + public List Doors { get; set; } + + [JsonPropertyName("EscapeTimeLimit")] + public int EscapeTimeLimit { get; set; } + + [JsonPropertyName("EscapeTimeLimitCoop")] + public int EscapeTimeLimitCoop { get; set; } + + [JsonPropertyName("EscapeTimeLimitPVE")] + public int EscapeTimeLimitPVE { get; set; } + + [JsonPropertyName("Events")] + public LocationEvents Events { get; set; } + + [JsonPropertyName("exit_access_time")] + public int ExitAccessTime { get; set; } + + [JsonPropertyName("ForceOnlineRaidInPVE")] + public bool ForceOnlineRaidInPVE { get; set; } + + [JsonPropertyName("exit_count")] + public int ExitCount { get; set; } + + [JsonPropertyName("exit_time")] + public int ExitTime { get; set; } + + [JsonPropertyName("exits")] + public List Exits { get; set; } + + [JsonPropertyName("filter_ex")] + public List FilterEx { get; set; } + + [JsonPropertyName("limits")] + public List Limits { get; set; } + + [JsonPropertyName("matching_min_seconds")] + public int MatchingMinSeconds { get; set; } + + [JsonPropertyName("GenerateLocalLootCache")] + public bool GenerateLocalLootCache { get; set; } + + [JsonPropertyName("maxItemCountInLocation")] + public List MaxItemCountInLocation { get; set; } + + [JsonPropertyName("sav_summon_seconds")] + public int SavSummonSeconds { get; set; } + + [JsonPropertyName("tmp_location_field_remove_me")] + public int TmpLocationFieldRemoveMe { get; set; } + + [JsonPropertyName("transits")] + public List Transits { get; set; } + + [JsonPropertyName("users_gather_seconds")] + public int UsersGatherSeconds { get; set; } + + [JsonPropertyName("users_spawn_seconds_n")] + public int UsersSpawnSecondsN { get; set; } + + [JsonPropertyName("users_spawn_seconds_n2")] + public int UsersSpawnSecondsN2 { get; set; } + + [JsonPropertyName("users_summon_seconds")] + public int UsersSummonSeconds { get; set; } + + [JsonPropertyName("waves")] + public List Waves { get; set; } +} + +public class Transit { + [JsonPropertyName("activateAfterSec")] + public string ActivateAfterSeconds { get; set; } + + [JsonPropertyName("active")] + public bool IsActive { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("conditions")] + public string Conditions { get; set; } + + [JsonPropertyName("description")] + public string Description { get; set; } + + [JsonPropertyName("id")] + public int Id { get; set; } + + [JsonPropertyName("location")] + public string Location { get; set; } + + [JsonPropertyName("target")] + public string Target { get; set; } + + [JsonPropertyName("time")] + public int Time { get; set; } +} + +public class NonWaveGroupScenario { + [JsonPropertyName("Chance")] + public double Chance { get; set; } + + [JsonPropertyName("Enabled")] + public bool IsEnabled { get; set; } + + [JsonPropertyName("MaxToBeGroup")] + public int MaximumToBeGrouped { get; set; } + + [JsonPropertyName("MinToBeGroup")] + public int MinimumToBeGrouped { get; set; } +} + +public class Limit : MinMax { + [JsonPropertyName("items")] + public object[] Items { get; set; } // TODO: was on TS any[] hmmm.. +} + +public class AirdropParameter { + [JsonPropertyName("AirdropPointDeactivateDistance")] + public double AirdropPointDeactivateDistance { get; set; } + + [JsonPropertyName("MinPlayersCountToSpawnAirdrop")] + public double MinimumPlayersCountToSpawnAirdrop { get; set; } + + [JsonPropertyName("PlaneAirdropChance")] + public double PlaneAirdropChance { get; set; } + + [JsonPropertyName("PlaneAirdropCooldownMax")] + public double PlaneAirdropCooldownMax { get; set; } + + [JsonPropertyName("PlaneAirdropCooldownMin")] + public double PlaneAirdropCooldownMin { get; set; } + + [JsonPropertyName("PlaneAirdropEnd")] + public double PlaneAirdropEnd { get; set; } + + [JsonPropertyName("PlaneAirdropMax")] + public double PlaneAirdropMax { get; set; } + + [JsonPropertyName("PlaneAirdropStartMax")] + public double PlaneAirdropStartMax { get; set; } + + [JsonPropertyName("PlaneAirdropStartMin")] + public double PlaneAirdropStartMin { get; set; } + + [JsonPropertyName("UnsuccessfulTryPenalty")] + public double UnsuccessfulTryPenalty { get; set; } +} + +public class Banner { + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("pic")] + public Pic Picture { get; set; } +} + +public class Pic { + [JsonPropertyName("path")] + public string Path { get; set; } + + [JsonPropertyName("rcid")] + public string Rcid { get; set; } +} + +public class BossLocationSpawn { + [JsonPropertyName("BossChance")] + public double BossChance { get; set; } + + [JsonPropertyName("BossDifficult")] + public string BossDifficulty { get; set; } + + [JsonPropertyName("BossEscortAmount")] + public string BossEscortAmount { get; set; } + + [JsonPropertyName("BossEscortDifficult")] + public string BossEscortDifficulty { get; set; } + + [JsonPropertyName("BossEscortType")] + public string BossEscortType { get; set; } + + [JsonPropertyName("BossName")] + public string BossName { get; set; } + + [JsonPropertyName("BossPlayer")] + public bool IsBossPlayer { get; set; } + + [JsonPropertyName("BossZone")] + public string BossZone { get; set; } + + [JsonPropertyName("RandomTimeSpawn")] + public bool IsRandomTimeSpawn { get; set; } + + [JsonPropertyName("Time")] + public double Time { get; set; } + + [JsonPropertyName("TriggerId")] + public string TriggerId { get; set; } + + [JsonPropertyName("TriggerName")] + public string TriggerName { get; set; } + + [JsonPropertyName("Delay")] + public double? Delay { get; set; } + + [JsonPropertyName("DependKarma")] + public bool? DependKarma { get; set; } + + [JsonPropertyName("DependKarmaPVE")] + public bool? DependKarmaPVE { get; set; } + + [JsonPropertyName("ForceSpawn")] + public bool? ForceSpawn { get; set; } + + [JsonPropertyName("IgnoreMaxBots")] + public bool? IgnoreMaxBots { get; set; } + + [JsonPropertyName("Supports")] + public BossSupport[] Supports { get; set; } + + [JsonPropertyName("sptId")] + public string SptId { get; set; } + + [JsonPropertyName("spawnMode")] + public string[] SpawnMode { get; set; } +} + +public class BossSupport { + [JsonPropertyName("BossEscortAmount")] + public string BossEscortAmount { get; set; } + + [JsonPropertyName("BossEscortDifficult")] + public string[] BossEscortDifficulty { get; set; } + + [JsonPropertyName("BossEscortType")] + public string BossEscortType { get; set; } +} + +public class BotLocationModifier { + [JsonPropertyName("AccuracySpeed")] + public double AccuracySpeed { get; set; } + + [JsonPropertyName("AdditionalHostilitySettings")] + public AdditionalHostilitySettings[] AdditionalHostilitySettings { get; set; } + + [JsonPropertyName("DistToActivate")] + public double DistanceToActivate { get; set; } + + [JsonPropertyName("DistToActivatePvE")] + public double DistanceToActivatePvE { get; set; } + + [JsonPropertyName("DistToPersueAxemanCoef")] + public double DistanceToPursueAxemanCoefficient { get; set; } + + [JsonPropertyName("DistToSleep")] + public double DistanceToSleep { get; set; } + + [JsonPropertyName("DistToSleepPvE")] + public double DistanceToSleepPvE { get; set; } + + [JsonPropertyName("GainSight")] + public double GainSight { get; set; } + + [JsonPropertyName("KhorovodChance")] + public double KhorovodChance { get; set; } + + [JsonPropertyName("MagnetPower")] + public double MagnetPower { get; set; } + + [JsonPropertyName("MarksmanAccuratyCoef")] + public double MarksmanAccuracyCoefficient { get; set; } + + [JsonPropertyName("Scattering")] + public double Scattering { get; set; } + + [JsonPropertyName("VisibleDistance")] + public double VisibleDistance { get; set; } + + [JsonPropertyName("MaxExfiltrationTime")] + public double MaxExfiltrationTime { get; set; } + + [JsonPropertyName("MinExfiltrationTime")] + public double MinExfiltrationTime { get; set; } +} + +public class AdditionalHostilitySettings +{ + [JsonPropertyName("AlwaysEnemies")] + public List AlwaysEnemies { get; set; } + + [JsonPropertyName("AlwaysFriends")] + public List AlwaysFriends { get; set; } + + [JsonPropertyName("BearEnemyChance")] + public int BearEnemyChance { get; set; } + + [JsonPropertyName("BearPlayerBehaviour")] + public string BearPlayerBehaviour { get; set; } + + [JsonPropertyName("BotRole")] + public string BotRole { get; set; } + + [JsonPropertyName("ChancedEnemies")] + public List ChancedEnemies { get; set; } + + [JsonPropertyName("Neutral")] + public List Neutral { get; set; } + + [JsonPropertyName("SavagePlayerBehaviour")] + public string SavagePlayerBehaviour { get; set; } + + [JsonPropertyName("SavageEnemyChance")] + public int? SavageEnemyChance { get; set; } + + [JsonPropertyName("UsecEnemyChance")] + public int UsecEnemyChance { get; set; } + + [JsonPropertyName("UsecPlayerBehaviour")] + public string UsecPlayerBehaviour { get; set; } + + [JsonPropertyName("Warn")] + public List Warn { get; set; } +} + +public class ChancedEnemy +{ + [JsonPropertyName("EnemyChance")] + public int EnemyChance { get; set; } + + [JsonPropertyName("Role")] + public string Role { get; set; } +} + +public class MinMaxBot : MinMax +{ + [JsonPropertyName("WildSpawnType")] + public object WildSpawnType { get; set; } // TODO: Could be WildSpawnType or string +} + +public class MinPlayerWaitTime +{ + [JsonPropertyName("minPlayers")] + public int MinPlayers { get; set; } + + [JsonPropertyName("time")] + public int Time { get; set; } +} + +public class Preview +{ + [JsonPropertyName("path")] + public string Path { get; set; } + + [JsonPropertyName("rcid")] + public string Rcid { get; set; } +} + +public class Scene +{ + [JsonPropertyName("path")] + public string Path { get; set; } + + [JsonPropertyName("rcid")] + public string Rcid { get; set; } +} + +public class SpawnPointParam +{ + [JsonPropertyName("BotZoneName")] + public string BotZoneName { get; set; } + + [JsonPropertyName("Categories")] + public List Categories { get; set; } + + [JsonPropertyName("ColliderParams")] + public ColliderParams ColliderParams { get; set; } + + [JsonPropertyName("CorePointId")] + public int CorePointId { get; set; } + + [JsonPropertyName("DelayToCanSpawnSec")] + public int DelayToCanSpawnSec { get; set; } + + [JsonPropertyName("Id")] + public string Id { get; set; } + + [JsonPropertyName("Infiltration")] + public string Infiltration { get; set; } + + [JsonPropertyName("Position")] + public XYZ Position { get; set; } + + [JsonPropertyName("Rotation")] + public float Rotation { get; set; } + + [JsonPropertyName("Sides")] + public List Sides { get; set; } +} + +public class ColliderParams +{ + [JsonPropertyName("_parent")] + public string Parent { get; set; } + + [JsonPropertyName("_props")] + public Props Props { get; set; } +} + +public class Props +{ + [JsonPropertyName("Center")] + public XYZ Center { get; set; } + + [JsonPropertyName("Radius")] + public float Radius { get; set; } +} + +public class Exit +{ + /** % Chance out of 100 exit will appear in raid */ + [JsonPropertyName("Chance")] + public int Chance { get; set; } + + [JsonPropertyName("ChancePVE")] + public int ChancePVE { get; set; } + + [JsonPropertyName("Count")] + public int Count { get; set; } + + [JsonPropertyName("CountPVE")] + public int CountPVE { get; set; } + + [JsonPropertyName("EntryPoints")] + public string EntryPoints { get; set; } + + [JsonPropertyName("EventAvailable")] + public bool EventAvailable { get; set; } + + [JsonPropertyName("ExfiltrationTime")] + public float ExfiltrationTime { get; set; } + + [JsonPropertyName("ExfiltrationTimePVE")] + public float ExfiltrationTimePVE { get; set; } + + [JsonPropertyName("ExfiltrationType")] + public string ExfiltrationType { get; set; } + + [JsonPropertyName("RequiredSlot")] + public string RequiredSlot { get; set; } + + [JsonPropertyName("Id")] + public string Id { get; set; } + + [JsonPropertyName("MaxTime")] + public float MaxTime { get; set; } + + [JsonPropertyName("MaxTimePVE")] + public float MaxTimePVE { get; set; } + + [JsonPropertyName("MinTime")] + public float MinTime { get; set; } + + [JsonPropertyName("MinTimePVE")] + public float MinTimePVE { get; set; } + + [JsonPropertyName("Name")] + public string Name { get; set; } + + [JsonPropertyName("PassageRequirement")] + public string PassageRequirement { get; set; } + + [JsonPropertyName("PlayersCount")] + public int PlayersCount { get; set; } + + [JsonPropertyName("PlayersCountPVE")] + public int PlayersCountPVE { get; set; } + + [JsonPropertyName("RequirementTip")] + public string RequirementTip { get; set; } + + [JsonPropertyName("Side")] + public string Side { get; set; } +} + +public class MaxItemCountInLocation +{ + [JsonPropertyName("TemplateId")] + public string TemplateId { get; set; } + + [JsonPropertyName("Value")] + public int Value { get; set; } +} + +public class Wave +{ + [JsonPropertyName("BotPreset")] + public string BotPreset { get; set; } + + [JsonPropertyName("BotSide")] + public string BotSide { get; set; } + + [JsonPropertyName("SpawnPoints")] + public string SpawnPoints { get; set; } + + [JsonPropertyName("WildSpawnType")] + public WildSpawnType WildSpawnType { get; set; } + + [JsonPropertyName("isPlayers")] + public bool IsPlayers { get; set; } + + [JsonPropertyName("number")] + public int Number { get; set; } + + [JsonPropertyName("slots_max")] + public int SlotsMax { get; set; } + + [JsonPropertyName("slots_min")] + public int SlotsMin { get; set; } + + [JsonPropertyName("time_max")] + public int TimeMax { get; set; } + + [JsonPropertyName("time_min")] + public int TimeMin { get; set; } + + /** OPTIONAL - Needs to be unique - Used by custom wave service to ensure same wave isnt added multiple times */ + [JsonPropertyName("sptId")] + public string? SptId { get; set; } + + [JsonPropertyName("ChanceGroup")] + public int? ChanceGroup { get; set; } + + /** 'pve' and/or 'regular' */ + [JsonPropertyName("SpawnMode")] + public List SpawnMode { get; set; } +} + +public class LocationEvents +{ + [JsonPropertyName("Halloween2024")] + public Halloween2024 Halloween2024 { get; set; } +} + +public class Halloween2024 +{ + [JsonPropertyName("CrowdAttackBlockRadius")] + public int CrowdAttackBlockRadius { get; set; } + + [JsonPropertyName("CrowdAttackSpawnParams")] + public List CrowdAttackSpawnParams { get; set; } + + [JsonPropertyName("CrowdCooldownPerPlayerSec")] + public int CrowdCooldownPerPlayerSec { get; set; } + + [JsonPropertyName("CrowdsLimit")] + public int CrowdsLimit { get; set; } + + [JsonPropertyName("InfectedLookCoeff")] + public double InfectedLookCoeff { get; set; } + + [JsonPropertyName("MaxCrowdAttackSpawnLimit")] + public int MaxCrowdAttackSpawnLimit { get; set; } + + [JsonPropertyName("MinInfectionPercentage")] + public double MinInfectionPercentage { get; set; } + + [JsonPropertyName("MinSpawnDistToPlayer")] + public double MinSpawnDistToPlayer { get; set; } + + [JsonPropertyName("TargetPointSearchRadiusLimit")] + public double TargetPointSearchRadiusLimit { get; set; } + + [JsonPropertyName("ZombieCallDeltaRadius")] + public double ZombieCallDeltaRadius { get; set; } + + [JsonPropertyName("ZombieCallPeriodSec")] + public int ZombieCallPeriodSec { get; set; } + + [JsonPropertyName("ZombieCallRadiusLimit")] + public double ZombieCallRadiusLimit { get; set; } + + [JsonPropertyName("ZombieMultiplier")] + public double ZombieMultiplier { get; set; } + + [JsonPropertyName("InfectionPercentage")] + public double InfectionPercentage { get; set; } +} + +public class CrowdAttackSpawnParam +{ + [JsonPropertyName("Difficulty")] + public string Difficulty { get; set; } + + [JsonPropertyName("Role")] + public string Role { get; set; } + + [JsonPropertyName("Weight")] + public int Weight { get; set; } +} + +public enum WildSpawnType +{ + assault, + marksman, + pmcbot, + bosskilla, + bossknight +} \ No newline at end of file diff --git a/Core/Models/Eft/Common/LooseLoot.cs b/Core/Models/Eft/Common/LooseLoot.cs new file mode 100644 index 00000000..f88b6164 --- /dev/null +++ b/Core/Models/Eft/Common/LooseLoot.cs @@ -0,0 +1,118 @@ +using System.Text.Json.Serialization; +using Core.Models.Eft.Common.Tables; + +namespace Core.Models.Eft.Common; + +public class LooseLoot +{ + [JsonPropertyName("spawnpointCount")] + public SpawnpointCount SpawnpointCount { get; set; } + + [JsonPropertyName("spawnpointsForced")] + public List SpawnpointsForced { get; set; } + + [JsonPropertyName("spawnpoints")] + public List Spawnpoints { get; set; } +} + +public class SpawnpointCount +{ + [JsonPropertyName("mean")] + public double Mean { get; set; } + + [JsonPropertyName("std")] + public double Std { get; set; } +} + +public class SpawnpointsForced +{ + [JsonPropertyName("locationId")] + public string LocationId { get; set; } + + [JsonPropertyName("probability")] + public double Probability { get; set; } + + [JsonPropertyName("template")] + public SpawnpointTemplate Template { get; set; } +} + +public class SpawnpointTemplate +{ + [JsonPropertyName("Id")] + public string Id { get; set; } + + [JsonPropertyName("IsContainer")] + public bool IsContainer { get; set; } + + [JsonPropertyName("useGravity")] + public bool UseGravity { get; set; } + + [JsonPropertyName("randomRotation")] + public bool RandomRotation { get; set; } + + [JsonPropertyName("Position")] + public XYZ Position { get; set; } + + [JsonPropertyName("Rotation")] + public XYZ Rotation { get; set; } + + [JsonPropertyName("IsAlwaysSpawn")] + public bool IsAlwaysSpawn { get; set; } + + [JsonPropertyName("IsGroupPosition")] + public bool IsGroupPosition { get; set; } + + [JsonPropertyName("GroupPositions")] + public List GroupPositions { get; set; } + + [JsonPropertyName("Root")] + public string Root { get; set; } + + [JsonPropertyName("Items")] + public List Items { get; set; } +} + +public class GroupPosition +{ + [JsonPropertyName("Name")] + public string Name { get; set; } + + [JsonPropertyName("Weight")] + public double Weight { get; set; } + + [JsonPropertyName("Postion")] + public XYZ Position { get; set; } + + [JsonPropertyName("Rotation")] + public XYZ Rotation { get; set; } +} + +public class Spawnpoint +{ + [JsonPropertyName("locationId")] + public string LocationId { get; set; } + + [JsonPropertyName("probability")] + public double Probability { get; set; } + + [JsonPropertyName("template")] + public SpawnpointTemplate Template { get; set; } + + [JsonPropertyName("itemDistribution")] + public List ItemDistribution { get; set; } +} + +public class LooseLootItemDistribution +{ + [JsonPropertyName("composedKey")] + public ComposedKey ComposedKey { get; set; } + + [JsonPropertyName("relativeProbability")] + public double RelativeProbability { get; set; } +} + +public class ComposedKey +{ + [JsonPropertyName("key")] + public string Key { get; set; } +} \ No newline at end of file diff --git a/Core/Models/Eft/Common/Tables/BotBase.cs b/Core/Models/Eft/Common/Tables/BotBase.cs index df51dbf4..efcff112 100644 --- a/Core/Models/Eft/Common/Tables/BotBase.cs +++ b/Core/Models/Eft/Common/Tables/BotBase.cs @@ -1,12 +1,106 @@ using System.Text.Json.Serialization; +using Core.Models.Eft.Ragfair; +using Core.Models.Enums; namespace Core.Models.Eft.Common.Tables; public class BotBase { - + [JsonPropertyName("_id")] + public string Id { get; set; } + [JsonPropertyName("aid")] + public int Aid { get; set; } + /** SPT property - use to store player id - TODO - move to AID ( account id as guid of choice) */ + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } + [JsonPropertyName("savage")] + public string? Savage { get; set; } + [JsonPropertyName("karmaValue")] + public int KarmaValue { get; set; } + [JsonPropertyName("Info")] + public Info Info { get; set; } + [JsonPropertyName("Customization")] + public Customization Customization { get; set; } + [JsonPropertyName("Health")] + public Health Health { get; set; } + [JsonPropertyName("Inventory")] + public Inventory Inventory { get; set; } + [JsonPropertyName("Skills")] + public Skills Skills { get; set; } + [JsonPropertyName("Stats")] + public Stats Stats { get; set; } + [JsonPropertyName("Encyclopedia")] + public Dictionary Encyclopedia { get; set; } + [JsonPropertyName("TaskConditionCounters")] + public Dictionary TaskConditionCounters { get; set; } + [JsonPropertyName("InsuredItems")] + public List InsuredItems { get; set; } + [JsonPropertyName("Hideout")] + public Hideout Hideout { get; set; } + [JsonPropertyName("Quests")] + public List Quests { get; set; } + [JsonPropertyName("TradersInfo")] + public Dictionary TradersInfo { get; set; } + [JsonPropertyName("UnlockedInfo")] + public UnlockedInfo UnlockedInfo { get; set; } + [JsonPropertyName("RagfairInfo")] + public RagfairInfo RagfairInfo { get; set; } + /** Achievement id and timestamp */ + [JsonPropertyName("Achievements")] + public Dictionary Achievements { get; set; } + [JsonPropertyName("RepeatableQuests")] + public List RepeatableQuests { get; set; } + [JsonPropertyName("Bonuses")] + public List Bonuses { get; set; } + [JsonPropertyName("Notes")] + public Notes Notes { get; set; } + [JsonPropertyName("CarExtractCounts")] + public Dictionary CarExtractCounts { get; set; } + [JsonPropertyName("CoopExtractCounts")] + public Dictionary CoopExtractCounts { get; set; } + [JsonPropertyName("SurvivorClass")] + public SurvivorClass SurvivorClass { get; set; } + [JsonPropertyName("WishList")] + public Dictionary WishList { get; set; } + [JsonPropertyName("moneyTransferLimitData")] + public MoneyTransferLimits MoneyTransferLimitData { get; set; } + /** SPT specific property used during bot generation in raid */ + [JsonPropertyName("sptIsPmc")] + public bool? IsPmc { get; set; } } +public class MoneyTransferLimits +{ + // Resets every 24 hours in live + /** TODO: Implement */ + [JsonPropertyName("nextResetTime")] + public double NextResetTime { get; set; } + [JsonPropertyName("remainingLimit")] + public double RemainingLimit { get; set; } + [JsonPropertyName("totalLimit")] + public double TotalLimit { get; set; } + [JsonPropertyName("resetInterval")] + public double ResetInterval { get; set; } +} + +public class TaskConditionCounter +{ + [JsonPropertyName("id")] + public string Id { get; set; } + [JsonPropertyName("type")] + public string Type { get; set; } + [JsonPropertyName("value")] + public double Value { get; set; } + /** Quest id */ + [JsonPropertyName("sourceId")] + public string SourceId { get; set; } +} + +public class UnlockedInfo +{ + [JsonPropertyName("unlockedProductionRecipe")] + public List UnlockedProductionRecipe { get; set; } +} public class Info { @@ -510,7 +604,7 @@ public enum SurvivorClass { SURVIVOR = 4, } -public class QuestStatus +public class Quests { [JsonPropertyName("qid")] public string QId { get; set; } diff --git a/Core/Models/Eft/Common/Tables/Item.cs b/Core/Models/Eft/Common/Tables/Item.cs new file mode 100644 index 00000000..5bf3ff62 --- /dev/null +++ b/Core/Models/Eft/Common/Tables/Item.cs @@ -0,0 +1,245 @@ +using System.Text.Json.Serialization; + +namespace Core.Models.Eft.Common.Tables; + + +public class Item +{ + [JsonPropertyName("_id")] + public string Id { get; set; } + [JsonPropertyName("_tpl")] + public string Template { get; set; } + public string? ParentId { get; set; } + public string? SlotId { get; set; } + public object? Location { get; set; } // TODO: Can be IItemLocation or number + public Upd? Update { get; set; } +} + +public class ItemLocation +{ + public float X { get; set; } + public float Y { get; set; } + public object R { get; set; } // TODO: Can be string or number + public bool? IsSearched { get; set; } + /** SPT property? */ + public object? Rotation { get; set; } // TODO: Can be string or boolean +} + +public class Upd +{ + public UpdBuff? Buff { get; set; } + public int? OriginalStackObjectsCount { get; set; } + public UpdTogglable? Togglable { get; set; } + public UpdMap? Map { get; set; } + public UpdTag? Tag { get; set; } + /** SPT specific property, not made by BSG */ + [JsonPropertyName("sptPresetId")] + public string? SptPresetId { get; set; } + public UpdFaceShield? FaceShield { get; set; } + public int? StackObjectsCount { get; set; } + public bool? UnlimitedCount { get; set; } + public UpdRepairable? Repairable { get; set; } + public UpdRecodableComponent? RecodableComponent { get; set; } + public UpdFireMode? FireMode { get; set; } + public bool? SpawnedInSession { get; set; } + public UpdLight? Light { get; set; } + public UpdKey? Key { get; set; } + public UpdResource? Resource { get; set; } + public UpdSight? Sight { get; set; } + public UpdMedKit? MedKit { get; set; } + public UpdFoodDrink? FoodDrink { get; set; } + public UpdDogtag? Dogtag { get; set; } + public int? BuyRestrictionMax { get; set; } + public int? BuyRestrictionCurrent { get; set; } + public UpdFoldable? Foldable { get; set; } + public UpdSideEffect? SideEffect { get; set; } + public UpdRepairKit? RepairKit { get; set; } + public UpdCultistAmulet? CultistAmulet { get; set; } + public PinLockState? PinLockState { get; set; } +} + +public enum PinLockState { + Free, + Locked, + Pinned +} + +public class UpdBuff +{ + [JsonPropertyName("Rarity")] + public string Rarity { get; set; } + + [JsonPropertyName("BuffType")] + public string BuffType { get; set; } + + [JsonPropertyName("Value")] + public int Value { get; set; } + + [JsonPropertyName("ThresholdDurability")] + public int? ThresholdDurability { get; set; } +} + +public class UpdTogglable +{ + [JsonPropertyName("On")] + public bool On { get; set; } +} + +public class UpdMap +{ + [JsonPropertyName("Markers")] + public List Markers { get; set; } +} + +public class MapMarker +{ + [JsonPropertyName("X")] + public int X { get; set; } + + [JsonPropertyName("Y")] + public int Y { get; set; } +} + +public class UpdTag +{ + [JsonPropertyName("Color")] + public int Color { get; set; } + + [JsonPropertyName("Name")] + public string Name { get; set; } +} + +public class UpdFaceShield +{ + [JsonPropertyName("Hits")] + public int Hits { get; set; } +} + +public class UpdRepairable +{ + [JsonPropertyName("Durability")] + public int Durability { get; set; } + + [JsonPropertyName("MaxDurability")] + public int MaxDurability { get; set; } +} + +public class UpdRecodableComponent +{ + [JsonPropertyName("IsEncoded")] + public bool IsEncoded { get; set; } +} + +public class UpdMedKit +{ + [JsonPropertyName("HpResource")] + public int HpResource { get; set; } +} + +public class UpdSight +{ + [JsonPropertyName("ScopesCurrentCalibPointIndexes")] + public List ScopesCurrentCalibPointIndexes { get; set; } + + [JsonPropertyName("ScopesSelectedModes")] + public List ScopesSelectedModes { get; set; } + + [JsonPropertyName("SelectedScope")] + public int SelectedScope { get; set; } +} + +public class UpdFoldable +{ + [JsonPropertyName("Folded")] + public bool Folded { get; set; } +} + +public class UpdFireMode +{ + [JsonPropertyName("FireMode")] + public string FireMode { get; set; } +} + +public class UpdFoodDrink +{ + [JsonPropertyName("HpPercent")] + public double HpPercent { get; set; } +} + +public class UpdKey +{ + [JsonPropertyName("NumberOfUsages")] + public double NumberOfUsages { get; set; } +} + +public class UpdResource +{ + [JsonPropertyName("Value")] + public double Value { get; set; } + + [JsonPropertyName("UnitsConsumed")] + public double UnitsConsumed { get; set; } +} + +public class UpdLight +{ + [JsonPropertyName("IsActive")] + public bool IsActive { get; set; } + + [JsonPropertyName("SelectedMode")] + public int SelectedMode { get; set; } +} + +public class UpdDogtag +{ + [JsonPropertyName("AccountId")] + public string AccountId { get; set; } + + [JsonPropertyName("ProfileId")] + public string ProfileId { get; set; } + + [JsonPropertyName("Nickname")] + public string Nickname { get; set; } + + [JsonPropertyName("Side")] + public string Side { get; set; } + + [JsonPropertyName("Level")] + public double Level { get; set; } + + [JsonPropertyName("Time")] + public string Time { get; set; } + + [JsonPropertyName("Status")] + public string Status { get; set; } + + [JsonPropertyName("KillerAccountId")] + public string KillerAccountId { get; set; } + + [JsonPropertyName("KillerProfileId")] + public string KillerProfileId { get; set; } + + [JsonPropertyName("KillerName")] + public string KillerName { get; set; } + + [JsonPropertyName("WeaponName")] + public string WeaponName { get; set; } +} + +public class UpdSideEffect +{ + [JsonPropertyName("Value")] + public double Value { get; set; } +} + +public class UpdRepairKit +{ + [JsonPropertyName("Resource")] + public double Resource { get; set; } +} + +public class UpdCultistAmulet +{ + [JsonPropertyName("NumberOfUsages")] + public double NumberOfUsages { get; set; } +} \ No newline at end of file diff --git a/Core/Models/Eft/Common/Tables/LocationsBase.cs b/Core/Models/Eft/Common/Tables/LocationsBase.cs new file mode 100644 index 00000000..9ad47b78 --- /dev/null +++ b/Core/Models/Eft/Common/Tables/LocationsBase.cs @@ -0,0 +1,26 @@ +using System.Text.Json.Serialization; + +namespace Core.Models.Eft.Common.Tables; + +public class LocationsBase +{ + [JsonPropertyName("locations")] + public Locations Locations { get; set; } + + [JsonPropertyName("paths")] + public List Paths { get; set; } +} + +public class Locations +{ + // Add properties as necessary +} + +public class Path +{ + [JsonPropertyName("Source")] + public string Source { get; set; } + + [JsonPropertyName("Destination")] + public string Destination { get; set; } +} \ No newline at end of file diff --git a/Core/Models/Eft/Common/Tables/Quest.cs b/Core/Models/Eft/Common/Tables/Quest.cs new file mode 100644 index 00000000..bab31d5f --- /dev/null +++ b/Core/Models/Eft/Common/Tables/Quest.cs @@ -0,0 +1,442 @@ +using System.Text.Json.Serialization; +using Core.Models.Enums; + +namespace Core.Models.Eft.Common.Tables; + +public class Quest +{ + /// + /// SPT addition - human readable quest name + /// + [JsonPropertyName("QuestName")] + public string? QuestName { get; set; } + + [JsonPropertyName("_id")] + public string Id { get; set; } + + [JsonPropertyName("canShowNotificationsInGame")] + public bool CanShowNotificationsInGame { get; set; } + + [JsonPropertyName("conditions")] + public QuestConditionTypes Conditions { get; set; } + + [JsonPropertyName("description")] + public string Description { get; set; } + + [JsonPropertyName("failMessageText")] + public string FailMessageText { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("note")] + public string Note { get; set; } + + [JsonPropertyName("traderId")] + public string TraderId { get; set; } + + [JsonPropertyName("location")] + public string Location { get; set; } + + [JsonPropertyName("image")] + public string Image { get; set; } + + [JsonPropertyName("type")] + public QuestTypeEnum Type { get; set; } + + [JsonPropertyName("isKey")] + public bool IsKey { get; set; } + + [JsonPropertyName("restartable")] + public bool Restartable { get; set; } + + [JsonPropertyName("instantComplete")] + public bool InstantComplete { get; set; } + + [JsonPropertyName("secretQuest")] + public bool SecretQuest { get; set; } + + [JsonPropertyName("startedMessageText")] + public string StartedMessageText { get; set; } + + [JsonPropertyName("successMessageText")] + public string SuccessMessageText { get; set; } + + [JsonPropertyName("acceptPlayerMessage")] + public string? AcceptPlayerMessage { get; set; } + + [JsonPropertyName("declinePlayerMessage")] + public string DeclinePlayerMessage { get; set; } + + [JsonPropertyName("completePlayerMessage")] + public string? CompletePlayerMessage { get; set; } + + [JsonPropertyName("templateId")] + public string? TemplateId { get; set; } + + [JsonPropertyName("rewards")] + public QuestRewards Rewards { get; set; } + + /// + /// Becomes 'AppearStatus' inside client + /// + [JsonPropertyName("status")] + public object? Status { get; set; } // TODO: string | number + + [JsonPropertyName("KeyQuest")] + public bool? KeyQuest { get; set; } + + [JsonPropertyName("changeQuestMessageText")] + public string ChangeQuestMessageText { get; set; } + + /// + /// "Pmc" or "Scav" + /// + [JsonPropertyName("side")] + public string Side { get; set; } + + [JsonPropertyName("acceptanceAndFinishingSource")] + public string AcceptanceAndFinishingSource { get; set; } + + [JsonPropertyName("progressSource")] + public string ProgressSource { get; set; } + + [JsonPropertyName("rankingModes")] + public List RankingModes { get; set; } + + [JsonPropertyName("gameModes")] + public List GameModes { get; set; } + + [JsonPropertyName("arenaLocations")] + public List ArenaLocations { get; set; } + + /// + /// Status of quest to player + /// + [JsonPropertyName("sptStatus")] + public QuestStatus? SptStatus { get; set; } +} + +public class QuestConditionTypes +{ + [JsonPropertyName("Started")] + public List? Started { get; set; } + + [JsonPropertyName("AvailableForFinish")] + public List AvailableForFinish { get; set; } + + [JsonPropertyName("AvailableForStart")] + public List AvailableForStart { get; set; } + + [JsonPropertyName("Success")] + public List? Success { get; set; } + + [JsonPropertyName("Fail")] + public List Fail { get; set; } +} + +public class QuestCondition +{ + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("index")] + public int? Index { get; set; } + + [JsonPropertyName("compareMethod")] + public string? CompareMethod { get; set; } + + [JsonPropertyName("dynamicLocale")] + public bool DynamicLocale { get; set; } + + [JsonPropertyName("visibilityConditions")] + public List? VisibilityConditions { get; set; } + + [JsonPropertyName("globalQuestCounterId")] + public string? GlobalQuestCounterId { get; set; } + + [JsonPropertyName("parentId")] + public string? ParentId { get; set; } + + [JsonPropertyName("target")] + public object? Target { get; set; } // TODO: string[] | string + + [JsonPropertyName("value")] + public object? Value { get; set; } // TODO: string | number + + [JsonPropertyName("type")] + public object? Type { get; set; } // TODO: boolean | string + + [JsonPropertyName("status")] + public List? Status { get; set; } + + [JsonPropertyName("availableAfter")] + public int? AvailableAfter { get; set; } + + [JsonPropertyName("dispersion")] + public double? Dispersion { get; set; } + + [JsonPropertyName("onlyFoundInRaid")] + public bool? OnlyFoundInRaid { get; set; } + + [JsonPropertyName("oneSessionOnly")] + public bool? OneSessionOnly { get; set; } + + [JsonPropertyName("isResetOnConditionFailed")] + public bool? IsResetOnConditionFailed { get; set; } + + [JsonPropertyName("isNecessary")] + public bool? IsNecessary { get; set; } + + [JsonPropertyName("doNotResetIfCounterCompleted")] + public bool? DoNotResetIfCounterCompleted { get; set; } + + [JsonPropertyName("dogtagLevel")] + public object? DogtagLevel { get; set; } // TODO: number | string + + [JsonPropertyName("traderId")] + public string? TraderId { get; set; } + + [JsonPropertyName("maxDurability")] + public object? MaxDurability { get; set; } // TODO: number | string + + [JsonPropertyName("minDurability")] + public object? MinDurability { get; set; } // TODO: number | string + + [JsonPropertyName("counter")] + public QuestConditionCounter? Counter { get; set; } + + [JsonPropertyName("plantTime")] + public int? PlantTime { get; set; } + + [JsonPropertyName("zoneId")] + public string? ZoneId { get; set; } + + [JsonPropertyName("countInRaid")] + public bool? CountInRaid { get; set; } + + [JsonPropertyName("completeInSeconds")] + public int? CompleteInSeconds { get; set; } + + [JsonPropertyName("isEncoded")] + public bool? IsEncoded { get; set; } + + [JsonPropertyName("conditionType")] + public string? ConditionType { get; set; } +} + +public class QuestConditionCounter +{ + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("conditions")] + public List Conditions { get; set; } +} + +public class QuestConditionCounterCondition +{ + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("dynamicLocale")] + public bool? DynamicLocale { get; set; } + + [JsonPropertyName("target")] + public object? Target { get; set; } // TODO: string[] | string + + [JsonPropertyName("completeInSeconds")] + public int? CompleteInSeconds { get; set; } + + [JsonPropertyName("energy")] + public ValueCompare? Energy { get; set; } + + [JsonPropertyName("exitName")] + public string? ExitName { get; set; } + + [JsonPropertyName("hydration")] + public ValueCompare? Hydration { get; set; } + + [JsonPropertyName("time")] + public ValueCompare? Time { get; set; } + + [JsonPropertyName("compareMethod")] + public string? CompareMethod { get; set; } + + [JsonPropertyName("value")] + public object? Value { get; set; } // TODO: number | string + + [JsonPropertyName("weapon")] + public List? Weapon { get; set; } + + [JsonPropertyName("distance")] + public CounterConditionDistance? Distance { get; set; } + + [JsonPropertyName("equipmentInclusive")] + public List>? EquipmentInclusive { get; set; } + + [JsonPropertyName("weaponModsInclusive")] + public List>? WeaponModsInclusive { get; set; } + + [JsonPropertyName("weaponModsExclusive")] + public List>? WeaponModsExclusive { get; set; } + + [JsonPropertyName("enemyEquipmentInclusive")] + public List>? EnemyEquipmentInclusive { get; set; } + + [JsonPropertyName("enemyEquipmentExclusive")] + public List>? EnemyEquipmentExclusive { get; set; } + + [JsonPropertyName("weaponCaliber")] + public List? WeaponCaliber { get; set; } + + [JsonPropertyName("savageRole")] + public List? SavageRole { get; set; } + + [JsonPropertyName("status")] + public List? Status { get; set; } + + [JsonPropertyName("bodyPart")] + public List? BodyPart { get; set; } + + [JsonPropertyName("daytime")] + public DaytimeCounter? Daytime { get; set; } + + [JsonPropertyName("conditionType")] + public string? ConditionType { get; set; } + + [JsonPropertyName("enemyHealthEffects")] + public List? EnemyHealthEffects { get; set; } + + [JsonPropertyName("resetOnSessionEnd")] + public bool? ResetOnSessionEnd { get; set; } +} + +public class EnemyHealthEffect +{ + [JsonPropertyName("bodyParts")] + public List BodyParts { get; set; } + + [JsonPropertyName("effects")] + public List Effects { get; set; } +} + +public class ValueCompare +{ + [JsonPropertyName("compareMethod")] + public string CompareMethod { get; set; } + + [JsonPropertyName("value")] + public int Value { get; set; } +} + +public class CounterConditionDistance +{ + [JsonPropertyName("value")] + public int Value { get; set; } + + [JsonPropertyName("compareMethod")] + public string CompareMethod { get; set; } +} + +public class DaytimeCounter +{ + [JsonPropertyName("from")] + public int From { get; set; } + + [JsonPropertyName("to")] + public int To { get; set; } +} + +public class VisibilityCondition +{ + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("target")] + public string Target { get; set; } + + [JsonPropertyName("value")] + public int? Value { get; set; } + + [JsonPropertyName("dynamicLocale")] + public bool? DynamicLocale { get; set; } + + [JsonPropertyName("oneSessionOnly")] + public bool? OneSessionOnly { get; set; } + + [JsonPropertyName("conditionType")] + public string ConditionType { get; set; } +} + +public class QuestRewards +{ + [JsonPropertyName("AvailableForStart")] + public List AvailableForStart { get; set; } + + [JsonPropertyName("AvailableForFinish")] + public List AvailableForFinish { get; set; } + + [JsonPropertyName("Started")] + public List Started { get; set; } + + [JsonPropertyName("Success")] + public List Success { get; set; } + + [JsonPropertyName("Fail")] + public List Fail { get; set; } + + [JsonPropertyName("FailRestartable")] + public List FailRestartable { get; set; } + + [JsonPropertyName("Expired")] + public List Expired { get; set; } +} + +public class QuestReward +{ + [JsonPropertyName("value")] + public object Value { get; set; } // TODO: Can be either string or number + + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("type")] + public QuestRewardType Type { get; set; } + + [JsonPropertyName("index")] + public int Index { get; set; } + + [JsonPropertyName("target")] + public string Target { get; set; } + + [JsonPropertyName("items")] + public List Items { get; set; } + + [JsonPropertyName("loyaltyLevel")] + public int? LoyaltyLevel { get; set; } + + /** Hideout area id */ + [JsonPropertyName("traderId")] + public string TraderId { get; set; } + + [JsonPropertyName("isEncoded")] + public bool? IsEncoded { get; set; } + + [JsonPropertyName("unknown")] + public bool? Unknown { get; set; } + + [JsonPropertyName("findInRaid")] + public bool? FindInRaid { get; set; } + + [JsonPropertyName("gameMode")] + public List GameMode { get; set; } + + /** Game editions whitelisted to get reward */ + [JsonPropertyName("availableInGameEditions")] + public List AvailableInGameEditions { get; set; } + + /** Game editions blacklisted from getting reward */ + [JsonPropertyName("notAvailableInGameEditions")] + public List NotAvailableInGameEditions { get; set; } +} \ No newline at end of file diff --git a/Core/Models/Eft/Common/Tables/RepeatableQuests.cs b/Core/Models/Eft/Common/Tables/RepeatableQuests.cs new file mode 100644 index 00000000..ed1c5ae9 --- /dev/null +++ b/Core/Models/Eft/Common/Tables/RepeatableQuests.cs @@ -0,0 +1,230 @@ +using System.Text.Json.Serialization; + +namespace Core.Models.Eft.Common.Tables; + +public class RepeatableQuest : Quest +{ + [JsonPropertyName("changeCost")] + public List ChangeCost { get; set; } + + [JsonPropertyName("changeStandingCost")] + public int ChangeStandingCost { get; set; } + + [JsonPropertyName("sptRepatableGroupName")] + public string SptRepatableGroupName { get; set; } + + [JsonPropertyName("acceptanceAndFinishingSource")] + public string AcceptanceAndFinishingSource { get; set; } + + [JsonPropertyName("progressSource")] + public string ProgressSource { get; set; } + + [JsonPropertyName("rankingModes")] + public List RankingModes { get; set; } + + [JsonPropertyName("gameModes")] + public List GameModes { get; set; } + + [JsonPropertyName("arenaLocations")] + public List ArenaLocations { get; set; } + + [JsonPropertyName("questStatus")] + public RepeatableQuestStatus QuestStatus { get; set; } +} + +public class RepeatableQuestDatabase +{ + [JsonPropertyName("templates")] + public RepeatableTemplates Templates { get; set; } + + [JsonPropertyName("rewards")] + public RewardOptions Rewards { get; set; } + + [JsonPropertyName("data")] + public Options Data { get; set; } + + [JsonPropertyName("samples")] + public List Samples { get; set; } +} + +public class RepeatableQuestStatus +{ + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("uid")] + public string Uid { get; set; } + + [JsonPropertyName("qid")] + public string Qid { get; set; } + + [JsonPropertyName("startTime")] + public long StartTime { get; set; } + + [JsonPropertyName("status")] + public int Status { get; set; } + + [JsonPropertyName("statusTimers")] + public object StatusTimers { get; set; } // Use object for any type +} + +public class RepeatableTemplates +{ + [JsonPropertyName("Elimination")] + public Quest Elimination { get; set; } + + [JsonPropertyName("Completion")] + public Quest Completion { get; set; } + + [JsonPropertyName("Exploration")] + public Quest Exploration { get; set; } +} + +public class PmcDataRepeatableQuest +{ + [JsonPropertyName("id")] + public string? Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("unavailableTime")] + public string? UnavailableTime { get; set; } + + [JsonPropertyName("activeQuests")] + public List ActiveQuests { get; set; } + + [JsonPropertyName("inactiveQuests")] + public List InactiveQuests { get; set; } + + [JsonPropertyName("endTime")] + public long EndTime { get; set; } + + [JsonPropertyName("changeRequirement")] + public Dictionary ChangeRequirement { get; set; } + + [JsonPropertyName("freeChanges")] + public int FreeChanges { get; set; } + + [JsonPropertyName("freeChangesAvailable")] + public int FreeChangesAvailable { get; set; } +} + +public class ChangeRequirement +{ + [JsonPropertyName("changeCost")] + public List ChangeCost { get; set; } + + [JsonPropertyName("changeStandingCost")] + public int ChangeStandingCost { get; set; } +} + +public class ChangeCost +{ + [JsonPropertyName("templateId")] + public string TemplateId { get; set; } + + [JsonPropertyName("count")] + public int Count { get; set; } +} + +// Config Options + +public class RewardOptions +{ + [JsonPropertyName("itemsBlacklist")] + public List ItemsBlacklist { get; set; } +} + +public class Options +{ + [JsonPropertyName("Completion")] + public CompletionFilter Completion { get; set; } +} + +public class CompletionFilter +{ + [JsonPropertyName("itemsBlacklist")] + public List ItemsBlacklist { get; set; } + + [JsonPropertyName("itemsWhitelist")] + public List ItemsWhitelist { get; set; } +} + +public class ItemsBlacklist +{ + [JsonPropertyName("minPlayerLevel")] + public int MinPlayerLevel { get; set; } + + [JsonPropertyName("itemIds")] + public List ItemIds { get; set; } +} + +public class ItemsWhitelist +{ + [JsonPropertyName("minPlayerLevel")] + public int MinPlayerLevel { get; set; } + + [JsonPropertyName("itemIds")] + public List ItemIds { get; set; } +} + +public class SampleQuests +{ + [JsonPropertyName("_id")] + public string Id { get; set; } + + [JsonPropertyName("traderId")] + public string TraderId { get; set; } + + [JsonPropertyName("location")] + public string Location { get; set; } + + [JsonPropertyName("image")] + public string Image { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("isKey")] + public bool IsKey { get; set; } + + [JsonPropertyName("restartable")] + public bool Restartable { get; set; } + + [JsonPropertyName("instantComplete")] + public bool InstantComplete { get; set; } + + [JsonPropertyName("secretQuest")] + public bool SecretQuest { get; set; } + + [JsonPropertyName("canShowNotificationsInGame")] + public bool CanShowNotificationsInGame { get; set; } + + [JsonPropertyName("rewards")] + public QuestRewards Rewards { get; set; } + + [JsonPropertyName("conditions")] + public QuestConditionTypes Conditions { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("note")] + public string Note { get; set; } + + [JsonPropertyName("description")] + public string Description { get; set; } + + [JsonPropertyName("successMessageText")] + public string SuccessMessageText { get; set; } + + [JsonPropertyName("failMessageText")] + public string FailMessageText { get; set; } + + [JsonPropertyName("startedMessageText")] + public string StartedMessageText { get; set; } + + [JsonPropertyName("templateId")] + public string TemplateId { get; set; } +} \ No newline at end of file diff --git a/Core/Models/Eft/Common/XYZ.cs b/Core/Models/Eft/Common/XYZ.cs new file mode 100644 index 00000000..205b7488 --- /dev/null +++ b/Core/Models/Eft/Common/XYZ.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace Core.Models.Eft.Common; + +public class XYZ +{ + [JsonPropertyName("x")] + public double X { get; set; } + + [JsonPropertyName("y")] + public double Y { get; set; } + + [JsonPropertyName("z")] + public double Z { get; set; } +} \ No newline at end of file diff --git a/Core/Models/Eft/Ragfair/RagfairOffer.cs b/Core/Models/Eft/Ragfair/RagfairOffer.cs new file mode 100644 index 00000000..3e120aa3 --- /dev/null +++ b/Core/Models/Eft/Ragfair/RagfairOffer.cs @@ -0,0 +1,121 @@ +using System.Text.Json.Serialization; +using Core.Models.Eft.Common.Tables; +using Core.Models.Enums; + +namespace Core.Models.Eft.Ragfair; + +public class RagfairOffer +{ + [JsonPropertyName("sellResult")] + public List? SellResults { get; set; } + + [JsonPropertyName("_id")] + public string Id { get; set; } + + [JsonPropertyName("items")] + public List Items { get; set; } + + [JsonPropertyName("requirements")] + public List Requirements { get; set; } + + [JsonPropertyName("root")] + public string Root { get; set; } + + [JsonPropertyName("intId")] + public int InternalId { get; set; } + + /** Handbook price */ + [JsonPropertyName("itemsCost")] + public decimal ItemsCost { get; set; } + + /** Rouble price per item */ + [JsonPropertyName("requirementsCost")] + public decimal RequirementsCost { get; set; } + + [JsonPropertyName("startTime")] + public long StartTime { get; set; } + + [JsonPropertyName("endTime")] + public long EndTime { get; set; } + + /** True when offer is sold as pack */ + [JsonPropertyName("sellInOnePiece")] + public bool SellInOnePiece { get; set; } + + /** Rouble price - same as requirementsCost */ + [JsonPropertyName("summaryCost")] + public decimal SummaryCost { get; set; } + + [JsonPropertyName("user")] + public RagfairOfferUser User { get; set; } + + /** Trader only */ + [JsonPropertyName("unlimitedCount")] + public bool? UnlimitedCount { get; set; } + + [JsonPropertyName("loyaltyLevel")] + public int LoyaltyLevel { get; set; } + + [JsonPropertyName("buyRestrictionMax")] + public int? BuyRestrictionMax { get; set; } + + [JsonPropertyName("buyRestrictionCurrent")] + public int? BuyRestrictionCurrent { get; set; } + + [JsonPropertyName("locked")] + public bool? Locked { get; set; } +} + +public class OfferRequirement +{ + [JsonPropertyName("_tpl")] + public string Template { get; set; } + + [JsonPropertyName("count")] + public int Count { get; set; } + + [JsonPropertyName("onlyFunctional")] + public bool OnlyFunctional { get; set; } + + [JsonPropertyName("level")] + public int? Level { get; set; } + + [JsonPropertyName("side")] + public DogtagExchangeSide? Side { get; set; } +} + +public class RagfairOfferUser +{ + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("nickname")] + public string? Nickname { get; set; } + + [JsonPropertyName("rating")] + public decimal? Rating { get; set; } + + [JsonPropertyName("memberType")] + public MemberCategory MemberType { get; set; } + + [JsonPropertyName("selectedMemberCategory")] + public MemberCategory? SelectedMemberCategory { get; set; } + + [JsonPropertyName("avatar")] + public string? Avatar { get; set; } + + [JsonPropertyName("isRatingGrowing")] + public bool? IsRatingGrowing { get; set; } + + [JsonPropertyName("aid")] + public int? Aid { get; set; } +} + +public class SellResult +{ + [JsonPropertyName("sellTime")] + public long SellTime { get; set; } + + [JsonPropertyName("amount")] + public decimal Amount { get; set; } +} \ No newline at end of file diff --git a/Core/Models/Enums/BonusSkillType.cs b/Core/Models/Enums/BonusSkillType.cs new file mode 100644 index 00000000..3f1e1783 --- /dev/null +++ b/Core/Models/Enums/BonusSkillType.cs @@ -0,0 +1,10 @@ +namespace Core.Models.Enums; + +public enum BonusSkillType +{ + Physical, + Combat, + Special, + Practical, + Mental +} \ No newline at end of file diff --git a/Core/Models/Enums/BonusType.cs b/Core/Models/Enums/BonusType.cs new file mode 100644 index 00000000..74f06ff6 --- /dev/null +++ b/Core/Models/Enums/BonusType.cs @@ -0,0 +1,36 @@ +namespace Core.Models.Enums; + +public enum BonusType +{ + EnergyRegeneration, + HydrationRegeneration, + HealthRegeneration, + ExperienceRate, + QuestMoneyReward, + ScavCooldownTimer, + UnlockItemCraft, + UnlockItemPassiveCreation, + UnlockRandomItemCreation, + SkillLevelingBoost, + DebuffEndDelay, + RagfairCommission, + InsuranceReturnTime, + UnlockWeaponModification, + UnlockScavPlay, + UnlockAddOffer, + UnlockItemCharge, + ReceiveItemBonus, + UnlockUniqueId, + IncreaseCanisterSlots, + AdditionalSlots, + FuelConsumption, + RepairWeaponBonus, + RepairArmorBonus, + UnlockWeaponRepair, + UnlockArmorRepair, + StashSize, + MaximumEnergyReserve, + TextBonus, + SkillGroupLevelingBoost, + StashRows +} \ No newline at end of file diff --git a/Core/Models/Enums/DogtagExchangeSide.cs b/Core/Models/Enums/DogtagExchangeSide.cs new file mode 100644 index 00000000..a4a5b97e --- /dev/null +++ b/Core/Models/Enums/DogtagExchangeSide.cs @@ -0,0 +1,8 @@ +namespace Core.Models.Enums; + +public enum DogtagExchangeSide +{ + Usec, + Bear, + Any +} \ No newline at end of file diff --git a/Core/Models/Enums/ELocationName.cs b/Core/Models/Enums/ELocationName.cs new file mode 100644 index 00000000..5dcd0e53 --- /dev/null +++ b/Core/Models/Enums/ELocationName.cs @@ -0,0 +1,17 @@ +namespace Core.Models.Enums; + +public enum ELocationName +{ + factory4_day, + factory4_night, + bigmap, + Woods, + Shoreline, + Sandbox, + Interchange, + Lighthouse, + laboratory, + RezervBase, + TarkovStreets, + any +} \ No newline at end of file diff --git a/Core/Models/Enums/HideoutAreas.cs b/Core/Models/Enums/HideoutAreas.cs new file mode 100644 index 00000000..c1106b11 --- /dev/null +++ b/Core/Models/Enums/HideoutAreas.cs @@ -0,0 +1,34 @@ +namespace Core.Models.Enums; + +public enum HideoutAreas +{ + NOTSET = -1, + VENTS = 0, + SECURITY = 1, + LAVATORY = 2, + STASH = 3, + GENERATOR = 4, + HEATING = 5, + WATER_COLLECTOR = 6, + MEDSTATION = 7, + NUTRITION_UNIT = 8, + REST_SPACE = 9, + WORKBENCH = 10, + INTEL_CENTER = 11, + SHOOTING_RANGE = 12, + LIBRARY = 13, + SCAV_CASE = 14, + ILLUMINATION = 15, + PLACE_OF_FAME = 16, + AIR_FILTERING = 17, + SOLAR_POWER = 18, + BOOZE_GENERATOR = 19, + BITCOIN_FARM = 20, + CHRISTMAS_TREE = 21, + EMERGENCY_WALL = 22, + GYM = 23, + WEAPON_STAND = 24, + WEAPON_STAND_SECONDARY = 25, + EQUIPMENT_PRESETS_STAND = 26, + CIRCLE_OF_CULTISTS = 27, +} \ No newline at end of file diff --git a/Core/Models/Enums/MemberCategory.cs b/Core/Models/Enums/MemberCategory.cs new file mode 100644 index 00000000..4b97e615 --- /dev/null +++ b/Core/Models/Enums/MemberCategory.cs @@ -0,0 +1,17 @@ +namespace Core.Models.Enums; + +public enum MemberCategory +{ + DEFAULT = 0, + DEVELOPER = 1, + UNIQUE_ID = 2, + TRADER = 4, + GROUP = 8, + SYSTEM = 16, + CHAT_MODERATOR = 32, + CHAT_MODERATOR_WITH_PERMANENT_BAN = 64, + UNIT_TEST = 128, + SHERPA = 256, + EMISSARY = 512, + UNHEARD = 1024, +} \ No newline at end of file diff --git a/Core/Models/Enums/QuestRewardType.cs b/Core/Models/Enums/QuestRewardType.cs new file mode 100644 index 00000000..4907a972 --- /dev/null +++ b/Core/Models/Enums/QuestRewardType.cs @@ -0,0 +1,17 @@ +namespace Core.Models.Enums; + +public enum QuestRewardType +{ + Skill, + Experience, + TraderStanding, + TraderUnlock, + Item, + AssortmentUnlock, + ProductionScheme, + TraderStandingReset, + TraderStandingRestore, + StashRows, + Achievement, + Pockets +} \ No newline at end of file diff --git a/Core/Models/Enums/QuestStatus.cs b/Core/Models/Enums/QuestStatus.cs new file mode 100644 index 00000000..08ed02e1 --- /dev/null +++ b/Core/Models/Enums/QuestStatus.cs @@ -0,0 +1,15 @@ +namespace Core.Models.Enums; + +public enum QuestStatus +{ + Locked = 0, + AvailableForStart = 1, + Started = 2, + AvailableForFinish = 3, + Success = 4, + Fail = 5, + FailRestartable = 6, + MarkedAsFailed = 7, + Expired = 8, + AvailableAfter = 9, +} \ No newline at end of file diff --git a/Core/Models/Enums/QuestTypeEnum.cs b/Core/Models/Enums/QuestTypeEnum.cs new file mode 100644 index 00000000..9aed8428 --- /dev/null +++ b/Core/Models/Enums/QuestTypeEnum.cs @@ -0,0 +1,18 @@ +namespace Core.Models.Enums; + +public enum QuestTypeEnum +{ + PickUp, + Elimination, + Discover, + Completion, + Exploration, + Levelling, + Experience, + Standing, + Loyalty, + Merchant, + Skill, + Multi, + WeaponAssembly +} \ No newline at end of file diff --git a/Core/Models/Spt/Quests/GetRepeatableByIdResult.cs b/Core/Models/Spt/Quests/GetRepeatableByIdResult.cs index 7fa2e8e1..43f85d4f 100644 --- a/Core/Models/Spt/Quests/GetRepeatableByIdResult.cs +++ b/Core/Models/Spt/Quests/GetRepeatableByIdResult.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using Core.Models.Eft.Common.Tables; namespace Core.Models.Spt.Quests; diff --git a/Core/Models/Spt/Repeatable/QuestTypePool.cs b/Core/Models/Spt/Repeatable/QuestTypePool.cs index 32b8e122..eadf8713 100644 --- a/Core/Models/Spt/Repeatable/QuestTypePool.cs +++ b/Core/Models/Spt/Repeatable/QuestTypePool.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Text.Json.Serialization; +using Core.Models.Enums; namespace Core.Models.Spt.Repeatable; diff --git a/Core/Models/Spt/Server/ExhaustableArray.cs b/Core/Models/Spt/Server/ExhaustableArray.cs index 2ed7bcb9..7f539d8a 100644 --- a/Core/Models/Spt/Server/ExhaustableArray.cs +++ b/Core/Models/Spt/Server/ExhaustableArray.cs @@ -1,6 +1,6 @@ // using System.Collections.Generic; // -// namespace Types.Models.Spt.Server; +// namespace Core.Models.Spt.Server; // // public class ExhaustableArray // { diff --git a/Core/Models/Spt/Server/Locations.cs b/Core/Models/Spt/Server/Locations.cs index 0d0fc118..631b3a2f 100644 --- a/Core/Models/Spt/Server/Locations.cs +++ b/Core/Models/Spt/Server/Locations.cs @@ -1,4 +1,6 @@ using System.Text.Json.Serialization; +using Core.Models.Eft.Common; +using Core.Models.Eft.Common.Tables; namespace Core.Models.Spt.Server; diff --git a/Core/Models/Utils/ILogger.cs b/Core/Models/Utils/ILogger.cs index cd73d2f6..3554c800 100644 --- a/Core/Models/Utils/ILogger.cs +++ b/Core/Models/Utils/ILogger.cs @@ -1,6 +1,6 @@ -using Types.Models.Logging; +using Core.Models.Logging; -namespace Types.Models.Utils; +namespace Core.Models.Utils; public interface ILogger { diff --git a/Core/Servers/ConfigServer.cs b/Core/Servers/ConfigServer.cs index cd471290..50813186 100644 --- a/Core/Servers/ConfigServer.cs +++ b/Core/Servers/ConfigServer.cs @@ -1,6 +1,6 @@ -using Types.Annotations; +using Core.Annotations; -namespace Types.Servers; +namespace Core.Servers; [Injectable(InjectionType.Singleton)] public class ConfigServer diff --git a/Core/Servers/DatabaseServer.cs b/Core/Servers/DatabaseServer.cs index 7045e67d..ea6a69a4 100644 --- a/Core/Servers/DatabaseServer.cs +++ b/Core/Servers/DatabaseServer.cs @@ -1,4 +1,4 @@ -namespace Types.Servers; +namespace Core.Servers; public class DatabaseServer { diff --git a/Core/Servers/Http/IHttpListener.cs b/Core/Servers/Http/IHttpListener.cs index 4a74d910..5161850c 100644 --- a/Core/Servers/Http/IHttpListener.cs +++ b/Core/Servers/Http/IHttpListener.cs @@ -1,4 +1,4 @@ -namespace Types.Servers.Http; +namespace Core.Servers.Http; public interface IHttpListener { diff --git a/Core/Servers/HttpServer.cs b/Core/Servers/HttpServer.cs index d3135cb1..c4d9b749 100644 --- a/Core/Servers/HttpServer.cs +++ b/Core/Servers/HttpServer.cs @@ -1,13 +1,13 @@ using System.Net.WebSockets; +using Core.Context; +using Core.Models.Config; +using Core.Servers.Http; +using Core.Services; using Microsoft.Extensions.Primitives; -using Types.Annotations; -using Types.Context; -using Types.Models.Config; -using Types.Servers.Http; -using Types.Services; -using ILogger = Types.Models.Utils.ILogger; +using Core.Annotations; +using ILogger = Core.Models.Utils.ILogger; -namespace Types.Servers; +namespace Core.Servers; [Injectable(InjectionType.Singleton)] public class HttpServer diff --git a/Core/Servers/WebSocketServer.cs b/Core/Servers/WebSocketServer.cs index 42ce2f9e..5ec5648b 100644 --- a/Core/Servers/WebSocketServer.cs +++ b/Core/Servers/WebSocketServer.cs @@ -1,6 +1,6 @@ -using Types.Annotations; +using Core.Annotations; -namespace Types.Servers; +namespace Core.Servers; [Injectable(InjectionType.Singleton)] public class WebSocketServer diff --git a/Core/Services/I18nService.cs b/Core/Services/I18nService.cs index bc31e90a..e508af5a 100644 --- a/Core/Services/I18nService.cs +++ b/Core/Services/I18nService.cs @@ -1,4 +1,4 @@ -namespace Types.Services; +namespace Core.Services; public class I18nService { diff --git a/Core/Services/LocaleService.cs b/Core/Services/LocaleService.cs index c194da1c..ac343072 100644 --- a/Core/Services/LocaleService.cs +++ b/Core/Services/LocaleService.cs @@ -1,8 +1,8 @@ -using Types.Annotations; -using Types.Servers; -using ILogger = Types.Models.Utils.ILogger; +using Core.Annotations; +using Core.Servers; +using ILogger = Core.Models.Utils.ILogger; -namespace Types.Services; +namespace Core.Services; [Injectable(InjectionType.Singleton)] public class LocaleService diff --git a/Core/Services/LocalisationService.cs b/Core/Services/LocalisationService.cs index 6ae740f8..cbf8dfef 100644 --- a/Core/Services/LocalisationService.cs +++ b/Core/Services/LocalisationService.cs @@ -1,9 +1,9 @@ -using Types.Annotations; -using Types.Servers; -using Types.Utils; -using ILogger = Types.Models.Utils.ILogger; +using Core.Utils; +using Core.Annotations; +using Core.Servers; +using ILogger = Core.Models.Utils.ILogger; -namespace Types.Services; +namespace Core.Services; [Injectable(InjectionType.Singleton)] public class LocalisationService diff --git a/Core/Utils/HashUtil.cs b/Core/Utils/HashUtil.cs new file mode 100644 index 00000000..b1a3318c --- /dev/null +++ b/Core/Utils/HashUtil.cs @@ -0,0 +1,92 @@ +using System.Text; +using System.Text.RegularExpressions; +using System.Security.Cryptography; +using Core.Annotations; + +namespace Core.Utils; + +[Injectable(InjectionType.Singleton)] +public partial class HashUtil +{ + /// + /// Create a 24 character id using the sha256 algorithm + current timestamp + /// + /// 24 character hash + public static string Generate() + { + throw new NotImplementedException(); + } + + /// + /// is the passed in string a valid mongo id + /// + /// String to check + /// True when string is a valid mongo id + public static bool IsValidMongoId(string stringToCheck) + { + return MongoIdRegex().IsMatch(stringToCheck); + } + + public static string GenerateMd5ForData(string data) + { + return GenerateHashForData(HashingAlgorithm.MD5, data); + } + + public static string GenerateSha1ForData(string data) + { + return GenerateHashForData(HashingAlgorithm.SHA1, data); + } + + public static string GenerateCrc32ForData(string data) + { + // TODO: Could not find a ms way of doing this. + // May need a custom impl to avoid an external lib. - CJ + throw new NotImplementedException(); + } + + /// + /// Create a hash for the data parameter + /// + /// algorithm to use to hash + /// data to be hashed + /// hash value + /// thrown if the provided algorithm is not implemented> + public static string GenerateHashForData(HashingAlgorithm algorithm, string data) + { + switch (algorithm) + { + case HashingAlgorithm.MD5: + var md5HashData = MD5.HashData(Encoding.UTF8.GetBytes(data)); + return Convert.ToHexString(md5HashData).Replace("-", string.Empty); + + case HashingAlgorithm.SHA1: + var sha1HashData = SHA1.HashData(Encoding.UTF8.GetBytes(data)); + return Convert.ToHexString(sha1HashData).Replace("-", string.Empty); + } + + throw new NotImplementedException("Provided hash algorithm is not supported."); + } + + /// + /// Generates an account ID for a profile + /// + /// Generated account ID + public static int GenerateAccountId() + { + const int min = 1000000; + const int max = 1999999; + + var random = new Random(); + + return random.Next() * (max - min + 1) + min; + } + + [GeneratedRegex("^[a-fA-F0-9]{24}$", RegexOptions.IgnoreCase, "en")] + private static partial Regex MongoIdRegex(); +} + +public enum HashingAlgorithm +{ + MD5, + SHA1, +} \ No newline at end of file diff --git a/Core/Utils/Logging/SimpleTextLogger.cs b/Core/Utils/Logging/SimpleTextLogger.cs index a09f55af..989b41fa 100644 --- a/Core/Utils/Logging/SimpleTextLogger.cs +++ b/Core/Utils/Logging/SimpleTextLogger.cs @@ -1,8 +1,8 @@ -using Types.Annotations; -using Types.Models.Logging; -using ILogger = Types.Models.Utils.ILogger; +using Core.Models.Logging; +using Core.Annotations; +using ILogger = Core.Models.Utils.ILogger; -namespace Types.Utils.Logging; +namespace Core.Utils.Logging; [Injectable(InjectionType.Singleton)] public class SimpleTextLogger : ILogger diff --git a/Core/Utils/RandomUtil.cs b/Core/Utils/RandomUtil.cs index 73bc97f4..dd8c41e4 100644 --- a/Core/Utils/RandomUtil.cs +++ b/Core/Utils/RandomUtil.cs @@ -1,6 +1,173 @@ -namespace Types.Utils; +using System.Security.Cryptography; +using Core.Annotations; +namespace Core.Utils; + +// TODO: Finish porting this class +[Injectable(InjectionType.Singleton)] public class RandomUtil { + private readonly Random _random = new(); + /// + /// Generates a random integer between the specified minimum and maximum values, inclusive. + /// + /// The minimum value (inclusive). + /// The maximum value (inclusive). + /// A random integer between the specified minimum and maximum values. + public int GetInt(int min, int max) + { + // Prevents a potential integer overflow. + if (max == int.MaxValue) + { + max -= 1; + } + + // maxVal is exclusive of the passed value, so add 1 + return max > min ? _random.Next(min, max + 1) : min; + } + + /// + /// Generates a random integer between 1 (inclusive) and the specified maximum value (exclusive). + /// If the maximum value is less than or equal to 1, it returns 1. + /// + /// The upper bound (exclusive) for the random integer generation. + /// A random integer between 1 and max - 1, or 1 if max is less than or equal to 1. + public int GetIntEx(int max) + { + return max > 2 ? _random.Next(1, max - 1) : 1; + } + + /// + /// Generates a random floating-point number within the specified range. + /// + /// The minimum value of the range (inclusive). + /// The maximum value of the range (exclusive). + /// A random floating-point number between `min` (inclusive) and `max` (exclusive). + public float GetFloat(float min, float max) + { + return (float)GetSecureRandomNumber() * (max - min) + min; + } + + /// + /// Generates a random boolean value. + /// + /// A random boolean value, where the probability of `true` and `false` is approximately equal. + public bool GetBool() + { + return GetSecureRandomNumber() < 0.5; + } + + /// + /// Calculates the percentage of a given number and returns the result. + /// + /// The percentage to calculate. + /// The number to calculate the percentage of. + /// The number of decimal places to round the result to (default is 2). + /// The calculated percentage of the given number, rounded to the specified number of decimal places. + public float GetPercentOfValue(float percent, float number, int toFixed = 2) + { + var num = percent * number / 100; + + return (float)Math.Round(num, toFixed); + } + + /// + /// Reduces a given number by a specified percentage. + /// + /// The original number to be reduced. + /// The percentage by which to reduce the number. + /// The reduced number after applying the percentage reduction. + public float ReduceValueByPercent(float number, float percentage) + { + var reductionAmount = number * percentage / 100; + + return number - reductionAmount; + } + + /// + /// Determines if a random event occurs based on the given chance percentage. + /// + /// The percentage chance (0-100) that the event will occur. + /// `true` if the event occurs, `false` otherwise. + public bool GetChance100(float chancePercent) + { + chancePercent = Math.Clamp(chancePercent, 0f, 100f); + + return GetIntEx(100) <= chancePercent; + } + + /// + /// Returns a random string from the provided collection of strings. + /// + /// This method is separate from GetCollectionValue so we can use a generic inference with GetCollectionValue. + /// + /// The collection of strings to select a random value from. + /// A randomly selected string from the array. + public string GetStringCollectionValue(IEnumerable collection) + { + return collection.ElementAt(GetInt(0, collection.Count() - 1)); + } + + /// + /// Returns a random string from the provided collection of strings. + /// + /// + /// The type of elements in the collection. + /// A random element from the collection. + /// This was formerly getArrayValue() in the node server + public T GetCollectionValue(IEnumerable collection) + { + return collection.ElementAt(GetInt(0, collection.Count() - 1)); + } + + /// + /// Gets a random key from the given dictionary + /// + /// The dictionary from which to retrieve a key. + /// Type of key + /// Type of Value + /// A random TKey representing one of the keys of the dictionary. + public TKey GetKey(Dictionary dictionary) where TKey : notnull + { + return GetCollectionValue(dictionary.Keys); + } + + /// + /// Generates a secure random number between 0 (inclusive) and 1 (exclusive). + /// + /// This method uses the `crypto` module to generate a 48-bit random integer, + /// which is then divided by the maximum possible 48-bit integer value to + /// produce a floating-point number in the range [0, 1). + /// + /// A secure random number between 0 (inclusive) and 1 (exclusive). + private static double GetSecureRandomNumber() + { + var buffer = new byte[6]; + + using var rng = RandomNumberGenerator.Create(); + + // Fill buffer with random bytes + rng.GetBytes(buffer); + + var integer = 0; + for (var i = 0; i < 6; i++) + { + integer = (integer << 8) | buffer[i]; + } + + const ulong maxInt = 1UL << 48; + + return (double)integer / maxInt; + } + + /// + /// Determines the number of decimal places in a number. + /// + /// The number to analyze. + /// The number of decimal places, or 0 if none exist. + private static int GetNumberPrecision(double num) + { + return num.ToString().Split('.')[1]?.Length ?? 0; + } } \ No newline at end of file diff --git a/Core/Utils/TimeUtil.cs b/Core/Utils/TimeUtil.cs new file mode 100644 index 00000000..94fcbb61 --- /dev/null +++ b/Core/Utils/TimeUtil.cs @@ -0,0 +1,178 @@ +using Core.Annotations; + +namespace Core.Utils; + +[Injectable(InjectionType.Singleton)] +public class TimeUtil +{ + public const int OneHourAsSeconds = 3600; + + /// + /// Formats the time part of a date as a UTC string. + /// + /// The date to format in UTC. + /// The formatted time as 'HH-MM-SS'. + public string FormatTime(DateTime dateTime) + { + var hour = Pad(dateTime.ToUniversalTime().Hour); + var minute = Pad(dateTime.ToUniversalTime().Minute); + var second = Pad(dateTime.ToUniversalTime().Second); + + return $"{hour}-{minute}-{second}"; + } + + /// + /// Formats the date part of a date as a UTC string. + /// + /// The date to format in UTC. + /// The formatted date as 'YYYY-MM-DD'. + public string FormatDate(DateTime dateTime) + { + var day = Pad(dateTime.ToUniversalTime().Day); + var month = Pad(dateTime.ToUniversalTime().Month); + var year = Pad(dateTime.ToUniversalTime().Year); + + return $"{year}-{month}-{day}"; + } + + /// + /// Gets the current date as a formatted UTC string. + /// + /// The current date as 'YYYY-MM-DD'. + public string GetDate() + { + return FormatDate(DateTime.Now); + } + + /// + /// Gets the current time as a formatted UTC string. + /// + /// The current time as 'HH-MM-SS'. + public string GetTime() + { + return FormatTime(DateTime.Now); + } + + /// + /// Gets the current timestamp in seconds in UTC. + /// + /// The current timestamp in seconds since the Unix epoch in UTC. + public long GetTimeStamp() + { + return DateTimeOffset.Now.ToUnixTimeSeconds(); + } + + /// + /// Gets the start of day timestamp for the given date + /// + /// datetime to get the time stamp for, if null it uses current date. + /// Unix epoch for the start of day of the calculated date + public long GetStartOfDayTimeStamp(DateTime? dateTime) + { + var now = dateTime ?? DateTime.Now; + + return new DateTimeOffset(new DateTime(now.Year, now.Month, now.Day, 0, 0, 0)) + .ToUnixTimeSeconds(); + } + + /// + /// Get timestamp of today + passed in day count + /// + /// Days from now + /// + public long GetTimeStampFromNowDays(int daysFromNow) + { + return DateTimeOffset.Now.AddDays(daysFromNow).ToUnixTimeSeconds(); + } + + /// + /// Get timestamp of today + passed in hour count + /// + /// + /// + public long GetTimeStampFromNowHours(int hoursFromNow) + { + return DateTimeOffset.Now.AddHours(hoursFromNow).ToUnixTimeSeconds(); + } + + /// + /// Gets the current time in UTC in a format suitable for mail in EFT. + /// + /// The current time as 'HH:MM' in UTC. + public string GetTimeMailFormat() + { + return DateTime.UtcNow.ToString("HH:mm"); + } + + /// + /// Gets the current date in UTC in a format suitable for emails in EFT. + /// + /// The current date as 'DD.MM.YYYY' in UTC. + public string GetDateMailFormat() + { + return DateTime.UtcNow.ToString("dd.MM.yyyy"); + } + + /// + /// Converts a number of hours into seconds. + /// + /// The number of hours to convert. + /// The equivalent number of seconds. + public int GetHoursAsSeconds(int hours) + { + return OneHourAsSeconds * hours; + } + + /// + /// Gets the time stamp of the start of the next hour in UTC + /// + /// Time stamp of the next hour in unix time seconds + public long GetTimeStampOfNextHour() + { + var now = DateTime.UtcNow; + + var nextHour = new DateTime( + now.Year, + now.Month, + now.Day, + now.Hour, + 0, + 0, + DateTimeKind.Utc + ).AddHours(1); + + return new DateTimeOffset(nextHour).ToUnixTimeSeconds(); + } + + /// + /// Returns the current days timestamp at 00:00 + /// e.g. current time: 13th March 14:22 will return 13th March 00:00 + /// + /// Timestamp + public long GetTodayMidNightTimeStamp() + { + var now = DateTime.UtcNow; + + var midNight = new DateTime( + now.Year, + now.Month, + now.Day, + 0, + 0, + 0, + DateTimeKind.Utc + ); + + return new DateTimeOffset(midNight).ToUnixTimeSeconds(); + } + + /// + /// Pads a number with a leading zero if it is less than 10. + /// + /// The number to pad. + /// The padded number as a string. + private static string Pad(int number) + { + return number.ToString().PadLeft(2, '0'); + } +} \ No newline at end of file diff --git a/Server/Program.cs b/Server/Program.cs index 765f8ee9..6e6d8a21 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -1,5 +1,5 @@ -using Types.Annotations; -using Types.Servers; +using Core.Annotations; +using Core.Servers; namespace Server; diff --git a/server-csharp.sln.DotSettings b/server-csharp.sln.DotSettings new file mode 100644 index 00000000..37cd0abc --- /dev/null +++ b/server-csharp.sln.DotSettings @@ -0,0 +1,5 @@ + + True + NEVER + NEVER + NEVER \ No newline at end of file