Moves a bunch of libraries to traits
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -132,8 +132,8 @@ impl ValueIdentifiable for ChoiceQueue {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::defines::LevelInt;
|
||||
use crate::dynamic_data::PassChoice;
|
||||
use crate::static_data::{AbilityIndex, DataLibrary, Gender};
|
||||
use crate::dynamic_data::{DynamicLibrary, PassChoice};
|
||||
use crate::static_data::{AbilityIndex, Gender};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::dynamic_data::Battle;
|
||||
use crate::dynamic_data::DamageSource;
|
||||
use crate::dynamic_data::ExecutingMove;
|
||||
use crate::dynamic_data::Pokemon;
|
||||
use crate::static_data::{DataLibrary, MoveCategory};
|
||||
use crate::static_data::MoveCategory;
|
||||
use crate::{run_scripts, script_hook, PkmnResult};
|
||||
|
||||
impl Battle {
|
||||
|
||||
@@ -137,3 +137,23 @@ impl ValueIdentifiable for Gen7BattleStatCalculator {
|
||||
self.identifier
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
|
||||
mockall::mock! {
|
||||
#[derive(Debug)]
|
||||
pub BattleStatCalculator{}
|
||||
impl BattleStatCalculator for BattleStatCalculator {
|
||||
fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<u32>);
|
||||
fn calculate_flat_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32;
|
||||
fn calculate_boosted_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<u32>);
|
||||
fn calculate_boosted_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32;
|
||||
}
|
||||
impl ValueIdentifiable for BattleStatCalculator {
|
||||
fn value_identifier(&self) -> ValueIdentifier{
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::fmt::Debug;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -11,14 +12,42 @@ use crate::static_data::Item;
|
||||
use crate::static_data::StaticData;
|
||||
use crate::{PkmnResult, StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
|
||||
/// The dynamic library stores a static data library, as well as holding different libraries and
|
||||
/// calculators that might be customized between different generations and implementations.
|
||||
pub trait DynamicLibrary: Debug + ValueIdentifiable {
|
||||
/// The static data is the immutable storage data for this library.
|
||||
fn static_data(&self) -> &Box<dyn StaticData>;
|
||||
/// The stat calculator deals with the calculation of flat and boosted stats, based on the
|
||||
/// Pokemons attributes.
|
||||
fn stat_calculator(&self) -> &dyn BattleStatCalculator;
|
||||
/// The damage calculator deals with the calculation of things relating to damage.
|
||||
fn damage_calculator(&self) -> &dyn DamageLibrary;
|
||||
/// The Misc Library holds minor functions that do not fall in any of the other libraries and
|
||||
/// calculators.
|
||||
fn misc_library(&self) -> &dyn MiscLibrary;
|
||||
|
||||
/// Loads a standard script with a given unique combination of category and key. If no script
|
||||
/// can be created with this combination, returns None.
|
||||
fn load_script(
|
||||
&self,
|
||||
owner: ScriptOwnerData,
|
||||
_category: ScriptCategory,
|
||||
_key: &StringKey,
|
||||
) -> PkmnResult<Option<Arc<dyn Script>>>;
|
||||
/// Loads an item script with the given unique key. If no script can be created with this
|
||||
/// combinations, returns None. Note that ItemScripts are immutable, as their script should be
|
||||
/// shared between all different usages.
|
||||
fn load_item_script(&self, _key: &Arc<dyn Item>) -> PkmnResult<Option<Arc<dyn ItemScript>>>;
|
||||
}
|
||||
|
||||
/// The dynamic library stores a static data library, as well as holding different libraries and
|
||||
/// calculators that might be customized between different generations and implementations.
|
||||
#[derive(Debug)]
|
||||
pub struct DynamicLibrary {
|
||||
pub struct DynamicLibraryImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The static data is the immutable storage data for this library.
|
||||
static_data: StaticData,
|
||||
static_data: Box<dyn StaticData>,
|
||||
/// The stat calculator deals with the calculation of flat and boosted stats, based on the
|
||||
/// Pokemons attributes.
|
||||
stat_calculator: Box<dyn BattleStatCalculator>,
|
||||
@@ -32,13 +61,10 @@ pub struct DynamicLibrary {
|
||||
script_resolver: Box<dyn ScriptResolver>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for DynamicLibrary {}
|
||||
unsafe impl Send for DynamicLibrary {}
|
||||
|
||||
impl DynamicLibrary {
|
||||
impl DynamicLibraryImpl {
|
||||
/// Instantiates a new DynamicLibrary with given parameters.
|
||||
pub fn new(
|
||||
static_data: StaticData,
|
||||
static_data: Box<dyn StaticData>,
|
||||
stat_calculator: Box<dyn BattleStatCalculator>,
|
||||
damage_calculator: Box<dyn DamageLibrary>,
|
||||
misc_library: Box<dyn MiscLibrary>,
|
||||
@@ -53,29 +79,31 @@ impl DynamicLibrary {
|
||||
script_resolver,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DynamicLibrary for DynamicLibraryImpl {
|
||||
/// The static data is the immutable storage data for this library.
|
||||
pub fn static_data(&self) -> &StaticData {
|
||||
fn static_data(&self) -> &Box<dyn StaticData> {
|
||||
&self.static_data
|
||||
}
|
||||
/// The stat calculator deals with the calculation of flat and boosted stats, based on the
|
||||
/// Pokemons attributes.
|
||||
pub fn stat_calculator(&self) -> &dyn BattleStatCalculator {
|
||||
fn stat_calculator(&self) -> &dyn BattleStatCalculator {
|
||||
self.stat_calculator.deref()
|
||||
}
|
||||
/// The damage calculator deals with the calculation of things relating to damage.
|
||||
pub fn damage_calculator(&self) -> &dyn DamageLibrary {
|
||||
fn damage_calculator(&self) -> &dyn DamageLibrary {
|
||||
self.damage_calculator.deref()
|
||||
}
|
||||
/// The Misc Library holds minor functions that do not fall in any of the other libraries and
|
||||
/// calculators.
|
||||
pub fn misc_library(&self) -> &dyn MiscLibrary {
|
||||
fn misc_library(&self) -> &dyn MiscLibrary {
|
||||
self.misc_library.deref()
|
||||
}
|
||||
|
||||
/// Loads a standard script with a given unique combination of category and key. If no script
|
||||
/// can be created with this combination, returns None.
|
||||
pub fn load_script(
|
||||
fn load_script(
|
||||
&self,
|
||||
owner: ScriptOwnerData,
|
||||
_category: ScriptCategory,
|
||||
@@ -86,12 +114,12 @@ impl DynamicLibrary {
|
||||
/// Loads an item script with the given unique key. If no script can be created with this
|
||||
/// combinations, returns None. Note that ItemScripts are immutable, as their script should be
|
||||
/// shared between all different usages.
|
||||
pub fn load_item_script(&self, _key: &Arc<dyn Item>) -> PkmnResult<Option<Arc<dyn ItemScript>>> {
|
||||
fn load_item_script(&self, _key: &Arc<dyn Item>) -> PkmnResult<Option<Arc<dyn ItemScript>>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for DynamicLibrary {
|
||||
impl ValueIdentifiable for DynamicLibraryImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
@@ -99,16 +127,39 @@ impl ValueIdentifiable for DynamicLibrary {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use crate::dynamic_data::libraries::battle_stat_calculator::Gen7BattleStatCalculator;
|
||||
use crate::dynamic_data::libraries::damage_library::Gen7DamageLibrary;
|
||||
use crate::dynamic_data::libraries::dynamic_library::DynamicLibrary;
|
||||
use crate::dynamic_data::libraries::misc_library::Gen7MiscLibrary;
|
||||
use crate::dynamic_data::EmptyScriptResolver;
|
||||
|
||||
pub fn build() -> DynamicLibrary {
|
||||
DynamicLibrary {
|
||||
mockall::mock! {
|
||||
#[derive(Debug)]
|
||||
pub DynamicLibrary{}
|
||||
impl DynamicLibrary for DynamicLibrary {
|
||||
fn static_data(&self) -> &Box<dyn StaticData>;
|
||||
fn stat_calculator(&self) -> &dyn BattleStatCalculator;
|
||||
fn damage_calculator(&self) -> &dyn DamageLibrary;
|
||||
fn misc_library(&self) -> &dyn MiscLibrary;
|
||||
fn load_script(
|
||||
&self,
|
||||
owner: ScriptOwnerData,
|
||||
_category: ScriptCategory,
|
||||
_key: &StringKey,
|
||||
) -> PkmnResult<Option<Arc<dyn Script>>>;
|
||||
fn load_item_script(&self, _key: &Arc<dyn Item>) -> PkmnResult<Option<Arc<dyn ItemScript>>>;
|
||||
}
|
||||
impl ValueIdentifiable for DynamicLibrary{
|
||||
fn value_identifier(&self) -> ValueIdentifier{
|
||||
ValueIdentifier::new(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build() -> DynamicLibraryImpl {
|
||||
DynamicLibraryImpl {
|
||||
identifier: Default::default(),
|
||||
static_data: crate::static_data::libraries::static_data::test::build(),
|
||||
static_data: Box::new(crate::static_data::libraries::static_data::test::build()),
|
||||
stat_calculator: Box::new(Gen7BattleStatCalculator::new()),
|
||||
damage_calculator: Box::new(Gen7DamageLibrary::new(false)),
|
||||
misc_library: Box::new(Gen7MiscLibrary::new()),
|
||||
|
||||
@@ -47,7 +47,7 @@ impl Gen7MiscLibrary {
|
||||
))),
|
||||
HashSet::new(),
|
||||
));
|
||||
let struggle_learned_move = Arc::new(LearnedMove::new(&struggle_data, MoveLearnMethod::Unknown));
|
||||
let struggle_learned_move = Arc::new(LearnedMove::new(struggle_data, MoveLearnMethod::Unknown));
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
struggle_learned_move,
|
||||
|
||||
@@ -26,7 +26,7 @@ pub struct Battle {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The library the battle uses for handling.
|
||||
library: Arc<DynamicLibrary>,
|
||||
library: Arc<dyn DynamicLibrary>,
|
||||
/// A list of all different parties in the battle.
|
||||
parties: Vec<BattleParty>,
|
||||
/// Whether or not Pokemon can flee from the battle.
|
||||
@@ -62,7 +62,7 @@ pub struct Battle {
|
||||
impl Battle {
|
||||
/// Initializes a new battle.
|
||||
pub fn new(
|
||||
library: Arc<DynamicLibrary>,
|
||||
library: Arc<dyn DynamicLibrary>,
|
||||
parties: Vec<BattleParty>,
|
||||
can_flee: bool,
|
||||
number_of_sides: u8,
|
||||
@@ -110,7 +110,7 @@ impl Battle {
|
||||
}
|
||||
|
||||
/// The library the battle uses for handling.
|
||||
pub fn library(&self) -> &Arc<DynamicLibrary> {
|
||||
pub fn library(&self) -> &Arc<dyn DynamicLibrary> {
|
||||
&self.library
|
||||
}
|
||||
/// A list of all different parties in the battle.
|
||||
|
||||
@@ -33,12 +33,13 @@ pub enum MoveLearnMethod {
|
||||
|
||||
impl LearnedMove {
|
||||
/// Instantiate a new learned move.
|
||||
pub fn new(move_data: &Arc<dyn MoveData>, learn_method: MoveLearnMethod) -> Self {
|
||||
pub fn new(move_data: Arc<dyn MoveData>, learn_method: MoveLearnMethod) -> Self {
|
||||
let max_pp = move_data.base_usages();
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
move_data: move_data.clone(),
|
||||
max_pp: move_data.base_usages(),
|
||||
remaining_pp: AtomicU8::new(move_data.base_usages()),
|
||||
move_data,
|
||||
max_pp,
|
||||
remaining_pp: AtomicU8::new(max_pp),
|
||||
learn_method,
|
||||
}
|
||||
}
|
||||
@@ -107,7 +108,7 @@ mod tests {
|
||||
let mut mock = MockMoveData::new();
|
||||
mock.expect_base_usages().return_const(30);
|
||||
let data: Arc<dyn MoveData> = Arc::new(mock);
|
||||
let learned_move = LearnedMove::new(&data, MoveLearnMethod::Level);
|
||||
let learned_move = LearnedMove::new(data, MoveLearnMethod::Level);
|
||||
assert!(learned_move.try_use(15));
|
||||
learned_move.restore_uses(5);
|
||||
assert_eq!(20, learned_move.remaining_pp());
|
||||
|
||||
@@ -12,6 +12,7 @@ use crate::dynamic_data::models::battle::Battle;
|
||||
use crate::dynamic_data::models::learned_move::{LearnedMove, MoveLearnMethod};
|
||||
use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper};
|
||||
use crate::dynamic_data::{DynamicLibrary, Script, ScriptCategory, ScriptContainer, ScriptSet, VolatileScriptsOwner};
|
||||
use crate::static_data::AbilityIndex;
|
||||
use crate::static_data::Form;
|
||||
use crate::static_data::Gender;
|
||||
use crate::static_data::Item;
|
||||
@@ -19,7 +20,6 @@ use crate::static_data::Nature;
|
||||
use crate::static_data::Species;
|
||||
use crate::static_data::TypeIdentifier;
|
||||
use crate::static_data::{Ability, Statistic};
|
||||
use crate::static_data::{AbilityIndex, DataLibrary};
|
||||
use crate::static_data::{ClampedStatisticSet, StatisticSet};
|
||||
use crate::utils::Random;
|
||||
use crate::{script_hook, PkmnResult, StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
@@ -30,7 +30,7 @@ pub struct Pokemon {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The library data of the Pokemon.
|
||||
library: Arc<DynamicLibrary>,
|
||||
library: Arc<dyn DynamicLibrary>,
|
||||
/// The species of the Pokemon.
|
||||
species: RwLock<Arc<dyn Species>>,
|
||||
/// The form of the Pokemon.
|
||||
@@ -120,7 +120,7 @@ pub struct Pokemon {
|
||||
impl Pokemon {
|
||||
/// Instantiates a new Pokemon.
|
||||
pub fn new(
|
||||
library: Arc<DynamicLibrary>,
|
||||
library: Arc<dyn DynamicLibrary>,
|
||||
species: Arc<dyn Species>,
|
||||
form: &Arc<dyn Form>,
|
||||
ability: AbilityIndex,
|
||||
@@ -188,7 +188,7 @@ impl Pokemon {
|
||||
}
|
||||
|
||||
/// The library data of the Pokemon.
|
||||
pub fn library(&self) -> &Arc<DynamicLibrary> {
|
||||
pub fn library(&self) -> &Arc<dyn DynamicLibrary> {
|
||||
&self.library
|
||||
}
|
||||
/// The species of the Pokemon.
|
||||
@@ -416,9 +416,9 @@ impl Pokemon {
|
||||
self.override_ability.is_some()
|
||||
}
|
||||
/// Returns the currently active ability.
|
||||
pub fn active_ability(&self) -> &Arc<dyn Ability> {
|
||||
pub fn active_ability(&self) -> Arc<dyn Ability> {
|
||||
if let Some(v) = &self.override_ability {
|
||||
return v;
|
||||
return v.clone();
|
||||
}
|
||||
self.library
|
||||
.static_data()
|
||||
@@ -523,7 +523,7 @@ impl Pokemon {
|
||||
.set(ability_script)
|
||||
.as_ref()
|
||||
// Ensure the ability script gets initialized with the parameters for the ability.
|
||||
.on_initialize(self.library.as_ref(), self.active_ability().parameters().to_vec())
|
||||
.on_initialize(&self.library, self.active_ability().parameters().to_vec())
|
||||
} else {
|
||||
self.ability_script.clear();
|
||||
}
|
||||
@@ -829,14 +829,69 @@ pub enum DamageSource {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use crate::dynamic_data::libraries::test::MockDynamicLibrary;
|
||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||
use crate::static_data::Gender;
|
||||
use crate::static_data::{AbilityIndex, DataLibrary};
|
||||
use crate::dynamic_data::tests::MockBattleStatCalculator;
|
||||
use crate::dynamic_data::DynamicLibrary;
|
||||
use crate::static_data::growth_rate_library::tests::MockGrowthRateLibrary;
|
||||
use crate::static_data::nature_library::tests::MockNatureLibrary;
|
||||
use crate::static_data::species_library::tests::MockSpeciesLibrary;
|
||||
use crate::static_data::test::MockStaticData;
|
||||
use crate::static_data::tests::{MockForm, MockNature, MockSpecies};
|
||||
use crate::static_data::{AbilityIndex, Species};
|
||||
use crate::static_data::{Form, Gender};
|
||||
use crate::StringKey;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub fn mock_library() -> Arc<dyn DynamicLibrary> {
|
||||
let mut species_lib = MockSpeciesLibrary::new();
|
||||
species_lib.expect_get().return_once(|_| {
|
||||
let mut species = MockSpecies::new();
|
||||
species.expect_get_form().return_once(|_| {
|
||||
let mut form = MockForm::new();
|
||||
form.expect_name().return_const(StringKey::new("default"));
|
||||
form.expect_weight().return_const(100.0);
|
||||
form.expect_height().return_const(20.0);
|
||||
form.expect_types().return_const(vec![0u8.into()]);
|
||||
let a: Arc<dyn Form> = Arc::new(form);
|
||||
Some(a)
|
||||
});
|
||||
species.expect_growth_rate().return_const(StringKey::empty());
|
||||
species.expect_name().return_const(StringKey::new("test_species"));
|
||||
|
||||
let s: Arc<dyn Species> = Arc::new(species);
|
||||
Some(s)
|
||||
});
|
||||
|
||||
let mut static_lib = MockStaticData::new();
|
||||
static_lib.expect_species().return_const(Box::new(species_lib));
|
||||
|
||||
let mut growth_rate_lib = MockGrowthRateLibrary::new();
|
||||
growth_rate_lib.expect_calculate_experience().return_const(1000u32);
|
||||
|
||||
let mut nature_lib = MockNatureLibrary::new();
|
||||
nature_lib.expect_get_nature().returning(|_| {
|
||||
let n = MockNature::new();
|
||||
Some(Arc::new(n))
|
||||
});
|
||||
|
||||
static_lib.expect_growth_rates().return_const(Box::new(growth_rate_lib));
|
||||
static_lib.expect_natures().return_const(Box::new(nature_lib));
|
||||
|
||||
let mut stat_calculator = MockBattleStatCalculator::new();
|
||||
stat_calculator.expect_calculate_flat_stats().returning(|_, _| {});
|
||||
stat_calculator.expect_calculate_boosted_stats().returning(|_, _| {});
|
||||
|
||||
let mut lib = MockDynamicLibrary::new();
|
||||
lib.expect_static_data().return_const(Box::new(static_lib));
|
||||
lib.expect_stat_calculator().return_const(Box::new(stat_calculator));
|
||||
|
||||
Arc::new(lib)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn construct_pokemon() {
|
||||
let lib = Arc::new(crate::dynamic_data::libraries::dynamic_library::test::build());
|
||||
let lib = mock_library();
|
||||
let species = lib.static_data().species().get(&"foo".into()).unwrap().clone();
|
||||
let form = species.get_form(&"default".into()).unwrap();
|
||||
|
||||
@@ -854,7 +909,7 @@ pub mod test {
|
||||
0,
|
||||
&"test_nature".into(),
|
||||
);
|
||||
assert_eq!(pokemon.species().name(), &"foo".into());
|
||||
assert_eq!(pokemon.species().name(), &"test_species".into());
|
||||
assert_eq!(pokemon.form().name(), &"default".into());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ use crate::defines::LevelInt;
|
||||
use crate::dynamic_data::models::learned_move::MoveLearnMethod;
|
||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||
use crate::dynamic_data::DynamicLibrary;
|
||||
use crate::static_data::{AbilityIndex, DataLibrary, Gender};
|
||||
use crate::static_data::{AbilityIndex, Gender};
|
||||
use crate::{Random, StringKey};
|
||||
|
||||
/// This allows for the easy chain building of a Pokemon.
|
||||
pub struct PokemonBuilder {
|
||||
/// The library of the Pokemon.
|
||||
library: Arc<DynamicLibrary>,
|
||||
library: Arc<dyn DynamicLibrary>,
|
||||
/// The name of the species of the Pokemon.
|
||||
species: StringKey,
|
||||
/// The level of the Pokemon.
|
||||
@@ -23,7 +23,7 @@ pub struct PokemonBuilder {
|
||||
|
||||
impl PokemonBuilder {
|
||||
/// Creates a new PokemonBuilder with a library, species, and level.
|
||||
pub fn new(library: Arc<DynamicLibrary>, species: StringKey, level: LevelInt) -> Self {
|
||||
pub fn new(library: Arc<dyn DynamicLibrary>, species: StringKey, level: LevelInt) -> Self {
|
||||
Self {
|
||||
library,
|
||||
species,
|
||||
|
||||
@@ -64,7 +64,7 @@ pub trait Script: Send + Sync {
|
||||
/// This function is ran when this script stops being in effect, and is removed from its owner.
|
||||
fn on_remove(&self) {}
|
||||
/// This function is ran when this script starts being in effect.
|
||||
fn on_initialize(&self, _library: &DynamicLibrary, _pars: Vec<EffectParameter>) {}
|
||||
fn on_initialize(&self, _library: &Arc<dyn DynamicLibrary>, _pars: Vec<EffectParameter>) {}
|
||||
/// This function is ran just before the start of the turn. Everyone has made its choices here,
|
||||
/// and the turn is about to start. This is a great place to initialize data if you need to know
|
||||
/// something has happened during a turn.
|
||||
|
||||
Reference in New Issue
Block a user