use crate::app_interface::{LearnedMove, MoveData, Pokemon}; use crate::handling::Script; use alloc::rc::Rc; #[cfg_attr(feature = "mock_data", mockall::automock)] pub trait ExecutingMoveTrait { fn number_of_hits(&self) -> u8; fn user(&self) -> Pokemon; fn chosen_move(&self) -> LearnedMove; fn use_move(&self) -> MoveData; fn move_script<'a>(&'a self) -> Option<&'a dyn Script>; fn number_of_targets(&self) -> usize; fn is_pokemon_target(&self, pokemon: &Pokemon) -> bool; fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> HitData; } #[cfg_attr(feature = "mock_data", mockall::automock)] pub trait HitDataTrait { fn is_critical(&self) -> bool; fn base_power(&self) -> u8; fn effectiveness(&self) -> f32; fn damage(&self) -> u32; fn move_type(&self) -> u8; fn has_failed(&self) -> bool; fn set_critical(&self, critical: bool); fn set_effectiveness(&self, effectiveness: f32); fn set_damage(&self, damage: u32); fn set_move_type(&self, move_type: u8); fn fail(&self); } pub type ExecutingMove = Rc; #[cfg(feature = "mock_data")] pub type MockExecutingMove = MockExecutingMoveTrait; pub type HitData = Rc; #[cfg(feature = "mock_data")] pub type MockHitData = MockHitDataTrait; #[cfg(not(feature = "mock_data"))] pub use implementation::*; #[cfg(not(feature = "mock_data"))] mod implementation { use super::*; use crate::app_interface::{LearnedMoveImpl, MoveDataImpl, PokemonImpl}; use crate::cached_value; use crate::handling::cached_value::CachedValue; use crate::handling::extern_ref::{ExternRef, ExternalReferenceType}; use crate::handling::temporary::Temporary; #[derive(Clone)] pub struct ExecutingMoveImpl { inner: Temporary, } struct ExecutingMoveInner { reference: ExternRef, number_of_hits: CachedValue, user: CachedValue, chosen_move: CachedValue>, use_move: CachedValue, } impl ExecutingMoveImpl { #[cfg(not(feature = "mock_data"))] pub(crate) fn new(reference: ExternRef) -> Self { Self { inner: Temporary::new( reference.get_internal_index(), ExecutingMoveInner { reference, number_of_hits: cached_value!({ executing_move_get_number_of_hits(reference) }), user: cached_value!({ Rc::new(executing_move_get_user(reference).get_value().unwrap()) }), chosen_move: cached_value!({ Rc::new( executing_move_get_chosen_move(reference) .get_value() .unwrap(), ) }), use_move: cached_value!({ Rc::new(executing_move_get_use_move(reference).get_value().unwrap()) }), }, ), } } } #[cfg(not(feature = "mock_data"))] impl ExecutingMoveTrait for ExecutingMoveImpl { fn number_of_hits(&self) -> u8 { self.inner.value().number_of_hits.value() } fn user(&self) -> Pokemon { self.inner.value().user.value() } fn chosen_move(&self) -> LearnedMove { self.inner.value().chosen_move.value() } fn use_move(&self) -> MoveData { self.inner.value().use_move.value() } fn move_script(&self) -> Option<&dyn Script> { unsafe { executing_move_get_script(self.inner.value().reference).as_ref() } } fn number_of_targets(&self) -> usize { unsafe { executing_move_get_number_of_targets(self.inner.value().reference) } } fn is_pokemon_target(&self, pokemon: &Pokemon) -> bool { unsafe { executing_move_is_pokemon_target( self.inner.value().reference, pokemon.reference().into(), ) } } fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> HitData { unsafe { Rc::new( executing_move_get_hit_data( self.inner.value().reference, pokemon.reference().into(), hit, ) .get_value() .unwrap(), ) } } } #[derive(Clone)] pub struct HitDataImpl { reference: ExternRef, } #[cfg(not(feature = "mock_data"))] impl HitDataTrait for HitDataImpl { fn is_critical(&self) -> bool { unsafe { hit_data_is_critical(self.reference) } } fn base_power(&self) -> u8 { unsafe { hit_data_get_base_power(self.reference) } } fn effectiveness(&self) -> f32 { unsafe { hit_data_get_effectiveness(self.reference) } } fn damage(&self) -> u32 { unsafe { hit_data_get_damage(self.reference) } } fn move_type(&self) -> u8 { unsafe { hit_data_get_move_type(self.reference) } } fn has_failed(&self) -> bool { unsafe { hit_data_is_critical(self.reference) } } fn set_critical(&self, critical: bool) { unsafe { hit_data_set_critical(self.reference, critical) } } fn set_effectiveness(&self, effectiveness: f32) { unsafe { hit_data_set_effectiveness(self.reference, effectiveness) } } fn set_damage(&self, damage: u32) { unsafe { hit_data_set_damage(self.reference, damage) } } fn set_move_type(&self, move_type: u8) { unsafe { hit_data_set_move_type(self.reference, move_type) } } fn fail(&self) { unsafe { hit_data_fail(self.reference) } } } #[cfg(not(feature = "mock_data"))] impl ExternalReferenceType for ExecutingMoveImpl { fn from_extern_value(reference: ExternRef) -> Self { Self::new(reference) } } #[cfg(not(feature = "mock_data"))] impl ExternalReferenceType for HitDataImpl { fn from_extern_value(reference: ExternRef) -> Self { Self { reference } } } #[cfg(not(feature = "mock_data"))] extern "wasm" { fn executing_move_get_number_of_targets(r: ExternRef) -> usize; fn executing_move_get_number_of_hits(r: ExternRef) -> u8; fn executing_move_get_user(r: ExternRef) -> ExternRef; fn executing_move_get_chosen_move( r: ExternRef, ) -> ExternRef; fn executing_move_get_use_move(r: ExternRef) -> ExternRef; #[allow(improper_ctypes)] fn executing_move_get_script(r: ExternRef) -> *const dyn Script; fn executing_move_is_pokemon_target( r: ExternRef, pokemon: ExternRef, ) -> bool; fn executing_move_get_hit_data( r: ExternRef, target: ExternRef, hit: u8, ) -> ExternRef; fn hit_data_is_critical(r: ExternRef) -> bool; fn hit_data_get_base_power(r: ExternRef) -> u8; fn hit_data_get_effectiveness(r: ExternRef) -> f32; fn hit_data_get_damage(r: ExternRef) -> u32; fn hit_data_get_move_type(r: ExternRef) -> u8; fn hit_data_has_failed(r: ExternRef) -> bool; fn hit_data_set_critical(r: ExternRef, critical: bool); fn hit_data_set_base_power(r: ExternRef, power: u8); fn hit_data_set_effectiveness(r: ExternRef, effectiveness: f32); fn hit_data_set_damage(r: ExternRef, damage: u32); fn hit_data_set_move_type(r: ExternRef, move_type: u8); fn hit_data_fail(r: ExternRef); } }