FFI for dynamic libraries

This commit is contained in:
2022-10-14 10:33:19 +02:00
parent 41b40ef98e
commit a840605bf7
15 changed files with 192 additions and 16 deletions

View File

@@ -3,9 +3,10 @@ use std::fmt::Debug;
use crate::dynamic_data::Pokemon;
use crate::static_data::Statistic;
use crate::static_data::StatisticSet;
use crate::{ValueIdentifiable, ValueIdentifier};
/// A battle stat calculator is used to calculate stats for a Pokemon.
pub trait BattleStatCalculator: Debug {
pub trait BattleStatCalculator: Debug + ValueIdentifiable {
/// Calculate all the flat stats of a Pokemon, disregarding stat boosts.
fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<u32>);
/// Calculate a single flat stat of a Pokemon, disregarding stat boost
@@ -18,9 +19,19 @@ pub trait BattleStatCalculator: Debug {
/// A basic implementation of the Gen 7 stat calculator.
#[derive(Debug)]
pub struct Gen7BattleStatCalculator {}
pub struct Gen7BattleStatCalculator {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
}
impl Gen7BattleStatCalculator {
/// Creates a new Gen 7 battle stat calculator
pub fn new() -> Self {
Self {
identifier: Default::default(),
}
}
/// The calculation used for health points.
fn calculate_health_stat(&self, pokemon: &Pokemon) -> u32 {
let base = pokemon.form().get_base_stat(Statistic::HP) as u32;
@@ -114,3 +125,9 @@ impl BattleStatCalculator for Gen7BattleStatCalculator {
(self.calculate_flat_stat(pokemon, stat) as f32 * self.get_stat_boost_modifier(pokemon, stat)) as u32
}
}
impl ValueIdentifiable for Gen7BattleStatCalculator {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}

View File

@@ -3,12 +3,12 @@ use std::sync::Arc;
use crate::dynamic_data::script_handling::ScriptSource;
use crate::dynamic_data::{Battle, Pokemon};
use crate::dynamic_data::{ExecutingMove, HitData};
use crate::script_hook;
use crate::static_data::{MoveCategory, Statistic};
use crate::{script_hook, ValueIdentifiable, ValueIdentifier};
/// A damage library holds the functions related to the calculation of damage. As this can change in
/// different generations and implementations, this is handled through a trait.
pub trait DamageLibrary: std::fmt::Debug {
pub trait DamageLibrary: std::fmt::Debug + ValueIdentifiable {
/// Calculate the damage for a given hit on a Pokemon.
fn get_damage(
&self,
@@ -40,6 +40,8 @@ pub trait DamageLibrary: std::fmt::Debug {
/// The implementation of a Damage Library for generation 7.
#[derive(Debug)]
pub struct Gen7DamageLibrary {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// Defines whether or not a random damage modifier is applied to damage (0.85 - 1.00).
has_randomness: bool,
}
@@ -48,7 +50,10 @@ impl Gen7DamageLibrary {
/// Creates a new generation 7 damage library. `has_randomness` defines whether a random damage
/// modifier (0.85x - 1.00x) is applied to the calculated damage.
pub fn new(has_randomness: bool) -> Self {
Self { has_randomness }
Self {
identifier: Default::default(),
has_randomness,
}
}
/// Calculates the modifier applied to damage from the statistics of the relevant Pokemon.
@@ -303,3 +308,9 @@ impl DamageLibrary for Gen7DamageLibrary {
}
}
}
impl ValueIdentifiable for Gen7DamageLibrary {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}

View File

@@ -9,13 +9,15 @@ use crate::dynamic_data::{ItemScript, ScriptResolver};
use crate::dynamic_data::{Script, ScriptOwnerData};
use crate::static_data::Item;
use crate::static_data::StaticData;
use crate::{PkmnResult, StringKey};
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.
#[derive(Debug)]
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
pub struct DynamicLibrary {
/// 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,
/// The stat calculator deals with the calculation of flat and boosted stats, based on the
@@ -44,6 +46,7 @@ impl DynamicLibrary {
script_resolver: Box<dyn ScriptResolver>,
) -> Self {
Self {
identifier: Default::default(),
static_data,
stat_calculator,
damage_calculator,
@@ -89,6 +92,12 @@ impl DynamicLibrary {
}
}
impl ValueIdentifiable for DynamicLibrary {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
pub mod test {
use crate::dynamic_data::libraries::battle_stat_calculator::Gen7BattleStatCalculator;
@@ -99,11 +108,14 @@ pub mod test {
pub fn build() -> DynamicLibrary {
DynamicLibrary {
identifier: Default::default(),
static_data: crate::static_data::libraries::static_data::test::build(),
stat_calculator: Box::new(Gen7BattleStatCalculator {}),
stat_calculator: Box::new(Gen7BattleStatCalculator::new()),
damage_calculator: Box::new(Gen7DamageLibrary::new(false)),
misc_library: Box::new(Gen7MiscLibrary::new()),
script_resolver: Box::new(EmptyScriptResolver {}),
script_resolver: Box::new(EmptyScriptResolver {
identifier: Default::default(),
}),
}
}
}

View File

@@ -7,10 +7,10 @@ use crate::dynamic_data::choices::{MoveChoice, TurnChoice};
use crate::dynamic_data::Pokemon;
use crate::dynamic_data::{LearnedMove, MoveLearnMethod};
use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffect};
use crate::StringKey;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
/// The misc library holds several misc functions required for the battle to run.
pub trait MiscLibrary: Debug {
pub trait MiscLibrary: Debug + ValueIdentifiable {
/// Returns whether or not a Pokemon is allowed to flee or switch out.
fn can_flee(&self, choice: &TurnChoice) -> bool;
/// Returns the move we need to use if we can't use another move. Typically Struggle.
@@ -22,6 +22,8 @@ pub trait MiscLibrary: Debug {
/// A gen 7 implementation for the MiscLibrary.
#[derive(Debug)]
pub struct Gen7MiscLibrary {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The learned move data for struggle.
struggle_learned_move: Arc<LearnedMove>,
}
@@ -42,7 +44,10 @@ impl Gen7MiscLibrary {
HashSet::new(),
));
let struggle_learned_move = Arc::new(LearnedMove::new(&struggle_data, MoveLearnMethod::Unknown));
Self { struggle_learned_move }
Self {
identifier: Default::default(),
struggle_learned_move,
}
}
}
@@ -67,3 +72,9 @@ impl MiscLibrary for Gen7MiscLibrary {
))
}
}
impl ValueIdentifiable for Gen7MiscLibrary {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}

View File

@@ -3,12 +3,12 @@ use std::sync::Arc;
use crate::dynamic_data::{ItemScript, Script, ScriptOwnerData};
use crate::static_data::Item;
use crate::{PkmnResult, StringKey};
use crate::{PkmnResult, StringKey, ValueIdentifiable, ValueIdentifier};
/// A script resolver deals with the resolving of scripts. These scripts are non-hardcoded
/// implementations of different effects in Pokemon. This allows for things such as generational
/// differences, and custom implementations.
pub trait ScriptResolver: Debug {
pub trait ScriptResolver: Debug + ValueIdentifiable {
/// 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(
@@ -55,7 +55,16 @@ pub enum ScriptCategory {
/// A basic empty script resolver, that always returns None.
#[derive(Debug)]
pub struct EmptyScriptResolver {}
pub struct EmptyScriptResolver {
/// A unique identifier so we know what value this is.
pub identifier: ValueIdentifier,
}
impl ValueIdentifiable for EmptyScriptResolver {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
impl ScriptResolver for EmptyScriptResolver {
fn load_script(