Implements first few actual move effects.
This commit is contained in:
parent
98130706fb
commit
05430c5e84
|
@ -1,5 +1,6 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"pkmn_lib_interface",
|
"pkmn_lib_interface",
|
||||||
|
|
|
@ -12,7 +12,8 @@ use pkmn_lib_interface::set_load_script_fn;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
||||||
pub mod registered_scripts;
|
pub mod registered_scripts;
|
||||||
pub mod test_script;
|
pub mod moves;
|
||||||
|
pub mod util_scripts;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[cfg(not(test))]
|
#[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 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};
|
use pkmn_lib_interface::handling::{Script, ScriptCategory};
|
||||||
|
|
||||||
macro_rules! resolve_match {
|
macro_rules! resolve_match {
|
||||||
(
|
(
|
||||||
$mid:expr,
|
$mid:expr,
|
||||||
$(
|
$(
|
||||||
$key:expr => $script:ident,
|
$script:ty,
|
||||||
)*
|
)*
|
||||||
) => (
|
) => (
|
||||||
match $mid {
|
match $mid {
|
||||||
$(
|
$(
|
||||||
const { get_hash_const($key) } => {
|
const { get_hash(<$script>::get_const_name()) } => {
|
||||||
return Some(Box::new($script {}))
|
return Some(Box::new(<$script>::new()))
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -26,13 +26,18 @@ pub fn get_script(category: ScriptCategory, name: &StringKey) -> Option<Box<dyn
|
||||||
ScriptCategory::Move => {
|
ScriptCategory::Move => {
|
||||||
resolve_match!(
|
resolve_match!(
|
||||||
name.hash(),
|
name.hash(),
|
||||||
b"test" => TestScript,
|
acrobatics::Acrobatics,
|
||||||
|
acupressure::Acupressure,
|
||||||
|
after_you::AfterYou,
|
||||||
|
multi_hit_move::MultiHitMove,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ScriptCategory::Ability => {}
|
ScriptCategory::Ability => {}
|
||||||
ScriptCategory::Status => {}
|
ScriptCategory::Status => {}
|
||||||
ScriptCategory::Pokemon => {}
|
ScriptCategory::Pokemon => {}
|
||||||
ScriptCategory::Battle => {}
|
ScriptCategory::Battle => {
|
||||||
|
resolve_match!(name.hash(), crate::util_scripts::ForceEffectTriggerScript,)
|
||||||
|
}
|
||||||
ScriptCategory::Side => {}
|
ScriptCategory::Side => {}
|
||||||
ScriptCategory::ItemBattleTrigger => {}
|
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]
|
[dependencies]
|
||||||
wee_alloc = "0.4.5"
|
wee_alloc = "0.4.5"
|
||||||
cstr_core = { version = "0.2.6", features = ["nightly"]}
|
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 }
|
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" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[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::cached_value::CachedValue;
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::Cacheable;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -13,6 +13,7 @@ struct BattleInner {
|
||||||
parties: CachedValue<ImmutableList<BattleParty>>,
|
parties: CachedValue<ImmutableList<BattleParty>>,
|
||||||
sides: CachedValue<ImmutableList<BattleSide>>,
|
sides: CachedValue<ImmutableList<BattleSide>>,
|
||||||
random: CachedValue<BattleRandom>,
|
random: CachedValue<BattleRandom>,
|
||||||
|
choice_queue: CachedValue<ChoiceQueue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -30,6 +31,9 @@ impl Battle {
|
||||||
parties: cached_value!({ battle_get_parties(reference).get_immutable_list() }),
|
parties: cached_value!({ battle_get_parties(reference).get_immutable_list() }),
|
||||||
sides: cached_value!({ battle_get_sides(reference).get_immutable_list() }),
|
sides: cached_value!({ battle_get_sides(reference).get_immutable_list() }),
|
||||||
random: cached_value!({ battle_get_random(reference).get_value().unwrap() }),
|
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 library(&self) -> DynamicLibrary;
|
||||||
pub fn parties(&self) -> ImmutableList<BattleParty>;
|
pub fn parties(&self) -> ImmutableList<BattleParty>;
|
||||||
pub fn sides(&self) -> ImmutableList<BattleSide>;
|
pub fn sides(&self) -> ImmutableList<BattleSide>;
|
||||||
|
pub fn random(&self) -> BattleRandom;
|
||||||
|
pub fn choice_queue(&self) -> ChoiceQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
@ -72,5 +78,6 @@ extern "wasm" {
|
||||||
fn battle_get_parties(r: ExternRef<Battle>) -> VecExternRef<BattleParty>;
|
fn battle_get_parties(r: ExternRef<Battle>) -> VecExternRef<BattleParty>;
|
||||||
fn battle_get_sides(r: ExternRef<Battle>) -> VecExternRef<BattleSide>;
|
fn battle_get_sides(r: ExternRef<Battle>) -> VecExternRef<BattleSide>;
|
||||||
fn battle_get_random(r: ExternRef<Battle>) -> ExternRef<BattleRandom>;
|
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>;
|
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"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn battle_party_get_party(r: ExternRef<BattleParty>) -> ExternRef<Party>;
|
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_party;
|
||||||
mod battle_random;
|
mod battle_random;
|
||||||
mod battle_side;
|
mod battle_side;
|
||||||
|
mod choice_queue;
|
||||||
mod dynamic_library;
|
mod dynamic_library;
|
||||||
|
mod executing_move;
|
||||||
mod learned_move;
|
mod learned_move;
|
||||||
mod party;
|
mod party;
|
||||||
mod pokemon;
|
mod pokemon;
|
||||||
|
@ -13,7 +15,9 @@ pub use battle::*;
|
||||||
pub use battle_party::*;
|
pub use battle_party::*;
|
||||||
pub use battle_random::*;
|
pub use battle_random::*;
|
||||||
pub use battle_side::*;
|
pub use battle_side::*;
|
||||||
|
pub use choice_queue::*;
|
||||||
pub use dynamic_library::DynamicLibrary;
|
pub use dynamic_library::DynamicLibrary;
|
||||||
|
pub use executing_move::*;
|
||||||
pub use learned_move::*;
|
pub use learned_move::*;
|
||||||
pub use party::*;
|
pub use party::*;
|
||||||
pub use pokemon::*;
|
pub use pokemon::*;
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::Cacheable;
|
||||||
use crate::{
|
use crate::{
|
||||||
cached_value, cached_value_getters, wasm_optional_reference_getters, wasm_reference_getters,
|
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::boxed::Box;
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
@ -61,6 +61,10 @@ impl Pokemon {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn reference(&self) -> ExternRef<Self> {
|
||||||
|
self.inner.reference
|
||||||
|
}
|
||||||
|
|
||||||
cached_value_getters! {
|
cached_value_getters! {
|
||||||
pub fn library(&self) -> DynamicLibrary;
|
pub fn library(&self) -> DynamicLibrary;
|
||||||
pub fn flat_stats(&self) -> StatisticSet<u32>;
|
pub fn flat_stats(&self) -> StatisticSet<u32>;
|
||||||
|
@ -101,8 +105,8 @@ impl Pokemon {
|
||||||
unsafe { pokemon_get_type(self.inner.reference, index) }
|
unsafe { pokemon_get_type(self.inner.reference, index) }
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn has_type(&self, type_identifier: u8) -> bool {
|
pub fn has_type(&self, type_identifier: TypeIdentifier) -> bool {
|
||||||
unsafe { pokemon_has_type(self.inner.reference, type_identifier) }
|
unsafe { pokemon_has_type(self.inner.reference, type_identifier.into()) }
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn has_type_by_name(&self, type_name: &str) -> bool {
|
pub fn has_type_by_name(&self, type_name: &str) -> bool {
|
||||||
|
@ -206,6 +210,12 @@ wasm_value_getters! {
|
||||||
pub fn is_usable(&self) -> bool;
|
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.
|
/// A source of damage. This should be as unique as possible.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
@ -246,6 +256,7 @@ extern "wasm" {
|
||||||
diff_amount: i8,
|
diff_amount: i8,
|
||||||
self_inflicted: bool,
|
self_inflicted: bool,
|
||||||
) -> bool;
|
) -> bool;
|
||||||
|
#[allow(improper_ctypes)]
|
||||||
fn pokemon_get_ability_script(r: ExternRef<Pokemon>) -> *const Box<dyn Script>;
|
fn pokemon_get_ability_script(r: ExternRef<Pokemon>) -> *const Box<dyn Script>;
|
||||||
fn pokemon_change_species(
|
fn pokemon_change_species(
|
||||||
r: ExternRef<Pokemon>,
|
r: ExternRef<Pokemon>,
|
||||||
|
|
|
@ -3,10 +3,9 @@ use crate::handling::cached_value::CachedValue;
|
||||||
use crate::handling::temporary::Temporary;
|
use crate::handling::temporary::Temporary;
|
||||||
use crate::ExternRef;
|
use crate::ExternRef;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[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"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::rc::Rc;
|
|
||||||
|
|
||||||
struct BaseTurnChoiceData {
|
struct BaseTurnChoiceData {
|
||||||
reference: ExternRef<TurnChoice>,
|
reference: ExternRef<TurnChoice>,
|
||||||
|
@ -19,12 +18,10 @@ struct MoveTurnChoiceDataInner {
|
||||||
target_side: CachedValue<u8>,
|
target_side: CachedValue<u8>,
|
||||||
target_index: CachedValue<u8>,
|
target_index: CachedValue<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct MoveTurnChoiceDataTemporary {
|
|
||||||
inner: Rc<MoveTurnChoiceDataInner>,
|
|
||||||
}
|
|
||||||
pub struct MoveTurnChoiceData {
|
pub struct MoveTurnChoiceData {
|
||||||
temp: Temporary<MoveTurnChoiceDataTemporary>,
|
inner: Temporary<MoveTurnChoiceDataInner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum TurnChoice {
|
pub enum TurnChoice {
|
||||||
|
@ -38,7 +35,7 @@ pub enum TurnChoice {
|
||||||
impl TurnChoice {
|
impl TurnChoice {
|
||||||
fn base(&self) -> &BaseTurnChoiceData {
|
fn base(&self) -> &BaseTurnChoiceData {
|
||||||
match self {
|
match self {
|
||||||
TurnChoice::Move(d) => &d.temp.value_ref().inner.base,
|
TurnChoice::Move(d) => &d.inner.value_ref().base,
|
||||||
TurnChoice::Item() => unimplemented!(),
|
TurnChoice::Item() => unimplemented!(),
|
||||||
TurnChoice::Switch() => unimplemented!(),
|
TurnChoice::Switch() => unimplemented!(),
|
||||||
TurnChoice::Flee => unimplemented!(),
|
TurnChoice::Flee => unimplemented!(),
|
||||||
|
@ -68,22 +65,22 @@ impl TurnChoice {
|
||||||
|
|
||||||
impl MoveTurnChoiceData {
|
impl MoveTurnChoiceData {
|
||||||
pub fn used_move(&self) -> LearnedMove {
|
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 {
|
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 {
|
pub fn target_index(&self) -> u8 {
|
||||||
self.temp.value().inner.target_index.value()
|
self.inner.value().target_index.value()
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn priority(&self) -> i8 {
|
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"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn move_script(&self) -> Option<&Box<dyn Script>> {
|
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) };
|
let kind = unsafe { turn_choice_get_kind(reference) };
|
||||||
match kind {
|
match kind {
|
||||||
0 => TurnChoice::Move(MoveTurnChoiceData {
|
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"),
|
_ => panic!("Unknown turn choice type"),
|
||||||
}
|
}
|
||||||
|
@ -101,24 +101,22 @@ impl ExternalReferenceType for TurnChoice {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
impl ExternalReferenceType for MoveTurnChoiceDataTemporary {
|
impl MoveTurnChoiceDataInner {
|
||||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
fn from_reference(reference: ExternRef<MoveTurnChoiceData>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Rc::new(MoveTurnChoiceDataInner {
|
base: BaseTurnChoiceData {
|
||||||
base: BaseTurnChoiceData {
|
reference: reference.cast(),
|
||||||
reference: reference.cast(),
|
user: cached_value!({
|
||||||
user: cached_value!({
|
turn_choice_get_user(reference.cast()).get_value().unwrap()
|
||||||
turn_choice_get_user(reference.cast()).get_value().unwrap()
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
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()) }),
|
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_side(r: ExternRef<MoveTurnChoiceData>) -> u8;
|
||||||
fn turn_choice_move_target_index(r: ExternRef<MoveTurnChoiceData>) -> u8;
|
fn turn_choice_move_target_index(r: ExternRef<MoveTurnChoiceData>) -> u8;
|
||||||
fn turn_choice_move_priority(r: ExternRef<MoveTurnChoiceData>) -> i8;
|
fn turn_choice_move_priority(r: ExternRef<MoveTurnChoiceData>) -> i8;
|
||||||
|
#[allow(improper_ctypes)]
|
||||||
fn turn_choice_move_script(r: ExternRef<MoveTurnChoiceData>) -> *const Box<dyn Script>;
|
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 crate::{ExternalReferenceType, VecExternRef};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::collections::BTreeMap;
|
#[cfg(feature = "mock_data")]
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
@ -44,13 +44,22 @@ where
|
||||||
|
|
||||||
pub(crate) fn from_ref(extern_ref: VecExternRef<T>) -> Self {
|
pub(crate) fn from_ref(extern_ref: VecExternRef<T>) -> Self {
|
||||||
unsafe {
|
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 {
|
if let Some(v) = existing {
|
||||||
let inner = *v as *const ImmutableListInner<T>;
|
let inner = *v as *const ImmutableListInner<T>;
|
||||||
ImmutableList { inner }
|
ImmutableList { inner }
|
||||||
} else {
|
} else {
|
||||||
let v = Self::new(extern_ref);
|
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
|
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 dynamic_data::*;
|
||||||
pub use static_data::*;
|
pub use static_data::*;
|
||||||
pub use string_key::get_hash_const;
|
pub use string_key::*;
|
||||||
pub use string_key::StringKey;
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
use crate::app_interface::{DataLibrary, Item};
|
use crate::app_interface::{DataLibrary, Item};
|
||||||
use crate::{ExternRef, ExternalReferenceType, StringKey};
|
use crate::{ExternRef, ExternalReferenceType, StringKey};
|
||||||
use alloc::collections::BTreeMap;
|
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use spin::rwlock::RwLock;
|
use spin::rwlock::RwLock;
|
||||||
|
|
||||||
struct ItemLibraryInner {
|
struct ItemLibraryInner {
|
||||||
ptr: ExternRef<ItemLibrary>,
|
ptr: ExternRef<ItemLibrary>,
|
||||||
cache: RwLock<BTreeMap<u32, Item>>,
|
cache: RwLock<hashbrown::HashMap<u32, Item>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -27,7 +26,7 @@ impl ItemLibrary {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DataLibrary<Item> for 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
|
&self.inner.cache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::{cached_value, cached_value_getters, ExternRef, ExternalReferenceType, StringKey};
|
use crate::{cached_value, cached_value_getters, ExternRef, ExternalReferenceType, StringKey};
|
||||||
use alloc::collections::BTreeMap;
|
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use move_library::MoveLibrary;
|
use move_library::MoveLibrary;
|
||||||
use spin::rwlock::RwLock;
|
use spin::rwlock::RwLock;
|
||||||
|
@ -51,6 +50,11 @@ impl StaticData {
|
||||||
type_library: cached_value!({
|
type_library: cached_value!({
|
||||||
static_data_get_type_library(reference).get_value().unwrap()
|
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"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
impl ExternalReferenceType for StaticData {
|
impl ExternalReferenceType for StaticData {
|
||||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
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"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
extern "wasm" {
|
extern "wasm" {
|
||||||
fn static_data_get_move_library(ptr: ExternRef<StaticData>) -> ExternRef<MoveLibrary>;
|
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_item_library(ptr: ExternRef<StaticData>) -> ExternRef<ItemLibrary>;
|
||||||
fn static_data_get_species_library(ptr: ExternRef<StaticData>) -> ExternRef<SpeciesLibrary>;
|
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_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;
|
fn library_settings_get_maximum_level(ptr: ExternRef<LibrarySettings>) -> LevelInt;
|
||||||
}
|
}
|
||||||
|
@ -141,7 +153,7 @@ where
|
||||||
T: ExternalReferenceType,
|
T: ExternalReferenceType,
|
||||||
T: Clone,
|
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>
|
fn get_self_ref(&self) -> ExternRef<Self>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
@ -188,7 +200,7 @@ pub trait DataLibrary<T>: Cacheable
|
||||||
where
|
where
|
||||||
T: Clone,
|
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>
|
fn get_self_ref(&self) -> ExternRef<Self>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
use crate::app_interface::data_libraries::DataLibrary;
|
use crate::app_interface::data_libraries::DataLibrary;
|
||||||
use crate::app_interface::{MoveData, StringKey};
|
use crate::app_interface::{MoveData, StringKey};
|
||||||
use crate::{ExternRef, ExternalReferenceType};
|
use crate::{ExternRef, ExternalReferenceType};
|
||||||
use alloc::collections::BTreeMap;
|
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use spin::RwLock;
|
use spin::RwLock;
|
||||||
|
|
||||||
struct MoveLibraryInner {
|
struct MoveLibraryInner {
|
||||||
ptr: ExternRef<MoveLibrary>,
|
ptr: ExternRef<MoveLibrary>,
|
||||||
cache: RwLock<BTreeMap<u32, MoveData>>,
|
cache: RwLock<hashbrown::HashMap<u32, MoveData>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -38,7 +37,7 @@ impl MoveLibrary {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DataLibrary<MoveData> for 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
|
&self.inner.cache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
use crate::app_interface::{DataLibrary, Species};
|
use crate::app_interface::{DataLibrary, Species};
|
||||||
use crate::{ExternRef, ExternalReferenceType, StringKey};
|
use crate::{ExternRef, ExternalReferenceType, StringKey};
|
||||||
use alloc::collections::BTreeMap;
|
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use spin::RwLock;
|
use spin::RwLock;
|
||||||
|
|
||||||
struct SpeciesLibraryInner {
|
struct SpeciesLibraryInner {
|
||||||
ptr: ExternRef<SpeciesLibrary>,
|
ptr: ExternRef<SpeciesLibrary>,
|
||||||
cache: RwLock<BTreeMap<u32, Species>>,
|
cache: RwLock<hashbrown::HashMap<u32, Species>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -37,7 +36,7 @@ impl SpeciesLibrary {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DataLibrary<Species> for 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
|
&self.inner.cache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::{ExternRef, ExternalReferenceType};
|
use crate::{ExternRef, ExternalReferenceType, TypeIdentifier};
|
||||||
use alloc::collections::BTreeMap;
|
|
||||||
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};
|
||||||
|
@ -7,8 +6,8 @@ use spin::RwLock;
|
||||||
|
|
||||||
struct TypeLibraryInner {
|
struct TypeLibraryInner {
|
||||||
reference: ExternRef<TypeLibrary>,
|
reference: ExternRef<TypeLibrary>,
|
||||||
name_to_type_cache: RwLock<BTreeMap<String, u8>>,
|
name_to_type_cache: RwLock<hashbrown::HashMap<String, TypeIdentifier>>,
|
||||||
effectiveness_cache: RwLock<BTreeMap<(u8, u8), f32>>,
|
effectiveness_cache: RwLock<hashbrown::HashMap<(TypeIdentifier, TypeIdentifier), f32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -39,7 +38,7 @@ impl TypeLibrary {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[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) {
|
if let Some(cached) = self.inner.name_to_type_cache.read().get(name) {
|
||||||
return Some(*cached);
|
return Some(*cached);
|
||||||
}
|
}
|
||||||
|
@ -48,6 +47,7 @@ impl TypeLibrary {
|
||||||
if v == 255 {
|
if v == 255 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
let v = v.into();
|
||||||
self.inner
|
self.inner
|
||||||
.name_to_type_cache
|
.name_to_type_cache
|
||||||
.write()
|
.write()
|
||||||
|
@ -56,7 +56,11 @@ impl TypeLibrary {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[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
|
if let Some(cached) = self
|
||||||
.inner
|
.inner
|
||||||
.effectiveness_cache
|
.effectiveness_cache
|
||||||
|
@ -68,8 +72,8 @@ impl TypeLibrary {
|
||||||
let effectiveness = unsafe {
|
let effectiveness = unsafe {
|
||||||
type_library_get_single_effectiveness(
|
type_library_get_single_effectiveness(
|
||||||
self.inner.reference,
|
self.inner.reference,
|
||||||
attacking_type,
|
attacking_type.into(),
|
||||||
defending_type,
|
defending_type.into(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
self.inner
|
self.inner
|
||||||
|
@ -80,7 +84,11 @@ impl TypeLibrary {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[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;
|
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);
|
||||||
|
|
|
@ -96,7 +96,7 @@ crate::handling::cacheable::cacheable!(Item);
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
impl ExternalReferenceType for Item {
|
impl ExternalReferenceType for Item {
|
||||||
fn from_extern_value(reference: ExternRef<Self>) -> Self {
|
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 use species::*;
|
||||||
|
|
||||||
pub type LevelInt = u8;
|
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::cached_value::CachedValue;
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::Cacheable;
|
||||||
use crate::{cached_value, cached_value_getters, ExternRef, ExternalReferenceType};
|
use crate::{cached_value, cached_value_getters, ExternRef, ExternalReferenceType};
|
||||||
|
@ -104,8 +104,8 @@ impl MoveData {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn has_flag<const N: usize>(&self, flag: &[u8; N]) -> bool {
|
pub fn has_flag(&self, flag: &str) -> bool {
|
||||||
let hash = get_hash_const(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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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::cached_value::CachedValue;
|
||||||
use crate::handling::Cacheable;
|
use crate::handling::Cacheable;
|
||||||
use crate::{
|
use crate::{
|
||||||
cached_value, cached_value_getters, ExternRef, ExternalReferenceType, FFIArray, ImmutableList,
|
cached_value, cached_value_getters, ExternRef, ExternalReferenceType, FFIArray, ImmutableList,
|
||||||
StringKey, VecExternRef,
|
StringKey, VecExternRef,
|
||||||
};
|
};
|
||||||
use alloc::collections::BTreeMap;
|
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use spin::RwLock;
|
use spin::RwLock;
|
||||||
|
@ -147,8 +146,8 @@ impl Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn has_flag<const N: usize>(&self, flag: &[u8; N]) -> bool {
|
pub fn has_flag(&self, flag: &str) -> bool {
|
||||||
let hash = get_hash_const(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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,7 +159,7 @@ pub struct SpeciesInner {
|
||||||
gender_rate: CachedValue<f32>,
|
gender_rate: CachedValue<f32>,
|
||||||
growth_rate: CachedValue<StringKey>,
|
growth_rate: CachedValue<StringKey>,
|
||||||
capture_rate: CachedValue<u8>,
|
capture_rate: CachedValue<u8>,
|
||||||
forms: RwLock<BTreeMap<u32, Option<Form>>>,
|
forms: RwLock<hashbrown::HashMap<u32, Option<Form>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -205,8 +204,8 @@ impl Species {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn get_form<const N: usize>(&self, form_name: &[u8; N]) -> Option<Form> {
|
pub fn get_form(&self, form_name: &str) -> Option<Form> {
|
||||||
let hash = get_hash_const(form_name);
|
let hash = get_hash(form_name);
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(v) = self.inner.forms.read().get(&hash) {
|
if let Some(v) = self.inner.forms.read().get(&hash) {
|
||||||
v.clone()
|
v.clone()
|
||||||
|
@ -220,8 +219,8 @@ impl Species {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub fn has_flag<const N: usize>(&self, flag: &[u8; N]) -> bool {
|
pub fn has_flag(&self, flag: &str) -> bool {
|
||||||
let hash = get_hash_const(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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ impl StringKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub(super) fn ptr(&self) -> ExternRef<Self> {
|
pub(crate) fn ptr(&self) -> ExternRef<Self> {
|
||||||
self.data.ptr
|
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);
|
crate::handling::cacheable::cacheable!(StringKey);
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
@ -134,23 +140,12 @@ const fn to_lower(c: u8) -> u8 {
|
||||||
c
|
c
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn get_hash_const<const N: usize>(s: &[u8; N]) -> u32 {
|
pub const fn get_hash(s: &str) -> 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 {
|
|
||||||
let mut crc: u32 = 0xffffffff;
|
let mut crc: u32 = 0xffffffff;
|
||||||
|
|
||||||
let mut i: usize = 0;
|
let mut i: usize = 0;
|
||||||
while i < s.len() {
|
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;
|
i += 1;
|
||||||
}
|
}
|
||||||
crc ^ 0xffffffff
|
crc ^ 0xffffffff
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
use crate::ExternRef;
|
use crate::ExternRef;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
|
||||||
use alloc::collections::BTreeMap;
|
|
||||||
|
|
||||||
pub trait Cacheable {
|
pub trait Cacheable {
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[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
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
|
||||||
|
@ -19,21 +17,28 @@ pub trait Cacheable {
|
||||||
if let Some(v) = opt {
|
if let Some(v) = opt {
|
||||||
return v.clone();
|
return v.clone();
|
||||||
}
|
}
|
||||||
Self::get_cache().insert(ptr, ctor(ptr));
|
let value = ctor(ptr);
|
||||||
return Self::get_cache().get(&ptr).unwrap().clone();
|
Self::get_cache().insert(ptr, value.clone());
|
||||||
|
value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! cacheable {
|
macro_rules! cacheable {
|
||||||
($type: ty) => {
|
($type: ty) => {
|
||||||
paste::paste!{
|
paste::paste! {
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
static mut [<$type:upper _CACHE>]: alloc::collections::BTreeMap<ExternRef<$type>, $type> =
|
static mut [<$type:upper _CACHE>]: Option<hashbrown::HashMap<ExternRef<$type>, $type>> =
|
||||||
alloc::collections::BTreeMap::new();
|
None;
|
||||||
impl crate::handling::Cacheable for $type {
|
impl crate::handling::Cacheable for $type {
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
fn get_cache<'a>() -> &'a mut alloc::collections::BTreeMap<ExternRef<$type>, $type> {
|
fn get_cache<'a>() -> &'a mut hashbrown::HashMap<ExternRef<$type>, $type> {
|
||||||
unsafe { &mut [<$type:upper _CACHE>] }
|
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)]
|
#[repr(u8)]
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum ScriptCapabilities {
|
pub enum ScriptCapabilities {
|
||||||
|
None = 0,
|
||||||
Initialize = 1,
|
Initialize = 1,
|
||||||
OnStack,
|
OnStack,
|
||||||
OnRemove,
|
OnRemove,
|
||||||
OnBeforeTurn,
|
OnBeforeTurn,
|
||||||
ChangeAttack,
|
ChangeMove,
|
||||||
ModifyNumberOfHits,
|
ChangeNumberOfHits,
|
||||||
PreventAttack,
|
PreventMove,
|
||||||
FailAttack,
|
FailMove,
|
||||||
StopBeforeAttack,
|
StopBeforeMove,
|
||||||
OnBeforeAttack,
|
OnBeforeMove,
|
||||||
FailIncomingAttack,
|
FailIncomingMove,
|
||||||
IsInvulnerable,
|
IsInvulnerable,
|
||||||
OnAttackMiss,
|
OnMoveMiss,
|
||||||
ChangeAttackType,
|
ChangeMoveType,
|
||||||
ChangeEffectiveness,
|
ChangeEffectiveness,
|
||||||
BlockCritical,
|
BlockCritical,
|
||||||
OnIncomingHit,
|
OnIncomingHit,
|
||||||
OnFaintingOpponent,
|
OnFaintingOpponent,
|
||||||
PreventStatBoostChange,
|
PreventStatBoostChange,
|
||||||
ModifyStatBoostChange,
|
ChangeStatBoostChange,
|
||||||
PreventSecondaryEffects,
|
PreventSecondaryEffects,
|
||||||
OnSecondaryEffect,
|
OnSecondaryEffect,
|
||||||
OnAfterHits,
|
OnAfterHits,
|
||||||
PreventSelfSwitch,
|
PreventSelfSwitch,
|
||||||
ModifyEffectChance,
|
ChangeEffectChance,
|
||||||
ModifyIncomingEffectChance,
|
ChangeIncomingEffectChance,
|
||||||
OverrideBasePower,
|
ChangeBasePower,
|
||||||
ChangeDamageStatsUser,
|
ChangeDamageStatsUser,
|
||||||
BypassDefensiveStat,
|
BypassDefensiveStat,
|
||||||
BypassOffensiveStat,
|
BypassOffensiveStat,
|
||||||
ModifyStatModifier,
|
ChangeStatModifier,
|
||||||
ModifyDamageModifier,
|
ChangeDamageModifier,
|
||||||
OverrideDamage,
|
ChangeDamage,
|
||||||
OverrideIncomingDamage,
|
ChangeIncomingDamage,
|
||||||
ChangeSpeed,
|
ChangeSpeed,
|
||||||
ChangePriority,
|
ChangePriority,
|
||||||
OnFail,
|
OnFail,
|
||||||
OnOpponentFail,
|
OnOpponentFail,
|
||||||
PreventRunAway,
|
PreventSelfRunAway,
|
||||||
PreventOpponentRunAway,
|
PreventOpponentRunAway,
|
||||||
PreventOpponentSwitch,
|
PreventOpponentSwitch,
|
||||||
OnEndTurn,
|
OnEndTurn,
|
||||||
OnDamage,
|
OnDamage,
|
||||||
OnFaint,
|
OnFaint,
|
||||||
OnAfterHeldItemConsume,
|
OnAfterHeldItemConsume,
|
||||||
PreventIncomingCritical,
|
BlockIncomingCritical,
|
||||||
ModifyCriticalStage,
|
ChangeAccuracy,
|
||||||
OverrideCriticalModifier,
|
ChangeCriticalStage,
|
||||||
OverrideSTABModifier,
|
ChangeCriticalModifier,
|
||||||
ModifyExperienceGain,
|
ChangeSTABModifier,
|
||||||
|
ChangeExperienceGain,
|
||||||
DoesShareExperience,
|
DoesShareExperience,
|
||||||
BlockWeather,
|
BlockWeather,
|
||||||
OnSwitchIn,
|
OnSwitchIn,
|
||||||
ModifyOffensiveStatValue,
|
ChangeOffensiveStatValue,
|
||||||
ModifyDefensiveStatValue,
|
ChangeDefensiveStatValue,
|
||||||
|
ChangeCaptureRate,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::ImmutableList;
|
use crate::ImmutableList;
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
|
use core::hash::{Hash, Hasher};
|
||||||
use core::intrinsics::transmute;
|
use core::intrinsics::transmute;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
@ -28,6 +29,16 @@ impl<T> ExternRef<T> {
|
||||||
T::instantiate_from_extern_value(*self)
|
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]
|
#[inline]
|
||||||
pub(crate) fn cast<TCast>(&self) -> ExternRef<TCast> {
|
pub(crate) fn cast<TCast>(&self) -> ExternRef<TCast> {
|
||||||
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)]
|
#[repr(C)]
|
||||||
pub struct VecExternRef<T> {
|
pub struct VecExternRef<T> {
|
||||||
v: u64,
|
v: u64,
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::app_interface::list::ImmutableList;
|
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::handling::ScriptCapabilities;
|
||||||
use crate::{ExternRef, TurnChoice};
|
use crate::{ExternRef, StringKey, TurnChoice, TypeIdentifier};
|
||||||
use core::ffi::c_void;
|
use core::ffi::c_void;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
|
||||||
|
@ -9,17 +11,338 @@ pub trait Script {
|
||||||
fn new() -> Self
|
fn new() -> Self
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn destroy(&self);
|
fn get_name() -> &'static str
|
||||||
fn get_name(&self) -> &str;
|
where
|
||||||
|
Self: Sized;
|
||||||
fn get_capabilities(&self) -> &[ScriptCapabilities];
|
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(
|
fn on_initialize(
|
||||||
&self,
|
&self,
|
||||||
_library: &DynamicLibrary,
|
_library: &DynamicLibrary,
|
||||||
_parameters: Option<ImmutableList<EffectParameter>>,
|
_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) {}
|
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 {
|
impl Debug for dyn Script {
|
||||||
|
|
|
@ -1,80 +1,63 @@
|
||||||
use crate::{ExternRef, ExternalReferenceType};
|
use alloc::rc::Rc;
|
||||||
use alloc::boxed::Box;
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
use core::cell::Cell;
|
|
||||||
use core::mem::forget;
|
|
||||||
|
|
||||||
struct TemporaryData<T> {
|
|
||||||
use_count: Cell<usize>,
|
|
||||||
is_deleted: bool,
|
|
||||||
value: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
pub struct Temporary<T> {
|
pub struct Temporary<T> {
|
||||||
value: *mut TemporaryData<T>,
|
is_deleted: Rc<AtomicBool>,
|
||||||
|
value: Rc<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
static mut TEMPORARIES: alloc::collections::BTreeMap<u32, *const u8> =
|
static mut TEMPORARIES: Option<hashbrown::HashMap<u32, Rc<AtomicBool>>> = None;
|
||||||
alloc::collections::BTreeMap::new();
|
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
impl<T> Temporary<T>
|
impl<T> Temporary<T> {
|
||||||
where
|
|
||||||
T: ExternalReferenceType,
|
|
||||||
T: Clone,
|
|
||||||
{
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_reference(reference: ExternRef<T>) -> Self {
|
pub fn new(reference: u32, value: T) -> Self {
|
||||||
let temporaries = unsafe { &mut TEMPORARIES };
|
|
||||||
let existing = temporaries.get(&reference.get_internal_index());
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(v) = existing {
|
if let None = TEMPORARIES {
|
||||||
let rc = (*v as *mut TemporaryData<T>).as_mut().unwrap();
|
TEMPORARIES = Some(hashbrown::HashMap::new());
|
||||||
if !rc.is_deleted {
|
|
||||||
*rc.use_count.get_mut() += 1;
|
|
||||||
return Self {
|
|
||||||
value: rc as *mut TemporaryData<T>,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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 value = Rc::new(value);
|
||||||
let mut reference_counter = TemporaryData {
|
let is_deleted = Rc::new(AtomicBool::new(false));
|
||||||
use_count: Cell::new(1),
|
temporaries.insert(reference, is_deleted.clone());
|
||||||
is_deleted: false,
|
Self { is_deleted, value }
|
||||||
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 }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn value(&self) -> T {
|
pub fn value(&self) -> Rc<T> {
|
||||||
unsafe { self.value.as_ref().unwrap().value.clone() }
|
if self.is_deleted.load(Ordering::SeqCst) {
|
||||||
|
panic!("Accessed value after it had been deleted");
|
||||||
|
}
|
||||||
|
self.value.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn value_ref(&self) -> &T {
|
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 temporaries = unsafe { &mut TEMPORARIES };
|
||||||
let existing = temporaries.get(&reference.get_internal_index());
|
let existing = temporaries.as_mut().unwrap().get_mut(&reference);
|
||||||
unsafe {
|
if let Some(v) = existing {
|
||||||
if let Some(v) = existing {
|
v.store(false, Ordering::SeqCst);
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,32 +65,28 @@ where
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
impl<T> Clone for Temporary<T> {
|
impl<T> Clone for Temporary<T> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*unsafe { self.value.as_mut() }.unwrap().use_count.get_mut() += 1;
|
Self {
|
||||||
Self { value: self.value }
|
is_deleted: self.is_deleted.clone(),
|
||||||
}
|
value: self.value.clone(),
|
||||||
}
|
|
||||||
|
|
||||||
#[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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "mock_data")]
|
#[no_mangle]
|
||||||
pub struct Temporary<T: Clone> {
|
#[cfg(not(feature = "mock_data"))]
|
||||||
value: T,
|
unsafe extern "wasm" fn _mark_deleted(r: u32) {
|
||||||
|
Temporary::<u8>::mark_as_deleted(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "mock_data")]
|
#[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]
|
#[inline]
|
||||||
pub fn value(&self) -> T {
|
pub fn value(&self) -> Rc<T> {
|
||||||
self.value.clone()
|
self.value.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,3 +95,12 @@ impl<T: Clone> Temporary<T> {
|
||||||
&self.value
|
&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(wasm_abi)]
|
||||||
#![feature(thread_local)]
|
#![feature(thread_local)]
|
||||||
#![feature(build_hasher_simple_hash_one)]
|
#![feature(build_hasher_simple_hash_one)]
|
||||||
|
#![feature(adt_const_params)]
|
||||||
#![cfg_attr(not(feature = "mock_data"), no_std)]
|
#![cfg_attr(not(feature = "mock_data"), no_std)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
@ -23,7 +24,12 @@ extern crate wee_alloc;
|
||||||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||||
|
|
||||||
use crate::app_interface::list::ImmutableList;
|
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::*;
|
pub(crate) use crate::handling::extern_ref::*;
|
||||||
use crate::handling::ffi_array::FFIArray;
|
use crate::handling::ffi_array::FFIArray;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
@ -47,61 +53,565 @@ pub fn set_load_script_fn(f: LoadScriptFnType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
macro_rules! exported_functions {
|
||||||
#[cfg(not(feature = "mock_data"))]
|
(
|
||||||
extern "wasm" fn load_script(category: ScriptCategory, name: ExternRef<StringKey>) -> u32 {
|
$(
|
||||||
|
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 name_c = StringKey::new(name);
|
||||||
let boxed_script = unsafe { &LOAD_SCRIPT_FN }.as_ref().unwrap()(category, &name_c);
|
let boxed_script = unsafe { &LOAD_SCRIPT_FN }.as_ref().unwrap()(category, &name_c);
|
||||||
if boxed_script.is_none() {
|
if boxed_script.is_none() {
|
||||||
return 0;
|
return ScriptPtr::new(core::ptr::null());
|
||||||
}
|
}
|
||||||
let b = Box::new(boxed_script.unwrap());
|
let b = Box::new(boxed_script.unwrap());
|
||||||
Box::into_raw(b) as u32
|
ScriptPtr::new(Box::into_raw(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
fn destroy_script(script: *mut Box<dyn Script>) {
|
||||||
#[cfg(not(feature = "mock_data"))]
|
|
||||||
unsafe extern "wasm" 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.
|
// 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.
|
// This lets Rust do the cleanup.
|
||||||
let boxed_script = Box::from_raw(script);
|
let boxed_script = Box::from_raw(script);
|
||||||
boxed_script.destroy();
|
drop(boxed_script);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
fn get_script_capabilities(script: ScriptPtr) -> FFIArray<ScriptCapabilities> {
|
||||||
#[cfg(not(feature = "mock_data"))]
|
let c = script.val().get_capabilities();
|
||||||
unsafe extern "wasm" fn get_script_capabilities(
|
|
||||||
script: *const Box<dyn Script>,
|
|
||||||
) -> FFIArray<ScriptCapabilities> {
|
|
||||||
let c = script.as_ref().unwrap().get_capabilities();
|
|
||||||
FFIArray::new(c)
|
FFIArray::new(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
fn script_stack(script: ScriptPtr) {
|
||||||
#[cfg(not(feature = "mock_data"))]
|
script.val().stack();
|
||||||
unsafe extern "wasm" fn script_on_initialize(
|
}
|
||||||
script: *const Box<dyn Script>,
|
|
||||||
|
fn script_on_remove(script: ScriptPtr) {
|
||||||
|
script.val().on_remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn script_on_initialize(
|
||||||
|
script: ScriptPtr,
|
||||||
library: ExternRef<DynamicLibrary>,
|
library: ExternRef<DynamicLibrary>,
|
||||||
parameters: VecExternRef<EffectParameter>,
|
parameters: VecExternRef<EffectParameter>,
|
||||||
) {
|
) {
|
||||||
let lib = DynamicLibrary::new(library);
|
|
||||||
let parameters = ImmutableList::from_ref(parameters);
|
let parameters = ImmutableList::from_ref(parameters);
|
||||||
script
|
script.val().on_initialize(&library.not_null(), Some(parameters));
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.as_ref()
|
|
||||||
.on_initialize(&lib, Some(parameters));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
fn script_on_before_turn(
|
||||||
#[cfg(not(feature = "mock_data"))]
|
script: ScriptPtr,
|
||||||
unsafe extern "wasm" fn script_on_before_turn(
|
|
||||||
script: *const Box<dyn Script>,
|
|
||||||
choice: ExternRef<TurnChoice>,
|
choice: ExternRef<TurnChoice>,
|
||||||
) {
|
) {
|
||||||
script
|
script.val().on_before_turn(choice.not_null())
|
||||||
.as_ref()
|
}
|
||||||
.unwrap()
|
|
||||||
.as_ref()
|
fn script_change_speed(
|
||||||
.on_before_turn(choice.get_value().unwrap())
|
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;
|
use core::alloc::Layout;
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
use core::panic::PanicInfo;
|
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"))]
|
||||||
#[cfg(not(feature = "mock_data"))]
|
#[cfg(not(feature = "mock_data"))]
|
||||||
|
|
Loading…
Reference in New Issue