using System.Text.Json.Serialization; namespace Theriapolis.Core.Data; /// /// Immutable species (subrace-equivalent) record loaded from species.json. /// Refines the parent : adds a body size, additional /// ability mods, species-specific traits, and species-specific detriments. /// public sealed record SpeciesDef { [JsonPropertyName("id")] public string Id { get; init; } = ""; [JsonPropertyName("clade_id")] public string CladeId { get; init; } = ""; [JsonPropertyName("name")] public string Name { get; init; } = ""; /// Codex-voice species description: usually the doc's italicized /// blockquote followed by a one-sentence physical/cultural summary. /// Surfaced on the Step 1 card. [JsonPropertyName("description")] public string Description { get; init; } = ""; /// Body size category, snake_case (small / medium / medium_large / large). [JsonPropertyName("size")] public string Size { get; init; } = "medium"; /// Additional ability mods on top of the clade's mods. [JsonPropertyName("ability_mods")] public Dictionary AbilityMods { get; init; } = new(); /// Base movement speed in feet per turn (5 ft. = 1 tactical tile per d20 standard). [JsonPropertyName("base_speed_ft")] public int BaseSpeedFt { get; init; } = 30; [JsonPropertyName("traits")] public TraitDef[] Traits { get; init; } = Array.Empty(); [JsonPropertyName("detriments")] public TraitDef[] Detriments { get; init; } = Array.Empty(); /// /// "sex" (male/female) or "lineage" (e.g. sheep/goat for Ram-Folk). /// Empty when the species has no variants. Determines how the variant /// is resolved: sex-axis is auto-keyed off character Sex (purebred) or /// parent role for hybrids (sire = male, dam = female); lineage-axis /// requires an explicit per-species pick. /// [JsonPropertyName("variant_axis")] public string VariantAxis { get; init; } = ""; /// /// Variant entries layered onto the species' base traits/detriments. /// The variant's id keys it: for sex-axis variants, "male" or "female"; /// for lineage variants, the lineage tag (e.g. "sheep", "goat"). /// Empty when the species has no variants. /// [JsonPropertyName("variants")] public SpeciesVariantDef[] Variants { get; init; } = Array.Empty(); } /// /// One sex- or lineage-keyed variant of a species. Layered on top of the /// base species' traits and detriments — the player ends up with both /// sets, not one or the other. /// public sealed record SpeciesVariantDef { [JsonPropertyName("id")] public string Id { get; init; } = ""; [JsonPropertyName("name")] public string Name { get; init; } = ""; [JsonPropertyName("traits")] public TraitDef[] Traits { get; init; } = Array.Empty(); [JsonPropertyName("detriments")] public TraitDef[] Detriments { get; init; } = Array.Empty(); }