Implements first few actual move effects.
This commit is contained in:
		| @@ -1,4 +1,4 @@ | ||||
| use crate::app_interface::{BattleParty, BattleRandom, BattleSide, Pokemon}; | ||||
| use crate::app_interface::{BattleParty, BattleRandom, BattleSide, ChoiceQueue, Pokemon}; | ||||
| use crate::handling::cached_value::CachedValue; | ||||
| use crate::handling::Cacheable; | ||||
| use crate::{ | ||||
| @@ -13,6 +13,7 @@ struct BattleInner { | ||||
|     parties: CachedValue<ImmutableList<BattleParty>>, | ||||
|     sides: CachedValue<ImmutableList<BattleSide>>, | ||||
|     random: CachedValue<BattleRandom>, | ||||
|     choice_queue: CachedValue<ChoiceQueue>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| @@ -30,6 +31,9 @@ impl Battle { | ||||
|                 parties: cached_value!({ battle_get_parties(reference).get_immutable_list() }), | ||||
|                 sides: cached_value!({ battle_get_sides(reference).get_immutable_list() }), | ||||
|                 random: cached_value!({ battle_get_random(reference).get_value().unwrap() }), | ||||
|                 choice_queue: cached_value!({ | ||||
|                     battle_get_choice_queue(reference).get_value().unwrap() | ||||
|                 }), | ||||
|             }), | ||||
|         }) | ||||
|     } | ||||
| @@ -38,6 +42,8 @@ impl Battle { | ||||
|         pub fn library(&self) -> DynamicLibrary; | ||||
|         pub fn parties(&self) -> ImmutableList<BattleParty>; | ||||
|         pub fn sides(&self) -> ImmutableList<BattleSide>; | ||||
|         pub fn random(&self) -> BattleRandom; | ||||
|         pub fn choice_queue(&self) -> ChoiceQueue; | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
| @@ -72,5 +78,6 @@ extern "wasm" { | ||||
|     fn battle_get_parties(r: ExternRef<Battle>) -> VecExternRef<BattleParty>; | ||||
|     fn battle_get_sides(r: ExternRef<Battle>) -> VecExternRef<BattleSide>; | ||||
|     fn battle_get_random(r: ExternRef<Battle>) -> ExternRef<BattleRandom>; | ||||
|     fn battle_get_choice_queue(r: ExternRef<Battle>) -> ExternRef<ChoiceQueue>; | ||||
|     fn battle_get_pokemon(r: ExternRef<Battle>, side: u8, index: u8) -> ExternRef<Pokemon>; | ||||
| } | ||||
|   | ||||
| @@ -39,7 +39,6 @@ impl ExternalReferenceType for BattleParty { | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| extern "wasm" { | ||||
|     fn battle_party_get_party(r: ExternRef<BattleParty>) -> ExternRef<Party>; | ||||
|   | ||||
| @@ -0,0 +1,31 @@ | ||||
| use crate::{ExternRef, ExternalReferenceType, Pokemon}; | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct ChoiceQueue { | ||||
|     reference: ExternRef<ChoiceQueue>, | ||||
| } | ||||
|  | ||||
| impl ChoiceQueue { | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn new(reference: ExternRef<ChoiceQueue>) -> Self { | ||||
|         Self { reference } | ||||
|     } | ||||
|  | ||||
|     pub fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> bool { | ||||
|         unsafe { choice_queue_move_pokemon_choice_next(self.reference, pokemon.reference()) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| impl ExternalReferenceType for ChoiceQueue { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
|         Self::new(reference) | ||||
|     } | ||||
| } | ||||
|  | ||||
| extern "wasm" { | ||||
|     fn choice_queue_move_pokemon_choice_next( | ||||
|         r: ExternRef<ChoiceQueue>, | ||||
|         pokemon: ExternRef<Pokemon>, | ||||
|     ) -> bool; | ||||
| } | ||||
| @@ -0,0 +1,161 @@ | ||||
| use crate::app_interface::{LearnedMove, MoveData, Pokemon}; | ||||
| use crate::handling::cached_value::CachedValue; | ||||
| use crate::handling::temporary::Temporary; | ||||
| use crate::{cached_value, ExternRef, ExternalReferenceType, Script}; | ||||
|  | ||||
| struct ExecutingMoveInner { | ||||
|     reference: ExternRef<ExecutingMove>, | ||||
|     number_of_hits: CachedValue<u8>, | ||||
|     user: CachedValue<Pokemon>, | ||||
|     chosen_move: CachedValue<LearnedMove>, | ||||
|     use_move: CachedValue<MoveData>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct ExecutingMove { | ||||
|     inner: Temporary<ExecutingMoveInner>, | ||||
| } | ||||
|  | ||||
| impl ExecutingMove { | ||||
|     pub(crate) fn new(reference: ExternRef<ExecutingMove>) -> 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!({ | ||||
|                         executing_move_get_user(reference).get_value().unwrap() | ||||
|                     }), | ||||
|                     chosen_move: cached_value!({ | ||||
|                         executing_move_get_chosen_move(reference) | ||||
|                             .get_value() | ||||
|                             .unwrap() | ||||
|                     }), | ||||
|                     use_move: cached_value!({ | ||||
|                         executing_move_get_use_move(reference).get_value().unwrap() | ||||
|                     }), | ||||
|                 }, | ||||
|             ), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn number_of_hits(&self) -> u8 { | ||||
|         self.inner.value().number_of_hits.value() | ||||
|     } | ||||
|     pub fn user(&self) -> Pokemon { | ||||
|         self.inner.value().user.value() | ||||
|     } | ||||
|     pub fn chosen_move(&self) -> LearnedMove { | ||||
|         self.inner.value().chosen_move.value() | ||||
|     } | ||||
|     pub fn use_move(&self) -> MoveData { | ||||
|         self.inner.value().use_move.value() | ||||
|     } | ||||
|     pub fn move_script(&self) -> Option<&dyn Script> { | ||||
|         unsafe { executing_move_get_script(self.inner.value().reference).as_ref() } | ||||
|     } | ||||
|     pub fn number_of_targets(&self) -> usize { | ||||
|         unsafe { executing_move_get_number_of_targets(self.inner.value().reference) } | ||||
|     } | ||||
|     pub fn is_pokemon_target(&self, pokemon: &Pokemon) -> bool { | ||||
|         unsafe { | ||||
|             executing_move_is_pokemon_target(self.inner.value().reference, pokemon.reference()) | ||||
|         } | ||||
|     } | ||||
|     pub fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> HitData { | ||||
|         unsafe { | ||||
|             executing_move_get_hit_data(self.inner.value().reference, pokemon.reference(), hit) | ||||
|                 .get_value() | ||||
|                 .unwrap() | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct HitData { | ||||
|     reference: ExternRef<HitData>, | ||||
| } | ||||
|  | ||||
| impl HitData { | ||||
|     pub fn is_critical(&self) -> bool { | ||||
|         unsafe { hit_data_is_critical(self.reference) } | ||||
|     } | ||||
|     pub fn base_power(&self) -> u8 { | ||||
|         unsafe { hit_data_get_base_power(self.reference) } | ||||
|     } | ||||
|     pub fn effectiveness(&self) -> f32 { | ||||
|         unsafe { hit_data_get_effectiveness(self.reference) } | ||||
|     } | ||||
|     pub fn damage(&self) -> u32 { | ||||
|         unsafe { hit_data_get_damage(self.reference) } | ||||
|     } | ||||
|     pub fn move_type(&self) -> u8 { | ||||
|         unsafe { hit_data_get_move_type(self.reference) } | ||||
|     } | ||||
|     pub fn has_failed(&self) -> bool { | ||||
|         unsafe { hit_data_is_critical(self.reference) } | ||||
|     } | ||||
|  | ||||
|     pub fn set_critical(&self, critical: bool) { | ||||
|         unsafe { hit_data_set_critical(self.reference, critical) } | ||||
|     } | ||||
|     pub fn set_effectiveness(&self, effectiveness: f32) { | ||||
|         unsafe { hit_data_set_effectiveness(self.reference, effectiveness) } | ||||
|     } | ||||
|     pub fn set_damage(&self, damage: u32) { | ||||
|         unsafe { hit_data_set_damage(self.reference, damage) } | ||||
|     } | ||||
|     pub fn set_move_type(&self, move_type: u8) { | ||||
|         unsafe { hit_data_set_move_type(self.reference, move_type) } | ||||
|     } | ||||
|     pub fn fail(&self) { | ||||
|         unsafe { hit_data_fail(self.reference) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl ExternalReferenceType for ExecutingMove { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
|         Self::new(reference) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl ExternalReferenceType for HitData { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
|         Self { reference } | ||||
|     } | ||||
| } | ||||
|  | ||||
| extern "wasm" { | ||||
|     fn executing_move_get_number_of_targets(r: ExternRef<ExecutingMove>) -> usize; | ||||
|     fn executing_move_get_number_of_hits(r: ExternRef<ExecutingMove>) -> u8; | ||||
|     fn executing_move_get_user(r: ExternRef<ExecutingMove>) -> ExternRef<Pokemon>; | ||||
|     fn executing_move_get_chosen_move(r: ExternRef<ExecutingMove>) -> ExternRef<LearnedMove>; | ||||
|     fn executing_move_get_use_move(r: ExternRef<ExecutingMove>) -> ExternRef<MoveData>; | ||||
|     #[allow(improper_ctypes)] | ||||
|     fn executing_move_get_script(r: ExternRef<ExecutingMove>) -> *const dyn Script; | ||||
|  | ||||
|     fn executing_move_is_pokemon_target( | ||||
|         r: ExternRef<ExecutingMove>, | ||||
|         pokemon: ExternRef<Pokemon>, | ||||
|     ) -> bool; | ||||
|     fn executing_move_get_hit_data( | ||||
|         r: ExternRef<ExecutingMove>, | ||||
|         target: ExternRef<Pokemon>, | ||||
|         hit: u8, | ||||
|     ) -> ExternRef<HitData>; | ||||
|  | ||||
|     fn hit_data_is_critical(r: ExternRef<HitData>) -> bool; | ||||
|     fn hit_data_get_base_power(r: ExternRef<HitData>) -> u8; | ||||
|     fn hit_data_get_effectiveness(r: ExternRef<HitData>) -> f32; | ||||
|     fn hit_data_get_damage(r: ExternRef<HitData>) -> u32; | ||||
|     fn hit_data_get_move_type(r: ExternRef<HitData>) -> u8; | ||||
|     fn hit_data_has_failed(r: ExternRef<HitData>) -> bool; | ||||
|  | ||||
|     fn hit_data_set_critical(r: ExternRef<HitData>, critical: bool); | ||||
|     fn hit_data_set_base_power(r: ExternRef<HitData>, power: u8); | ||||
|     fn hit_data_set_effectiveness(r: ExternRef<HitData>, effectiveness: f32); | ||||
|     fn hit_data_set_damage(r: ExternRef<HitData>, damage: u32); | ||||
|     fn hit_data_set_move_type(r: ExternRef<HitData>, move_type: u8); | ||||
|     fn hit_data_fail(r: ExternRef<HitData>); | ||||
| } | ||||
| @@ -2,7 +2,9 @@ mod battle; | ||||
| mod battle_party; | ||||
| mod battle_random; | ||||
| mod battle_side; | ||||
| mod choice_queue; | ||||
| mod dynamic_library; | ||||
| mod executing_move; | ||||
| mod learned_move; | ||||
| mod party; | ||||
| mod pokemon; | ||||
| @@ -13,7 +15,9 @@ pub use battle::*; | ||||
| pub use battle_party::*; | ||||
| pub use battle_random::*; | ||||
| pub use battle_side::*; | ||||
| pub use choice_queue::*; | ||||
| pub use dynamic_library::DynamicLibrary; | ||||
| pub use executing_move::*; | ||||
| pub use learned_move::*; | ||||
| pub use party::*; | ||||
| pub use pokemon::*; | ||||
|   | ||||
| @@ -7,7 +7,7 @@ use crate::handling::cached_value::CachedValue; | ||||
| use crate::handling::Cacheable; | ||||
| use crate::{ | ||||
|     cached_value, cached_value_getters, wasm_optional_reference_getters, wasm_reference_getters, | ||||
|     wasm_value_getters, DynamicLibrary, ExternRef, ExternalReferenceType, Script, | ||||
|     wasm_value_getters, DynamicLibrary, ExternRef, ExternalReferenceType, Script, TypeIdentifier, | ||||
| }; | ||||
| use alloc::boxed::Box; | ||||
| use alloc::rc::Rc; | ||||
| @@ -61,6 +61,10 @@ impl Pokemon { | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn reference(&self) -> ExternRef<Self> { | ||||
|         self.inner.reference | ||||
|     } | ||||
|  | ||||
|     cached_value_getters! { | ||||
|         pub fn library(&self) -> DynamicLibrary; | ||||
|         pub fn flat_stats(&self) -> StatisticSet<u32>; | ||||
| @@ -101,8 +105,8 @@ impl Pokemon { | ||||
|         unsafe { pokemon_get_type(self.inner.reference, index) } | ||||
|     } | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn has_type(&self, type_identifier: u8) -> bool { | ||||
|         unsafe { pokemon_has_type(self.inner.reference, type_identifier) } | ||||
|     pub fn has_type(&self, type_identifier: TypeIdentifier) -> bool { | ||||
|         unsafe { pokemon_has_type(self.inner.reference, type_identifier.into()) } | ||||
|     } | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn has_type_by_name(&self, type_name: &str) -> bool { | ||||
| @@ -206,6 +210,12 @@ wasm_value_getters! { | ||||
|     pub fn is_usable(&self) -> bool; | ||||
| } | ||||
|  | ||||
| impl PartialEq for Pokemon { | ||||
|     fn eq(&self, other: &Self) -> bool { | ||||
|         self.inner.reference == other.inner.reference | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// A source of damage. This should be as unique as possible. | ||||
| #[derive(Debug, Clone, Copy)] | ||||
| #[repr(u8)] | ||||
| @@ -246,6 +256,7 @@ extern "wasm" { | ||||
|         diff_amount: i8, | ||||
|         self_inflicted: bool, | ||||
|     ) -> bool; | ||||
|     #[allow(improper_ctypes)] | ||||
|     fn pokemon_get_ability_script(r: ExternRef<Pokemon>) -> *const Box<dyn Script>; | ||||
|     fn pokemon_change_species( | ||||
|         r: ExternRef<Pokemon>, | ||||
|   | ||||
| @@ -3,10 +3,9 @@ use crate::handling::cached_value::CachedValue; | ||||
| use crate::handling::temporary::Temporary; | ||||
| use crate::ExternRef; | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| use crate::{cached_value, wasm_value_getters, ExternalReferenceType, Script}; | ||||
| use crate::{cached_value, ExternalReferenceType, Script}; | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| use alloc::boxed::Box; | ||||
| use alloc::rc::Rc; | ||||
|  | ||||
| struct BaseTurnChoiceData { | ||||
|     reference: ExternRef<TurnChoice>, | ||||
| @@ -19,12 +18,10 @@ struct MoveTurnChoiceDataInner { | ||||
|     target_side: CachedValue<u8>, | ||||
|     target_index: CachedValue<u8>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| struct MoveTurnChoiceDataTemporary { | ||||
|     inner: Rc<MoveTurnChoiceDataInner>, | ||||
| } | ||||
| pub struct MoveTurnChoiceData { | ||||
|     temp: Temporary<MoveTurnChoiceDataTemporary>, | ||||
|     inner: Temporary<MoveTurnChoiceDataInner>, | ||||
| } | ||||
|  | ||||
| pub enum TurnChoice { | ||||
| @@ -38,7 +35,7 @@ pub enum TurnChoice { | ||||
| impl TurnChoice { | ||||
|     fn base(&self) -> &BaseTurnChoiceData { | ||||
|         match self { | ||||
|             TurnChoice::Move(d) => &d.temp.value_ref().inner.base, | ||||
|             TurnChoice::Move(d) => &d.inner.value_ref().base, | ||||
|             TurnChoice::Item() => unimplemented!(), | ||||
|             TurnChoice::Switch() => unimplemented!(), | ||||
|             TurnChoice::Flee => unimplemented!(), | ||||
| @@ -68,22 +65,22 @@ impl TurnChoice { | ||||
|  | ||||
| impl MoveTurnChoiceData { | ||||
|     pub fn used_move(&self) -> LearnedMove { | ||||
|         self.temp.value().inner.used_move.value() | ||||
|         self.inner.value().used_move.value() | ||||
|     } | ||||
|     pub fn target_side(&self) -> u8 { | ||||
|         self.temp.value().inner.target_side.value() | ||||
|         self.inner.value().target_side.value() | ||||
|     } | ||||
|     pub fn target_index(&self) -> u8 { | ||||
|         self.temp.value().inner.target_index.value() | ||||
|         self.inner.value().target_index.value() | ||||
|     } | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn priority(&self) -> i8 { | ||||
|         unsafe { turn_choice_move_priority(self.temp.value().inner.base.reference.cast()) } | ||||
|         unsafe { turn_choice_move_priority(self.inner.value().base.reference.cast()) } | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "mock_data"))] | ||||
|     pub fn move_script(&self) -> Option<&Box<dyn Script>> { | ||||
|         unsafe { turn_choice_move_script(self.temp.value().inner.base.reference.cast()).as_ref() } | ||||
|         unsafe { turn_choice_move_script(self.inner.value().base.reference.cast()).as_ref() } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -93,7 +90,10 @@ impl ExternalReferenceType for TurnChoice { | ||||
|         let kind = unsafe { turn_choice_get_kind(reference) }; | ||||
|         match kind { | ||||
|             0 => TurnChoice::Move(MoveTurnChoiceData { | ||||
|                 temp: Temporary::from_reference(reference.cast()), | ||||
|                 inner: Temporary::new( | ||||
|                     reference.get_internal_index(), | ||||
|                     MoveTurnChoiceDataInner::from_reference(reference.cast()), | ||||
|                 ), | ||||
|             }), | ||||
|             _ => panic!("Unknown turn choice type"), | ||||
|         } | ||||
| @@ -101,24 +101,22 @@ impl ExternalReferenceType for TurnChoice { | ||||
| } | ||||
|  | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| impl ExternalReferenceType for MoveTurnChoiceDataTemporary { | ||||
|     fn from_extern_value(reference: ExternRef<Self>) -> Self { | ||||
| impl MoveTurnChoiceDataInner { | ||||
|     fn from_reference(reference: ExternRef<MoveTurnChoiceData>) -> Self { | ||||
|         Self { | ||||
|             inner: Rc::new(MoveTurnChoiceDataInner { | ||||
|                 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() | ||||
|             base: BaseTurnChoiceData { | ||||
|                 reference: reference.cast(), | ||||
|                 user: cached_value!({ | ||||
|                     turn_choice_get_user(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()) }), | ||||
|             }, | ||||
|             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()) }), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -135,14 +133,6 @@ extern "wasm" { | ||||
|     fn turn_choice_move_target_side(r: ExternRef<MoveTurnChoiceData>) -> u8; | ||||
|     fn turn_choice_move_target_index(r: ExternRef<MoveTurnChoiceData>) -> u8; | ||||
|     fn turn_choice_move_priority(r: ExternRef<MoveTurnChoiceData>) -> i8; | ||||
|     #[allow(improper_ctypes)] | ||||
|     fn turn_choice_move_script(r: ExternRef<MoveTurnChoiceData>) -> *const Box<dyn Script>; | ||||
| } | ||||
|  | ||||
| #[no_mangle] | ||||
| #[cfg(not(feature = "mock_data"))] | ||||
| unsafe extern "wasm" fn turn_choice_mark_deleted(r: ExternRef<TurnChoice>, kind: u8) { | ||||
|     match kind { | ||||
|         0 => Temporary::<MoveTurnChoiceDataTemporary>::mark_as_deleted(r.cast()), | ||||
|         _ => panic!("Unknown turn choice type"), | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user