More work on mocking and unit testing
This commit is contained in:
parent
a1e13af793
commit
517c5710d1
|
@ -44,7 +44,7 @@ impl Script for Acrobatics {
|
|||
mod tests {
|
||||
use super::*;
|
||||
use alloc::rc::Rc;
|
||||
use pkmn_lib_interface::app_interface::{Item, MockExecutingMove, MockItem, MockPokemon};
|
||||
use pkmn_lib_interface::app_interface::{MockExecutingMove, MockItem, MockPokemon};
|
||||
|
||||
fn mock_executing_move(has_held_item: bool) -> ExecutingMove {
|
||||
let mut mv = MockExecutingMove::new();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use alloc::boxed::Box;
|
||||
use core::any::Any;
|
||||
use core::mem::transmute;
|
||||
use pkmn_lib_interface::app_interface::{ExecutingMove, Pokemon, Statistic};
|
||||
|
@ -39,3 +38,68 @@ impl Script for Acupressure {
|
|||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use alloc::rc::Rc;
|
||||
use pkmn_lib_interface::app_interface::{
|
||||
MockBattle, MockBattleRandom, MockExecutingMove, MockHitData, MockItem, MockPokemon,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn fails_if_target_is_user() {
|
||||
let mut user = MockPokemon::new();
|
||||
user.expect_equals().return_const(true);
|
||||
let user = Rc::new(user);
|
||||
let u = user.clone();
|
||||
|
||||
let mut mv = MockExecutingMove::new();
|
||||
mv.expect_user().returning_st(move || user.clone());
|
||||
|
||||
let mut hit_data = MockHitData::new();
|
||||
hit_data.expect_fail().once();
|
||||
let hit_data = Rc::new(hit_data);
|
||||
mv.expect_get_hit_data()
|
||||
.returning_st(move |_, _| hit_data.clone());
|
||||
|
||||
let script = Acupressure::new();
|
||||
script.on_secondary_effect(Rc::new(mv), u, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn increases_stat_by_two() {
|
||||
let mut user = MockPokemon::new();
|
||||
user.expect_equals().return_const(false);
|
||||
user.expect_battle().returning_st(move || {
|
||||
let mut battle = MockBattle::new();
|
||||
battle.expect_random().returning_st(move || {
|
||||
let mut random = MockBattleRandom::new();
|
||||
random.expect_get_between().returning_st(|low, high| {
|
||||
assert_eq!(1, low);
|
||||
assert_eq!(6, high);
|
||||
return 1;
|
||||
});
|
||||
Rc::new(random)
|
||||
});
|
||||
Some(Rc::new(battle))
|
||||
});
|
||||
user.expect_change_stat_boost()
|
||||
.once()
|
||||
.returning(|stat, amount, self_inflicted| {
|
||||
assert_eq!(Statistic::Attack, stat);
|
||||
assert_eq!(2, amount);
|
||||
assert_eq!(false, self_inflicted);
|
||||
true
|
||||
});
|
||||
|
||||
let user = Rc::new(user);
|
||||
let u = user.clone();
|
||||
|
||||
let mut mv = MockExecutingMove::new();
|
||||
mv.expect_user().returning_st(move || user.clone());
|
||||
|
||||
let script = Acupressure::new();
|
||||
script.on_secondary_effect(Rc::new(mv), u, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,8 @@ impl Script for AuroraVeil {
|
|||
if target.battle().unwrap().has_weather(Hail::get_const_name()) {
|
||||
return mv.get_hit_data(&target, hit).fail();
|
||||
}
|
||||
let script = target
|
||||
.battle_side()
|
||||
let binding = target.battle_side();
|
||||
let script = binding
|
||||
.add_volatile(Box::new(AuroraVeilEffect::new()))
|
||||
.as_any()
|
||||
.downcast_ref::<AuroraVeilEffect>()
|
||||
|
|
|
@ -14,6 +14,6 @@ spin = { version = "0.9.4", default-features = false, features = ["rwlock"] }
|
|||
paste = { version = "1.0.7" }
|
||||
hashbrown = { version = "0.12.3" }
|
||||
dlmalloc = { version = "0.2.4", features = ["global"] }
|
||||
mockall = { version = "0.11.2", optional = true }
|
||||
mockall = { version = "0.11.2", optional = true, features = ["nightly"] }
|
||||
|
||||
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
use crate::app_interface::{
|
||||
BattleParty, BattlePartyImpl, BattleRandom, BattleRandomImpl, BattleSide, BattleSideImpl,
|
||||
ChoiceQueue, ChoiceQueueImpl, Pokemon, PokemonImpl,
|
||||
};
|
||||
use crate::handling::cached_value::CachedValue;
|
||||
use crate::handling::Cacheable;
|
||||
use crate::{
|
||||
cached_value, cached_value_getters, wasm_value_getters, wasm_value_getters_extern,
|
||||
wasm_value_getters_funcs, DynamicLibrary, ExternRef, ExternalReferenceType, ImmutableList,
|
||||
StringKey, VecExternRef,
|
||||
};
|
||||
use alloc::rc::Rc;
|
||||
|
||||
use crate::app_interface::list::ImmutableList;
|
||||
use crate::app_interface::BattleSideImpl;
|
||||
use crate::app_interface::{
|
||||
BattleParty, BattlePartyImpl, BattleRandom, ChoiceQueue, DynamicLibrary, Pokemon, StringKey,
|
||||
};
|
||||
|
||||
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
||||
pub trait BattleTrait {
|
||||
fn library(&self) -> DynamicLibrary;
|
||||
fn parties(&self) -> ImmutableList<BattlePartyImpl>;
|
||||
|
@ -31,130 +27,157 @@ pub trait BattleTrait {
|
|||
}
|
||||
|
||||
pub type Battle = Rc<dyn BattleTrait>;
|
||||
|
||||
struct BattleInner {
|
||||
reference: ExternRef<BattleImpl>,
|
||||
library: CachedValue<DynamicLibrary>,
|
||||
parties: CachedValue<ImmutableList<BattlePartyImpl>>,
|
||||
sides: CachedValue<ImmutableList<BattleSideImpl>>,
|
||||
random: CachedValue<Rc<BattleRandomImpl>>,
|
||||
choice_queue: CachedValue<Rc<ChoiceQueueImpl>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BattleImpl {
|
||||
inner: Rc<BattleInner>,
|
||||
}
|
||||
#[cfg(feature = "mock_data")]
|
||||
pub type MockBattle = MockBattleTrait;
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl BattleImpl {
|
||||
pub fn new(reference: ExternRef<BattleImpl>) -> Self {
|
||||
Self::from_ref(reference, &|reference| Self {
|
||||
inner: Rc::new(BattleInner {
|
||||
reference,
|
||||
library: cached_value!({ battle_get_library(reference).get_value().unwrap() }),
|
||||
parties: cached_value!({ battle_get_parties(reference).get_immutable_list() }),
|
||||
sides: cached_value!({ battle_get_sides(reference).get_immutable_list() }),
|
||||
random: cached_value!({
|
||||
Rc::new(battle_get_random(reference).get_value().unwrap())
|
||||
mod implementation {
|
||||
use super::*;
|
||||
use crate::app_interface::PokemonImpl;
|
||||
use crate::app_interface::{
|
||||
BattleParty, BattlePartyImpl, BattleRandom, BattleRandomImpl, BattleSide, BattleSideImpl,
|
||||
ChoiceQueue, ChoiceQueueImpl, Pokemon,
|
||||
};
|
||||
use crate::handling::cached_value::CachedValue;
|
||||
use crate::handling::Cacheable;
|
||||
use crate::{
|
||||
cached_value, cached_value_getters, wasm_value_getters, wasm_value_getters_extern,
|
||||
wasm_value_getters_funcs, DynamicLibrary, ExternRef, ExternalReferenceType, ImmutableList,
|
||||
StringKey, VecExternRef,
|
||||
};
|
||||
|
||||
struct BattleInner {
|
||||
reference: ExternRef<BattleImpl>,
|
||||
library: CachedValue<DynamicLibrary>,
|
||||
parties: CachedValue<ImmutableList<BattlePartyImpl>>,
|
||||
sides: CachedValue<ImmutableList<BattleSideImpl>>,
|
||||
random: CachedValue<Rc<BattleRandomImpl>>,
|
||||
choice_queue: CachedValue<Rc<ChoiceQueueImpl>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BattleImpl {
|
||||
inner: Rc<BattleInner>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl BattleImpl {
|
||||
pub fn new(reference: ExternRef<BattleImpl>) -> Self {
|
||||
Self::from_ref(reference, &|reference| Self {
|
||||
inner: Rc::new(BattleInner {
|
||||
reference,
|
||||
library: cached_value!({ battle_get_library(reference).get_value().unwrap() }),
|
||||
parties: cached_value!({ battle_get_parties(reference).get_immutable_list() }),
|
||||
sides: cached_value!({ battle_get_sides(reference).get_immutable_list() }),
|
||||
random: cached_value!({
|
||||
Rc::new(battle_get_random(reference).get_value().unwrap())
|
||||
}),
|
||||
choice_queue: cached_value!({
|
||||
Rc::new(battle_get_choice_queue(reference).get_value().unwrap())
|
||||
}),
|
||||
}),
|
||||
choice_queue: cached_value!({
|
||||
Rc::new(battle_get_choice_queue(reference).get_value().unwrap())
|
||||
}),
|
||||
}),
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl BattleTrait for BattleImpl {
|
||||
cached_value_getters! {
|
||||
fn library(&self) -> DynamicLibrary;
|
||||
fn parties(&self) -> ImmutableList<BattlePartyImpl>;
|
||||
fn sides(&self) -> ImmutableList<BattleSideImpl>;
|
||||
fn random(&self) -> BattleRandom;
|
||||
fn choice_queue(&self) -> ChoiceQueue;
|
||||
}
|
||||
|
||||
fn get_pokemon(&self, side: u8, index: u8) -> Option<Pokemon> {
|
||||
unsafe {
|
||||
let v = battle_get_pokemon(self.inner.reference, side, index).get_value();
|
||||
if let Some(v) = v {
|
||||
Some(Rc::new(v))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> Option<BattleParty> {
|
||||
unsafe {
|
||||
let b =
|
||||
battle_find_party_for_pokemon(self.inner.reference, pokemon.reference().into())
|
||||
.get_value();
|
||||
if let Some(b) = b {
|
||||
Some(Rc::new(b))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn weather_name(&self) -> Option<StringKey> {
|
||||
unsafe { battle_get_weather_name(self.inner.reference).get_value() }
|
||||
}
|
||||
fn has_weather(&self, name: &str) -> bool {
|
||||
if let Some(weather) = self.weather_name() {
|
||||
if weather.eq(name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
wasm_value_getters_funcs! {
|
||||
Battle,
|
||||
fn can_flee(&self) -> bool;
|
||||
fn number_of_sides(&self) -> u8;
|
||||
fn pokemon_per_side(&self) -> u8;
|
||||
fn has_ended(&self) -> bool;
|
||||
fn has_ended_conclusively(&self) -> bool;
|
||||
fn winning_side(&self) -> u8;
|
||||
fn current_turn(&self) -> u32;
|
||||
}
|
||||
}
|
||||
|
||||
wasm_value_getters_extern! {
|
||||
BattleImpl, Battle,
|
||||
pub fn can_flee(&self) -> bool;
|
||||
pub fn number_of_sides(&self) -> u8;
|
||||
pub fn pokemon_per_side(&self) -> u8;
|
||||
pub fn has_ended(&self) -> bool;
|
||||
pub fn has_ended_conclusively(&self) -> bool;
|
||||
pub fn winning_side(&self) -> u8;
|
||||
pub fn current_turn(&self) -> u32;
|
||||
}
|
||||
|
||||
crate::handling::cacheable::cacheable!(BattleImpl);
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl ExternalReferenceType for BattleImpl {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
Self::new(reference)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
extern "wasm" {
|
||||
fn battle_get_library(r: ExternRef<BattleImpl>) -> ExternRef<DynamicLibrary>;
|
||||
fn battle_get_parties(r: ExternRef<BattleImpl>) -> VecExternRef<BattlePartyImpl>;
|
||||
fn battle_get_sides(r: ExternRef<BattleImpl>) -> VecExternRef<BattleSideImpl>;
|
||||
fn battle_get_random(r: ExternRef<BattleImpl>) -> ExternRef<BattleRandomImpl>;
|
||||
fn battle_get_choice_queue(r: ExternRef<BattleImpl>) -> ExternRef<ChoiceQueueImpl>;
|
||||
fn battle_get_pokemon(
|
||||
r: ExternRef<BattleImpl>,
|
||||
side: u8,
|
||||
index: u8,
|
||||
) -> ExternRef<PokemonImpl>;
|
||||
fn battle_find_party_for_pokemon(
|
||||
r: ExternRef<BattleImpl>,
|
||||
mon: ExternRef<PokemonImpl>,
|
||||
) -> ExternRef<BattlePartyImpl>;
|
||||
|
||||
fn battle_get_weather_name(r: ExternRef<BattleImpl>) -> ExternRef<StringKey>;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl BattleTrait for BattleImpl {
|
||||
cached_value_getters! {
|
||||
fn library(&self) -> DynamicLibrary;
|
||||
fn parties(&self) -> ImmutableList<BattlePartyImpl>;
|
||||
fn sides(&self) -> ImmutableList<BattleSideImpl>;
|
||||
fn random(&self) -> BattleRandom;
|
||||
fn choice_queue(&self) -> ChoiceQueue;
|
||||
}
|
||||
|
||||
fn get_pokemon(&self, side: u8, index: u8) -> Option<Pokemon> {
|
||||
unsafe {
|
||||
let v = battle_get_pokemon(self.inner.reference, side, index).get_value();
|
||||
if let Some(v) = v {
|
||||
Some(Rc::new(v))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> Option<BattleParty> {
|
||||
unsafe {
|
||||
let b = battle_find_party_for_pokemon(self.inner.reference, pokemon.reference().into())
|
||||
.get_value();
|
||||
if let Some(b) = b {
|
||||
Some(Rc::new(b))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn weather_name(&self) -> Option<StringKey> {
|
||||
unsafe { battle_get_weather_name(self.inner.reference).get_value() }
|
||||
}
|
||||
fn has_weather(&self, name: &str) -> bool {
|
||||
if let Some(weather) = self.weather_name() {
|
||||
if weather.eq(name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
wasm_value_getters_funcs! {
|
||||
Battle,
|
||||
fn can_flee(&self) -> bool;
|
||||
fn number_of_sides(&self) -> u8;
|
||||
fn pokemon_per_side(&self) -> u8;
|
||||
fn has_ended(&self) -> bool;
|
||||
fn has_ended_conclusively(&self) -> bool;
|
||||
fn winning_side(&self) -> u8;
|
||||
fn current_turn(&self) -> u32;
|
||||
}
|
||||
}
|
||||
|
||||
wasm_value_getters_extern! {
|
||||
BattleImpl, Battle,
|
||||
pub fn can_flee(&self) -> bool;
|
||||
pub fn number_of_sides(&self) -> u8;
|
||||
pub fn pokemon_per_side(&self) -> u8;
|
||||
pub fn has_ended(&self) -> bool;
|
||||
pub fn has_ended_conclusively(&self) -> bool;
|
||||
pub fn winning_side(&self) -> u8;
|
||||
pub fn current_turn(&self) -> u32;
|
||||
}
|
||||
|
||||
crate::handling::cacheable::cacheable!(BattleImpl);
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl ExternalReferenceType for BattleImpl {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
Self::new(reference)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
extern "wasm" {
|
||||
fn battle_get_library(r: ExternRef<BattleImpl>) -> ExternRef<DynamicLibrary>;
|
||||
fn battle_get_parties(r: ExternRef<BattleImpl>) -> VecExternRef<BattlePartyImpl>;
|
||||
fn battle_get_sides(r: ExternRef<BattleImpl>) -> VecExternRef<BattleSideImpl>;
|
||||
fn battle_get_random(r: ExternRef<BattleImpl>) -> ExternRef<BattleRandomImpl>;
|
||||
fn battle_get_choice_queue(r: ExternRef<BattleImpl>) -> ExternRef<ChoiceQueueImpl>;
|
||||
fn battle_get_pokemon(r: ExternRef<BattleImpl>, side: u8, index: u8) -> ExternRef<PokemonImpl>;
|
||||
fn battle_find_party_for_pokemon(
|
||||
r: ExternRef<BattleImpl>,
|
||||
mon: ExternRef<PokemonImpl>,
|
||||
) -> ExternRef<BattlePartyImpl>;
|
||||
|
||||
fn battle_get_weather_name(r: ExternRef<BattleImpl>) -> ExternRef<StringKey>;
|
||||
}
|
||||
pub use implementation::*;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{ExternRef, ExternalReferenceType};
|
||||
use alloc::rc::Rc;
|
||||
|
||||
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
||||
pub trait BattleRandomTrait {
|
||||
fn get(&self) -> i32;
|
||||
fn get_max(&self, max: i32) -> i32;
|
||||
|
@ -8,39 +8,49 @@ pub trait BattleRandomTrait {
|
|||
}
|
||||
|
||||
pub type BattleRandom = Rc<dyn BattleRandomTrait>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BattleRandomImpl {
|
||||
reference: ExternRef<Self>,
|
||||
}
|
||||
#[cfg(feature = "mock_data")]
|
||||
pub type MockBattleRandom = MockBattleRandomTrait;
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl BattleRandomTrait for BattleRandomImpl {
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
fn get(&self) -> i32 {
|
||||
unsafe { battle_random_get(self.reference) }
|
||||
}
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
fn get_max(&self, max: i32) -> i32 {
|
||||
unsafe { battle_random_get_max(self.reference, max) }
|
||||
}
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
fn get_between(&self, min: i32, max: i32) -> i32 {
|
||||
unsafe { battle_random_get_between(self.reference, min, max) }
|
||||
}
|
||||
// TODO: effect_chance()
|
||||
}
|
||||
|
||||
impl ExternalReferenceType for BattleRandomImpl {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
Self { reference }
|
||||
}
|
||||
}
|
||||
pub use implementation::*;
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
extern "wasm" {
|
||||
fn battle_random_get(r: ExternRef<BattleRandomImpl>) -> i32;
|
||||
fn battle_random_get_max(r: ExternRef<BattleRandomImpl>, max: i32) -> i32;
|
||||
fn battle_random_get_between(r: ExternRef<BattleRandomImpl>, min: i32, max: i32) -> i32;
|
||||
mod implementation {
|
||||
use super::*;
|
||||
use crate::{ExternRef, ExternalReferenceType};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BattleRandomImpl {
|
||||
reference: ExternRef<Self>,
|
||||
}
|
||||
|
||||
impl BattleRandomTrait for BattleRandomImpl {
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
fn get(&self) -> i32 {
|
||||
unsafe { battle_random_get(self.reference) }
|
||||
}
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
fn get_max(&self, max: i32) -> i32 {
|
||||
unsafe { battle_random_get_max(self.reference, max) }
|
||||
}
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
fn get_between(&self, min: i32, max: i32) -> i32 {
|
||||
unsafe { battle_random_get_between(self.reference, min, max) }
|
||||
}
|
||||
// TODO: effect_chance()
|
||||
}
|
||||
|
||||
impl ExternalReferenceType for BattleRandomImpl {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
Self { reference }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
extern "wasm" {
|
||||
fn battle_random_get(r: ExternRef<BattleRandomImpl>) -> i32;
|
||||
fn battle_random_get_max(r: ExternRef<BattleRandomImpl>, max: i32) -> i32;
|
||||
fn battle_random_get_between(r: ExternRef<BattleRandomImpl>, min: i32, max: i32) -> i32;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::app_interface::{Battle, BattleImpl, Pokemon, PokemonImpl, WithVolatile};
|
||||
use crate::app_interface::{Battle, Pokemon, WithVolatile};
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
use crate::app_interface::{BattleImpl, PokemonImpl};
|
||||
use crate::handling::cacheable::Cacheable;
|
||||
use crate::handling::cached_value::CachedValue;
|
||||
use crate::{
|
||||
|
@ -20,6 +22,7 @@ pub trait BattleSideTrait: WithVolatile {
|
|||
|
||||
pub type BattleSide = Rc<dyn BattleSideTrait>;
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
struct BattleSideInner {
|
||||
reference: ExternRef<BattleSideImpl>,
|
||||
side_index: CachedValue<u8>,
|
||||
|
@ -29,6 +32,7 @@ struct BattleSideInner {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct BattleSideImpl {
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
inner: Rc<BattleSideInner>,
|
||||
}
|
||||
|
||||
|
@ -82,13 +86,23 @@ impl WithVolatile for BattleSideImpl {
|
|||
battleside_has_volatile(self.inner.reference, script_name.as_ptr())
|
||||
}
|
||||
}
|
||||
fn add_volatile<'a, 'b>(&'a self, script: Box<dyn Script>) -> &'b dyn Script {
|
||||
fn add_volatile(&self, script: Box<dyn Script>) -> &dyn Script {
|
||||
unsafe {
|
||||
battleside_add_volatile(self.inner.reference, ScriptPtr::new(script))
|
||||
.val()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script {
|
||||
unsafe {
|
||||
let ptr = CString::new(script_name).unwrap();
|
||||
battleside_add_volatile_by_name(self.inner.reference, ptr.as_ptr())
|
||||
.val()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_volatile(&self, script: &dyn Script) {
|
||||
unsafe {
|
||||
let name = CString::new(script.get_name()).unwrap();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#[cfg(not(feature = "mock_data"))]
|
||||
use crate::app_interface::PokemonImpl;
|
||||
use crate::{ExternRef, ExternalReferenceType, Pokemon};
|
||||
use alloc::rc::Rc;
|
||||
|
|
|
@ -1,18 +1,11 @@
|
|||
use crate::app_interface::{LearnedMove, MoveData, Pokemon, PokemonImpl};
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
use crate::app_interface::PokemonImpl;
|
||||
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};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::rc::Rc;
|
||||
|
||||
struct ExecutingMoveInner {
|
||||
reference: ExternRef<ExecutingMoveImpl>,
|
||||
number_of_hits: CachedValue<u8>,
|
||||
user: CachedValue<PokemonImpl>,
|
||||
chosen_move: CachedValue<LearnedMove>,
|
||||
use_move: CachedValue<MoveData>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
||||
pub trait ExecutingMoveTrait {
|
||||
fn number_of_hits(&self) -> u8;
|
||||
|
@ -25,84 +18,7 @@ pub trait ExecutingMoveTrait {
|
|||
fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> HitData;
|
||||
}
|
||||
|
||||
pub type ExecutingMove = Rc<dyn ExecutingMoveTrait>;
|
||||
#[cfg(feature = "mock_data")]
|
||||
pub type MockExecutingMove = MockExecutingMoveTrait;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ExecutingMoveImpl {
|
||||
inner: Temporary<ExecutingMoveInner>,
|
||||
}
|
||||
|
||||
impl ExecutingMoveImpl {
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub(crate) fn new(reference: ExternRef<Self>) -> 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()
|
||||
}),
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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 {
|
||||
Rc::new(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(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
||||
pub trait HitDataTrait {
|
||||
fn is_critical(&self) -> bool;
|
||||
fn base_power(&self) -> u8;
|
||||
|
@ -117,96 +33,196 @@ pub trait HitDataTrait {
|
|||
fn fail(&self);
|
||||
}
|
||||
|
||||
pub type ExecutingMove = Rc<dyn ExecutingMoveTrait>;
|
||||
#[cfg(feature = "mock_data")]
|
||||
pub type MockExecutingMove = MockExecutingMoveTrait;
|
||||
|
||||
pub type HitData = Rc<dyn HitDataTrait>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct HitDataImpl {
|
||||
reference: ExternRef<HitDataImpl>,
|
||||
}
|
||||
#[cfg(feature = "mock_data")]
|
||||
pub type MockHitData = MockHitDataTrait;
|
||||
|
||||
#[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) }
|
||||
}
|
||||
}
|
||||
pub use implementation::*;
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl ExternalReferenceType for ExecutingMoveImpl {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
Self::new(reference)
|
||||
mod implementation {
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ExecutingMoveImpl {
|
||||
inner: Temporary<ExecutingMoveInner>,
|
||||
}
|
||||
|
||||
struct ExecutingMoveInner {
|
||||
reference: ExternRef<ExecutingMoveImpl>,
|
||||
number_of_hits: CachedValue<u8>,
|
||||
user: CachedValue<PokemonImpl>,
|
||||
chosen_move: CachedValue<LearnedMove>,
|
||||
use_move: CachedValue<MoveData>,
|
||||
}
|
||||
|
||||
impl ExecutingMoveImpl {
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub(crate) fn new(reference: ExternRef<Self>) -> 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()
|
||||
}),
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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 {
|
||||
Rc::new(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<HitDataImpl>,
|
||||
}
|
||||
|
||||
#[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 {
|
||||
Self::new(reference)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl ExternalReferenceType for HitDataImpl {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
Self { reference }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
extern "wasm" {
|
||||
fn executing_move_get_number_of_targets(r: ExternRef<ExecutingMoveImpl>) -> usize;
|
||||
fn executing_move_get_number_of_hits(r: ExternRef<ExecutingMoveImpl>) -> u8;
|
||||
fn executing_move_get_user(r: ExternRef<ExecutingMoveImpl>) -> ExternRef<PokemonImpl>;
|
||||
fn executing_move_get_chosen_move(
|
||||
r: ExternRef<ExecutingMoveImpl>,
|
||||
) -> ExternRef<LearnedMove>;
|
||||
fn executing_move_get_use_move(r: ExternRef<ExecutingMoveImpl>) -> ExternRef<MoveData>;
|
||||
#[allow(improper_ctypes)]
|
||||
fn executing_move_get_script(r: ExternRef<ExecutingMoveImpl>) -> *const dyn Script;
|
||||
|
||||
fn executing_move_is_pokemon_target(
|
||||
r: ExternRef<ExecutingMoveImpl>,
|
||||
pokemon: ExternRef<PokemonImpl>,
|
||||
) -> bool;
|
||||
fn executing_move_get_hit_data(
|
||||
r: ExternRef<ExecutingMoveImpl>,
|
||||
target: ExternRef<PokemonImpl>,
|
||||
hit: u8,
|
||||
) -> ExternRef<HitDataImpl>;
|
||||
|
||||
fn hit_data_is_critical(r: ExternRef<HitDataImpl>) -> bool;
|
||||
fn hit_data_get_base_power(r: ExternRef<HitDataImpl>) -> u8;
|
||||
fn hit_data_get_effectiveness(r: ExternRef<HitDataImpl>) -> f32;
|
||||
fn hit_data_get_damage(r: ExternRef<HitDataImpl>) -> u32;
|
||||
fn hit_data_get_move_type(r: ExternRef<HitDataImpl>) -> u8;
|
||||
fn hit_data_has_failed(r: ExternRef<HitDataImpl>) -> bool;
|
||||
|
||||
fn hit_data_set_critical(r: ExternRef<HitDataImpl>, critical: bool);
|
||||
fn hit_data_set_base_power(r: ExternRef<HitDataImpl>, power: u8);
|
||||
fn hit_data_set_effectiveness(r: ExternRef<HitDataImpl>, effectiveness: f32);
|
||||
fn hit_data_set_damage(r: ExternRef<HitDataImpl>, damage: u32);
|
||||
fn hit_data_set_move_type(r: ExternRef<HitDataImpl>, move_type: u8);
|
||||
fn hit_data_fail(r: ExternRef<HitDataImpl>);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl ExternalReferenceType for HitDataImpl {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
Self { reference }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
extern "wasm" {
|
||||
fn executing_move_get_number_of_targets(r: ExternRef<ExecutingMoveImpl>) -> usize;
|
||||
fn executing_move_get_number_of_hits(r: ExternRef<ExecutingMoveImpl>) -> u8;
|
||||
fn executing_move_get_user(r: ExternRef<ExecutingMoveImpl>) -> ExternRef<PokemonImpl>;
|
||||
fn executing_move_get_chosen_move(r: ExternRef<ExecutingMoveImpl>) -> ExternRef<LearnedMove>;
|
||||
fn executing_move_get_use_move(r: ExternRef<ExecutingMoveImpl>) -> ExternRef<MoveData>;
|
||||
#[allow(improper_ctypes)]
|
||||
fn executing_move_get_script(r: ExternRef<ExecutingMoveImpl>) -> *const dyn Script;
|
||||
|
||||
fn executing_move_is_pokemon_target(
|
||||
r: ExternRef<ExecutingMoveImpl>,
|
||||
pokemon: ExternRef<PokemonImpl>,
|
||||
) -> bool;
|
||||
fn executing_move_get_hit_data(
|
||||
r: ExternRef<ExecutingMoveImpl>,
|
||||
target: ExternRef<PokemonImpl>,
|
||||
hit: u8,
|
||||
) -> ExternRef<HitDataImpl>;
|
||||
|
||||
fn hit_data_is_critical(r: ExternRef<HitDataImpl>) -> bool;
|
||||
fn hit_data_get_base_power(r: ExternRef<HitDataImpl>) -> u8;
|
||||
fn hit_data_get_effectiveness(r: ExternRef<HitDataImpl>) -> f32;
|
||||
fn hit_data_get_damage(r: ExternRef<HitDataImpl>) -> u32;
|
||||
fn hit_data_get_move_type(r: ExternRef<HitDataImpl>) -> u8;
|
||||
fn hit_data_has_failed(r: ExternRef<HitDataImpl>) -> bool;
|
||||
|
||||
fn hit_data_set_critical(r: ExternRef<HitDataImpl>, critical: bool);
|
||||
fn hit_data_set_base_power(r: ExternRef<HitDataImpl>, power: u8);
|
||||
fn hit_data_set_effectiveness(r: ExternRef<HitDataImpl>, effectiveness: f32);
|
||||
fn hit_data_set_damage(r: ExternRef<HitDataImpl>, damage: u32);
|
||||
fn hit_data_set_move_type(r: ExternRef<HitDataImpl>, move_type: u8);
|
||||
fn hit_data_fail(r: ExternRef<HitDataImpl>);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::app_interface::{Pokemon, PokemonImpl};
|
||||
use crate::app_interface::Pokemon;
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
use crate::app_interface::PokemonImpl;
|
||||
use crate::{ExternRef, ExternalReferenceType};
|
||||
use alloc::rc::Rc;
|
||||
|
||||
|
|
|
@ -1,48 +1,17 @@
|
|||
use crate::app_interface::ability::{Ability, AbilityIndex};
|
||||
use crate::app_interface::{
|
||||
AbilityImpl, Battle, BattleImpl, BattleSide, ClampedStatisticSet, Form, Gender, Item, ItemImpl,
|
||||
LearnedMove, LevelInt, Nature, Species, Statistic, StatisticSet, StatisticSetImpl,
|
||||
};
|
||||
use crate::handling::cached_value::CachedValue;
|
||||
use crate::handling::Cacheable;
|
||||
use crate::{
|
||||
cached_value, cached_value_getters, wasm_optional_reference_getters,
|
||||
wasm_optional_reference_getters_extern, wasm_optional_reference_getters_funcs,
|
||||
wasm_reference_getters, wasm_reference_getters_extern, wasm_reference_getters_funcs,
|
||||
wasm_value_getters, wasm_value_getters_extern, wasm_value_getters_funcs, DynamicLibrary,
|
||||
ExternRef, ExternalReferenceType, Script, ScriptPtr, TypeIdentifier,
|
||||
AbilityImpl, AbilityIndex, Battle, BattleSide, ClampedStatisticSet, DynamicLibrary, Form,
|
||||
Gender, Item, LearnedMove, LevelInt, Nature, Species, Statistic, StatisticSet, TypeIdentifier,
|
||||
WithVolatile,
|
||||
};
|
||||
use crate::handling::Script;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::rc::Rc;
|
||||
use core::any::Any;
|
||||
use cstr_core::{c_char, CString};
|
||||
use cstr_core::c_char;
|
||||
|
||||
struct PokemonInner {
|
||||
reference: ExternRef<PokemonImpl>,
|
||||
library: CachedValue<DynamicLibrary>,
|
||||
// We cache the reference to the data, not the values stored inside, which are dynamic.
|
||||
flat_stats: CachedValue<Rc<StatisticSetImpl<u32>>>,
|
||||
// We cache the reference to the data, not the values stored inside, which are dynamic.
|
||||
stat_boosts: CachedValue<ClampedStatisticSet<i8>>,
|
||||
// We cache the reference to the data, not the values stored inside, which are dynamic.
|
||||
boosted_stats: CachedValue<Rc<StatisticSetImpl<u32>>>,
|
||||
// We cache the reference to the data, not the values stored inside, which are dynamic.
|
||||
individual_values: CachedValue<ClampedStatisticSet<u8>>,
|
||||
// We cache the reference to the data, not the values stored inside, which are dynamic.
|
||||
effort_values: CachedValue<ClampedStatisticSet<u8>>,
|
||||
}
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub use implementation::*;
|
||||
|
||||
pub type Pokemon = Rc<dyn PokemonTrait>;
|
||||
#[cfg(feature = "mock_data")]
|
||||
pub type MockPokemon = MockPokemonTrait;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PokemonImpl {
|
||||
inner: Rc<PokemonInner>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
||||
pub trait PokemonTrait {
|
||||
pub trait PokemonTrait: WithVolatile {
|
||||
fn reference(&self) -> u32;
|
||||
|
||||
fn species(&self) -> Species;
|
||||
|
@ -95,189 +64,437 @@ pub trait PokemonTrait {
|
|||
fn set_weight(&self, weight: f32);
|
||||
fn clear_status(&self);
|
||||
fn battle_side(&self) -> BattleSide;
|
||||
fn add_volatile(&self, script: Box<dyn Script>) -> &dyn Script;
|
||||
fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script;
|
||||
fn remove_volatile(&self, script: &dyn Script);
|
||||
// fn get_volatile<T: Script>(&self, script_name: &str) -> Option<&'static T>
|
||||
// where
|
||||
// T: Script + 'static;
|
||||
|
||||
fn equals(&self, other: &Pokemon) -> bool;
|
||||
}
|
||||
|
||||
pub type Pokemon = Rc<dyn PokemonTrait>;
|
||||
|
||||
/// A source of damage. This should be as unique as possible.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(u8)]
|
||||
pub enum DamageSource {
|
||||
/// The damage is done by a move.
|
||||
MoveDamage = 0,
|
||||
/// The damage is done by something else.
|
||||
Misc = 1,
|
||||
/// The damage is done because of struggling.
|
||||
Struggle = 2,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl PokemonTrait for PokemonImpl {
|
||||
fn reference(&self) -> u32 {
|
||||
self.reference().get_internal_index()
|
||||
mod implementation {
|
||||
use super::*;
|
||||
use cstr_core::CString;
|
||||
|
||||
use crate::app_interface::{BattleImpl, ItemImpl, StatisticSetImpl};
|
||||
use crate::handling::cached_value::CachedValue;
|
||||
use crate::handling::Cacheable;
|
||||
use crate::{
|
||||
cached_value, cached_value_getters, wasm_optional_reference_getters_extern,
|
||||
wasm_optional_reference_getters_funcs, wasm_reference_getters_extern,
|
||||
wasm_reference_getters_funcs, wasm_value_getters_extern, wasm_value_getters_funcs,
|
||||
DynamicLibrary, ExternRef, ExternalReferenceType, Script, ScriptPtr, TypeIdentifier,
|
||||
};
|
||||
|
||||
struct PokemonInner {
|
||||
reference: ExternRef<PokemonImpl>,
|
||||
library: CachedValue<DynamicLibrary>,
|
||||
// We cache the reference to the data, not the values stored inside, which are dynamic.
|
||||
flat_stats: CachedValue<Rc<StatisticSetImpl<u32>>>,
|
||||
// We cache the reference to the data, not the values stored inside, which are dynamic.
|
||||
stat_boosts: CachedValue<ClampedStatisticSet<i8>>,
|
||||
// We cache the reference to the data, not the values stored inside, which are dynamic.
|
||||
boosted_stats: CachedValue<Rc<StatisticSetImpl<u32>>>,
|
||||
// We cache the reference to the data, not the values stored inside, which are dynamic.
|
||||
individual_values: CachedValue<ClampedStatisticSet<u8>>,
|
||||
// We cache the reference to the data, not the values stored inside, which are dynamic.
|
||||
effort_values: CachedValue<ClampedStatisticSet<u8>>,
|
||||
}
|
||||
|
||||
cached_value_getters! {
|
||||
fn library(&self) -> DynamicLibrary;
|
||||
fn flat_stats(&self) -> StatisticSet<u32>;
|
||||
fn stat_boosts(&self) -> ClampedStatisticSet<i8>;
|
||||
fn boosted_stats(&self) -> StatisticSet<u32>;
|
||||
fn individual_values(&self) -> ClampedStatisticSet<u8>;
|
||||
fn effort_values(&self) -> ClampedStatisticSet<u8>;
|
||||
#[derive(Clone)]
|
||||
pub struct PokemonImpl {
|
||||
inner: Rc<PokemonInner>,
|
||||
}
|
||||
|
||||
fn battle(&self) -> Option<Battle> {
|
||||
unsafe {
|
||||
let b = pokemon_get_battle(self.reference()).get_value();
|
||||
if let Some(b) = b {
|
||||
Some(Rc::new(b))
|
||||
} else {
|
||||
None
|
||||
impl PokemonTrait for PokemonImpl {
|
||||
fn reference(&self) -> u32 {
|
||||
self.reference().get_internal_index()
|
||||
}
|
||||
|
||||
cached_value_getters! {
|
||||
fn library(&self) -> DynamicLibrary;
|
||||
fn flat_stats(&self) -> StatisticSet<u32>;
|
||||
fn stat_boosts(&self) -> ClampedStatisticSet<i8>;
|
||||
fn boosted_stats(&self) -> StatisticSet<u32>;
|
||||
fn individual_values(&self) -> ClampedStatisticSet<u8>;
|
||||
fn effort_values(&self) -> ClampedStatisticSet<u8>;
|
||||
}
|
||||
|
||||
fn battle(&self) -> Option<Battle> {
|
||||
unsafe {
|
||||
let b = pokemon_get_battle(self.reference()).get_value();
|
||||
if let Some(b) = b {
|
||||
Some(Rc::new(b))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn has_held_item(&self, name: &str) -> bool {
|
||||
let cstr = CString::new(name).unwrap();
|
||||
unsafe { pokemon_has_held_item(self.inner.reference, cstr.as_ptr()) }
|
||||
}
|
||||
fn set_held_item(&self, item: &Item) -> Option<Item> {
|
||||
unsafe {
|
||||
let i =
|
||||
pokemon_set_held_item(self.inner.reference, item.reference().into()).get_value();
|
||||
if let Some(i) = i {
|
||||
Some(Rc::new(i))
|
||||
} else {
|
||||
None
|
||||
fn has_held_item(&self, name: &str) -> bool {
|
||||
let cstr = CString::new(name).unwrap();
|
||||
unsafe { pokemon_has_held_item(self.inner.reference, cstr.as_ptr()) }
|
||||
}
|
||||
fn set_held_item(&self, item: &Item) -> Option<Item> {
|
||||
unsafe {
|
||||
let i = pokemon_set_held_item(self.inner.reference, item.reference().into())
|
||||
.get_value();
|
||||
if let Some(i) = i {
|
||||
Some(Rc::new(i))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn remove_held_item(&self) -> Option<Item> {
|
||||
unsafe {
|
||||
let i = pokemon_remove_held_item(self.inner.reference).get_value();
|
||||
if let Some(i) = i {
|
||||
Some(Rc::new(i))
|
||||
} else {
|
||||
None
|
||||
fn remove_held_item(&self) -> Option<Item> {
|
||||
unsafe {
|
||||
let i = pokemon_remove_held_item(self.inner.reference).get_value();
|
||||
if let Some(i) = i {
|
||||
Some(Rc::new(i))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn consume_held_item(&self) -> bool {
|
||||
unsafe { pokemon_consume_held_item(self.inner.reference) }
|
||||
}
|
||||
fn max_health(&self) -> u32 {
|
||||
self.boosted_stats().hp()
|
||||
}
|
||||
fn get_type(&self, index: usize) -> u8 {
|
||||
unsafe { pokemon_get_type(self.inner.reference, index) }
|
||||
}
|
||||
fn has_type(&self, type_identifier: TypeIdentifier) -> bool {
|
||||
unsafe { pokemon_has_type(self.inner.reference, type_identifier.into()) }
|
||||
}
|
||||
fn has_type_by_name(&self, type_name: &str) -> bool {
|
||||
let type_identifier = self
|
||||
.library()
|
||||
.data_library()
|
||||
.type_library()
|
||||
.get_type_from_name(type_name);
|
||||
if let Some(type_identifier) = type_identifier {
|
||||
return self.has_type(type_identifier);
|
||||
fn consume_held_item(&self) -> bool {
|
||||
unsafe { pokemon_consume_held_item(self.inner.reference) }
|
||||
}
|
||||
false
|
||||
}
|
||||
fn get_learned_move(&self, index: usize) -> Option<LearnedMove> {
|
||||
unsafe { pokemon_get_learned_move(self.inner.reference, index).get_value() }
|
||||
}
|
||||
fn change_stat_boost(&self, stat: Statistic, diff_amount: i8, self_inflicted: bool) -> bool {
|
||||
unsafe {
|
||||
pokemon_change_stat_boost(self.inner.reference, stat, diff_amount, self_inflicted)
|
||||
fn max_health(&self) -> u32 {
|
||||
self.boosted_stats().hp()
|
||||
}
|
||||
}
|
||||
fn ability_script(&self) -> Option<&Box<dyn Script>> {
|
||||
unsafe { pokemon_get_ability_script(self.inner.reference).as_ref() }
|
||||
}
|
||||
fn change_species(&self, species: Species, form: Form) {
|
||||
unsafe {
|
||||
pokemon_change_species(self.inner.reference, species.reference(), form.reference());
|
||||
fn get_type(&self, index: usize) -> u8 {
|
||||
unsafe { pokemon_get_type(self.inner.reference, index) }
|
||||
}
|
||||
}
|
||||
fn change_form(&self, form: Form) {
|
||||
unsafe {
|
||||
pokemon_change_form(self.inner.reference, form.reference());
|
||||
fn has_type(&self, type_identifier: TypeIdentifier) -> bool {
|
||||
unsafe { pokemon_has_type(self.inner.reference, type_identifier.into()) }
|
||||
}
|
||||
}
|
||||
fn is_fainted(&self) -> bool {
|
||||
self.current_health() == 0
|
||||
}
|
||||
fn damage(&self, damage: u32, source: DamageSource) {
|
||||
unsafe { pokemon_damage(self.inner.reference, damage, source) }
|
||||
}
|
||||
fn heal(&self, amount: u32, allow_revive: bool) -> bool {
|
||||
unsafe { pokemon_heal(self.inner.reference, amount, allow_revive) }
|
||||
}
|
||||
fn set_weight(&self, weight: f32) {
|
||||
unsafe {
|
||||
pokemon_set_weight(self.reference(), weight);
|
||||
fn has_type_by_name(&self, type_name: &str) -> bool {
|
||||
let type_identifier = self
|
||||
.library()
|
||||
.data_library()
|
||||
.type_library()
|
||||
.get_type_from_name(type_name);
|
||||
if let Some(type_identifier) = type_identifier {
|
||||
return self.has_type(type_identifier);
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
fn clear_status(&self) {
|
||||
unsafe {
|
||||
pokemon_clear_status(self.reference());
|
||||
fn get_learned_move(&self, index: usize) -> Option<LearnedMove> {
|
||||
unsafe { pokemon_get_learned_move(self.inner.reference, index).get_value() }
|
||||
}
|
||||
}
|
||||
fn battle_side(&self) -> BattleSide {
|
||||
Rc::new(
|
||||
self.battle()
|
||||
.unwrap()
|
||||
.sides()
|
||||
.get(self.battle_side_index() as u32)
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
fn add_volatile(&self, script: Box<dyn Script>) -> &dyn Script {
|
||||
unsafe {
|
||||
pokemon_add_volatile(self.inner.reference, ScriptPtr::new(script))
|
||||
.val()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script {
|
||||
unsafe {
|
||||
let ptr = CString::new(script_name).unwrap();
|
||||
pokemon_add_volatile_by_name(self.inner.reference, ptr.as_ptr())
|
||||
.val()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
wasm_reference_getters_funcs! {
|
||||
Pokemon,
|
||||
fn species(&self) -> Species;
|
||||
fn form(&self) -> Form;
|
||||
fn active_ability(&self) -> AbilityImpl;
|
||||
fn nature(&self) -> Nature;
|
||||
}
|
||||
|
||||
wasm_optional_reference_getters_funcs! {
|
||||
Pokemon,
|
||||
fn display_species(&self) -> Option<Species>;
|
||||
fn display_form(&self) -> Option<Form>;
|
||||
}
|
||||
|
||||
fn held_item(&self) -> Option<Item> {
|
||||
unsafe {
|
||||
let i = pokemon_get_held_item(self.inner.reference).get_value();
|
||||
if let Some(i) = i {
|
||||
Some(Rc::new(i))
|
||||
} else {
|
||||
None
|
||||
fn change_stat_boost(
|
||||
&self,
|
||||
stat: Statistic,
|
||||
diff_amount: i8,
|
||||
self_inflicted: bool,
|
||||
) -> bool {
|
||||
unsafe {
|
||||
pokemon_change_stat_boost(self.inner.reference, stat, diff_amount, self_inflicted)
|
||||
}
|
||||
}
|
||||
}
|
||||
fn ability_script(&self) -> Option<&Box<dyn Script>> {
|
||||
unsafe { pokemon_get_ability_script(self.inner.reference).as_ref() }
|
||||
}
|
||||
fn change_species(&self, species: Species, form: Form) {
|
||||
unsafe {
|
||||
pokemon_change_species(self.inner.reference, species.reference(), form.reference());
|
||||
}
|
||||
}
|
||||
fn change_form(&self, form: Form) {
|
||||
unsafe {
|
||||
pokemon_change_form(self.inner.reference, form.reference());
|
||||
}
|
||||
}
|
||||
fn is_fainted(&self) -> bool {
|
||||
self.current_health() == 0
|
||||
}
|
||||
fn damage(&self, damage: u32, source: DamageSource) {
|
||||
unsafe { pokemon_damage(self.inner.reference, damage, source) }
|
||||
}
|
||||
fn heal(&self, amount: u32, allow_revive: bool) -> bool {
|
||||
unsafe { pokemon_heal(self.inner.reference, amount, allow_revive) }
|
||||
}
|
||||
fn set_weight(&self, weight: f32) {
|
||||
unsafe {
|
||||
pokemon_set_weight(self.reference(), weight);
|
||||
}
|
||||
}
|
||||
fn clear_status(&self) {
|
||||
unsafe {
|
||||
pokemon_clear_status(self.reference());
|
||||
}
|
||||
}
|
||||
fn battle_side(&self) -> BattleSide {
|
||||
Rc::new(
|
||||
self.battle()
|
||||
.unwrap()
|
||||
.sides()
|
||||
.get(self.battle_side_index() as u32)
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
fn remove_volatile(&self, script: &dyn Script) {
|
||||
unsafe {
|
||||
let name = CString::new(script.get_name()).unwrap();
|
||||
pokemon_remove_volatile(self.inner.reference, name.as_ptr());
|
||||
wasm_reference_getters_funcs! {
|
||||
Pokemon,
|
||||
fn species(&self) -> Species;
|
||||
fn form(&self) -> Form;
|
||||
fn active_ability(&self) -> AbilityImpl;
|
||||
fn nature(&self) -> Nature;
|
||||
}
|
||||
|
||||
wasm_optional_reference_getters_funcs! {
|
||||
Pokemon,
|
||||
fn display_species(&self) -> Option<Species>;
|
||||
fn display_form(&self) -> Option<Form>;
|
||||
}
|
||||
|
||||
fn held_item(&self) -> Option<Item> {
|
||||
unsafe {
|
||||
let i = pokemon_get_held_item(self.inner.reference).get_value();
|
||||
if let Some(i) = i {
|
||||
Some(Rc::new(i))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
wasm_value_getters_funcs! {
|
||||
Pokemon,
|
||||
fn level(&self) -> LevelInt;
|
||||
fn experience(&self) -> u32;
|
||||
fn unique_identifier(&self) -> u32;
|
||||
fn gender(&self) -> Gender;
|
||||
fn coloring(&self) -> u8;
|
||||
fn current_health(&self) -> u32;
|
||||
fn weight(&self) -> f32;
|
||||
fn height(&self) -> f32;
|
||||
fn nickname(&self) -> *const c_char;
|
||||
fn real_ability(&self) -> AbilityIndex;
|
||||
fn types_length(&self) -> usize;
|
||||
fn battle_side_index(&self) -> u8;
|
||||
fn battle_index(&self) -> u8;
|
||||
fn is_ability_overriden(&self) -> u8;
|
||||
fn allowed_experience_gain(&self) -> bool;
|
||||
fn is_usable(&self) -> bool;
|
||||
}
|
||||
|
||||
fn equals(&self, other: &Pokemon) -> bool {
|
||||
self.inner
|
||||
.reference
|
||||
.get_internal_index()
|
||||
.eq(&other.reference())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
wasm_value_getters_funcs! {
|
||||
Pokemon,
|
||||
impl WithVolatile for PokemonImpl {
|
||||
fn has_volatile(&self, script_name: &str) -> bool {
|
||||
unsafe {
|
||||
let ptr = CString::new(script_name).unwrap();
|
||||
pokemon_has_volatile(self.inner.reference, ptr.as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
fn add_volatile(&self, script: Box<dyn Script>) -> &dyn Script {
|
||||
unsafe {
|
||||
pokemon_add_volatile(self.inner.reference, ScriptPtr::new(script))
|
||||
.val()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script {
|
||||
unsafe {
|
||||
let ptr = CString::new(script_name).unwrap();
|
||||
pokemon_add_volatile_by_name(self.inner.reference, ptr.as_ptr())
|
||||
.val()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_volatile(&self, script: &dyn Script) {
|
||||
unsafe {
|
||||
let name = CString::new(script.get_name()).unwrap();
|
||||
pokemon_remove_volatile(self.inner.reference, name.as_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
fn get_volatile_script(&self, script_name: &str) -> Option<&dyn Script> {
|
||||
unsafe {
|
||||
let script_name = CString::new(script_name).unwrap();
|
||||
pokemon_get_volatile(self.inner.reference, script_name.as_ptr()).val()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl PokemonImpl {
|
||||
pub(crate) fn new(reference: ExternRef<Self>) -> Self {
|
||||
Self::from_ref(reference, &|reference| Self {
|
||||
inner: Rc::new(PokemonInner {
|
||||
reference,
|
||||
library: cached_value!({ pokemon_get_library(reference).get_value().unwrap() }),
|
||||
flat_stats: cached_value!({
|
||||
Rc::new(pokemon_get_flat_stats(reference).get_value().unwrap())
|
||||
}),
|
||||
stat_boosts: cached_value!({
|
||||
pokemon_get_stat_boosts(reference).get_value().unwrap()
|
||||
}),
|
||||
boosted_stats: cached_value!({
|
||||
Rc::new(pokemon_get_boosted_stats(reference).get_value().unwrap())
|
||||
}),
|
||||
individual_values: cached_value!({
|
||||
pokemon_get_individual_values(reference)
|
||||
.get_value()
|
||||
.unwrap()
|
||||
}),
|
||||
effort_values: cached_value!({
|
||||
pokemon_get_effort_values(reference).get_value().unwrap()
|
||||
}),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn reference(&self) -> ExternRef<Self> {
|
||||
self.inner.reference
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
wasm_reference_getters_extern! {
|
||||
PokemonImpl, Pokemon,
|
||||
pub fn species(&self) -> Species;
|
||||
pub fn form(&self) -> Form;
|
||||
pub fn active_ability(&self) -> AbilityImpl;
|
||||
pub fn nature(&self) -> Nature;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
wasm_optional_reference_getters_extern! {
|
||||
PokemonImpl, Pokemon,
|
||||
pub fn display_species(&self) -> Option<Species>;
|
||||
pub fn display_form(&self) -> Option<Form>;
|
||||
pub fn held_item(&self) -> Option<ItemImpl>;
|
||||
pub fn battle(&self) -> Option<BattleImpl>;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
wasm_value_getters_extern! {
|
||||
PokemonImpl, Pokemon,
|
||||
pub fn level(&self) -> LevelInt;
|
||||
pub fn experience(&self) -> u32;
|
||||
pub fn unique_identifier(&self) -> u32;
|
||||
pub fn gender(&self) -> Gender;
|
||||
pub fn coloring(&self) -> u8;
|
||||
pub fn current_health(&self) -> u32;
|
||||
pub fn weight(&self) -> f32;
|
||||
pub fn height(&self) -> f32;
|
||||
pub fn nickname(&self) -> *const c_char;
|
||||
pub fn real_ability(&self) -> AbilityIndex;
|
||||
pub fn types_length(&self) -> usize;
|
||||
pub fn battle_side_index(&self) -> u8;
|
||||
pub fn battle_index(&self) -> u8;
|
||||
pub fn is_ability_overriden(&self) -> u8;
|
||||
pub fn allowed_experience_gain(&self) -> bool;
|
||||
pub fn is_usable(&self) -> bool;
|
||||
}
|
||||
|
||||
impl PartialEq for PokemonImpl {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner.reference == other.inner.reference
|
||||
}
|
||||
}
|
||||
|
||||
crate::handling::cacheable::cacheable!(PokemonImpl);
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl ExternalReferenceType for PokemonImpl {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
Self::new(reference)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
extern "wasm" {
|
||||
fn pokemon_get_library(r: ExternRef<PokemonImpl>) -> ExternRef<DynamicLibrary>;
|
||||
fn pokemon_get_flat_stats(r: ExternRef<PokemonImpl>) -> ExternRef<StatisticSetImpl<u32>>;
|
||||
fn pokemon_get_stat_boosts(r: ExternRef<PokemonImpl>)
|
||||
-> ExternRef<ClampedStatisticSet<i8>>;
|
||||
fn pokemon_get_boosted_stats(r: ExternRef<PokemonImpl>)
|
||||
-> ExternRef<StatisticSetImpl<u32>>;
|
||||
fn pokemon_get_individual_values(
|
||||
r: ExternRef<PokemonImpl>,
|
||||
) -> ExternRef<ClampedStatisticSet<u8>>;
|
||||
fn pokemon_get_effort_values(
|
||||
r: ExternRef<PokemonImpl>,
|
||||
) -> ExternRef<ClampedStatisticSet<u8>>;
|
||||
fn pokemon_has_held_item(r: ExternRef<PokemonImpl>, name: *const c_char) -> bool;
|
||||
fn pokemon_set_held_item(
|
||||
r: ExternRef<PokemonImpl>,
|
||||
item: ExternRef<ItemImpl>,
|
||||
) -> ExternRef<ItemImpl>;
|
||||
fn pokemon_remove_held_item(r: ExternRef<PokemonImpl>) -> ExternRef<ItemImpl>;
|
||||
fn pokemon_consume_held_item(r: ExternRef<PokemonImpl>) -> bool;
|
||||
fn pokemon_get_type(r: ExternRef<PokemonImpl>, index: usize) -> u8;
|
||||
fn pokemon_has_type(r: ExternRef<PokemonImpl>, identifier: u8) -> bool;
|
||||
fn pokemon_get_learned_move(
|
||||
r: ExternRef<PokemonImpl>,
|
||||
index: usize,
|
||||
) -> ExternRef<LearnedMove>;
|
||||
fn pokemon_change_stat_boost(
|
||||
r: ExternRef<PokemonImpl>,
|
||||
tat: Statistic,
|
||||
diff_amount: i8,
|
||||
self_inflicted: bool,
|
||||
) -> bool;
|
||||
#[allow(improper_ctypes)]
|
||||
fn pokemon_get_ability_script(r: ExternRef<PokemonImpl>) -> *const Box<dyn Script>;
|
||||
fn pokemon_change_species(
|
||||
r: ExternRef<PokemonImpl>,
|
||||
species: ExternRef<Species>,
|
||||
form: ExternRef<Form>,
|
||||
);
|
||||
fn pokemon_change_form(r: ExternRef<PokemonImpl>, form: ExternRef<Form>);
|
||||
fn pokemon_damage(r: ExternRef<PokemonImpl>, damage: u32, source: DamageSource);
|
||||
fn pokemon_heal(r: ExternRef<PokemonImpl>, amount: u32, allow_revive: bool) -> bool;
|
||||
fn pokemon_set_weight(r: ExternRef<PokemonImpl>, weight: f32);
|
||||
fn pokemon_clear_status(r: ExternRef<PokemonImpl>);
|
||||
|
||||
fn pokemon_add_volatile_by_name(
|
||||
r: ExternRef<PokemonImpl>,
|
||||
name: *const c_char,
|
||||
) -> ScriptPtr;
|
||||
fn pokemon_add_volatile(r: ExternRef<PokemonImpl>, script: ScriptPtr) -> ScriptPtr;
|
||||
fn pokemon_has_volatile(r: ExternRef<PokemonImpl>, name: *const c_char) -> bool;
|
||||
fn pokemon_remove_volatile(r: ExternRef<PokemonImpl>, name: *const c_char);
|
||||
fn pokemon_get_volatile(r: ExternRef<PokemonImpl>, name: *const c_char) -> ScriptPtr;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mock_data")]
|
||||
mockall::mock!(
|
||||
pub Pokemon {}
|
||||
impl PokemonTrait for Pokemon {
|
||||
fn reference(&self) -> u32;
|
||||
fn species(&self) -> Species;
|
||||
fn form(&self) -> Form;
|
||||
fn active_ability(&self) -> AbilityImpl;
|
||||
fn nature(&self) -> Nature;
|
||||
fn display_species(&self) -> Option<Species>;
|
||||
fn display_form(&self) -> Option<Form>;
|
||||
fn held_item(&self) -> Option<Item>;
|
||||
fn battle(&self) -> Option<Battle>;
|
||||
fn level(&self) -> LevelInt;
|
||||
fn experience(&self) -> u32;
|
||||
fn unique_identifier(&self) -> u32;
|
||||
|
@ -294,172 +511,51 @@ impl PokemonTrait for PokemonImpl {
|
|||
fn is_ability_overriden(&self) -> u8;
|
||||
fn allowed_experience_gain(&self) -> bool;
|
||||
fn is_usable(&self) -> bool;
|
||||
}
|
||||
|
||||
fn equals(&self, other: &Pokemon) -> bool {
|
||||
self.inner
|
||||
.reference
|
||||
.get_internal_index()
|
||||
.eq(&other.reference())
|
||||
fn library(&self) -> DynamicLibrary;
|
||||
fn flat_stats(&self) -> StatisticSet<u32>;
|
||||
fn stat_boosts(&self) -> ClampedStatisticSet<i8>;
|
||||
fn boosted_stats(&self) -> StatisticSet<u32>;
|
||||
fn individual_values(&self) -> ClampedStatisticSet<u8>;
|
||||
fn effort_values(&self) -> ClampedStatisticSet<u8>;
|
||||
fn has_held_item(&self, name: &str) -> bool;
|
||||
fn set_held_item(&self, item: &Item) -> Option<Item>;
|
||||
fn remove_held_item(&self) -> Option<Item>;
|
||||
fn consume_held_item(&self) -> bool;
|
||||
fn max_health(&self) -> u32;
|
||||
fn get_type(&self, index: usize) -> u8;
|
||||
fn has_type(&self, type_identifier: TypeIdentifier) -> bool;
|
||||
fn has_type_by_name(&self, type_name: &str) -> bool;
|
||||
fn get_learned_move(&self, index: usize) -> Option<LearnedMove>;
|
||||
fn change_stat_boost(&self, stat: Statistic, diff_amount: i8, self_inflicted: bool) -> bool;
|
||||
fn ability_script<'a>(&'a self) -> Option<&'a Box<dyn Script>>;
|
||||
fn change_species(&self, species: Species, form: Form);
|
||||
fn change_form(&self, form: Form);
|
||||
fn is_fainted(&self) -> bool;
|
||||
fn damage(&self, damage: u32, source: DamageSource);
|
||||
fn heal(&self, amount: u32, allow_revive: bool) -> bool;
|
||||
fn set_weight(&self, weight: f32);
|
||||
fn clear_status(&self);
|
||||
fn battle_side(&self) -> BattleSide;
|
||||
fn equals(&self, other: &Pokemon) -> bool;
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(feature = "mock_data")]
|
||||
impl WithVolatile for MockPokemon {
|
||||
fn has_volatile(&self, script_name: &str) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
fn add_volatile(&self, script: Box<dyn Script>) -> &dyn Script {
|
||||
unimplemented!()
|
||||
}
|
||||
fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script {
|
||||
unimplemented!()
|
||||
}
|
||||
fn remove_volatile<'a, 'b>(&'a self, script: &dyn Script) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn get_volatile_script<'a>(&'a self, script_name: &str) -> Option<&'a dyn Script> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl PokemonImpl {
|
||||
pub(crate) fn new(reference: ExternRef<Self>) -> Self {
|
||||
Self::from_ref(reference, &|reference| Self {
|
||||
inner: Rc::new(PokemonInner {
|
||||
reference,
|
||||
library: cached_value!({ pokemon_get_library(reference).get_value().unwrap() }),
|
||||
flat_stats: cached_value!({
|
||||
Rc::new(pokemon_get_flat_stats(reference).get_value().unwrap())
|
||||
}),
|
||||
stat_boosts: cached_value!({
|
||||
pokemon_get_stat_boosts(reference).get_value().unwrap()
|
||||
}),
|
||||
boosted_stats: cached_value!({
|
||||
Rc::new(pokemon_get_boosted_stats(reference).get_value().unwrap())
|
||||
}),
|
||||
individual_values: cached_value!({
|
||||
pokemon_get_individual_values(reference)
|
||||
.get_value()
|
||||
.unwrap()
|
||||
}),
|
||||
effort_values: cached_value!({
|
||||
pokemon_get_effort_values(reference).get_value().unwrap()
|
||||
}),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn reference(&self) -> ExternRef<Self> {
|
||||
self.inner.reference
|
||||
}
|
||||
|
||||
fn get_volatile<T>(&self, script_name: &str) -> Option<&T>
|
||||
where
|
||||
T: Script + 'static,
|
||||
{
|
||||
unsafe {
|
||||
let script_name = CString::new(script_name).unwrap();
|
||||
let s = pokemon_get_volatile(self.inner.reference, script_name.as_ptr()).val();
|
||||
if let Some(s) = s {
|
||||
Some(s.as_any().downcast_ref().unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
wasm_reference_getters_extern! {
|
||||
PokemonImpl, Pokemon,
|
||||
pub fn species(&self) -> Species;
|
||||
pub fn form(&self) -> Form;
|
||||
pub fn active_ability(&self) -> AbilityImpl;
|
||||
pub fn nature(&self) -> Nature;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
wasm_optional_reference_getters_extern! {
|
||||
PokemonImpl, Pokemon,
|
||||
pub fn display_species(&self) -> Option<Species>;
|
||||
pub fn display_form(&self) -> Option<Form>;
|
||||
pub fn held_item(&self) -> Option<ItemImpl>;
|
||||
pub fn battle(&self) -> Option<BattleImpl>;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
wasm_value_getters_extern! {
|
||||
PokemonImpl, Pokemon,
|
||||
pub fn level(&self) -> LevelInt;
|
||||
pub fn experience(&self) -> u32;
|
||||
pub fn unique_identifier(&self) -> u32;
|
||||
pub fn gender(&self) -> Gender;
|
||||
pub fn coloring(&self) -> u8;
|
||||
pub fn current_health(&self) -> u32;
|
||||
pub fn weight(&self) -> f32;
|
||||
pub fn height(&self) -> f32;
|
||||
pub fn nickname(&self) -> *const c_char;
|
||||
pub fn real_ability(&self) -> AbilityIndex;
|
||||
pub fn types_length(&self) -> usize;
|
||||
pub fn battle_side_index(&self) -> u8;
|
||||
pub fn battle_index(&self) -> u8;
|
||||
pub fn is_ability_overriden(&self) -> u8;
|
||||
pub fn allowed_experience_gain(&self) -> bool;
|
||||
pub fn is_usable(&self) -> bool;
|
||||
}
|
||||
|
||||
impl PartialEq for PokemonImpl {
|
||||
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)]
|
||||
pub enum DamageSource {
|
||||
/// The damage is done by a move.
|
||||
MoveDamage = 0,
|
||||
/// The damage is done by something else.
|
||||
Misc = 1,
|
||||
/// The damage is done because of struggling.
|
||||
Struggle = 2,
|
||||
}
|
||||
|
||||
crate::handling::cacheable::cacheable!(PokemonImpl);
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl ExternalReferenceType for PokemonImpl {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
Self::new(reference)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
extern "wasm" {
|
||||
fn pokemon_get_library(r: ExternRef<PokemonImpl>) -> ExternRef<DynamicLibrary>;
|
||||
fn pokemon_get_flat_stats(r: ExternRef<PokemonImpl>) -> ExternRef<StatisticSetImpl<u32>>;
|
||||
fn pokemon_get_stat_boosts(r: ExternRef<PokemonImpl>) -> ExternRef<ClampedStatisticSet<i8>>;
|
||||
fn pokemon_get_boosted_stats(r: ExternRef<PokemonImpl>) -> ExternRef<StatisticSetImpl<u32>>;
|
||||
fn pokemon_get_individual_values(
|
||||
r: ExternRef<PokemonImpl>,
|
||||
) -> ExternRef<ClampedStatisticSet<u8>>;
|
||||
fn pokemon_get_effort_values(r: ExternRef<PokemonImpl>) -> ExternRef<ClampedStatisticSet<u8>>;
|
||||
fn pokemon_has_held_item(r: ExternRef<PokemonImpl>, name: *const c_char) -> bool;
|
||||
fn pokemon_set_held_item(
|
||||
r: ExternRef<PokemonImpl>,
|
||||
item: ExternRef<ItemImpl>,
|
||||
) -> ExternRef<ItemImpl>;
|
||||
fn pokemon_remove_held_item(r: ExternRef<PokemonImpl>) -> ExternRef<ItemImpl>;
|
||||
fn pokemon_consume_held_item(r: ExternRef<PokemonImpl>) -> bool;
|
||||
fn pokemon_get_type(r: ExternRef<PokemonImpl>, index: usize) -> u8;
|
||||
fn pokemon_has_type(r: ExternRef<PokemonImpl>, identifier: u8) -> bool;
|
||||
fn pokemon_get_learned_move(r: ExternRef<PokemonImpl>, index: usize) -> ExternRef<LearnedMove>;
|
||||
fn pokemon_change_stat_boost(
|
||||
r: ExternRef<PokemonImpl>,
|
||||
tat: Statistic,
|
||||
diff_amount: i8,
|
||||
self_inflicted: bool,
|
||||
) -> bool;
|
||||
#[allow(improper_ctypes)]
|
||||
fn pokemon_get_ability_script(r: ExternRef<PokemonImpl>) -> *const Box<dyn Script>;
|
||||
fn pokemon_change_species(
|
||||
r: ExternRef<PokemonImpl>,
|
||||
species: ExternRef<Species>,
|
||||
form: ExternRef<Form>,
|
||||
);
|
||||
fn pokemon_change_form(r: ExternRef<PokemonImpl>, form: ExternRef<Form>);
|
||||
fn pokemon_damage(r: ExternRef<PokemonImpl>, damage: u32, source: DamageSource);
|
||||
fn pokemon_heal(r: ExternRef<PokemonImpl>, amount: u32, allow_revive: bool) -> bool;
|
||||
fn pokemon_set_weight(r: ExternRef<PokemonImpl>, weight: f32);
|
||||
fn pokemon_clear_status(r: ExternRef<PokemonImpl>);
|
||||
|
||||
fn pokemon_add_volatile_by_name(r: ExternRef<PokemonImpl>, name: *const c_char) -> ScriptPtr;
|
||||
fn pokemon_add_volatile(r: ExternRef<PokemonImpl>, script: ScriptPtr) -> ScriptPtr;
|
||||
fn pokemon_has_volatile(r: ExternRef<PokemonImpl>, name: *const c_char) -> bool;
|
||||
fn pokemon_remove_volatile(r: ExternRef<PokemonImpl>, name: *const c_char);
|
||||
fn pokemon_get_volatile(r: ExternRef<PokemonImpl>, name: *const c_char) -> ScriptPtr;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::app_interface::{LearnedMove, Pokemon, PokemonImpl};
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
use crate::app_interface::PokemonImpl;
|
||||
use crate::app_interface::{LearnedMove, Pokemon};
|
||||
use crate::handling::cached_value::CachedValue;
|
||||
use crate::handling::temporary::Temporary;
|
||||
use crate::ExternRef;
|
||||
|
@ -14,6 +16,7 @@ pub trait BaseTurnChoiceDataTrait {
|
|||
fn fail(&self);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
struct BaseTurnChoiceDataImpl {
|
||||
reference: ExternRef<TurnChoice>,
|
||||
user: CachedValue<Rc<PokemonImpl>>,
|
||||
|
|
|
@ -3,7 +3,8 @@ use alloc::boxed::Box;
|
|||
|
||||
pub trait WithVolatile {
|
||||
fn has_volatile(&self, script_name: &str) -> bool;
|
||||
fn add_volatile<'a, 'b>(&'a self, script: Box<dyn Script>) -> &'b dyn Script;
|
||||
fn add_volatile(&self, script: Box<dyn Script>) -> &dyn Script;
|
||||
fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script;
|
||||
fn remove_volatile(&self, script: &dyn Script);
|
||||
fn get_volatile_script(&self, script_name: &str) -> Option<&dyn Script>;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use alloc::vec::Vec;
|
|||
use spin::RwLock;
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Eq, PartialEq)]
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub enum Gender {
|
||||
Male = 0,
|
||||
Female = 1,
|
||||
|
@ -18,6 +18,7 @@ pub enum Gender {
|
|||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
pub enum Statistic {
|
||||
HP = 0,
|
||||
Attack = 1,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::app_interface::list::ImmutableList;
|
||||
use crate::app_interface::{
|
||||
Battle, BattleImpl, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Item,
|
||||
Pokemon, Statistic,
|
||||
Battle, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Item, Pokemon, Statistic,
|
||||
};
|
||||
use crate::handling::ScriptCapabilities;
|
||||
use crate::{ExternRef, ExternalReferenceType, ScriptPtr, StringKey, TurnChoice, TypeIdentifier};
|
||||
|
|
|
@ -23,10 +23,13 @@ extern crate dlmalloc;
|
|||
static ALLOC: dlmalloc::GlobalDlmalloc = dlmalloc::GlobalDlmalloc {};
|
||||
|
||||
use crate::app_interface::list::ImmutableList;
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
use crate::app_interface::{BattleImpl, ExecutingMoveImpl, PokemonImpl};
|
||||
use crate::app_interface::{
|
||||
BattleImpl, DamageSource, DynamicLibrary, EffectParameter, ExecutingMoveImpl, Item, ItemImpl,
|
||||
Pokemon, PokemonImpl, Statistic, StringKey, TurnChoice, TypeIdentifier,
|
||||
DamageSource, DynamicLibrary, EffectParameter, Item, ItemImpl, Pokemon, Statistic, StringKey,
|
||||
TurnChoice, TypeIdentifier,
|
||||
};
|
||||
|
||||
pub(crate) use crate::handling::extern_ref::*;
|
||||
use crate::handling::ffi_array::FFIArray;
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use alloc::alloc::alloc;
|
||||
use alloc::string::String;
|
||||
use core::alloc::Layout;
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
use core::panic::PanicInfo;
|
||||
|
@ -22,9 +23,9 @@ pub fn print_raw(s: &[u8]) {
|
|||
}
|
||||
|
||||
#[cfg(feature = "mock_data")]
|
||||
pub fn print_raw(s: CString) {
|
||||
pub fn print_raw(s: &[u8]) {
|
||||
unsafe {
|
||||
println!("{}", s.into_string().unwrap());
|
||||
println!("{}", String::from_utf8_lossy(s));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue