From a3f2b91119d8d369fd0d1a503b7fed856a000ae1 Mon Sep 17 00:00:00 2001 From: Lauren Kaviak Date: Sun, 22 Mar 2026 01:16:49 -0500 Subject: [PATCH] refactor into multiple files --- src/classes.rs | 89 ++++++++++ src/dice.rs | 41 +++++ src/main.rs | 383 +------------------------------------------- src/player.rs | 146 +++++++++++++++++ src/stats_skills.rs | 102 ++++++++++++ 5 files changed, 384 insertions(+), 377 deletions(-) create mode 100644 src/classes.rs create mode 100644 src/dice.rs create mode 100644 src/player.rs create mode 100644 src/stats_skills.rs diff --git a/src/classes.rs b/src/classes.rs new file mode 100644 index 0000000..4b8619f --- /dev/null +++ b/src/classes.rs @@ -0,0 +1,89 @@ +use crate::dice::{DieRoll, RollResult, RollCalculation, Rollable}; + +pub trait ShortRestRecovery { + fn on_short_rest(&mut self); +} + +pub trait LongRestRecovery { + fn on_long_rest(&mut self); +} + +pub trait LevelAndHitDieManagement { + fn get_hit_die() -> u8; + + fn max_hit_die(&self) -> DieRoll { + return DieRoll { + sides: Self::get_hit_die(), + count: self.get_total_levels() + } + } + + fn expended_hit_die(&self) -> u8; + fn get_total_levels(&self) -> u8; + fn single_hit_die(&self) -> DieRoll { + return DieRoll { + sides: Self::get_hit_die(), + count: 1 + } + } + fn available_hit_die(&self) -> DieRoll { + let max = self.max_hit_die(); + let expended = self.expended_hit_die(); + return DieRoll { + sides: max.sides, + count: max.count - expended + } + } + fn get_historical_hit_die(&self) -> &Vec; + fn get_total_hp(&self) -> i32 { + let mut max_hp = 0; + let historical_hp_rolls = self.get_historical_hit_die(); + for roll in historical_hp_rolls { + max_hp += roll.total; + } + return max_hp; + } + + fn level_up(&mut self); +} + +pub struct UniversalClass { + pub levels: u8, + // reset to 0 on long rest + pub expended_hit_die: u8, + // historical, each should be immutable. + pub hit_die_history: Vec +} + +impl LongRestRecovery for UniversalClass { + fn on_long_rest(&mut self) { + self.expended_hit_die = 0; + } +} + +impl LevelAndHitDieManagement for UniversalClass { + fn get_hit_die() -> u8 { + return 6; + } + + fn get_total_levels(&self) -> u8 { + return self.levels; + } + + fn expended_hit_die(&self) -> u8 { + return self.expended_hit_die; + } + + fn get_historical_hit_die(&self) -> &Vec { + return &self.hit_die_history; + } + + fn level_up(&mut self) { + self.levels += 1; + let new_hit_die = self.single_hit_die(); + self.hit_die_history.push(RollResult { + total: new_hit_die.roll(), + calculation: new_hit_die.calculation() + }); + } +} diff --git a/src/dice.rs b/src/dice.rs new file mode 100644 index 0000000..103f46d --- /dev/null +++ b/src/dice.rs @@ -0,0 +1,41 @@ +use rand::prelude::*; + +pub struct DieRoll { + pub sides: u8, + pub count: u8 +} + +pub struct RollCalculation { + pub rolls: Vec, + pub modifier: i8 +} + +pub struct RollResult { + pub total: i32, + pub calculation: RollCalculation +} + +pub trait Rollable { + fn calculation(&self) -> RollCalculation; + + fn roll(&self) -> i32 { + let calculation = self.calculation(); + let mut total : i32 = calculation.modifier as i32; + let mut _rng = rand::rng(); + for die in calculation.rolls { + for _ in 0..die.count { + total += (rand::random::() % die.sides + 1) as i32; + } + } + return total; + } +} + +impl Rollable for DieRoll { + fn calculation(&self) -> RollCalculation { + return RollCalculation { + rolls: vec![DieRoll { sides: self.sides, count: self.count }], + modifier: 0 + } + } +} diff --git a/src/main.rs b/src/main.rs index 5071065..e2afa43 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,381 +1,10 @@ -use rand::prelude::*; - -pub enum StandardSkills { - Acrobatics, - AnimalHandling, - Arcana, - Athletics, - Deception, - History, - Insight, - Intimidation, - Investigation, - Medicine, - Nature, - Perception, - Performance, - Persuasion, - Religion, - SleightOfHand, - Stealth, - Survival, - StrengthSave, - DexteritySave, - ConstitutionSave, - IntelligenceSave, - WisdomSave, - CharismaSave -} - -#[derive(PartialEq, Clone, Copy)] -pub enum SkillProficiency { - None, - Proficient, - Expert, -} - -impl Default for SkillProficiency { - fn default() -> Self { SkillProficiency::None } -} - -pub trait Stat { - fn score(&self) -> u8; - - fn modifier(&self) -> i8 { - return (self.score() as i8 / 2) - 5; - } - - fn skill_modifier(&self, proficiency_modifier: u8, proficiency: SkillProficiency) -> i8 { - let modifier : i8 = self.modifier(); - let expert = proficiency == SkillProficiency::Expert; // are they an expert? - let proficient = expert || proficiency == SkillProficiency::Proficient; // are they at least proficient? - let proficiency_boost : u8 = proficiency_modifier * proficient as u8; - let expertise_boost : u8 = proficiency_modifier * expert as u8; - return modifier + (proficiency_boost as i8) + (expertise_boost as i8); - } -} - -pub trait StatSet { - fn strength(&self) -> &impl Stat; - fn dexterity(&self) -> &impl Stat; - fn constitution(&self) -> &impl Stat; - fn intelligence(&self) -> &impl Stat; - fn wisdom(&self) -> &impl Stat; - fn charisma(&self) -> &impl Stat; -} - -pub trait ProficiencySet { - fn get_proficiency(&self, skill: StandardSkills) -> SkillProficiency; - - fn get_proficiency_modifier(&self) -> u8; -} - -pub trait Skill { - fn select_stat<'a>(&self, set: &'a impl StatSet) -> &'a dyn Stat; - - fn get_modifier(&self, set: &impl StatSet, proficiency: SkillProficiency, proficiency_modifier: u8) -> i8 { - return self.select_stat(set).skill_modifier(proficiency_modifier, proficiency); - } - - fn is_save(&self) -> bool; -} - -pub struct DieRoll { - sides: u8, - count: u8 -} - -pub struct RollCalculation { - rolls: Vec, - modifier: i8 -} - -pub struct RollResult { - total: i32, - calculation: RollCalculation -} - -pub trait Rollable { - fn calculation(&self) -> RollCalculation; - - fn roll(&self) -> i32 { - let calculation = self.calculation(); - let mut total : i32 = calculation.modifier as i32; - let mut _rng = rand::rng(); - for die in calculation.rolls { - for _ in 0..die.count { - total += (rand::random::() % die.sides + 1) as i32; - } - } - return total; - } -} - -impl Rollable for DieRoll { - fn calculation(&self) -> RollCalculation { - return RollCalculation { - rolls: vec![DieRoll { sides: self.sides, count: self.count }], - modifier: 0 - } - } -} - -pub trait ShortRestRecovery { - fn on_short_rest(&mut self); -} - -pub trait LongRestRecovery { - fn on_long_rest(&mut self); -} - -pub trait LevelAndHitDieManagement { - fn get_hit_die() -> u8; - - fn max_hit_die(&self) -> DieRoll { - return DieRoll { - sides: Self::get_hit_die(), - count: self.get_total_levels() - } - } - - fn expended_hit_die(&self) -> u8; - fn get_total_levels(&self) -> u8; - fn single_hit_die(&self) -> DieRoll { - return DieRoll { - sides: Self::get_hit_die(), - count: 1 - } - } - fn available_hit_die(&self) -> DieRoll { - let max = self.max_hit_die(); - let expended = self.expended_hit_die(); - return DieRoll { - sides: max.sides, - count: max.count - expended - } - } - fn get_historical_hit_die(&self) -> &Vec; - fn get_total_hp(&self) -> i32 { - let mut max_hp = 0; - let historical_hp_rolls = self.get_historical_hit_die(); - for roll in historical_hp_rolls { - max_hp += roll.total; - } - return max_hp; - } - - fn level_up(&mut self); -} - -pub struct UniversalClass { - levels: u8, - // reset to 0 on long rest - expended_hit_die: u8, - // historical, each should be immutable. - hit_die_history: Vec -} - -impl LongRestRecovery for UniversalClass { - fn on_long_rest(&mut self) { - self.expended_hit_die = 0; - } -} - -impl LevelAndHitDieManagement for UniversalClass { - fn get_hit_die() -> u8 { - return 6; - } - - fn get_total_levels(&self) -> u8 { - return self.levels; - } - - fn expended_hit_die(&self) -> u8 { - return self.expended_hit_die; - } - - fn get_historical_hit_die(&self) -> &Vec { - return &self.hit_die_history; - } - - fn level_up(&mut self) { - self.levels += 1; - let new_hit_die = self.single_hit_die(); - self.hit_die_history.push(RollResult { - total: new_hit_die.roll(), - calculation: new_hit_die.calculation() - }); - } -} - -impl Stat for u8 { - fn score(&self) -> u8 { - return *self; - } -} - -impl Skill for StandardSkills { - fn select_stat<'a>(&self, set: &'a impl StatSet) -> &'a dyn Stat { - match self { - StandardSkills::DexteritySave | StandardSkills::Acrobatics | StandardSkills::SleightOfHand | StandardSkills::Stealth => set.dexterity(), - StandardSkills::StrengthSave | StandardSkills::Athletics => set.strength(), - StandardSkills::ConstitutionSave => set.constitution(), - StandardSkills::IntelligenceSave | StandardSkills::Arcana | StandardSkills::History | StandardSkills::Investigation | StandardSkills::Nature | StandardSkills::Religion => set.intelligence(), - StandardSkills::WisdomSave | StandardSkills::AnimalHandling | StandardSkills::Insight | StandardSkills::Medicine | StandardSkills::Perception | StandardSkills::Survival => set.wisdom(), - StandardSkills::CharismaSave | StandardSkills::Deception | StandardSkills::Intimidation | StandardSkills::Performance | StandardSkills::Persuasion => set.charisma(), - } - } - - fn is_save(&self) -> bool { - return matches!(self, StandardSkills::StrengthSave | StandardSkills::DexteritySave | StandardSkills::ConstitutionSave | StandardSkills::IntelligenceSave | StandardSkills::WisdomSave | StandardSkills::CharismaSave); - } -} - -pub struct Player { - strength_score: u8, - dexterity_score: u8, - constitution_score: u8, - intelligence_score: u8, - wisdom_score: u8, - charisma_score: u8, - level: u8, - - // saves - dexterity_save_proficiency: SkillProficiency, - strength_save_proficiency: SkillProficiency, - constitution_save_proficiency: SkillProficiency, - intelligence_save_proficiency: SkillProficiency, - wisdom_save_proficiency: SkillProficiency, - charisma_save_proficiency: SkillProficiency, - - // skills - // dexterity: Acrobatics, SleightOfHand, Stealth - acrobatics_proficiency: SkillProficiency, - sleight_of_hand_proficiency: SkillProficiency, - stealth_proficiency: SkillProficiency, - // strength: Athletics - athletics_proficiency: SkillProficiency, - // constitution: none - // intelligence: Arcana, History, Investigation, Nature, Religion - arcana_proficiency: SkillProficiency, - history_proficiency: SkillProficiency, - investigation_proficiency: SkillProficiency, - nature_proficiency: SkillProficiency, - religion_proficiency: SkillProficiency, - // wisdom: Animal Handling, Insight, Medicine, Perception, Survival - animal_handling_proficiency: SkillProficiency, - insight_proficiency: SkillProficiency, - medicine_proficiency: SkillProficiency, - perception_proficiency: SkillProficiency, - survival_proficiency: SkillProficiency, - // charisma: Deception, Intimidation, Performance, Persuasion - deception_proficiency: SkillProficiency, - intimidation_proficiency: SkillProficiency, - performance_proficiency: SkillProficiency, - persuasion_proficiency: SkillProficiency -} - -impl Default for Player { - fn default() -> Self { - return Player { - strength_score: 10, - dexterity_score: 10, - constitution_score: 10, - intelligence_score: 10, - wisdom_score: 10, - charisma_score: 10, - - level: 1, - - dexterity_save_proficiency: SkillProficiency::None, - strength_save_proficiency: SkillProficiency::None, - constitution_save_proficiency: SkillProficiency::None, - intelligence_save_proficiency: SkillProficiency::None, - wisdom_save_proficiency: SkillProficiency::None, - charisma_save_proficiency: SkillProficiency::None, - - acrobatics_proficiency: SkillProficiency::None, - sleight_of_hand_proficiency: SkillProficiency::None, - stealth_proficiency: SkillProficiency::None, - - athletics_proficiency: SkillProficiency::None, - - arcana_proficiency: SkillProficiency::None, - history_proficiency: SkillProficiency::None, - investigation_proficiency: SkillProficiency::None, - nature_proficiency: SkillProficiency::None, - religion_proficiency: SkillProficiency::None, - - animal_handling_proficiency: SkillProficiency::None, - insight_proficiency: SkillProficiency::None, - medicine_proficiency: SkillProficiency::None, - perception_proficiency: SkillProficiency::None, - survival_proficiency: SkillProficiency::None, - - deception_proficiency: SkillProficiency::None, - intimidation_proficiency: SkillProficiency::None, - performance_proficiency: SkillProficiency::None, - persuasion_proficiency: SkillProficiency::None - } - } -} - -impl StatSet for Player { - fn strength(&self) -> &impl Stat { - return &self.strength_score; - } - fn dexterity(&self) -> &impl Stat { - return &self.dexterity_score; - } - fn constitution(&self) -> &impl Stat { - return &self.constitution_score; - } - fn intelligence(&self) -> &impl Stat { - return &self.intelligence_score; - } - fn wisdom(&self) -> &impl Stat { - return &self.wisdom_score; - } - fn charisma(&self) -> &impl Stat { - return &self.charisma_score; - } -} - -impl ProficiencySet for Player { - fn get_proficiency(&self, skill: StandardSkills) -> SkillProficiency { - match skill { - StandardSkills::DexteritySave => self.dexterity_save_proficiency, - StandardSkills::StrengthSave => self.strength_save_proficiency, - StandardSkills::ConstitutionSave => self.constitution_save_proficiency, - StandardSkills::IntelligenceSave => self.intelligence_save_proficiency, - StandardSkills::WisdomSave => self.wisdom_save_proficiency, - StandardSkills::CharismaSave => self.charisma_save_proficiency, - StandardSkills::Acrobatics => self.acrobatics_proficiency, - StandardSkills::SleightOfHand => self.sleight_of_hand_proficiency, - StandardSkills::Stealth => self.stealth_proficiency, - StandardSkills::Athletics => self.athletics_proficiency, - StandardSkills::Arcana => self.arcana_proficiency, - StandardSkills::History => self.history_proficiency, - StandardSkills::Investigation => self.investigation_proficiency, - StandardSkills::Nature => self.nature_proficiency, - StandardSkills::Religion => self.religion_proficiency, - StandardSkills::AnimalHandling => self.animal_handling_proficiency, - StandardSkills::Insight => self.insight_proficiency, - StandardSkills::Medicine => self.medicine_proficiency, - StandardSkills::Perception => self.perception_proficiency, - StandardSkills::Survival => self.survival_proficiency, - StandardSkills::Deception => self.deception_proficiency, - StandardSkills::Intimidation => self.intimidation_proficiency, - StandardSkills::Performance => self.performance_proficiency, - StandardSkills::Persuasion => self.persuasion_proficiency - } - } - - fn get_proficiency_modifier(&self) -> u8 { - return ((self.level - 1) / 4) + 2; - } -} +mod dice; +mod stats_skills; +mod player; +mod classes; +use stats_skills::{StandardSkills, SkillProficiency, Skill, ProficiencySet, StatSet, Stat}; +use player::Player; fn main() { let demo : Player = Player { diff --git a/src/player.rs b/src/player.rs new file mode 100644 index 0000000..f436f8e --- /dev/null +++ b/src/player.rs @@ -0,0 +1,146 @@ +use crate::stats_skills::{Stat, StatSet, ProficiencySet, SkillProficiency, StandardSkills}; + +pub struct Player { + pub strength_score: u8, + pub dexterity_score: u8, + pub constitution_score: u8, + pub intelligence_score: u8, + pub wisdom_score: u8, + pub charisma_score: u8, + pub level: u8, + + // saves + pub dexterity_save_proficiency: SkillProficiency, + pub strength_save_proficiency: SkillProficiency, + pub constitution_save_proficiency: SkillProficiency, + pub intelligence_save_proficiency: SkillProficiency, + pub wisdom_save_proficiency: SkillProficiency, + pub charisma_save_proficiency: SkillProficiency, + + // skills + // dexterity: Acrobatics, SleightOfHand, Stealth + pub acrobatics_proficiency: SkillProficiency, + pub sleight_of_hand_proficiency: SkillProficiency, + pub stealth_proficiency: SkillProficiency, + // strength: Athletics + pub athletics_proficiency: SkillProficiency, + // constitution: none + // intelligence: Arcana, History, Investigation, Nature, Religion + pub arcana_proficiency: SkillProficiency, + pub history_proficiency: SkillProficiency, + pub investigation_proficiency: SkillProficiency, + pub nature_proficiency: SkillProficiency, + pub religion_proficiency: SkillProficiency, + // wisdom: Animal Handling, Insight, Medicine, Perception, Survival + pub animal_handling_proficiency: SkillProficiency, + pub insight_proficiency: SkillProficiency, + pub medicine_proficiency: SkillProficiency, + pub perception_proficiency: SkillProficiency, + pub survival_proficiency: SkillProficiency, + // charisma: Deception, Intimidation, Performance, Persuasion + pub deception_proficiency: SkillProficiency, + pub intimidation_proficiency: SkillProficiency, + pub performance_proficiency: SkillProficiency, + pub persuasion_proficiency: SkillProficiency +} + +impl Default for Player { + fn default() -> Self { + return Player { + strength_score: 10, + dexterity_score: 10, + constitution_score: 10, + intelligence_score: 10, + wisdom_score: 10, + charisma_score: 10, + + level: 1, + + dexterity_save_proficiency: SkillProficiency::None, + strength_save_proficiency: SkillProficiency::None, + constitution_save_proficiency: SkillProficiency::None, + intelligence_save_proficiency: SkillProficiency::None, + wisdom_save_proficiency: SkillProficiency::None, + charisma_save_proficiency: SkillProficiency::None, + + acrobatics_proficiency: SkillProficiency::None, + sleight_of_hand_proficiency: SkillProficiency::None, + stealth_proficiency: SkillProficiency::None, + + athletics_proficiency: SkillProficiency::None, + + arcana_proficiency: SkillProficiency::None, + history_proficiency: SkillProficiency::None, + investigation_proficiency: SkillProficiency::None, + nature_proficiency: SkillProficiency::None, + religion_proficiency: SkillProficiency::None, + + animal_handling_proficiency: SkillProficiency::None, + insight_proficiency: SkillProficiency::None, + medicine_proficiency: SkillProficiency::None, + perception_proficiency: SkillProficiency::None, + survival_proficiency: SkillProficiency::None, + + deception_proficiency: SkillProficiency::None, + intimidation_proficiency: SkillProficiency::None, + performance_proficiency: SkillProficiency::None, + persuasion_proficiency: SkillProficiency::None + } + } +} + +impl StatSet for Player { + fn strength(&self) -> &impl Stat { + return &self.strength_score; + } + fn dexterity(&self) -> &impl Stat { + return &self.dexterity_score; + } + fn constitution(&self) -> &impl Stat { + return &self.constitution_score; + } + fn intelligence(&self) -> &impl Stat { + return &self.intelligence_score; + } + fn wisdom(&self) -> &impl Stat { + return &self.wisdom_score; + } + fn charisma(&self) -> &impl Stat { + return &self.charisma_score; + } +} + +impl ProficiencySet for Player { + fn get_proficiency(&self, skill: StandardSkills) -> SkillProficiency { + match skill { + StandardSkills::DexteritySave => self.dexterity_save_proficiency, + StandardSkills::StrengthSave => self.strength_save_proficiency, + StandardSkills::ConstitutionSave => self.constitution_save_proficiency, + StandardSkills::IntelligenceSave => self.intelligence_save_proficiency, + StandardSkills::WisdomSave => self.wisdom_save_proficiency, + StandardSkills::CharismaSave => self.charisma_save_proficiency, + StandardSkills::Acrobatics => self.acrobatics_proficiency, + StandardSkills::SleightOfHand => self.sleight_of_hand_proficiency, + StandardSkills::Stealth => self.stealth_proficiency, + StandardSkills::Athletics => self.athletics_proficiency, + StandardSkills::Arcana => self.arcana_proficiency, + StandardSkills::History => self.history_proficiency, + StandardSkills::Investigation => self.investigation_proficiency, + StandardSkills::Nature => self.nature_proficiency, + StandardSkills::Religion => self.religion_proficiency, + StandardSkills::AnimalHandling => self.animal_handling_proficiency, + StandardSkills::Insight => self.insight_proficiency, + StandardSkills::Medicine => self.medicine_proficiency, + StandardSkills::Perception => self.perception_proficiency, + StandardSkills::Survival => self.survival_proficiency, + StandardSkills::Deception => self.deception_proficiency, + StandardSkills::Intimidation => self.intimidation_proficiency, + StandardSkills::Performance => self.performance_proficiency, + StandardSkills::Persuasion => self.persuasion_proficiency + } + } + + fn get_proficiency_modifier(&self) -> u8 { + return ((self.level - 1) / 4) + 2; + } +} diff --git a/src/stats_skills.rs b/src/stats_skills.rs new file mode 100644 index 0000000..5962745 --- /dev/null +++ b/src/stats_skills.rs @@ -0,0 +1,102 @@ +pub enum StandardSkills { + Acrobatics, + AnimalHandling, + Arcana, + Athletics, + Deception, + History, + Insight, + Intimidation, + Investigation, + Medicine, + Nature, + Perception, + Performance, + Persuasion, + Religion, + SleightOfHand, + Stealth, + Survival, + StrengthSave, + DexteritySave, + ConstitutionSave, + IntelligenceSave, + WisdomSave, + CharismaSave +} + +#[derive(PartialEq, Clone, Copy)] +pub enum SkillProficiency { + None, + Proficient, + Expert, +} + +impl Default for SkillProficiency { + fn default() -> Self { SkillProficiency::None } +} + +pub trait Stat { + fn score(&self) -> u8; + + fn modifier(&self) -> i8 { + return (self.score() as i8 / 2) - 5; + } + + fn skill_modifier(&self, proficiency_modifier: u8, proficiency: SkillProficiency) -> i8 { + let modifier : i8 = self.modifier(); + let expert = proficiency == SkillProficiency::Expert; // are they an expert? + let proficient = expert || proficiency == SkillProficiency::Proficient; // are they at least proficient? + let proficiency_boost : u8 = proficiency_modifier * proficient as u8; + let expertise_boost : u8 = proficiency_modifier * expert as u8; + return modifier + (proficiency_boost as i8) + (expertise_boost as i8); + } +} + +pub trait StatSet { + fn strength(&self) -> &impl Stat; + fn dexterity(&self) -> &impl Stat; + fn constitution(&self) -> &impl Stat; + fn intelligence(&self) -> &impl Stat; + fn wisdom(&self) -> &impl Stat; + fn charisma(&self) -> &impl Stat; +} + +pub trait ProficiencySet { + fn get_proficiency(&self, skill: StandardSkills) -> SkillProficiency; + + fn get_proficiency_modifier(&self) -> u8; +} + +pub trait Skill { + fn select_stat<'a>(&self, set: &'a impl StatSet) -> &'a dyn Stat; + + fn get_modifier(&self, set: &impl StatSet, proficiency: SkillProficiency, proficiency_modifier: u8) -> i8 { + return self.select_stat(set).skill_modifier(proficiency_modifier, proficiency); + } + + fn is_save(&self) -> bool; +} + +impl Skill for StandardSkills { + fn select_stat<'a>(&self, set: &'a impl StatSet) -> &'a dyn Stat { + match self { + StandardSkills::DexteritySave | StandardSkills::Acrobatics | StandardSkills::SleightOfHand | StandardSkills::Stealth => set.dexterity(), + StandardSkills::StrengthSave | StandardSkills::Athletics => set.strength(), + StandardSkills::ConstitutionSave => set.constitution(), + StandardSkills::IntelligenceSave | StandardSkills::Arcana | StandardSkills::History | StandardSkills::Investigation | StandardSkills::Nature | StandardSkills::Religion => set.intelligence(), + StandardSkills::WisdomSave | StandardSkills::AnimalHandling | StandardSkills::Insight | StandardSkills::Medicine | StandardSkills::Perception | StandardSkills::Survival => set.wisdom(), + StandardSkills::CharismaSave | StandardSkills::Deception | StandardSkills::Intimidation | StandardSkills::Performance | StandardSkills::Persuasion => set.charisma(), + } + } + + fn is_save(&self) -> bool { + return matches!(self, StandardSkills::StrengthSave | StandardSkills::DexteritySave | StandardSkills::ConstitutionSave | StandardSkills::IntelligenceSave | StandardSkills::WisdomSave | StandardSkills::CharismaSave); + } +} + +impl Stat for u8 { + fn score(&self) -> u8 { + return *self; + } +}