Implements first few actual move effects.
This commit is contained in:
parent
98130706fb
commit
05430c5e84
|
@ -1,5 +1,6 @@
|
|||
[workspace]
|
||||
edition = "2021"
|
||||
resolver = "2"
|
||||
|
||||
members = [
|
||||
"pkmn_lib_interface",
|
||||
|
|
|
@ -12,7 +12,8 @@ use pkmn_lib_interface::set_load_script_fn;
|
|||
#[macro_use]
|
||||
|
||||
pub mod registered_scripts;
|
||||
pub mod test_script;
|
||||
pub mod moves;
|
||||
pub mod util_scripts;
|
||||
|
||||
#[no_mangle]
|
||||
#[cfg(not(test))]
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
use pkmn_lib_interface::app_interface::{ExecutingMove, Pokemon};
|
||||
use pkmn_lib_interface::handling::{Script, ScriptCapabilities};
|
||||
|
||||
pub struct Acrobatics {}
|
||||
|
||||
impl Acrobatics {
|
||||
pub const fn get_const_name() -> &'static str {
|
||||
"acrobatics"
|
||||
}
|
||||
}
|
||||
|
||||
impl Script for Acrobatics {
|
||||
fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
fn get_name() -> &'static str {
|
||||
Self::get_const_name()
|
||||
}
|
||||
|
||||
fn get_capabilities(&self) -> &[ScriptCapabilities] {
|
||||
&[ScriptCapabilities::ChangeBasePower]
|
||||
}
|
||||
|
||||
fn change_base_power(
|
||||
&self,
|
||||
mv: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
base_power: &mut u8,
|
||||
) {
|
||||
if mv.user().held_item().is_none() {
|
||||
if *base_power >= 128_u8 {
|
||||
*base_power = 255
|
||||
} else {
|
||||
*base_power *= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
use core::mem::transmute;
|
||||
use pkmn_lib_interface::app_interface::{ExecutingMove, Pokemon, Statistic};
|
||||
use pkmn_lib_interface::handling::{Script, ScriptCapabilities};
|
||||
|
||||
pub struct Acupressure {}
|
||||
|
||||
impl Acupressure {
|
||||
pub const fn get_const_name() -> &'static str {
|
||||
"acupressure"
|
||||
}
|
||||
}
|
||||
|
||||
impl Script for Acupressure {
|
||||
fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
fn get_name() -> &'static str {
|
||||
Self::get_const_name()
|
||||
}
|
||||
|
||||
fn get_capabilities(&self) -> &[ScriptCapabilities] {
|
||||
&[ScriptCapabilities::OnSecondaryEffect]
|
||||
}
|
||||
|
||||
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) {
|
||||
if target == mv.user() {
|
||||
mv.get_hit_data(&target, hit).fail();
|
||||
return;
|
||||
}
|
||||
let rand_stat: Statistic =
|
||||
unsafe { transmute(target.battle().unwrap().random().get_between(1, 6) as u8) };
|
||||
target.change_stat_boost(rand_stat, 2, false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
use pkmn_lib_interface::app_interface::{ExecutingMove, Pokemon};
|
||||
use pkmn_lib_interface::handling::{Script, ScriptCapabilities};
|
||||
|
||||
pub struct AfterYou {}
|
||||
|
||||
impl AfterYou {
|
||||
pub const fn get_const_name() -> &'static str {
|
||||
"after_you"
|
||||
}
|
||||
}
|
||||
|
||||
impl Script for AfterYou {
|
||||
fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
fn get_name() -> &'static str {
|
||||
Self::get_const_name()
|
||||
}
|
||||
|
||||
fn get_capabilities(&self) -> &[ScriptCapabilities] {
|
||||
&[ScriptCapabilities::OnSecondaryEffect]
|
||||
}
|
||||
|
||||
fn on_secondary_effect(&self, mv: ExecutingMove, target: Pokemon, hit: u8) {
|
||||
if !target
|
||||
.battle()
|
||||
.unwrap()
|
||||
.choice_queue()
|
||||
.move_pokemon_choice_next(&target)
|
||||
{
|
||||
mv.get_hit_data(&target, hit).fail()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
pub mod acrobatics;
|
||||
pub mod acupressure;
|
||||
pub mod after_you;
|
||||
pub mod multi_hit_move;
|
|
@ -0,0 +1,37 @@
|
|||
use pkmn_lib_interface::app_interface::TurnChoice;
|
||||
use pkmn_lib_interface::handling::{Script, ScriptCapabilities};
|
||||
|
||||
pub struct MultiHitMove {}
|
||||
|
||||
impl MultiHitMove {
|
||||
pub const fn get_const_name() -> &'static str {
|
||||
"2_5_hit_move"
|
||||
}
|
||||
}
|
||||
|
||||
impl Script for MultiHitMove {
|
||||
fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
fn get_name() -> &'static str {
|
||||
Self::get_const_name()
|
||||
}
|
||||
|
||||
fn get_capabilities(&self) -> &[ScriptCapabilities] {
|
||||
&[ScriptCapabilities::ChangeNumberOfHits]
|
||||
}
|
||||
|
||||
fn change_number_of_hits(&self, choice: TurnChoice, number_of_hits: &mut u8) {
|
||||
// 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.
|
||||
let rand_value = choice.user().battle().unwrap().random().get_between(0, 100);
|
||||
*number_of_hits = match rand_value {
|
||||
0..=34 => 2,
|
||||
35..=69 => 3,
|
||||
70..=84 => 4,
|
||||
85..=100 => 5,
|
||||
_ => *number_of_hits,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +1,19 @@
|
|||
use crate::test_script::TestScript;
|
||||
use crate::moves::*;
|
||||
use alloc::boxed::Box;
|
||||
use pkmn_lib_interface::app_interface::{get_hash_const, StringKey};
|
||||
use pkmn_lib_interface::app_interface::{get_hash, StringKey};
|
||||
use pkmn_lib_interface::handling::{Script, ScriptCategory};
|
||||
|
||||
macro_rules! resolve_match {
|
||||
(
|
||||
$mid:expr,
|
||||
$(
|
||||
$key:expr => $script:ident,
|
||||
$script:ty,
|
||||
)*
|
||||
) => (
|
||||
match $mid {
|
||||
$(
|
||||
const { get_hash_const($key) } => {
|
||||
return Some(Box::new($script {}))
|
||||
const { get_hash(<$script>::get_const_name()) } => {
|
||||
return Some(Box::new(<$script>::new()))
|
||||
}
|
||||
)*
|
||||
_ => {}
|
||||
|
@ -26,13 +26,18 @@ pub fn get_script(category: ScriptCategory, name: &StringKey) -> Option<Box<dyn
|
|||
ScriptCategory::Move => {
|
||||
resolve_match!(
|
||||
name.hash(),
|
||||
b"test" => TestScript,
|
||||
acrobatics::Acrobatics,
|
||||
acupressure::Acupressure,
|
||||
after_you::AfterYou,
|
||||
multi_hit_move::MultiHitMove,
|
||||
);
|
||||
}
|
||||
ScriptCategory::Ability => {}
|
||||
ScriptCategory::Status => {}
|
||||
ScriptCategory::Pokemon => {}
|
||||
ScriptCategory::Battle => {}
|
||||
ScriptCategory::Battle => {
|
||||
resolve_match!(name.hash(), crate::util_scripts::ForceEffectTriggerScript,)
|
||||
}
|
||||
ScriptCategory::Side => {}
|
||||
ScriptCategory::ItemBattleTrigger => {}
|
||||
}
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
use pkmn_lib_interface::app_interface::list::ImmutableList;
|
||||
use pkmn_lib_interface::app_interface::{
|
||||
get_hash_const, DamageSource, DataLibrary, DynamicLibrary, EffectParameter, TurnChoice,
|
||||
};
|
||||
use pkmn_lib_interface::dbg;
|
||||
use pkmn_lib_interface::handling::{Script, ScriptCapabilities};
|
||||
|
||||
pub struct TestScript {}
|
||||
|
||||
impl Script for TestScript {
|
||||
fn new() -> Self {
|
||||
TestScript {}
|
||||
}
|
||||
fn destroy(&self) {}
|
||||
|
||||
fn get_name(&self) -> &str {
|
||||
"TestScript"
|
||||
}
|
||||
|
||||
fn get_capabilities(&self) -> &[ScriptCapabilities] {
|
||||
&[
|
||||
ScriptCapabilities::Initialize,
|
||||
ScriptCapabilities::OnBeforeTurn,
|
||||
]
|
||||
}
|
||||
|
||||
fn on_initialize(
|
||||
&self,
|
||||
library: &DynamicLibrary,
|
||||
parameters: Option<ImmutableList<EffectParameter>>,
|
||||
) {
|
||||
let l = library.data_library();
|
||||
let ml = l.move_library();
|
||||
let m = ml.get_by_hash(const { get_hash_const(b"tackle") }).unwrap();
|
||||
dbg!("found move!");
|
||||
dbg!("{:?} has {} base power", m.name().str(), m.base_power());
|
||||
dbg!(
|
||||
"Found a parameter with value: {}",
|
||||
parameters.unwrap().get(0).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
fn on_before_turn(&self, choice: TurnChoice) {
|
||||
dbg!(
|
||||
"On before turn for user: {}",
|
||||
choice.user().species().name()
|
||||
);
|
||||
// choice.user().damage(50, DamageSource::Misc);
|
||||
if let TurnChoice::Move(d) = choice {
|
||||
dbg!(
|
||||
"On before turn for move choice: {}",
|
||||
d.used_move().move_data().name()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use pkmn_lib_interface::app_interface::move_library::MoveLibrary;
|
||||
use pkmn_lib_interface::app_interface::species_library::SpeciesLibrary;
|
||||
use pkmn_lib_interface::app_interface::type_library::TypeLibrary;
|
||||
use pkmn_lib_interface::app_interface::{
|
||||
Item, ItemLibrary, LibrarySettings, MoveCategory, MoveData, MoveTarget, StaticData,
|
||||
};
|
||||
use pkmn_lib_interface::handling::Script;
|
||||
|
||||
#[test]
|
||||
fn test_foo() {
|
||||
let item = Item::mock();
|
||||
assert_eq!(item.name().str().to_str().unwrap(), "test");
|
||||
|
||||
let script = TestScript::new();
|
||||
assert_eq!(script.get_name(), "TestScript");
|
||||
|
||||
let lib = DynamicLibrary::new(StaticData::mock(
|
||||
MoveLibrary::mock(),
|
||||
ItemLibrary::mock(),
|
||||
SpeciesLibrary::mock(),
|
||||
TypeLibrary::mock(),
|
||||
LibrarySettings::mock(100),
|
||||
));
|
||||
lib.data_library().move_library().insert(
|
||||
const { get_hash_const(b"tackle") },
|
||||
MoveData::mock(
|
||||
"tackle",
|
||||
0,
|
||||
MoveCategory::Physical,
|
||||
60,
|
||||
100,
|
||||
10,
|
||||
MoveTarget::Adjacent,
|
||||
0,
|
||||
),
|
||||
);
|
||||
script.on_initialize(
|
||||
&lib,
|
||||
Some(ImmutableList::mock((&[EffectParameter::Int(100)]).to_vec())),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
use pkmn_lib_interface::app_interface::{ExecutingMove, Pokemon};
|
||||
use pkmn_lib_interface::handling::{Script, ScriptCapabilities};
|
||||
|
||||
pub struct ForceEffectTriggerScript {}
|
||||
|
||||
impl ForceEffectTriggerScript {
|
||||
pub const fn get_const_name() -> &'static str {
|
||||
"force_effect_trigger"
|
||||
}
|
||||
}
|
||||
|
||||
impl Script for ForceEffectTriggerScript {
|
||||
fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
fn get_name() -> &'static str {
|
||||
Self::get_const_name()
|
||||
}
|
||||
|
||||
fn get_capabilities(&self) -> &[ScriptCapabilities] {
|
||||
&[ScriptCapabilities::ChangeEffectChance]
|
||||
}
|
||||
|
||||
fn change_effect_chance(
|
||||
&self,
|
||||
_mv: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
chance: &mut f32,
|
||||
) {
|
||||
// Set to 50_000% chance.
|
||||
*chance = 50_000.0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
mod force_effect_trigger;
|
||||
|
||||
pub use force_effect_trigger::*;
|
|
@ -10,10 +10,10 @@ mock_data = []
|
|||
[dependencies]
|
||||
wee_alloc = "0.4.5"
|
||||
cstr_core = { version = "0.2.6", features = ["nightly"]}
|
||||
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
|
||||
enumflags2 = { version = "0.7.5", default-features = false }
|
||||
spin = { version = "0.9.4", default-features = false, features = ["rwlock"] }
|
||||
paste = { version = "1.0.7" }
|
||||
hashbrown = { version = "0.12.3" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::app_interface::{BattleParty, BattleRandom, BattleSide, Pokemon};
|
||||
use crate::app_interface::{BattleParty, BattleRandom, BattleSide, ChoiceQueue, Pokemon};
|
||||
use crate::handling::cached_value::CachedValue;
|
||||
use crate::handling::Cacheable;
|
||||
use crate::{
|
||||
|
@ -13,6 +13,7 @@ struct BattleInner {
|
|||
parties: CachedValue<ImmutableList<BattleParty>>,
|
||||
sides: CachedValue<ImmutableList<BattleSide>>,
|
||||
random: CachedValue<BattleRandom>,
|
||||
choice_queue: CachedValue<ChoiceQueue>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -30,6 +31,9 @@ impl Battle {
|
|||
parties: cached_value!({ battle_get_parties(reference).get_immutable_list() }),
|
||||
sides: cached_value!({ battle_get_sides(reference).get_immutable_list() }),
|
||||
random: cached_value!({ battle_get_random(reference).get_value().unwrap() }),
|
||||
choice_queue: cached_value!({
|
||||
battle_get_choice_queue(reference).get_value().unwrap()
|
||||
}),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
@ -38,6 +42,8 @@ impl Battle {
|
|||
pub fn library(&self) -> DynamicLibrary;
|
||||
pub fn parties(&self) -> ImmutableList<BattleParty>;
|
||||
pub fn sides(&self) -> ImmutableList<BattleSide>;
|
||||
pub fn random(&self) -> BattleRandom;
|
||||
pub fn choice_queue(&self) -> ChoiceQueue;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
|
@ -72,5 +78,6 @@ extern "wasm" {
|
|||
fn battle_get_parties(r: ExternRef<Battle>) -> VecExternRef<BattleParty>;
|
||||
fn battle_get_sides(r: ExternRef<Battle>) -> VecExternRef<BattleSide>;
|
||||
fn battle_get_random(r: ExternRef<Battle>) -> ExternRef<BattleRandom>;
|
||||
fn battle_get_choice_queue(r: ExternRef<Battle>) -> ExternRef<ChoiceQueue>;
|
||||
fn battle_get_pokemon(r: ExternRef<Battle>, side: u8, index: u8) -> ExternRef<Pokemon>;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@ impl ExternalReferenceType for BattleParty {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
extern "wasm" {
|
||||
fn battle_party_get_party(r: ExternRef<BattleParty>) -> ExternRef<Party>;
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
use crate::{ExternRef, ExternalReferenceType, Pokemon};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ChoiceQueue {
|
||||
reference: ExternRef<ChoiceQueue>,
|
||||
}
|
||||
|
||||
impl ChoiceQueue {
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub fn new(reference: ExternRef<ChoiceQueue>) -> Self {
|
||||
Self { reference }
|
||||
}
|
||||
|
||||
pub fn move_pokemon_choice_next(&self, pokemon: &Pokemon) -> bool {
|
||||
unsafe { choice_queue_move_pokemon_choice_next(self.reference, pokemon.reference()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl ExternalReferenceType for ChoiceQueue {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
Self::new(reference)
|
||||
}
|
||||
}
|
||||
|
||||
extern "wasm" {
|
||||
fn choice_queue_move_pokemon_choice_next(
|
||||
r: ExternRef<ChoiceQueue>,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
) -> bool;
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
use crate::app_interface::{LearnedMove, MoveData, Pokemon};
|
||||
use crate::handling::cached_value::CachedValue;
|
||||
use crate::handling::temporary::Temporary;
|
||||
use crate::{cached_value, ExternRef, ExternalReferenceType, Script};
|
||||
|
||||
struct ExecutingMoveInner {
|
||||
reference: ExternRef<ExecutingMove>,
|
||||
number_of_hits: CachedValue<u8>,
|
||||
user: CachedValue<Pokemon>,
|
||||
chosen_move: CachedValue<LearnedMove>,
|
||||
use_move: CachedValue<MoveData>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ExecutingMove {
|
||||
inner: Temporary<ExecutingMoveInner>,
|
||||
}
|
||||
|
||||
impl ExecutingMove {
|
||||
pub(crate) fn new(reference: ExternRef<ExecutingMove>) -> Self {
|
||||
Self {
|
||||
inner: Temporary::new(
|
||||
reference.get_internal_index(),
|
||||
ExecutingMoveInner {
|
||||
reference,
|
||||
number_of_hits: cached_value!({ executing_move_get_number_of_hits(reference) }),
|
||||
user: cached_value!({
|
||||
executing_move_get_user(reference).get_value().unwrap()
|
||||
}),
|
||||
chosen_move: cached_value!({
|
||||
executing_move_get_chosen_move(reference)
|
||||
.get_value()
|
||||
.unwrap()
|
||||
}),
|
||||
use_move: cached_value!({
|
||||
executing_move_get_use_move(reference).get_value().unwrap()
|
||||
}),
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn number_of_hits(&self) -> u8 {
|
||||
self.inner.value().number_of_hits.value()
|
||||
}
|
||||
pub fn user(&self) -> Pokemon {
|
||||
self.inner.value().user.value()
|
||||
}
|
||||
pub fn chosen_move(&self) -> LearnedMove {
|
||||
self.inner.value().chosen_move.value()
|
||||
}
|
||||
pub fn use_move(&self) -> MoveData {
|
||||
self.inner.value().use_move.value()
|
||||
}
|
||||
pub fn move_script(&self) -> Option<&dyn Script> {
|
||||
unsafe { executing_move_get_script(self.inner.value().reference).as_ref() }
|
||||
}
|
||||
pub fn number_of_targets(&self) -> usize {
|
||||
unsafe { executing_move_get_number_of_targets(self.inner.value().reference) }
|
||||
}
|
||||
pub fn is_pokemon_target(&self, pokemon: &Pokemon) -> bool {
|
||||
unsafe {
|
||||
executing_move_is_pokemon_target(self.inner.value().reference, pokemon.reference())
|
||||
}
|
||||
}
|
||||
pub fn get_hit_data(&self, pokemon: &Pokemon, hit: u8) -> HitData {
|
||||
unsafe {
|
||||
executing_move_get_hit_data(self.inner.value().reference, pokemon.reference(), hit)
|
||||
.get_value()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct HitData {
|
||||
reference: ExternRef<HitData>,
|
||||
}
|
||||
|
||||
impl HitData {
|
||||
pub fn is_critical(&self) -> bool {
|
||||
unsafe { hit_data_is_critical(self.reference) }
|
||||
}
|
||||
pub fn base_power(&self) -> u8 {
|
||||
unsafe { hit_data_get_base_power(self.reference) }
|
||||
}
|
||||
pub fn effectiveness(&self) -> f32 {
|
||||
unsafe { hit_data_get_effectiveness(self.reference) }
|
||||
}
|
||||
pub fn damage(&self) -> u32 {
|
||||
unsafe { hit_data_get_damage(self.reference) }
|
||||
}
|
||||
pub fn move_type(&self) -> u8 {
|
||||
unsafe { hit_data_get_move_type(self.reference) }
|
||||
}
|
||||
pub fn has_failed(&self) -> bool {
|
||||
unsafe { hit_data_is_critical(self.reference) }
|
||||
}
|
||||
|
||||
pub fn set_critical(&self, critical: bool) {
|
||||
unsafe { hit_data_set_critical(self.reference, critical) }
|
||||
}
|
||||
pub fn set_effectiveness(&self, effectiveness: f32) {
|
||||
unsafe { hit_data_set_effectiveness(self.reference, effectiveness) }
|
||||
}
|
||||
pub fn set_damage(&self, damage: u32) {
|
||||
unsafe { hit_data_set_damage(self.reference, damage) }
|
||||
}
|
||||
pub fn set_move_type(&self, move_type: u8) {
|
||||
unsafe { hit_data_set_move_type(self.reference, move_type) }
|
||||
}
|
||||
pub fn fail(&self) {
|
||||
unsafe { hit_data_fail(self.reference) }
|
||||
}
|
||||
}
|
||||
|
||||
impl ExternalReferenceType for ExecutingMove {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
Self::new(reference)
|
||||
}
|
||||
}
|
||||
|
||||
impl ExternalReferenceType for HitData {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
Self { reference }
|
||||
}
|
||||
}
|
||||
|
||||
extern "wasm" {
|
||||
fn executing_move_get_number_of_targets(r: ExternRef<ExecutingMove>) -> usize;
|
||||
fn executing_move_get_number_of_hits(r: ExternRef<ExecutingMove>) -> u8;
|
||||
fn executing_move_get_user(r: ExternRef<ExecutingMove>) -> ExternRef<Pokemon>;
|
||||
fn executing_move_get_chosen_move(r: ExternRef<ExecutingMove>) -> ExternRef<LearnedMove>;
|
||||
fn executing_move_get_use_move(r: ExternRef<ExecutingMove>) -> ExternRef<MoveData>;
|
||||
#[allow(improper_ctypes)]
|
||||
fn executing_move_get_script(r: ExternRef<ExecutingMove>) -> *const dyn Script;
|
||||
|
||||
fn executing_move_is_pokemon_target(
|
||||
r: ExternRef<ExecutingMove>,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
) -> bool;
|
||||
fn executing_move_get_hit_data(
|
||||
r: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
) -> ExternRef<HitData>;
|
||||
|
||||
fn hit_data_is_critical(r: ExternRef<HitData>) -> bool;
|
||||
fn hit_data_get_base_power(r: ExternRef<HitData>) -> u8;
|
||||
fn hit_data_get_effectiveness(r: ExternRef<HitData>) -> f32;
|
||||
fn hit_data_get_damage(r: ExternRef<HitData>) -> u32;
|
||||
fn hit_data_get_move_type(r: ExternRef<HitData>) -> u8;
|
||||
fn hit_data_has_failed(r: ExternRef<HitData>) -> bool;
|
||||
|
||||
fn hit_data_set_critical(r: ExternRef<HitData>, critical: bool);
|
||||
fn hit_data_set_base_power(r: ExternRef<HitData>, power: u8);
|
||||
fn hit_data_set_effectiveness(r: ExternRef<HitData>, effectiveness: f32);
|
||||
fn hit_data_set_damage(r: ExternRef<HitData>, damage: u32);
|
||||
fn hit_data_set_move_type(r: ExternRef<HitData>, move_type: u8);
|
||||
fn hit_data_fail(r: ExternRef<HitData>);
|
||||
}
|
|
@ -2,7 +2,9 @@ mod battle;
|
|||
mod battle_party;
|
||||
mod battle_random;
|
||||
mod battle_side;
|
||||
mod choice_queue;
|
||||
mod dynamic_library;
|
||||
mod executing_move;
|
||||
mod learned_move;
|
||||
mod party;
|
||||
mod pokemon;
|
||||
|
@ -13,7 +15,9 @@ pub use battle::*;
|
|||
pub use battle_party::*;
|
||||
pub use battle_random::*;
|
||||
pub use battle_side::*;
|
||||
pub use choice_queue::*;
|
||||
pub use dynamic_library::DynamicLibrary;
|
||||
pub use executing_move::*;
|
||||
pub use learned_move::*;
|
||||
pub use party::*;
|
||||
pub use pokemon::*;
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::handling::cached_value::CachedValue;
|
|||
use crate::handling::Cacheable;
|
||||
use crate::{
|
||||
cached_value, cached_value_getters, wasm_optional_reference_getters, wasm_reference_getters,
|
||||
wasm_value_getters, DynamicLibrary, ExternRef, ExternalReferenceType, Script,
|
||||
wasm_value_getters, DynamicLibrary, ExternRef, ExternalReferenceType, Script, TypeIdentifier,
|
||||
};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::rc::Rc;
|
||||
|
@ -61,6 +61,10 @@ impl Pokemon {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn reference(&self) -> ExternRef<Self> {
|
||||
self.inner.reference
|
||||
}
|
||||
|
||||
cached_value_getters! {
|
||||
pub fn library(&self) -> DynamicLibrary;
|
||||
pub fn flat_stats(&self) -> StatisticSet<u32>;
|
||||
|
@ -101,8 +105,8 @@ impl Pokemon {
|
|||
unsafe { pokemon_get_type(self.inner.reference, index) }
|
||||
}
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub fn has_type(&self, type_identifier: u8) -> bool {
|
||||
unsafe { pokemon_has_type(self.inner.reference, type_identifier) }
|
||||
pub fn has_type(&self, type_identifier: TypeIdentifier) -> bool {
|
||||
unsafe { pokemon_has_type(self.inner.reference, type_identifier.into()) }
|
||||
}
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub fn has_type_by_name(&self, type_name: &str) -> bool {
|
||||
|
@ -206,6 +210,12 @@ wasm_value_getters! {
|
|||
pub fn is_usable(&self) -> bool;
|
||||
}
|
||||
|
||||
impl PartialEq for Pokemon {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner.reference == other.inner.reference
|
||||
}
|
||||
}
|
||||
|
||||
/// A source of damage. This should be as unique as possible.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(u8)]
|
||||
|
@ -246,6 +256,7 @@ extern "wasm" {
|
|||
diff_amount: i8,
|
||||
self_inflicted: bool,
|
||||
) -> bool;
|
||||
#[allow(improper_ctypes)]
|
||||
fn pokemon_get_ability_script(r: ExternRef<Pokemon>) -> *const Box<dyn Script>;
|
||||
fn pokemon_change_species(
|
||||
r: ExternRef<Pokemon>,
|
||||
|
|
|
@ -3,10 +3,9 @@ use crate::handling::cached_value::CachedValue;
|
|||
use crate::handling::temporary::Temporary;
|
||||
use crate::ExternRef;
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
use crate::{cached_value, wasm_value_getters, ExternalReferenceType, Script};
|
||||
use crate::{cached_value, ExternalReferenceType, Script};
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
use alloc::boxed::Box;
|
||||
use alloc::rc::Rc;
|
||||
|
||||
struct BaseTurnChoiceData {
|
||||
reference: ExternRef<TurnChoice>,
|
||||
|
@ -19,12 +18,10 @@ struct MoveTurnChoiceDataInner {
|
|||
target_side: CachedValue<u8>,
|
||||
target_index: CachedValue<u8>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct MoveTurnChoiceDataTemporary {
|
||||
inner: Rc<MoveTurnChoiceDataInner>,
|
||||
}
|
||||
pub struct MoveTurnChoiceData {
|
||||
temp: Temporary<MoveTurnChoiceDataTemporary>,
|
||||
inner: Temporary<MoveTurnChoiceDataInner>,
|
||||
}
|
||||
|
||||
pub enum TurnChoice {
|
||||
|
@ -38,7 +35,7 @@ pub enum TurnChoice {
|
|||
impl TurnChoice {
|
||||
fn base(&self) -> &BaseTurnChoiceData {
|
||||
match self {
|
||||
TurnChoice::Move(d) => &d.temp.value_ref().inner.base,
|
||||
TurnChoice::Move(d) => &d.inner.value_ref().base,
|
||||
TurnChoice::Item() => unimplemented!(),
|
||||
TurnChoice::Switch() => unimplemented!(),
|
||||
TurnChoice::Flee => unimplemented!(),
|
||||
|
@ -68,22 +65,22 @@ impl TurnChoice {
|
|||
|
||||
impl MoveTurnChoiceData {
|
||||
pub fn used_move(&self) -> LearnedMove {
|
||||
self.temp.value().inner.used_move.value()
|
||||
self.inner.value().used_move.value()
|
||||
}
|
||||
pub fn target_side(&self) -> u8 {
|
||||
self.temp.value().inner.target_side.value()
|
||||
self.inner.value().target_side.value()
|
||||
}
|
||||
pub fn target_index(&self) -> u8 {
|
||||
self.temp.value().inner.target_index.value()
|
||||
self.inner.value().target_index.value()
|
||||
}
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub fn priority(&self) -> i8 {
|
||||
unsafe { turn_choice_move_priority(self.temp.value().inner.base.reference.cast()) }
|
||||
unsafe { turn_choice_move_priority(self.inner.value().base.reference.cast()) }
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub fn move_script(&self) -> Option<&Box<dyn Script>> {
|
||||
unsafe { turn_choice_move_script(self.temp.value().inner.base.reference.cast()).as_ref() }
|
||||
unsafe { turn_choice_move_script(self.inner.value().base.reference.cast()).as_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,7 +90,10 @@ impl ExternalReferenceType for TurnChoice {
|
|||
let kind = unsafe { turn_choice_get_kind(reference) };
|
||||
match kind {
|
||||
0 => TurnChoice::Move(MoveTurnChoiceData {
|
||||
temp: Temporary::from_reference(reference.cast()),
|
||||
inner: Temporary::new(
|
||||
reference.get_internal_index(),
|
||||
MoveTurnChoiceDataInner::from_reference(reference.cast()),
|
||||
),
|
||||
}),
|
||||
_ => panic!("Unknown turn choice type"),
|
||||
}
|
||||
|
@ -101,24 +101,22 @@ impl ExternalReferenceType for TurnChoice {
|
|||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl ExternalReferenceType for MoveTurnChoiceDataTemporary {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
impl MoveTurnChoiceDataInner {
|
||||
fn from_reference(reference: ExternRef<MoveTurnChoiceData>) -> Self {
|
||||
Self {
|
||||
inner: Rc::new(MoveTurnChoiceDataInner {
|
||||
base: BaseTurnChoiceData {
|
||||
reference: reference.cast(),
|
||||
user: cached_value!({
|
||||
turn_choice_get_user(reference.cast()).get_value().unwrap()
|
||||
}),
|
||||
},
|
||||
used_move: cached_value!({
|
||||
turn_choice_move_used_move(reference.cast())
|
||||
.get_value()
|
||||
.unwrap()
|
||||
base: BaseTurnChoiceData {
|
||||
reference: reference.cast(),
|
||||
user: cached_value!({
|
||||
turn_choice_get_user(reference.cast()).get_value().unwrap()
|
||||
}),
|
||||
target_side: cached_value!({ turn_choice_move_target_side(reference.cast()) }),
|
||||
target_index: cached_value!({ turn_choice_move_target_index(reference.cast()) }),
|
||||
},
|
||||
used_move: cached_value!({
|
||||
turn_choice_move_used_move(reference.cast())
|
||||
.get_value()
|
||||
.unwrap()
|
||||
}),
|
||||
target_side: cached_value!({ turn_choice_move_target_side(reference.cast()) }),
|
||||
target_index: cached_value!({ turn_choice_move_target_index(reference.cast()) }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,14 +133,6 @@ extern "wasm" {
|
|||
fn turn_choice_move_target_side(r: ExternRef<MoveTurnChoiceData>) -> u8;
|
||||
fn turn_choice_move_target_index(r: ExternRef<MoveTurnChoiceData>) -> u8;
|
||||
fn turn_choice_move_priority(r: ExternRef<MoveTurnChoiceData>) -> i8;
|
||||
#[allow(improper_ctypes)]
|
||||
fn turn_choice_move_script(r: ExternRef<MoveTurnChoiceData>) -> *const Box<dyn Script>;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
unsafe extern "wasm" fn turn_choice_mark_deleted(r: ExternRef<TurnChoice>, kind: u8) {
|
||||
match kind {
|
||||
0 => Temporary::<MoveTurnChoiceDataTemporary>::mark_as_deleted(r.cast()),
|
||||
_ => panic!("Unknown turn choice type"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{ExternalReferenceType, VecExternRef};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::collections::BTreeMap;
|
||||
#[cfg(feature = "mock_data")]
|
||||
use alloc::rc::Rc;
|
||||
use alloc::vec::Vec;
|
||||
use core::marker::PhantomData;
|
||||
|
@ -44,13 +44,22 @@ where
|
|||
|
||||
pub(crate) fn from_ref(extern_ref: VecExternRef<T>) -> Self {
|
||||
unsafe {
|
||||
let existing = CACHE.get(&extern_ref.get_internal_index());
|
||||
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>;
|
||||
ImmutableList { inner }
|
||||
} else {
|
||||
let v = Self::new(extern_ref);
|
||||
CACHE.insert(extern_ref.get_internal_index(), v.inner as *const u8);
|
||||
CACHE
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.insert(extern_ref.get_internal_index(), v.inner as *const u8);
|
||||
v
|
||||
}
|
||||
}
|
||||
|
@ -102,4 +111,4 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
static mut CACHE: BTreeMap<u32, *const u8> = BTreeMap::new();
|
||||
static mut CACHE: Option<hashbrown::HashMap<u32, *const u8>> = None;
|
||||
|
|
|
@ -5,5 +5,4 @@ pub mod string_key;
|
|||
|
||||
pub use dynamic_data::*;
|
||||
pub use static_data::*;
|
||||
pub use string_key::get_hash_const;
|
||||
pub use string_key::StringKey;
|
||||
pub use string_key::*;
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use crate::app_interface::{DataLibrary, Item};
|
||||
use crate::{ExternRef, ExternalReferenceType, StringKey};
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::rc::Rc;
|
||||
use spin::rwlock::RwLock;
|
||||
|
||||
struct ItemLibraryInner {
|
||||
ptr: ExternRef<ItemLibrary>,
|
||||
cache: RwLock<BTreeMap<u32, Item>>,
|
||||
cache: RwLock<hashbrown::HashMap<u32, Item>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -27,7 +26,7 @@ impl ItemLibrary {
|
|||
}
|
||||
|
||||
impl DataLibrary<Item> for ItemLibrary {
|
||||
fn get_cache(&self) -> &spin::rwlock::RwLock<BTreeMap<u32, Item>> {
|
||||
fn get_cache(&self) -> &spin::rwlock::RwLock<hashbrown::HashMap<u32, Item>> {
|
||||
&self.inner.cache
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use crate::{cached_value, cached_value_getters, ExternRef, ExternalReferenceType, StringKey};
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::rc::Rc;
|
||||
use move_library::MoveLibrary;
|
||||
use spin::rwlock::RwLock;
|
||||
|
@ -51,6 +50,11 @@ impl StaticData {
|
|||
type_library: cached_value!({
|
||||
static_data_get_type_library(reference).get_value().unwrap()
|
||||
}),
|
||||
settings: cached_value!({
|
||||
static_data_get_library_settings(reference)
|
||||
.get_value()
|
||||
.unwrap()
|
||||
}),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
@ -88,7 +92,7 @@ crate::handling::cacheable::cacheable!(StaticData);
|
|||
#[cfg(not(feature = "mock_data"))]
|
||||
impl ExternalReferenceType for StaticData {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
StaticData::mock(reference)
|
||||
StaticData::new(reference)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,12 +129,20 @@ impl LibrarySettings {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl ExternalReferenceType for LibrarySettings {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
LibrarySettings::new(reference)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
extern "wasm" {
|
||||
fn static_data_get_move_library(ptr: ExternRef<StaticData>) -> ExternRef<MoveLibrary>;
|
||||
fn static_data_get_item_library(ptr: ExternRef<StaticData>) -> ExternRef<ItemLibrary>;
|
||||
fn static_data_get_species_library(ptr: ExternRef<StaticData>) -> ExternRef<SpeciesLibrary>;
|
||||
fn static_data_get_type_library(ptr: ExternRef<StaticData>) -> ExternRef<TypeLibrary>;
|
||||
fn static_data_get_library_settings(ptr: ExternRef<StaticData>) -> ExternRef<LibrarySettings>;
|
||||
|
||||
fn library_settings_get_maximum_level(ptr: ExternRef<LibrarySettings>) -> LevelInt;
|
||||
}
|
||||
|
@ -141,7 +153,7 @@ where
|
|||
T: ExternalReferenceType,
|
||||
T: Clone,
|
||||
{
|
||||
fn get_cache(&self) -> &RwLock<BTreeMap<u32, T>>;
|
||||
fn get_cache(&self) -> &RwLock<hashbrown::HashMap<u32, T>>;
|
||||
fn get_self_ref(&self) -> ExternRef<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
|
@ -188,7 +200,7 @@ pub trait DataLibrary<T>: Cacheable
|
|||
where
|
||||
T: Clone,
|
||||
{
|
||||
fn get_cache(&self) -> &RwLock<BTreeMap<u32, T>>;
|
||||
fn get_cache(&self) -> &RwLock<hashbrown::HashMap<u32, T>>;
|
||||
fn get_self_ref(&self) -> ExternRef<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
use crate::app_interface::data_libraries::DataLibrary;
|
||||
use crate::app_interface::{MoveData, StringKey};
|
||||
use crate::{ExternRef, ExternalReferenceType};
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::rc::Rc;
|
||||
use spin::RwLock;
|
||||
|
||||
struct MoveLibraryInner {
|
||||
ptr: ExternRef<MoveLibrary>,
|
||||
cache: RwLock<BTreeMap<u32, MoveData>>,
|
||||
cache: RwLock<hashbrown::HashMap<u32, MoveData>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -38,7 +37,7 @@ impl MoveLibrary {
|
|||
}
|
||||
|
||||
impl DataLibrary<MoveData> for MoveLibrary {
|
||||
fn get_cache(&self) -> &spin::rwlock::RwLock<BTreeMap<u32, MoveData>> {
|
||||
fn get_cache(&self) -> &spin::rwlock::RwLock<hashbrown::HashMap<u32, MoveData>> {
|
||||
&self.inner.cache
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use crate::app_interface::{DataLibrary, Species};
|
||||
use crate::{ExternRef, ExternalReferenceType, StringKey};
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::rc::Rc;
|
||||
use spin::RwLock;
|
||||
|
||||
struct SpeciesLibraryInner {
|
||||
ptr: ExternRef<SpeciesLibrary>,
|
||||
cache: RwLock<BTreeMap<u32, Species>>,
|
||||
cache: RwLock<hashbrown::HashMap<u32, Species>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -37,7 +36,7 @@ impl SpeciesLibrary {
|
|||
}
|
||||
|
||||
impl DataLibrary<Species> for SpeciesLibrary {
|
||||
fn get_cache(&self) -> &spin::rwlock::RwLock<BTreeMap<u32, Species>> {
|
||||
fn get_cache(&self) -> &spin::rwlock::RwLock<hashbrown::HashMap<u32, Species>> {
|
||||
&self.inner.cache
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use crate::{ExternRef, ExternalReferenceType};
|
||||
use alloc::collections::BTreeMap;
|
||||
use crate::{ExternRef, ExternalReferenceType, TypeIdentifier};
|
||||
use alloc::rc::Rc;
|
||||
use alloc::string::{String, ToString};
|
||||
use cstr_core::{c_char, CString};
|
||||
|
@ -7,8 +6,8 @@ use spin::RwLock;
|
|||
|
||||
struct TypeLibraryInner {
|
||||
reference: ExternRef<TypeLibrary>,
|
||||
name_to_type_cache: RwLock<BTreeMap<String, u8>>,
|
||||
effectiveness_cache: RwLock<BTreeMap<(u8, u8), f32>>,
|
||||
name_to_type_cache: RwLock<hashbrown::HashMap<String, TypeIdentifier>>,
|
||||
effectiveness_cache: RwLock<hashbrown::HashMap<(TypeIdentifier, TypeIdentifier), f32>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -39,7 +38,7 @@ impl TypeLibrary {
|
|||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub fn get_type_from_name(&self, name: &str) -> Option<u8> {
|
||||
pub fn get_type_from_name(&self, name: &str) -> Option<TypeIdentifier> {
|
||||
if let Some(cached) = self.inner.name_to_type_cache.read().get(name) {
|
||||
return Some(*cached);
|
||||
}
|
||||
|
@ -48,6 +47,7 @@ impl TypeLibrary {
|
|||
if v == 255 {
|
||||
return None;
|
||||
}
|
||||
let v = v.into();
|
||||
self.inner
|
||||
.name_to_type_cache
|
||||
.write()
|
||||
|
@ -56,7 +56,11 @@ impl TypeLibrary {
|
|||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub fn get_single_effectiveness(&self, attacking_type: u8, defending_type: u8) -> f32 {
|
||||
pub fn get_single_effectiveness(
|
||||
&self,
|
||||
attacking_type: TypeIdentifier,
|
||||
defending_type: TypeIdentifier,
|
||||
) -> f32 {
|
||||
if let Some(cached) = self
|
||||
.inner
|
||||
.effectiveness_cache
|
||||
|
@ -68,8 +72,8 @@ impl TypeLibrary {
|
|||
let effectiveness = unsafe {
|
||||
type_library_get_single_effectiveness(
|
||||
self.inner.reference,
|
||||
attacking_type,
|
||||
defending_type,
|
||||
attacking_type.into(),
|
||||
defending_type.into(),
|
||||
)
|
||||
};
|
||||
self.inner
|
||||
|
@ -80,7 +84,11 @@ impl TypeLibrary {
|
|||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub fn get_effectiveness(&self, attacking_type: u8, defending_types: &[u8]) -> f32 {
|
||||
pub fn get_effectiveness(
|
||||
&self,
|
||||
attacking_type: TypeIdentifier,
|
||||
defending_types: &[TypeIdentifier],
|
||||
) -> f32 {
|
||||
let mut f = 1.0;
|
||||
for defending_type in defending_types {
|
||||
f *= self.get_single_effectiveness(attacking_type, *defending_type);
|
||||
|
|
|
@ -96,7 +96,7 @@ crate::handling::cacheable::cacheable!(Item);
|
|||
#[cfg(not(feature = "mock_data"))]
|
||||
impl ExternalReferenceType for Item {
|
||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
||||
Item::mock(reference)
|
||||
Item::new(reference)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,3 +14,23 @@ pub use nature::*;
|
|||
pub use species::*;
|
||||
|
||||
pub type LevelInt = u8;
|
||||
|
||||
/// A unique key that can be used to store a reference to a type. Opaque reference to a byte
|
||||
/// internally.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash)]
|
||||
pub struct TypeIdentifier {
|
||||
/// The unique internal value.
|
||||
val: u8,
|
||||
}
|
||||
|
||||
impl From<u8> for TypeIdentifier {
|
||||
fn from(val: u8) -> Self {
|
||||
Self { val }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TypeIdentifier> for u8 {
|
||||
fn from(id: TypeIdentifier) -> Self {
|
||||
id.val
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::app_interface::{get_hash_const, StringKey};
|
||||
use crate::app_interface::{get_hash, StringKey};
|
||||
use crate::handling::cached_value::CachedValue;
|
||||
use crate::handling::Cacheable;
|
||||
use crate::{cached_value, cached_value_getters, ExternRef, ExternalReferenceType};
|
||||
|
@ -104,8 +104,8 @@ impl MoveData {
|
|||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub fn has_flag<const N: usize>(&self, flag: &[u8; N]) -> bool {
|
||||
let hash = get_hash_const(flag);
|
||||
pub fn has_flag(&self, flag: &str) -> bool {
|
||||
let hash = get_hash(flag);
|
||||
unsafe { move_data_has_flag_by_hash(self.inner.ptr, hash) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use crate::app_interface::get_hash_const;
|
||||
use crate::app_interface::get_hash;
|
||||
use crate::handling::cached_value::CachedValue;
|
||||
use crate::handling::Cacheable;
|
||||
use crate::{
|
||||
cached_value, cached_value_getters, ExternRef, ExternalReferenceType, FFIArray, ImmutableList,
|
||||
StringKey, VecExternRef,
|
||||
};
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::rc::Rc;
|
||||
use alloc::vec::Vec;
|
||||
use spin::RwLock;
|
||||
|
@ -147,8 +146,8 @@ impl Form {
|
|||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub fn has_flag<const N: usize>(&self, flag: &[u8; N]) -> bool {
|
||||
let hash = get_hash_const(flag);
|
||||
pub fn has_flag(&self, flag: &str) -> bool {
|
||||
let hash = get_hash(flag);
|
||||
unsafe { form_has_flag_by_hash(self.inner.reference, hash) }
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +159,7 @@ pub struct SpeciesInner {
|
|||
gender_rate: CachedValue<f32>,
|
||||
growth_rate: CachedValue<StringKey>,
|
||||
capture_rate: CachedValue<u8>,
|
||||
forms: RwLock<BTreeMap<u32, Option<Form>>>,
|
||||
forms: RwLock<hashbrown::HashMap<u32, Option<Form>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -205,8 +204,8 @@ impl Species {
|
|||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub fn get_form<const N: usize>(&self, form_name: &[u8; N]) -> Option<Form> {
|
||||
let hash = get_hash_const(form_name);
|
||||
pub fn get_form(&self, form_name: &str) -> Option<Form> {
|
||||
let hash = get_hash(form_name);
|
||||
unsafe {
|
||||
if let Some(v) = self.inner.forms.read().get(&hash) {
|
||||
v.clone()
|
||||
|
@ -220,8 +219,8 @@ impl Species {
|
|||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub fn has_flag<const N: usize>(&self, flag: &[u8; N]) -> bool {
|
||||
let hash = get_hash_const(flag);
|
||||
pub fn has_flag(&self, flag: &str) -> bool {
|
||||
let hash = get_hash(flag);
|
||||
unsafe { species_has_flag_by_hash(self.inner.reference, hash) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ impl StringKey {
|
|||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub(super) fn ptr(&self) -> ExternRef<Self> {
|
||||
pub(crate) fn ptr(&self) -> ExternRef<Self> {
|
||||
self.data.ptr
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,12 @@ impl StringKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq for StringKey {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.data.ptr == other.data.ptr
|
||||
}
|
||||
}
|
||||
|
||||
crate::handling::cacheable::cacheable!(StringKey);
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
|
@ -134,23 +140,12 @@ const fn to_lower(c: u8) -> u8 {
|
|||
c
|
||||
}
|
||||
|
||||
pub const fn get_hash_const<const N: usize>(s: &[u8; N]) -> u32 {
|
||||
let mut crc: u32 = 0xffffffff;
|
||||
|
||||
let mut i: usize = 0;
|
||||
while i < N {
|
||||
crc = (crc >> 8) ^ CRC_TABLE[((crc ^ (to_lower(s[i]) as u32)) & 0xff) as usize];
|
||||
i += 1;
|
||||
}
|
||||
crc ^ 0xffffffff
|
||||
}
|
||||
|
||||
pub const fn get_hash(s: &[u8]) -> u32 {
|
||||
pub const fn get_hash(s: &str) -> u32 {
|
||||
let mut crc: u32 = 0xffffffff;
|
||||
|
||||
let mut i: usize = 0;
|
||||
while i < s.len() {
|
||||
crc = (crc >> 8) ^ CRC_TABLE[((crc ^ (to_lower(s[i]) as u32)) & 0xff) as usize];
|
||||
crc = (crc >> 8) ^ CRC_TABLE[((crc ^ (to_lower(s.as_bytes()[i]) as u32)) & 0xff) as usize];
|
||||
i += 1;
|
||||
}
|
||||
crc ^ 0xffffffff
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
#[cfg(not(feature = "mock_data"))]
|
||||
use crate::ExternRef;
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
use alloc::collections::BTreeMap;
|
||||
|
||||
pub trait Cacheable {
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
fn get_cache<'a>() -> &'a mut BTreeMap<ExternRef<Self>, Self>
|
||||
fn get_cache<'a>() -> &'a mut hashbrown::HashMap<ExternRef<Self>, Self>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
|
@ -19,21 +17,28 @@ pub trait Cacheable {
|
|||
if let Some(v) = opt {
|
||||
return v.clone();
|
||||
}
|
||||
Self::get_cache().insert(ptr, ctor(ptr));
|
||||
return Self::get_cache().get(&ptr).unwrap().clone();
|
||||
let value = ctor(ptr);
|
||||
Self::get_cache().insert(ptr, value.clone());
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! cacheable {
|
||||
($type: ty) => {
|
||||
paste::paste!{
|
||||
paste::paste! {
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
static mut [<$type:upper _CACHE>]: alloc::collections::BTreeMap<ExternRef<$type>, $type> =
|
||||
alloc::collections::BTreeMap::new();
|
||||
static mut [<$type:upper _CACHE>]: Option<hashbrown::HashMap<ExternRef<$type>, $type>> =
|
||||
None;
|
||||
impl crate::handling::Cacheable for $type {
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
fn get_cache<'a>() -> &'a mut alloc::collections::BTreeMap<ExternRef<$type>, $type> {
|
||||
unsafe { &mut [<$type:upper _CACHE>] }
|
||||
fn get_cache<'a>() -> &'a mut hashbrown::HashMap<ExternRef<$type>, $type> {
|
||||
unsafe {
|
||||
if let None = [<$type:upper _CACHE>] {
|
||||
[<$type:upper _CACHE>] = Some(hashbrown::HashMap::new());
|
||||
}
|
||||
|
||||
[<$type:upper _CACHE>].as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,59 +1,62 @@
|
|||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ScriptCapabilities {
|
||||
None = 0,
|
||||
Initialize = 1,
|
||||
OnStack,
|
||||
OnRemove,
|
||||
OnBeforeTurn,
|
||||
ChangeAttack,
|
||||
ModifyNumberOfHits,
|
||||
PreventAttack,
|
||||
FailAttack,
|
||||
StopBeforeAttack,
|
||||
OnBeforeAttack,
|
||||
FailIncomingAttack,
|
||||
ChangeMove,
|
||||
ChangeNumberOfHits,
|
||||
PreventMove,
|
||||
FailMove,
|
||||
StopBeforeMove,
|
||||
OnBeforeMove,
|
||||
FailIncomingMove,
|
||||
IsInvulnerable,
|
||||
OnAttackMiss,
|
||||
ChangeAttackType,
|
||||
OnMoveMiss,
|
||||
ChangeMoveType,
|
||||
ChangeEffectiveness,
|
||||
BlockCritical,
|
||||
OnIncomingHit,
|
||||
OnFaintingOpponent,
|
||||
PreventStatBoostChange,
|
||||
ModifyStatBoostChange,
|
||||
ChangeStatBoostChange,
|
||||
PreventSecondaryEffects,
|
||||
OnSecondaryEffect,
|
||||
OnAfterHits,
|
||||
PreventSelfSwitch,
|
||||
ModifyEffectChance,
|
||||
ModifyIncomingEffectChance,
|
||||
OverrideBasePower,
|
||||
ChangeEffectChance,
|
||||
ChangeIncomingEffectChance,
|
||||
ChangeBasePower,
|
||||
ChangeDamageStatsUser,
|
||||
BypassDefensiveStat,
|
||||
BypassOffensiveStat,
|
||||
ModifyStatModifier,
|
||||
ModifyDamageModifier,
|
||||
OverrideDamage,
|
||||
OverrideIncomingDamage,
|
||||
ChangeStatModifier,
|
||||
ChangeDamageModifier,
|
||||
ChangeDamage,
|
||||
ChangeIncomingDamage,
|
||||
ChangeSpeed,
|
||||
ChangePriority,
|
||||
OnFail,
|
||||
OnOpponentFail,
|
||||
PreventRunAway,
|
||||
PreventSelfRunAway,
|
||||
PreventOpponentRunAway,
|
||||
PreventOpponentSwitch,
|
||||
OnEndTurn,
|
||||
OnDamage,
|
||||
OnFaint,
|
||||
OnAfterHeldItemConsume,
|
||||
PreventIncomingCritical,
|
||||
ModifyCriticalStage,
|
||||
OverrideCriticalModifier,
|
||||
OverrideSTABModifier,
|
||||
ModifyExperienceGain,
|
||||
BlockIncomingCritical,
|
||||
ChangeAccuracy,
|
||||
ChangeCriticalStage,
|
||||
ChangeCriticalModifier,
|
||||
ChangeSTABModifier,
|
||||
ChangeExperienceGain,
|
||||
DoesShareExperience,
|
||||
BlockWeather,
|
||||
OnSwitchIn,
|
||||
ModifyOffensiveStatValue,
|
||||
ModifyDefensiveStatValue,
|
||||
ChangeOffensiveStatValue,
|
||||
ChangeDefensiveStatValue,
|
||||
ChangeCaptureRate,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::ImmutableList;
|
||||
use core::cmp::Ordering;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::intrinsics::transmute;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
|
@ -28,6 +29,16 @@ impl<T> ExternRef<T> {
|
|||
T::instantiate_from_extern_value(*self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn not_null(&self) -> T
|
||||
where
|
||||
T: ExternalReferenceType,
|
||||
T: Sized,
|
||||
T:,
|
||||
{
|
||||
T::instantiate_from_extern_value(*self).unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn cast<TCast>(&self) -> ExternRef<TCast> {
|
||||
ExternRef::<TCast> {
|
||||
|
@ -76,6 +87,12 @@ impl<T> Ord for ExternRef<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Hash for ExternRef<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.p.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct VecExternRef<T> {
|
||||
v: u64,
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use crate::app_interface::list::ImmutableList;
|
||||
use crate::app_interface::{DynamicLibrary, EffectParameter};
|
||||
use crate::app_interface::{
|
||||
Battle, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Item, Pokemon, Statistic,
|
||||
};
|
||||
use crate::handling::ScriptCapabilities;
|
||||
use crate::{ExternRef, TurnChoice};
|
||||
use crate::{ExternRef, StringKey, TurnChoice, TypeIdentifier};
|
||||
use core::ffi::c_void;
|
||||
use core::fmt::Debug;
|
||||
|
||||
|
@ -9,17 +11,338 @@ pub trait Script {
|
|||
fn new() -> Self
|
||||
where
|
||||
Self: Sized;
|
||||
fn destroy(&self);
|
||||
fn get_name(&self) -> &str;
|
||||
fn get_name() -> &'static str
|
||||
where
|
||||
Self: Sized;
|
||||
fn get_capabilities(&self) -> &[ScriptCapabilities];
|
||||
|
||||
/// 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.
|
||||
fn stack(&self) {}
|
||||
/// This function is ran when this script stops being in effect, and is removed from its owner.
|
||||
fn on_remove(&self) {}
|
||||
|
||||
/// This function is ran when this script starts being in effect.
|
||||
fn on_initialize(
|
||||
&self,
|
||||
_library: &DynamicLibrary,
|
||||
_parameters: Option<ImmutableList<EffectParameter>>,
|
||||
) {
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// something has happened during a turn.
|
||||
fn on_before_turn(&self, _choice: TurnChoice) {}
|
||||
|
||||
/// 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.
|
||||
fn change_speed(&self, _choice: TurnChoice, _speed: &mut u32) {}
|
||||
/// 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
|
||||
/// 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) {}
|
||||
|
||||
/// 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.
|
||||
fn change_move(&self, _choice: TurnChoice, _move_name: &mut StringKey) {}
|
||||
/// 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
|
||||
/// first hit.
|
||||
fn change_number_of_hits(&self, _choice: TurnChoice, _number_of_hits: &mut u8) {}
|
||||
|
||||
/// 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.
|
||||
fn prevent_move(&self, _move: ExecutingMove, _prevent: &mut bool) {}
|
||||
/// This function makes the move fail. If the fail field gets set to true, the move ends execution,
|
||||
/// and fail events get triggered.
|
||||
fn fail_move(&self, _move: ExecutingMove, _fail: &mut bool) {}
|
||||
/// Similar to [`Self::prevent_move`]. This function will also stop execution, but PP will be
|
||||
/// decreased.
|
||||
fn stop_before_move(&self, _move: ExecutingMove, _stop: &mut bool) {}
|
||||
/// This function runs just before the move starts its execution.
|
||||
fn on_before_move(&self, _move: ExecutingMove) {}
|
||||
/// 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.
|
||||
fn fail_incoming_move(&self, _move: ExecutingMove, _target: Pokemon, _fail: &mut bool) {}
|
||||
/// 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) {}
|
||||
/// 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.
|
||||
fn on_move_miss(&self, _move: ExecutingMove, _target: Pokemon) {}
|
||||
/// This function allows the script to change the actual type that is used for the move on a target.
|
||||
fn change_move_type(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_move_type: &mut TypeIdentifier,
|
||||
) {
|
||||
}
|
||||
/// This function allows the script to change how effective a move is on a target.
|
||||
fn change_effectiveness(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_effectiveness: &mut f32,
|
||||
) {
|
||||
}
|
||||
/// This function allows a script to block an outgoing move from being critical.
|
||||
fn block_critical(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_block_critical: &mut bool,
|
||||
) {
|
||||
}
|
||||
/// This function allows a script to block an incoming move from being critical.
|
||||
fn block_incoming_critical(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_block_critical: &mut bool,
|
||||
) {
|
||||
}
|
||||
/// 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.
|
||||
fn change_accuracy(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_accuracy: &mut u8,
|
||||
) {
|
||||
}
|
||||
|
||||
/// This function allows a script to change the critical stage of the move used.
|
||||
fn change_critical_stage(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_stage: &mut u8,
|
||||
) {
|
||||
}
|
||||
/// This function allows a script to change the damage modifier of a critical hit. This will only
|
||||
/// run when a hit is critical.
|
||||
fn change_critical_modifier(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_modifier: &mut f32,
|
||||
) {
|
||||
}
|
||||
/// 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.
|
||||
fn change_stab_modifier(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_modifier: &mut f32,
|
||||
) {
|
||||
}
|
||||
|
||||
/// This function allows a script to change the effective base power of a move hit.
|
||||
fn change_base_power(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_base_power: &mut u8,
|
||||
) {
|
||||
}
|
||||
/// This function allows a script to bypass defensive stat boosts for a move hit.
|
||||
fn bypass_defensive_stat_boost(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_bypass: &mut bool,
|
||||
) {
|
||||
}
|
||||
/// This function allows a script to bypass offensive stat boosts for a move hit.
|
||||
fn bypass_offensive_stat_boost(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_bypass: &mut bool,
|
||||
) {
|
||||
}
|
||||
/// This function allows a script to change the actual offensive stat values used when calculating damage
|
||||
fn change_offensive_stat_value(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_amount: &mut u32,
|
||||
) {
|
||||
}
|
||||
/// This function allows a script to change the actual defensive stat values used when calculating damage.
|
||||
fn change_defensive_stat_value(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_amount: &mut u32,
|
||||
) {
|
||||
}
|
||||
|
||||
/// This function allows a script to change the raw modifier we retrieved from the stats of the
|
||||
/// defender and attacker.
|
||||
fn change_damage_stat_modifier(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_modifier: &mut f32,
|
||||
) {
|
||||
}
|
||||
/// This function allows a script to apply a raw multiplier to the damage done by a move.
|
||||
fn change_damage_modifier(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_modifier: &mut f32,
|
||||
) {
|
||||
}
|
||||
/// 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) {}
|
||||
/// This function allows a script to modify the incoming damage done by a move.
|
||||
fn change_incoming_damage(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_damage: &mut u32,
|
||||
) {
|
||||
}
|
||||
/// This function triggers when an incoming hit happens. This triggers after the damage is done,
|
||||
/// but before the secondary effect of the move happens.
|
||||
fn on_incoming_hit(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) {}
|
||||
/// This function triggers when an opponent on the field faints.
|
||||
fn on_opponent_faints(&self, _move: ExecutingMove, _target: Pokemon, _hit: u8) {}
|
||||
/// This function allows a script attached to a Pokemon or its parents to prevent stat boost
|
||||
/// changes on that Pokemon.
|
||||
fn prevent_stat_boost_change(
|
||||
&self,
|
||||
_target: Pokemon,
|
||||
_stat: Statistic,
|
||||
_amount: i8,
|
||||
_self_inflicted: bool,
|
||||
_prevent: &mut bool,
|
||||
) {
|
||||
}
|
||||
/// 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
|
||||
/// inflicted will be true, otherwise it will be false.
|
||||
fn change_stat_boost_change(
|
||||
&self,
|
||||
_target: Pokemon,
|
||||
_stat: Statistic,
|
||||
_self_inflicted: bool,
|
||||
_amount: &mut i8,
|
||||
) {
|
||||
}
|
||||
/// 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. Note that this function is not called for status moves.
|
||||
fn prevent_secondary_effect(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_prevent: &mut bool,
|
||||
) {
|
||||
}
|
||||
/// 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
|
||||
/// changing this to above or equal to 100 will make it always hit, while setting it to equal or
|
||||
/// below 0 will make it never hit.
|
||||
fn change_effect_chance(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_chance: &mut f32,
|
||||
) {
|
||||
}
|
||||
/// 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,
|
||||
/// so changing this to above or equal to 100 will make it always hit, while setting it to equal
|
||||
/// or below 0 will make it never hit.
|
||||
fn change_incoming_effect_chance(
|
||||
&self,
|
||||
_move: ExecutingMove,
|
||||
_target: Pokemon,
|
||||
_hit: u8,
|
||||
_chance: &mut f32,
|
||||
) {
|
||||
}
|
||||
/// 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
|
||||
/// 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) {}
|
||||
/// 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) {}
|
||||
/// 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) {}
|
||||
/// This function allows the prevention of switching for any opponent.
|
||||
fn prevent_opponent_switch(&self, _choice: TurnChoice, _prevent: &mut bool) {}
|
||||
/// This function is called on a move and its parents when the move fails.
|
||||
fn on_fail(&self, _target: Pokemon) {}
|
||||
/// This function is called on a script when an opponent fails.
|
||||
fn on_opponent_fail(&self, _target: Pokemon) {}
|
||||
/// This function allows preventing the running away of the Pokemon its attached to
|
||||
fn prevent_self_run_away(&self, _choice: TurnChoice, _prevent: &mut bool) {}
|
||||
/// 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) {}
|
||||
/// 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
|
||||
/// function.
|
||||
fn on_end_turn(&self) {}
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon takes damage.
|
||||
fn on_damage(
|
||||
&self,
|
||||
_pokemon: Pokemon,
|
||||
_source: DamageSource,
|
||||
_old_health: u32,
|
||||
_new_health: u32,
|
||||
) {
|
||||
}
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon faints.
|
||||
fn on_faint(&self, _pokemon: Pokemon, _source: DamageSource) {}
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon is switched into
|
||||
/// the battlefield.
|
||||
fn on_switch_in(&self, _pokemon: Pokemon) {}
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon consumes the
|
||||
/// held item it had.
|
||||
fn on_after_held_item_consume(&self, _pokemon: Pokemon, _item: &Item) {}
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon gains experience,
|
||||
/// and allows for changing this amount of experience.
|
||||
fn change_experience_gained(
|
||||
&self,
|
||||
_fainted_mon: Pokemon,
|
||||
_winning_mon: Pokemon,
|
||||
_amount: &mut u32,
|
||||
) {
|
||||
}
|
||||
/// 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.
|
||||
fn share_experience(&self, _fainted_mon: Pokemon, _winning_mon: Pokemon, _shares: &mut bool) {}
|
||||
/// This function is triggered on a battle and its parents when something attempts to change the
|
||||
/// weather, and allows for blocking the weather change.
|
||||
fn block_weather(&self, _battle: Battle, _blocked: &mut bool) {}
|
||||
/// 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
|
||||
/// example status effects that change capture rates.
|
||||
fn change_capture_rate_bonus(&self, _target: Pokemon, _pokeball: Item, _modifier: &mut u8) {}
|
||||
}
|
||||
|
||||
impl Debug for dyn Script {
|
||||
|
|
|
@ -1,80 +1,63 @@
|
|||
use crate::{ExternRef, ExternalReferenceType};
|
||||
use alloc::boxed::Box;
|
||||
use core::cell::Cell;
|
||||
use core::mem::forget;
|
||||
|
||||
struct TemporaryData<T> {
|
||||
use_count: Cell<usize>,
|
||||
is_deleted: bool,
|
||||
value: T,
|
||||
}
|
||||
use alloc::rc::Rc;
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
pub struct Temporary<T> {
|
||||
value: *mut TemporaryData<T>,
|
||||
is_deleted: Rc<AtomicBool>,
|
||||
value: Rc<T>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
static mut TEMPORARIES: alloc::collections::BTreeMap<u32, *const u8> =
|
||||
alloc::collections::BTreeMap::new();
|
||||
static mut TEMPORARIES: Option<hashbrown::HashMap<u32, Rc<AtomicBool>>> = None;
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl<T> Temporary<T>
|
||||
where
|
||||
T: ExternalReferenceType,
|
||||
T: Clone,
|
||||
{
|
||||
impl<T> Temporary<T> {
|
||||
#[inline]
|
||||
pub fn from_reference(reference: ExternRef<T>) -> Self {
|
||||
let temporaries = unsafe { &mut TEMPORARIES };
|
||||
let existing = temporaries.get(&reference.get_internal_index());
|
||||
pub fn new(reference: u32, value: T) -> Self {
|
||||
unsafe {
|
||||
if let Some(v) = existing {
|
||||
let rc = (*v as *mut TemporaryData<T>).as_mut().unwrap();
|
||||
if !rc.is_deleted {
|
||||
*rc.use_count.get_mut() += 1;
|
||||
return Self {
|
||||
value: rc as *mut TemporaryData<T>,
|
||||
};
|
||||
}
|
||||
if let None = TEMPORARIES {
|
||||
TEMPORARIES = Some(hashbrown::HashMap::new());
|
||||
}
|
||||
}
|
||||
let temporaries = unsafe { &mut TEMPORARIES }.as_mut().unwrap();
|
||||
let existing = temporaries.get(&reference);
|
||||
if let Some(v) = existing {
|
||||
return Self {
|
||||
is_deleted: v.clone(),
|
||||
value: Rc::new(value),
|
||||
};
|
||||
}
|
||||
|
||||
let value = reference.get_value().unwrap();
|
||||
let mut reference_counter = TemporaryData {
|
||||
use_count: Cell::new(1),
|
||||
is_deleted: false,
|
||||
value,
|
||||
};
|
||||
let ptr = &mut reference_counter as *mut TemporaryData<T>;
|
||||
forget(reference_counter);
|
||||
temporaries.insert(reference.get_internal_index(), ptr as *const u8);
|
||||
Self { value: ptr }
|
||||
let value = Rc::new(value);
|
||||
let is_deleted = Rc::new(AtomicBool::new(false));
|
||||
temporaries.insert(reference, is_deleted.clone());
|
||||
Self { is_deleted, value }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn value(&self) -> T {
|
||||
unsafe { self.value.as_ref().unwrap().value.clone() }
|
||||
pub fn value(&self) -> Rc<T> {
|
||||
if self.is_deleted.load(Ordering::SeqCst) {
|
||||
panic!("Accessed value after it had been deleted");
|
||||
}
|
||||
self.value.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn value_ref(&self) -> &T {
|
||||
unsafe { &self.value.as_ref().unwrap().value }
|
||||
if self.is_deleted.load(Ordering::SeqCst) {
|
||||
panic!("Accessed value after it had been deleted");
|
||||
}
|
||||
self.value.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mark_as_deleted(reference: ExternRef<T>) {
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl Temporary<u8> {
|
||||
pub(crate) fn mark_as_deleted(reference: u32) {
|
||||
let temporaries = unsafe { &mut TEMPORARIES };
|
||||
let existing = temporaries.get(&reference.get_internal_index());
|
||||
unsafe {
|
||||
if let Some(v) = existing {
|
||||
crate::utils::print_raw(b"Dropping temporary");
|
||||
let rc = (*v as *mut TemporaryData<T>).as_mut().unwrap();
|
||||
rc.is_deleted = true;
|
||||
if rc.use_count.get() == 0 {
|
||||
drop(Box::from(*v as *mut TemporaryData<T>))
|
||||
}
|
||||
temporaries.remove(&reference.get_internal_index());
|
||||
}
|
||||
let existing = temporaries.as_mut().unwrap().get_mut(&reference);
|
||||
if let Some(v) = existing {
|
||||
v.store(false, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,32 +65,28 @@ where
|
|||
#[cfg(not(feature = "mock_data"))]
|
||||
impl<T> Clone for Temporary<T> {
|
||||
fn clone(&self) -> Self {
|
||||
*unsafe { self.value.as_mut() }.unwrap().use_count.get_mut() += 1;
|
||||
Self { value: self.value }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
impl<T> Drop for Temporary<T> {
|
||||
fn drop(&mut self) {
|
||||
let data = unsafe { self.value.as_mut() }.unwrap();
|
||||
let v = data.use_count.get_mut();
|
||||
*v -= 1;
|
||||
if *v == 0 && data.is_deleted {
|
||||
drop(Box::from(self.value))
|
||||
Self {
|
||||
is_deleted: self.is_deleted.clone(),
|
||||
value: self.value.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mock_data")]
|
||||
pub struct Temporary<T: Clone> {
|
||||
value: T,
|
||||
#[no_mangle]
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
unsafe extern "wasm" fn _mark_deleted(r: u32) {
|
||||
Temporary::<u8>::mark_as_deleted(r)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mock_data")]
|
||||
impl<T: Clone> Temporary<T> {
|
||||
pub struct Temporary<T> {
|
||||
value: Rc<T>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "mock_data")]
|
||||
impl<T> Temporary<T> {
|
||||
#[inline]
|
||||
pub fn value(&self) -> T {
|
||||
pub fn value(&self) -> Rc<T> {
|
||||
self.value.clone()
|
||||
}
|
||||
|
||||
|
@ -116,3 +95,12 @@ impl<T: Clone> Temporary<T> {
|
|||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mock_data")]
|
||||
impl<T> Clone for Temporary<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
value: self.value.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#![feature(wasm_abi)]
|
||||
#![feature(thread_local)]
|
||||
#![feature(build_hasher_simple_hash_one)]
|
||||
#![feature(adt_const_params)]
|
||||
#![cfg_attr(not(feature = "mock_data"), no_std)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
|
@ -23,7 +24,12 @@ extern crate wee_alloc;
|
|||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||
|
||||
use crate::app_interface::list::ImmutableList;
|
||||
use crate::app_interface::{DynamicLibrary, EffectParameter, StringKey, TurnChoice};
|
||||
use crate::app_interface::Statistic;
|
||||
use crate::app_interface::{
|
||||
Battle, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Item, StringKey,
|
||||
TurnChoice,
|
||||
};
|
||||
use crate::app_interface::{Pokemon, TypeIdentifier};
|
||||
pub(crate) use crate::handling::extern_ref::*;
|
||||
use crate::handling::ffi_array::FFIArray;
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
|
@ -47,61 +53,565 @@ pub fn set_load_script_fn(f: LoadScriptFnType) {
|
|||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
extern "wasm" fn load_script(category: ScriptCategory, name: ExternRef<StringKey>) -> u32 {
|
||||
macro_rules! exported_functions {
|
||||
(
|
||||
$(
|
||||
fn $func_name:ident($($par_name:ident: $par_type:ty),*$(,)?) $(-> $return_type:ty)? $func_body:block
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
#[no_mangle]
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
unsafe extern "wasm" fn $func_name(
|
||||
$(
|
||||
$par_name: $par_type,
|
||||
)*
|
||||
) $(-> $return_type)* $func_body
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ScriptPtr {
|
||||
ptr: *const Box<dyn Script>,
|
||||
}
|
||||
|
||||
impl ScriptPtr {
|
||||
pub fn new(ptr: *const Box<dyn Script>) -> Self {
|
||||
Self { ptr }
|
||||
}
|
||||
|
||||
pub fn val(&self) -> &dyn Script {
|
||||
unsafe { self.ptr.as_ref().unwrap().as_ref() }
|
||||
}
|
||||
|
||||
pub fn ptr(&self) -> *const Box<dyn Script> {
|
||||
self.ptr
|
||||
}
|
||||
}
|
||||
|
||||
exported_functions! {
|
||||
|
||||
fn load_script(category: ScriptCategory, name: ExternRef<StringKey>) -> ScriptPtr {
|
||||
let name_c = StringKey::new(name);
|
||||
let boxed_script = unsafe { &LOAD_SCRIPT_FN }.as_ref().unwrap()(category, &name_c);
|
||||
if boxed_script.is_none() {
|
||||
return 0;
|
||||
return ScriptPtr::new(core::ptr::null());
|
||||
}
|
||||
let b = Box::new(boxed_script.unwrap());
|
||||
Box::into_raw(b) as u32
|
||||
ScriptPtr::new(Box::into_raw(b))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
unsafe extern "wasm" fn destroy_script(script: *mut Box<dyn Script>) {
|
||||
fn destroy_script(script: *mut Box<dyn Script>) {
|
||||
// By turning it from a raw pointer back into a Box with from_raw, we give ownership back to rust.
|
||||
// This lets Rust do the cleanup.
|
||||
let boxed_script = Box::from_raw(script);
|
||||
boxed_script.destroy();
|
||||
drop(boxed_script);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
unsafe extern "wasm" fn get_script_capabilities(
|
||||
script: *const Box<dyn Script>,
|
||||
) -> FFIArray<ScriptCapabilities> {
|
||||
let c = script.as_ref().unwrap().get_capabilities();
|
||||
fn get_script_capabilities(script: ScriptPtr) -> FFIArray<ScriptCapabilities> {
|
||||
let c = script.val().get_capabilities();
|
||||
FFIArray::new(c)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
unsafe extern "wasm" fn script_on_initialize(
|
||||
script: *const Box<dyn Script>,
|
||||
fn script_stack(script: ScriptPtr) {
|
||||
script.val().stack();
|
||||
}
|
||||
|
||||
fn script_on_remove(script: ScriptPtr) {
|
||||
script.val().on_remove();
|
||||
}
|
||||
|
||||
fn script_on_initialize(
|
||||
script: ScriptPtr,
|
||||
library: ExternRef<DynamicLibrary>,
|
||||
parameters: VecExternRef<EffectParameter>,
|
||||
) {
|
||||
let lib = DynamicLibrary::new(library);
|
||||
let parameters = ImmutableList::from_ref(parameters);
|
||||
script
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.on_initialize(&lib, Some(parameters));
|
||||
script.val().on_initialize(&library.not_null(), Some(parameters));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
unsafe extern "wasm" fn script_on_before_turn(
|
||||
script: *const Box<dyn Script>,
|
||||
fn script_on_before_turn(
|
||||
script: ScriptPtr,
|
||||
choice: ExternRef<TurnChoice>,
|
||||
) {
|
||||
script
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.on_before_turn(choice.get_value().unwrap())
|
||||
script.val().on_before_turn(choice.not_null())
|
||||
}
|
||||
|
||||
fn script_change_speed(
|
||||
script:ScriptPtr,
|
||||
choice: ExternRef<TurnChoice>,
|
||||
speed: *mut u32,
|
||||
) {
|
||||
script.val().change_speed(choice.not_null(), speed.as_mut().unwrap())
|
||||
}
|
||||
|
||||
fn script_change_priority(
|
||||
script: ScriptPtr,
|
||||
choice: ExternRef<TurnChoice>,
|
||||
priority: *mut i8,
|
||||
) {
|
||||
script.val().change_priority(choice.not_null(), priority.as_mut().unwrap())
|
||||
}
|
||||
|
||||
fn script_change_move(
|
||||
script: ScriptPtr,
|
||||
choice: ExternRef<TurnChoice>,
|
||||
mv: *mut ExternRef<StringKey>,
|
||||
) {
|
||||
let old = mv.as_ref().unwrap().not_null();
|
||||
let mut new = old.clone();
|
||||
script.val().change_move(choice.not_null(), &mut new);
|
||||
if old != new {
|
||||
*mv = new.ptr();
|
||||
}
|
||||
}
|
||||
|
||||
fn script_change_number_of_hits(
|
||||
script: ScriptPtr,
|
||||
choice: ExternRef<TurnChoice>,
|
||||
out: *mut u8,
|
||||
) {
|
||||
script.val().change_number_of_hits(choice.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_prevent_move(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().prevent_move(mv.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_fail_move(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().fail_move(mv.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_stop_before_move(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().stop_before_move(mv.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_on_before_move(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
) {
|
||||
script.val().on_before_move(mv.not_null());
|
||||
}
|
||||
|
||||
fn script_fail_incoming_move(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().fail_incoming_move(mv.not_null(), target.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_is_invulnerable(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().is_invulnerable(mv.not_null(), target.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_on_move_miss(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
) {
|
||||
script.val().on_move_miss(mv.not_null(), target.not_null());
|
||||
}
|
||||
|
||||
fn script_change_move_type(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut TypeIdentifier,
|
||||
) {
|
||||
script.val().change_move_type(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_effectiveness(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut f32,
|
||||
) {
|
||||
script.val().change_effectiveness(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_block_critical(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().block_critical(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_block_incoming_critical(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().block_incoming_critical(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_accuracy(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut u8,
|
||||
) {
|
||||
script.val().change_accuracy(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_critical_stage(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut u8,
|
||||
) {
|
||||
script.val().change_critical_stage(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_critical_modifier(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut f32,
|
||||
) {
|
||||
script.val().change_critical_modifier(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_stab_modifier(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut f32,
|
||||
) {
|
||||
script.val().change_stab_modifier(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_base_power(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut u8,
|
||||
) {
|
||||
script.val().change_base_power(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_bypass_defensive_stat_boost(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().bypass_defensive_stat_boost(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_bypass_offensive_stat_boost(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().bypass_offensive_stat_boost(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_defensive_stat_value(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut u32,
|
||||
) {
|
||||
script.val().change_defensive_stat_value(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_offensive_stat_value(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut u32,
|
||||
) {
|
||||
script.val().change_offensive_stat_value(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_damage_stat_modifier(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut f32,
|
||||
) {
|
||||
script.val().change_damage_stat_modifier(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_damage_modifier(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut f32,
|
||||
) {
|
||||
script.val().change_damage_modifier(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_damage(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut u32,
|
||||
) {
|
||||
script.val().change_damage(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_incoming_damage(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut u32,
|
||||
) {
|
||||
script.val().change_incoming_damage(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_on_incoming_hit(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
) {
|
||||
script.val().on_incoming_hit(mv.not_null(), target.not_null(), hit);
|
||||
}
|
||||
|
||||
fn script_on_opponent_faints(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
) {
|
||||
script.val().on_opponent_faints(mv.not_null(), target.not_null(), hit);
|
||||
}
|
||||
|
||||
fn script_prevent_stat_boost_change(
|
||||
script: ScriptPtr,
|
||||
target: ExternRef<Pokemon>,
|
||||
stat: Statistic,
|
||||
amount: i8,
|
||||
self_inflicted: u8,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().prevent_stat_boost_change(target.not_null(), stat, amount, self_inflicted == 1, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_prevent_secondary_effect(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().prevent_secondary_effect(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_effect_chance(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut f32,
|
||||
) {
|
||||
script.val().change_effect_chance(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_incoming_effect_chance(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
out: *mut f32,
|
||||
) {
|
||||
script.val().change_incoming_effect_chance(mv.not_null(), target.not_null(), hit, out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_on_secondary_effect(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
hit: u8,
|
||||
) {
|
||||
script.val().on_secondary_effect(mv.not_null(), target.not_null(), hit);
|
||||
}
|
||||
|
||||
fn script_on_after_hits(
|
||||
script: ScriptPtr,
|
||||
mv: ExternRef<ExecutingMove>,
|
||||
target: ExternRef<Pokemon>,
|
||||
) {
|
||||
script.val().on_after_hits(mv.not_null(), target.not_null());
|
||||
}
|
||||
|
||||
fn script_prevent_self_switch(
|
||||
script: ScriptPtr,
|
||||
choice: ExternRef<TurnChoice>,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().prevent_self_switch(choice.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_prevent_opponent_switch(
|
||||
script: ScriptPtr,
|
||||
choice: ExternRef<TurnChoice>,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().prevent_opponent_switch(choice.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_on_fail(
|
||||
script: ScriptPtr,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
) {
|
||||
script.val().on_fail(pokemon.not_null());
|
||||
}
|
||||
|
||||
fn script_on_opponent_fail(
|
||||
script: ScriptPtr,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
) {
|
||||
script.val().on_opponent_fail(pokemon.not_null());
|
||||
}
|
||||
|
||||
fn script_prevent_self_run_away(
|
||||
script: ScriptPtr,
|
||||
choice: ExternRef<TurnChoice>,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().prevent_self_run_away(choice.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_prevent_opponent_run_away(
|
||||
script: ScriptPtr,
|
||||
choice: ExternRef<TurnChoice>,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().prevent_opponent_run_away(choice.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_on_end_turn(
|
||||
script: ScriptPtr,
|
||||
) {
|
||||
script.val().on_end_turn();
|
||||
}
|
||||
|
||||
fn script_on_damage(
|
||||
script: ScriptPtr,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
source: DamageSource,
|
||||
old_health: u32,
|
||||
new_health: u32,
|
||||
) {
|
||||
script.val().on_damage(pokemon.not_null(), source, old_health, new_health);
|
||||
}
|
||||
|
||||
fn script_on_faint(
|
||||
script: ScriptPtr,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
source: DamageSource,
|
||||
) {
|
||||
script.val().on_faint(pokemon.not_null(), source);
|
||||
}
|
||||
|
||||
fn script_on_switch_in(
|
||||
script: ScriptPtr,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
) {
|
||||
script.val().on_switch_in(pokemon.not_null());
|
||||
}
|
||||
|
||||
fn script_on_after_held_item_consume(
|
||||
script: ScriptPtr,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
item: ExternRef<Item>
|
||||
) {
|
||||
script.val().on_after_held_item_consume(pokemon.not_null(), &item.not_null());
|
||||
}
|
||||
|
||||
fn script_change_experience_gained(
|
||||
script: ScriptPtr,
|
||||
fainted_pokemon: ExternRef<Pokemon>,
|
||||
winning_pokemon: ExternRef<Pokemon>,
|
||||
out: *mut u32
|
||||
) {
|
||||
script.val().change_experience_gained(fainted_pokemon.not_null(), winning_pokemon.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_share_experience(
|
||||
script: ScriptPtr,
|
||||
fainted_pokemon: ExternRef<Pokemon>,
|
||||
winning_pokemon: ExternRef<Pokemon>,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().share_experience(fainted_pokemon.not_null(), winning_pokemon.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_block_weather(
|
||||
script: ScriptPtr,
|
||||
battle: ExternRef<Battle>,
|
||||
out: *mut bool,
|
||||
) {
|
||||
script.val().block_weather(battle.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
fn script_change_capture_rate_bonus(
|
||||
script: ScriptPtr,
|
||||
target: ExternRef<Pokemon>,
|
||||
pokeball: ExternRef<Item>,
|
||||
out: *mut u8,
|
||||
) {
|
||||
script.val().change_capture_rate_bonus(target.not_null(), pokeball.not_null(), out.as_mut().unwrap());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@ use alloc::alloc::alloc;
|
|||
use core::alloc::Layout;
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
use core::panic::PanicInfo;
|
||||
use cstr_core::{c_char, CStr, CString};
|
||||
use cstr_core::c_char;
|
||||
#[cfg(feature = "mock_data")]
|
||||
use cstr_core::{CStr, CString};
|
||||
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
#[cfg(not(feature = "mock_data"))]
|
||||
|
|
Loading…
Reference in New Issue