use crate::app_interface::{LearnedMove, Pokemon, PokemonImpl}; use crate::handling::cached_value::CachedValue; use crate::handling::temporary::Temporary; use crate::ExternRef; use crate::{cached_value, ExternalReferenceType, Script}; use alloc::boxed::Box; use alloc::rc::Rc; pub trait BaseTurnChoiceDataTrait { fn reference(&self) -> u32; fn user(&self) -> Pokemon; fn speed(&self) -> u32; fn has_failed(&self) -> bool; fn fail(&self); } struct BaseTurnChoiceDataImpl { reference: ExternRef, user: CachedValue>, } #[cfg(not(feature = "mock_data"))] impl BaseTurnChoiceDataTrait for BaseTurnChoiceDataImpl { fn reference(&self) -> u32 { self.reference.get_internal_index() } fn user(&self) -> Pokemon { self.user.value() } fn speed(&self) -> u32 { unsafe { turn_choice_get_speed(self.reference) } } fn has_failed(&self) -> bool { unsafe { turn_choice_has_failed(self.reference) } } fn fail(&self) { unsafe { turn_choice_fail(self.reference) } } } pub type BaseTurnChoiceData = Rc; struct MoveTurnChoiceDataInner { base: BaseTurnChoiceData, used_move: CachedValue, target_side: CachedValue, target_index: CachedValue, } pub trait MoveTurnChoiceDataTrait { fn base(&self) -> BaseTurnChoiceData; fn used_move(&self) -> LearnedMove; fn target_side(&self) -> u8; fn target_index(&self) -> u8; fn priority(&self) -> i8; fn move_script(&self) -> Option<&Box>; } #[derive(Clone)] pub struct MoveTurnChoiceDataImpl { inner: Temporary, } pub enum TurnChoice { Move(Box), Item(), Switch(), Flee, Pass, } impl TurnChoice { fn base(&self) -> BaseTurnChoiceData { match self { TurnChoice::Move(m) => m.base(), TurnChoice::Item() => unimplemented!(), TurnChoice::Switch() => unimplemented!(), TurnChoice::Flee => unimplemented!(), TurnChoice::Pass => unimplemented!(), } } pub fn user(&self) -> Pokemon { self.base().user() } pub fn speed(&self) -> u32 { self.base().speed() } pub fn has_failed(&self) -> bool { self.base().has_failed() } pub fn fail(&self) { self.base().fail() } } #[cfg(not(feature = "mock_data"))] impl MoveTurnChoiceDataTrait for MoveTurnChoiceDataImpl { fn base(&self) -> BaseTurnChoiceData { self.inner.value().base.clone() } fn used_move(&self) -> LearnedMove { self.inner.value().used_move.value() } fn target_side(&self) -> u8 { self.inner.value().target_side.value() } fn target_index(&self) -> u8 { self.inner.value().target_index.value() } fn priority(&self) -> i8 { unsafe { turn_choice_move_priority(self.base().reference().into()) } } fn move_script(&self) -> Option<&Box> { unsafe { turn_choice_move_script(self.base().reference().into()).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(Box::new(MoveTurnChoiceDataImpl { 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: Rc::new(BaseTurnChoiceDataImpl { reference: reference.cast(), user: cached_value!({ Rc::new(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; }