use crate::app_interface::{LearnedMove, Pokemon}; use crate::handling::cached_value::CachedValue; use crate::handling::temporary::Temporary; use crate::ExternRef; #[cfg(not(feature = "mock_data"))] use crate::{cached_value, ExternalReferenceType, Script}; #[cfg(not(feature = "mock_data"))] use alloc::boxed::Box; struct BaseTurnChoiceData { reference: ExternRef, user: CachedValue, } struct MoveTurnChoiceDataInner { base: BaseTurnChoiceData, used_move: CachedValue, target_side: CachedValue, target_index: CachedValue, } #[derive(Clone)] pub struct MoveTurnChoiceData { inner: Temporary, } pub enum TurnChoice { Move(MoveTurnChoiceData), Item(), Switch(), Flee, Pass, } impl TurnChoice { fn base(&self) -> &BaseTurnChoiceData { match self { TurnChoice::Move(d) => &d.inner.value_ref().base, TurnChoice::Item() => unimplemented!(), TurnChoice::Switch() => unimplemented!(), TurnChoice::Flee => unimplemented!(), TurnChoice::Pass => unimplemented!(), } } pub fn user(&self) -> Pokemon { self.base().user.value() } #[cfg(not(feature = "mock_data"))] pub fn speed(&self) -> u32 { unsafe { turn_choice_get_speed(self.base().reference) } } #[cfg(not(feature = "mock_data"))] pub fn has_failed(&self) -> bool { unsafe { turn_choice_has_failed(self.base().reference) } } #[cfg(not(feature = "mock_data"))] pub fn fail(&self) { unsafe { turn_choice_fail(self.base().reference) } } } impl MoveTurnChoiceData { pub fn used_move(&self) -> LearnedMove { self.inner.value().used_move.value() } pub fn target_side(&self) -> u8 { self.inner.value().target_side.value() } pub fn target_index(&self) -> u8 { self.inner.value().target_index.value() } #[cfg(not(feature = "mock_data"))] pub fn priority(&self) -> i8 { unsafe { turn_choice_move_priority(self.inner.value().base.reference.cast()) } } #[cfg(not(feature = "mock_data"))] pub fn move_script(&self) -> Option<&Box> { unsafe { turn_choice_move_script(self.inner.value().base.reference.cast()).as_ref() } } } #[cfg(not(feature = "mock_data"))] impl ExternalReferenceType for TurnChoice { fn from_extern_value(reference: ExternRef) -> Self { let kind = unsafe { turn_choice_get_kind(reference) }; match kind { 0 => TurnChoice::Move(MoveTurnChoiceData { inner: Temporary::new( reference.get_internal_index(), MoveTurnChoiceDataInner::from_reference(reference.cast()), ), }), _ => panic!("Unknown turn choice type"), } } } #[cfg(not(feature = "mock_data"))] impl MoveTurnChoiceDataInner { fn from_reference(reference: ExternRef) -> Self { Self { base: BaseTurnChoiceData { reference: reference.cast(), user: cached_value!({ turn_choice_get_user(reference.cast()).get_value().unwrap() }), }, used_move: cached_value!({ turn_choice_move_used_move(reference.cast()) .get_value() .unwrap() }), target_side: cached_value!({ turn_choice_move_target_side(reference.cast()) }), target_index: cached_value!({ turn_choice_move_target_index(reference.cast()) }), } } } #[cfg(not(feature = "mock_data"))] extern "wasm" { fn turn_choice_get_kind(r: ExternRef) -> u8; fn turn_choice_get_user(r: ExternRef) -> ExternRef; fn turn_choice_get_speed(r: ExternRef) -> u32; fn turn_choice_has_failed(r: ExternRef) -> bool; fn turn_choice_fail(r: ExternRef); fn turn_choice_move_used_move(r: ExternRef) -> ExternRef; fn turn_choice_move_target_side(r: ExternRef) -> u8; fn turn_choice_move_target_index(r: ExternRef) -> u8; fn turn_choice_move_priority(r: ExternRef) -> i8; #[allow(improper_ctypes)] fn turn_choice_move_script(r: ExternRef) -> *const Box; }