Implements first few actual move effects.

This commit is contained in:
2022-08-28 15:50:12 +02:00
parent 98130706fb
commit 05430c5e84
38 changed files with 1539 additions and 355 deletions

View File

@@ -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>;
}

View File

@@ -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>;

View File

@@ -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;
}

View File

@@ -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>);
}

View File

@@ -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::*;

View File

@@ -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>,

View File

@@ -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"),
}
}