diff --git a/Cargo.toml b/Cargo.toml index 294d6e8..7067d1c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,8 +36,6 @@ rpath = false [dependencies] # Used for PrimInt, so we can check if a generic is an integer num-traits = "0.2" -# Used for automatically generating getters -derive-getters = "0.2.0" # Allow us to assert whether floats are approximately a value assert_approx_eq = "1.1.0" # Used for time based code (i.e. randomness) diff --git a/src/dynamic_data/libraries/battle_stat_calculator.rs b/src/dynamic_data/libraries/battle_stat_calculator.rs index 7bfe929..bf74b7c 100644 --- a/src/dynamic_data/libraries/battle_stat_calculator.rs +++ b/src/dynamic_data/libraries/battle_stat_calculator.rs @@ -43,9 +43,9 @@ impl BattleStatCalculator { fn calculate_health_stat(&self, pokemon: &Pokemon) -> u32 { let base = pokemon.form().get_base_stat(Statistic::HP) as u32; - let iv = *pokemon.individual_values().hp() as u32; - let ev = *pokemon.effort_values().hp() as u32; - let level = *pokemon.level() as u32; + let iv = pokemon.individual_values().hp() as u32; + let ev = pokemon.effort_values().hp() as u32; + let level = pokemon.level() as u32; (((2 * base + iv + (ev / 4)) * level) / 100) + level + 10 } @@ -53,7 +53,7 @@ impl BattleStatCalculator { let base = pokemon.form().get_base_stat(stat) as u32; let iv = pokemon.individual_values().get_stat(stat) as u32; let ev = pokemon.effort_values().get_stat(stat) as u32; - let level = *pokemon.level() as u32; + let level = pokemon.level() as u32; let unmodified = (((2 * base + iv + (ev / 4)) * level) / 100) + 5; return (unmodified as f32 * pokemon.nature().get_stat_modifier(stat)) as u32; } diff --git a/src/dynamic_data/models/battle.rs b/src/dynamic_data/models/battle.rs index 19c66f4..a3f97ad 100644 --- a/src/dynamic_data/models/battle.rs +++ b/src/dynamic_data/models/battle.rs @@ -6,20 +6,20 @@ use crate::dynamic_data::models::battle_party::BattleParty; use crate::dynamic_data::models::battle_random::BattleRandom; use crate::dynamic_data::models::battle_result::BattleResult; use crate::dynamic_data::models::battle_side::BattleSide; +use crate::dynamic_data::script_handling::script::Script; use crate::dynamic_data::script_handling::script_set::ScriptSet; -use derive_getters::Getters; +use crate::dynamic_data::script_handling::volatile_scripts::VolatileScripts; +use crate::{PkmnResult, ScriptCategory}; use std::sync::{Arc, RwLock}; -#[derive(Getters, Debug)] +#[derive(Debug)] pub struct Battle<'a> { - #[getter(skip)] library: &'a DynamicLibrary<'a>, parties: Vec>, can_flee: bool, number_of_sides: u8, pokemon_per_side: u8, sides: Vec>, - #[getter(skip)] random: BattleRandom, choice_queue: ChoiceQueue, has_ended: bool, @@ -27,7 +27,7 @@ pub struct Battle<'a> { event_hook: EventHook, history_holder: Box, current_turn: u32, - volatile: ScriptSet, + volatile: Arc>, last_turn_time: i64, } @@ -60,7 +60,7 @@ impl<'a> Battle<'a> { event_hook: Default::default(), history_holder: Box::new(HistoryHolder {}), current_turn: 0, - volatile: ScriptSet::default(), + volatile: Default::default(), last_turn_time: 0, })); @@ -71,15 +71,60 @@ impl<'a> Battle<'a> { battle } + pub fn library(&self) -> &'a DynamicLibrary<'a> { + self.library + } + pub fn parties(&self) -> &Vec> { + &self.parties + } + pub fn can_flee(&self) -> bool { + self.can_flee + } + pub fn number_of_sides(&self) -> u8 { + self.number_of_sides + } + pub fn pokemon_per_side(&self) -> u8 { + self.pokemon_per_side + } + pub fn sides(&self) -> &Vec> { + &self.sides + } pub fn random(&self) -> &BattleRandom { &self.random } + pub fn has_ended(&self) -> bool { + self.has_ended + } + pub fn result(&self) -> BattleResult { + self.result + } + pub fn event_hook(&self) -> &EventHook { + &self.event_hook + } + pub fn history_holder(&self) -> &Box { + &self.history_holder + } + pub fn current_turn(&self) -> u32 { + self.current_turn + } + pub fn last_turn_time(&self) -> i64 { + self.last_turn_time + } + pub fn choice_queue(&self) -> &ChoiceQueue { + &self.choice_queue + } pub fn can_slot_be_filled(&self) -> bool { todo!() } +} - pub fn library(&self) -> &'a DynamicLibrary<'a> { - self.library +impl<'a> VolatileScripts<'a> for Battle<'a> { + fn volatile_scripts(&self) -> &Arc> { + &self.volatile + } + + fn load_volatile_script(&self, key: &str) -> PkmnResult> { + self.library.load_script(ScriptCategory::Battle, key) } } diff --git a/src/dynamic_data/models/battle_result.rs b/src/dynamic_data/models/battle_result.rs index b0cd5fe..6f56783 100644 --- a/src/dynamic_data/models/battle_result.rs +++ b/src/dynamic_data/models/battle_result.rs @@ -1,4 +1,4 @@ -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] pub enum BattleResult { Inconclusive, Conclusive(u8), diff --git a/src/dynamic_data/models/battle_side.rs b/src/dynamic_data/models/battle_side.rs index f7a9808..286fe3f 100644 --- a/src/dynamic_data/models/battle_side.rs +++ b/src/dynamic_data/models/battle_side.rs @@ -8,10 +8,9 @@ use crate::dynamic_data::script_handling::script_set::ScriptSet; use crate::dynamic_data::script_handling::volatile_scripts::VolatileScripts; use crate::dynamic_data::script_handling::ScriptSource; use crate::{script_hook, PkmnResult}; -use derive_getters::Getters; use std::sync::{Arc, RwLock, Weak}; -#[derive(Getters, Debug)] +#[derive(Debug)] pub struct BattleSide<'a> { index: u8, pokemon_per_side: u8, @@ -48,6 +47,33 @@ impl<'a> BattleSide<'a> { volatile_scripts: Default::default(), } } + pub fn index(&self) -> u8 { + self.index + } + pub fn pokemon_per_side(&self) -> u8 { + self.pokemon_per_side + } + pub fn pokemon(&self) -> &Vec>>>> { + &self.pokemon + } + pub fn choices(&self) -> &Vec>>> { + &self.choices + } + pub fn fillable_slots(&self) -> &Vec { + &self.fillable_slots + } + pub fn choices_set(&self) -> u8 { + self.choices_set + } + pub fn battle(&self) -> &Weak>> { + &self.battle + } + pub fn has_fled_battle(&self) -> bool { + self.has_fled_battle + } + pub fn volatile_scripts(&self) -> &Arc> { + &self.volatile_scripts + } pub fn all_choices_set(&self) -> bool { self.choices_set == self.pokemon_per_side @@ -108,13 +134,13 @@ impl<'a> BattleSide<'a> { let battle = self.battle.upgrade().unwrap(); let battle = battle.read().unwrap(); for side in battle.sides() { - if *side.index() == self.index { + if side.index() == self.index { continue; } for opponent in side.pokemon().iter().flatten() { let mut opponent = opponent.write().unwrap(); - opponent.mark_opponent_as_seen(*pokemon.unique_identifier()); - pokemon.mark_opponent_as_seen(*opponent.unique_identifier()); + opponent.mark_opponent_as_seen(pokemon.unique_identifier()); + pokemon.mark_opponent_as_seen(opponent.unique_identifier()); } } battle.event_hook().trigger(Event::Switch { diff --git a/src/dynamic_data/models/pokemon.rs b/src/dynamic_data/models/pokemon.rs index 30cc7ab..7d5d2a9 100644 --- a/src/dynamic_data/models/pokemon.rs +++ b/src/dynamic_data/models/pokemon.rs @@ -16,7 +16,6 @@ use crate::static_data::statistic_set::{ClampedStatisticSet, StatisticSet}; use crate::static_data::statistics::Statistic; use crate::utils::random::Random; use crate::{PkmnResult, ScriptCategory}; -use derive_getters::Getters; use std::collections::HashSet; use std::sync::{Arc, RwLock, Weak}; @@ -44,11 +43,10 @@ impl<'a> PokemonBattleData<'a> { } } -#[derive(Getters, Debug)] +#[derive(Debug)] pub struct Pokemon<'a> { library: &'a DynamicLibrary<'a>, species: &'a Species<'a>, - #[getter(skip)] form: &'a Form<'a>, display_species: Option<&'a Species<'a>>, @@ -70,14 +68,12 @@ pub struct Pokemon<'a> { boosted_stats: StatisticSet, individual_values: ClampedStatisticSet, effort_values: ClampedStatisticSet, - #[getter(skip)] nature: &'a Nature, nickname: Option, ability_index: AbilityIndex, is_ability_overridden: bool, - overridden_ability_name: String, battle_data: Option>, @@ -109,8 +105,8 @@ impl<'a> Pokemon<'a> { .growth_rates() .calculate_experience(species.growth_rate(), level); let health = form.get_base_stat(Statistic::HP) as u32; - let weight = *form.weight(); - let height = *form.height(); + let weight = form.weight(); + let height = form.height(); let nature = library .static_data() .natures() @@ -140,7 +136,6 @@ impl<'a> Pokemon<'a> { nickname: None, ability_index: ability, is_ability_overridden: false, - overridden_ability_name: "".to_string(), battle_data: None, moves: [None, None, None, None], allowed_experience: false, @@ -154,9 +149,121 @@ impl<'a> Pokemon<'a> { pokemon } + pub fn library(&self) -> &'a DynamicLibrary<'a> { + self.library + } + pub fn species(&self) -> &'a Species<'a> { + self.species + } pub fn form(&self) -> &'a Form<'a> { self.form } + pub fn display_species(&self) -> &'a Species<'a> { + if let Some(v) = self.display_species { + v + } else { + self.species + } + } + pub fn display_form(&self) -> &'a Form<'a> { + if let Some(v) = self.display_form { + v + } else { + self.form + } + } + + pub fn level(&self) -> LevelInt { + self.level + } + pub fn experience(&self) -> u32 { + self.experience + } + pub fn unique_identifier(&self) -> u32 { + self.unique_identifier + } + pub fn gender(&self) -> Gender { + self.gender + } + pub fn coloring(&self) -> u8 { + self.coloring + } + pub fn held_item(&self) -> Option<&'a Item> { + self.held_item + } + pub fn current_health(&self) -> u32 { + self.current_health + } + pub fn max_health(&self) -> u32 { + self.boosted_stats.hp() + } + pub fn weight(&self) -> f32 { + self.weight + } + pub fn height(&self) -> f32 { + self.height + } + pub fn nickname(&self) -> &Option { + &self.nickname + } + pub fn real_ability(&self) -> &AbilityIndex { + &self.ability_index + } + pub fn types(&self) -> &Vec { + &self.types + } + pub fn learned_moves(&self) -> &[Option; MAX_MOVES] { + &self.moves + } + pub fn status(&self) -> &Option> { + &self.status_script + } + pub fn flat_stats(&self) -> &StatisticSet { + &self.flat_stats + } + pub fn boosted_stats(&self) -> &StatisticSet { + &self.boosted_stats + } + pub fn stat_boost(&self) -> &ClampedStatisticSet { + &self.stat_boost + } + pub fn individual_values(&self) -> &ClampedStatisticSet { + &self.individual_values + } + pub fn effort_values(&self) -> &ClampedStatisticSet { + &self.effort_values + } + + pub fn get_battle(&self) -> Option<&Weak>>> { + if let Some(data) = &self.battle_data { + Some(&data.battle) + } else { + None + } + } + pub fn get_battle_side_index(&self) -> Option { + self.battle_data.as_ref().map(|data| data.battle_side_index) + } + pub fn get_battle_index(&self) -> Option { + self.battle_data.as_ref().map(|data| data.index) + } + pub fn is_ability_overriden(&self) -> bool { + self.is_ability_overridden + } + pub fn active_ability(&self) -> &Option> { + &self.ability_script + } + pub fn seen_opponents(&self) -> Option<&HashSet> { + if let Some(data) = &self.battle_data { + Some(&data.seen_opponents) + } else { + None + } + } + pub fn allowed_experience_gain(&self) -> bool { + self.allowed_experience + } + pub fn nature(&self) -> &'a Nature { self.nature } @@ -174,7 +281,7 @@ impl<'a> Pokemon<'a> { self.form = form; // If the pokemon is genderless, but it's new species is not, we want to set its gender - if self.gender != Gender::Genderless && *species.gender_rate() < 0.0 { + if self.gender != Gender::Genderless && species.gender_rate() < 0.0 { if self.battle_data.is_some() { let battle_data = self.battle_data.as_mut().unwrap(); self.gender = species.get_random_gender( @@ -194,7 +301,7 @@ impl<'a> Pokemon<'a> { } } // Else if the new species is genderless, but the pokemon has a gender, make the creature genderless. - else if *species.gender_rate() < 0.0 && self.gender != Gender::Genderless { + else if species.gender_rate() < 0.0 && self.gender != Gender::Genderless { self.gender = Gender::Genderless; } // TODO: Battle Event trigger @@ -224,8 +331,8 @@ impl<'a> Pokemon<'a> { data.on_battle_field = value; if !value { self.volatile.write().unwrap().clear(); - self.weight = *self.form.weight(); - self.height = *self.form.height(); + self.weight = self.form.weight(); + self.height = self.form.height(); } } } diff --git a/src/static_data/items/item.rs b/src/static_data/items/item.rs index 5460368..cbaa428 100644 --- a/src/static_data/items/item.rs +++ b/src/static_data/items/item.rs @@ -1,8 +1,7 @@ use super::item_category::{BattleItemCategory, ItemCategory}; -use derive_getters::Getters; use std::collections::HashSet; -#[derive(Getters, Debug)] +#[derive(Debug)] pub struct Item { name: String, category: ItemCategory, @@ -28,6 +27,22 @@ impl Item { } } + pub fn name(&self) -> &str { + &self.name + } + pub fn category(&self) -> ItemCategory { + self.category + } + pub fn battle_category(&self) -> BattleItemCategory { + self.battle_category + } + pub fn price(&self) -> i32 { + self.price + } + pub fn flags(&self) -> &HashSet { + &self.flags + } + pub fn has_flag(&self, key: &str) -> bool { self.flags.contains(key) } diff --git a/src/static_data/items/item_category.rs b/src/static_data/items/item_category.rs index 60dcaa3..d0007a5 100644 --- a/src/static_data/items/item_category.rs +++ b/src/static_data/items/item_category.rs @@ -1,4 +1,4 @@ -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] #[repr(u8)] pub enum ItemCategory { MiscItem, @@ -11,7 +11,7 @@ pub enum ItemCategory { Mail, } -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] #[repr(u8)] pub enum BattleItemCategory { Healing, diff --git a/src/static_data/libraries/library_settings.rs b/src/static_data/libraries/library_settings.rs index d05e10e..fd449be 100644 --- a/src/static_data/libraries/library_settings.rs +++ b/src/static_data/libraries/library_settings.rs @@ -1,7 +1,16 @@ use crate::defines::LevelInt; -use derive_getters::Getters; -#[derive(Getters, Debug)] +#[derive(Debug)] pub struct LibrarySettings { - pub(crate) maximum_level: LevelInt, + maximum_level: LevelInt, +} + +impl LibrarySettings { + pub fn new(maximum_level: LevelInt) -> Self { + Self { maximum_level } + } + + pub fn maximum_level(&self) -> LevelInt { + self.maximum_level + } } diff --git a/src/static_data/libraries/species_library.rs b/src/static_data/libraries/species_library.rs index ee0eb55..5534008 100644 --- a/src/static_data/libraries/species_library.rs +++ b/src/static_data/libraries/species_library.rs @@ -83,7 +83,7 @@ pub mod tests { let r = &lib; let mon = r.get("foo"); assert!(mon.is_some()); - assert_eq!(*mon.unwrap().id(), 0_u16); + assert_eq!(mon.unwrap().id(), 0_u16); assert_eq!(mon.unwrap().as_ref().name(), "foo"); assert_eq!(r.len(), 1); } diff --git a/src/static_data/libraries/static_data.rs b/src/static_data/libraries/static_data.rs index 917cc42..4adcefe 100644 --- a/src/static_data/libraries/static_data.rs +++ b/src/static_data/libraries/static_data.rs @@ -5,9 +5,8 @@ use crate::static_data::libraries::move_library::MoveLibrary; use crate::static_data::libraries::species_library::SpeciesLibrary; use crate::static_data::libraries::type_library::TypeLibrary; use crate::static_data::natures::NatureLibrary; -use derive_getters::Getters; -#[derive(Getters, Debug)] +#[derive(Debug)] pub struct StaticData<'a> { settings: LibrarySettings, species: SpeciesLibrary<'a>, @@ -18,6 +17,50 @@ pub struct StaticData<'a> { natures: NatureLibrary, } +impl<'a> StaticData<'a> { + pub fn new( + settings: LibrarySettings, + species: SpeciesLibrary<'a>, + moves: MoveLibrary, + items: ItemLibrary, + growth_rates: GrowthRateLibrary, + types: TypeLibrary, + natures: NatureLibrary, + ) -> Self { + Self { + settings, + species, + moves, + items, + growth_rates, + types, + natures, + } + } + + pub fn settings(&self) -> &LibrarySettings { + &self.settings + } + pub fn species(&self) -> &SpeciesLibrary<'a> { + &self.species + } + pub fn moves(&self) -> &MoveLibrary { + &self.moves + } + pub fn items(&self) -> &ItemLibrary { + &self.items + } + pub fn growth_rates(&self) -> &GrowthRateLibrary { + &self.growth_rates + } + pub fn types(&self) -> &TypeLibrary { + &self.types + } + pub fn natures(&self) -> &NatureLibrary { + &self.natures + } +} + #[cfg(test)] pub mod test { use crate::static_data::libraries::library_settings::LibrarySettings; @@ -29,7 +72,7 @@ pub mod test { pub fn build<'a>() -> StaticData<'a> { StaticData { - settings: LibrarySettings { maximum_level: 100 }, + settings: LibrarySettings::new(100), species: species_library::tests::build(), moves: move_library::tests::build(), items: item_library::tests::build(), diff --git a/src/static_data/moves/secondary_effect.rs b/src/static_data/moves/secondary_effect.rs index d5e1fb9..f06fdf6 100644 --- a/src/static_data/moves/secondary_effect.rs +++ b/src/static_data/moves/secondary_effect.rs @@ -1,5 +1,3 @@ -use derive_getters::Getters; - #[derive(PartialEq, Debug)] pub enum EffectParameter { Bool(bool), @@ -8,7 +6,7 @@ pub enum EffectParameter { String(String), } -#[derive(PartialEq, Debug, Getters)] +#[derive(PartialEq, Debug)] pub struct SecondaryEffect { chance: f32, effect_name: String, @@ -34,6 +32,16 @@ impl SecondaryEffect { parameters, } } + + pub fn chance(&self) -> f32 { + self.chance + } + pub fn effect_name(&self) -> &str { + &self.effect_name + } + pub fn parameters(&self) -> &Vec { + &self.parameters + } } #[cfg(test)] diff --git a/src/static_data/species_data/form.rs b/src/static_data/species_data/form.rs index 18d987b..c8beaff 100644 --- a/src/static_data/species_data/form.rs +++ b/src/static_data/species_data/form.rs @@ -3,10 +3,9 @@ use crate::static_data::species_data::ability_index::AbilityIndex; use crate::static_data::statistic_set::StatisticSet; use crate::static_data::statistics::Statistic; use crate::utils::random::Random; -use derive_getters::Getters; use hashbrown::HashSet; -#[derive(Getters, Debug)] +#[derive(Debug)] pub struct Form<'a> { name: String, height: f32, @@ -47,6 +46,37 @@ impl<'a> Form<'a> { } } + pub fn name(&self) -> &str { + &self.name + } + pub fn height(&self) -> f32 { + self.height + } + pub fn weight(&self) -> f32 { + self.weight + } + pub fn base_experience(&self) -> u32 { + self.base_experience + } + pub fn types(&self) -> &Vec { + &self.types + } + pub fn base_stats(&self) -> StatisticSet { + self.base_stats + } + pub fn abilities(&self) -> &Vec { + &self.abilities + } + pub fn hidden_abilities(&self) -> &Vec { + &self.hidden_abilities + } + pub fn moves(&self) -> &LearnableMoves<'a> { + &self.moves + } + pub fn flags(&self) -> &HashSet { + &self.flags + } + pub fn get_type(&self, index: usize) -> u8 { self.types[index] } diff --git a/src/static_data/species_data/gender.rs b/src/static_data/species_data/gender.rs index b7a7397..3ab8e40 100644 --- a/src/static_data/species_data/gender.rs +++ b/src/static_data/species_data/gender.rs @@ -1,8 +1,8 @@ // Required for standard pokemon functions, but somewhat controversial nowadays. Consider adding a feature // that allows for a more progressive gender system for those that want it? -#[derive(Eq, PartialEq, Debug)] +#[derive(Eq, PartialEq, Copy, Clone, Debug)] pub enum Gender { - Male, - Female, - Genderless, + Genderless = 0, + Male = 1, + Female = 2, } diff --git a/src/static_data/species_data/species.rs b/src/static_data/species_data/species.rs index 9f56211..2313a39 100644 --- a/src/static_data/species_data/species.rs +++ b/src/static_data/species_data/species.rs @@ -1,10 +1,9 @@ use self::super::form::Form; use crate::static_data::species_data::gender::Gender; use crate::utils::random::Random; -use derive_getters::Getters; use hashbrown::{HashMap, HashSet}; -#[derive(Debug, Getters)] +#[derive(Debug)] pub struct Species<'a> { id: u16, name: String, @@ -37,6 +36,27 @@ impl<'a> Species<'a> { flags, } } + pub fn id(&self) -> u16 { + self.id + } + pub fn name(&self) -> &str { + &self.name + } + pub fn gender_rate(&self) -> f32 { + self.gender_rate + } + pub fn growth_rate(&self) -> &str { + &self.growth_rate + } + pub fn capture_rate(&self) -> u8 { + self.capture_rate + } + pub fn forms(&self) -> &HashMap> { + &self.forms + } + pub fn flags(&self) -> &HashSet { + &self.flags + } pub fn add_form(&mut self, id: String, form: Form<'a>) { self.forms.insert(id, form); diff --git a/src/static_data/statistic_set.rs b/src/static_data/statistic_set.rs index 13123cc..468b5e4 100644 --- a/src/static_data/statistic_set.rs +++ b/src/static_data/statistic_set.rs @@ -1,8 +1,7 @@ use super::statistics::Statistic; -use derive_getters::Getters; use num_traits::PrimInt; -#[derive(Default, Eq, PartialEq, Copy, Clone, Debug, Getters)] +#[derive(Default, Eq, PartialEq, Copy, Clone, Debug)] pub struct StatisticSet where T: PrimInt, @@ -37,6 +36,25 @@ where } } + pub fn hp(&self) -> T { + self.hp + } + pub fn attack(&self) -> T { + self.attack + } + pub fn defense(&self) -> T { + self.defense + } + pub fn special_attack(&self) -> T { + self.special_attack + } + pub fn special_defense(&self) -> T { + self.special_defense + } + pub fn speed(&self) -> T { + self.speed + } + pub const fn get_stat(&self, stat: Statistic) -> T { match stat { Statistic::HP => self.hp, @@ -82,7 +100,7 @@ where } } -#[derive(Default, Eq, PartialEq, Copy, Clone, Debug, Getters)] +#[derive(Default, Eq, PartialEq, Copy, Clone, Debug)] pub struct ClampedStatisticSet where T: PrimInt, @@ -99,6 +117,25 @@ impl ClampedStatisticSet where T: PrimInt, { + pub fn hp(&self) -> T { + self.hp + } + pub fn attack(&self) -> T { + self.attack + } + pub fn defense(&self) -> T { + self.defense + } + pub fn special_attack(&self) -> T { + self.special_attack + } + pub fn special_defense(&self) -> T { + self.special_defense + } + pub fn speed(&self) -> T { + self.speed + } + pub const fn get_stat(&self, stat: Statistic) -> T { match stat { Statistic::HP => self.hp,