namespace Theriapolis.Core.Rules.Stats; /// /// Skill list used by Theriapolis — extends the d20 baseline with 12 /// additional skills (M6.18) so each ability has 5 skills tied to it. /// New skills appended at the end of the byte enum to preserve save-game /// compatibility with characters created before M6.18. Each skill is /// backed by a single ability — see . /// public enum SkillId : byte { Acrobatics = 0, AnimalHandling = 1, Arcana = 2, // Theriapolis: "Advanced Engineering" Athletics = 3, Deception = 4, History = 5, Insight = 6, Intimidation = 7, Investigation = 8, Medicine = 9, Nature = 10, Perception = 11, Performance = 12, Persuasion = 13, Religion = 14, // Theriapolis: Covenant lore SleightOfHand = 15, Stealth = 16, Survival = 17, // M6.18 — Theriapolis-flavored expansions, 5 per ability. Brawl = 18, // STR BuildRead = 19, // STR Driving = 20, // DEX Endurance = 21, // CON Force = 22, // STR Fortitude = 23, // CON Hardiness = 24, // CON Haulage = 25, // STR LungCraft = 26, // CON Marksmanship = 27, // DEX PainTolerance = 28, // CON ScentSpeak = 29, // CHA } public static class SkillIdExtensions { public static AbilityId Ability(this SkillId s) => s switch { SkillId.Acrobatics => AbilityId.DEX, SkillId.AnimalHandling => AbilityId.WIS, SkillId.Arcana => AbilityId.INT, SkillId.Athletics => AbilityId.STR, SkillId.Deception => AbilityId.CHA, SkillId.History => AbilityId.INT, SkillId.Insight => AbilityId.WIS, SkillId.Intimidation => AbilityId.CHA, SkillId.Investigation => AbilityId.INT, SkillId.Medicine => AbilityId.WIS, SkillId.Nature => AbilityId.INT, SkillId.Perception => AbilityId.WIS, SkillId.Performance => AbilityId.CHA, SkillId.Persuasion => AbilityId.CHA, SkillId.Religion => AbilityId.INT, SkillId.SleightOfHand => AbilityId.DEX, SkillId.Stealth => AbilityId.DEX, SkillId.Survival => AbilityId.WIS, SkillId.Brawl => AbilityId.STR, SkillId.BuildRead => AbilityId.STR, SkillId.Driving => AbilityId.DEX, SkillId.Endurance => AbilityId.CON, SkillId.Force => AbilityId.STR, SkillId.Fortitude => AbilityId.CON, SkillId.Hardiness => AbilityId.CON, SkillId.Haulage => AbilityId.STR, SkillId.LungCraft => AbilityId.CON, SkillId.Marksmanship => AbilityId.DEX, SkillId.PainTolerance => AbilityId.CON, SkillId.ScentSpeak => AbilityId.CHA, _ => throw new ArgumentOutOfRangeException(nameof(s)), }; /// Parses a snake_case JSON value (e.g. "animal_handling") into a SkillId. public static SkillId FromJson(string raw) => raw.ToLowerInvariant() switch { "acrobatics" => SkillId.Acrobatics, "animal_handling" => SkillId.AnimalHandling, "arcana" => SkillId.Arcana, "athletics" => SkillId.Athletics, "deception" => SkillId.Deception, "history" => SkillId.History, "insight" => SkillId.Insight, "intimidation" => SkillId.Intimidation, "investigation" => SkillId.Investigation, "medicine" => SkillId.Medicine, "nature" => SkillId.Nature, "perception" => SkillId.Perception, "performance" => SkillId.Performance, "persuasion" => SkillId.Persuasion, "religion" => SkillId.Religion, "sleight_of_hand" => SkillId.SleightOfHand, "stealth" => SkillId.Stealth, "survival" => SkillId.Survival, "brawl" => SkillId.Brawl, "build_read" => SkillId.BuildRead, "driving" => SkillId.Driving, "endurance" => SkillId.Endurance, "force" => SkillId.Force, "fortitude" => SkillId.Fortitude, "hardiness" => SkillId.Hardiness, "haulage" => SkillId.Haulage, "lung_craft" => SkillId.LungCraft, "marksmanship" => SkillId.Marksmanship, "pain_tolerance" => SkillId.PainTolerance, "scent_speak" => SkillId.ScentSpeak, _ => throw new ArgumentException($"Unknown skill: '{raw}'"), }; }