Rework in line with PkmnLib for moving towards Result
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
2df5feab26
commit
5e0bd632b9
|
@ -12,3 +12,6 @@ opt-level = "s"
|
||||||
lto = false
|
lto = false
|
||||||
debug-assertions = true
|
debug-assertions = true
|
||||||
|
|
||||||
|
[profile.release.package."*"]
|
||||||
|
opt-level = "s"
|
||||||
|
debug-assertions = false
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
pub use crate::script;
|
pub use crate::script;
|
||||||
pub use alloc::boxed::Box;
|
pub use alloc::boxed::Box;
|
||||||
pub use alloc::rc::Rc;
|
pub use alloc::rc::Rc;
|
||||||
|
pub use alloc::vec::Vec;
|
||||||
pub use atomic_float::AtomicF32;
|
pub use atomic_float::AtomicF32;
|
||||||
pub use core::any::Any;
|
pub use core::any::Any;
|
||||||
pub use core::sync::atomic::{AtomicBool, AtomicI8, AtomicU32, Ordering};
|
pub use core::sync::atomic::{AtomicBool, AtomicI8, AtomicU32, Ordering};
|
||||||
pub use pkmn_lib_interface::app_interface::list::ImmutableList;
|
|
||||||
pub use pkmn_lib_interface::app_interface::{
|
pub use pkmn_lib_interface::app_interface::{
|
||||||
get_volatile_as, BattleSide, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove,
|
get_volatile_as, BattleSide, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove,
|
||||||
Gender, MoveCategory, MoveData, Party, Pokemon, Statistic, StringKey, TurnChoice,
|
Gender, MoveCategory, MoveData, Party, Pokemon, Statistic, StringKey, TurnChoice,
|
||||||
};
|
};
|
||||||
pub use pkmn_lib_interface::handling::{Script, ScriptCapabilities, ScriptOwner};
|
pub use pkmn_lib_interface::handling::{Script, ScriptCapabilities, ScriptOwner};
|
||||||
|
pub use pkmn_lib_interface::PkmnResult;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::common_usings::*;
|
use crate::common_usings::*;
|
||||||
|
use pkmn_lib_interface::PkmnResult;
|
||||||
|
|
||||||
script!(Acrobatics, "acrobatics");
|
script!(Acrobatics, "acrobatics");
|
||||||
|
|
||||||
|
@ -21,14 +22,15 @@ impl Script for Acrobatics {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
base_power: &mut u8,
|
base_power: &mut u8,
|
||||||
) {
|
) -> PkmnResult<()> {
|
||||||
if mv.user().held_item().is_none() {
|
if mv.user().held_item()?.is_none() {
|
||||||
if *base_power >= 128_u8 {
|
if *base_power >= 128_u8 {
|
||||||
*base_power = 255
|
*base_power = 255
|
||||||
} else {
|
} else {
|
||||||
*base_power *= 2;
|
*base_power *= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
@ -47,11 +49,11 @@ mod tests {
|
||||||
mv.expect_user().returning(move || {
|
mv.expect_user().returning(move || {
|
||||||
let mut user = MockPokemon::new();
|
let mut user = MockPokemon::new();
|
||||||
user.expect_held_item().returning(move || {
|
user.expect_held_item().returning(move || {
|
||||||
if has_held_item {
|
Ok(if has_held_item {
|
||||||
Some(Rc::new(MockItem::new()))
|
Some(Rc::new(MockItem::new()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
})
|
||||||
});
|
});
|
||||||
Rc::new(user)
|
Rc::new(user)
|
||||||
});
|
});
|
||||||
|
@ -64,7 +66,9 @@ mod tests {
|
||||||
|
|
||||||
let script = Acrobatics::new();
|
let script = Acrobatics::new();
|
||||||
let mut base_power = 50u8;
|
let mut base_power = 50u8;
|
||||||
script.change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power);
|
script
|
||||||
|
.change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(100, base_power);
|
assert_eq!(100, base_power);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +78,9 @@ mod tests {
|
||||||
|
|
||||||
let script = Acrobatics::new();
|
let script = Acrobatics::new();
|
||||||
let mut base_power = 200u8;
|
let mut base_power = 200u8;
|
||||||
script.change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power);
|
script
|
||||||
|
.change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(255, base_power);
|
assert_eq!(255, base_power);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +90,9 @@ mod tests {
|
||||||
|
|
||||||
let script = Acrobatics::new();
|
let script = Acrobatics::new();
|
||||||
let mut base_power = 50u8;
|
let mut base_power = 50u8;
|
||||||
script.change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power);
|
script
|
||||||
|
.change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(50, base_power);
|
assert_eq!(50, base_power);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::common_usings::*;
|
use crate::common_usings::*;
|
||||||
use core::mem::transmute;
|
use core::mem::transmute;
|
||||||
|
use pkmn_lib_interface::PkmnResult;
|
||||||
|
|
||||||
pub struct Acupressure {}
|
pub struct Acupressure {}
|
||||||
|
|
||||||
|
@ -22,14 +23,15 @@ impl Script for Acupressure {
|
||||||
&[ScriptCapabilities::OnSecondaryEffect]
|
&[ScriptCapabilities::OnSecondaryEffect]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) {
|
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) -> PkmnResult<()> {
|
||||||
if target.equals(&mv.user()) {
|
if target.equals(&mv.user()) {
|
||||||
mv.get_hit_data(&target, hit).fail();
|
mv.get_hit_data(&target, hit)?.fail()?;
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
let rand_stat: Statistic =
|
let rand_stat: Statistic =
|
||||||
unsafe { transmute(target.battle().unwrap().random().get_between(1, 6) as u8) };
|
unsafe { transmute(target.battle()?.unwrap().random().get_between(1, 6)? as u8) };
|
||||||
target.change_stat_boost(rand_stat, 2, false);
|
target.change_stat_boost(rand_stat, 2, false)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
@ -56,13 +58,13 @@ mod tests {
|
||||||
mv.expect_user().returning_st(move || user.clone());
|
mv.expect_user().returning_st(move || user.clone());
|
||||||
|
|
||||||
let mut hit_data = MockHitData::new();
|
let mut hit_data = MockHitData::new();
|
||||||
hit_data.expect_fail().once();
|
hit_data.expect_fail().returning(|| Ok(())).once();
|
||||||
let hit_data = Rc::new(hit_data);
|
let hit_data = Rc::new(hit_data);
|
||||||
mv.expect_get_hit_data()
|
mv.expect_get_hit_data()
|
||||||
.returning_st(move |_, _| hit_data.clone());
|
.returning_st(move |_, _| Ok(hit_data.clone()));
|
||||||
|
|
||||||
let script = Acupressure::new();
|
let script = Acupressure::new();
|
||||||
script.on_secondary_effect(Rc::new(mv), u, 0);
|
script.on_secondary_effect(Rc::new(mv), u, 0).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -76,11 +78,11 @@ mod tests {
|
||||||
random.expect_get_between().returning_st(|low, high| {
|
random.expect_get_between().returning_st(|low, high| {
|
||||||
assert_eq!(1, low);
|
assert_eq!(1, low);
|
||||||
assert_eq!(6, high);
|
assert_eq!(6, high);
|
||||||
1
|
Ok(1)
|
||||||
});
|
});
|
||||||
Rc::new(random)
|
Rc::new(random)
|
||||||
});
|
});
|
||||||
Some(Rc::new(battle))
|
Ok(Some(Rc::new(battle)))
|
||||||
});
|
});
|
||||||
user.expect_change_stat_boost()
|
user.expect_change_stat_boost()
|
||||||
.once()
|
.once()
|
||||||
|
@ -88,7 +90,7 @@ mod tests {
|
||||||
assert_eq!(Statistic::Attack, stat);
|
assert_eq!(Statistic::Attack, stat);
|
||||||
assert_eq!(2, amount);
|
assert_eq!(2, amount);
|
||||||
assert!(!self_inflicted);
|
assert!(!self_inflicted);
|
||||||
true
|
Ok(true)
|
||||||
});
|
});
|
||||||
|
|
||||||
let user = Rc::new(user);
|
let user = Rc::new(user);
|
||||||
|
@ -98,6 +100,6 @@ mod tests {
|
||||||
mv.expect_user().returning_st(move || user.clone());
|
mv.expect_user().returning_st(move || user.clone());
|
||||||
|
|
||||||
let script = Acupressure::new();
|
let script = Acupressure::new();
|
||||||
script.on_secondary_effect(Rc::new(mv), u, 0);
|
script.on_secondary_effect(Rc::new(mv), u, 0).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::common_usings::*;
|
use crate::common_usings::*;
|
||||||
|
use pkmn_lib_interface::PkmnResult;
|
||||||
|
|
||||||
pub struct AfterYou {}
|
pub struct AfterYou {}
|
||||||
|
|
||||||
|
@ -21,15 +22,16 @@ impl Script for AfterYou {
|
||||||
&[ScriptCapabilities::OnSecondaryEffect]
|
&[ScriptCapabilities::OnSecondaryEffect]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) {
|
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) -> PkmnResult<()> {
|
||||||
if !target
|
if !target
|
||||||
.battle()
|
.battle()?
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.choice_queue()
|
.choice_queue()
|
||||||
.move_pokemon_choice_next(&target)
|
.move_pokemon_choice_next(&target)?
|
||||||
{
|
{
|
||||||
mv.get_hit_data(&target, hit).fail()
|
mv.get_hit_data(&target, hit)?.fail()?
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
@ -53,7 +55,7 @@ mod tests {
|
||||||
choice_queue
|
choice_queue
|
||||||
.expect_move_pokemon_choice_next()
|
.expect_move_pokemon_choice_next()
|
||||||
.once()
|
.once()
|
||||||
.return_const(true);
|
.returning_st(move |_| Ok(true));
|
||||||
Rc::new(choice_queue)
|
Rc::new(choice_queue)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -62,11 +64,13 @@ mod tests {
|
||||||
target
|
target
|
||||||
.expect_battle()
|
.expect_battle()
|
||||||
.once()
|
.once()
|
||||||
.return_once_st(move || Some(battle));
|
.return_once_st(move || Ok(Some(battle)));
|
||||||
let target = Rc::new(target);
|
let target = Rc::new(target);
|
||||||
|
|
||||||
let script = AfterYou::new();
|
let script = AfterYou::new();
|
||||||
script.on_secondary_effect(Rc::new(MockExecutingMove::new()), target, 0);
|
script
|
||||||
|
.on_secondary_effect(Rc::new(MockExecutingMove::new()), target, 0)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -77,7 +81,7 @@ mod tests {
|
||||||
choice_queue
|
choice_queue
|
||||||
.expect_move_pokemon_choice_next()
|
.expect_move_pokemon_choice_next()
|
||||||
.once()
|
.once()
|
||||||
.return_const(false);
|
.returning_st(move |_| Ok(false));
|
||||||
Rc::new(choice_queue)
|
Rc::new(choice_queue)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -86,18 +90,18 @@ mod tests {
|
||||||
target
|
target
|
||||||
.expect_battle()
|
.expect_battle()
|
||||||
.once()
|
.once()
|
||||||
.return_once_st(move || Some(battle));
|
.return_once_st(move || Ok(Some(battle)));
|
||||||
let target = Rc::new(target);
|
let target = Rc::new(target);
|
||||||
|
|
||||||
let mut mv = MockExecutingMove::new();
|
let mut mv = MockExecutingMove::new();
|
||||||
mv.expect_get_hit_data().once().returning_st(move |_, _| {
|
mv.expect_get_hit_data().once().returning_st(move |_, _| {
|
||||||
let mut hit = MockHitData::new();
|
let mut hit = MockHitData::new();
|
||||||
hit.expect_fail().once();
|
hit.expect_fail().returning(|| Ok(())).once();
|
||||||
Rc::new(hit)
|
Ok(Rc::new(hit))
|
||||||
});
|
});
|
||||||
let mv = Rc::new(mv);
|
let mv = Rc::new(mv);
|
||||||
|
|
||||||
let script = AfterYou::new();
|
let script = AfterYou::new();
|
||||||
script.on_secondary_effect(mv, target, 0);
|
script.on_secondary_effect(mv, target, 0).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
use crate::common_usings::*;
|
use crate::common_usings::*;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use pkmn_lib_interface::PkmnResult;
|
||||||
|
|
||||||
script!(Assist, "assist");
|
script!(Assist, "assist");
|
||||||
|
|
||||||
impl Assist {
|
impl Assist {
|
||||||
/// Gets all the learned moves from the entire party, except the ones from the user, and the ones
|
/// Gets all the learned moves from the entire party, except the ones from the user, and the ones
|
||||||
/// that are not allowed to be copied.
|
/// that are not allowed to be copied.
|
||||||
fn get_party_moves(party: &Party, user: &Pokemon) -> Vec<MoveData> {
|
fn get_party_moves(party: &Party, user: &Pokemon) -> PkmnResult<Vec<MoveData>> {
|
||||||
let mut possible_moves = Vec::new();
|
let mut possible_moves = Vec::new();
|
||||||
// Iterate over every mon in the party
|
// Iterate over every mon in the party
|
||||||
for mon in party.into_iter().flatten() {
|
for mon in party.into_iter().flatten() {
|
||||||
|
@ -16,7 +17,7 @@ impl Assist {
|
||||||
}
|
}
|
||||||
// Iterate over all moves. We make the assumption of 4 moves.
|
// Iterate over all moves. We make the assumption of 4 moves.
|
||||||
for move_index in 0..4 {
|
for move_index in 0..4 {
|
||||||
let mv = mon.get_learned_move(move_index);
|
let mv = mon.get_learned_move(move_index)?;
|
||||||
if let Some(mv) = mv {
|
if let Some(mv) = mv {
|
||||||
// Make sure we can copy the move, otherwise add it as possible move.
|
// Make sure we can copy the move, otherwise add it as possible move.
|
||||||
if crate::utils::copyable_moves::can_copy_move(&mv.move_data()) {
|
if crate::utils::copyable_moves::can_copy_move(&mv.move_data()) {
|
||||||
|
@ -25,7 +26,7 @@ impl Assist {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
possible_moves
|
Ok(possible_moves)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,24 +43,25 @@ impl Script for Assist {
|
||||||
&[ScriptCapabilities::ChangeMove]
|
&[ScriptCapabilities::ChangeMove]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_move(&self, choice: TurnChoice, move_name: &mut StringKey) {
|
fn change_move(&self, choice: TurnChoice, move_name: &mut StringKey) -> PkmnResult<()> {
|
||||||
let user = choice.user();
|
let user = choice.user();
|
||||||
let battle = user.battle().unwrap();
|
let battle = user.battle()?.unwrap();
|
||||||
let party = battle.find_party_for_pokemon(&user);
|
let party = battle.find_party_for_pokemon(&user)?;
|
||||||
if party.is_none() {
|
if party.is_none() {
|
||||||
choice.fail();
|
choice.fail()?;
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let party = party.unwrap().party();
|
let party = party.unwrap().party();
|
||||||
let possible_moves = Self::get_party_moves(&party, &user);
|
let possible_moves = Self::get_party_moves(&party, &user)?;
|
||||||
|
|
||||||
if possible_moves.is_empty() {
|
if possible_moves.is_empty() {
|
||||||
choice.fail();
|
choice.fail()?;
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
let random = battle.random().get_max(possible_moves.len() as i32);
|
let random = battle.random().get_max(possible_moves.len() as i32)?;
|
||||||
*move_name = possible_moves[random as usize].name();
|
*move_name = possible_moves[random as usize].name();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
@ -93,9 +95,9 @@ mod tests {
|
||||||
.returning_st(move || moves.get(index).unwrap().clone());
|
.returning_st(move || moves.get(index).unwrap().clone());
|
||||||
Rc::new(move_data)
|
Rc::new(move_data)
|
||||||
});
|
});
|
||||||
Some(Rc::new(learned_move))
|
Ok(Some(Rc::new(learned_move)))
|
||||||
} else {
|
} else {
|
||||||
None
|
Ok(None)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mon.expect_equals().return_const(equals_user);
|
mon.expect_equals().return_const(equals_user);
|
||||||
|
@ -105,16 +107,19 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn get_party_moves_returns_moves_from_party_length_1() {
|
fn get_party_moves_returns_moves_from_party_length_1() {
|
||||||
let mut party = MockParty::new();
|
let mut party = MockParty::new();
|
||||||
party.expect_length().once().return_const(1usize);
|
party
|
||||||
|
.expect_length()
|
||||||
|
.once()
|
||||||
|
.returning_st(move || Ok(1usize));
|
||||||
party
|
party
|
||||||
.expect_get_pokemon()
|
.expect_get_pokemon()
|
||||||
.times(1)
|
.times(1)
|
||||||
.returning_st(move |_| Some(mock_pokemon_with_moves(vec!["tackle".into()], false)));
|
.returning_st(move |_| Ok(Some(mock_pokemon_with_moves(vec!["tackle".into()], false))));
|
||||||
|
|
||||||
let party: Party = Rc::new(party);
|
let party: Party = Rc::new(party);
|
||||||
let user: Pokemon = Rc::new(MockPokemon::new());
|
let user: Pokemon = Rc::new(MockPokemon::new());
|
||||||
|
|
||||||
let moves = Assist::get_party_moves(&party, &user);
|
let moves = Assist::get_party_moves(&party, &user).unwrap();
|
||||||
assert_eq!(1, moves.len());
|
assert_eq!(1, moves.len());
|
||||||
assert_eq!(moves[0].name(), "tackle".into())
|
assert_eq!(moves[0].name(), "tackle".into())
|
||||||
}
|
}
|
||||||
|
@ -122,35 +127,38 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn get_party_moves_returns_moves_from_party_length_7() {
|
fn get_party_moves_returns_moves_from_party_length_7() {
|
||||||
let mut party = MockParty::new();
|
let mut party = MockParty::new();
|
||||||
party.expect_length().once().return_const(3usize);
|
party
|
||||||
|
.expect_length()
|
||||||
|
.once()
|
||||||
|
.returning_st(move || Ok(3usize));
|
||||||
party
|
party
|
||||||
.expect_get_pokemon()
|
.expect_get_pokemon()
|
||||||
.times(3)
|
.times(3)
|
||||||
.returning_st(move |index| {
|
.returning_st(move |index| {
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
Some(mock_pokemon_with_moves(
|
Ok(Some(mock_pokemon_with_moves(
|
||||||
vec!["move1".into(), "move2".into(), "move3".into()],
|
vec!["move1".into(), "move2".into(), "move3".into()],
|
||||||
false,
|
false,
|
||||||
))
|
)))
|
||||||
} else if index == 1 {
|
} else if index == 1 {
|
||||||
Some(mock_pokemon_with_moves(
|
Ok(Some(mock_pokemon_with_moves(
|
||||||
vec!["move1".into(), "move4".into()],
|
vec!["move1".into(), "move4".into()],
|
||||||
false,
|
false,
|
||||||
))
|
)))
|
||||||
} else if index == 2 {
|
} else if index == 2 {
|
||||||
Some(mock_pokemon_with_moves(
|
Ok(Some(mock_pokemon_with_moves(
|
||||||
vec!["move2".into(), "move5".into()],
|
vec!["move2".into(), "move5".into()],
|
||||||
false,
|
false,
|
||||||
))
|
)))
|
||||||
} else {
|
} else {
|
||||||
None
|
Ok(None)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let party: Party = Rc::new(party);
|
let party: Party = Rc::new(party);
|
||||||
let user: Pokemon = Rc::new(MockPokemon::new());
|
let user: Pokemon = Rc::new(MockPokemon::new());
|
||||||
|
|
||||||
let moves = Assist::get_party_moves(&party, &user);
|
let moves = Assist::get_party_moves(&party, &user).unwrap();
|
||||||
assert_eq!(7, moves.len());
|
assert_eq!(7, moves.len());
|
||||||
assert_eq!(moves[0].name(), "move1".into());
|
assert_eq!(moves[0].name(), "move1".into());
|
||||||
assert_eq!(moves[1].name(), "move2".into());
|
assert_eq!(moves[1].name(), "move2".into());
|
||||||
|
@ -164,12 +172,15 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn get_party_moves_ignores_user() {
|
fn get_party_moves_ignores_user() {
|
||||||
let mut party = MockParty::new();
|
let mut party = MockParty::new();
|
||||||
party.expect_length().once().return_const(3usize);
|
party
|
||||||
|
.expect_length()
|
||||||
|
.once()
|
||||||
|
.returning_st(move || Ok(3usize));
|
||||||
party
|
party
|
||||||
.expect_get_pokemon()
|
.expect_get_pokemon()
|
||||||
.times(3)
|
.times(3)
|
||||||
.returning_st(move |index| {
|
.returning_st(move |index| {
|
||||||
if index == 0 {
|
Ok(if index == 0 {
|
||||||
Some(mock_pokemon_with_moves(
|
Some(mock_pokemon_with_moves(
|
||||||
vec!["move1".into(), "move2".into(), "move3".into()],
|
vec!["move1".into(), "move2".into(), "move3".into()],
|
||||||
false,
|
false,
|
||||||
|
@ -186,13 +197,13 @@ mod tests {
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let party: Party = Rc::new(party);
|
let party: Party = Rc::new(party);
|
||||||
let user: Pokemon = Rc::new(MockPokemon::new());
|
let user: Pokemon = Rc::new(MockPokemon::new());
|
||||||
|
|
||||||
let moves = Assist::get_party_moves(&party, &user);
|
let moves = Assist::get_party_moves(&party, &user).unwrap();
|
||||||
assert_eq!(5, moves.len());
|
assert_eq!(5, moves.len());
|
||||||
assert_eq!(moves[0].name(), "move1".into());
|
assert_eq!(moves[0].name(), "move1".into());
|
||||||
assert_eq!(moves[1].name(), "move2".into());
|
assert_eq!(moves[1].name(), "move2".into());
|
||||||
|
@ -204,26 +215,31 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn get_party_moves_ignores_non_copyable_move() {
|
fn get_party_moves_ignores_non_copyable_move() {
|
||||||
let mut party = MockParty::new();
|
let mut party = MockParty::new();
|
||||||
party.expect_length().once().return_const(1usize);
|
|
||||||
party
|
party
|
||||||
.expect_get_pokemon()
|
.expect_length()
|
||||||
.times(1)
|
.once()
|
||||||
.returning_st(move |_| Some(mock_pokemon_with_moves(vec!["chatter".into()], false)));
|
.returning_st(move || Ok(1usize));
|
||||||
|
party.expect_get_pokemon().times(1).returning_st(move |_| {
|
||||||
|
Ok(Some(mock_pokemon_with_moves(vec!["chatter".into()], false)))
|
||||||
|
});
|
||||||
let party: Party = Rc::new(party);
|
let party: Party = Rc::new(party);
|
||||||
let user: Pokemon = Rc::new(MockPokemon::new());
|
let user: Pokemon = Rc::new(MockPokemon::new());
|
||||||
|
|
||||||
let moves = Assist::get_party_moves(&party, &user);
|
let moves = Assist::get_party_moves(&party, &user).unwrap();
|
||||||
assert_eq!(0, moves.len());
|
assert_eq!(0, moves.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_moves_found_assist_uses_that_move() {
|
fn if_moves_found_assist_uses_that_move() {
|
||||||
let mut party = MockParty::new();
|
let mut party = MockParty::new();
|
||||||
party.expect_length().once().return_const(1usize);
|
party
|
||||||
|
.expect_length()
|
||||||
|
.once()
|
||||||
|
.returning_st(move || Ok(1usize));
|
||||||
party
|
party
|
||||||
.expect_get_pokemon()
|
.expect_get_pokemon()
|
||||||
.times(1)
|
.times(1)
|
||||||
.returning_st(move |_| Some(mock_pokemon_with_moves(vec!["tackle".into()], false)));
|
.returning_st(move |_| Ok(Some(mock_pokemon_with_moves(vec!["tackle".into()], false))));
|
||||||
|
|
||||||
let party: Party = Rc::new(party);
|
let party: Party = Rc::new(party);
|
||||||
|
|
||||||
|
@ -243,16 +259,16 @@ mod tests {
|
||||||
let mut p = MockBattleParty::new();
|
let mut p = MockBattleParty::new();
|
||||||
p.expect_party().returning_st(move || party.clone());
|
p.expect_party().returning_st(move || party.clone());
|
||||||
|
|
||||||
Some(Rc::new(p))
|
Ok(Some(Rc::new(p)))
|
||||||
});
|
});
|
||||||
|
|
||||||
battle.expect_random().returning_st(|| {
|
battle.expect_random().returning_st(|| {
|
||||||
let mut random = MockBattleRandom::new();
|
let mut random = MockBattleRandom::new();
|
||||||
random.expect_get_max().return_const(0);
|
random.expect_get_max().returning_st(move |_| Ok(0));
|
||||||
Rc::new(random)
|
Rc::new(random)
|
||||||
});
|
});
|
||||||
|
|
||||||
Some(Rc::new(battle))
|
Ok(Some(Rc::new(battle)))
|
||||||
});
|
});
|
||||||
|
|
||||||
Rc::new(user)
|
Rc::new(user)
|
||||||
|
@ -270,7 +286,7 @@ mod tests {
|
||||||
|
|
||||||
let mut move_name: StringKey = "".into();
|
let mut move_name: StringKey = "".into();
|
||||||
let script = Assist::new();
|
let script = Assist::new();
|
||||||
script.change_move(choice_data, &mut move_name);
|
script.change_move(choice_data, &mut move_name).unwrap();
|
||||||
assert_eq!(move_name, "tackle".into())
|
assert_eq!(move_name, "tackle".into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::common_usings::*;
|
use crate::common_usings::*;
|
||||||
|
use pkmn_lib_interface::PkmnResult;
|
||||||
|
|
||||||
script!(Assurance, "assurance");
|
script!(Assurance, "assurance");
|
||||||
|
|
||||||
|
@ -18,20 +19,22 @@ impl Script for Assurance {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_before_turn(&self, choice: TurnChoice) {
|
fn on_before_turn(&self, choice: TurnChoice) -> PkmnResult<()> {
|
||||||
if let TurnChoice::Move(data) = &choice {
|
if let TurnChoice::Move(data) = &choice {
|
||||||
let side: BattleSide = choice
|
let side: BattleSide = choice
|
||||||
.user()
|
.user()
|
||||||
.battle()
|
.battle()?
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.sides()
|
.sides()
|
||||||
.get(data.target_side() as u32)
|
.get(data.target_side() as usize)
|
||||||
.unwrap();
|
.unwrap()
|
||||||
|
.clone();
|
||||||
side.add_volatile(Box::new(AssuranceData {
|
side.add_volatile(Box::new(AssuranceData {
|
||||||
for_position: data.target_index(),
|
for_position: data.target_index(),
|
||||||
has_hit: AtomicBool::new(false),
|
has_hit: AtomicBool::new(false),
|
||||||
}));
|
}))?;
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_base_power(
|
fn change_base_power(
|
||||||
|
@ -40,15 +43,16 @@ impl Script for Assurance {
|
||||||
target: Pokemon,
|
target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
base_power: &mut u8,
|
base_power: &mut u8,
|
||||||
) {
|
) -> PkmnResult<()> {
|
||||||
if let Some(s) = get_volatile_as::<AssuranceData>(
|
if let Some(s) = get_volatile_as::<AssuranceData>(
|
||||||
target.battle_side().as_ref(),
|
target.battle_side()?.as_ref(),
|
||||||
AssuranceData::get_const_name(),
|
AssuranceData::get_const_name(),
|
||||||
) {
|
)? {
|
||||||
if s.has_hit.load(Ordering::Relaxed) {
|
if s.has_hit.load(Ordering::Relaxed) {
|
||||||
*base_power *= 2;
|
*base_power *= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
@ -79,9 +83,10 @@ impl Script for AssuranceData {
|
||||||
&[ScriptCapabilities::OnEndTurn, ScriptCapabilities::OnDamage]
|
&[ScriptCapabilities::OnEndTurn, ScriptCapabilities::OnDamage]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_end_turn(&self) {
|
fn on_end_turn(&self) -> PkmnResult<()> {
|
||||||
let side = self.get_owner().unwrap().as_side();
|
let side = self.get_owner().unwrap().as_side();
|
||||||
side.remove_volatile(self);
|
side.remove_volatile(self)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_damage(
|
fn on_damage(
|
||||||
|
@ -90,10 +95,11 @@ impl Script for AssuranceData {
|
||||||
_source: DamageSource,
|
_source: DamageSource,
|
||||||
_old_health: u32,
|
_old_health: u32,
|
||||||
_new_health: u32,
|
_new_health: u32,
|
||||||
) {
|
) -> PkmnResult<()> {
|
||||||
if pokemon.battle_index() == self.for_position {
|
if pokemon.battle_index()? == self.for_position {
|
||||||
self.has_hit.store(true, Ordering::Relaxed);
|
self.has_hit.store(true, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::common_usings::*;
|
use crate::common_usings::*;
|
||||||
use crate::pokemon::infatuated::Infatuated;
|
use crate::pokemon::infatuated::Infatuated;
|
||||||
|
use pkmn_lib_interface::PkmnResult;
|
||||||
|
|
||||||
script!(Attract, "attract");
|
script!(Attract, "attract");
|
||||||
|
|
||||||
|
@ -16,19 +17,22 @@ impl Script for Attract {
|
||||||
&[ScriptCapabilities::OnSecondaryEffect]
|
&[ScriptCapabilities::OnSecondaryEffect]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) {
|
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) -> PkmnResult<()> {
|
||||||
let user_gender = mv.user().gender();
|
let user_gender = mv.user().gender()?;
|
||||||
let target_gender = target.gender();
|
let target_gender = target.gender()?;
|
||||||
// If the move is used on a Pokémon that is the same gender as the user, it will fail
|
// If the move is used on a Pokémon that is the same gender as the user, it will fail
|
||||||
if target_gender == user_gender {
|
if target_gender == user_gender {
|
||||||
return mv.get_hit_data(&target, hit).fail();
|
mv.get_hit_data(&target, hit)?.fail()?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
// It will also fail if used by or on a gender-unknown Pokémon
|
// It will also fail if used by or on a gender-unknown Pokémon
|
||||||
if user_gender == Gender::Genderless || target_gender == Gender::Genderless {
|
if user_gender == Gender::Genderless || target_gender == Gender::Genderless {
|
||||||
return mv.get_hit_data(&target, hit).fail();
|
mv.get_hit_data(&target, hit)?.fail()?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
// If the target is the opposite gender of the Pokémon who launched the move, the target becomes infatuated
|
// If the target is the opposite gender of the Pokémon who launched the move, the target becomes infatuated
|
||||||
target.add_volatile_by_name(Infatuated::get_const_name());
|
target.add_volatile_by_name(Infatuated::get_const_name())?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::common_usings::*;
|
||||||
use crate::moves::light_screen::LightScreenEffect;
|
use crate::moves::light_screen::LightScreenEffect;
|
||||||
use crate::moves::reflect::ReflectEffect;
|
use crate::moves::reflect::ReflectEffect;
|
||||||
use crate::weather::hail::Hail;
|
use crate::weather::hail::Hail;
|
||||||
|
use pkmn_lib_interface::PkmnResult;
|
||||||
|
|
||||||
script!(AuroraVeil, "aurora_veil");
|
script!(AuroraVeil, "aurora_veil");
|
||||||
|
|
||||||
|
@ -18,21 +19,27 @@ impl Script for AuroraVeil {
|
||||||
&[ScriptCapabilities::OnSecondaryEffect]
|
&[ScriptCapabilities::OnSecondaryEffect]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) {
|
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) -> PkmnResult<()> {
|
||||||
if target.battle().unwrap().has_weather(Hail::get_const_name()) {
|
if target
|
||||||
return mv.get_hit_data(&target, hit).fail();
|
.battle()?
|
||||||
|
.unwrap()
|
||||||
|
.has_weather(Hail::get_const_name())?
|
||||||
|
{
|
||||||
|
mv.get_hit_data(&target, hit)?.fail()?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
let binding = target.battle_side();
|
let binding = target.battle_side()?;
|
||||||
let script = binding
|
let script = binding
|
||||||
.add_volatile(Box::new(AuroraVeilEffect::new()))
|
.add_volatile(Box::new(AuroraVeilEffect::new()))?
|
||||||
.as_any()
|
.as_any()
|
||||||
.downcast_ref::<AuroraVeilEffect>()
|
.downcast_ref::<AuroraVeilEffect>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if mv.user().has_held_item("light_clay") {
|
if mv.user().has_held_item("light_clay")? {
|
||||||
script.turns.store(8, Ordering::SeqCst);
|
script.turns.store(8, Ordering::SeqCst);
|
||||||
} else {
|
} else {
|
||||||
script.turns.store(5, Ordering::SeqCst);
|
script.turns.store(5, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
@ -66,30 +73,32 @@ impl Script for AuroraVeilEffect {
|
||||||
target: Pokemon,
|
target: Pokemon,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
damage: &mut u32,
|
damage: &mut u32,
|
||||||
) {
|
) -> PkmnResult<()> {
|
||||||
if mv.get_hit_data(&target, hit).is_critical() {
|
if mv.get_hit_data(&target, hit)?.is_critical()? {
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
let side = self.get_owner().unwrap().as_side();
|
let side = self.get_owner().unwrap().as_side();
|
||||||
if side.has_volatile(ReflectEffect::get_const_name())
|
if side.has_volatile(ReflectEffect::get_const_name())?
|
||||||
&& mv.use_move().category() == MoveCategory::Physical
|
&& mv.use_move().category() == MoveCategory::Physical
|
||||||
{
|
{
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
if side.has_volatile(LightScreenEffect::get_const_name())
|
if side.has_volatile(LightScreenEffect::get_const_name())?
|
||||||
&& mv.use_move().category() == MoveCategory::Special
|
&& mv.use_move().category() == MoveCategory::Special
|
||||||
{
|
{
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
let mut modifier = 2.0;
|
let mut modifier = 2.0;
|
||||||
if target.battle().unwrap().pokemon_per_side() > 1 {
|
if target.battle()?.unwrap().pokemon_per_side()? > 1 {
|
||||||
modifier = 1.5
|
modifier = 1.5
|
||||||
}
|
}
|
||||||
*damage = (*damage as f32 / modifier) as u32;
|
*damage = (*damage as f32 / modifier) as u32;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_end_turn(&self) {
|
fn on_end_turn(&self) -> PkmnResult<()> {
|
||||||
todo!()
|
// TODO
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::common_usings::*;
|
use crate::common_usings::*;
|
||||||
|
use pkmn_lib_interface::PkmnResult;
|
||||||
|
|
||||||
script!(Automize, "automize");
|
script!(Automize, "automize");
|
||||||
|
|
||||||
|
@ -15,18 +16,19 @@ impl Script for Automize {
|
||||||
&[ScriptCapabilities::OnSecondaryEffect]
|
&[ScriptCapabilities::OnSecondaryEffect]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_secondary_effect(&self, mv: ExecutingMove, _target: Pokemon, _hit: u8) {
|
fn on_secondary_effect(&self, mv: ExecutingMove, _target: Pokemon, _hit: u8) -> PkmnResult<()> {
|
||||||
let user = mv.user();
|
let user = mv.user();
|
||||||
let stats = user.boosted_stats();
|
let stats = user.boosted_stats();
|
||||||
let original_speed = stats.speed();
|
let original_speed = stats.speed()?;
|
||||||
let original_weight = user.weight();
|
let original_weight = user.weight()?;
|
||||||
user.change_stat_boost(Statistic::Speed, 2, true);
|
user.change_stat_boost(Statistic::Speed, 2, true)?;
|
||||||
if user.boosted_stats().speed() != original_speed {
|
if user.boosted_stats().speed()? != original_speed {
|
||||||
user.set_weight(original_weight - 100.0);
|
user.set_weight(original_weight - 100.0);
|
||||||
if user.weight() != original_weight {
|
if user.weight()? != original_weight {
|
||||||
// TODO: Became nimble dialog.
|
// TODO: Became nimble dialog.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::common_usings::*;
|
use crate::common_usings::*;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
use pkmn_lib_interface::PkmnResult;
|
||||||
|
|
||||||
script!(
|
script!(
|
||||||
ChangeAllTargetStats,
|
ChangeAllTargetStats,
|
||||||
|
@ -27,22 +29,24 @@ impl Script for ChangeAllTargetStats {
|
||||||
fn on_initialize(
|
fn on_initialize(
|
||||||
&self,
|
&self,
|
||||||
_library: DynamicLibrary,
|
_library: DynamicLibrary,
|
||||||
parameters: Option<ImmutableList<Rc<EffectParameter>>>,
|
parameters: Option<Vec<Rc<EffectParameter>>>,
|
||||||
) {
|
) -> PkmnResult<()> {
|
||||||
self.amount.store(
|
self.amount.store(
|
||||||
parameters.unwrap().get(0).unwrap().as_int() as i8,
|
parameters.unwrap().get(0).unwrap().as_int() as i8,
|
||||||
Ordering::SeqCst,
|
Ordering::SeqCst,
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, _hit: u8) {
|
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, _hit: u8) -> PkmnResult<()> {
|
||||||
let user = mv.user();
|
let user = mv.user();
|
||||||
let amount = self.amount.load(Ordering::SeqCst);
|
let amount = self.amount.load(Ordering::SeqCst);
|
||||||
target.change_stat_boost(Statistic::Attack, amount, user.equals(&target));
|
target.change_stat_boost(Statistic::Attack, amount, user.equals(&target))?;
|
||||||
target.change_stat_boost(Statistic::Defense, amount, user.equals(&target));
|
target.change_stat_boost(Statistic::Defense, amount, user.equals(&target))?;
|
||||||
target.change_stat_boost(Statistic::SpecialAttack, amount, user.equals(&target));
|
target.change_stat_boost(Statistic::SpecialAttack, amount, user.equals(&target))?;
|
||||||
target.change_stat_boost(Statistic::SpecialDefense, amount, user.equals(&target));
|
target.change_stat_boost(Statistic::SpecialDefense, amount, user.equals(&target))?;
|
||||||
target.change_stat_boost(Statistic::Speed, amount, user.equals(&target));
|
target.change_stat_boost(Statistic::Speed, amount, user.equals(&target))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -36,20 +36,22 @@ macro_rules! change_stat_effect {
|
||||||
fn on_initialize(
|
fn on_initialize(
|
||||||
&self,
|
&self,
|
||||||
_library: DynamicLibrary,
|
_library: DynamicLibrary,
|
||||||
parameters: Option<ImmutableList<Rc<EffectParameter>>>,
|
parameters: Option<Vec<Rc<EffectParameter>>>,
|
||||||
) {
|
) -> PkmnResult<()> {
|
||||||
self.amount.store(
|
self.amount.store(
|
||||||
parameters.unwrap().get(0).unwrap().as_int() as i8,
|
parameters.unwrap().get(0).unwrap().as_int() as i8,
|
||||||
Ordering::SeqCst,
|
Ordering::SeqCst,
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, _hit: u8) {
|
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, _hit: u8) -> PkmnResult<()> {
|
||||||
target.change_stat_boost(
|
target.change_stat_boost(
|
||||||
Statistic::$stat,
|
Statistic::$stat,
|
||||||
self.amount.load(Ordering::SeqCst),
|
self.amount.load(Ordering::SeqCst),
|
||||||
mv.user().equals(&target),
|
mv.user().equals(&target),
|
||||||
);
|
)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -15,21 +15,19 @@ impl Script for CurePartyStatus {
|
||||||
&[ScriptCapabilities::OnSecondaryEffect]
|
&[ScriptCapabilities::OnSecondaryEffect]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_secondary_effect(&self, mv: ExecutingMove, _target: Pokemon, _hit: u8) {
|
fn on_secondary_effect(&self, mv: ExecutingMove, _target: Pokemon, _hit: u8) -> PkmnResult<()> {
|
||||||
let user = mv.user();
|
let user = mv.user();
|
||||||
user.clear_status();
|
user.clear_status();
|
||||||
let party = user.battle().unwrap().find_party_for_pokemon(&user);
|
let party = user.battle()?.unwrap().find_party_for_pokemon(&user)?;
|
||||||
if let Some(party) = party {
|
if let Some(party) = party {
|
||||||
let p = party.party();
|
let p = party.party();
|
||||||
for index in 0..p.length() {
|
for mon in p.as_ref().into_iter().flatten() {
|
||||||
let mon = p.get_pokemon(index);
|
|
||||||
if let Some(mon) = mon {
|
|
||||||
if !mon.equals(&user) {
|
if !mon.equals(&user) {
|
||||||
mon.clear_status();
|
mon.clear_status();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -23,22 +23,24 @@ impl Script for Drain {
|
||||||
fn on_initialize(
|
fn on_initialize(
|
||||||
&self,
|
&self,
|
||||||
_library: DynamicLibrary,
|
_library: DynamicLibrary,
|
||||||
parameters: Option<ImmutableList<Rc<EffectParameter>>>,
|
parameters: Option<Vec<Rc<EffectParameter>>>,
|
||||||
) {
|
) -> PkmnResult<()> {
|
||||||
self.heal_modifier.store(
|
self.heal_modifier.store(
|
||||||
parameters.unwrap().get(0).unwrap().as_float(),
|
parameters.unwrap().get(0).unwrap().as_float(),
|
||||||
Ordering::SeqCst,
|
Ordering::SeqCst,
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) {
|
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) -> PkmnResult<()> {
|
||||||
let hit_data = mv.get_hit_data(&target, hit);
|
let hit_data = mv.get_hit_data(&target, hit)?;
|
||||||
let damage = hit_data.damage();
|
let damage = hit_data.damage()?;
|
||||||
let mut modifier = self.heal_modifier.load(Ordering::SeqCst);
|
let mut modifier = self.heal_modifier.load(Ordering::SeqCst);
|
||||||
if mv.user().has_held_item("big_root") {
|
if mv.user().has_held_item("big_root")? {
|
||||||
modifier *= 1.3;
|
modifier *= 1.3;
|
||||||
}
|
}
|
||||||
mv.user().heal((damage as f32 * modifier) as u32, false);
|
mv.user().heal((damage as f32 * modifier) as u32, false)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -15,8 +15,14 @@ impl Script for Flinch {
|
||||||
&[ScriptCapabilities::OnSecondaryEffect]
|
&[ScriptCapabilities::OnSecondaryEffect]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_secondary_effect(&self, _move: ExecutingMove, target: Pokemon, _hit: u8) {
|
fn on_secondary_effect(
|
||||||
target.add_volatile(Box::new(FlinchEffect::new()));
|
&self,
|
||||||
|
_move: ExecutingMove,
|
||||||
|
target: Pokemon,
|
||||||
|
_hit: u8,
|
||||||
|
) -> PkmnResult<()> {
|
||||||
|
target.add_volatile(Box::new(FlinchEffect::new()))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
@ -39,9 +45,10 @@ impl Script for FlinchEffect {
|
||||||
&[ScriptCapabilities::PreventMove]
|
&[ScriptCapabilities::PreventMove]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prevent_move(&self, mv: ExecutingMove, prevent: &mut bool) {
|
fn prevent_move(&self, mv: ExecutingMove, prevent: &mut bool) -> PkmnResult<()> {
|
||||||
*prevent = true;
|
*prevent = true;
|
||||||
mv.user().remove_volatile(self);
|
mv.user().remove_volatile(self)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -28,16 +28,17 @@ impl Script for HealEachEndOfTurn {
|
||||||
fn on_initialize(
|
fn on_initialize(
|
||||||
&self,
|
&self,
|
||||||
_library: DynamicLibrary,
|
_library: DynamicLibrary,
|
||||||
parameters: Option<ImmutableList<Rc<EffectParameter>>>,
|
parameters: Option<Vec<Rc<EffectParameter>>>,
|
||||||
) {
|
) -> PkmnResult<()> {
|
||||||
self.heal_percent.store(
|
self.heal_percent.store(
|
||||||
parameters.unwrap().get(0).unwrap().as_float() / 100.0,
|
parameters.unwrap().get(0).unwrap().as_float() / 100.0,
|
||||||
Ordering::SeqCst,
|
Ordering::SeqCst,
|
||||||
);
|
);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_secondary_effect(&self, _mv: ExecutingMove, target: Pokemon, _hit: u8) {
|
fn on_secondary_effect(&self, _mv: ExecutingMove, target: Pokemon, _hit: u8) -> PkmnResult<()> {
|
||||||
let script = target.add_volatile_by_name("heal_each_end_of_turn_effect");
|
let script = target.add_volatile_by_name("heal_each_end_of_turn_effect")?;
|
||||||
let amount = self.heal_percent.load(Ordering::SeqCst);
|
let amount = self.heal_percent.load(Ordering::SeqCst);
|
||||||
script
|
script
|
||||||
.as_any()
|
.as_any()
|
||||||
|
@ -45,6 +46,7 @@ impl Script for HealEachEndOfTurn {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.heal_percent
|
.heal_percent
|
||||||
.store(amount, Ordering::SeqCst);
|
.store(amount, Ordering::SeqCst);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -21,17 +21,23 @@ impl Script for MultiHitMove {
|
||||||
&[ScriptCapabilities::ChangeNumberOfHits]
|
&[ScriptCapabilities::ChangeNumberOfHits]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_number_of_hits(&self, choice: TurnChoice, number_of_hits: &mut u8) {
|
fn change_number_of_hits(&self, choice: TurnChoice, number_of_hits: &mut u8) -> PkmnResult<()> {
|
||||||
// 35% chance that it will hit 2 times, a 35% chance it will hit 3 times, a 15% chance it
|
// 35% chance that it will hit 2 times, a 35% chance it will hit 3 times, a 15% chance it
|
||||||
// will hit 4 times, and a 15% chance it will hit 5 times.
|
// will hit 4 times, and a 15% chance it will hit 5 times.
|
||||||
let rand_value = choice.user().battle().unwrap().random().get_between(0, 100);
|
let rand_value = choice
|
||||||
|
.user()
|
||||||
|
.battle()?
|
||||||
|
.unwrap()
|
||||||
|
.random()
|
||||||
|
.get_between(0, 100)?;
|
||||||
*number_of_hits = match rand_value {
|
*number_of_hits = match rand_value {
|
||||||
0..=34 => 2,
|
0..=34 => 2,
|
||||||
35..=69 => 3,
|
35..=69 => 3,
|
||||||
70..=84 => 4,
|
70..=84 => 4,
|
||||||
85..=100 => 5,
|
85..=100 => 5,
|
||||||
_ => *number_of_hits,
|
_ => *number_of_hits,
|
||||||
}
|
};
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -20,12 +20,23 @@ impl Script for Struggle {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_number_of_hits(&self, _choice: TurnChoice, number_of_hits: &mut u8) {
|
fn change_number_of_hits(
|
||||||
*number_of_hits = 1
|
&self,
|
||||||
|
_choice: TurnChoice,
|
||||||
|
number_of_hits: &mut u8,
|
||||||
|
) -> PkmnResult<()> {
|
||||||
|
*number_of_hits = 1;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_invulnerable(&self, _move: ExecutingMove, _target: Pokemon, invulnerable: &mut bool) {
|
fn is_invulnerable(
|
||||||
|
&self,
|
||||||
|
_move: ExecutingMove,
|
||||||
|
_target: Pokemon,
|
||||||
|
invulnerable: &mut bool,
|
||||||
|
) -> PkmnResult<()> {
|
||||||
*invulnerable = false;
|
*invulnerable = false;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_effectiveness(
|
fn change_effectiveness(
|
||||||
|
@ -34,16 +45,18 @@ impl Script for Struggle {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
effectiveness: &mut f32,
|
effectiveness: &mut f32,
|
||||||
) {
|
) -> PkmnResult<()> {
|
||||||
*effectiveness = 1.0;
|
*effectiveness = 1.0;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_secondary_effect(&self, mv: ExecutingMove, _target: Pokemon, _hit: u8) {
|
fn on_secondary_effect(&self, mv: ExecutingMove, _target: Pokemon, _hit: u8) -> PkmnResult<()> {
|
||||||
let mut damage = mv.user().max_health() / 4;
|
let mut damage = mv.user().max_health()? / 4;
|
||||||
if damage == 0 {
|
if damage == 0 {
|
||||||
damage = 1
|
damage = 1
|
||||||
}
|
}
|
||||||
mv.user().damage(damage, DamageSource::Struggle);
|
mv.user().damage(damage, DamageSource::Struggle)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -21,15 +21,16 @@ impl Script for HealEachEndOfTurnEffect {
|
||||||
&[ScriptCapabilities::OnEndTurn]
|
&[ScriptCapabilities::OnEndTurn]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_end_turn(&self) {
|
fn on_end_turn(&self) -> PkmnResult<()> {
|
||||||
if let Some(ScriptOwner::Pokemon(pokemon)) = self.get_owner() {
|
if let Some(ScriptOwner::Pokemon(pokemon)) = self.get_owner() {
|
||||||
let mut amount =
|
let mut amount =
|
||||||
pokemon.max_health() as f32 * self.heal_percent.load(Ordering::Relaxed);
|
pokemon.max_health()? as f32 * self.heal_percent.load(Ordering::Relaxed);
|
||||||
if pokemon.has_held_item("big_root") {
|
if pokemon.has_held_item("big_root")? {
|
||||||
amount *= 1.3;
|
amount *= 1.3;
|
||||||
}
|
}
|
||||||
pokemon.heal(amount as u32, false);
|
pokemon.heal(amount as u32, false)?;
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -15,10 +15,11 @@ impl Script for Infatuated {
|
||||||
&[ScriptCapabilities::PreventMove]
|
&[ScriptCapabilities::PreventMove]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prevent_move(&self, mv: ExecutingMove, prevent: &mut bool) {
|
fn prevent_move(&self, mv: ExecutingMove, prevent: &mut bool) -> PkmnResult<()> {
|
||||||
if mv.user().battle().unwrap().random().get_max(2) == 0 {
|
if mv.user().battle()?.unwrap().random().get_max(2)? == 0 {
|
||||||
*prevent = true
|
*prevent = true
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::pokemon::*;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use pkmn_lib_interface::app_interface::{get_hash, StringKey};
|
use pkmn_lib_interface::app_interface::{get_hash, StringKey};
|
||||||
use pkmn_lib_interface::handling::{Script, ScriptCategory};
|
use pkmn_lib_interface::handling::{Script, ScriptCategory};
|
||||||
|
use pkmn_lib_interface::println;
|
||||||
|
|
||||||
macro_rules! resolve_match {
|
macro_rules! resolve_match {
|
||||||
(
|
(
|
||||||
|
@ -24,10 +25,11 @@ macro_rules! resolve_match {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_script(category: ScriptCategory, name: &StringKey) -> Option<Box<dyn Script>> {
|
pub fn get_script(category: ScriptCategory, name: &StringKey) -> Option<Box<dyn Script>> {
|
||||||
|
println!("Getting script {:?}", name);
|
||||||
match category {
|
match category {
|
||||||
ScriptCategory::Move => {
|
ScriptCategory::Move => {
|
||||||
resolve_match! {
|
resolve_match! {
|
||||||
name.hash(),
|
name.hash().unwrap(),
|
||||||
acrobatics::Acrobatics,
|
acrobatics::Acrobatics,
|
||||||
acupressure::Acupressure,
|
acupressure::Acupressure,
|
||||||
after_you::AfterYou,
|
after_you::AfterYou,
|
||||||
|
@ -54,13 +56,13 @@ pub fn get_script(category: ScriptCategory, name: &StringKey) -> Option<Box<dyn
|
||||||
ScriptCategory::Status => {}
|
ScriptCategory::Status => {}
|
||||||
ScriptCategory::Pokemon => {
|
ScriptCategory::Pokemon => {
|
||||||
resolve_match! {
|
resolve_match! {
|
||||||
name.hash(),
|
name.hash().unwrap(),
|
||||||
infatuated::Infatuated,
|
infatuated::Infatuated,
|
||||||
pokemon::heal_each_end_of_turn::HealEachEndOfTurnEffect,
|
pokemon::heal_each_end_of_turn::HealEachEndOfTurnEffect,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ScriptCategory::Battle => {
|
ScriptCategory::Battle => {
|
||||||
resolve_match! {name.hash(), crate::util_scripts::ForceEffectTriggerScript,}
|
resolve_match! {name.hash().unwrap(), crate::util_scripts::ForceEffectTriggerScript,}
|
||||||
}
|
}
|
||||||
ScriptCategory::Side => {}
|
ScriptCategory::Side => {}
|
||||||
ScriptCategory::ItemBattleTrigger => {}
|
ScriptCategory::ItemBattleTrigger => {}
|
||||||
|
|
|
@ -27,9 +27,10 @@ impl Script for ForceEffectTriggerScript {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
chance: &mut f32,
|
chance: &mut f32,
|
||||||
) {
|
) -> PkmnResult<()> {
|
||||||
// Set to 50_000% chance.
|
// Set to 50_000% chance.
|
||||||
*chance = 50_000.0;
|
*chance = 50_000.0;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|
|
@ -5,7 +5,7 @@ macro_rules! non_copyable {
|
||||||
$mv:ident,
|
$mv:ident,
|
||||||
$($move_name:literal),+
|
$($move_name:literal),+
|
||||||
) => {
|
) => {
|
||||||
match $mv.name().hash() {
|
match $mv.name().hash().unwrap() {
|
||||||
0
|
0
|
||||||
$(
|
$(
|
||||||
| const { get_hash($move_name) }
|
| const { get_hash($move_name) }
|
||||||
|
|
|
@ -8,12 +8,11 @@ edition = "2021"
|
||||||
mock_data = ["mockall"]
|
mock_data = ["mockall"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cstr_core = { version = "0.2.6", features = ["nightly"]}
|
cstr_core = { version = "0.2.6", features = ["nightly"] }
|
||||||
enumflags2 = { version = "0.7.5", default-features = false }
|
enumflags2 = { version = "0.7.5", default-features = false }
|
||||||
spin = { version = "0.9.4", default-features = false, features = ["rwlock"] }
|
spin = { version = "0.9.4", default-features = false, features = ["rwlock"] }
|
||||||
paste = { version = "1.0.7" }
|
paste = { version = "1.0.7" }
|
||||||
hashbrown = { version = "0.12.3" }
|
hashbrown = { version = "0.13.2" }
|
||||||
dlmalloc = { version = "0.2.4", features = ["global"] }
|
dlmalloc = { version = "0.2.4", features = ["global"] }
|
||||||
mockall = { version = "0.11.2", optional = true, features = ["nightly"] }
|
mockall = { version = "0.11.2", optional = true, features = ["nightly"] }
|
||||||
|
num-traits = { version = "0.2", default-features = false }
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
|
||||||
use crate::app_interface::list::ImmutableList;
|
|
||||||
use crate::app_interface::{
|
use crate::app_interface::{
|
||||||
BattleParty, BattleRandom, BattleSide, ChoiceQueue, DynamicLibrary, Pokemon, StringKey,
|
BattleParty, BattleRandom, BattleSide, ChoiceQueue, DynamicLibrary, Pokemon, StringKey,
|
||||||
};
|
};
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
||||||
pub trait BattleTrait {
|
pub trait BattleTrait {
|
||||||
fn library(&self) -> DynamicLibrary;
|
fn library(&self) -> DynamicLibrary;
|
||||||
fn parties(&self) -> ImmutableList<BattleParty>;
|
fn parties(&self) -> Vec<BattleParty>;
|
||||||
fn sides(&self) -> ImmutableList<BattleSide>;
|
fn sides(&self) -> Vec<BattleSide>;
|
||||||
fn random(&self) -> BattleRandom;
|
fn random(&self) -> BattleRandom;
|
||||||
fn choice_queue(&self) -> ChoiceQueue;
|
fn choice_queue(&self) -> ChoiceQueue;
|
||||||
fn get_pokemon(&self, side: u8, index: u8) -> Option<Pokemon>;
|
fn get_pokemon(&self, side: u8, index: u8) -> PkmnResult<Option<Pokemon>>;
|
||||||
fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> Option<BattleParty>;
|
fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> PkmnResult<Option<BattleParty>>;
|
||||||
fn weather_name(&self) -> Option<StringKey>;
|
fn weather_name(&self) -> PkmnResult<Option<StringKey>>;
|
||||||
fn has_weather(&self, name: &str) -> bool;
|
fn has_weather(&self, name: &str) -> PkmnResult<bool>;
|
||||||
fn can_flee(&self) -> bool;
|
fn can_flee(&self) -> PkmnResult<bool>;
|
||||||
fn number_of_sides(&self) -> u8;
|
fn number_of_sides(&self) -> PkmnResult<u8>;
|
||||||
fn pokemon_per_side(&self) -> u8;
|
fn pokemon_per_side(&self) -> PkmnResult<u8>;
|
||||||
fn has_ended(&self) -> bool;
|
fn has_ended(&self) -> PkmnResult<bool>;
|
||||||
fn has_ended_conclusively(&self) -> bool;
|
fn has_ended_conclusively(&self) -> PkmnResult<bool>;
|
||||||
fn winning_side(&self) -> u8;
|
fn winning_side(&self) -> PkmnResult<u8>;
|
||||||
fn current_turn(&self) -> u32;
|
fn current_turn(&self) -> PkmnResult<u32>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Battle = Rc<dyn BattleTrait>;
|
pub type Battle = Rc<dyn BattleTrait>;
|
||||||
|
@ -33,26 +33,26 @@ pub type MockBattle = MockBattleTrait;
|
||||||
mod implementation {
|
mod implementation {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::app_interface::dynamic_data::dynamic_library::DynamicLibraryImpl;
|
use crate::app_interface::dynamic_data::dynamic_library::DynamicLibraryImpl;
|
||||||
use crate::app_interface::list::{
|
|
||||||
BattlePartyImmutableList, BattleSideImmutableList, ImmutableListWasm,
|
|
||||||
};
|
|
||||||
use crate::app_interface::PokemonImpl;
|
use crate::app_interface::PokemonImpl;
|
||||||
use crate::app_interface::{
|
use crate::app_interface::{
|
||||||
BattleParty, BattlePartyImpl, BattleRandom, BattleRandomImpl, BattleSide, BattleSideImpl,
|
BattleParty, BattlePartyImpl, BattleRandom, BattleRandomImpl, BattleSide, BattleSideImpl,
|
||||||
ChoiceQueue, ChoiceQueueImpl, Pokemon,
|
ChoiceQueue, ChoiceQueueImpl, Pokemon,
|
||||||
};
|
};
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
|
use crate::handling::ffi_array::FFIArray;
|
||||||
|
use crate::handling::wasm_result::WasmResult;
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::Cacheable;
|
||||||
use crate::{
|
use crate::{
|
||||||
cached_value, cached_value_getters, wasm_value_getters_extern, wasm_value_getters_funcs,
|
cached_value, cached_value_getters, wasm_value_getters_extern, wasm_value_getters_funcs,
|
||||||
ExternRef, ExternalReferenceType, StringKey, VecExternRef,
|
ExternRef, ExternalReferenceType, PkmnResult, StringKey,
|
||||||
};
|
};
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
struct BattleInner {
|
struct BattleInner {
|
||||||
reference: ExternRef<BattleImpl>,
|
reference: ExternRef<BattleImpl>,
|
||||||
library: CachedValue<DynamicLibrary>,
|
library: CachedValue<DynamicLibrary>,
|
||||||
parties: CachedValue<ImmutableList<BattleParty>>,
|
parties: CachedValue<Vec<BattleParty>>,
|
||||||
sides: CachedValue<ImmutableList<BattleSide>>,
|
sides: CachedValue<Vec<BattleSide>>,
|
||||||
random: CachedValue<Rc<BattleRandomImpl>>,
|
random: CachedValue<Rc<BattleRandomImpl>>,
|
||||||
choice_queue: CachedValue<Rc<ChoiceQueueImpl>>,
|
choice_queue: CachedValue<Rc<ChoiceQueueImpl>>,
|
||||||
}
|
}
|
||||||
|
@ -69,21 +69,39 @@ mod implementation {
|
||||||
inner: Rc::new(BattleInner {
|
inner: Rc::new(BattleInner {
|
||||||
reference,
|
reference,
|
||||||
library: cached_value!({
|
library: cached_value!({
|
||||||
Rc::new(battle_get_library(reference).get_value().unwrap())
|
Rc::new(battle_get_library(reference).unwrap().get_value().unwrap())
|
||||||
}),
|
}),
|
||||||
parties: cached_value!({
|
parties: cached_value!({
|
||||||
let reference = battle_get_parties(reference);
|
let parties: FFIArray<ExternRef<BattlePartyImpl>> =
|
||||||
Rc::new(BattlePartyImmutableList::from_ref(reference))
|
FFIArray::from_u64(battle_get_parties(reference).unwrap());
|
||||||
|
let parties =
|
||||||
|
Vec::from_raw_parts(parties.ptr(), parties.len(), parties.len());
|
||||||
|
let parties = parties
|
||||||
|
.into_iter()
|
||||||
|
.map::<BattleParty, _>(|r| Rc::new(BattlePartyImpl::new(r)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
parties
|
||||||
}),
|
}),
|
||||||
sides: cached_value!({
|
sides: cached_value!({
|
||||||
let reference = battle_get_sides(reference);
|
let sides: FFIArray<ExternRef<BattleSideImpl>> =
|
||||||
Rc::new(BattleSideImmutableList::from_ref(reference))
|
FFIArray::from_u64(battle_get_sides(reference).unwrap());
|
||||||
|
let sides = Vec::from_raw_parts(sides.ptr(), sides.len(), sides.len());
|
||||||
|
let sides = sides
|
||||||
|
.into_iter()
|
||||||
|
.map::<BattleSide, _>(|r| Rc::new(BattleSideImpl::new(r)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
sides
|
||||||
}),
|
}),
|
||||||
random: cached_value!({
|
random: cached_value!({
|
||||||
Rc::new(battle_get_random(reference).get_value().unwrap())
|
Rc::new(battle_get_random(reference).unwrap().get_value().unwrap())
|
||||||
}),
|
}),
|
||||||
choice_queue: cached_value!({
|
choice_queue: cached_value!({
|
||||||
Rc::new(battle_get_choice_queue(reference).get_value().unwrap())
|
Rc::new(
|
||||||
|
battle_get_choice_queue(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
@ -94,46 +112,53 @@ mod implementation {
|
||||||
impl BattleTrait for BattleImpl {
|
impl BattleTrait for BattleImpl {
|
||||||
cached_value_getters! {
|
cached_value_getters! {
|
||||||
fn library(&self) -> DynamicLibrary;
|
fn library(&self) -> DynamicLibrary;
|
||||||
fn parties(&self) -> ImmutableList<BattleParty>;
|
fn parties(&self) -> Vec<BattleParty>;
|
||||||
fn sides(&self) -> ImmutableList<BattleSide>;
|
fn sides(&self) -> Vec<BattleSide>;
|
||||||
fn random(&self) -> BattleRandom;
|
fn random(&self) -> BattleRandom;
|
||||||
fn choice_queue(&self) -> ChoiceQueue;
|
fn choice_queue(&self) -> ChoiceQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pokemon(&self, side: u8, index: u8) -> Option<Pokemon> {
|
fn get_pokemon(&self, side: u8, index: u8) -> PkmnResult<Option<Pokemon>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let v = battle_get_pokemon(self.inner.reference, side, index).get_value();
|
let v = battle_get_pokemon(self.inner.reference, side, index)
|
||||||
|
.as_res()?
|
||||||
|
.get_value();
|
||||||
if let Some(v) = v {
|
if let Some(v) = v {
|
||||||
Some(Rc::new(v))
|
Ok(Some(Rc::new(v)))
|
||||||
} else {
|
} else {
|
||||||
None
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> Option<BattleParty> {
|
fn find_party_for_pokemon(&self, pokemon: &Pokemon) -> PkmnResult<Option<BattleParty>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let b =
|
let b =
|
||||||
battle_find_party_for_pokemon(self.inner.reference, pokemon.reference().into())
|
battle_find_party_for_pokemon(self.inner.reference, pokemon.reference().into())
|
||||||
|
.as_res()?
|
||||||
.get_value();
|
.get_value();
|
||||||
if let Some(b) = b {
|
Ok(if let Some(b) = b {
|
||||||
Some(Rc::new(b))
|
Some(Rc::new(b))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn weather_name(&self) -> Option<StringKey> {
|
fn weather_name(&self) -> PkmnResult<Option<StringKey>> {
|
||||||
unsafe { battle_get_weather_name(self.inner.reference).get_value() }
|
unsafe {
|
||||||
|
Ok(battle_get_weather_name(self.inner.reference)
|
||||||
|
.as_res()?
|
||||||
|
.get_value())
|
||||||
}
|
}
|
||||||
fn has_weather(&self, name: &str) -> bool {
|
}
|
||||||
if let Some(weather) = self.weather_name() {
|
fn has_weather(&self, name: &str) -> PkmnResult<bool> {
|
||||||
|
if let Some(weather) = self.weather_name()? {
|
||||||
if weather.equals_str(name) {
|
if weather.equals_str(name) {
|
||||||
return true;
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm_value_getters_funcs! {
|
wasm_value_getters_funcs! {
|
||||||
|
@ -170,24 +195,29 @@ mod implementation {
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn battle_get_library(r: ExternRef<BattleImpl>) -> ExternRef<DynamicLibraryImpl>;
|
fn battle_get_library(
|
||||||
fn battle_get_parties(r: ExternRef<BattleImpl>) -> VecExternRef<BattlePartyImpl>;
|
r: ExternRef<BattleImpl>,
|
||||||
fn battle_get_sides(r: ExternRef<BattleImpl>) -> VecExternRef<BattleSideImpl>;
|
) -> WasmResult<ExternRef<DynamicLibraryImpl>>;
|
||||||
fn battle_get_random(r: ExternRef<BattleImpl>) -> ExternRef<BattleRandomImpl>;
|
fn battle_get_parties(r: ExternRef<BattleImpl>) -> WasmResult<u64>;
|
||||||
fn battle_get_choice_queue(r: ExternRef<BattleImpl>) -> ExternRef<ChoiceQueueImpl>;
|
fn battle_get_sides(r: ExternRef<BattleImpl>) -> WasmResult<u64>;
|
||||||
|
fn battle_get_random(r: ExternRef<BattleImpl>) -> WasmResult<ExternRef<BattleRandomImpl>>;
|
||||||
|
fn battle_get_choice_queue(
|
||||||
|
r: ExternRef<BattleImpl>,
|
||||||
|
) -> WasmResult<ExternRef<ChoiceQueueImpl>>;
|
||||||
fn battle_get_pokemon(
|
fn battle_get_pokemon(
|
||||||
r: ExternRef<BattleImpl>,
|
r: ExternRef<BattleImpl>,
|
||||||
side: u8,
|
side: u8,
|
||||||
index: u8,
|
index: u8,
|
||||||
) -> ExternRef<PokemonImpl>;
|
) -> WasmResult<ExternRef<PokemonImpl>>;
|
||||||
fn battle_find_party_for_pokemon(
|
fn battle_find_party_for_pokemon(
|
||||||
r: ExternRef<BattleImpl>,
|
r: ExternRef<BattleImpl>,
|
||||||
mon: ExternRef<PokemonImpl>,
|
mon: ExternRef<PokemonImpl>,
|
||||||
) -> ExternRef<BattlePartyImpl>;
|
) -> WasmResult<ExternRef<BattlePartyImpl>>;
|
||||||
|
|
||||||
fn battle_get_weather_name(r: ExternRef<BattleImpl>) -> ExternRef<StringKey>;
|
fn battle_get_weather_name(r: ExternRef<BattleImpl>) -> WasmResult<ExternRef<StringKey>>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::PkmnResult;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub use implementation::*;
|
pub use implementation::*;
|
||||||
|
|
|
@ -15,6 +15,7 @@ mod implementation {
|
||||||
use crate::app_interface::{BattlePartyTrait, Party, PartyImpl};
|
use crate::app_interface::{BattlePartyTrait, Party, PartyImpl};
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
|
use crate::handling::wasm_result::WasmResult;
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::Cacheable;
|
||||||
use crate::{cached_value, cached_value_getters};
|
use crate::{cached_value, cached_value_getters};
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
@ -35,7 +36,12 @@ mod implementation {
|
||||||
inner: Rc::new(BattlePartyInner {
|
inner: Rc::new(BattlePartyInner {
|
||||||
reference,
|
reference,
|
||||||
party: cached_value!({
|
party: cached_value!({
|
||||||
Rc::new(battle_party_get_party(reference).get_value().unwrap())
|
Rc::new(
|
||||||
|
battle_party_get_party(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
@ -59,7 +65,9 @@ mod implementation {
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn battle_party_get_party(r: ExternRef<BattlePartyImpl>) -> ExternRef<PartyImpl>;
|
fn battle_party_get_party(
|
||||||
|
r: ExternRef<BattlePartyImpl>,
|
||||||
|
) -> WasmResult<ExternRef<PartyImpl>>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
use crate::PkmnResult;
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
|
||||||
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
||||||
pub trait BattleRandomTrait {
|
pub trait BattleRandomTrait {
|
||||||
fn get(&self) -> i32;
|
fn get(&self) -> PkmnResult<i32>;
|
||||||
fn get_max(&self, max: i32) -> i32;
|
fn get_max(&self, max: i32) -> PkmnResult<i32>;
|
||||||
fn get_between(&self, min: i32, max: i32) -> i32;
|
fn get_between(&self, min: i32, max: i32) -> PkmnResult<i32>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type BattleRandom = Rc<dyn BattleRandomTrait>;
|
pub type BattleRandom = Rc<dyn BattleRandomTrait>;
|
||||||
|
@ -17,6 +18,7 @@ pub use implementation::*;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
mod implementation {
|
mod implementation {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::handling::wasm_result::WasmResult;
|
||||||
use crate::{ExternRef, ExternalReferenceType};
|
use crate::{ExternRef, ExternalReferenceType};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -26,16 +28,16 @@ mod implementation {
|
||||||
|
|
||||||
impl BattleRandomTrait for BattleRandomImpl {
|
impl BattleRandomTrait for BattleRandomImpl {
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
fn get(&self) -> i32 {
|
fn get(&self) -> PkmnResult<i32> {
|
||||||
unsafe { battle_random_get(self.reference) }
|
unsafe { battle_random_get(self.reference).as_res() }
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
fn get_max(&self, max: i32) -> i32 {
|
fn get_max(&self, max: i32) -> PkmnResult<i32> {
|
||||||
unsafe { battle_random_get_max(self.reference, max) }
|
unsafe { battle_random_get_max(self.reference, max).as_res() }
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
fn get_between(&self, min: i32, max: i32) -> i32 {
|
fn get_between(&self, min: i32, max: i32) -> PkmnResult<i32> {
|
||||||
unsafe { battle_random_get_between(self.reference, min, max) }
|
unsafe { battle_random_get_between(self.reference, min, max).as_res() }
|
||||||
}
|
}
|
||||||
// TODO: effect_chance()
|
// TODO: effect_chance()
|
||||||
}
|
}
|
||||||
|
@ -48,9 +50,13 @@ mod implementation {
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn battle_random_get(r: ExternRef<BattleRandomImpl>) -> i32;
|
fn battle_random_get(r: ExternRef<BattleRandomImpl>) -> WasmResult<i32>;
|
||||||
fn battle_random_get_max(r: ExternRef<BattleRandomImpl>, max: i32) -> i32;
|
fn battle_random_get_max(r: ExternRef<BattleRandomImpl>, max: i32) -> WasmResult<i32>;
|
||||||
fn battle_random_get_between(r: ExternRef<BattleRandomImpl>, min: i32, max: i32) -> i32;
|
fn battle_random_get_between(
|
||||||
|
r: ExternRef<BattleRandomImpl>,
|
||||||
|
min: i32,
|
||||||
|
max: i32,
|
||||||
|
) -> WasmResult<i32>;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ pub trait BattleSideTrait: WithVolatile {
|
||||||
fn pokemon_per_side(&self) -> u8;
|
fn pokemon_per_side(&self) -> u8;
|
||||||
fn battle(&self) -> Battle;
|
fn battle(&self) -> Battle;
|
||||||
fn get_pokemon(&self, index: usize) -> Option<Pokemon>;
|
fn get_pokemon(&self, index: usize) -> Option<Pokemon>;
|
||||||
fn has_fled_battle(&self) -> bool;
|
fn has_fled_battle(&self) -> PkmnResult<bool>;
|
||||||
fn is_defeated(&self) -> bool;
|
fn is_defeated(&self) -> PkmnResult<bool>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type BattleSide = Rc<dyn BattleSideTrait>;
|
pub type BattleSide = Rc<dyn BattleSideTrait>;
|
||||||
|
@ -18,10 +18,11 @@ mod implementation {
|
||||||
use crate::app_interface::{BattleImpl, PokemonImpl};
|
use crate::app_interface::{BattleImpl, PokemonImpl};
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
|
use crate::handling::wasm_result::{WasmResult, WasmVoidResult};
|
||||||
use crate::handling::{Cacheable, Script};
|
use crate::handling::{Cacheable, Script};
|
||||||
use crate::{
|
use crate::{
|
||||||
cached_value, cached_value_getters, wasm_value_getters_extern, wasm_value_getters_funcs,
|
cached_value, cached_value_getters, wasm_value_getters_extern, wasm_value_getters_funcs,
|
||||||
ScriptPtr,
|
PkmnResult, ScriptPtr,
|
||||||
};
|
};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use cstr_core::{c_char, CString};
|
use cstr_core::{c_char, CString};
|
||||||
|
@ -43,10 +44,17 @@ mod implementation {
|
||||||
Self::from_ref(reference, &|reference| Self {
|
Self::from_ref(reference, &|reference| Self {
|
||||||
inner: Rc::new(BattleSideInner {
|
inner: Rc::new(BattleSideInner {
|
||||||
reference,
|
reference,
|
||||||
side_index: cached_value!({ battleside_get_side_index(reference) }),
|
side_index: cached_value!({ battleside_get_side_index(reference).unwrap() }),
|
||||||
pokemon_per_side: cached_value!({ battleside_get_pokemon_per_side(reference) }),
|
pokemon_per_side: cached_value!({
|
||||||
|
battleside_get_pokemon_per_side(reference).unwrap()
|
||||||
|
}),
|
||||||
battle: cached_value!({
|
battle: cached_value!({
|
||||||
Rc::new(battleside_get_battle(reference).get_value().unwrap())
|
Rc::new(
|
||||||
|
battleside_get_battle(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
@ -62,7 +70,9 @@ mod implementation {
|
||||||
|
|
||||||
fn get_pokemon(&self, index: usize) -> Option<Pokemon> {
|
fn get_pokemon(&self, index: usize) -> Option<Pokemon> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let p = battleside_get_pokemon(self.inner.reference, index).get_value();
|
let p = battleside_get_pokemon(self.inner.reference, index)
|
||||||
|
.unwrap()
|
||||||
|
.get_value();
|
||||||
if let Some(p) = p {
|
if let Some(p) = p {
|
||||||
Some(Rc::new(p))
|
Some(Rc::new(p))
|
||||||
} else {
|
} else {
|
||||||
|
@ -79,39 +89,51 @@ mod implementation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WithVolatile for BattleSideImpl {
|
impl WithVolatile for BattleSideImpl {
|
||||||
fn has_volatile(&self, script_name: &str) -> bool {
|
fn has_volatile(&self, script_name: &str) -> PkmnResult<bool> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let script_name = CString::new(script_name).unwrap();
|
let script_name = CString::new(script_name).unwrap();
|
||||||
battleside_has_volatile(self.inner.reference, script_name.as_ptr())
|
battleside_has_volatile(self.inner.reference, script_name.as_ptr()).as_res()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn add_volatile(&self, script: Box<dyn Script>) -> &dyn Script {
|
fn add_volatile(&self, script: Box<dyn Script>) -> PkmnResult<&dyn Script> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
Ok(
|
||||||
battleside_add_volatile(self.inner.reference, ScriptPtr::new(script))
|
battleside_add_volatile(self.inner.reference, ScriptPtr::new(script))
|
||||||
|
.as_res()?
|
||||||
.val()
|
.val()
|
||||||
.unwrap()
|
.unwrap(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script {
|
fn add_volatile_by_name(&self, script_name: &str) -> PkmnResult<&dyn Script> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = CString::new(script_name).unwrap();
|
let ptr = CString::new(script_name).unwrap();
|
||||||
|
Ok(
|
||||||
battleside_add_volatile_by_name(self.inner.reference, ptr.as_ptr())
|
battleside_add_volatile_by_name(self.inner.reference, ptr.as_ptr())
|
||||||
|
.as_res()?
|
||||||
.val()
|
.val()
|
||||||
.unwrap()
|
.unwrap(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_volatile(&self, script: &dyn Script) {
|
fn remove_volatile(&self, script: &dyn Script) -> PkmnResult<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let name = CString::new(script.get_name()).unwrap();
|
let name = CString::new(script.get_name()).unwrap();
|
||||||
battleside_remove_volatile(self.inner.reference, name.as_ptr());
|
battleside_remove_volatile(self.inner.reference, name.as_ptr()).as_res()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_volatile_script(&self, script_name: &str) -> Option<&dyn Script> {
|
fn get_volatile_script(&self, script_name: &str) -> PkmnResult<Option<&dyn Script>> {
|
||||||
let script_name = CString::new(script_name).unwrap();
|
let script_name = CString::new(script_name).unwrap();
|
||||||
unsafe { battleside_get_volatile(self.inner.reference, script_name.as_ptr()).val() }
|
unsafe {
|
||||||
|
Ok(
|
||||||
|
battleside_get_volatile(self.inner.reference, script_name.as_ptr())
|
||||||
|
.as_res()?
|
||||||
|
.val(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,24 +152,38 @@ mod implementation {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn battleside_get_side_index(r: ExternRef<BattleSideImpl>) -> u8;
|
fn battleside_get_side_index(r: ExternRef<BattleSideImpl>) -> WasmResult<u8>;
|
||||||
fn battleside_get_pokemon_per_side(r: ExternRef<BattleSideImpl>) -> u8;
|
fn battleside_get_pokemon_per_side(r: ExternRef<BattleSideImpl>) -> WasmResult<u8>;
|
||||||
fn battleside_get_battle(r: ExternRef<BattleSideImpl>) -> ExternRef<BattleImpl>;
|
fn battleside_get_battle(r: ExternRef<BattleSideImpl>)
|
||||||
|
-> WasmResult<ExternRef<BattleImpl>>;
|
||||||
fn battleside_get_pokemon(
|
fn battleside_get_pokemon(
|
||||||
r: ExternRef<BattleSideImpl>,
|
r: ExternRef<BattleSideImpl>,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> ExternRef<PokemonImpl>;
|
) -> WasmResult<ExternRef<PokemonImpl>>;
|
||||||
|
|
||||||
fn battleside_add_volatile_by_name(
|
fn battleside_add_volatile_by_name(
|
||||||
r: ExternRef<BattleSideImpl>,
|
r: ExternRef<BattleSideImpl>,
|
||||||
name: *const c_char,
|
name: *const c_char,
|
||||||
) -> ScriptPtr;
|
) -> WasmResult<ScriptPtr>;
|
||||||
fn battleside_add_volatile(r: ExternRef<BattleSideImpl>, script: ScriptPtr) -> ScriptPtr;
|
fn battleside_add_volatile(
|
||||||
fn battleside_has_volatile(r: ExternRef<BattleSideImpl>, name: *const c_char) -> bool;
|
r: ExternRef<BattleSideImpl>,
|
||||||
fn battleside_remove_volatile(r: ExternRef<BattleSideImpl>, name: *const c_char);
|
script: ScriptPtr,
|
||||||
fn battleside_get_volatile(r: ExternRef<BattleSideImpl>, name: *const c_char) -> ScriptPtr;
|
) -> WasmResult<ScriptPtr>;
|
||||||
|
fn battleside_has_volatile(
|
||||||
|
r: ExternRef<BattleSideImpl>,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> WasmResult<bool>;
|
||||||
|
fn battleside_remove_volatile(
|
||||||
|
r: ExternRef<BattleSideImpl>,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> WasmVoidResult;
|
||||||
|
fn battleside_get_volatile(
|
||||||
|
r: ExternRef<BattleSideImpl>,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> WasmResult<ScriptPtr>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::PkmnResult;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub use implementation::*;
|
pub use implementation::*;
|
||||||
|
|
|
@ -3,7 +3,7 @@ use alloc::rc::Rc;
|
||||||
|
|
||||||
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
||||||
pub trait ChoiceQueueTrait {
|
pub trait ChoiceQueueTrait {
|
||||||
fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> bool;
|
fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> PkmnResult<bool>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ChoiceQueue = Rc<dyn ChoiceQueueTrait>;
|
pub type ChoiceQueue = Rc<dyn ChoiceQueueTrait>;
|
||||||
|
@ -14,7 +14,8 @@ pub type MockChoiceQueue = MockChoiceQueueTrait;
|
||||||
mod implementation {
|
mod implementation {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::app_interface::PokemonImpl;
|
use crate::app_interface::PokemonImpl;
|
||||||
use crate::{ExternRef, ExternalReferenceType};
|
use crate::handling::wasm_result::WasmResult;
|
||||||
|
use crate::{ExternRef, ExternalReferenceType, PkmnResult};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ChoiceQueueImpl {
|
pub struct ChoiceQueueImpl {
|
||||||
|
@ -28,9 +29,10 @@ mod implementation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChoiceQueueTrait for ChoiceQueueImpl {
|
impl ChoiceQueueTrait for ChoiceQueueImpl {
|
||||||
fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> bool {
|
fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> PkmnResult<bool> {
|
||||||
unsafe {
|
unsafe {
|
||||||
choice_queue_move_pokemon_choice_next(self.reference, pokemon.reference().into())
|
choice_queue_move_pokemon_choice_next(self.reference, pokemon.reference().into())
|
||||||
|
.as_res()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,9 +47,10 @@ mod implementation {
|
||||||
fn choice_queue_move_pokemon_choice_next(
|
fn choice_queue_move_pokemon_choice_next(
|
||||||
r: ExternRef<ChoiceQueueImpl>,
|
r: ExternRef<ChoiceQueueImpl>,
|
||||||
pokemon: ExternRef<PokemonImpl>,
|
pokemon: ExternRef<PokemonImpl>,
|
||||||
) -> bool;
|
) -> WasmResult<bool>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::PkmnResult;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub use implementation::*;
|
pub use implementation::*;
|
||||||
|
|
|
@ -15,6 +15,7 @@ mod implementation {
|
||||||
use crate::cached_value;
|
use crate::cached_value;
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
|
use crate::handling::wasm_result::WasmResult;
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::Cacheable;
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
|
||||||
|
@ -36,7 +37,12 @@ mod implementation {
|
||||||
inner: Rc::new(DynamicLibraryInner {
|
inner: Rc::new(DynamicLibraryInner {
|
||||||
ptr,
|
ptr,
|
||||||
static_data: cached_value!({
|
static_data: cached_value!({
|
||||||
Rc::new(dynamic_library_get_static_data(ptr).get_value().unwrap())
|
Rc::new(
|
||||||
|
dynamic_library_get_static_data(ptr)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
@ -58,7 +64,7 @@ mod implementation {
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn dynamic_library_get_static_data(
|
fn dynamic_library_get_static_data(
|
||||||
ptr: ExternRef<DynamicLibraryImpl>,
|
ptr: ExternRef<DynamicLibraryImpl>,
|
||||||
) -> ExternRef<StaticDataImpl>;
|
) -> WasmResult<ExternRef<StaticDataImpl>>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::app_interface::{LearnedMove, MoveData, Pokemon};
|
use crate::app_interface::{LearnedMove, MoveData, Pokemon};
|
||||||
use crate::handling::Script;
|
use crate::handling::Script;
|
||||||
|
use alloc::boxed::Box;
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
|
||||||
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
||||||
|
@ -8,25 +9,25 @@ pub trait ExecutingMoveTrait {
|
||||||
fn user(&self) -> Pokemon;
|
fn user(&self) -> Pokemon;
|
||||||
fn chosen_move(&self) -> LearnedMove;
|
fn chosen_move(&self) -> LearnedMove;
|
||||||
fn use_move(&self) -> MoveData;
|
fn use_move(&self) -> MoveData;
|
||||||
fn move_script<'a>(&'a self) -> Option<&'a dyn Script>;
|
fn move_script<'a>(&'a self) -> PkmnResult<Option<&'a Box<dyn Script>>>;
|
||||||
fn number_of_targets(&self) -> usize;
|
fn number_of_targets(&self) -> PkmnResult<usize>;
|
||||||
fn is_pokemon_target(&self, pokemon: &Pokemon) -> bool;
|
fn is_pokemon_target(&self, pokemon: &Pokemon) -> PkmnResult<bool>;
|
||||||
fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> HitData;
|
fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> PkmnResult<HitData>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
||||||
pub trait HitDataTrait {
|
pub trait HitDataTrait {
|
||||||
fn is_critical(&self) -> bool;
|
fn is_critical(&self) -> PkmnResult<bool>;
|
||||||
fn base_power(&self) -> u8;
|
fn base_power(&self) -> PkmnResult<u8>;
|
||||||
fn effectiveness(&self) -> f32;
|
fn effectiveness(&self) -> PkmnResult<f32>;
|
||||||
fn damage(&self) -> u32;
|
fn damage(&self) -> PkmnResult<u32>;
|
||||||
fn move_type(&self) -> u8;
|
fn move_type(&self) -> PkmnResult<u8>;
|
||||||
fn has_failed(&self) -> bool;
|
fn has_failed(&self) -> PkmnResult<bool>;
|
||||||
fn set_critical(&self, critical: bool);
|
fn set_critical(&self, critical: bool) -> PkmnResult<()>;
|
||||||
fn set_effectiveness(&self, effectiveness: f32);
|
fn set_effectiveness(&self, effectiveness: f32) -> PkmnResult<()>;
|
||||||
fn set_damage(&self, damage: u32);
|
fn set_damage(&self, damage: u32) -> PkmnResult<()>;
|
||||||
fn set_move_type(&self, move_type: u8);
|
fn set_move_type(&self, move_type: u8) -> PkmnResult<()>;
|
||||||
fn fail(&self);
|
fn fail(&self) -> PkmnResult<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ExecutingMove = Rc<dyn ExecutingMoveTrait>;
|
pub type ExecutingMove = Rc<dyn ExecutingMoveTrait>;
|
||||||
|
@ -37,6 +38,7 @@ pub type HitData = Rc<dyn HitDataTrait>;
|
||||||
#[cfg(feature = "mock_data")]
|
#[cfg(feature = "mock_data")]
|
||||||
pub type MockHitData = MockHitDataTrait;
|
pub type MockHitData = MockHitDataTrait;
|
||||||
|
|
||||||
|
use crate::PkmnResult;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub use implementation::*;
|
pub use implementation::*;
|
||||||
|
|
||||||
|
@ -44,10 +46,12 @@ pub use implementation::*;
|
||||||
mod implementation {
|
mod implementation {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::app_interface::{LearnedMoveImpl, MoveDataImpl, PokemonImpl};
|
use crate::app_interface::{LearnedMoveImpl, MoveDataImpl, PokemonImpl};
|
||||||
use crate::cached_value;
|
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
use crate::handling::temporary::Temporary;
|
use crate::handling::temporary::Temporary;
|
||||||
|
use crate::handling::wasm_result::WasmResult;
|
||||||
|
use crate::{cached_value, PkmnResult};
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ExecutingMoveImpl {
|
pub struct ExecutingMoveImpl {
|
||||||
|
@ -71,20 +75,31 @@ mod implementation {
|
||||||
ExecutingMoveInner {
|
ExecutingMoveInner {
|
||||||
reference,
|
reference,
|
||||||
number_of_hits: cached_value!({
|
number_of_hits: cached_value!({
|
||||||
executing_move_get_number_of_hits(reference)
|
executing_move_get_number_of_hits(reference).unwrap()
|
||||||
}),
|
}),
|
||||||
user: cached_value!({
|
user: cached_value!({
|
||||||
Rc::new(executing_move_get_user(reference).get_value().unwrap())
|
Rc::new(
|
||||||
|
executing_move_get_user(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
chosen_move: cached_value!({
|
chosen_move: cached_value!({
|
||||||
Rc::new(
|
Rc::new(
|
||||||
executing_move_get_chosen_move(reference)
|
executing_move_get_chosen_move(reference)
|
||||||
|
.unwrap()
|
||||||
.get_value()
|
.get_value()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
use_move: cached_value!({
|
use_move: cached_value!({
|
||||||
Rc::new(executing_move_get_use_move(reference).get_value().unwrap())
|
Rc::new(
|
||||||
|
executing_move_get_use_move(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -106,31 +121,39 @@ mod implementation {
|
||||||
fn use_move(&self) -> MoveData {
|
fn use_move(&self) -> MoveData {
|
||||||
self.inner.value().use_move.value()
|
self.inner.value().use_move.value()
|
||||||
}
|
}
|
||||||
fn move_script(&self) -> Option<&dyn Script> {
|
fn move_script(&self) -> PkmnResult<Option<&Box<dyn Script>>> {
|
||||||
unsafe { executing_move_get_script(self.inner.value().reference).as_ref() }
|
unsafe {
|
||||||
|
Ok(
|
||||||
|
(executing_move_get_script(self.inner.value().reference).as_res()?
|
||||||
|
as *const Box<dyn Script>)
|
||||||
|
.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 {
|
fn number_of_targets(&self) -> PkmnResult<usize> {
|
||||||
|
unsafe { executing_move_get_number_of_targets(self.inner.value().reference).as_res() }
|
||||||
|
}
|
||||||
|
fn is_pokemon_target(&self, pokemon: &Pokemon) -> PkmnResult<bool> {
|
||||||
unsafe {
|
unsafe {
|
||||||
executing_move_is_pokemon_target(
|
executing_move_is_pokemon_target(
|
||||||
self.inner.value().reference,
|
self.inner.value().reference,
|
||||||
pokemon.reference().into(),
|
pokemon.reference().into(),
|
||||||
)
|
)
|
||||||
|
.as_res()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> HitData {
|
fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> PkmnResult<HitData> {
|
||||||
unsafe {
|
unsafe {
|
||||||
Rc::new(
|
Ok(Rc::new(
|
||||||
executing_move_get_hit_data(
|
executing_move_get_hit_data(
|
||||||
self.inner.value().reference,
|
self.inner.value().reference,
|
||||||
pokemon.reference().into(),
|
pokemon.reference().into(),
|
||||||
hit,
|
hit,
|
||||||
)
|
)
|
||||||
|
.as_res()?
|
||||||
.get_value()
|
.get_value()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,39 +165,39 @@ mod implementation {
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
impl HitDataTrait for HitDataImpl {
|
impl HitDataTrait for HitDataImpl {
|
||||||
fn is_critical(&self) -> bool {
|
fn is_critical(&self) -> PkmnResult<bool> {
|
||||||
unsafe { hit_data_is_critical(self.reference) }
|
unsafe { hit_data_is_critical(self.reference).as_res() }
|
||||||
}
|
}
|
||||||
fn base_power(&self) -> u8 {
|
fn base_power(&self) -> PkmnResult<u8> {
|
||||||
unsafe { hit_data_get_base_power(self.reference) }
|
unsafe { hit_data_get_base_power(self.reference).as_res() }
|
||||||
}
|
}
|
||||||
fn effectiveness(&self) -> f32 {
|
fn effectiveness(&self) -> PkmnResult<f32> {
|
||||||
unsafe { hit_data_get_effectiveness(self.reference) }
|
unsafe { hit_data_get_effectiveness(self.reference).as_res() }
|
||||||
}
|
}
|
||||||
fn damage(&self) -> u32 {
|
fn damage(&self) -> PkmnResult<u32> {
|
||||||
unsafe { hit_data_get_damage(self.reference) }
|
unsafe { hit_data_get_damage(self.reference).as_res() }
|
||||||
}
|
}
|
||||||
fn move_type(&self) -> u8 {
|
fn move_type(&self) -> PkmnResult<u8> {
|
||||||
unsafe { hit_data_get_move_type(self.reference) }
|
unsafe { hit_data_get_move_type(self.reference).as_res() }
|
||||||
}
|
}
|
||||||
fn has_failed(&self) -> bool {
|
fn has_failed(&self) -> PkmnResult<bool> {
|
||||||
unsafe { hit_data_is_critical(self.reference) }
|
unsafe { hit_data_is_critical(self.reference).as_res() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_critical(&self, critical: bool) {
|
fn set_critical(&self, critical: bool) -> PkmnResult<()> {
|
||||||
unsafe { hit_data_set_critical(self.reference, critical) }
|
unsafe { hit_data_set_critical(self.reference, critical).as_res() }
|
||||||
}
|
}
|
||||||
fn set_effectiveness(&self, effectiveness: f32) {
|
fn set_effectiveness(&self, effectiveness: f32) -> PkmnResult<()> {
|
||||||
unsafe { hit_data_set_effectiveness(self.reference, effectiveness) }
|
unsafe { hit_data_set_effectiveness(self.reference, effectiveness).as_res() }
|
||||||
}
|
}
|
||||||
fn set_damage(&self, damage: u32) {
|
fn set_damage(&self, damage: u32) -> PkmnResult<()> {
|
||||||
unsafe { hit_data_set_damage(self.reference, damage) }
|
unsafe { hit_data_set_damage(self.reference, damage).as_res() }
|
||||||
}
|
}
|
||||||
fn set_move_type(&self, move_type: u8) {
|
fn set_move_type(&self, move_type: u8) -> PkmnResult<()> {
|
||||||
unsafe { hit_data_set_move_type(self.reference, move_type) }
|
unsafe { hit_data_set_move_type(self.reference, move_type).as_res() }
|
||||||
}
|
}
|
||||||
fn fail(&self) {
|
fn fail(&self) -> PkmnResult<()> {
|
||||||
unsafe { hit_data_fail(self.reference) }
|
unsafe { hit_data_fail(self.reference).as_res() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,38 +217,47 @@ mod implementation {
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn executing_move_get_number_of_targets(r: ExternRef<ExecutingMoveImpl>) -> usize;
|
fn executing_move_get_number_of_targets(
|
||||||
fn executing_move_get_number_of_hits(r: ExternRef<ExecutingMoveImpl>) -> u8;
|
r: ExternRef<ExecutingMoveImpl>,
|
||||||
fn executing_move_get_user(r: ExternRef<ExecutingMoveImpl>) -> ExternRef<PokemonImpl>;
|
) -> WasmResult<usize>;
|
||||||
|
fn executing_move_get_number_of_hits(r: ExternRef<ExecutingMoveImpl>) -> WasmResult<u8>;
|
||||||
|
fn executing_move_get_user(
|
||||||
|
r: ExternRef<ExecutingMoveImpl>,
|
||||||
|
) -> WasmResult<ExternRef<PokemonImpl>>;
|
||||||
fn executing_move_get_chosen_move(
|
fn executing_move_get_chosen_move(
|
||||||
r: ExternRef<ExecutingMoveImpl>,
|
r: ExternRef<ExecutingMoveImpl>,
|
||||||
) -> ExternRef<LearnedMoveImpl>;
|
) -> WasmResult<ExternRef<LearnedMoveImpl>>;
|
||||||
fn executing_move_get_use_move(r: ExternRef<ExecutingMoveImpl>) -> ExternRef<MoveDataImpl>;
|
fn executing_move_get_use_move(
|
||||||
|
r: ExternRef<ExecutingMoveImpl>,
|
||||||
|
) -> WasmResult<ExternRef<MoveDataImpl>>;
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
fn executing_move_get_script(r: ExternRef<ExecutingMoveImpl>) -> *const dyn Script;
|
fn executing_move_get_script(r: ExternRef<ExecutingMoveImpl>) -> WasmResult<u32>;
|
||||||
|
|
||||||
fn executing_move_is_pokemon_target(
|
fn executing_move_is_pokemon_target(
|
||||||
r: ExternRef<ExecutingMoveImpl>,
|
r: ExternRef<ExecutingMoveImpl>,
|
||||||
pokemon: ExternRef<PokemonImpl>,
|
pokemon: ExternRef<PokemonImpl>,
|
||||||
) -> bool;
|
) -> WasmResult<bool>;
|
||||||
fn executing_move_get_hit_data(
|
fn executing_move_get_hit_data(
|
||||||
r: ExternRef<ExecutingMoveImpl>,
|
r: ExternRef<ExecutingMoveImpl>,
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
) -> ExternRef<HitDataImpl>;
|
) -> WasmResult<ExternRef<HitDataImpl>>;
|
||||||
|
|
||||||
fn hit_data_is_critical(r: ExternRef<HitDataImpl>) -> bool;
|
fn hit_data_is_critical(r: ExternRef<HitDataImpl>) -> WasmResult<bool>;
|
||||||
fn hit_data_get_base_power(r: ExternRef<HitDataImpl>) -> u8;
|
fn hit_data_get_base_power(r: ExternRef<HitDataImpl>) -> WasmResult<u8>;
|
||||||
fn hit_data_get_effectiveness(r: ExternRef<HitDataImpl>) -> f32;
|
fn hit_data_get_effectiveness(r: ExternRef<HitDataImpl>) -> WasmResult<f32>;
|
||||||
fn hit_data_get_damage(r: ExternRef<HitDataImpl>) -> u32;
|
fn hit_data_get_damage(r: ExternRef<HitDataImpl>) -> WasmResult<u32>;
|
||||||
fn hit_data_get_move_type(r: ExternRef<HitDataImpl>) -> u8;
|
fn hit_data_get_move_type(r: ExternRef<HitDataImpl>) -> WasmResult<u8>;
|
||||||
fn hit_data_has_failed(r: ExternRef<HitDataImpl>) -> bool;
|
fn hit_data_has_failed(r: ExternRef<HitDataImpl>) -> WasmResult<bool>;
|
||||||
|
|
||||||
fn hit_data_set_critical(r: ExternRef<HitDataImpl>, critical: bool);
|
fn hit_data_set_critical(r: ExternRef<HitDataImpl>, critical: bool) -> WasmResult<()>;
|
||||||
fn hit_data_set_base_power(r: ExternRef<HitDataImpl>, power: u8);
|
fn hit_data_set_base_power(r: ExternRef<HitDataImpl>, power: u8) -> WasmResult<()>;
|
||||||
fn hit_data_set_effectiveness(r: ExternRef<HitDataImpl>, effectiveness: f32);
|
fn hit_data_set_effectiveness(
|
||||||
fn hit_data_set_damage(r: ExternRef<HitDataImpl>, damage: u32);
|
r: ExternRef<HitDataImpl>,
|
||||||
fn hit_data_set_move_type(r: ExternRef<HitDataImpl>, move_type: u8);
|
effectiveness: f32,
|
||||||
fn hit_data_fail(r: ExternRef<HitDataImpl>);
|
) -> WasmResult<()>;
|
||||||
|
fn hit_data_set_damage(r: ExternRef<HitDataImpl>, damage: u32) -> WasmResult<()>;
|
||||||
|
fn hit_data_set_move_type(r: ExternRef<HitDataImpl>, move_type: u8) -> WasmResult<()>;
|
||||||
|
fn hit_data_fail(r: ExternRef<HitDataImpl>) -> WasmResult<()>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ mod implementation {
|
||||||
use crate::app_interface::MoveDataImpl;
|
use crate::app_interface::MoveDataImpl;
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
|
use crate::handling::wasm_result::WasmResult;
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::Cacheable;
|
||||||
use crate::{cached_value, cached_value_getters, wasm_value_getters};
|
use crate::{cached_value, cached_value_getters, wasm_value_getters};
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
@ -58,9 +59,16 @@ mod implementation {
|
||||||
inner: Rc::new(LearnedMoveInner {
|
inner: Rc::new(LearnedMoveInner {
|
||||||
reference,
|
reference,
|
||||||
move_data: cached_value!({
|
move_data: cached_value!({
|
||||||
Rc::new(learned_move_get_move_data(reference).get_value().unwrap())
|
Rc::new(
|
||||||
|
learned_move_get_move_data(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
learn_method: cached_value!({
|
||||||
|
learned_move_get_learn_method(reference).unwrap()
|
||||||
}),
|
}),
|
||||||
learn_method: cached_value!({ learned_move_get_learn_method(reference) }),
|
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -92,10 +100,14 @@ mod implementation {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn learned_move_get_move_data(r: ExternRef<LearnedMoveImpl>) -> ExternRef<MoveDataImpl>;
|
fn learned_move_get_move_data(
|
||||||
fn learned_move_get_learn_method(r: ExternRef<LearnedMoveImpl>) -> MoveLearnMethod;
|
r: ExternRef<LearnedMoveImpl>,
|
||||||
fn learned_move_restore_uses(r: ExternRef<LearnedMoveImpl>, uses: u8);
|
) -> WasmResult<ExternRef<MoveDataImpl>>;
|
||||||
fn learned_move_restore_all_uses(r: ExternRef<LearnedMoveImpl>);
|
fn learned_move_get_learn_method(
|
||||||
|
r: ExternRef<LearnedMoveImpl>,
|
||||||
|
) -> WasmResult<MoveLearnMethod>;
|
||||||
|
fn learned_move_restore_uses(r: ExternRef<LearnedMoveImpl>, uses: u8) -> WasmResult<()>;
|
||||||
|
fn learned_move_restore_all_uses(r: ExternRef<LearnedMoveImpl>) -> WasmResult<()>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ use core::iter::IntoIterator;
|
||||||
|
|
||||||
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
||||||
pub trait PartyTrait {
|
pub trait PartyTrait {
|
||||||
fn get_pokemon(&self, index: usize) -> Option<Pokemon>;
|
fn get_pokemon(&self, index: usize) -> PkmnResult<Option<Pokemon>>;
|
||||||
fn length(&self) -> usize;
|
fn length(&self) -> PkmnResult<usize>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Party = Rc<dyn PartyTrait>;
|
pub type Party = Rc<dyn PartyTrait>;
|
||||||
|
@ -16,7 +16,10 @@ impl<'a> IntoIterator for &'a dyn PartyTrait {
|
||||||
type IntoIter = ExternIterator<'a, Self::Item>;
|
type IntoIter = ExternIterator<'a, Self::Item>;
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
ExternIterator::new(self.length(), Box::new(move |i| self.get_pokemon(i)))
|
ExternIterator::new(
|
||||||
|
self.length().unwrap(),
|
||||||
|
Box::new(move |i| self.get_pokemon(i).unwrap()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +31,8 @@ mod implementation {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::app_interface::PokemonImpl;
|
use crate::app_interface::PokemonImpl;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
|
use crate::handling::wasm_result::WasmResult;
|
||||||
|
use crate::PkmnResult;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PartyImpl {
|
pub struct PartyImpl {
|
||||||
|
@ -41,19 +46,21 @@ mod implementation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartyTrait for PartyImpl {
|
impl PartyTrait for PartyImpl {
|
||||||
fn get_pokemon(&self, index: usize) -> Option<Pokemon> {
|
fn get_pokemon(&self, index: usize) -> PkmnResult<Option<Pokemon>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let v = party_get_pokemon(self.reference, index).get_value();
|
let v = party_get_pokemon(self.reference, index)
|
||||||
if let Some(v) = v {
|
.as_res()?
|
||||||
|
.get_value();
|
||||||
|
Ok(if let Some(v) = v {
|
||||||
Some(Rc::new(v))
|
Some(Rc::new(v))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn length(&self) -> usize {
|
fn length(&self) -> PkmnResult<usize> {
|
||||||
unsafe { party_get_length(self.reference) }
|
unsafe { party_get_length(self.reference).as_res() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,11 +71,15 @@ mod implementation {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn party_get_pokemon(r: ExternRef<PartyImpl>, index: usize) -> ExternRef<PokemonImpl>;
|
fn party_get_pokemon(
|
||||||
fn party_get_length(r: ExternRef<PartyImpl>) -> usize;
|
r: ExternRef<PartyImpl>,
|
||||||
|
index: usize,
|
||||||
|
) -> WasmResult<ExternRef<PokemonImpl>>;
|
||||||
|
fn party_get_length(r: ExternRef<PartyImpl>) -> WasmResult<usize>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::utils::ExternIterator;
|
use crate::utils::ExternIterator;
|
||||||
|
use crate::PkmnResult;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub use implementation::*;
|
pub use implementation::*;
|
||||||
|
|
|
@ -8,36 +8,37 @@ use alloc::boxed::Box;
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use cstr_core::c_char;
|
use cstr_core::c_char;
|
||||||
|
|
||||||
|
use crate::PkmnResult;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub use implementation::*;
|
pub use implementation::*;
|
||||||
|
|
||||||
pub trait PokemonTrait: WithVolatile {
|
pub trait PokemonTrait: WithVolatile {
|
||||||
fn reference(&self) -> u32;
|
fn reference(&self) -> u32;
|
||||||
|
|
||||||
fn species(&self) -> Species;
|
fn species(&self) -> PkmnResult<Species>;
|
||||||
fn form(&self) -> Form;
|
fn form(&self) -> PkmnResult<Form>;
|
||||||
fn active_ability(&self) -> Ability;
|
fn active_ability(&self) -> PkmnResult<Ability>;
|
||||||
fn nature(&self) -> Nature;
|
fn nature(&self) -> PkmnResult<Nature>;
|
||||||
fn display_species(&self) -> Species;
|
fn display_species(&self) -> PkmnResult<Species>;
|
||||||
fn display_form(&self) -> Form;
|
fn display_form(&self) -> PkmnResult<Form>;
|
||||||
fn held_item(&self) -> Option<Item>;
|
fn held_item(&self) -> PkmnResult<Option<Item>>;
|
||||||
fn battle(&self) -> Option<Battle>;
|
fn battle(&self) -> PkmnResult<Option<Battle>>;
|
||||||
fn level(&self) -> LevelInt;
|
fn level(&self) -> PkmnResult<LevelInt>;
|
||||||
fn experience(&self) -> u32;
|
fn experience(&self) -> PkmnResult<u32>;
|
||||||
fn unique_identifier(&self) -> u32;
|
fn unique_identifier(&self) -> PkmnResult<u32>;
|
||||||
fn gender(&self) -> Gender;
|
fn gender(&self) -> PkmnResult<Gender>;
|
||||||
fn coloring(&self) -> u8;
|
fn coloring(&self) -> PkmnResult<u8>;
|
||||||
fn current_health(&self) -> u32;
|
fn current_health(&self) -> PkmnResult<u32>;
|
||||||
fn weight(&self) -> f32;
|
fn weight(&self) -> PkmnResult<f32>;
|
||||||
fn height(&self) -> f32;
|
fn height(&self) -> PkmnResult<f32>;
|
||||||
fn nickname(&self) -> *const c_char;
|
fn nickname(&self) -> PkmnResult<*const c_char>;
|
||||||
fn real_ability(&self) -> AbilityIndex;
|
fn real_ability(&self) -> PkmnResult<AbilityIndex>;
|
||||||
fn types_length(&self) -> usize;
|
fn types_length(&self) -> PkmnResult<usize>;
|
||||||
fn battle_side_index(&self) -> u8;
|
fn battle_side_index(&self) -> PkmnResult<u8>;
|
||||||
fn battle_index(&self) -> u8;
|
fn battle_index(&self) -> PkmnResult<u8>;
|
||||||
fn is_ability_overriden(&self) -> u8;
|
fn is_ability_overriden(&self) -> PkmnResult<u8>;
|
||||||
fn allowed_experience_gain(&self) -> bool;
|
fn allowed_experience_gain(&self) -> PkmnResult<bool>;
|
||||||
fn is_usable(&self) -> bool;
|
fn is_usable(&self) -> PkmnResult<bool>;
|
||||||
|
|
||||||
fn library(&self) -> DynamicLibrary;
|
fn library(&self) -> DynamicLibrary;
|
||||||
fn flat_stats(&self) -> StatisticSet<u32>;
|
fn flat_stats(&self) -> StatisticSet<u32>;
|
||||||
|
@ -45,25 +46,30 @@ pub trait PokemonTrait: WithVolatile {
|
||||||
fn boosted_stats(&self) -> StatisticSet<u32>;
|
fn boosted_stats(&self) -> StatisticSet<u32>;
|
||||||
fn individual_values(&self) -> ClampedStatisticSet<u8>;
|
fn individual_values(&self) -> ClampedStatisticSet<u8>;
|
||||||
fn effort_values(&self) -> ClampedStatisticSet<u8>;
|
fn effort_values(&self) -> ClampedStatisticSet<u8>;
|
||||||
fn has_held_item(&self, name: &str) -> bool;
|
fn has_held_item(&self, name: &str) -> PkmnResult<bool>;
|
||||||
fn set_held_item(&self, item: &Item) -> Option<Item>;
|
fn set_held_item(&self, item: &Item) -> PkmnResult<Option<Item>>;
|
||||||
fn remove_held_item(&self) -> Option<Item>;
|
fn remove_held_item(&self) -> PkmnResult<Option<Item>>;
|
||||||
fn consume_held_item(&self) -> bool;
|
fn consume_held_item(&self) -> PkmnResult<bool>;
|
||||||
fn max_health(&self) -> u32;
|
fn max_health(&self) -> PkmnResult<u32>;
|
||||||
fn get_type(&self, index: usize) -> u8;
|
fn get_type(&self, index: usize) -> PkmnResult<u8>;
|
||||||
fn has_type(&self, type_identifier: TypeIdentifier) -> bool;
|
fn has_type(&self, type_identifier: TypeIdentifier) -> PkmnResult<bool>;
|
||||||
fn has_type_by_name(&self, type_name: &str) -> bool;
|
fn has_type_by_name(&self, type_name: &str) -> PkmnResult<bool>;
|
||||||
fn get_learned_move(&self, index: usize) -> Option<LearnedMove>;
|
fn get_learned_move(&self, index: usize) -> PkmnResult<Option<LearnedMove>>;
|
||||||
fn change_stat_boost(&self, stat: Statistic, diff_amount: i8, self_inflicted: bool) -> bool;
|
fn change_stat_boost(
|
||||||
fn ability_script(&self) -> Option<&Box<dyn Script>>;
|
&self,
|
||||||
|
stat: Statistic,
|
||||||
|
diff_amount: i8,
|
||||||
|
self_inflicted: bool,
|
||||||
|
) -> PkmnResult<bool>;
|
||||||
|
fn ability_script(&self) -> PkmnResult<Option<&Box<dyn Script>>>;
|
||||||
fn change_species(&self, species: Species, form: Form);
|
fn change_species(&self, species: Species, form: Form);
|
||||||
fn change_form(&self, form: Form);
|
fn change_form(&self, form: Form);
|
||||||
fn is_fainted(&self) -> bool;
|
fn is_fainted(&self) -> PkmnResult<bool>;
|
||||||
fn damage(&self, damage: u32, source: DamageSource);
|
fn damage(&self, damage: u32, source: DamageSource) -> PkmnResult<()>;
|
||||||
fn heal(&self, amount: u32, allow_revive: bool) -> bool;
|
fn heal(&self, amount: u32, allow_revive: bool) -> PkmnResult<bool>;
|
||||||
fn set_weight(&self, weight: f32);
|
fn set_weight(&self, weight: f32);
|
||||||
fn clear_status(&self);
|
fn clear_status(&self);
|
||||||
fn battle_side(&self) -> BattleSide;
|
fn battle_side(&self) -> PkmnResult<BattleSide>;
|
||||||
fn equals(&self, other: &Pokemon) -> bool;
|
fn equals(&self, other: &Pokemon) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +90,7 @@ pub enum DamageSource {
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
mod implementation {
|
mod implementation {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use core::mem::transmute;
|
||||||
use cstr_core::CString;
|
use cstr_core::CString;
|
||||||
|
|
||||||
use crate::app_interface::dynamic_data::dynamic_library::DynamicLibraryImpl;
|
use crate::app_interface::dynamic_data::dynamic_library::DynamicLibraryImpl;
|
||||||
|
@ -92,12 +99,13 @@ mod implementation {
|
||||||
StatisticSetImpl,
|
StatisticSetImpl,
|
||||||
};
|
};
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
|
use crate::handling::wasm_result::WasmResult;
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::Cacheable;
|
||||||
use crate::implementation::ScriptPtr;
|
use crate::implementation::ScriptPtr;
|
||||||
use crate::{
|
use crate::{
|
||||||
cached_value, cached_value_getters, wasm_optional_reference_getters_extern,
|
cached_value, cached_value_getters, wasm_optional_reference_getters_extern,
|
||||||
wasm_reference_getters_extern, wasm_value_getters_extern, wasm_value_getters_funcs,
|
wasm_reference_getters_extern, wasm_value_getters_extern, wasm_value_getters_funcs,
|
||||||
ExternRef, ExternalReferenceType,
|
ExternRef, ExternalReferenceType, PkmnResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PokemonInner {
|
struct PokemonInner {
|
||||||
|
@ -134,90 +142,154 @@ mod implementation {
|
||||||
fn effort_values(&self) -> ClampedStatisticSet<u8>;
|
fn effort_values(&self) -> ClampedStatisticSet<u8>;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn active_ability(&self) -> Ability {
|
fn nickname(&self) -> PkmnResult<*const u8> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let nickname = pokemon_get_nickname(self.inner.reference).as_res()?;
|
||||||
|
Ok(nickname as *const u8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn species(&self) -> PkmnResult<Species> {
|
||||||
|
Ok(unsafe {
|
||||||
|
Rc::new(
|
||||||
|
pokemon_get_species(self.inner.reference)
|
||||||
|
.as_res()?
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn form(&self) -> PkmnResult<Form> {
|
||||||
|
Ok(unsafe {
|
||||||
|
Rc::new(
|
||||||
|
pokemon_get_form(self.inner.reference)
|
||||||
|
.as_res()?
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn active_ability(&self) -> PkmnResult<Ability> {
|
||||||
|
Ok(unsafe {
|
||||||
let implementation = pokemon_get_active_ability(self.reference())
|
let implementation = pokemon_get_active_ability(self.reference())
|
||||||
|
.as_res()?
|
||||||
.get_value()
|
.get_value()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Rc::new(implementation)
|
Rc::new(implementation)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
fn nature(&self) -> PkmnResult<Nature> {
|
||||||
|
Ok(unsafe {
|
||||||
|
Rc::new(
|
||||||
|
pokemon_get_nature(self.inner.reference)
|
||||||
|
.as_res()?
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
fn held_item(&self) -> Option<Item> {
|
fn display_species(&self) -> PkmnResult<Species> {
|
||||||
unsafe {
|
Ok(unsafe {
|
||||||
let i = pokemon_get_held_item(self.inner.reference).get_value();
|
Rc::new(
|
||||||
if let Some(i) = i {
|
pokemon_get_display_species(self.inner.reference)
|
||||||
Some(Rc::new(i))
|
.as_res()?
|
||||||
} else {
|
.get_value()
|
||||||
None
|
.unwrap(),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
fn display_form(&self) -> PkmnResult<Form> {
|
||||||
|
Ok(unsafe {
|
||||||
|
Rc::new(
|
||||||
|
pokemon_get_display_form(self.inner.reference)
|
||||||
|
.as_res()?
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
fn held_item(&self) -> PkmnResult<Option<Item>> {
|
||||||
fn battle(&self) -> Option<Battle> {
|
Ok(unsafe {
|
||||||
unsafe {
|
let i = pokemon_get_held_item(self.inner.reference)
|
||||||
let b = pokemon_get_battle(self.reference()).get_value();
|
.as_res()?
|
||||||
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();
|
.get_value();
|
||||||
if let Some(i) = i {
|
if let Some(i) = i {
|
||||||
Some(Rc::new(i))
|
Some(Rc::new(i))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
fn battle(&self) -> PkmnResult<Option<Battle>> {
|
||||||
fn remove_held_item(&self) -> Option<Item> {
|
Ok(unsafe {
|
||||||
unsafe {
|
let b = pokemon_get_battle(self.reference()).as_res()?.get_value();
|
||||||
let i = pokemon_remove_held_item(self.inner.reference).get_value();
|
if let Some(b) = b {
|
||||||
if let Some(i) = i {
|
Some(Rc::new(b))
|
||||||
Some(Rc::new(i))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn has_held_item(&self, name: &str) -> PkmnResult<bool> {
|
||||||
|
let cstr = CString::new(name).unwrap();
|
||||||
|
unsafe { pokemon_has_held_item(self.inner.reference, cstr.as_ptr()).as_res() }
|
||||||
|
}
|
||||||
|
fn set_held_item(&self, item: &Item) -> PkmnResult<Option<Item>> {
|
||||||
|
unsafe {
|
||||||
|
let i = pokemon_set_held_item(self.inner.reference, item.reference().into())
|
||||||
|
.as_res()?
|
||||||
|
.get_value();
|
||||||
|
Ok(if let Some(i) = i {
|
||||||
|
Some(Rc::new(i))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn consume_held_item(&self) -> bool {
|
fn remove_held_item(&self) -> PkmnResult<Option<Item>> {
|
||||||
unsafe { pokemon_consume_held_item(self.inner.reference) }
|
unsafe {
|
||||||
|
let i = pokemon_remove_held_item(self.inner.reference)
|
||||||
|
.as_res()?
|
||||||
|
.get_value();
|
||||||
|
Ok(if let Some(i) = i {
|
||||||
|
Some(Rc::new(i))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
})
|
||||||
}
|
}
|
||||||
fn max_health(&self) -> u32 {
|
}
|
||||||
|
fn consume_held_item(&self) -> PkmnResult<bool> {
|
||||||
|
unsafe { pokemon_consume_held_item(self.inner.reference).as_res() }
|
||||||
|
}
|
||||||
|
fn max_health(&self) -> PkmnResult<u32> {
|
||||||
self.boosted_stats().hp()
|
self.boosted_stats().hp()
|
||||||
}
|
}
|
||||||
fn get_type(&self, index: usize) -> u8 {
|
fn get_type(&self, index: usize) -> PkmnResult<u8> {
|
||||||
unsafe { pokemon_get_type(self.inner.reference, index) }
|
unsafe { pokemon_get_type(self.inner.reference, index).as_res() }
|
||||||
}
|
}
|
||||||
fn has_type(&self, type_identifier: TypeIdentifier) -> bool {
|
fn has_type(&self, type_identifier: TypeIdentifier) -> PkmnResult<bool> {
|
||||||
unsafe { pokemon_has_type(self.inner.reference, type_identifier.into()) }
|
unsafe { pokemon_has_type(self.inner.reference, type_identifier.into()).as_res() }
|
||||||
}
|
}
|
||||||
fn has_type_by_name(&self, type_name: &str) -> bool {
|
fn has_type_by_name(&self, type_name: &str) -> PkmnResult<bool> {
|
||||||
let type_identifier = self
|
let type_identifier = self
|
||||||
.library()
|
.library()
|
||||||
.data_library()
|
.data_library()
|
||||||
.type_library()
|
.type_library()
|
||||||
.get_type_from_name(type_name);
|
.get_type_from_name(type_name)?;
|
||||||
if let Some(type_identifier) = type_identifier {
|
if let Some(type_identifier) = type_identifier {
|
||||||
return self.has_type(type_identifier);
|
return self.has_type(type_identifier);
|
||||||
}
|
}
|
||||||
false
|
Ok(false)
|
||||||
}
|
}
|
||||||
fn get_learned_move(&self, index: usize) -> Option<LearnedMove> {
|
fn get_learned_move(&self, index: usize) -> PkmnResult<Option<LearnedMove>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let v = pokemon_get_learned_move(self.inner.reference, index).get_value();
|
let v = pokemon_get_learned_move(self.inner.reference, index)
|
||||||
if let Some(v) = v {
|
.as_res()?
|
||||||
|
.get_value();
|
||||||
|
Ok(if let Some(v) = v {
|
||||||
Some(Rc::new(v))
|
Some(Rc::new(v))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn change_stat_boost(
|
fn change_stat_boost(
|
||||||
|
@ -225,13 +297,18 @@ mod implementation {
|
||||||
stat: Statistic,
|
stat: Statistic,
|
||||||
diff_amount: i8,
|
diff_amount: i8,
|
||||||
self_inflicted: bool,
|
self_inflicted: bool,
|
||||||
) -> bool {
|
) -> PkmnResult<bool> {
|
||||||
unsafe {
|
unsafe {
|
||||||
pokemon_change_stat_boost(self.inner.reference, stat, diff_amount, self_inflicted)
|
pokemon_change_stat_boost(self.inner.reference, stat, diff_amount, self_inflicted)
|
||||||
|
.as_res()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn ability_script(&self) -> Option<&Box<dyn Script>> {
|
fn ability_script(&self) -> PkmnResult<Option<&Box<dyn Script>>> {
|
||||||
unsafe { pokemon_get_ability_script(self.inner.reference).as_ref() }
|
unsafe {
|
||||||
|
Ok((pokemon_get_ability_script(self.inner.reference).as_res()?
|
||||||
|
as *const Box<dyn Script>)
|
||||||
|
.as_ref())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn change_species(&self, species: Species, form: Form) {
|
fn change_species(&self, species: Species, form: Form) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -245,81 +322,44 @@ mod implementation {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_form(&self, form: Form) {
|
fn change_form(&self, form: Form) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let form_impl = form.as_any().downcast_ref_unchecked::<FormImpl>();
|
let form_impl = form.as_any().downcast_ref_unchecked::<FormImpl>();
|
||||||
pokemon_change_form(self.inner.reference, form_impl.reference());
|
pokemon_change_form(self.inner.reference, form_impl.reference());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn is_fainted(&self) -> bool {
|
|
||||||
self.current_health() == 0
|
fn is_fainted(&self) -> PkmnResult<bool> {
|
||||||
|
Ok(self.current_health()? == 0)
|
||||||
}
|
}
|
||||||
fn damage(&self, damage: u32, source: DamageSource) {
|
fn damage(&self, damage: u32, source: DamageSource) -> PkmnResult<()> {
|
||||||
unsafe { pokemon_damage(self.inner.reference, damage, source) }
|
unsafe { pokemon_damage(self.inner.reference, damage, source).as_res() }
|
||||||
}
|
}
|
||||||
fn heal(&self, amount: u32, allow_revive: bool) -> bool {
|
|
||||||
unsafe { pokemon_heal(self.inner.reference, amount, allow_revive) }
|
fn heal(&self, amount: u32, allow_revive: bool) -> PkmnResult<bool> {
|
||||||
|
unsafe { pokemon_heal(self.inner.reference, amount, allow_revive).as_res() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_weight(&self, weight: f32) {
|
fn set_weight(&self, weight: f32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
pokemon_set_weight(self.reference(), weight);
|
pokemon_set_weight(self.reference(), weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nature(&self) -> Nature {
|
|
||||||
unsafe {
|
|
||||||
Rc::new(
|
|
||||||
pokemon_get_nature(self.inner.reference)
|
|
||||||
.get_value()
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn species(&self) -> Species {
|
|
||||||
unsafe {
|
|
||||||
Rc::new(
|
|
||||||
pokemon_get_species(self.inner.reference)
|
|
||||||
.get_value()
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn form(&self) -> Form {
|
|
||||||
unsafe { Rc::new(pokemon_get_form(self.inner.reference).get_value().unwrap()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear_status(&self) {
|
fn clear_status(&self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
pokemon_clear_status(self.reference());
|
pokemon_clear_status(self.reference());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_species(&self) -> Species {
|
fn battle_side(&self) -> PkmnResult<BattleSide> {
|
||||||
unsafe {
|
Ok(self
|
||||||
Rc::new(
|
.battle()?
|
||||||
pokemon_get_display_species(self.inner.reference)
|
|
||||||
.get_value()
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn display_form(&self) -> Form {
|
|
||||||
unsafe {
|
|
||||||
Rc::new(
|
|
||||||
pokemon_get_display_form(self.inner.reference)
|
|
||||||
.get_value()
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn battle_side(&self) -> BattleSide {
|
|
||||||
self.battle()
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.sides()
|
.sides()
|
||||||
.get(self.battle_side_index() as u32)
|
.get(self.battle_side_index()? as usize)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
@ -333,8 +373,6 @@ mod implementation {
|
||||||
fn current_health(&self) -> u32;
|
fn current_health(&self) -> u32;
|
||||||
fn weight(&self) -> f32;
|
fn weight(&self) -> f32;
|
||||||
fn height(&self) -> f32;
|
fn height(&self) -> f32;
|
||||||
fn nickname(&self) -> *const c_char;
|
|
||||||
fn real_ability(&self) -> AbilityIndex;
|
|
||||||
fn types_length(&self) -> usize;
|
fn types_length(&self) -> usize;
|
||||||
fn battle_side_index(&self) -> u8;
|
fn battle_side_index(&self) -> u8;
|
||||||
fn battle_index(&self) -> u8;
|
fn battle_index(&self) -> u8;
|
||||||
|
@ -349,45 +387,66 @@ mod implementation {
|
||||||
.get_internal_index()
|
.get_internal_index()
|
||||||
.eq(&other.reference())
|
.eq(&other.reference())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn real_ability(&self) -> PkmnResult<AbilityIndex> {
|
||||||
|
unsafe {
|
||||||
|
let real_ability = pokemon_get_real_ability(self.reference()).as_res()?;
|
||||||
|
let split: (u8, u8) = transmute(real_ability);
|
||||||
|
Ok(AbilityIndex {
|
||||||
|
index: split.0,
|
||||||
|
hidden: split.1 == 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
impl WithVolatile for PokemonImpl {
|
impl WithVolatile for PokemonImpl {
|
||||||
fn has_volatile(&self, script_name: &str) -> bool {
|
fn has_volatile(&self, script_name: &str) -> PkmnResult<bool> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = CString::new(script_name).unwrap();
|
let ptr = CString::new(script_name).unwrap();
|
||||||
pokemon_has_volatile(self.inner.reference, ptr.as_ptr())
|
pokemon_has_volatile(self.inner.reference, ptr.as_ptr()).as_res()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_volatile(&self, script: Box<dyn Script>) -> &dyn Script {
|
fn add_volatile(&self, script: Box<dyn Script>) -> PkmnResult<&dyn Script> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
Ok(
|
||||||
pokemon_add_volatile(self.inner.reference, ScriptPtr::new(script))
|
pokemon_add_volatile(self.inner.reference, ScriptPtr::new(script))
|
||||||
|
.as_res()?
|
||||||
.val()
|
.val()
|
||||||
.unwrap()
|
.unwrap(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script {
|
fn add_volatile_by_name(&self, script_name: &str) -> PkmnResult<&dyn Script> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = CString::new(script_name).unwrap();
|
let ptr = CString::new(script_name).unwrap();
|
||||||
|
Ok(
|
||||||
pokemon_add_volatile_by_name(self.inner.reference, ptr.as_ptr())
|
pokemon_add_volatile_by_name(self.inner.reference, ptr.as_ptr())
|
||||||
|
.as_res()?
|
||||||
.val()
|
.val()
|
||||||
.unwrap()
|
.unwrap(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_volatile(&self, script: &dyn Script) {
|
fn remove_volatile(&self, script: &dyn Script) -> PkmnResult<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let name = CString::new(script.get_name()).unwrap();
|
let name = CString::new(script.get_name()).unwrap();
|
||||||
pokemon_remove_volatile(self.inner.reference, name.as_ptr());
|
pokemon_remove_volatile(self.inner.reference, name.as_ptr()).as_res()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_volatile_script(&self, script_name: &str) -> Option<&dyn Script> {
|
fn get_volatile_script(&self, script_name: &str) -> PkmnResult<Option<&dyn Script>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let script_name = CString::new(script_name).unwrap();
|
let script_name = CString::new(script_name).unwrap();
|
||||||
pokemon_get_volatile(self.inner.reference, script_name.as_ptr()).val()
|
Ok(
|
||||||
|
pokemon_get_volatile(self.inner.reference, script_name.as_ptr())
|
||||||
|
.as_res()?
|
||||||
|
.val(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -398,24 +457,41 @@ mod implementation {
|
||||||
inner: Rc::new(PokemonInner {
|
inner: Rc::new(PokemonInner {
|
||||||
reference,
|
reference,
|
||||||
library: cached_value!({
|
library: cached_value!({
|
||||||
Rc::new(pokemon_get_library(reference).get_value().unwrap())
|
Rc::new(pokemon_get_library(reference).unwrap().get_value().unwrap())
|
||||||
}),
|
}),
|
||||||
flat_stats: cached_value!({
|
flat_stats: cached_value!({
|
||||||
Rc::new(pokemon_get_flat_stats(reference).get_value().unwrap())
|
Rc::new(
|
||||||
|
pokemon_get_flat_stats(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
stat_boosts: cached_value!({
|
stat_boosts: cached_value!({
|
||||||
pokemon_get_stat_boosts(reference).get_value().unwrap()
|
pokemon_get_stat_boosts(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
boosted_stats: cached_value!({
|
boosted_stats: cached_value!({
|
||||||
Rc::new(pokemon_get_boosted_stats(reference).get_value().unwrap())
|
Rc::new(
|
||||||
|
pokemon_get_boosted_stats(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
individual_values: cached_value!({
|
individual_values: cached_value!({
|
||||||
pokemon_get_individual_values(reference)
|
pokemon_get_individual_values(reference)
|
||||||
|
.unwrap()
|
||||||
.get_value()
|
.get_value()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
effort_values: cached_value!({
|
effort_values: cached_value!({
|
||||||
pokemon_get_effort_values(reference).get_value().unwrap()
|
pokemon_get_effort_values(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
@ -430,14 +506,14 @@ mod implementation {
|
||||||
PokemonImpl, Pokemon,
|
PokemonImpl, Pokemon,
|
||||||
pub fn species(&self) -> SpeciesImpl;
|
pub fn species(&self) -> SpeciesImpl;
|
||||||
pub fn form(&self) -> FormImpl;
|
pub fn form(&self) -> FormImpl;
|
||||||
|
pub fn display_species(&self) -> SpeciesImpl;
|
||||||
|
pub fn display_form(&self) -> FormImpl;
|
||||||
pub fn active_ability(&self) -> AbilityImpl;
|
pub fn active_ability(&self) -> AbilityImpl;
|
||||||
pub fn nature(&self) -> NatureImpl;
|
pub fn nature(&self) -> NatureImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm_optional_reference_getters_extern! {
|
wasm_optional_reference_getters_extern! {
|
||||||
PokemonImpl, Pokemon,
|
PokemonImpl, Pokemon,
|
||||||
pub fn display_species(&self) -> Option<SpeciesImpl>;
|
|
||||||
pub fn display_form(&self) -> Option<FormImpl>;
|
|
||||||
pub fn held_item(&self) -> Option<ItemImpl>;
|
pub fn held_item(&self) -> Option<ItemImpl>;
|
||||||
pub fn battle(&self) -> Option<BattleImpl>;
|
pub fn battle(&self) -> Option<BattleImpl>;
|
||||||
}
|
}
|
||||||
|
@ -452,8 +528,7 @@ mod implementation {
|
||||||
pub fn current_health(&self) -> u32;
|
pub fn current_health(&self) -> u32;
|
||||||
pub fn weight(&self) -> f32;
|
pub fn weight(&self) -> f32;
|
||||||
pub fn height(&self) -> f32;
|
pub fn height(&self) -> f32;
|
||||||
pub fn nickname(&self) -> *const c_char;
|
pub fn real_ability(&self) -> u16;
|
||||||
pub fn real_ability(&self) -> AbilityIndex;
|
|
||||||
pub fn types_length(&self) -> usize;
|
pub fn types_length(&self) -> usize;
|
||||||
pub fn battle_side_index(&self) -> u8;
|
pub fn battle_side_index(&self) -> u8;
|
||||||
pub fn battle_index(&self) -> u8;
|
pub fn battle_index(&self) -> u8;
|
||||||
|
@ -477,58 +552,89 @@ mod implementation {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn pokemon_get_library(r: ExternRef<PokemonImpl>) -> ExternRef<DynamicLibraryImpl>;
|
fn pokemon_get_nickname(r: ExternRef<PokemonImpl>) -> WasmResult<u32>;
|
||||||
fn pokemon_get_flat_stats(r: ExternRef<PokemonImpl>) -> ExternRef<StatisticSetImpl<u32>>;
|
fn pokemon_get_library(
|
||||||
fn pokemon_get_stat_boosts(r: ExternRef<PokemonImpl>)
|
r: ExternRef<PokemonImpl>,
|
||||||
-> ExternRef<ClampedStatisticSet<i8>>;
|
) -> WasmResult<ExternRef<DynamicLibraryImpl>>;
|
||||||
fn pokemon_get_boosted_stats(r: ExternRef<PokemonImpl>)
|
fn pokemon_get_flat_stats(
|
||||||
-> ExternRef<StatisticSetImpl<u32>>;
|
r: ExternRef<PokemonImpl>,
|
||||||
|
) -> WasmResult<ExternRef<StatisticSetImpl<u32>>>;
|
||||||
|
fn pokemon_get_stat_boosts(
|
||||||
|
r: ExternRef<PokemonImpl>,
|
||||||
|
) -> WasmResult<ExternRef<ClampedStatisticSet<i8>>>;
|
||||||
|
fn pokemon_get_boosted_stats(
|
||||||
|
r: ExternRef<PokemonImpl>,
|
||||||
|
) -> WasmResult<ExternRef<StatisticSetImpl<u32>>>;
|
||||||
fn pokemon_get_individual_values(
|
fn pokemon_get_individual_values(
|
||||||
r: ExternRef<PokemonImpl>,
|
r: ExternRef<PokemonImpl>,
|
||||||
) -> ExternRef<ClampedStatisticSet<u8>>;
|
) -> WasmResult<ExternRef<ClampedStatisticSet<u8>>>;
|
||||||
fn pokemon_get_effort_values(
|
fn pokemon_get_effort_values(
|
||||||
r: ExternRef<PokemonImpl>,
|
r: ExternRef<PokemonImpl>,
|
||||||
) -> ExternRef<ClampedStatisticSet<u8>>;
|
) -> WasmResult<ExternRef<ClampedStatisticSet<u8>>>;
|
||||||
fn pokemon_has_held_item(r: ExternRef<PokemonImpl>, name: *const c_char) -> bool;
|
fn pokemon_has_held_item(
|
||||||
|
r: ExternRef<PokemonImpl>,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> WasmResult<bool>;
|
||||||
fn pokemon_set_held_item(
|
fn pokemon_set_held_item(
|
||||||
r: ExternRef<PokemonImpl>,
|
r: ExternRef<PokemonImpl>,
|
||||||
item: ExternRef<ItemImpl>,
|
item: ExternRef<ItemImpl>,
|
||||||
) -> ExternRef<ItemImpl>;
|
) -> WasmResult<ExternRef<ItemImpl>>;
|
||||||
fn pokemon_remove_held_item(r: ExternRef<PokemonImpl>) -> ExternRef<ItemImpl>;
|
fn pokemon_remove_held_item(r: ExternRef<PokemonImpl>) -> WasmResult<ExternRef<ItemImpl>>;
|
||||||
fn pokemon_consume_held_item(r: ExternRef<PokemonImpl>) -> bool;
|
fn pokemon_consume_held_item(r: ExternRef<PokemonImpl>) -> WasmResult<bool>;
|
||||||
fn pokemon_get_type(r: ExternRef<PokemonImpl>, index: usize) -> u8;
|
fn pokemon_get_type(r: ExternRef<PokemonImpl>, index: usize) -> WasmResult<u8>;
|
||||||
fn pokemon_has_type(r: ExternRef<PokemonImpl>, identifier: u8) -> bool;
|
fn pokemon_has_type(r: ExternRef<PokemonImpl>, identifier: u8) -> WasmResult<bool>;
|
||||||
fn pokemon_get_learned_move(
|
fn pokemon_get_learned_move(
|
||||||
r: ExternRef<PokemonImpl>,
|
r: ExternRef<PokemonImpl>,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> ExternRef<LearnedMoveImpl>;
|
) -> WasmResult<ExternRef<LearnedMoveImpl>>;
|
||||||
fn pokemon_change_stat_boost(
|
fn pokemon_change_stat_boost(
|
||||||
r: ExternRef<PokemonImpl>,
|
r: ExternRef<PokemonImpl>,
|
||||||
tat: Statistic,
|
tat: Statistic,
|
||||||
diff_amount: i8,
|
diff_amount: i8,
|
||||||
self_inflicted: bool,
|
self_inflicted: bool,
|
||||||
) -> bool;
|
) -> WasmResult<bool>;
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
fn pokemon_get_ability_script(r: ExternRef<PokemonImpl>) -> *const Box<dyn Script>;
|
fn pokemon_get_ability_script(r: ExternRef<PokemonImpl>) -> WasmResult<u32>;
|
||||||
fn pokemon_change_species(
|
fn pokemon_change_species(
|
||||||
r: ExternRef<PokemonImpl>,
|
r: ExternRef<PokemonImpl>,
|
||||||
species: ExternRef<SpeciesImpl>,
|
species: ExternRef<SpeciesImpl>,
|
||||||
form: ExternRef<FormImpl>,
|
form: ExternRef<FormImpl>,
|
||||||
);
|
) -> WasmResult<()>;
|
||||||
fn pokemon_change_form(r: ExternRef<PokemonImpl>, form: ExternRef<FormImpl>);
|
fn pokemon_change_form(
|
||||||
fn pokemon_damage(r: ExternRef<PokemonImpl>, damage: u32, source: DamageSource);
|
r: ExternRef<PokemonImpl>,
|
||||||
fn pokemon_heal(r: ExternRef<PokemonImpl>, amount: u32, allow_revive: bool) -> bool;
|
form: ExternRef<FormImpl>,
|
||||||
fn pokemon_set_weight(r: ExternRef<PokemonImpl>, weight: f32);
|
) -> WasmResult<()>;
|
||||||
fn pokemon_clear_status(r: ExternRef<PokemonImpl>);
|
fn pokemon_damage(
|
||||||
|
r: ExternRef<PokemonImpl>,
|
||||||
|
damage: u32,
|
||||||
|
source: DamageSource,
|
||||||
|
) -> WasmResult<()>;
|
||||||
|
fn pokemon_heal(
|
||||||
|
r: ExternRef<PokemonImpl>,
|
||||||
|
amount: u32,
|
||||||
|
allow_revive: bool,
|
||||||
|
) -> WasmResult<bool>;
|
||||||
|
fn pokemon_set_weight(r: ExternRef<PokemonImpl>, weight: f32) -> WasmResult<()>;
|
||||||
|
fn pokemon_clear_status(r: ExternRef<PokemonImpl>) -> WasmResult<()>;
|
||||||
|
|
||||||
fn pokemon_add_volatile_by_name(
|
fn pokemon_add_volatile_by_name(
|
||||||
r: ExternRef<PokemonImpl>,
|
r: ExternRef<PokemonImpl>,
|
||||||
name: *const c_char,
|
name: *const c_char,
|
||||||
) -> ScriptPtr;
|
) -> WasmResult<ScriptPtr>;
|
||||||
fn pokemon_add_volatile(r: ExternRef<PokemonImpl>, script: ScriptPtr) -> ScriptPtr;
|
fn pokemon_add_volatile(
|
||||||
fn pokemon_has_volatile(r: ExternRef<PokemonImpl>, name: *const c_char) -> bool;
|
r: ExternRef<PokemonImpl>,
|
||||||
fn pokemon_remove_volatile(r: ExternRef<PokemonImpl>, name: *const c_char);
|
script: ScriptPtr,
|
||||||
fn pokemon_get_volatile(r: ExternRef<PokemonImpl>, name: *const c_char) -> ScriptPtr;
|
) -> WasmResult<ScriptPtr>;
|
||||||
|
fn pokemon_has_volatile(r: ExternRef<PokemonImpl>, name: *const c_char)
|
||||||
|
-> WasmResult<bool>;
|
||||||
|
fn pokemon_remove_volatile(
|
||||||
|
r: ExternRef<PokemonImpl>,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> WasmResult<()>;
|
||||||
|
fn pokemon_get_volatile(
|
||||||
|
r: ExternRef<PokemonImpl>,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> WasmResult<ScriptPtr>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,30 +643,30 @@ mockall::mock!(
|
||||||
pub Pokemon {}
|
pub Pokemon {}
|
||||||
impl PokemonTrait for Pokemon {
|
impl PokemonTrait for Pokemon {
|
||||||
fn reference(&self) -> u32;
|
fn reference(&self) -> u32;
|
||||||
fn species(&self) -> Species;
|
fn species(&self) -> PkmnResult<Species>;
|
||||||
fn form(&self) -> Form;
|
fn form(&self) -> PkmnResult<Form>;
|
||||||
fn active_ability(&self) -> Ability;
|
fn active_ability(&self) -> PkmnResult<Ability>;
|
||||||
fn nature(&self) -> Nature;
|
fn nature(&self) -> PkmnResult<Nature>;
|
||||||
fn display_species(&self) -> Species;
|
fn display_species(&self) -> PkmnResult<Species>;
|
||||||
fn display_form(&self) -> Form;
|
fn display_form(&self) -> PkmnResult<Form>;
|
||||||
fn held_item(&self) -> Option<Item>;
|
fn held_item(&self) -> PkmnResult<Option<Item>>;
|
||||||
fn battle(&self) -> Option<Battle>;
|
fn battle(&self) -> PkmnResult<Option<Battle>>;
|
||||||
fn level(&self) -> LevelInt;
|
fn level(&self) -> PkmnResult<LevelInt>;
|
||||||
fn experience(&self) -> u32;
|
fn experience(&self) -> PkmnResult<u32>;
|
||||||
fn unique_identifier(&self) -> u32;
|
fn unique_identifier(&self) -> PkmnResult<u32>;
|
||||||
fn gender(&self) -> Gender;
|
fn gender(&self) -> PkmnResult<Gender>;
|
||||||
fn coloring(&self) -> u8;
|
fn coloring(&self) -> PkmnResult<u8>;
|
||||||
fn current_health(&self) -> u32;
|
fn current_health(&self) -> PkmnResult<u32>;
|
||||||
fn weight(&self) -> f32;
|
fn weight(&self) -> PkmnResult<f32>;
|
||||||
fn height(&self) -> f32;
|
fn height(&self) -> PkmnResult<f32>;
|
||||||
fn nickname(&self) -> *const c_char;
|
fn nickname(&self) -> PkmnResult<*const c_char>;
|
||||||
fn real_ability(&self) -> AbilityIndex;
|
fn real_ability(&self) -> PkmnResult<AbilityIndex>;
|
||||||
fn types_length(&self) -> usize;
|
fn types_length(&self) -> PkmnResult<usize>;
|
||||||
fn battle_side_index(&self) -> u8;
|
fn battle_side_index(&self) -> PkmnResult<u8>;
|
||||||
fn battle_index(&self) -> u8;
|
fn battle_index(&self) -> PkmnResult<u8>;
|
||||||
fn is_ability_overriden(&self) -> u8;
|
fn is_ability_overriden(&self) -> PkmnResult<u8>;
|
||||||
fn allowed_experience_gain(&self) -> bool;
|
fn allowed_experience_gain(&self) -> PkmnResult<bool>;
|
||||||
fn is_usable(&self) -> bool;
|
fn is_usable(&self) -> PkmnResult<bool>;
|
||||||
|
|
||||||
fn library(&self) -> DynamicLibrary;
|
fn library(&self) -> DynamicLibrary;
|
||||||
fn flat_stats(&self) -> StatisticSet<u32>;
|
fn flat_stats(&self) -> StatisticSet<u32>;
|
||||||
|
@ -568,44 +674,44 @@ mockall::mock!(
|
||||||
fn boosted_stats(&self) -> StatisticSet<u32>;
|
fn boosted_stats(&self) -> StatisticSet<u32>;
|
||||||
fn individual_values(&self) -> ClampedStatisticSet<u8>;
|
fn individual_values(&self) -> ClampedStatisticSet<u8>;
|
||||||
fn effort_values(&self) -> ClampedStatisticSet<u8>;
|
fn effort_values(&self) -> ClampedStatisticSet<u8>;
|
||||||
fn has_held_item(&self, name: &str) -> bool;
|
fn has_held_item(&self, name: &str) -> PkmnResult<bool>;
|
||||||
fn set_held_item(&self, item: &Item) -> Option<Item>;
|
fn set_held_item(&self, item: &Item) -> PkmnResult<Option<Item>>;
|
||||||
fn remove_held_item(&self) -> Option<Item>;
|
fn remove_held_item(&self) -> PkmnResult<Option<Item>>;
|
||||||
fn consume_held_item(&self) -> bool;
|
fn consume_held_item(&self) -> PkmnResult<bool>;
|
||||||
fn max_health(&self) -> u32;
|
fn max_health(&self) -> PkmnResult<u32>;
|
||||||
fn get_type(&self, index: usize) -> u8;
|
fn get_type(&self, index: usize) -> PkmnResult<u8>;
|
||||||
fn has_type(&self, type_identifier: TypeIdentifier) -> bool;
|
fn has_type(&self, type_identifier: TypeIdentifier) -> PkmnResult<bool>;
|
||||||
fn has_type_by_name(&self, type_name: &str) -> bool;
|
fn has_type_by_name(&self, type_name: &str) -> PkmnResult<bool>;
|
||||||
fn get_learned_move(&self, index: usize) -> Option<LearnedMove>;
|
fn get_learned_move(&self, index: usize) -> PkmnResult<Option<LearnedMove>>;
|
||||||
fn change_stat_boost(&self, stat: Statistic, diff_amount: i8, self_inflicted: bool) -> bool;
|
fn change_stat_boost(&self, stat: Statistic, diff_amount: i8, self_inflicted: bool) -> PkmnResult<bool>;
|
||||||
fn ability_script<'a>(&'a self) -> Option<&'a Box<dyn Script>>;
|
fn ability_script<'a>(&'a self) -> PkmnResult<Option<&'a Box<dyn Script>>>;
|
||||||
fn change_species(&self, species: Species, form: Form);
|
fn change_species(&self, species: Species, form: Form);
|
||||||
fn change_form(&self, form: Form);
|
fn change_form(&self, form: Form);
|
||||||
fn is_fainted(&self) -> bool;
|
fn is_fainted(&self) -> PkmnResult<bool>;
|
||||||
fn damage(&self, damage: u32, source: DamageSource);
|
fn damage(&self, damage: u32, source: DamageSource) -> PkmnResult<()>;
|
||||||
fn heal(&self, amount: u32, allow_revive: bool) -> bool;
|
fn heal(&self, amount: u32, allow_revive: bool) -> PkmnResult<bool>;
|
||||||
fn set_weight(&self, weight: f32);
|
fn set_weight(&self, weight: f32);
|
||||||
fn clear_status(&self);
|
fn clear_status(&self);
|
||||||
fn battle_side(&self) -> BattleSide;
|
fn battle_side(&self) -> PkmnResult<BattleSide>;
|
||||||
fn equals(&self, other: &Pokemon) -> bool;
|
fn equals(&self, other: &Pokemon) -> bool;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(feature = "mock_data")]
|
#[cfg(feature = "mock_data")]
|
||||||
impl WithVolatile for MockPokemon {
|
impl WithVolatile for MockPokemon {
|
||||||
fn has_volatile(&self, _script_name: &str) -> bool {
|
fn has_volatile(&self, _script_name: &str) -> PkmnResult<bool> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn add_volatile(&self, _script: Box<dyn Script>) -> &dyn Script {
|
fn add_volatile(&self, _script: Box<dyn Script>) -> PkmnResult<&dyn Script> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn add_volatile_by_name(&self, _script_name: &str) -> &dyn Script {
|
fn add_volatile_by_name(&self, _script_name: &str) -> PkmnResult<&dyn Script> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn remove_volatile(&self, _script: &dyn Script) {
|
fn remove_volatile(&self, _script: &dyn Script) -> PkmnResult<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn get_volatile_script<'a>(&'a self, _script_name: &str) -> Option<&'a dyn Script> {
|
fn get_volatile_script<'a>(&'a self, _script_name: &str) -> PkmnResult<Option<&'a dyn Script>> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use crate::app_interface::Statistic;
|
use crate::app_interface::Statistic;
|
||||||
use crate::{ExternRef, ExternalReferenceType};
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
use crate::handling::wasm_result::WasmResult;
|
||||||
|
use crate::{ExternRef, ExternalReferenceType, PkmnResult};
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use core::convert::{TryFrom, TryInto};
|
use core::convert::{TryFrom, TryInto};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
@ -12,28 +14,28 @@ where
|
||||||
<T as TryFrom<i64>>::Error: Debug,
|
<T as TryFrom<i64>>::Error: Debug,
|
||||||
<T as TryInto<i64>>::Error: Debug,
|
<T as TryInto<i64>>::Error: Debug,
|
||||||
{
|
{
|
||||||
fn hp(&self) -> T {
|
fn hp(&self) -> PkmnResult<T> {
|
||||||
self.get_stat(Statistic::Attack)
|
self.get_stat(Statistic::Attack)
|
||||||
}
|
}
|
||||||
fn attack(&self) -> T {
|
fn attack(&self) -> PkmnResult<T> {
|
||||||
self.get_stat(Statistic::Attack)
|
self.get_stat(Statistic::Attack)
|
||||||
}
|
}
|
||||||
fn defense(&self) -> T {
|
fn defense(&self) -> PkmnResult<T> {
|
||||||
self.get_stat(Statistic::Defense)
|
self.get_stat(Statistic::Defense)
|
||||||
}
|
}
|
||||||
fn special_attack(&self) -> T {
|
fn special_attack(&self) -> PkmnResult<T> {
|
||||||
self.get_stat(Statistic::SpecialAttack)
|
self.get_stat(Statistic::SpecialAttack)
|
||||||
}
|
}
|
||||||
fn special_defense(&self) -> T {
|
fn special_defense(&self) -> PkmnResult<T> {
|
||||||
self.get_stat(Statistic::SpecialDefense)
|
self.get_stat(Statistic::SpecialDefense)
|
||||||
}
|
}
|
||||||
fn speed(&self) -> T {
|
fn speed(&self) -> PkmnResult<T> {
|
||||||
self.get_stat(Statistic::Speed)
|
self.get_stat(Statistic::Speed)
|
||||||
}
|
}
|
||||||
fn get_stat(&self, stat: Statistic) -> T;
|
fn get_stat(&self, stat: Statistic) -> PkmnResult<T>;
|
||||||
fn set_stat(&self, stat: Statistic, value: T);
|
fn set_stat(&self, stat: Statistic, value: T) -> PkmnResult<()>;
|
||||||
fn increase_stat(&self, stat: Statistic, value: T);
|
fn increase_stat(&self, stat: Statistic, value: T) -> PkmnResult<()>;
|
||||||
fn decrease_stat(&self, stat: Statistic, value: T);
|
fn decrease_stat(&self, stat: Statistic, value: T) -> PkmnResult<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type StatisticSet<T> = Rc<dyn StatisticSetTrait<T>>;
|
pub type StatisticSet<T> = Rc<dyn StatisticSetTrait<T>>;
|
||||||
|
@ -74,24 +76,29 @@ where
|
||||||
<T as TryFrom<i64>>::Error: Debug,
|
<T as TryFrom<i64>>::Error: Debug,
|
||||||
<T as TryInto<i64>>::Error: Debug,
|
<T as TryInto<i64>>::Error: Debug,
|
||||||
{
|
{
|
||||||
fn get_stat(&self, stat: Statistic) -> T {
|
fn get_stat(&self, stat: Statistic) -> PkmnResult<T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
statistic_set_get(self.reference.cast(), stat)
|
Ok(statistic_set_get(self.reference.cast(), stat)
|
||||||
|
.as_res()?
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap()
|
.unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn set_stat(&self, stat: Statistic, value: T) {
|
fn set_stat(&self, stat: Statistic, value: T) -> PkmnResult<()> {
|
||||||
unsafe { statistic_set_set(self.reference.cast(), stat, value.try_into().unwrap()) }
|
unsafe {
|
||||||
|
statistic_set_set(self.reference.cast(), stat, value.try_into().unwrap()).as_res()
|
||||||
}
|
}
|
||||||
fn increase_stat(&self, stat: Statistic, value: T) {
|
}
|
||||||
|
fn increase_stat(&self, stat: Statistic, value: T) -> PkmnResult<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
statistic_set_increase_stat(self.reference.cast(), stat, value.try_into().unwrap())
|
statistic_set_increase_stat(self.reference.cast(), stat, value.try_into().unwrap())
|
||||||
|
.as_res()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn decrease_stat(&self, stat: Statistic, value: T) {
|
fn decrease_stat(&self, stat: Statistic, value: T) -> PkmnResult<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
statistic_set_decrease_stat(self.reference.cast(), stat, value.try_into().unwrap())
|
statistic_set_decrease_stat(self.reference.cast(), stat, value.try_into().unwrap())
|
||||||
|
.as_res()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,62 +143,68 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn hp(&self) -> T {
|
pub fn hp(&self) -> PkmnResult<T> {
|
||||||
self.get_stat(Statistic::HP)
|
self.get_stat(Statistic::HP)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn attack(&self) -> T {
|
pub fn attack(&self) -> PkmnResult<T> {
|
||||||
self.get_stat(Statistic::Attack)
|
self.get_stat(Statistic::Attack)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn defense(&self) -> T {
|
pub fn defense(&self) -> PkmnResult<T> {
|
||||||
self.get_stat(Statistic::Defense)
|
self.get_stat(Statistic::Defense)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn special_attack(&self) -> T {
|
pub fn special_attack(&self) -> PkmnResult<T> {
|
||||||
self.get_stat(Statistic::SpecialAttack)
|
self.get_stat(Statistic::SpecialAttack)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn special_defense(&self) -> T {
|
pub fn special_defense(&self) -> PkmnResult<T> {
|
||||||
self.get_stat(Statistic::SpecialDefense)
|
self.get_stat(Statistic::SpecialDefense)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn speed(&self) -> T {
|
pub fn speed(&self) -> PkmnResult<T> {
|
||||||
self.get_stat(Statistic::Speed)
|
self.get_stat(Statistic::Speed)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn get_stat(&self, stat: Statistic) -> T {
|
pub fn get_stat(&self, stat: Statistic) -> PkmnResult<T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
clamped_statistic_set_get(self.reference.cast(), stat)
|
Ok(clamped_statistic_set_get(self.reference.cast(), stat)
|
||||||
|
.as_res()?
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap()
|
.unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn set_stat(&self, stat: Statistic, value: T) {
|
pub fn set_stat(&self, stat: Statistic, value: T) -> PkmnResult<()> {
|
||||||
unsafe { clamped_statistic_set_set(self.reference.cast(), stat, value.try_into().unwrap()) }
|
unsafe {
|
||||||
|
clamped_statistic_set_set(self.reference.cast(), stat, value.try_into().unwrap())
|
||||||
|
.as_res()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn increase_stat(&self, stat: Statistic, value: T) -> bool {
|
pub fn increase_stat(&self, stat: Statistic, value: T) -> PkmnResult<bool> {
|
||||||
unsafe {
|
unsafe {
|
||||||
clamped_statistic_set_increase_stat(
|
clamped_statistic_set_increase_stat(
|
||||||
self.reference.cast(),
|
self.reference.cast(),
|
||||||
stat,
|
stat,
|
||||||
value.try_into().unwrap(),
|
value.try_into().unwrap(),
|
||||||
)
|
)
|
||||||
|
.as_res()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn decrease_stat(&self, stat: Statistic, value: T) -> bool {
|
pub fn decrease_stat(&self, stat: Statistic, value: T) -> PkmnResult<bool> {
|
||||||
unsafe {
|
unsafe {
|
||||||
clamped_statistic_set_decrease_stat(
|
clamped_statistic_set_decrease_stat(
|
||||||
self.reference.cast(),
|
self.reference.cast(),
|
||||||
stat,
|
stat,
|
||||||
value.try_into().unwrap(),
|
value.try_into().unwrap(),
|
||||||
)
|
)
|
||||||
|
.as_res()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,33 +223,40 @@ where
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn statistic_set_get(r: ExternRef<StatisticSetImpl<i64>>, stat: Statistic) -> i64;
|
fn statistic_set_get(r: ExternRef<StatisticSetImpl<i64>>, stat: Statistic) -> WasmResult<i64>;
|
||||||
fn statistic_set_set(r: ExternRef<StatisticSetImpl<i64>>, stat: Statistic, value: i64);
|
fn statistic_set_set(
|
||||||
|
r: ExternRef<StatisticSetImpl<i64>>,
|
||||||
|
stat: Statistic,
|
||||||
|
value: i64,
|
||||||
|
) -> WasmResult<()>;
|
||||||
fn statistic_set_increase_stat(
|
fn statistic_set_increase_stat(
|
||||||
r: ExternRef<StatisticSetImpl<i64>>,
|
r: ExternRef<StatisticSetImpl<i64>>,
|
||||||
stat: Statistic,
|
stat: Statistic,
|
||||||
value: i64,
|
value: i64,
|
||||||
);
|
) -> WasmResult<()>;
|
||||||
fn statistic_set_decrease_stat(
|
fn statistic_set_decrease_stat(
|
||||||
r: ExternRef<StatisticSetImpl<i64>>,
|
r: ExternRef<StatisticSetImpl<i64>>,
|
||||||
stat: Statistic,
|
stat: Statistic,
|
||||||
value: i64,
|
value: i64,
|
||||||
);
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
fn clamped_statistic_set_get(r: ExternRef<ClampedStatisticSet<i64>>, stat: Statistic) -> i64;
|
fn clamped_statistic_set_get(
|
||||||
|
r: ExternRef<ClampedStatisticSet<i64>>,
|
||||||
|
stat: Statistic,
|
||||||
|
) -> WasmResult<i64>;
|
||||||
fn clamped_statistic_set_set(
|
fn clamped_statistic_set_set(
|
||||||
r: ExternRef<ClampedStatisticSet<i64>>,
|
r: ExternRef<ClampedStatisticSet<i64>>,
|
||||||
stat: Statistic,
|
stat: Statistic,
|
||||||
value: i64,
|
value: i64,
|
||||||
);
|
) -> WasmResult<()>;
|
||||||
fn clamped_statistic_set_increase_stat(
|
fn clamped_statistic_set_increase_stat(
|
||||||
r: ExternRef<ClampedStatisticSet<i64>>,
|
r: ExternRef<ClampedStatisticSet<i64>>,
|
||||||
stat: Statistic,
|
stat: Statistic,
|
||||||
value: i64,
|
value: i64,
|
||||||
) -> bool;
|
) -> WasmResult<bool>;
|
||||||
fn clamped_statistic_set_decrease_stat(
|
fn clamped_statistic_set_decrease_stat(
|
||||||
r: ExternRef<ClampedStatisticSet<i64>>,
|
r: ExternRef<ClampedStatisticSet<i64>>,
|
||||||
stat: Statistic,
|
stat: Statistic,
|
||||||
value: i64,
|
value: i64,
|
||||||
) -> bool;
|
) -> WasmResult<bool>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,13 +25,13 @@ impl TurnChoice {
|
||||||
pub fn user(&self) -> Pokemon {
|
pub fn user(&self) -> Pokemon {
|
||||||
self.base().user()
|
self.base().user()
|
||||||
}
|
}
|
||||||
pub fn speed(&self) -> u32 {
|
pub fn speed(&self) -> PkmnResult<u32> {
|
||||||
self.base().speed()
|
self.base().speed()
|
||||||
}
|
}
|
||||||
pub fn has_failed(&self) -> bool {
|
pub fn has_failed(&self) -> PkmnResult<bool> {
|
||||||
self.base().has_failed()
|
self.base().has_failed()
|
||||||
}
|
}
|
||||||
pub fn fail(&self) {
|
pub fn fail(&self) -> PkmnResult<()> {
|
||||||
self.base().fail()
|
self.base().fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,9 +40,9 @@ impl TurnChoice {
|
||||||
pub trait BaseTurnChoiceDataTrait {
|
pub trait BaseTurnChoiceDataTrait {
|
||||||
fn reference(&self) -> u32;
|
fn reference(&self) -> u32;
|
||||||
fn user(&self) -> Pokemon;
|
fn user(&self) -> Pokemon;
|
||||||
fn speed(&self) -> u32;
|
fn speed(&self) -> PkmnResult<u32>;
|
||||||
fn has_failed(&self) -> bool;
|
fn has_failed(&self) -> PkmnResult<bool>;
|
||||||
fn fail(&self);
|
fn fail(&self) -> PkmnResult<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type BaseTurnChoiceData = Rc<dyn BaseTurnChoiceDataTrait>;
|
pub type BaseTurnChoiceData = Rc<dyn BaseTurnChoiceDataTrait>;
|
||||||
|
@ -55,8 +55,8 @@ pub trait MoveTurnChoiceDataTrait {
|
||||||
fn used_move(&self) -> LearnedMove;
|
fn used_move(&self) -> LearnedMove;
|
||||||
fn target_side(&self) -> u8;
|
fn target_side(&self) -> u8;
|
||||||
fn target_index(&self) -> u8;
|
fn target_index(&self) -> u8;
|
||||||
fn priority(&self) -> i8;
|
fn priority(&self) -> PkmnResult<i8>;
|
||||||
fn move_script<'a>(&self) -> Option<&'a Box<dyn Script>>;
|
fn move_script<'a>(&self) -> PkmnResult<Option<&'a Box<dyn Script>>>;
|
||||||
}
|
}
|
||||||
#[cfg(feature = "mock_data")]
|
#[cfg(feature = "mock_data")]
|
||||||
pub type MockMoveTurnChoiceData = MockMoveTurnChoiceDataTrait;
|
pub type MockMoveTurnChoiceData = MockMoveTurnChoiceDataTrait;
|
||||||
|
@ -65,10 +65,11 @@ pub type MockMoveTurnChoiceData = MockMoveTurnChoiceDataTrait;
|
||||||
mod implementation {
|
mod implementation {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::app_interface::{LearnedMoveImpl, PokemonImpl};
|
use crate::app_interface::{LearnedMoveImpl, PokemonImpl};
|
||||||
use crate::cached_value;
|
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
use crate::handling::temporary::Temporary;
|
use crate::handling::temporary::Temporary;
|
||||||
|
use crate::handling::wasm_result::WasmResult;
|
||||||
|
use crate::{cached_value, PkmnResult};
|
||||||
|
|
||||||
struct BaseTurnChoiceDataImpl {
|
struct BaseTurnChoiceDataImpl {
|
||||||
reference: ExternRef<TurnChoice>,
|
reference: ExternRef<TurnChoice>,
|
||||||
|
@ -83,14 +84,14 @@ mod implementation {
|
||||||
fn user(&self) -> Pokemon {
|
fn user(&self) -> Pokemon {
|
||||||
self.user.value()
|
self.user.value()
|
||||||
}
|
}
|
||||||
fn speed(&self) -> u32 {
|
fn speed(&self) -> PkmnResult<u32> {
|
||||||
unsafe { turn_choice_get_speed(self.reference) }
|
unsafe { turn_choice_get_speed(self.reference).as_res() }
|
||||||
}
|
}
|
||||||
fn has_failed(&self) -> bool {
|
fn has_failed(&self) -> PkmnResult<bool> {
|
||||||
unsafe { turn_choice_has_failed(self.reference) }
|
unsafe { turn_choice_has_failed(self.reference).as_res() }
|
||||||
}
|
}
|
||||||
fn fail(&self) {
|
fn fail(&self) -> PkmnResult<()> {
|
||||||
unsafe { turn_choice_fail(self.reference) }
|
unsafe { turn_choice_fail(self.reference).as_res() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,18 +122,24 @@ mod implementation {
|
||||||
fn target_index(&self) -> u8 {
|
fn target_index(&self) -> u8 {
|
||||||
self.inner.value().target_index.value()
|
self.inner.value().target_index.value()
|
||||||
}
|
}
|
||||||
fn priority(&self) -> i8 {
|
fn priority(&self) -> PkmnResult<i8> {
|
||||||
unsafe { turn_choice_move_priority(self.base().reference().into()) }
|
unsafe { turn_choice_move_priority(self.base().reference().into()).as_res() }
|
||||||
|
}
|
||||||
|
fn move_script<'a>(&self) -> PkmnResult<Option<&'a Box<dyn Script>>> {
|
||||||
|
unsafe {
|
||||||
|
Ok(
|
||||||
|
(turn_choice_move_script(self.base().reference().into()).as_res()?
|
||||||
|
as *const Box<dyn Script>)
|
||||||
|
.as_ref(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
fn move_script<'a>(&self) -> Option<&'a Box<dyn Script>> {
|
|
||||||
unsafe { turn_choice_move_script(self.base().reference().into()).as_ref() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
impl ExternalReferenceType for TurnChoice {
|
impl ExternalReferenceType for TurnChoice {
|
||||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||||
let kind = unsafe { turn_choice_get_kind(reference) };
|
let kind = unsafe { turn_choice_get_kind(reference).unwrap() };
|
||||||
match kind {
|
match kind {
|
||||||
0 => TurnChoice::Move(Box::new(MoveTurnChoiceDataImpl {
|
0 => TurnChoice::Move(Box::new(MoveTurnChoiceDataImpl {
|
||||||
inner: Temporary::new(
|
inner: Temporary::new(
|
||||||
|
@ -152,39 +159,50 @@ mod implementation {
|
||||||
base: Rc::new(BaseTurnChoiceDataImpl {
|
base: Rc::new(BaseTurnChoiceDataImpl {
|
||||||
reference: reference.cast(),
|
reference: reference.cast(),
|
||||||
user: cached_value!({
|
user: cached_value!({
|
||||||
Rc::new(turn_choice_get_user(reference.cast()).get_value().unwrap())
|
Rc::new(
|
||||||
|
turn_choice_get_user(reference.cast())
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
used_move: cached_value!({
|
used_move: cached_value!({
|
||||||
Rc::new(
|
Rc::new(
|
||||||
turn_choice_move_used_move(reference.cast())
|
turn_choice_move_used_move(reference.cast())
|
||||||
|
.unwrap()
|
||||||
.get_value()
|
.get_value()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
target_side: cached_value!({ turn_choice_move_target_side(reference.cast()) }),
|
target_side: cached_value!({
|
||||||
target_index: cached_value!({ turn_choice_move_target_index(reference.cast()) }),
|
turn_choice_move_target_side(reference.cast()).unwrap()
|
||||||
|
}),
|
||||||
|
target_index: cached_value!({
|
||||||
|
turn_choice_move_target_index(reference.cast()).unwrap()
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn turn_choice_get_kind(r: ExternRef<TurnChoice>) -> u8;
|
fn turn_choice_get_kind(r: ExternRef<TurnChoice>) -> WasmResult<u8>;
|
||||||
fn turn_choice_get_user(r: ExternRef<TurnChoice>) -> ExternRef<PokemonImpl>;
|
fn turn_choice_get_user(r: ExternRef<TurnChoice>) -> WasmResult<ExternRef<PokemonImpl>>;
|
||||||
fn turn_choice_get_speed(r: ExternRef<TurnChoice>) -> u32;
|
fn turn_choice_get_speed(r: ExternRef<TurnChoice>) -> WasmResult<u32>;
|
||||||
fn turn_choice_has_failed(r: ExternRef<TurnChoice>) -> bool;
|
fn turn_choice_has_failed(r: ExternRef<TurnChoice>) -> WasmResult<bool>;
|
||||||
fn turn_choice_fail(r: ExternRef<TurnChoice>);
|
fn turn_choice_fail(r: ExternRef<TurnChoice>) -> WasmResult<()>;
|
||||||
|
|
||||||
fn turn_choice_move_used_move(
|
fn turn_choice_move_used_move(
|
||||||
r: ExternRef<MoveTurnChoiceDataImpl>,
|
r: ExternRef<MoveTurnChoiceDataImpl>,
|
||||||
) -> ExternRef<LearnedMoveImpl>;
|
) -> WasmResult<ExternRef<LearnedMoveImpl>>;
|
||||||
fn turn_choice_move_target_side(r: ExternRef<MoveTurnChoiceDataImpl>) -> u8;
|
fn turn_choice_move_target_side(r: ExternRef<MoveTurnChoiceDataImpl>) -> WasmResult<u8>;
|
||||||
fn turn_choice_move_target_index(r: ExternRef<MoveTurnChoiceDataImpl>) -> u8;
|
fn turn_choice_move_target_index(r: ExternRef<MoveTurnChoiceDataImpl>) -> WasmResult<u8>;
|
||||||
fn turn_choice_move_priority(r: ExternRef<MoveTurnChoiceDataImpl>) -> i8;
|
fn turn_choice_move_priority(r: ExternRef<MoveTurnChoiceDataImpl>) -> WasmResult<i8>;
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
fn turn_choice_move_script(r: ExternRef<MoveTurnChoiceDataImpl>) -> *const Box<dyn Script>;
|
fn turn_choice_move_script(r: ExternRef<MoveTurnChoiceDataImpl>) -> WasmResult<u32>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::PkmnResult;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub use implementation::*;
|
pub use implementation::*;
|
||||||
|
|
|
@ -1,22 +1,26 @@
|
||||||
use crate::handling::Script;
|
use crate::handling::Script;
|
||||||
|
use crate::PkmnResult;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
pub trait WithVolatile {
|
pub trait WithVolatile {
|
||||||
fn has_volatile(&self, script_name: &str) -> bool;
|
fn has_volatile(&self, script_name: &str) -> PkmnResult<bool>;
|
||||||
fn add_volatile(&self, script: Box<dyn Script>) -> &dyn Script;
|
fn add_volatile(&self, script: Box<dyn Script>) -> PkmnResult<&dyn Script>;
|
||||||
fn add_volatile_by_name(&self, script_name: &str) -> &dyn Script;
|
fn add_volatile_by_name(&self, script_name: &str) -> PkmnResult<&dyn Script>;
|
||||||
fn remove_volatile(&self, script: &dyn Script);
|
fn remove_volatile(&self, script: &dyn Script) -> PkmnResult<()>;
|
||||||
fn get_volatile_script(&self, script_name: &str) -> Option<&dyn Script>;
|
fn get_volatile_script(&self, script_name: &str) -> PkmnResult<Option<&dyn Script>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_volatile_as<'a, T>(v: &'a dyn WithVolatile, script_name: &str) -> Option<&'a T>
|
pub fn get_volatile_as<'a, T>(
|
||||||
|
v: &'a dyn WithVolatile,
|
||||||
|
script_name: &str,
|
||||||
|
) -> PkmnResult<Option<&'a T>>
|
||||||
where
|
where
|
||||||
T: Script + 'static,
|
T: Script + 'static,
|
||||||
{
|
{
|
||||||
let s = v.get_volatile_script(script_name);
|
let s = v.get_volatile_script(script_name)?;
|
||||||
if let Some(s) = s {
|
if let Some(s) = s {
|
||||||
Some(s.as_any().downcast_ref::<T>().unwrap())
|
Ok(Some(s.as_any().downcast_ref::<T>().unwrap()))
|
||||||
} else {
|
} else {
|
||||||
None
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,204 +0,0 @@
|
||||||
use alloc::rc::Rc;
|
|
||||||
|
|
||||||
pub trait ImmutableListTrait<T> {
|
|
||||||
fn get(&self, index: u32) -> Option<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type ImmutableList<T> = Rc<dyn ImmutableListTrait<T>>;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
|
||||||
mod implementation {
|
|
||||||
use super::*;
|
|
||||||
use crate::app_interface::{
|
|
||||||
BattleParty, BattlePartyImpl, BattleSide, BattleSideImpl, EffectParameter, StringKey,
|
|
||||||
};
|
|
||||||
use crate::handling::extern_ref::{ExternalReferenceType, VecExternRef};
|
|
||||||
use alloc::boxed::Box;
|
|
||||||
use alloc::vec::Vec;
|
|
||||||
use core::marker::PhantomData;
|
|
||||||
|
|
||||||
pub(crate) struct ImmutableListInner<T: Clone> {
|
|
||||||
extern_ref: VecExternRef<T>,
|
|
||||||
resource_type: PhantomData<T>,
|
|
||||||
values: spin::RwLock<Vec<Option<Option<Rc<T>>>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) trait ImmutableListWasm<T: Clone + ExternalReferenceType> {
|
|
||||||
fn initialize(inner: *const ImmutableListInner<T>) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
|
|
||||||
fn new(extern_ref: VecExternRef<T>) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
let mut values = Vec::new();
|
|
||||||
values.resize(extern_ref.len() as usize, None);
|
|
||||||
let inner = Box::new(ImmutableListInner {
|
|
||||||
extern_ref,
|
|
||||||
resource_type: Default::default(),
|
|
||||||
values: spin::RwLock::new(values),
|
|
||||||
});
|
|
||||||
let inner_ptr = Box::into_raw(inner);
|
|
||||||
Self::initialize(inner_ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_ref(extern_ref: VecExternRef<T>) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
unsafe {
|
|
||||||
if let None = CACHE {
|
|
||||||
CACHE = Some(hashbrown::HashMap::new());
|
|
||||||
}
|
|
||||||
let existing = CACHE
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.get(&extern_ref.get_internal_index());
|
|
||||||
if let Some(v) = existing {
|
|
||||||
let inner = *v as *const ImmutableListInner<T>;
|
|
||||||
Self::initialize(inner)
|
|
||||||
} else {
|
|
||||||
let v = Self::new(extern_ref);
|
|
||||||
CACHE.as_mut().unwrap().insert(
|
|
||||||
extern_ref.get_internal_index(),
|
|
||||||
v.get_inner_ptr() as *const u8,
|
|
||||||
);
|
|
||||||
v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_inner(&self) -> &ImmutableListInner<T> {
|
|
||||||
unsafe { self.get_inner_ptr().as_ref().unwrap() }
|
|
||||||
}
|
|
||||||
fn get_inner_ptr(&self) -> *const ImmutableListInner<T>;
|
|
||||||
|
|
||||||
fn get_cached(&self, index: u32) -> Option<Rc<T>> {
|
|
||||||
let inner = self.get_inner();
|
|
||||||
let rg = inner.values.read();
|
|
||||||
let v = rg.get(index as usize).unwrap();
|
|
||||||
if let Some(v) = v {
|
|
||||||
return v.clone();
|
|
||||||
}
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_value(&self, index: u32) -> Option<Rc<T>> {
|
|
||||||
if let Some(cached) = self.get_cached(index) {
|
|
||||||
return Some(cached);
|
|
||||||
}
|
|
||||||
let inner = self.get_inner();
|
|
||||||
let r = inner.extern_ref.at(index);
|
|
||||||
let value = r.get_value();
|
|
||||||
let value = if let Some(value) = value {
|
|
||||||
Some(Rc::new(value))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let mut wg = inner.values.write();
|
|
||||||
wg[index as usize] = Some(value);
|
|
||||||
let v = wg[index as usize].as_ref().unwrap().clone();
|
|
||||||
v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! immutable_list_type {
|
|
||||||
($type_name:ident, $underlying:ident) => {
|
|
||||||
paste::paste! {
|
|
||||||
pub struct [<$type_name ImmutableList>] {
|
|
||||||
inner: *const ImmutableListInner<$underlying>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImmutableListWasm<$underlying> for [<$type_name ImmutableList>] {
|
|
||||||
fn initialize(inner: *const ImmutableListInner<$underlying>) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
Self { inner }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_inner_ptr(&self) -> *const ImmutableListInner<$underlying> {
|
|
||||||
self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImmutableListTrait<$type_name> for [<$type_name ImmutableList>] {
|
|
||||||
fn get(&self, index: u32) -> Option<$type_name> {
|
|
||||||
let v = self.get_value(index);
|
|
||||||
if let Some(v) = v {
|
|
||||||
Some(v)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
immutable_list_type!(BattleSide, BattleSideImpl);
|
|
||||||
immutable_list_type!(BattleParty, BattlePartyImpl);
|
|
||||||
|
|
||||||
pub struct EffectParameterImmutableList {
|
|
||||||
inner: *const ImmutableListInner<EffectParameter>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImmutableListWasm<EffectParameter> for EffectParameterImmutableList {
|
|
||||||
fn initialize(inner: *const ImmutableListInner<EffectParameter>) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
Self { inner }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_inner_ptr(&self) -> *const ImmutableListInner<EffectParameter> {
|
|
||||||
self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImmutableListTrait<Rc<EffectParameter>> for EffectParameterImmutableList {
|
|
||||||
fn get(&self, index: u32) -> Option<Rc<EffectParameter>> {
|
|
||||||
let v = self.get_value(index);
|
|
||||||
if let Some(v) = v {
|
|
||||||
Some(v)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct StringKeyImmutableList {
|
|
||||||
inner: *const ImmutableListInner<StringKey>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImmutableListWasm<StringKey> for StringKeyImmutableList {
|
|
||||||
fn initialize(inner: *const ImmutableListInner<StringKey>) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
Self { inner }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_inner_ptr(&self) -> *const ImmutableListInner<StringKey> {
|
|
||||||
self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImmutableListTrait<Rc<StringKey>> for StringKeyImmutableList {
|
|
||||||
fn get(&self, index: u32) -> Option<Rc<StringKey>> {
|
|
||||||
let v = self.get_value(index);
|
|
||||||
if let Some(v) = v {
|
|
||||||
Some(v)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static mut CACHE: Option<hashbrown::HashMap<u32, *const u8>> = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
|
||||||
pub use implementation::*;
|
|
|
@ -1,5 +1,4 @@
|
||||||
pub mod dynamic_data;
|
pub mod dynamic_data;
|
||||||
pub mod list;
|
|
||||||
pub mod static_data;
|
pub mod static_data;
|
||||||
pub mod string_key;
|
pub mod string_key;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ pub trait AbilityTrait {
|
||||||
|
|
||||||
pub type Ability = Rc<dyn AbilityTrait>;
|
pub type Ability = Rc<dyn AbilityTrait>;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct AbilityIndex {
|
pub struct AbilityIndex {
|
||||||
pub hidden: bool,
|
pub hidden: bool,
|
||||||
|
@ -19,21 +19,20 @@ pub struct AbilityIndex {
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
mod implementation {
|
mod implementation {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::app_interface::list::{
|
|
||||||
EffectParameterImmutableList, ImmutableList, ImmutableListWasm,
|
|
||||||
};
|
|
||||||
use crate::app_interface::{EffectParameter, StringKey};
|
use crate::app_interface::{EffectParameter, StringKey};
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType, VecExternRef};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::ffi_array::FFIArray;
|
||||||
|
use crate::handling::{Cacheable, WasmResult};
|
||||||
use crate::{cached_value, cached_value_getters};
|
use crate::{cached_value, cached_value_getters};
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
struct AbilityInner {
|
struct AbilityInner {
|
||||||
reference: ExternRef<AbilityImpl>,
|
reference: ExternRef<AbilityImpl>,
|
||||||
name: CachedValue<StringKey>,
|
name: CachedValue<StringKey>,
|
||||||
effect: CachedValue<StringKey>,
|
effect: CachedValue<StringKey>,
|
||||||
parameters: CachedValue<ImmutableList<Rc<EffectParameter>>>,
|
parameters: CachedValue<Vec<Rc<EffectParameter>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -47,12 +46,21 @@ mod implementation {
|
||||||
Self::from_ref(reference, &|reference| Self {
|
Self::from_ref(reference, &|reference| Self {
|
||||||
inner: Rc::new(AbilityInner {
|
inner: Rc::new(AbilityInner {
|
||||||
reference,
|
reference,
|
||||||
name: cached_value!({ ability_get_name(reference).get_value().unwrap() }),
|
name: cached_value!({
|
||||||
effect: cached_value!({ ability_get_effect(reference).get_value().unwrap() }),
|
ability_get_name(reference).unwrap().get_value().unwrap()
|
||||||
|
}),
|
||||||
|
effect: cached_value!({
|
||||||
|
ability_get_effect(reference).unwrap().get_value().unwrap()
|
||||||
|
}),
|
||||||
parameters: cached_value!({
|
parameters: cached_value!({
|
||||||
Rc::new(EffectParameterImmutableList::from_ref(
|
let pars: FFIArray<ExternRef<EffectParameter>> =
|
||||||
ability_get_parameters(reference),
|
FFIArray::from_u64(ability_get_parameters(reference).unwrap());
|
||||||
))
|
let pars = Vec::from_raw_parts(pars.ptr(), pars.len(), pars.len());
|
||||||
|
let pars = pars
|
||||||
|
.into_iter()
|
||||||
|
.map(|r| Rc::new(EffectParameter::new(r).unwrap()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
pars
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
@ -77,9 +85,9 @@ mod implementation {
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn ability_get_name(r: ExternRef<AbilityImpl>) -> ExternRef<StringKey>;
|
fn ability_get_name(r: ExternRef<AbilityImpl>) -> WasmResult<ExternRef<StringKey>>;
|
||||||
fn ability_get_effect(r: ExternRef<AbilityImpl>) -> ExternRef<StringKey>;
|
fn ability_get_effect(r: ExternRef<AbilityImpl>) -> WasmResult<ExternRef<StringKey>>;
|
||||||
fn ability_get_parameters(r: ExternRef<AbilityImpl>) -> VecExternRef<EffectParameter>;
|
fn ability_get_parameters(r: ExternRef<AbilityImpl>) -> WasmResult<u64>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ mod implementation {
|
||||||
use crate::app_interface::{get_hash, StringKey};
|
use crate::app_interface::{get_hash, StringKey};
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::{Cacheable, WasmResult};
|
||||||
use crate::{cached_value, cached_value_getters};
|
use crate::{cached_value, cached_value_getters};
|
||||||
use spin::RwLock;
|
use spin::RwLock;
|
||||||
|
|
||||||
|
@ -60,24 +60,41 @@ mod implementation {
|
||||||
inner: Rc::new(StaticDataInner {
|
inner: Rc::new(StaticDataInner {
|
||||||
reference,
|
reference,
|
||||||
move_library: cached_value!({
|
move_library: cached_value!({
|
||||||
Rc::new(static_data_get_move_library(reference).get_value().unwrap())
|
Rc::new(
|
||||||
|
static_data_get_move_library(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
item_library: cached_value!({
|
item_library: cached_value!({
|
||||||
Rc::new(static_data_get_item_library(reference).get_value().unwrap())
|
Rc::new(
|
||||||
|
static_data_get_item_library(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
species_library: cached_value!({
|
species_library: cached_value!({
|
||||||
Rc::new(
|
Rc::new(
|
||||||
static_data_get_species_library(reference)
|
static_data_get_species_library(reference)
|
||||||
|
.unwrap()
|
||||||
.get_value()
|
.get_value()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
type_library: cached_value!({
|
type_library: cached_value!({
|
||||||
Rc::new(static_data_get_type_library(reference).get_value().unwrap())
|
Rc::new(
|
||||||
|
static_data_get_type_library(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
settings: cached_value!({
|
settings: cached_value!({
|
||||||
Rc::new(
|
Rc::new(
|
||||||
static_data_get_library_settings(reference)
|
static_data_get_library_settings(reference)
|
||||||
|
.unwrap()
|
||||||
.get_value()
|
.get_value()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
|
@ -119,7 +136,9 @@ mod implementation {
|
||||||
pub(crate) fn new(ptr: ExternRef<LibrarySettingsImpl>) -> Self {
|
pub(crate) fn new(ptr: ExternRef<LibrarySettingsImpl>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Rc::new(LibrarySettingsInner {
|
inner: Rc::new(LibrarySettingsInner {
|
||||||
maximum_level: cached_value!({ library_settings_get_maximum_level(ptr) }),
|
maximum_level: cached_value!({
|
||||||
|
library_settings_get_maximum_level(ptr).unwrap()
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,21 +161,23 @@ mod implementation {
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn static_data_get_move_library(
|
fn static_data_get_move_library(
|
||||||
ptr: ExternRef<StaticDataImpl>,
|
ptr: ExternRef<StaticDataImpl>,
|
||||||
) -> ExternRef<MoveLibraryImpl>;
|
) -> WasmResult<ExternRef<MoveLibraryImpl>>;
|
||||||
fn static_data_get_item_library(
|
fn static_data_get_item_library(
|
||||||
ptr: ExternRef<StaticDataImpl>,
|
ptr: ExternRef<StaticDataImpl>,
|
||||||
) -> ExternRef<ItemLibraryImpl>;
|
) -> WasmResult<ExternRef<ItemLibraryImpl>>;
|
||||||
fn static_data_get_species_library(
|
fn static_data_get_species_library(
|
||||||
ptr: ExternRef<StaticDataImpl>,
|
ptr: ExternRef<StaticDataImpl>,
|
||||||
) -> ExternRef<SpeciesLibraryImpl>;
|
) -> WasmResult<ExternRef<SpeciesLibraryImpl>>;
|
||||||
fn static_data_get_type_library(
|
fn static_data_get_type_library(
|
||||||
ptr: ExternRef<StaticDataImpl>,
|
ptr: ExternRef<StaticDataImpl>,
|
||||||
) -> ExternRef<TypeLibraryImpl>;
|
) -> WasmResult<ExternRef<TypeLibraryImpl>>;
|
||||||
fn static_data_get_library_settings(
|
fn static_data_get_library_settings(
|
||||||
ptr: ExternRef<StaticDataImpl>,
|
ptr: ExternRef<StaticDataImpl>,
|
||||||
) -> ExternRef<LibrarySettingsImpl>;
|
) -> WasmResult<ExternRef<LibrarySettingsImpl>>;
|
||||||
|
|
||||||
fn library_settings_get_maximum_level(ptr: ExternRef<LibrarySettingsImpl>) -> LevelInt;
|
fn library_settings_get_maximum_level(
|
||||||
|
ptr: ExternRef<LibrarySettingsImpl>,
|
||||||
|
) -> WasmResult<LevelInt>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DataLibrary<T>: Cacheable
|
pub trait DataLibrary<T>: Cacheable
|
||||||
|
@ -182,14 +203,16 @@ mod implementation {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
if let Some(v) = self.get_cache().read().get(&name.hash()) {
|
if let Some(v) = self.get_cache().read().get(&name.hash().unwrap()) {
|
||||||
return Some(v.clone());
|
return Some(v.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let index = Self::_get_ref_by_name(self.get_self_ref(), name.ptr());
|
let index = Self::_get_ref_by_name(self.get_self_ref(), name.ptr());
|
||||||
let v = Self::_from_external_ref_index(index);
|
let v = Self::_from_external_ref_index(index);
|
||||||
if let Some(v) = &v {
|
if let Some(v) = &v {
|
||||||
self.get_cache().write().insert(name.hash(), v.clone());
|
self.get_cache()
|
||||||
|
.write()
|
||||||
|
.insert(name.hash().unwrap(), v.clone());
|
||||||
}
|
}
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
@ -242,7 +265,7 @@ mod mocked {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.get_cache().read().get(&name.hash()).cloned()
|
self.get_cache().read().get(&name.hash().unwrap()).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_by_hash(&self, hash: u32) -> Option<T>
|
fn get_by_hash(&self, hash: u32) -> Option<T>
|
||||||
|
|
|
@ -2,17 +2,17 @@ use crate::app_interface::TypeIdentifier;
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
|
||||||
pub trait TypeLibraryTrait {
|
pub trait TypeLibraryTrait {
|
||||||
fn get_type_from_name(&self, name: &str) -> Option<TypeIdentifier>;
|
fn get_type_from_name(&self, name: &str) -> PkmnResult<Option<TypeIdentifier>>;
|
||||||
fn get_single_effectiveness(
|
fn get_single_effectiveness(
|
||||||
&self,
|
&self,
|
||||||
attacking_type: TypeIdentifier,
|
attacking_type: TypeIdentifier,
|
||||||
defending_type: TypeIdentifier,
|
defending_type: TypeIdentifier,
|
||||||
) -> f32;
|
) -> PkmnResult<f32>;
|
||||||
fn get_effectiveness(
|
fn get_effectiveness(
|
||||||
&self,
|
&self,
|
||||||
attacking_type: TypeIdentifier,
|
attacking_type: TypeIdentifier,
|
||||||
defending_types: &[TypeIdentifier],
|
defending_types: &[TypeIdentifier],
|
||||||
) -> f32;
|
) -> PkmnResult<f32>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Typelibrary = Rc<dyn TypeLibraryTrait>;
|
pub type Typelibrary = Rc<dyn TypeLibraryTrait>;
|
||||||
|
@ -21,6 +21,8 @@ pub type Typelibrary = Rc<dyn TypeLibraryTrait>;
|
||||||
mod implementation {
|
mod implementation {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
|
use crate::handling::WasmResult;
|
||||||
|
use crate::PkmnResult;
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use alloc::string::{String, ToString};
|
use alloc::string::{String, ToString};
|
||||||
use cstr_core::{c_char, CString};
|
use cstr_core::{c_char, CString};
|
||||||
|
@ -51,35 +53,37 @@ mod implementation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeLibraryTrait for TypeLibraryImpl {
|
impl TypeLibraryTrait for TypeLibraryImpl {
|
||||||
fn get_type_from_name(&self, name: &str) -> Option<TypeIdentifier> {
|
fn get_type_from_name(&self, name: &str) -> PkmnResult<Option<TypeIdentifier>> {
|
||||||
if let Some(cached) = self.inner.name_to_type_cache.read().get(name) {
|
if let Some(cached) = self.inner.name_to_type_cache.read().get(name) {
|
||||||
return Some(*cached);
|
return Ok(Some(*cached));
|
||||||
}
|
}
|
||||||
let cstr = CString::new(name).unwrap();
|
let cstr = CString::new(name).unwrap();
|
||||||
let v = unsafe { type_library_get_type_by_name(self.inner.reference, cstr.as_ptr()) };
|
let v = unsafe {
|
||||||
|
type_library_get_type_by_name(self.inner.reference, cstr.as_ptr()).as_res()?
|
||||||
|
};
|
||||||
if v == 255 {
|
if v == 255 {
|
||||||
return None;
|
return Ok(None);
|
||||||
}
|
}
|
||||||
let v = v.into();
|
let v = v.into();
|
||||||
self.inner
|
self.inner
|
||||||
.name_to_type_cache
|
.name_to_type_cache
|
||||||
.write()
|
.write()
|
||||||
.insert(name.to_string(), v);
|
.insert(name.to_string(), v);
|
||||||
Some(v)
|
Ok(Some(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_single_effectiveness(
|
fn get_single_effectiveness(
|
||||||
&self,
|
&self,
|
||||||
attacking_type: TypeIdentifier,
|
attacking_type: TypeIdentifier,
|
||||||
defending_type: TypeIdentifier,
|
defending_type: TypeIdentifier,
|
||||||
) -> f32 {
|
) -> PkmnResult<f32> {
|
||||||
if let Some(cached) = self
|
if let Some(cached) = self
|
||||||
.inner
|
.inner
|
||||||
.effectiveness_cache
|
.effectiveness_cache
|
||||||
.read()
|
.read()
|
||||||
.get(&(attacking_type, defending_type))
|
.get(&(attacking_type, defending_type))
|
||||||
{
|
{
|
||||||
return *cached;
|
return Ok(*cached);
|
||||||
}
|
}
|
||||||
let effectiveness = unsafe {
|
let effectiveness = unsafe {
|
||||||
type_library_get_single_effectiveness(
|
type_library_get_single_effectiveness(
|
||||||
|
@ -87,24 +91,25 @@ mod implementation {
|
||||||
attacking_type.into(),
|
attacking_type.into(),
|
||||||
defending_type.into(),
|
defending_type.into(),
|
||||||
)
|
)
|
||||||
};
|
}
|
||||||
|
.as_res()?;
|
||||||
self.inner
|
self.inner
|
||||||
.effectiveness_cache
|
.effectiveness_cache
|
||||||
.write()
|
.write()
|
||||||
.insert((attacking_type, defending_type), effectiveness);
|
.insert((attacking_type, defending_type), effectiveness);
|
||||||
effectiveness
|
Ok(effectiveness)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_effectiveness(
|
fn get_effectiveness(
|
||||||
&self,
|
&self,
|
||||||
attacking_type: TypeIdentifier,
|
attacking_type: TypeIdentifier,
|
||||||
defending_types: &[TypeIdentifier],
|
defending_types: &[TypeIdentifier],
|
||||||
) -> f32 {
|
) -> PkmnResult<f32> {
|
||||||
let mut f = 1.0;
|
let mut f = 1.0;
|
||||||
for defending_type in defending_types {
|
for defending_type in defending_types {
|
||||||
f *= self.get_single_effectiveness(attacking_type, *defending_type);
|
f *= self.get_single_effectiveness(attacking_type, *defending_type)?;
|
||||||
}
|
}
|
||||||
f
|
Ok(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,10 +128,14 @@ mod implementation {
|
||||||
r: ExternRef<TypeLibraryImpl>,
|
r: ExternRef<TypeLibraryImpl>,
|
||||||
attacking_type: u8,
|
attacking_type: u8,
|
||||||
defending_type: u8,
|
defending_type: u8,
|
||||||
) -> f32;
|
) -> WasmResult<f32>;
|
||||||
fn type_library_get_type_by_name(r: ExternRef<TypeLibraryImpl>, name: *const c_char) -> u8;
|
fn type_library_get_type_by_name(
|
||||||
|
r: ExternRef<TypeLibraryImpl>,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> WasmResult<u8>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::PkmnResult;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub use implementation::*;
|
pub use implementation::*;
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use crate::app_interface::StringKey;
|
use crate::app_interface::StringKey;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
use crate::{ExternRef, ExternalReferenceType};
|
use crate::{handling::WasmResult, ExternRef, ExternalReferenceType, PkmnResult};
|
||||||
use core::fmt::{Display, Formatter};
|
use core::fmt::{Display, Formatter};
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
enum EffectParameterType {
|
enum EffectParameterType {
|
||||||
None,
|
None,
|
||||||
Bool,
|
Bool,
|
||||||
|
@ -12,6 +13,12 @@ enum EffectParameterType {
|
||||||
String,
|
String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for EffectParameterType {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum EffectParameter {
|
pub enum EffectParameter {
|
||||||
None,
|
None,
|
||||||
|
@ -23,18 +30,18 @@ pub enum EffectParameter {
|
||||||
|
|
||||||
impl EffectParameter {
|
impl EffectParameter {
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub(crate) fn new(ptr: ExternRef<Self>) -> Self {
|
pub(crate) fn new(ptr: ExternRef<Self>) -> PkmnResult<Self> {
|
||||||
unsafe {
|
Ok(unsafe {
|
||||||
match effect_parameter_get_type(ptr) {
|
match effect_parameter_get_type(ptr).as_res()? {
|
||||||
EffectParameterType::None => Self::None,
|
EffectParameterType::None => Self::None,
|
||||||
EffectParameterType::Bool => Self::Bool(effect_parameter_as_bool(ptr)),
|
EffectParameterType::Bool => Self::Bool(effect_parameter_as_bool(ptr).as_res()?),
|
||||||
EffectParameterType::Int => Self::Int(effect_parameter_as_int(ptr)),
|
EffectParameterType::Int => Self::Int(effect_parameter_as_int(ptr).as_res()?),
|
||||||
EffectParameterType::Float => Self::Float(effect_parameter_as_float(ptr)),
|
EffectParameterType::Float => Self::Float(effect_parameter_as_float(ptr).as_res()?),
|
||||||
EffectParameterType::String => {
|
EffectParameterType::String => {
|
||||||
Self::String(StringKey::new(effect_parameter_as_string(ptr)))
|
Self::String(StringKey::new(effect_parameter_as_string(ptr).as_res()?))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_bool(&self) -> bool {
|
pub fn as_bool(&self) -> bool {
|
||||||
|
@ -72,7 +79,7 @@ impl ExternalReferenceType for EffectParameter {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
EffectParameter::new(reference)
|
EffectParameter::new(reference).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,9 +99,13 @@ impl Display for EffectParameter {
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn effect_parameter_get_type(ptr: ExternRef<EffectParameter>) -> EffectParameterType;
|
fn effect_parameter_get_type(
|
||||||
fn effect_parameter_as_bool(ptr: ExternRef<EffectParameter>) -> bool;
|
ptr: ExternRef<EffectParameter>,
|
||||||
fn effect_parameter_as_int(ptr: ExternRef<EffectParameter>) -> i64;
|
) -> WasmResult<EffectParameterType>;
|
||||||
fn effect_parameter_as_float(ptr: ExternRef<EffectParameter>) -> f32;
|
fn effect_parameter_as_bool(ptr: ExternRef<EffectParameter>) -> WasmResult<bool>;
|
||||||
fn effect_parameter_as_string(ptr: ExternRef<EffectParameter>) -> ExternRef<StringKey>;
|
fn effect_parameter_as_int(ptr: ExternRef<EffectParameter>) -> WasmResult<i64>;
|
||||||
|
fn effect_parameter_as_float(ptr: ExternRef<EffectParameter>) -> WasmResult<f32>;
|
||||||
|
fn effect_parameter_as_string(
|
||||||
|
ptr: ExternRef<EffectParameter>,
|
||||||
|
) -> WasmResult<ExternRef<StringKey>>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,12 @@ pub enum ItemCategory {
|
||||||
Mail,
|
Mail,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for ItemCategory {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::MiscItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A battle item category defines how the item is categorized when in battle.
|
/// A battle item category defines how the item is categorized when in battle.
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -39,6 +45,12 @@ pub enum BattleItemCategory {
|
||||||
MiscBattleItem,
|
MiscBattleItem,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for BattleItemCategory {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
||||||
pub trait ItemTrait {
|
pub trait ItemTrait {
|
||||||
fn reference(&self) -> u32;
|
fn reference(&self) -> u32;
|
||||||
|
@ -50,7 +62,7 @@ pub trait ItemTrait {
|
||||||
fn battle_category(&self) -> BattleItemCategory;
|
fn battle_category(&self) -> BattleItemCategory;
|
||||||
/// The buying value of the item.
|
/// The buying value of the item.
|
||||||
fn price(&self) -> i32;
|
fn price(&self) -> i32;
|
||||||
fn has_flag(&self, flag: &StringKey) -> bool;
|
fn has_flag(&self, flag: &StringKey) -> PkmnResult<bool>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Item = Rc<dyn ItemTrait>;
|
pub type Item = Rc<dyn ItemTrait>;
|
||||||
|
@ -62,8 +74,8 @@ mod implementation {
|
||||||
use crate::app_interface::{BattleItemCategory, ItemCategory, ItemTrait, StringKey};
|
use crate::app_interface::{BattleItemCategory, ItemCategory, ItemTrait, StringKey};
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::{Cacheable, WasmResult};
|
||||||
use crate::{cached_value, cached_value_getters};
|
use crate::{cached_value, cached_value_getters, PkmnResult};
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
|
||||||
struct ItemInner {
|
struct ItemInner {
|
||||||
|
@ -86,10 +98,12 @@ mod implementation {
|
||||||
Self::from_ref(reference, &|reference| Self {
|
Self::from_ref(reference, &|reference| Self {
|
||||||
inner: Rc::new(ItemInner {
|
inner: Rc::new(ItemInner {
|
||||||
reference,
|
reference,
|
||||||
name: cached_value!({ StringKey::new(item_get_name(reference)) }),
|
name: cached_value!({ StringKey::new(item_get_name(reference).unwrap()) }),
|
||||||
category: cached_value!({ item_get_category(reference) }),
|
category: cached_value!({ item_get_category(reference).unwrap() }),
|
||||||
battle_category: cached_value!({ item_get_battle_category(reference) }),
|
battle_category: cached_value!({
|
||||||
price: cached_value!({ item_get_price(reference) }),
|
item_get_battle_category(reference).unwrap()
|
||||||
|
}),
|
||||||
|
price: cached_value!({ item_get_price(reference).unwrap() }),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -116,8 +130,8 @@ mod implementation {
|
||||||
fn price(&self) -> i32;
|
fn price(&self) -> i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_flag(&self, flag: &StringKey) -> bool {
|
fn has_flag(&self, flag: &StringKey) -> PkmnResult<bool> {
|
||||||
unsafe { item_has_flag(self.inner.reference, flag.ptr()) }
|
unsafe { item_has_flag(self.inner.reference, flag.ptr()).as_res() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,13 +145,14 @@ mod implementation {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn item_get_name(ptr: ExternRef<ItemImpl>) -> ExternRef<StringKey>;
|
fn item_get_name(ptr: ExternRef<ItemImpl>) -> WasmResult<ExternRef<StringKey>>;
|
||||||
fn item_get_category(ptr: ExternRef<ItemImpl>) -> ItemCategory;
|
fn item_get_category(ptr: ExternRef<ItemImpl>) -> WasmResult<ItemCategory>;
|
||||||
fn item_get_battle_category(ptr: ExternRef<ItemImpl>) -> BattleItemCategory;
|
fn item_get_battle_category(ptr: ExternRef<ItemImpl>) -> WasmResult<BattleItemCategory>;
|
||||||
fn item_get_price(ptr: ExternRef<ItemImpl>) -> i32;
|
fn item_get_price(ptr: ExternRef<ItemImpl>) -> WasmResult<i32>;
|
||||||
fn item_has_flag(ptr: ExternRef<ItemImpl>, flag: ExternRef<StringKey>) -> bool;
|
fn item_has_flag(ptr: ExternRef<ItemImpl>, flag: ExternRef<StringKey>) -> WasmResult<bool>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::PkmnResult;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub use implementation::*;
|
pub use implementation::*;
|
||||||
|
|
|
@ -9,6 +9,12 @@ pub enum MoveCategory {
|
||||||
Status = 2,
|
Status = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for MoveCategory {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Physical
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
pub enum MoveTarget {
|
pub enum MoveTarget {
|
||||||
|
@ -29,6 +35,12 @@ pub enum MoveTarget {
|
||||||
OnSelf,
|
OnSelf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for MoveTarget {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Adjacent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
#[cfg_attr(feature = "mock_data", mockall::automock)]
|
||||||
pub trait MoveDataTrait {
|
pub trait MoveDataTrait {
|
||||||
fn name(&self) -> StringKey;
|
fn name(&self) -> StringKey;
|
||||||
|
@ -39,7 +51,7 @@ pub trait MoveDataTrait {
|
||||||
fn base_usages(&self) -> u8;
|
fn base_usages(&self) -> u8;
|
||||||
fn target(&self) -> MoveTarget;
|
fn target(&self) -> MoveTarget;
|
||||||
fn priority(&self) -> i8;
|
fn priority(&self) -> i8;
|
||||||
fn has_flag(&self, flag: &str) -> bool;
|
fn has_flag(&self, flag: &str) -> PkmnResult<bool>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type MoveData = Rc<dyn MoveDataTrait>;
|
pub type MoveData = Rc<dyn MoveDataTrait>;
|
||||||
|
@ -52,8 +64,8 @@ mod implementation {
|
||||||
use crate::app_interface::get_hash;
|
use crate::app_interface::get_hash;
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::{Cacheable, WasmResult};
|
||||||
use crate::{cached_value, cached_value_getters};
|
use crate::{cached_value, cached_value_getters, PkmnResult};
|
||||||
|
|
||||||
struct MoveDataInner {
|
struct MoveDataInner {
|
||||||
ptr: ExternRef<MoveDataImpl>,
|
ptr: ExternRef<MoveDataImpl>,
|
||||||
|
@ -77,14 +89,14 @@ mod implementation {
|
||||||
MoveDataImpl::from_ref(ptr, &|ptr| Self {
|
MoveDataImpl::from_ref(ptr, &|ptr| Self {
|
||||||
inner: Rc::new(MoveDataInner {
|
inner: Rc::new(MoveDataInner {
|
||||||
ptr,
|
ptr,
|
||||||
name: cached_value!({ StringKey::new(move_data_get_name(ptr)) }),
|
name: cached_value!({ StringKey::new(move_data_get_name(ptr).unwrap()) }),
|
||||||
move_type: cached_value!({ move_data_get_type(ptr) }),
|
move_type: cached_value!({ move_data_get_type(ptr).unwrap() }),
|
||||||
category: cached_value!({ move_data_get_category(ptr) }),
|
category: cached_value!({ move_data_get_category(ptr).unwrap() }),
|
||||||
base_power: cached_value!({ move_data_get_base_power(ptr) }),
|
base_power: cached_value!({ move_data_get_base_power(ptr).unwrap() }),
|
||||||
accuracy: cached_value!({ move_data_get_accuracy(ptr) }),
|
accuracy: cached_value!({ move_data_get_accuracy(ptr).unwrap() }),
|
||||||
base_usages: cached_value!({ move_data_get_base_power(ptr) }),
|
base_usages: cached_value!({ move_data_get_base_power(ptr).unwrap() }),
|
||||||
target: cached_value!({ move_data_get_target(ptr) }),
|
target: cached_value!({ move_data_get_target(ptr).unwrap() }),
|
||||||
priority: cached_value!({ move_data_get_priority(ptr) }),
|
priority: cached_value!({ move_data_get_priority(ptr).unwrap() }),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -102,9 +114,9 @@ mod implementation {
|
||||||
fn priority(&self) -> i8;
|
fn priority(&self) -> i8;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_flag(&self, flag: &str) -> bool {
|
fn has_flag(&self, flag: &str) -> PkmnResult<bool> {
|
||||||
let hash = get_hash(flag);
|
let hash = get_hash(flag);
|
||||||
unsafe { move_data_has_flag_by_hash(self.inner.ptr, hash) }
|
unsafe { move_data_has_flag_by_hash(self.inner.ptr, hash).as_res() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,17 +129,21 @@ mod implementation {
|
||||||
crate::handling::cacheable::cacheable!(MoveDataImpl);
|
crate::handling::cacheable::cacheable!(MoveDataImpl);
|
||||||
|
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn move_data_get_name(ptr: ExternRef<MoveDataImpl>) -> ExternRef<StringKey>;
|
fn move_data_get_name(ptr: ExternRef<MoveDataImpl>) -> WasmResult<ExternRef<StringKey>>;
|
||||||
fn move_data_get_type(ptr: ExternRef<MoveDataImpl>) -> u8;
|
fn move_data_get_type(ptr: ExternRef<MoveDataImpl>) -> WasmResult<u8>;
|
||||||
fn move_data_get_category(ptr: ExternRef<MoveDataImpl>) -> MoveCategory;
|
fn move_data_get_category(ptr: ExternRef<MoveDataImpl>) -> WasmResult<MoveCategory>;
|
||||||
fn move_data_get_base_power(ptr: ExternRef<MoveDataImpl>) -> u8;
|
fn move_data_get_base_power(ptr: ExternRef<MoveDataImpl>) -> WasmResult<u8>;
|
||||||
fn move_data_get_accuracy(ptr: ExternRef<MoveDataImpl>) -> u8;
|
fn move_data_get_accuracy(ptr: ExternRef<MoveDataImpl>) -> WasmResult<u8>;
|
||||||
fn move_data_get_base_usages(ptr: ExternRef<MoveDataImpl>) -> u8;
|
fn move_data_get_base_usages(ptr: ExternRef<MoveDataImpl>) -> WasmResult<u8>;
|
||||||
fn move_data_get_target(ptr: ExternRef<MoveDataImpl>) -> MoveTarget;
|
fn move_data_get_target(ptr: ExternRef<MoveDataImpl>) -> WasmResult<MoveTarget>;
|
||||||
fn move_data_get_priority(ptr: ExternRef<MoveDataImpl>) -> i8;
|
fn move_data_get_priority(ptr: ExternRef<MoveDataImpl>) -> WasmResult<i8>;
|
||||||
fn move_data_has_flag_by_hash(ptr: ExternRef<MoveDataImpl>, flag_hash: u32) -> bool;
|
fn move_data_has_flag_by_hash(
|
||||||
|
ptr: ExternRef<MoveDataImpl>,
|
||||||
|
flag_hash: u32,
|
||||||
|
) -> WasmResult<bool>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::PkmnResult;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub use implementation::*;
|
pub use implementation::*;
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub type Nature = Rc<dyn NatureTrait>;
|
||||||
mod implementation {
|
mod implementation {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::{Cacheable, WasmResult};
|
||||||
|
|
||||||
struct NatureInner {
|
struct NatureInner {
|
||||||
reference: ExternRef<NatureImpl>,
|
reference: ExternRef<NatureImpl>,
|
||||||
|
@ -41,10 +41,10 @@ mod implementation {
|
||||||
Self {
|
Self {
|
||||||
inner: Rc::new(NatureInner {
|
inner: Rc::new(NatureInner {
|
||||||
reference,
|
reference,
|
||||||
increase_stat: nature_get_increase_stat(reference),
|
increase_stat: nature_get_increase_stat(reference).unwrap(),
|
||||||
decrease_stat: nature_get_decrease_stat(reference),
|
decrease_stat: nature_get_decrease_stat(reference).unwrap(),
|
||||||
increase_modifier: nature_get_increase_modifier(reference),
|
increase_modifier: nature_get_increase_modifier(reference).unwrap(),
|
||||||
decrease_modifier: nature_get_decrease_modifier(reference),
|
decrease_modifier: nature_get_decrease_modifier(reference).unwrap(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -76,10 +76,10 @@ mod implementation {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn nature_get_increase_stat(r: ExternRef<NatureImpl>) -> Statistic;
|
fn nature_get_increase_stat(r: ExternRef<NatureImpl>) -> WasmResult<Statistic>;
|
||||||
fn nature_get_decrease_stat(r: ExternRef<NatureImpl>) -> Statistic;
|
fn nature_get_decrease_stat(r: ExternRef<NatureImpl>) -> WasmResult<Statistic>;
|
||||||
fn nature_get_increase_modifier(r: ExternRef<NatureImpl>) -> f32;
|
fn nature_get_increase_modifier(r: ExternRef<NatureImpl>) -> WasmResult<f32>;
|
||||||
fn nature_get_decrease_modifier(r: ExternRef<NatureImpl>) -> f32;
|
fn nature_get_decrease_modifier(r: ExternRef<NatureImpl>) -> WasmResult<f32>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,32 @@
|
||||||
use crate::app_interface::list::ImmutableList;
|
|
||||||
use crate::app_interface::{ImmutableStatisticSet, StringKey};
|
use crate::app_interface::{ImmutableStatisticSet, StringKey};
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Eq, PartialEq, Debug)]
|
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||||
pub enum Gender {
|
pub enum Gender {
|
||||||
Male = 0,
|
Male = 0,
|
||||||
Female = 1,
|
Female = 1,
|
||||||
Genderless = 2,
|
Genderless = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Gender {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Genderless
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait FormTrait {
|
pub trait FormTrait {
|
||||||
fn name(&self) -> StringKey;
|
fn name(&self) -> StringKey;
|
||||||
fn height(&self) -> f32;
|
fn height(&self) -> f32;
|
||||||
fn weight(&self) -> f32;
|
fn weight(&self) -> f32;
|
||||||
fn base_experience(&self) -> u32;
|
fn base_experience(&self) -> u32;
|
||||||
fn base_stats(&self) -> ImmutableStatisticSet;
|
fn base_stats(&self) -> ImmutableStatisticSet;
|
||||||
fn abilities(&self) -> ImmutableList<Rc<StringKey>>;
|
fn abilities(&self) -> Vec<Rc<StringKey>>;
|
||||||
fn hidden_abilities(&self) -> ImmutableList<Rc<StringKey>>;
|
fn hidden_abilities(&self) -> Vec<Rc<StringKey>>;
|
||||||
fn types(&self) -> &Vec<u8>;
|
fn types(&self) -> &Vec<u8>;
|
||||||
fn has_flag(&self, flag: &str) -> bool;
|
fn has_flag(&self, flag: &str) -> PkmnResult<bool>;
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +44,7 @@ pub trait SpeciesTrait {
|
||||||
/// uncatchable.
|
/// uncatchable.
|
||||||
fn capture_rate(&self) -> u8;
|
fn capture_rate(&self) -> u8;
|
||||||
fn get_form(&self, form_name: &str) -> Option<Form>;
|
fn get_form(&self, form_name: &str) -> Option<Form>;
|
||||||
fn has_flag(&self, flag: &str) -> bool;
|
fn has_flag(&self, flag: &str) -> PkmnResult<bool>;
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
}
|
}
|
||||||
|
@ -50,13 +55,13 @@ pub type Species = Rc<dyn SpeciesTrait>;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
mod implementation {
|
mod implementation {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::app_interface::list::ImmutableListWasm;
|
|
||||||
use crate::app_interface::{get_hash, ImmutableStatisticSetImpl};
|
use crate::app_interface::{get_hash, ImmutableStatisticSetImpl};
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType, VecExternRef};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
use crate::handling::ffi_array::FFIArray;
|
use crate::handling::ffi_array::FFIArray;
|
||||||
|
use crate::handling::wasm_result::WasmResult;
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::Cacheable;
|
||||||
use crate::{cached_value, cached_value_getters};
|
use crate::{cached_value, cached_value_getters, PkmnResult};
|
||||||
use spin::RwLock;
|
use spin::RwLock;
|
||||||
|
|
||||||
struct FormInner {
|
struct FormInner {
|
||||||
|
@ -67,8 +72,8 @@ mod implementation {
|
||||||
types: CachedValue<Vec<u8>>,
|
types: CachedValue<Vec<u8>>,
|
||||||
base_experience: CachedValue<u32>,
|
base_experience: CachedValue<u32>,
|
||||||
base_stats: CachedValue<ImmutableStatisticSet>,
|
base_stats: CachedValue<ImmutableStatisticSet>,
|
||||||
abilities: CachedValue<ImmutableList<Rc<StringKey>>>,
|
abilities: CachedValue<Vec<Rc<StringKey>>>,
|
||||||
hidden_abilities: CachedValue<ImmutableList<Rc<StringKey>>>,
|
hidden_abilities: CachedValue<Vec<Rc<StringKey>>>,
|
||||||
// moves: CachedValue<LearnableMoves>,
|
// moves: CachedValue<LearnableMoves>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,30 +87,38 @@ mod implementation {
|
||||||
Self::from_ref(reference, &|reference| Self {
|
Self::from_ref(reference, &|reference| Self {
|
||||||
inner: Rc::new(FormInner {
|
inner: Rc::new(FormInner {
|
||||||
reference,
|
reference,
|
||||||
name: cached_value!({ form_get_name(reference).get_value().unwrap() }),
|
name: cached_value!({ form_get_name(reference).unwrap().get_value().unwrap() }),
|
||||||
height: cached_value!({ form_get_height(reference) }),
|
height: cached_value!({ form_get_height(reference).unwrap() }),
|
||||||
weight: cached_value!({ form_get_weight(reference) }),
|
weight: cached_value!({ form_get_weight(reference).unwrap() }),
|
||||||
types: cached_value!({
|
types: cached_value!({
|
||||||
let raw = form_get_types(reference);
|
let raw = FFIArray::from_u64(form_get_types(reference).unwrap());
|
||||||
Vec::from_raw_parts(raw.ptr(), raw.len(), raw.len())
|
Vec::from_raw_parts(raw.ptr(), raw.len(), raw.len())
|
||||||
}),
|
}),
|
||||||
base_experience: cached_value!({ form_get_base_experience(reference) }),
|
base_experience: cached_value!({
|
||||||
|
form_get_base_experience(reference).unwrap()
|
||||||
|
}),
|
||||||
base_stats: cached_value!({
|
base_stats: cached_value!({
|
||||||
Rc::new(form_get_base_stats(reference).get_value().unwrap())
|
Rc::new(form_get_base_stats(reference).unwrap().get_value().unwrap())
|
||||||
}),
|
}),
|
||||||
abilities: cached_value!({
|
abilities: cached_value!({
|
||||||
Rc::new(
|
let abilities: FFIArray<ExternRef<StringKey>> =
|
||||||
crate::app_interface::list::StringKeyImmutableList::from_ref(
|
FFIArray::from_u64(form_get_abilities(reference).unwrap());
|
||||||
form_get_abilities(reference),
|
let abilities =
|
||||||
),
|
Vec::from_raw_parts(abilities.ptr(), abilities.len(), abilities.len());
|
||||||
)
|
abilities
|
||||||
|
.into_iter()
|
||||||
|
.map::<Rc<StringKey>, _>(|r| Rc::new(StringKey::new(r)))
|
||||||
|
.collect()
|
||||||
}),
|
}),
|
||||||
hidden_abilities: cached_value!({
|
hidden_abilities: cached_value!({
|
||||||
Rc::new(
|
let abilities: FFIArray<ExternRef<StringKey>> =
|
||||||
crate::app_interface::list::StringKeyImmutableList::from_ref(
|
FFIArray::from_u64(form_get_hidden_abilities(reference).unwrap());
|
||||||
form_get_hidden_abilities(reference),
|
let abilities =
|
||||||
),
|
Vec::from_raw_parts(abilities.ptr(), abilities.len(), abilities.len());
|
||||||
)
|
abilities
|
||||||
|
.into_iter()
|
||||||
|
.map::<Rc<StringKey>, _>(|r| Rc::new(StringKey::new(r)))
|
||||||
|
.collect()
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
@ -123,16 +136,16 @@ mod implementation {
|
||||||
fn weight(&self) -> f32;
|
fn weight(&self) -> f32;
|
||||||
fn base_experience(&self) -> u32;
|
fn base_experience(&self) -> u32;
|
||||||
fn base_stats(&self) -> ImmutableStatisticSet;
|
fn base_stats(&self) -> ImmutableStatisticSet;
|
||||||
fn abilities(&self) -> ImmutableList<Rc<StringKey>>;
|
fn abilities(&self) -> Vec<Rc<StringKey>>;
|
||||||
fn hidden_abilities(&self) -> ImmutableList<Rc<StringKey>>;
|
fn hidden_abilities(&self) -> Vec<Rc<StringKey>>;
|
||||||
}
|
}
|
||||||
fn types(&self) -> &Vec<u8> {
|
fn types(&self) -> &Vec<u8> {
|
||||||
self.inner.types.value_ref()
|
self.inner.types.value_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_flag(&self, flag: &str) -> bool {
|
fn has_flag(&self, flag: &str) -> PkmnResult<bool> {
|
||||||
let hash = get_hash(flag);
|
let hash = get_hash(flag);
|
||||||
unsafe { form_has_flag_by_hash(self.inner.reference, hash) }
|
unsafe { form_has_flag_by_hash(self.inner.reference, hash).as_res() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
@ -160,13 +173,18 @@ mod implementation {
|
||||||
Self {
|
Self {
|
||||||
inner: Rc::new(SpeciesInner {
|
inner: Rc::new(SpeciesInner {
|
||||||
reference,
|
reference,
|
||||||
id: cached_value!({ species_get_id(reference) }),
|
id: cached_value!({ species_get_id(reference).unwrap() }),
|
||||||
name: cached_value!({ species_get_name(reference).get_value().unwrap() }),
|
name: cached_value!({
|
||||||
gender_rate: cached_value!({ species_get_gender_rate(reference) }),
|
species_get_name(reference).unwrap().get_value().unwrap()
|
||||||
growth_rate: cached_value!({
|
|
||||||
species_get_growth_rate(reference).get_value().unwrap()
|
|
||||||
}),
|
}),
|
||||||
capture_rate: cached_value!({ species_get_capture_rate(reference) }),
|
gender_rate: cached_value!({ species_get_gender_rate(reference).unwrap() }),
|
||||||
|
growth_rate: cached_value!({
|
||||||
|
species_get_growth_rate(reference)
|
||||||
|
.unwrap()
|
||||||
|
.get_value()
|
||||||
|
.unwrap()
|
||||||
|
}),
|
||||||
|
capture_rate: cached_value!({ species_get_capture_rate(reference).unwrap() }),
|
||||||
forms: Default::default(),
|
forms: Default::default(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
@ -198,7 +216,7 @@ mod implementation {
|
||||||
if let Some(v) = self.inner.forms.read().get(&hash) {
|
if let Some(v) = self.inner.forms.read().get(&hash) {
|
||||||
v.clone()
|
v.clone()
|
||||||
} else {
|
} else {
|
||||||
let r = species_get_form_by_hash(self.inner.reference, hash);
|
let r = species_get_form_by_hash(self.inner.reference, hash).unwrap();
|
||||||
let value = r.get_value();
|
let value = r.get_value();
|
||||||
let value: Option<Form> = if let Some(value) = value {
|
let value: Option<Form> = if let Some(value) = value {
|
||||||
Some(Rc::new(value))
|
Some(Rc::new(value))
|
||||||
|
@ -211,9 +229,9 @@ mod implementation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_flag(&self, flag: &str) -> bool {
|
fn has_flag(&self, flag: &str) -> PkmnResult<bool> {
|
||||||
let hash = get_hash(flag);
|
let hash = get_hash(flag);
|
||||||
unsafe { species_has_flag_by_hash(self.inner.reference, hash) }
|
unsafe { species_has_flag_by_hash(self.inner.reference, hash).as_res() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
@ -237,25 +255,31 @@ mod implementation {
|
||||||
crate::handling::cacheable::cacheable!(SpeciesImpl);
|
crate::handling::cacheable::cacheable!(SpeciesImpl);
|
||||||
|
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn form_get_name(r: ExternRef<FormImpl>) -> ExternRef<StringKey>;
|
fn form_get_name(r: ExternRef<FormImpl>) -> WasmResult<ExternRef<StringKey>>;
|
||||||
fn form_get_height(r: ExternRef<FormImpl>) -> f32;
|
fn form_get_height(r: ExternRef<FormImpl>) -> WasmResult<f32>;
|
||||||
fn form_get_weight(r: ExternRef<FormImpl>) -> f32;
|
fn form_get_weight(r: ExternRef<FormImpl>) -> WasmResult<f32>;
|
||||||
fn form_get_types(r: ExternRef<FormImpl>) -> FFIArray<u8>;
|
fn form_get_types(r: ExternRef<FormImpl>) -> WasmResult<u64>;
|
||||||
fn form_get_base_experience(r: ExternRef<FormImpl>) -> u32;
|
fn form_get_base_experience(r: ExternRef<FormImpl>) -> WasmResult<u32>;
|
||||||
fn form_get_base_stats(r: ExternRef<FormImpl>) -> ExternRef<ImmutableStatisticSetImpl>;
|
fn form_get_base_stats(
|
||||||
fn form_get_abilities(r: ExternRef<FormImpl>) -> VecExternRef<StringKey>;
|
r: ExternRef<FormImpl>,
|
||||||
fn form_get_hidden_abilities(r: ExternRef<FormImpl>) -> VecExternRef<StringKey>;
|
) -> WasmResult<ExternRef<ImmutableStatisticSetImpl>>;
|
||||||
fn form_has_flag_by_hash(r: ExternRef<FormImpl>, hash: u32) -> bool;
|
fn form_get_abilities(r: ExternRef<FormImpl>) -> WasmResult<u64>;
|
||||||
|
fn form_get_hidden_abilities(r: ExternRef<FormImpl>) -> WasmResult<u64>;
|
||||||
|
fn form_has_flag_by_hash(r: ExternRef<FormImpl>, hash: u32) -> WasmResult<bool>;
|
||||||
|
|
||||||
fn species_get_id(r: ExternRef<SpeciesImpl>) -> u16;
|
fn species_get_id(r: ExternRef<SpeciesImpl>) -> WasmResult<u16>;
|
||||||
fn species_get_name(r: ExternRef<SpeciesImpl>) -> ExternRef<StringKey>;
|
fn species_get_name(r: ExternRef<SpeciesImpl>) -> WasmResult<ExternRef<StringKey>>;
|
||||||
fn species_get_gender_rate(r: ExternRef<SpeciesImpl>) -> f32;
|
fn species_get_gender_rate(r: ExternRef<SpeciesImpl>) -> WasmResult<f32>;
|
||||||
fn species_get_growth_rate(r: ExternRef<SpeciesImpl>) -> ExternRef<StringKey>;
|
fn species_get_growth_rate(r: ExternRef<SpeciesImpl>) -> WasmResult<ExternRef<StringKey>>;
|
||||||
fn species_get_capture_rate(r: ExternRef<SpeciesImpl>) -> u8;
|
fn species_get_capture_rate(r: ExternRef<SpeciesImpl>) -> WasmResult<u8>;
|
||||||
fn species_get_form_by_hash(r: ExternRef<SpeciesImpl>, hash: u32) -> ExternRef<FormImpl>;
|
fn species_get_form_by_hash(
|
||||||
fn species_has_flag_by_hash(r: ExternRef<SpeciesImpl>, flag_hash: u32) -> bool;
|
r: ExternRef<SpeciesImpl>,
|
||||||
|
hash: u32,
|
||||||
|
) -> WasmResult<ExternRef<FormImpl>>;
|
||||||
|
fn species_has_flag_by_hash(r: ExternRef<SpeciesImpl>, flag_hash: u32) -> WasmResult<bool>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::PkmnResult;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub use implementation::*;
|
pub use implementation::*;
|
||||||
|
|
|
@ -11,6 +11,12 @@ pub enum Statistic {
|
||||||
Speed = 5,
|
Speed = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Statistic {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::HP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ImmutableStatisticSetTrait {
|
pub trait ImmutableStatisticSetTrait {
|
||||||
fn hp(&self) -> u16;
|
fn hp(&self) -> u16;
|
||||||
fn attack(&self) -> u16;
|
fn attack(&self) -> u16;
|
||||||
|
@ -28,7 +34,7 @@ mod implementation {
|
||||||
use crate::cached_value;
|
use crate::cached_value;
|
||||||
use crate::handling::cached_value::CachedValue;
|
use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
use crate::handling::extern_ref::{ExternRef, ExternalReferenceType};
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::{Cacheable, WasmResult};
|
||||||
|
|
||||||
pub struct ImmutableStatisticSetInner {
|
pub struct ImmutableStatisticSetInner {
|
||||||
reference: ExternRef<ImmutableStatisticSetImpl>,
|
reference: ExternRef<ImmutableStatisticSetImpl>,
|
||||||
|
@ -56,21 +62,24 @@ mod implementation {
|
||||||
Self::from_ref(reference, &|reference| Self {
|
Self::from_ref(reference, &|reference| Self {
|
||||||
inner: Rc::new(ImmutableStatisticSetInner {
|
inner: Rc::new(ImmutableStatisticSetInner {
|
||||||
reference,
|
reference,
|
||||||
hp: cached_value!({ static_statistics_set_get_stat(reference, Statistic::HP) }),
|
hp: cached_value!({
|
||||||
|
static_statistics_set_get_stat(reference, Statistic::HP).unwrap()
|
||||||
|
}),
|
||||||
attack: cached_value!({
|
attack: cached_value!({
|
||||||
static_statistics_set_get_stat(reference, Statistic::Attack)
|
static_statistics_set_get_stat(reference, Statistic::Attack).unwrap()
|
||||||
}),
|
}),
|
||||||
defense: cached_value!({
|
defense: cached_value!({
|
||||||
static_statistics_set_get_stat(reference, Statistic::Defense)
|
static_statistics_set_get_stat(reference, Statistic::Defense).unwrap()
|
||||||
}),
|
}),
|
||||||
special_attack: cached_value!({
|
special_attack: cached_value!({
|
||||||
static_statistics_set_get_stat(reference, Statistic::SpecialAttack)
|
static_statistics_set_get_stat(reference, Statistic::SpecialAttack).unwrap()
|
||||||
}),
|
}),
|
||||||
special_defense: cached_value!({
|
special_defense: cached_value!({
|
||||||
static_statistics_set_get_stat(reference, Statistic::SpecialDefense)
|
static_statistics_set_get_stat(reference, Statistic::SpecialDefense)
|
||||||
|
.unwrap()
|
||||||
}),
|
}),
|
||||||
speed: cached_value!({
|
speed: cached_value!({
|
||||||
static_statistics_set_get_stat(reference, Statistic::Speed)
|
static_statistics_set_get_stat(reference, Statistic::Speed).unwrap()
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
@ -110,7 +119,7 @@ mod implementation {
|
||||||
fn static_statistics_set_get_stat(
|
fn static_statistics_set_get_stat(
|
||||||
r: ExternRef<ImmutableStatisticSetImpl>,
|
r: ExternRef<ImmutableStatisticSetImpl>,
|
||||||
stat: Statistic,
|
stat: Statistic,
|
||||||
) -> u16;
|
) -> WasmResult<u16>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
use crate::alloc::string::ToString;
|
||||||
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
use crate::handling::wasm_result::WasmResult;
|
||||||
|
#[cfg(not(feature = "mock_data"))]
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::Cacheable;
|
||||||
|
use crate::PkmnResult;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
use crate::{ExternRef, ExternalReferenceType};
|
use crate::{pkmn_err, ExternRef, ExternalReferenceType, PkmnErr};
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use core::fmt::{Debug, Display, Formatter};
|
use core::fmt::{Debug, Display, Formatter};
|
||||||
|
@ -21,7 +26,10 @@ pub struct StringKey {
|
||||||
|
|
||||||
impl Debug for StringKey {
|
impl Debug for StringKey {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
write!(f, "\"{}\"", self.str().to_str().unwrap())
|
match self.str() {
|
||||||
|
Ok(s) => write!(f, "\"{}\"", s.to_str().unwrap()),
|
||||||
|
Err(e) => write!(f, "Error: {}", e),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,41 +53,44 @@ impl StringKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn str(&self) -> &CString {
|
pub fn str(&self) -> PkmnResult<&CString> {
|
||||||
if self.data.str.borrow().is_none() {
|
if self.data.str.borrow().is_none() {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.data
|
let ptr = string_key_get_str(self.ptr()).as_res()?;
|
||||||
.str
|
let ptr = ptr as *mut cstr_core::c_char;
|
||||||
.replace(Some(CString::from_raw(string_key_get_str(self.ptr()))));
|
self.data.str.replace(Some(CString::from_raw(ptr)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe { (*self.data.str.as_ptr()).as_ref().unwrap() }
|
Ok(unsafe {
|
||||||
|
(*self.data.str.as_ptr())
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(pkmn_err!("Stringkey was null"))?
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "mock_data")]
|
#[cfg(feature = "mock_data")]
|
||||||
pub fn str(&self) -> &CString {
|
pub fn str(&self) -> PkmnResult<&CString> {
|
||||||
unsafe { (*self.data.str.as_ptr()).as_ref().unwrap() }
|
Ok(unsafe { (*self.data.str.as_ptr()).as_ref().unwrap() })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn hash(&self) -> u32 {
|
pub fn hash(&self) -> PkmnResult<u32> {
|
||||||
if self.data.hash.borrow().is_none() {
|
if self.data.hash.borrow().is_none() {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.data
|
let hash = string_key_get_hash(self.ptr()).as_res()?;
|
||||||
.hash
|
self.data.hash.replace(Some(hash));
|
||||||
.replace(Some(string_key_get_hash(self.ptr())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.data.hash.borrow().unwrap()
|
Ok(self.data.hash.borrow().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "mock_data")]
|
#[cfg(feature = "mock_data")]
|
||||||
pub fn hash(&self) -> u32 {
|
pub fn hash(&self) -> PkmnResult<u32> {
|
||||||
self.data.hash.borrow().unwrap()
|
Ok(self.data.hash.borrow().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equals_str(&self, other: &str) -> bool {
|
pub fn equals_str(&self, other: &str) -> bool {
|
||||||
self.hash() == get_hash(other)
|
self.hash().unwrap() == get_hash(other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,15 +118,15 @@ impl ExternalReferenceType for StringKey {
|
||||||
|
|
||||||
impl Display for StringKey {
|
impl Display for StringKey {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
let s = self.str();
|
let s = self.str().unwrap();
|
||||||
f.write_str(s.to_str().as_ref().unwrap())
|
f.write_str(s.to_str().as_ref().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn string_key_get_str(ptr: ExternRef<StringKey>) -> *mut cstr_core::c_char;
|
fn string_key_get_str(ptr: ExternRef<StringKey>) -> WasmResult<u32>;
|
||||||
fn string_key_get_hash(ptr: ExternRef<StringKey>) -> u32;
|
fn string_key_get_hash(ptr: ExternRef<StringKey>) -> WasmResult<u32>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CRC_TABLE: &[u32] = &[
|
const CRC_TABLE: &[u32] = &[
|
||||||
|
|
|
@ -7,7 +7,7 @@ pub struct CachedValue<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
impl<T> CachedValue<T> {
|
impl<T: Clone> CachedValue<T> {
|
||||||
pub fn new(init_fn: Box<dyn Fn() -> T>) -> Self {
|
pub fn new(init_fn: Box<dyn Fn() -> T>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
init_fn,
|
init_fn,
|
||||||
|
@ -15,13 +15,15 @@ impl<T> CachedValue<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
fn init_if_empty(&self) -> T
|
||||||
fn init_if_empty(&self) {
|
where
|
||||||
if self.value.is_none() {
|
T: Clone,
|
||||||
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
let s = self as *const Self as *mut Self;
|
let s = self as *const Self as *mut Self;
|
||||||
s.as_mut().unwrap().value.replace((self.init_fn)());
|
let v = (self.init_fn)();
|
||||||
}
|
s.as_mut().unwrap().value.replace(v.clone());
|
||||||
|
v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,8 +32,10 @@ impl<T> CachedValue<T> {
|
||||||
where
|
where
|
||||||
T: Clone,
|
T: Clone,
|
||||||
{
|
{
|
||||||
self.init_if_empty();
|
match self.value {
|
||||||
self.value.as_ref().unwrap().clone()
|
Some(ref v) => v.clone(),
|
||||||
|
None => self.init_if_empty(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use core::hash::{Hash, Hasher};
|
use core::hash::{Hash, Hasher};
|
||||||
#[cfg(not(feature = "mock_data"))]
|
|
||||||
use core::intrinsics::transmute;
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -82,6 +80,15 @@ impl<T> Clone for ExternRef<T> {
|
||||||
|
|
||||||
impl<T> Copy for ExternRef<T> {}
|
impl<T> Copy for ExternRef<T> {}
|
||||||
|
|
||||||
|
impl<T> Default for ExternRef<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
p: 0,
|
||||||
|
resource_type: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Eq for ExternRef<T> {}
|
impl<T> Eq for ExternRef<T> {}
|
||||||
|
|
||||||
impl<T> PartialEq<Self> for ExternRef<T> {
|
impl<T> PartialEq<Self> for ExternRef<T> {
|
||||||
|
@ -117,70 +124,6 @@ impl<T> From<u32> for ExternRef<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct VecExternRef<T> {
|
|
||||||
v: u64,
|
|
||||||
resource_type: PhantomData<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> VecExternRef<T> {
|
|
||||||
pub fn is_null(&self) -> bool {
|
|
||||||
self.v == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
|
||||||
pub(crate) fn get_internal_index(&self) -> u32 {
|
|
||||||
let v: (u32, u32) = unsafe { transmute(self.v) };
|
|
||||||
v.0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
|
||||||
pub(crate) fn len(&self) -> u32 {
|
|
||||||
let v: (u32, u32) = unsafe { transmute(self.v) };
|
|
||||||
v.1
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
|
||||||
pub(crate) fn at(&self, index: u32) -> ExternRef<T> {
|
|
||||||
let p = unsafe { _vec_extern_ref_get_value(self.get_internal_index(), index) };
|
|
||||||
ExternRef {
|
|
||||||
p,
|
|
||||||
resource_type: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Clone for VecExternRef<T> {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
Self {
|
|
||||||
v: self.v,
|
|
||||||
resource_type: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Copy for VecExternRef<T> {}
|
|
||||||
|
|
||||||
impl<T> Eq for VecExternRef<T> {}
|
|
||||||
|
|
||||||
impl<T> PartialEq<Self> for VecExternRef<T> {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
u64::eq(&self.v, &other.v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> PartialOrd<Self> for VecExternRef<T> {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
u64::partial_cmp(&self.v, &other.v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Ord for VecExternRef<T> {
|
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
|
||||||
u64::cmp(&self.v, &other.v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ExternalReferenceType {
|
pub trait ExternalReferenceType {
|
||||||
fn from_extern_value(reference: ExternRef<Self>) -> Self
|
fn from_extern_value(reference: ExternRef<Self>) -> Self
|
||||||
where
|
where
|
||||||
|
@ -222,8 +165,3 @@ macro_rules! impl_extern_ctor {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
|
||||||
extern "wasm" {
|
|
||||||
fn _vec_extern_ref_get_value(extern_ref: u32, index: u32) -> u32;
|
|
||||||
}
|
|
||||||
|
|
|
@ -19,6 +19,24 @@ impl<T> FFIArray<T> {
|
||||||
mem::forget(boxed_slice);
|
mem::forget(boxed_slice);
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
pub(crate) fn from_u64(v: u64) -> Self {
|
||||||
|
let v: (u32, u32) = unsafe { core::mem::transmute(v) };
|
||||||
|
Self {
|
||||||
|
ptr: v.0 as *mut T,
|
||||||
|
len: v.1 as usize,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for FFIArray<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
ptr: core::ptr::null_mut(),
|
||||||
|
len: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
|
|
@ -8,6 +8,7 @@ pub mod ffi_array;
|
||||||
pub mod script;
|
pub mod script;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub(crate) mod temporary;
|
pub(crate) mod temporary;
|
||||||
|
pub(crate) mod wasm_result;
|
||||||
|
|
||||||
pub use capabilities::*;
|
pub use capabilities::*;
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@ pub use capabilities::*;
|
||||||
pub(crate) use cacheable::Cacheable;
|
pub(crate) use cacheable::Cacheable;
|
||||||
pub use script::Script;
|
pub use script::Script;
|
||||||
pub use script::ScriptOwner;
|
pub use script::ScriptOwner;
|
||||||
|
pub use wasm_result::*;
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum ScriptCategory {
|
pub enum ScriptCategory {
|
||||||
|
@ -41,7 +43,7 @@ macro_rules! wasm_reference_getters_extern {
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
$(
|
$(
|
||||||
paste::paste!{
|
paste::paste!{
|
||||||
fn [<$type_name:snake _get_ $name>](r: ExternRef<$base_type>) -> ExternRef<$type>;
|
fn [<$type_name:snake _get_ $name>](r: ExternRef<$base_type>) -> WasmResult<ExternRef<$type>>;
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
@ -151,7 +153,7 @@ macro_rules! wasm_optional_reference_getters_extern {
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
$(
|
$(
|
||||||
paste::paste!{
|
paste::paste!{
|
||||||
fn [<$type_name:snake _get_ $name>](r: ExternRef<$base_type>) -> ExternRef<$type>;
|
fn [<$type_name:snake _get_ $name>](r: ExternRef<$base_type>) -> WasmResult<ExternRef<$type>>;
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
@ -228,7 +230,7 @@ macro_rules! wasm_value_getters_extern {
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
$(
|
$(
|
||||||
paste::paste!{
|
paste::paste!{
|
||||||
fn [<$type_name:snake _get_ $name>](r: ExternRef<$base_type>) -> $type;
|
fn [<$type_name:snake _get_ $name>](r: ExternRef<$base_type>) -> WasmResult<$type>;
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
@ -246,10 +248,10 @@ macro_rules! wasm_value_getters_funcs {
|
||||||
) => {
|
) => {
|
||||||
$(
|
$(
|
||||||
$(#[$attr])*
|
$(#[$attr])*
|
||||||
$v fn $name(&self) -> $type {
|
$v fn $name(&self) -> PkmnResult<$type> {
|
||||||
paste::paste!{
|
paste::paste!{
|
||||||
unsafe{
|
unsafe{
|
||||||
[<$base_type:snake _get_ $name>](self.inner.reference)
|
[<$base_type:snake _get_ $name>](self.inner.reference).as_res()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use crate::app_interface::list::ImmutableList;
|
|
||||||
use crate::app_interface::{
|
use crate::app_interface::{
|
||||||
Battle, BattleSide, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Item,
|
Battle, BattleSide, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Item,
|
||||||
Pokemon, Statistic, TurnChoice, TypeIdentifier,
|
Pokemon, Statistic, TurnChoice, TypeIdentifier,
|
||||||
|
@ -6,8 +5,10 @@ use crate::app_interface::{
|
||||||
use crate::handling::ScriptCapabilities;
|
use crate::handling::ScriptCapabilities;
|
||||||
use crate::StringKey;
|
use crate::StringKey;
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
use core::fmt::{Debug, Display, Formatter};
|
use core::fmt::{Debug, Display, Formatter};
|
||||||
|
type Result<T> = crate::result::PkmnResult<T>;
|
||||||
|
|
||||||
pub trait Script {
|
pub trait Script {
|
||||||
fn new() -> Self
|
fn new() -> Self
|
||||||
|
@ -18,58 +19,97 @@ pub trait Script {
|
||||||
|
|
||||||
/// This function is ran when a volatile effect is added while that volatile effect already is
|
/// This function is ran when a volatile effect is added while that volatile effect already is
|
||||||
/// in place. Instead of adding the volatile effect twice, it will execute this function instead.
|
/// in place. Instead of adding the volatile effect twice, it will execute this function instead.
|
||||||
fn stack(&self) {}
|
fn stack(&self) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function is ran when this script stops being in effect, and is removed from its owner.
|
/// This function is ran when this script stops being in effect, and is removed from its owner.
|
||||||
fn on_remove(&self) {}
|
fn on_remove(&self) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// This function is ran when this script starts being in effect.
|
/// This function is ran when this script starts being in effect.
|
||||||
fn on_initialize(
|
fn on_initialize(
|
||||||
&self,
|
&self,
|
||||||
_library: DynamicLibrary,
|
_library: DynamicLibrary,
|
||||||
_parameters: Option<ImmutableList<Rc<EffectParameter>>>,
|
_parameters: Option<Vec<Rc<EffectParameter>>>,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function is ran just before the start of the turn. Everyone has made its choices here,
|
/// This function is ran just before the start of the turn. Everyone has made its choices here,
|
||||||
/// and the turn is about to start. This is a great place to initialize data if you need to know
|
/// and the turn is about to start. This is a great place to initialize data if you need to know
|
||||||
/// something has happened during a turn.
|
/// something has happened during a turn.
|
||||||
fn on_before_turn(&self, _choice: TurnChoice) {}
|
fn on_before_turn(&self, _choice: TurnChoice) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// This function allows you to modify the effective speed of the Pokemon. This is ran before
|
/// This function allows you to modify the effective speed of the Pokemon. This is ran before
|
||||||
/// turn ordering, so overriding here will allow you to put certain Pokemon before others.
|
/// turn ordering, so overriding here will allow you to put certain Pokemon before others.
|
||||||
fn change_speed(&self, _choice: TurnChoice, _speed: &mut u32) {}
|
fn change_speed(&self, _choice: TurnChoice, _speed: &mut u32) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function allows you to modify the effective priority of the Pokemon. This is ran before
|
/// This function allows you to modify the effective priority of the Pokemon. This is ran before
|
||||||
/// turn ordering, so overriding here will allow you to put certain Pokemon before others. Note
|
/// turn ordering, so overriding here will allow you to put certain Pokemon before others. Note
|
||||||
/// that this is only relevant on move choices, as other turn choice types do not have a priority.
|
/// that this is only relevant on move choices, as other turn choice types do not have a priority.
|
||||||
fn change_priority(&self, _choice: TurnChoice, _priority: &mut i8) {}
|
fn change_priority(&self, _choice: TurnChoice, _priority: &mut i8) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// This function allows you to change the move that is used during execution. This is useful for
|
/// This function allows you to change the move that is used during execution. This is useful for
|
||||||
/// moves such as metronome, where the move chosen actually differs from the move used.
|
/// moves such as metronome, where the move chosen actually differs from the move used.
|
||||||
fn change_move(&self, _choice: TurnChoice, _move_name: &mut StringKey) {}
|
fn change_move(&self, _choice: TurnChoice, _move_name: &mut StringKey) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function allows you to change a move into a multi-hit move. The number of hits set here
|
/// This function allows you to change a move into a multi-hit move. The number of hits set here
|
||||||
/// gets used as the number of hits. If set to 0, this will behave as if the move missed on its
|
/// gets used as the number of hits. If set to 0, this will behave as if the move missed on its
|
||||||
/// first hit.
|
/// first hit.
|
||||||
fn change_number_of_hits(&self, _choice: TurnChoice, _number_of_hits: &mut u8) {}
|
fn change_number_of_hits(&self, _choice: TurnChoice, _number_of_hits: &mut u8) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// This function allows you to prevent a move from running. If this gets set to true, the move
|
/// This function allows you to prevent a move from running. If this gets set to true, the move
|
||||||
/// ends execution here. No PP will be decreased in this case.
|
/// ends execution here. No PP will be decreased in this case.
|
||||||
fn prevent_move(&self, _move: ExecutingMove, _prevent: &mut bool) {}
|
fn prevent_move(&self, _move: ExecutingMove, _prevent: &mut bool) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function makes the move fail. If the fail field gets set to true, the move ends execution,
|
/// This function makes the move fail. If the fail field gets set to true, the move ends execution,
|
||||||
/// and fail events get triggered.
|
/// and fail events get triggered.
|
||||||
fn fail_move(&self, _move: ExecutingMove, _fail: &mut bool) {}
|
fn fail_move(&self, _move: ExecutingMove, _fail: &mut bool) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// Similar to [`Self::prevent_move`]. This function will also stop execution, but PP will be
|
/// Similar to [`Self::prevent_move`]. This function will also stop execution, but PP will be
|
||||||
/// decreased.
|
/// decreased.
|
||||||
fn stop_before_move(&self, _move: ExecutingMove, _stop: &mut bool) {}
|
fn stop_before_move(&self, _move: ExecutingMove, _stop: &mut bool) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function runs just before the move starts its execution.
|
/// This function runs just before the move starts its execution.
|
||||||
fn on_before_move(&self, _move: ExecutingMove) {}
|
fn on_before_move(&self, _move: ExecutingMove) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function allows a script to prevent a move that is targeted at its owner. If set to true
|
/// This function allows a script to prevent a move that is targeted at its owner. If set to true
|
||||||
/// the move fails, and fail events get triggered.
|
/// the move fails, and fail events get triggered.
|
||||||
fn fail_incoming_move(&self, _move: ExecutingMove, _target: Pokemon, _fail: &mut bool) {}
|
fn fail_incoming_move(
|
||||||
|
&self,
|
||||||
|
_move: ExecutingMove,
|
||||||
|
_target: Pokemon,
|
||||||
|
_fail: &mut bool,
|
||||||
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function allows a script to make its owner invulnerable to an incoming move.
|
/// This function allows a script to make its owner invulnerable to an incoming move.
|
||||||
fn is_invulnerable(&self, _move: ExecutingMove, _target: Pokemon, _invulnerable: &mut bool) {}
|
fn is_invulnerable(
|
||||||
|
&self,
|
||||||
|
_move: ExecutingMove,
|
||||||
|
_target: Pokemon,
|
||||||
|
_invulnerable: &mut bool,
|
||||||
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function occurs when a move gets missed. This runs on the scripts belonging to the executing
|
/// This function occurs when a move gets missed. This runs on the scripts belonging to the executing
|
||||||
/// move, which include the scripts that are attached to the owner of the script.
|
/// move, which include the scripts that are attached to the owner of the script.
|
||||||
fn on_move_miss(&self, _move: ExecutingMove, _target: Pokemon) {}
|
fn on_move_miss(&self, _move: ExecutingMove, _target: Pokemon) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function allows the script to change the actual type that is used for the move on a target.
|
/// This function allows the script to change the actual type that is used for the move on a target.
|
||||||
fn change_move_type(
|
fn change_move_type(
|
||||||
&self,
|
&self,
|
||||||
|
@ -77,7 +117,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_move_type: &mut TypeIdentifier,
|
_move_type: &mut TypeIdentifier,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows the script to change how effective a move is on a target.
|
/// This function allows the script to change how effective a move is on a target.
|
||||||
fn change_effectiveness(
|
fn change_effectiveness(
|
||||||
|
@ -86,7 +127,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_effectiveness: &mut f32,
|
_effectiveness: &mut f32,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script to block an outgoing move from being critical.
|
/// This function allows a script to block an outgoing move from being critical.
|
||||||
fn block_critical(
|
fn block_critical(
|
||||||
|
@ -95,7 +137,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_block_critical: &mut bool,
|
_block_critical: &mut bool,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script to block an incoming move from being critical.
|
/// This function allows a script to block an incoming move from being critical.
|
||||||
fn block_incoming_critical(
|
fn block_incoming_critical(
|
||||||
|
@ -104,7 +147,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_block_critical: &mut bool,
|
_block_critical: &mut bool,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script to modify the accuracy of a move used. This value represents
|
/// This function allows a script to modify the accuracy of a move used. This value represents
|
||||||
/// the percentage accuracy, so anything above 100% will make it always hit.
|
/// the percentage accuracy, so anything above 100% will make it always hit.
|
||||||
|
@ -114,7 +158,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_accuracy: &mut u8,
|
_accuracy: &mut u8,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function allows a script to change the critical stage of the move used.
|
/// This function allows a script to change the critical stage of the move used.
|
||||||
|
@ -124,7 +169,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_stage: &mut u8,
|
_stage: &mut u8,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script to change the damage modifier of a critical hit. This will only
|
/// This function allows a script to change the damage modifier of a critical hit. This will only
|
||||||
/// run when a hit is critical.
|
/// run when a hit is critical.
|
||||||
|
@ -134,7 +180,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_modifier: &mut f32,
|
_modifier: &mut f32,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script to change the damage modifier of a Same Type Attack Bonus, which
|
/// This function allows a script to change the damage modifier of a Same Type Attack Bonus, which
|
||||||
/// occurs when the user has the move type as one of its own types.
|
/// occurs when the user has the move type as one of its own types.
|
||||||
|
@ -144,7 +191,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_modifier: &mut f32,
|
_modifier: &mut f32,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function allows a script to change the effective base power of a move hit.
|
/// This function allows a script to change the effective base power of a move hit.
|
||||||
|
@ -154,7 +202,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_base_power: &mut u8,
|
_base_power: &mut u8,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script to bypass defensive stat boosts for a move hit.
|
/// This function allows a script to bypass defensive stat boosts for a move hit.
|
||||||
fn bypass_defensive_stat_boost(
|
fn bypass_defensive_stat_boost(
|
||||||
|
@ -163,7 +212,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_bypass: &mut bool,
|
_bypass: &mut bool,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script to bypass offensive stat boosts for a move hit.
|
/// This function allows a script to bypass offensive stat boosts for a move hit.
|
||||||
fn bypass_offensive_stat_boost(
|
fn bypass_offensive_stat_boost(
|
||||||
|
@ -172,7 +222,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_bypass: &mut bool,
|
_bypass: &mut bool,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script to change the actual offensive stat values used when calculating damage
|
/// This function allows a script to change the actual offensive stat values used when calculating damage
|
||||||
fn change_offensive_stat_value(
|
fn change_offensive_stat_value(
|
||||||
|
@ -181,7 +232,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_amount: &mut u32,
|
_amount: &mut u32,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script to change the actual defensive stat values used when calculating damage.
|
/// This function allows a script to change the actual defensive stat values used when calculating damage.
|
||||||
fn change_defensive_stat_value(
|
fn change_defensive_stat_value(
|
||||||
|
@ -190,7 +242,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_amount: &mut u32,
|
_amount: &mut u32,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function allows a script to change the raw modifier we retrieved from the stats of the
|
/// This function allows a script to change the raw modifier we retrieved from the stats of the
|
||||||
|
@ -201,7 +254,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_modifier: &mut f32,
|
_modifier: &mut f32,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script to apply a raw multiplier to the damage done by a move.
|
/// This function allows a script to apply a raw multiplier to the damage done by a move.
|
||||||
fn change_damage_modifier(
|
fn change_damage_modifier(
|
||||||
|
@ -210,10 +264,19 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_modifier: &mut f32,
|
_modifier: &mut f32,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script to modify the outgoing damage done by a move.
|
/// This function allows a script to modify the outgoing damage done by a move.
|
||||||
fn change_damage(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8, _damage: &mut u32) {}
|
fn change_damage(
|
||||||
|
&self,
|
||||||
|
_move: ExecutingMove,
|
||||||
|
_target: Pokemon,
|
||||||
|
_hit: u8,
|
||||||
|
_damage: &mut u32,
|
||||||
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function allows a script to modify the incoming damage done by a move.
|
/// This function allows a script to modify the incoming damage done by a move.
|
||||||
fn change_incoming_damage(
|
fn change_incoming_damage(
|
||||||
&self,
|
&self,
|
||||||
|
@ -221,13 +284,18 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_damage: &mut u32,
|
_damage: &mut u32,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function triggers when an incoming hit happens. This triggers after the damage is done,
|
/// This function triggers when an incoming hit happens. This triggers after the damage is done,
|
||||||
/// but before the secondary effect of the move happens.
|
/// but before the secondary effect of the move happens.
|
||||||
fn on_incoming_hit(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) {}
|
fn on_incoming_hit(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function triggers when an opponent on the field faints.
|
/// This function triggers when an opponent on the field faints.
|
||||||
fn on_opponent_faints(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) {}
|
fn on_opponent_faints(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function allows a script attached to a Pokemon or its parents to prevent stat boost
|
/// This function allows a script attached to a Pokemon or its parents to prevent stat boost
|
||||||
/// changes on that Pokemon.
|
/// changes on that Pokemon.
|
||||||
fn prevent_stat_boost_change(
|
fn prevent_stat_boost_change(
|
||||||
|
@ -237,7 +305,8 @@ pub trait Script {
|
||||||
_amount: i8,
|
_amount: i8,
|
||||||
_self_inflicted: bool,
|
_self_inflicted: bool,
|
||||||
_prevent: &mut bool,
|
_prevent: &mut bool,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script attached to a Pokemon or its parents to modify the amount by
|
/// This function allows a script attached to a Pokemon or its parents to modify the amount by
|
||||||
/// which the stat boost will change. If the stat boost is done by the user itself, self
|
/// which the stat boost will change. If the stat boost is done by the user itself, self
|
||||||
|
@ -248,7 +317,8 @@ pub trait Script {
|
||||||
_stat: Statistic,
|
_stat: Statistic,
|
||||||
_self_inflicted: bool,
|
_self_inflicted: bool,
|
||||||
_amount: &mut i8,
|
_amount: &mut i8,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script attached to a Pokemon or its parents to prevent an incoming
|
/// This function allows a script attached to a Pokemon or its parents to prevent an incoming
|
||||||
/// secondary effect. This means the move will still hit and do damage, but not trigger its
|
/// secondary effect. This means the move will still hit and do damage, but not trigger its
|
||||||
|
@ -259,7 +329,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_prevent: &mut bool,
|
_prevent: &mut bool,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script attached to a move or its parents to change the chance the
|
/// This function allows a script attached to a move or its parents to change the chance the
|
||||||
/// secondary effect of a move will trigger. The chance is depicted in percentage here, so
|
/// secondary effect of a move will trigger. The chance is depicted in percentage here, so
|
||||||
|
@ -271,7 +342,8 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_chance: &mut f32,
|
_chance: &mut f32,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function allows a script attached to a Pokemon or its parents to change the chance the
|
/// This function allows a script attached to a Pokemon or its parents to change the chance the
|
||||||
/// secondary effect of an incoming move will trigger. The chance is depicted in percentage here,
|
/// secondary effect of an incoming move will trigger. The chance is depicted in percentage here,
|
||||||
|
@ -283,30 +355,49 @@ pub trait Script {
|
||||||
_target: Pokemon,
|
_target: Pokemon,
|
||||||
_hit: u8,
|
_hit: u8,
|
||||||
_chance: &mut f32,
|
_chance: &mut f32,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function triggers when the move uses its secondary effect. Moves should implement their
|
/// This function triggers when the move uses its secondary effect. Moves should implement their
|
||||||
/// secondary effects here. Status moves should implement their actual functionality in this
|
/// secondary effects here. Status moves should implement their actual functionality in this
|
||||||
/// function as well, as status moves effects are defined as secondary effects for simplicity.
|
/// function as well, as status moves effects are defined as secondary effects for simplicity.
|
||||||
fn on_secondary_effect(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) {}
|
fn on_secondary_effect(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function triggers on a move or its parents when all hits on a target are finished.
|
/// This function triggers on a move or its parents when all hits on a target are finished.
|
||||||
fn on_after_hits(&self, _move: ExecutingMove, _target: Pokemon) {}
|
fn on_after_hits(&self, _move: ExecutingMove, _target: Pokemon) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function prevents the Pokemon it is attached to from being able to switch out.
|
/// This function prevents the Pokemon it is attached to from being able to switch out.
|
||||||
fn prevent_self_switch(&self, _choice: TurnChoice, _prevent: &mut bool) {}
|
fn prevent_self_switch(&self, _choice: TurnChoice, _prevent: &mut bool) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function allows the prevention of switching for any opponent.
|
/// This function allows the prevention of switching for any opponent.
|
||||||
fn prevent_opponent_switch(&self, _choice: TurnChoice, _prevent: &mut bool) {}
|
fn prevent_opponent_switch(&self, _choice: TurnChoice, _prevent: &mut bool) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function is called on a move and its parents when the move fails.
|
/// This function is called on a move and its parents when the move fails.
|
||||||
fn on_fail(&self, _target: Pokemon) {}
|
fn on_fail(&self, _target: Pokemon) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function is called on a script when an opponent fails.
|
/// This function is called on a script when an opponent fails.
|
||||||
fn on_opponent_fail(&self, _target: Pokemon) {}
|
fn on_opponent_fail(&self, _target: Pokemon) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function allows preventing the running away of the Pokemon its attached to
|
/// This function allows preventing the running away of the Pokemon its attached to
|
||||||
fn prevent_self_run_away(&self, _choice: TurnChoice, _prevent: &mut bool) {}
|
fn prevent_self_run_away(&self, _choice: TurnChoice, _prevent: &mut bool) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function prevents a Pokemon on another side than where its attached to from running away.
|
/// This function prevents a Pokemon on another side than where its attached to from running away.
|
||||||
fn prevent_opponent_run_away(&self, _choice: TurnChoice, _prevent: &mut bool) {}
|
fn prevent_opponent_run_away(&self, _choice: TurnChoice, _prevent: &mut bool) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function id triggered on all scripts active in the battle after all choices have finished
|
/// This function id triggered on all scripts active in the battle after all choices have finished
|
||||||
/// running. Note that choices are not active anymore here, so their scripts do not call this
|
/// running. Note that choices are not active anymore here, so their scripts do not call this
|
||||||
/// function.
|
/// function.
|
||||||
fn on_end_turn(&self) {}
|
fn on_end_turn(&self) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon takes damage.
|
/// This function is triggered on a Pokemon and its parents when the given Pokemon takes damage.
|
||||||
fn on_damage(
|
fn on_damage(
|
||||||
&self,
|
&self,
|
||||||
|
@ -314,16 +405,23 @@ pub trait Script {
|
||||||
_source: DamageSource,
|
_source: DamageSource,
|
||||||
_old_health: u32,
|
_old_health: u32,
|
||||||
_new_health: u32,
|
_new_health: u32,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon faints.
|
/// This function is triggered on a Pokemon and its parents when the given Pokemon faints.
|
||||||
fn on_faint(&self, _pokemon: Pokemon, _source: DamageSource) {}
|
fn on_faint(&self, _pokemon: Pokemon, _source: DamageSource) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon is switched into
|
/// This function is triggered on a Pokemon and its parents when the given Pokemon is switched into
|
||||||
/// the battlefield.
|
/// the battlefield.
|
||||||
fn on_switch_in(&self, _pokemon: Pokemon) {}
|
fn on_switch_in(&self, _pokemon: Pokemon) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon consumes the
|
/// This function is triggered on a Pokemon and its parents when the given Pokemon consumes the
|
||||||
/// held item it had.
|
/// held item it had.
|
||||||
fn on_after_held_item_consume(&self, _pokemon: Pokemon, _item: Item) {}
|
fn on_after_held_item_consume(&self, _pokemon: Pokemon, _item: Item) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon gains experience,
|
/// This function is triggered on a Pokemon and its parents when the given Pokemon gains experience,
|
||||||
/// and allows for changing this amount of experience.
|
/// and allows for changing this amount of experience.
|
||||||
fn change_experience_gained(
|
fn change_experience_gained(
|
||||||
|
@ -331,18 +429,35 @@ pub trait Script {
|
||||||
_fainted_mon: Pokemon,
|
_fainted_mon: Pokemon,
|
||||||
_winning_mon: Pokemon,
|
_winning_mon: Pokemon,
|
||||||
_amount: &mut u32,
|
_amount: &mut u32,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon gains experience,
|
/// This function is triggered on a Pokemon and its parents when the given Pokemon gains experience,
|
||||||
/// and allows for making the experience be shared across multiple Pokemon.
|
/// and allows for making the experience be shared across multiple Pokemon.
|
||||||
fn share_experience(&self, _fainted_mon: Pokemon, _winning_mon: Pokemon, _shares: &mut bool) {}
|
fn share_experience(
|
||||||
|
&self,
|
||||||
|
_fainted_mon: Pokemon,
|
||||||
|
_winning_mon: Pokemon,
|
||||||
|
_shares: &mut bool,
|
||||||
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function is triggered on a battle and its parents when something attempts to change the
|
/// This function is triggered on a battle and its parents when something attempts to change the
|
||||||
/// weather, and allows for blocking the weather change.
|
/// weather, and allows for blocking the weather change.
|
||||||
fn block_weather(&self, _battle: Battle, _blocked: &mut bool) {}
|
fn block_weather(&self, _battle: Battle, _blocked: &mut bool) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
/// This function is called when a Pokeball is thrown at a Pokemon, and allows modifying the catch
|
/// This function is called when a Pokeball is thrown at a Pokemon, and allows modifying the catch
|
||||||
/// rate of this attempt. Pokeball modifier effects should be implemented here, as well as for
|
/// rate of this attempt. Pokeball modifier effects should be implemented here, as well as for
|
||||||
/// example status effects that change capture rates.
|
/// example status effects that change capture rates.
|
||||||
fn change_capture_rate_bonus(&self, _target: Pokemon, _pokeball: Item, _modifier: &mut u8) {}
|
fn change_capture_rate_bonus(
|
||||||
|
&self,
|
||||||
|
_target: Pokemon,
|
||||||
|
_pokeball: Item,
|
||||||
|
_modifier: &mut u8,
|
||||||
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
use crate::{pkmn_err, PkmnErr, PkmnResult};
|
||||||
|
use alloc::string::ToString;
|
||||||
|
use cstr_core::{c_char, CString};
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[repr(packed)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct WasmResult<T>
|
||||||
|
where
|
||||||
|
T: Default,
|
||||||
|
{
|
||||||
|
err_ptr: u32,
|
||||||
|
value: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type WasmVoidResult = WasmResult<()>;
|
||||||
|
|
||||||
|
impl<T> WasmResult<T>
|
||||||
|
where
|
||||||
|
T: Default,
|
||||||
|
{
|
||||||
|
pub fn unwrap(self) -> T {
|
||||||
|
unsafe {
|
||||||
|
if self.err_ptr == 0 {
|
||||||
|
self.value
|
||||||
|
} else {
|
||||||
|
let ptr = self.err_ptr as *mut c_char;
|
||||||
|
let s = CString::from_raw(ptr).to_string_lossy().to_string();
|
||||||
|
panic!("{}", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_res(self) -> PkmnResult<T> {
|
||||||
|
PkmnResult::from(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ok(value: T) -> Self {
|
||||||
|
WasmResult { err_ptr: 0, value }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn err(err: PkmnErr) -> Self {
|
||||||
|
let s: CString = err.into();
|
||||||
|
let ptr = s.into_raw();
|
||||||
|
WasmResult {
|
||||||
|
err_ptr: ptr as u32,
|
||||||
|
value: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_res(res: PkmnResult<T>) -> Self {
|
||||||
|
WasmResult::from(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<WasmResult<T>> for crate::PkmnResult<T>
|
||||||
|
where
|
||||||
|
T: Default,
|
||||||
|
{
|
||||||
|
fn from(value: WasmResult<T>) -> Self {
|
||||||
|
unsafe {
|
||||||
|
if value.err_ptr == 0 {
|
||||||
|
Ok(value.value)
|
||||||
|
} else {
|
||||||
|
let ptr = value.err_ptr as *mut c_char;
|
||||||
|
let s = CString::from_raw(ptr).to_string_lossy().to_string();
|
||||||
|
Err(pkmn_err!(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<crate::PkmnResult<T>> for WasmResult<T>
|
||||||
|
where
|
||||||
|
T: Default,
|
||||||
|
{
|
||||||
|
fn from(value: PkmnResult<T>) -> Self {
|
||||||
|
match value {
|
||||||
|
Ok(value) => WasmResult { err_ptr: 0, value },
|
||||||
|
Err(e) => {
|
||||||
|
let s: CString = e.into();
|
||||||
|
let ptr = s.into_raw();
|
||||||
|
WasmResult {
|
||||||
|
err_ptr: ptr as u32,
|
||||||
|
value: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,11 +12,13 @@
|
||||||
#![feature(thread_local)]
|
#![feature(thread_local)]
|
||||||
#![feature(build_hasher_simple_hash_one)]
|
#![feature(build_hasher_simple_hash_one)]
|
||||||
#![feature(adt_const_params)]
|
#![feature(adt_const_params)]
|
||||||
|
#![feature(try_trait_v2)]
|
||||||
#![cfg_attr(not(feature = "mock_data"), no_std)]
|
#![cfg_attr(not(feature = "mock_data"), no_std)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
// These give false positives too often
|
// These give false positives too often
|
||||||
#![allow(clippy::borrowed_box)]
|
#![allow(clippy::borrowed_box)]
|
||||||
#![allow(clippy::needless_lifetimes)]
|
#![allow(clippy::needless_lifetimes)]
|
||||||
|
#![allow(stable_features)]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
@ -33,25 +35,28 @@ use alloc::boxed::Box;
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub mod app_interface;
|
pub mod app_interface;
|
||||||
pub mod handling;
|
pub mod handling;
|
||||||
|
mod result;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
|
pub use result::*;
|
||||||
|
|
||||||
pub type LoadScriptFnType = Box<dyn Fn(ScriptCategory, &StringKey) -> Option<Box<dyn Script>>>;
|
pub type LoadScriptFnType = Box<dyn Fn(ScriptCategory, &StringKey) -> Option<Box<dyn Script>>>;
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
mod implementation {
|
mod implementation {
|
||||||
use super::LoadScriptFnType;
|
use super::LoadScriptFnType;
|
||||||
|
|
||||||
use crate::app_interface::list::{EffectParameterImmutableList, ImmutableListWasm};
|
|
||||||
use crate::app_interface::{
|
use crate::app_interface::{
|
||||||
BattleImpl, DamageSource, DynamicLibraryImpl, EffectParameter, ExecutingMoveImpl, ItemImpl,
|
BattleImpl, DamageSource, DynamicLibraryImpl, EffectParameter, ExecutingMoveImpl, ItemImpl,
|
||||||
PokemonImpl, Statistic, StringKey, TurnChoice, TypeIdentifier,
|
PokemonImpl, Statistic, StringKey, TurnChoice, TypeIdentifier,
|
||||||
};
|
};
|
||||||
use crate::handling::extern_ref::ExternRef;
|
use crate::handling::extern_ref::ExternRef;
|
||||||
use crate::handling::extern_ref::VecExternRef;
|
|
||||||
use crate::handling::ffi_array::FFIArray;
|
use crate::handling::ffi_array::FFIArray;
|
||||||
|
use crate::handling::wasm_result::WasmVoidResult;
|
||||||
use crate::handling::{Script, ScriptCapabilities, ScriptCategory};
|
use crate::handling::{Script, ScriptCapabilities, ScriptCategory};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use core::sync::atomic::{AtomicU32, Ordering};
|
use core::sync::atomic::{AtomicU32, Ordering};
|
||||||
use cstr_core::{c_char, CString};
|
use cstr_core::{c_char, CString};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
@ -86,7 +91,7 @@ mod implementation {
|
||||||
static mut SCRIPT_INDEX_COUNTER: AtomicU32 = AtomicU32::new(1);
|
static mut SCRIPT_INDEX_COUNTER: AtomicU32 = AtomicU32::new(1);
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Default)]
|
||||||
pub struct ScriptPtr {
|
pub struct ScriptPtr {
|
||||||
index: u32,
|
index: u32,
|
||||||
}
|
}
|
||||||
|
@ -183,96 +188,104 @@ mod implementation {
|
||||||
FFIArray::new(c)
|
FFIArray::new(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_stack(script: ScriptPtr) {
|
fn script_stack(script: ScriptPtr) -> WasmVoidResult {
|
||||||
script.val().unwrap().stack();
|
WasmVoidResult::from_res(script.val().unwrap().stack())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_remove(script: ScriptPtr) {
|
fn script_on_remove(script: ScriptPtr) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_remove();
|
WasmVoidResult::from_res(script.val().unwrap().on_remove())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_initialize(
|
fn script_on_initialize(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
library: ExternRef<DynamicLibraryImpl>,
|
library: ExternRef<DynamicLibraryImpl>,
|
||||||
parameters: VecExternRef<EffectParameter>,
|
parameters: u64,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
let parameters = Rc::new(EffectParameterImmutableList::from_ref(parameters));
|
let parameters : FFIArray<ExternRef<EffectParameter>> = FFIArray::from_u64(parameters);
|
||||||
script.val().unwrap().on_initialize(library.not_null_rc(), Some(parameters));
|
let parameters = Vec::from_raw_parts(parameters.ptr(), parameters.len(), parameters.len());
|
||||||
|
let parameters = parameters.into_iter().map(|p| Rc::new(EffectParameter::new(p).unwrap())).collect::<Vec<_>>();
|
||||||
|
WasmVoidResult::from_res(script.val().unwrap().on_initialize(library.not_null_rc(), Some(parameters)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_before_turn(
|
fn script_on_before_turn(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
choice: ExternRef<TurnChoice>,
|
choice: ExternRef<TurnChoice>,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_before_turn(choice.not_null())
|
WasmVoidResult::from_res(script.val().unwrap().on_before_turn(choice.not_null()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_speed(
|
fn script_change_speed(
|
||||||
script:ScriptPtr,
|
script:ScriptPtr,
|
||||||
choice: ExternRef<TurnChoice>,
|
choice: ExternRef<TurnChoice>,
|
||||||
speed: *mut u32,
|
speed: *mut u32,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_speed(choice.not_null(), speed.as_mut().unwrap())
|
WasmVoidResult::from_res(script.val().unwrap().change_speed(choice.not_null(), speed.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_priority(
|
fn script_change_priority(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
choice: ExternRef<TurnChoice>,
|
choice: ExternRef<TurnChoice>,
|
||||||
priority: *mut i8,
|
priority: *mut i8,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_priority(choice.not_null(), priority.as_mut().unwrap())
|
WasmVoidResult::from_res(script.val().unwrap().change_priority(choice.not_null(), priority.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_move(
|
fn script_change_move(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
choice: ExternRef<TurnChoice>,
|
choice: ExternRef<TurnChoice>,
|
||||||
mv: *mut ExternRef<StringKey>,
|
mv: *mut ExternRef<StringKey>,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
let old = mv.as_ref().unwrap().not_null();
|
let old = mv.as_ref().unwrap().not_null();
|
||||||
let mut new = old.clone();
|
let mut new = old.clone();
|
||||||
script.val().unwrap().change_move(choice.not_null(), &mut new);
|
let res = script.val().unwrap().change_move(choice.not_null(), &mut new);
|
||||||
|
match res {
|
||||||
|
Ok(_) => {
|
||||||
if old != new {
|
if old != new {
|
||||||
*mv = new.ptr();
|
*mv = new.ptr();
|
||||||
}
|
}
|
||||||
|
WasmVoidResult::ok(())
|
||||||
|
}
|
||||||
|
Err(e) => WasmVoidResult::err(e),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_number_of_hits(
|
fn script_change_number_of_hits(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
choice: ExternRef<TurnChoice>,
|
choice: ExternRef<TurnChoice>,
|
||||||
out: *mut u8,
|
out: *mut u8,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_number_of_hits(choice.not_null(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_number_of_hits(choice.not_null(), out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_prevent_move(
|
fn script_prevent_move(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
mv: ExternRef<ExecutingMoveImpl>,
|
mv: ExternRef<ExecutingMoveImpl>,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().prevent_move(mv.not_null_rc(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().prevent_move(mv.not_null_rc(), out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_fail_move(
|
fn script_fail_move(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
mv: ExternRef<ExecutingMoveImpl>,
|
mv: ExternRef<ExecutingMoveImpl>,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().fail_move(mv.not_null_rc(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().fail_move(mv.not_null_rc(), out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_stop_before_move(
|
fn script_stop_before_move(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
mv: ExternRef<ExecutingMoveImpl>,
|
mv: ExternRef<ExecutingMoveImpl>,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().stop_before_move(mv.not_null_rc(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().stop_before_move(mv.not_null_rc(), out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_before_move(
|
fn script_on_before_move(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
mv: ExternRef<ExecutingMoveImpl>,
|
mv: ExternRef<ExecutingMoveImpl>,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_before_move(mv.not_null_rc());
|
WasmVoidResult::from_res(script.val().unwrap().on_before_move(mv.not_null_rc()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_fail_incoming_move(
|
fn script_fail_incoming_move(
|
||||||
|
@ -280,8 +293,8 @@ mod implementation {
|
||||||
mv: ExternRef<ExecutingMoveImpl>,
|
mv: ExternRef<ExecutingMoveImpl>,
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().fail_incoming_move(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().fail_incoming_move(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_is_invulnerable(
|
fn script_is_invulnerable(
|
||||||
|
@ -289,16 +302,16 @@ mod implementation {
|
||||||
mv: ExternRef<ExecutingMoveImpl>,
|
mv: ExternRef<ExecutingMoveImpl>,
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().is_invulnerable(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().is_invulnerable(mv.not_null_rc(), target.not_null_rc(), out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_move_miss(
|
fn script_on_move_miss(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
mv: ExternRef<ExecutingMoveImpl>,
|
mv: ExternRef<ExecutingMoveImpl>,
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_move_miss(mv.not_null_rc(), target.not_null_rc());
|
WasmVoidResult::from_res(script.val().unwrap().on_move_miss(mv.not_null_rc(), target.not_null_rc()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_move_type(
|
fn script_change_move_type(
|
||||||
|
@ -307,8 +320,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut TypeIdentifier,
|
out: *mut TypeIdentifier,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_move_type(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_move_type(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_effectiveness(
|
fn script_change_effectiveness(
|
||||||
|
@ -317,8 +330,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut f32,
|
out: *mut f32,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_effectiveness(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_effectiveness(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_block_critical(
|
fn script_block_critical(
|
||||||
|
@ -327,8 +340,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().block_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().block_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_block_incoming_critical(
|
fn script_block_incoming_critical(
|
||||||
|
@ -337,8 +350,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().block_incoming_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().block_incoming_critical(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_accuracy(
|
fn script_change_accuracy(
|
||||||
|
@ -347,8 +360,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut u8,
|
out: *mut u8,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_accuracy(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_accuracy(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_critical_stage(
|
fn script_change_critical_stage(
|
||||||
|
@ -357,8 +370,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut u8,
|
out: *mut u8,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_critical_stage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_critical_stage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_critical_modifier(
|
fn script_change_critical_modifier(
|
||||||
|
@ -367,8 +380,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut f32,
|
out: *mut f32,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_critical_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_critical_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_stab_modifier(
|
fn script_change_stab_modifier(
|
||||||
|
@ -377,8 +390,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut f32,
|
out: *mut f32,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_stab_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_stab_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_base_power(
|
fn script_change_base_power(
|
||||||
|
@ -387,8 +400,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut u8,
|
out: *mut u8,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_base_power(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_base_power(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_bypass_defensive_stat_boost(
|
fn script_bypass_defensive_stat_boost(
|
||||||
|
@ -397,8 +410,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().bypass_defensive_stat_boost(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().bypass_defensive_stat_boost(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_bypass_offensive_stat_boost(
|
fn script_bypass_offensive_stat_boost(
|
||||||
|
@ -407,8 +420,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().bypass_offensive_stat_boost(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().bypass_offensive_stat_boost(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_defensive_stat_value(
|
fn script_change_defensive_stat_value(
|
||||||
|
@ -417,8 +430,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut u32,
|
out: *mut u32,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_defensive_stat_value(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_defensive_stat_value(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_offensive_stat_value(
|
fn script_change_offensive_stat_value(
|
||||||
|
@ -427,8 +440,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut u32,
|
out: *mut u32,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_offensive_stat_value(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_offensive_stat_value(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_damage_stat_modifier(
|
fn script_change_damage_stat_modifier(
|
||||||
|
@ -437,8 +450,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut f32,
|
out: *mut f32,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_damage_stat_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_damage_stat_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_damage_modifier(
|
fn script_change_damage_modifier(
|
||||||
|
@ -447,8 +460,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut f32,
|
out: *mut f32,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_damage_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_damage_modifier(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_damage(
|
fn script_change_damage(
|
||||||
|
@ -457,8 +470,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut u32,
|
out: *mut u32,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_incoming_damage(
|
fn script_change_incoming_damage(
|
||||||
|
@ -467,8 +480,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut u32,
|
out: *mut u32,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_incoming_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_incoming_damage(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_incoming_hit(
|
fn script_on_incoming_hit(
|
||||||
|
@ -476,8 +489,8 @@ mod implementation {
|
||||||
mv: ExternRef<ExecutingMoveImpl>,
|
mv: ExternRef<ExecutingMoveImpl>,
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_incoming_hit(mv.not_null_rc(), target.not_null_rc(), hit);
|
WasmVoidResult::from_res(script.val().unwrap().on_incoming_hit(mv.not_null_rc(), target.not_null_rc(), hit))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_opponent_faints(
|
fn script_on_opponent_faints(
|
||||||
|
@ -485,8 +498,8 @@ mod implementation {
|
||||||
mv: ExternRef<ExecutingMoveImpl>,
|
mv: ExternRef<ExecutingMoveImpl>,
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_opponent_faints(mv.not_null_rc(), target.not_null_rc(), hit);
|
WasmVoidResult::from_res(script.val().unwrap().on_opponent_faints(mv.not_null_rc(), target.not_null_rc(), hit))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_prevent_stat_boost_change(
|
fn script_prevent_stat_boost_change(
|
||||||
|
@ -496,8 +509,8 @@ mod implementation {
|
||||||
amount: i8,
|
amount: i8,
|
||||||
self_inflicted: u8,
|
self_inflicted: u8,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().prevent_stat_boost_change(target.not_null_rc(), stat, amount, self_inflicted == 1, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().prevent_stat_boost_change(target.not_null_rc(), stat, amount, self_inflicted == 1, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_prevent_secondary_effect(
|
fn script_prevent_secondary_effect(
|
||||||
|
@ -506,8 +519,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().prevent_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().prevent_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_effect_chance(
|
fn script_change_effect_chance(
|
||||||
|
@ -516,8 +529,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut f32,
|
out: *mut f32,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_effect_chance(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_effect_chance(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_incoming_effect_chance(
|
fn script_change_incoming_effect_chance(
|
||||||
|
@ -526,8 +539,8 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
out: *mut f32,
|
out: *mut f32,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_incoming_effect_chance(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_incoming_effect_chance(mv.not_null_rc(), target.not_null_rc(), hit, out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_secondary_effect(
|
fn script_on_secondary_effect(
|
||||||
|
@ -535,68 +548,68 @@ mod implementation {
|
||||||
mv: ExternRef<ExecutingMoveImpl>,
|
mv: ExternRef<ExecutingMoveImpl>,
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
hit: u8,
|
hit: u8,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit);
|
WasmVoidResult::from_res(script.val().unwrap().on_secondary_effect(mv.not_null_rc(), target.not_null_rc(), hit))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_after_hits(
|
fn script_on_after_hits(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
mv: ExternRef<ExecutingMoveImpl>,
|
mv: ExternRef<ExecutingMoveImpl>,
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_after_hits(mv.not_null_rc(), target.not_null_rc());
|
WasmVoidResult::from_res(script.val().unwrap().on_after_hits(mv.not_null_rc(), target.not_null_rc()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_prevent_self_switch(
|
fn script_prevent_self_switch(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
choice: ExternRef<TurnChoice>,
|
choice: ExternRef<TurnChoice>,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().prevent_self_switch(choice.not_null(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().prevent_self_switch(choice.not_null(), out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_prevent_opponent_switch(
|
fn script_prevent_opponent_switch(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
choice: ExternRef<TurnChoice>,
|
choice: ExternRef<TurnChoice>,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().prevent_opponent_switch(choice.not_null(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().prevent_opponent_switch(choice.not_null(), out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_fail(
|
fn script_on_fail(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
pokemon: ExternRef<PokemonImpl>,
|
pokemon: ExternRef<PokemonImpl>,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_fail(pokemon.not_null_rc());
|
WasmVoidResult::from_res(script.val().unwrap().on_fail(pokemon.not_null_rc()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_opponent_fail(
|
fn script_on_opponent_fail(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
pokemon: ExternRef<PokemonImpl>,
|
pokemon: ExternRef<PokemonImpl>,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_opponent_fail(pokemon.not_null_rc());
|
WasmVoidResult::from_res(script.val().unwrap().on_opponent_fail(pokemon.not_null_rc()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_prevent_self_run_away(
|
fn script_prevent_self_run_away(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
choice: ExternRef<TurnChoice>,
|
choice: ExternRef<TurnChoice>,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().prevent_self_run_away(choice.not_null(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().prevent_self_run_away(choice.not_null(), out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_prevent_opponent_run_away(
|
fn script_prevent_opponent_run_away(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
choice: ExternRef<TurnChoice>,
|
choice: ExternRef<TurnChoice>,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().prevent_opponent_run_away(choice.not_null(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().prevent_opponent_run_away(choice.not_null(), out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_end_turn(
|
fn script_on_end_turn(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_end_turn();
|
WasmVoidResult::from_res(script.val().unwrap().on_end_turn())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_damage(
|
fn script_on_damage(
|
||||||
|
@ -605,31 +618,31 @@ mod implementation {
|
||||||
source: DamageSource,
|
source: DamageSource,
|
||||||
old_health: u32,
|
old_health: u32,
|
||||||
new_health: u32,
|
new_health: u32,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_damage(pokemon.not_null_rc(), source, old_health, new_health);
|
WasmVoidResult::from_res(script.val().unwrap().on_damage(pokemon.not_null_rc(), source, old_health, new_health))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_faint(
|
fn script_on_faint(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
pokemon: ExternRef<PokemonImpl>,
|
pokemon: ExternRef<PokemonImpl>,
|
||||||
source: DamageSource,
|
source: DamageSource,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_faint(pokemon.not_null_rc(), source);
|
WasmVoidResult::from_res(script.val().unwrap().on_faint(pokemon.not_null_rc(), source))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_switch_in(
|
fn script_on_switch_in(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
pokemon: ExternRef<PokemonImpl>,
|
pokemon: ExternRef<PokemonImpl>,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_switch_in(pokemon.not_null_rc());
|
WasmVoidResult::from_res(script.val().unwrap().on_switch_in(pokemon.not_null_rc()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_on_after_held_item_consume(
|
fn script_on_after_held_item_consume(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
pokemon: ExternRef<PokemonImpl>,
|
pokemon: ExternRef<PokemonImpl>,
|
||||||
item: ExternRef<ItemImpl>
|
item: ExternRef<ItemImpl>
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().on_after_held_item_consume(pokemon.not_null_rc(), item.not_null_rc());
|
WasmVoidResult::from_res(script.val().unwrap().on_after_held_item_consume(pokemon.not_null_rc(), item.not_null_rc()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_experience_gained(
|
fn script_change_experience_gained(
|
||||||
|
@ -637,8 +650,12 @@ mod implementation {
|
||||||
fainted_pokemon: ExternRef<PokemonImpl>,
|
fainted_pokemon: ExternRef<PokemonImpl>,
|
||||||
winning_pokemon: ExternRef<PokemonImpl>,
|
winning_pokemon: ExternRef<PokemonImpl>,
|
||||||
out: *mut u32
|
out: *mut u32
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_experience_gained(fainted_pokemon.not_null_rc(), winning_pokemon.not_null_rc(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_experience_gained(
|
||||||
|
fainted_pokemon.not_null_rc(),
|
||||||
|
winning_pokemon.not_null_rc(),
|
||||||
|
out.as_mut().unwrap()
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_share_experience(
|
fn script_share_experience(
|
||||||
|
@ -646,16 +663,20 @@ mod implementation {
|
||||||
fainted_pokemon: ExternRef<PokemonImpl>,
|
fainted_pokemon: ExternRef<PokemonImpl>,
|
||||||
winning_pokemon: ExternRef<PokemonImpl>,
|
winning_pokemon: ExternRef<PokemonImpl>,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().share_experience(fainted_pokemon.not_null_rc(), winning_pokemon.not_null_rc(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().share_experience(
|
||||||
|
fainted_pokemon.not_null_rc(),
|
||||||
|
winning_pokemon.not_null_rc(),
|
||||||
|
out.as_mut().unwrap()
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_block_weather(
|
fn script_block_weather(
|
||||||
script: ScriptPtr,
|
script: ScriptPtr,
|
||||||
battle: ExternRef<BattleImpl>,
|
battle: ExternRef<BattleImpl>,
|
||||||
out: *mut bool,
|
out: *mut bool,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().block_weather(battle.not_null_rc(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().block_weather(battle.not_null_rc(), out.as_mut().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_change_capture_rate_bonus(
|
fn script_change_capture_rate_bonus(
|
||||||
|
@ -663,8 +684,12 @@ mod implementation {
|
||||||
target: ExternRef<PokemonImpl>,
|
target: ExternRef<PokemonImpl>,
|
||||||
pokeball: ExternRef<ItemImpl>,
|
pokeball: ExternRef<ItemImpl>,
|
||||||
out: *mut u8,
|
out: *mut u8,
|
||||||
) {
|
) -> WasmVoidResult {
|
||||||
script.val().unwrap().change_capture_rate_bonus(target.not_null_rc(), pokeball.not_null_rc(), out.as_mut().unwrap());
|
WasmVoidResult::from_res(script.val().unwrap().change_capture_rate_bonus(
|
||||||
|
target.not_null_rc(),
|
||||||
|
pokeball.not_null_rc(),
|
||||||
|
out.as_mut().unwrap()
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
|
use core::fmt;
|
||||||
|
use core::fmt::{Debug, Display, Formatter};
|
||||||
|
use cstr_core::CString;
|
||||||
|
|
||||||
|
pub type PkmnResult<T> = Result<T, PkmnErr>;
|
||||||
|
|
||||||
|
pub struct PkmnErr {
|
||||||
|
pub file: &'static str,
|
||||||
|
pub line: u32,
|
||||||
|
pub message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PkmnErr {
|
||||||
|
pub fn new(file: &'static str, line: u32, message: String) -> Self {
|
||||||
|
Self {
|
||||||
|
file,
|
||||||
|
line,
|
||||||
|
message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for PkmnErr {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "PkmnErr: {}:{}: {}", self.file, self.line, self.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for PkmnErr {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "PkmnErr: {}:{}: {}", self.file, self.line, self.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PkmnErr> for CString {
|
||||||
|
fn from(val: PkmnErr) -> Self {
|
||||||
|
CString::new(val.to_string()).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! pkmn_err {
|
||||||
|
($message: expr) => {
|
||||||
|
PkmnErr::new(file!(), line!(), $message.to_string())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use pkmn_err;
|
|
@ -1,8 +1,23 @@
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
#[cfg(feature = "mock_data")]
|
||||||
|
macro_rules! println {
|
||||||
|
($($args:tt)*) => {};
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
macro_rules! println { ($($args:tt)*) => { crate::utils::print_raw(alloc::format!($($args)*).as_bytes()); } }
|
macro_rules! println { ($($args:tt)*) => { pkmn_lib_interface::utils::print_raw(alloc::format!($($args)*).as_bytes()); } }
|
||||||
|
|
||||||
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
#[allow(unused_macros)]
|
||||||
|
macro_rules! println_crate { ($($args:tt)*) => { crate::utils::print_raw(alloc::format!($($args)*).as_bytes()); } }
|
||||||
|
|
||||||
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
#[allow(unused_macros)]
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
pub(crate) use println_crate;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
@ -18,13 +33,14 @@ macro_rules! dbg {
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
mod implementation {
|
mod implementation {
|
||||||
use alloc::alloc::alloc;
|
use alloc::alloc::alloc;
|
||||||
|
use alloc::string::ToString;
|
||||||
use core::alloc::Layout;
|
use core::alloc::Layout;
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
use cstr_core::{c_char, CString};
|
use cstr_core::{c_char, CString};
|
||||||
|
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn _print(s: *const u8);
|
fn _print(s: *const u8);
|
||||||
fn _error(message: *const u8, file: *const u8, line: u32, position: u32);
|
fn _error(message: *const u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
@ -40,18 +56,11 @@ mod implementation {
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
pub fn begin_panic_handler(panic_info: &PanicInfo<'_>) -> ! {
|
pub fn begin_panic_handler(panic_info: &PanicInfo<'_>) -> ! {
|
||||||
let msg = CString::new(panic_info.message().unwrap().as_str().unwrap()).unwrap();
|
let payload = panic_info.to_string();
|
||||||
let mut line = 0;
|
let msg = CString::new(payload.as_bytes()).unwrap();
|
||||||
let mut position = 0;
|
|
||||||
let mut file = CString::default();
|
|
||||||
if let Some(s) = panic_info.location() {
|
|
||||||
line = s.line();
|
|
||||||
position = s.column();
|
|
||||||
file = CString::new(s.file()).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
_error(msg.as_ptr(), file.as_ptr(), line, position);
|
_error(msg.as_ptr());
|
||||||
}
|
}
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue