Implements every script function
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
bd62c1ac62
commit
ba5992e925
|
@ -92,8 +92,8 @@ impl Battle {
|
|||
|
||||
/// Executes a move choice.
|
||||
fn execute_move_choice<'func>(&'func self, choice: &'func TurnChoice) -> PkmnResult<()> {
|
||||
let choice = choice.get_move_turn_data();
|
||||
let used_move = choice.used_move();
|
||||
let move_choice = choice.get_move_turn_data();
|
||||
let used_move = move_choice.used_move();
|
||||
let move_data = {
|
||||
let move_data_lock = used_move;
|
||||
let move_data = move_data_lock.move_data();
|
||||
|
@ -103,7 +103,7 @@ impl Battle {
|
|||
};
|
||||
// FIXME: also change the script on the choice if changed;
|
||||
let target_type = move_data.target();
|
||||
let targets = resolve_targets(choice.target_side(), choice.target_index(), target_type, self);
|
||||
let targets = resolve_targets(move_choice.target_side(), move_choice.target_index(), target_type, self);
|
||||
|
||||
let mut number_of_hits: u8 = 1;
|
||||
script_hook!(change_number_of_hits, choice, choice, &mut number_of_hits);
|
||||
|
@ -116,7 +116,7 @@ impl Battle {
|
|||
choice.user().clone(),
|
||||
used_move.clone(),
|
||||
move_data.clone(),
|
||||
choice.script().clone(),
|
||||
move_choice.script().clone(),
|
||||
);
|
||||
let mut prevented = false;
|
||||
script_hook!(prevent_move, executing_move, &executing_move, &mut prevented);
|
||||
|
|
|
@ -22,6 +22,7 @@ use crate::{script_hook, PkmnResult, StringKey};
|
|||
|
||||
/// A pokemon battle, with any amount of sides and pokemon per side.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
|
||||
pub struct Battle {
|
||||
/// The library the battle uses for handling.
|
||||
library: Arc<DynamicLibrary>,
|
||||
|
|
|
@ -84,6 +84,7 @@ impl HitData {
|
|||
|
||||
/// An executing move is the data of the move for while it is executing.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
|
||||
pub struct ExecutingMove {
|
||||
/// The number of hits this move has.
|
||||
number_of_hits: u8,
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::thread::JoinHandle;
|
|||
|
||||
use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard};
|
||||
|
||||
use crate::dynamic_data::choices::{MoveChoice, TurnChoice};
|
||||
use crate::dynamic_data::choices::TurnChoice;
|
||||
use crate::dynamic_data::DamageSource;
|
||||
use crate::dynamic_data::ExecutingMove;
|
||||
use crate::dynamic_data::Pokemon;
|
||||
|
@ -79,11 +79,11 @@ pub trait Script: Send + Sync {
|
|||
|
||||
/// 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: &MoveChoice, _move_name: &mut StringKey) {}
|
||||
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: &MoveChoice, _number_of_hits: &mut u8) {}
|
||||
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.
|
||||
|
|
|
@ -13,7 +13,7 @@ register! {
|
|||
turn_choice: ExternRef<LearnedMove>,
|
||||
) -> u8 {
|
||||
unsafe {
|
||||
transmute(turn_choice.value(&env).unwrap().learn_method())
|
||||
transmute(turn_choice.value_func(&env).unwrap().learn_method())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,6 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
turn_choice: ExternRef<LearnedMove>,
|
||||
) -> ExternRef<MoveData> {
|
||||
ExternRef::func_new(&env, turn_choice.value(&env).unwrap().move_data())
|
||||
ExternRef::func_new(&env, turn_choice.value_func(&env).unwrap().move_data())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
dynamic_lib: ExternRef<DynamicLibrary>,
|
||||
) -> ExternRef<StaticData> {
|
||||
ExternRef::func_new(&env, dynamic_lib.value(&env).unwrap().static_data())
|
||||
ExternRef::func_new(&env, dynamic_lib.value_func(&env).unwrap().static_data())
|
||||
}
|
||||
manual manual_register
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
) -> ExternRef<DynamicLibrary> {
|
||||
let lib = pokemon.value(&env).unwrap().library();
|
||||
let lib = pokemon.value_func(&env).unwrap().library();
|
||||
ExternRef::func_new(&env, lib)
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
) -> ExternRef<StatisticSet<u32>> {
|
||||
let statistic_set = pokemon.value(&env).unwrap().boosted_stats();
|
||||
let statistic_set = pokemon.value_func(&env).unwrap().boosted_stats();
|
||||
ExternRef::func_new(&env, statistic_set)
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
) -> ExternRef<StatisticSet<u32>> {
|
||||
let statistic_set = pokemon.value(&env).unwrap().flat_stats();
|
||||
let statistic_set = pokemon.value_func(&env).unwrap().flat_stats();
|
||||
ExternRef::func_new(&env, statistic_set)
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
) -> ExternRef<ClampedStatisticSet<i8, -6, 6>> {
|
||||
let statistic_set = pokemon.value(&env).unwrap().stat_boosts();
|
||||
let statistic_set = pokemon.value_func(&env).unwrap().stat_boosts();
|
||||
ExternRef::func_new(&env, statistic_set)
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
) -> ExternRef<ClampedStatisticSet<u8, 0, 31>> {
|
||||
let statistic_set = pokemon.value(&env).unwrap().individual_values();
|
||||
let statistic_set = pokemon.value_func(&env).unwrap().individual_values();
|
||||
ExternRef::func_new(&env, statistic_set)
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
) -> ExternRef<ClampedStatisticSet<u8, 0, 252>> {
|
||||
let statistic_set = pokemon.value(&env).unwrap().effort_values();
|
||||
let statistic_set = pokemon.value_func(&env).unwrap().effort_values();
|
||||
ExternRef::func_new(&env, statistic_set)
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
pokemon: ExternRef<Pokemon>,
|
||||
) -> ExternRef<Species> {
|
||||
let species = pokemon.value(&env).unwrap().species();
|
||||
let species = pokemon.value_func(&env).unwrap().species();
|
||||
ExternRef::func_new(&env, species)
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ register! {
|
|||
source: u8
|
||||
) {
|
||||
unsafe{
|
||||
pokemon.value(&env).unwrap().damage(damage, transmute(source));
|
||||
pokemon.value_func(&env).unwrap().damage(damage, transmute(source));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
turn_choice: ExternRef<TurnChoice>,
|
||||
) -> ExternRef<Pokemon> {
|
||||
let turn_choice = turn_choice.value(&env).unwrap();
|
||||
let turn_choice = turn_choice.value_func(&env).unwrap();
|
||||
ExternRef::func_new(&env, turn_choice.user().as_ref().deref())
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
turn_choice: ExternRef<TurnChoice>,
|
||||
) -> u8 {
|
||||
match turn_choice.value(&env).unwrap() {
|
||||
match turn_choice.value_func(&env).unwrap() {
|
||||
TurnChoice::Move(_) => 0,
|
||||
TurnChoice::Item(_) => 1,
|
||||
TurnChoice::Switch(_) => 2,
|
||||
|
@ -33,7 +33,7 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
turn_choice: ExternRef<TurnChoice>,
|
||||
) -> ExternRef<LearnedMove> {
|
||||
if let TurnChoice::Move(d) = turn_choice.value(&env).unwrap() {
|
||||
if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() {
|
||||
return ExternRef::func_new(&env, d.used_move().as_ref());
|
||||
}
|
||||
panic!("Invalid turn choice");
|
||||
|
@ -43,7 +43,7 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
turn_choice: ExternRef<TurnChoice>,
|
||||
) -> u8 {
|
||||
if let TurnChoice::Move(d) = turn_choice.value(&env).unwrap() {
|
||||
if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() {
|
||||
return d.target_side();
|
||||
}
|
||||
panic!("Invalid turn choice");
|
||||
|
@ -53,7 +53,7 @@ register! {
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
turn_choice: ExternRef<TurnChoice>,
|
||||
) -> u8 {
|
||||
if let TurnChoice::Move(d) = turn_choice.value(&env).unwrap() {
|
||||
if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() {
|
||||
return d.target_index();
|
||||
}
|
||||
panic!("Invalid turn choice");
|
||||
|
|
|
@ -119,13 +119,13 @@ fn _vec_extern_ref_get_value(env: FunctionEnvMut<WebAssemblyEnv>, reference: u32
|
|||
|
||||
/// Gets the hash value of a StringKey.
|
||||
fn string_key_get_hash(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> u32 {
|
||||
string_key.value(&env).unwrap().hash()
|
||||
string_key.value_func(&env).unwrap().hash()
|
||||
}
|
||||
|
||||
/// Get a null-terminated C string from a StringKey. Note that this involves a copy into WASM
|
||||
/// memory, so this is relatively heavy.
|
||||
fn string_key_get_str(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef<StringKey>) -> u32 {
|
||||
let string_key = string_key.value(&env).unwrap().str();
|
||||
let string_key = string_key.value_func(&env).unwrap().str();
|
||||
let wasm_string_ptr = env
|
||||
.data()
|
||||
.data()
|
||||
|
@ -141,7 +141,7 @@ fn string_key_get_str(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef
|
|||
|
||||
/// Gets the type of an EffectParameter
|
||||
fn effect_parameter_get_type(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> u8 {
|
||||
let v = parameter.value(&env).unwrap();
|
||||
let v = parameter.value_func(&env).unwrap();
|
||||
match v {
|
||||
EffectParameter::Bool(_) => 1,
|
||||
EffectParameter::Int(_) => 2,
|
||||
|
@ -152,7 +152,7 @@ fn effect_parameter_get_type(env: FunctionEnvMut<WebAssemblyEnv>, parameter: Ext
|
|||
|
||||
/// Gets the inner bool data of an EffectParameter. Panics if it's not a bool.
|
||||
fn effect_parameter_as_bool(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> u8 {
|
||||
let v = parameter.value(&env).unwrap();
|
||||
let v = parameter.value_func(&env).unwrap();
|
||||
match v {
|
||||
EffectParameter::Bool(b) => {
|
||||
if *b {
|
||||
|
@ -167,7 +167,7 @@ fn effect_parameter_as_bool(env: FunctionEnvMut<WebAssemblyEnv>, parameter: Exte
|
|||
|
||||
/// Gets the inner int data of an EffectParameter. Panics if it's not an int.
|
||||
fn effect_parameter_as_int(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> i64 {
|
||||
let v = parameter.value(&env).unwrap();
|
||||
let v = parameter.value_func(&env).unwrap();
|
||||
match v {
|
||||
EffectParameter::Int(i) => *i,
|
||||
_ => panic!("Unexpected parameter type!"),
|
||||
|
@ -176,7 +176,7 @@ fn effect_parameter_as_int(env: FunctionEnvMut<WebAssemblyEnv>, parameter: Exter
|
|||
|
||||
/// Gets the inner float data of an EffectParameter. Panics if it's not a float.
|
||||
fn effect_parameter_as_float(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<EffectParameter>) -> f32 {
|
||||
let v = parameter.value(&env).unwrap();
|
||||
let v = parameter.value_func(&env).unwrap();
|
||||
match v {
|
||||
EffectParameter::Float(f) => *f,
|
||||
_ => panic!("Unexpected parameter type!"),
|
||||
|
@ -188,7 +188,7 @@ fn effect_parameter_as_string(
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
parameter: ExternRef<EffectParameter>,
|
||||
) -> ExternRef<StringKey> {
|
||||
let v = parameter.value(&env).unwrap();
|
||||
let v = parameter.value_func(&env).unwrap();
|
||||
match v {
|
||||
EffectParameter::String(s) => ExternRef::func_new(&env, s),
|
||||
_ => panic!("Unexpected parameter type!"),
|
||||
|
|
|
@ -13,33 +13,33 @@ mod species;
|
|||
|
||||
register! {
|
||||
fn static_data_get_move_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<StaticData>) -> ExternRef<MoveLibrary> {
|
||||
ExternRef::func_new(&env, data_library.value(&env).unwrap().moves())
|
||||
ExternRef::func_new(&env, data_library.value_func(&env).unwrap().moves())
|
||||
}
|
||||
|
||||
fn static_data_get_species_library(
|
||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
data_library: ExternRef<StaticData>,
|
||||
) -> ExternRef<SpeciesLibrary> {
|
||||
ExternRef::func_new(&env, data_library.value(&env).unwrap().species())
|
||||
ExternRef::func_new(&env, data_library.value_func(&env).unwrap().species())
|
||||
}
|
||||
|
||||
fn static_data_get_item_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<StaticData>) -> ExternRef<ItemLibrary> {
|
||||
ExternRef::func_new(&env, data_library.value(&env).unwrap().items())
|
||||
ExternRef::func_new(&env, data_library.value_func(&env).unwrap().items())
|
||||
}
|
||||
|
||||
fn static_data_get_type_library(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<StaticData>) -> ExternRef<TypeLibrary> {
|
||||
ExternRef::func_new(&env, data_library.value(&env).unwrap().types())
|
||||
ExternRef::func_new(&env, data_library.value_func(&env).unwrap().types())
|
||||
}
|
||||
|
||||
fn static_data_get_library_settings(
|
||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
data_library: ExternRef<StaticData>,
|
||||
) -> ExternRef<LibrarySettings> {
|
||||
ExternRef::func_new(&env, data_library.value(&env).unwrap().settings())
|
||||
ExternRef::func_new(&env, data_library.value_func(&env).unwrap().settings())
|
||||
}
|
||||
|
||||
fn library_settings_get_maximum_level(env: FunctionEnvMut<WebAssemblyEnv>, data_library: ExternRef<LibrarySettings>) -> LevelInt {
|
||||
data_library.value(&env).unwrap().maximum_level()
|
||||
data_library.value_func(&env).unwrap().maximum_level()
|
||||
}
|
||||
|
||||
manual manual_registration
|
||||
|
|
|
@ -11,8 +11,8 @@ fn move_library_get_move(
|
|||
lib: ExternRef<MoveLibrary>,
|
||||
string_key: ExternRef<StringKey>,
|
||||
) -> ExternRef<MoveData> {
|
||||
let lib = lib.value(&env).unwrap();
|
||||
let m = lib.get(string_key.value(&env).unwrap());
|
||||
let lib = lib.value_func(&env).unwrap();
|
||||
let m = lib.get(string_key.value_func(&env).unwrap());
|
||||
if let Some(v) = m {
|
||||
ExternRef::func_new(&env, v)
|
||||
} else {
|
||||
|
@ -21,7 +21,7 @@ fn move_library_get_move(
|
|||
}
|
||||
|
||||
fn move_library_get_move_by_hash(env: FunctionEnvMut<WebAssemblyEnv>, lib: ExternRef<MoveLibrary>, hash: u32) -> ExternRef<MoveData> {
|
||||
let lib = lib.value(&env).unwrap();
|
||||
let lib = lib.value_func(&env).unwrap();
|
||||
let m = lib.get_by_hash(hash);
|
||||
if let Some(v) = m {
|
||||
ExternRef::func_new(&env, v)
|
||||
|
@ -31,39 +31,39 @@ fn move_library_get_move_by_hash(env: FunctionEnvMut<WebAssemblyEnv>, lib: Exter
|
|||
}
|
||||
|
||||
fn move_data_get_name(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> ExternRef<StringKey> {
|
||||
ExternRef::func_new(&env, move_data.value(&env).unwrap().name())
|
||||
ExternRef::func_new(&env, move_data.value_func(&env).unwrap().name())
|
||||
}
|
||||
|
||||
fn move_data_get_type(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 {
|
||||
move_data.value(&env).unwrap().move_type().into()
|
||||
move_data.value_func(&env).unwrap().move_type().into()
|
||||
}
|
||||
fn move_data_get_category(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 {
|
||||
move_data.value(&env).unwrap().category() as u8
|
||||
move_data.value_func(&env).unwrap().category() as u8
|
||||
}
|
||||
fn move_data_get_base_power(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 {
|
||||
move_data.value(&env).unwrap().base_power()
|
||||
move_data.value_func(&env).unwrap().base_power()
|
||||
}
|
||||
fn move_data_get_accuracy(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 {
|
||||
move_data.value(&env).unwrap().accuracy()
|
||||
move_data.value_func(&env).unwrap().accuracy()
|
||||
}
|
||||
fn move_data_get_base_usages(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 {
|
||||
move_data.value(&env).unwrap().base_usages()
|
||||
move_data.value_func(&env).unwrap().base_usages()
|
||||
}
|
||||
fn move_data_get_target(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> u8 {
|
||||
move_data.value(&env).unwrap().target() as u8
|
||||
move_data.value_func(&env).unwrap().target() as u8
|
||||
}
|
||||
fn move_data_get_priority(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>) -> i8 {
|
||||
move_data.value(&env).unwrap().priority()
|
||||
move_data.value_func(&env).unwrap().priority()
|
||||
}
|
||||
fn move_data_has_flag(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>, flag: ExternRef<StringKey>) -> u8 {
|
||||
if move_data.value(&env).unwrap().has_flag(flag.value(&env).unwrap()) {
|
||||
if move_data.value_func(&env).unwrap().has_flag(flag.value_func(&env).unwrap()) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
fn move_data_has_flag_by_hash(env: FunctionEnvMut<WebAssemblyEnv>, move_data: ExternRef<MoveData>, flag_hash: u32) -> u8 {
|
||||
if move_data.value(&env).unwrap().has_flag_by_hash(flag_hash) {
|
||||
if move_data.value_func(&env).unwrap().has_flag_by_hash(flag_hash) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
|
|
|
@ -12,8 +12,8 @@ fn species_library_get_species(
|
|||
lib: ExternRef<SpeciesLibrary>,
|
||||
string_key: ExternRef<StringKey>,
|
||||
) -> ExternRef<Species> {
|
||||
let lib = lib.value(&env).unwrap();
|
||||
let m = lib.get(string_key.value(&env).unwrap());
|
||||
let lib = lib.value_func(&env).unwrap();
|
||||
let m = lib.get(string_key.value_func(&env).unwrap());
|
||||
if let Some(v) = m {
|
||||
ExternRef::func_new(&env, v)
|
||||
} else {
|
||||
|
@ -25,14 +25,14 @@ fn species_get_capture_rate(
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
species: ExternRef<Species>,
|
||||
) -> u8 {
|
||||
species.value(&env).unwrap().capture_rate()
|
||||
species.value_func(&env).unwrap().capture_rate()
|
||||
}
|
||||
|
||||
fn species_get_growth_rate(
|
||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
species: ExternRef<Species>,
|
||||
) -> ExternRef<StringKey> {
|
||||
let species = species.value(&env).unwrap();
|
||||
let species = species.value_func(&env).unwrap();
|
||||
ExternRef::func_new(&env, species.growth_rate())
|
||||
}
|
||||
|
||||
|
@ -40,14 +40,14 @@ fn species_get_gender_rate(
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
species: ExternRef<Species>,
|
||||
) -> f32 {
|
||||
species.value(&env).unwrap().gender_rate()
|
||||
species.value_func(&env).unwrap().gender_rate()
|
||||
}
|
||||
|
||||
fn species_get_name(
|
||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
species: ExternRef<Species>,
|
||||
) -> ExternRef<StringKey> {
|
||||
let species = species.value(&env).unwrap();
|
||||
let species = species.value_func(&env).unwrap();
|
||||
ExternRef::func_new(&env, species.name())
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ fn species_get_id(
|
|||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
species: ExternRef<Species>,
|
||||
) -> u16 {
|
||||
species.value(&env).unwrap().id()
|
||||
species.value_func(&env).unwrap().id()
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::marker::PhantomData;
|
||||
use std::mem::transmute;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::script_implementations::wasm::script_resolver::{
|
||||
WebAssemblyEnv, WebAssemblyEnvironmentData, WebAssemblyScriptResolver,
|
||||
|
@ -11,6 +12,7 @@ use wasmer::FunctionEnvMut;
|
|||
/// An Extern Ref allows us to pass objects to WASM without actually passing raw memory, or
|
||||
/// requiring us to make copies. Instead, we pass a simple increment index, that we can then use
|
||||
/// to find the relevant data.
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) struct ExternRef<T: UniqueTypeId<u64>> {
|
||||
/// The lookup index we can use to find the data.
|
||||
index: u32,
|
||||
|
@ -55,8 +57,14 @@ impl<T: UniqueTypeId<u64>> ExternRef<T> {
|
|||
|
||||
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
|
||||
/// value when it was passed before. If these types do not match, this will panic.
|
||||
pub fn value<'a, 'b>(&'a self, env: &'b FunctionEnvMut<WebAssemblyEnv>) -> Option<&'b T> {
|
||||
let ptr = env.data().data().get_extern_ref_value(self.index) as *const T;
|
||||
pub fn value_func<'a, 'b>(&'a self, env: &'b FunctionEnvMut<WebAssemblyEnv>) -> Option<&'b T> {
|
||||
self.value(&env.data().data())
|
||||
}
|
||||
|
||||
/// Returns the real value for a given ExternRef. Note that the requested type must be the same as the type of the
|
||||
/// value when it was passed before. If these types do not match, this will panic.
|
||||
pub fn value<'a, 'b, 'c>(&'a self, env: &'b Arc<WebAssemblyEnvironmentData>) -> Option<&'c T> {
|
||||
let ptr = env.get_extern_ref_value(self.index) as *const T;
|
||||
unsafe { ptr.as_ref() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,61 +16,64 @@ mod temp_wasm_allocator;
|
|||
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
|
||||
#[allow(missing_docs)]
|
||||
#[allow(clippy::missing_docs_in_private_items)]
|
||||
#[repr(u8)]
|
||||
pub enum WebAssemblyScriptCapabilities {
|
||||
None = 0,
|
||||
Initialize = 1,
|
||||
OnStack,
|
||||
OnRemove,
|
||||
OnBeforeTurn,
|
||||
ChangeAttack,
|
||||
ModifyNumberOfHits,
|
||||
PreventAttack,
|
||||
FailAttack,
|
||||
StopBeforeAttack,
|
||||
OnBeforeAttack,
|
||||
FailIncomingAttack,
|
||||
ChangeMove,
|
||||
ChangeNumberOfHits,
|
||||
PreventMove,
|
||||
FailMove,
|
||||
StopBeforeMove,
|
||||
OnBeforeMove,
|
||||
FailIncomingMove,
|
||||
IsInvulnerable,
|
||||
OnAttackMiss,
|
||||
ChangeAttackType,
|
||||
OnMoveMiss,
|
||||
ChangeMoveType,
|
||||
ChangeEffectiveness,
|
||||
BlockCritical,
|
||||
OnIncomingHit,
|
||||
OnFaintingOpponent,
|
||||
PreventStatBoostChange,
|
||||
ModifyStatBoostChange,
|
||||
ChangeStatBoostChange,
|
||||
PreventSecondaryEffects,
|
||||
OnSecondaryEffect,
|
||||
OnAfterHits,
|
||||
PreventSelfSwitch,
|
||||
ModifyEffectChance,
|
||||
ModifyIncomingEffectChance,
|
||||
OverrideBasePower,
|
||||
ChangeEffectChance,
|
||||
ChangeIncomingEffectChance,
|
||||
ChangeBasePower,
|
||||
ChangeDamageStatsUser,
|
||||
BypassDefensiveStat,
|
||||
BypassOffensiveStat,
|
||||
ModifyStatModifier,
|
||||
ModifyDamageModifier,
|
||||
OverrideDamage,
|
||||
OverrideIncomingDamage,
|
||||
ChangeStatModifier,
|
||||
ChangeDamageModifier,
|
||||
ChangeDamage,
|
||||
ChangeIncomingDamage,
|
||||
ChangeSpeed,
|
||||
ChangePriority,
|
||||
OnFail,
|
||||
OnOpponentFail,
|
||||
PreventRunAway,
|
||||
PreventSelfRunAway,
|
||||
PreventOpponentRunAway,
|
||||
PreventOpponentSwitch,
|
||||
OnEndTurn,
|
||||
OnDamage,
|
||||
OnFaint,
|
||||
OnAfterHeldItemConsume,
|
||||
PreventIncomingCritical,
|
||||
ModifyCriticalStage,
|
||||
OverrideCriticalModifier,
|
||||
OverrideSTABModifier,
|
||||
ModifyExperienceGain,
|
||||
BlockIncomingCritical,
|
||||
ChangeAccuracy,
|
||||
ChangeCriticalStage,
|
||||
ChangeCriticalModifier,
|
||||
ChangeSTABModifier,
|
||||
ChangeExperienceGain,
|
||||
DoesShareExperience,
|
||||
BlockWeather,
|
||||
OnSwitchIn,
|
||||
ModifyOffensiveStatValue,
|
||||
ModifyDefensiveStatValue,
|
||||
ChangeOffensiveStatValue,
|
||||
ChangeDefensiveStatValue,
|
||||
ChangeCaptureRate,
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use std::any::Any;
|
||||
use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize};
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::sync::Arc;
|
||||
|
||||
use hashbrown::HashSet;
|
||||
|
||||
use crate::dynamic_data::{DynamicLibrary, Script, TurnChoice};
|
||||
use crate::dynamic_data::{Battle, DamageSource, DynamicLibrary, ExecutingMove, Pokemon, Script, TurnChoice};
|
||||
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
|
||||
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData;
|
||||
use crate::script_implementations::wasm::WebAssemblyScriptCapabilities;
|
||||
use crate::static_data::EffectParameter;
|
||||
use crate::static_data::{EffectParameter, Item, Statistic, TypeIdentifier};
|
||||
use crate::StringKey;
|
||||
|
||||
/// A WebAssemblyScript is there to implement the Script trait within WebAssemblyScript.
|
||||
|
@ -29,7 +29,7 @@ pub struct WebAssemblyScript {
|
|||
/// Capabilities define which functions we actually implement.
|
||||
capabilities: Arc<HashSet<WebAssemblyScriptCapabilities>>,
|
||||
/// The global runtime environment data.
|
||||
environment: Weak<WebAssemblyEnvironmentData>,
|
||||
environment: Arc<WebAssemblyEnvironmentData>,
|
||||
}
|
||||
|
||||
impl WebAssemblyScript {
|
||||
|
@ -38,7 +38,7 @@ impl WebAssemblyScript {
|
|||
owner_ptr: *mut u8,
|
||||
self_ptr: u32,
|
||||
capabilities: Arc<HashSet<WebAssemblyScriptCapabilities>>,
|
||||
environment: Weak<WebAssemblyEnvironmentData>,
|
||||
environment: Arc<WebAssemblyEnvironmentData>,
|
||||
name: StringKey,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
@ -51,6 +51,33 @@ impl WebAssemblyScript {
|
|||
environment,
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if this script implements a certain capability.
|
||||
#[inline(always)]
|
||||
fn has_capability(&self, cap: &WebAssemblyScriptCapabilities) -> bool {
|
||||
self.capabilities.contains(cap)
|
||||
}
|
||||
}
|
||||
|
||||
/// Util macro to reduce function call verbosity.
|
||||
macro_rules! call_func {
|
||||
($func:ident, $env:ident, $self:ident $(, $par_name:expr)*) => {
|
||||
$func.call(&mut $env.store_mut(), $self.self_ptr $(, $par_name)*).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Util macro to reduce extern ref instantiation verbosity.
|
||||
macro_rules! ex_ref {
|
||||
($env:ident, $value:expr) => {
|
||||
ExternRef::new($env.as_ref(), $value)
|
||||
};
|
||||
}
|
||||
|
||||
/// Util macro to reduce vec extern ref instantiation verbosity.
|
||||
macro_rules! vec_ex_ref {
|
||||
($env:ident, $value:expr) => {
|
||||
VecExternRef::new($env.as_ref(), $value)
|
||||
};
|
||||
}
|
||||
|
||||
impl Script for WebAssemblyScript {
|
||||
|
@ -67,104 +94,721 @@ impl Script for WebAssemblyScript {
|
|||
}
|
||||
|
||||
fn stack(&self) {
|
||||
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::OnStack) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnStack) {
|
||||
return;
|
||||
}
|
||||
let env = self.environment.upgrade().unwrap();
|
||||
let func = env.script_function_cache().stack(&env);
|
||||
if let Some(func) = func {
|
||||
func.call(&mut env.store_mut(), self.self_ptr).unwrap();
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().stack(env) {
|
||||
call_func!(func, env, self);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_remove(&self) {
|
||||
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::OnRemove) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnRemove) {
|
||||
return;
|
||||
}
|
||||
let env = self.environment.upgrade().unwrap();
|
||||
let func = env.script_function_cache().on_remove(&env);
|
||||
if let Some(func) = func {
|
||||
func.call(&mut env.store_mut(), self.self_ptr).unwrap();
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_remove(env) {
|
||||
call_func!(func, env, self);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_initialize(&self, library: &DynamicLibrary, pars: &[EffectParameter]) {
|
||||
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::Initialize) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::Initialize) {
|
||||
return;
|
||||
}
|
||||
|
||||
let env = self.environment.upgrade().unwrap();
|
||||
let func = env.script_function_cache().on_initialize(&env);
|
||||
if let Some(func) = func {
|
||||
func.call(
|
||||
&mut env.store_mut(),
|
||||
self.self_ptr,
|
||||
ExternRef::new(env.as_ref(), library),
|
||||
VecExternRef::new(env.as_ref(), pars),
|
||||
)
|
||||
.unwrap();
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_initialize(env) {
|
||||
call_func!(func, env, self, ex_ref!(env, library), vec_ex_ref!(env, pars));
|
||||
}
|
||||
}
|
||||
|
||||
fn on_before_turn(&self, choice: &TurnChoice) {
|
||||
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::OnBeforeTurn) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnBeforeTurn) {
|
||||
return;
|
||||
}
|
||||
let env = self.environment.upgrade().unwrap();
|
||||
let func = env.script_function_cache().on_before_turn(&env);
|
||||
if let Some(func) = func {
|
||||
func.call(
|
||||
&mut env.store_mut(),
|
||||
self.self_ptr,
|
||||
ExternRef::new(env.as_ref(), choice),
|
||||
)
|
||||
.unwrap();
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_before_turn(env) {
|
||||
call_func!(func, env, self, ex_ref!(env, choice));
|
||||
}
|
||||
}
|
||||
|
||||
fn change_speed(&self, choice: &TurnChoice, speed: &mut u32) {
|
||||
if !self.capabilities.contains(&WebAssemblyScriptCapabilities::ChangeSpeed) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeSpeed) {
|
||||
return;
|
||||
}
|
||||
|
||||
let env = self.environment.upgrade().unwrap();
|
||||
let func = env.script_function_cache().change_speed(&env);
|
||||
if let Some(func) = func {
|
||||
let ptr = env.temp_allocate_mem_typed::<u32>(*speed);
|
||||
func.call(
|
||||
&mut env.store_mut(),
|
||||
self.self_ptr,
|
||||
ExternRef::new(env.as_ref(), choice),
|
||||
ptr.wasm_pointer,
|
||||
)
|
||||
.unwrap();
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_speed(env) {
|
||||
let ptr = env.allocate_temp::<u32>(*speed);
|
||||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*speed = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_priority(&self, choice: &TurnChoice, priority: &mut i8) {
|
||||
if !self
|
||||
.capabilities
|
||||
.contains(&WebAssemblyScriptCapabilities::ChangePriority)
|
||||
{
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangePriority) {
|
||||
return;
|
||||
}
|
||||
|
||||
let env = self.environment.upgrade().unwrap();
|
||||
let func = env.script_function_cache().change_priority(&env);
|
||||
if let Some(func) = func {
|
||||
let ptr = env.temp_allocate_mem_typed::<i8>(*priority);
|
||||
func.call(
|
||||
&mut env.store_mut(),
|
||||
self.self_ptr,
|
||||
ExternRef::new(env.as_ref(), choice),
|
||||
ptr.wasm_pointer,
|
||||
)
|
||||
.unwrap();
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_priority(env) {
|
||||
let ptr = env.allocate_temp::<i8>(*priority);
|
||||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*priority = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_move(&self, choice: &TurnChoice, move_name: &mut StringKey) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeMove) {
|
||||
return;
|
||||
}
|
||||
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_move(env) {
|
||||
let move_ref = ex_ref!(env, move_name);
|
||||
let ptr = env.allocate_temp::<ExternRef<StringKey>>(move_ref);
|
||||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*move_name = ptr.value().value(env).unwrap().clone();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_number_of_hits(&self, choice: &TurnChoice, number_of_hits: &mut u8) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeNumberOfHits) {
|
||||
return;
|
||||
}
|
||||
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_number_of_hits(env) {
|
||||
let ptr = env.allocate_temp::<u8>(*number_of_hits);
|
||||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*number_of_hits = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn prevent_move(&self, mv: &ExecutingMove, prevent: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventMove) {
|
||||
return;
|
||||
}
|
||||
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().prevent_move(env) {
|
||||
let ptr = env.allocate_temp::<bool>(*prevent);
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ptr.wasm_ptr);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn fail_move(&self, mv: &ExecutingMove, fail: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::FailMove) {
|
||||
return;
|
||||
}
|
||||
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().fail_move(env) {
|
||||
let ptr = env.allocate_temp::<bool>(*fail);
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ptr.wasm_ptr);
|
||||
*fail = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn stop_before_move(&self, mv: &ExecutingMove, stop: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::StopBeforeMove) {
|
||||
return;
|
||||
}
|
||||
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().stop_before_move(env) {
|
||||
let ptr = env.allocate_temp::<bool>(*stop);
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ptr.wasm_ptr);
|
||||
*stop = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn on_before_move(&self, mv: &ExecutingMove) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnBeforeMove) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_before_move(env) {
|
||||
call_func!(func, env, self, ex_ref!(env, mv));
|
||||
}
|
||||
}
|
||||
|
||||
fn fail_incoming_move(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, fail: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::FailIncomingMove) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().fail_incoming_move(env) {
|
||||
let ptr = env.allocate_temp::<bool>(*fail);
|
||||
call_func!(
|
||||
func,
|
||||
env,
|
||||
self,
|
||||
ex_ref!(env, mv),
|
||||
ex_ref!(env, target.as_ref()),
|
||||
ptr.wasm_ptr
|
||||
);
|
||||
*fail = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn is_invulnerable(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, invulnerable: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::IsInvulnerable) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().is_invulnerable(env) {
|
||||
let ptr = env.allocate_temp::<bool>(*invulnerable);
|
||||
call_func!(
|
||||
func,
|
||||
env,
|
||||
self,
|
||||
ex_ref!(env, mv),
|
||||
ex_ref!(env, target.as_ref()),
|
||||
ptr.wasm_ptr
|
||||
);
|
||||
*invulnerable = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn on_move_miss(&self, mv: &ExecutingMove, target: &Arc<Pokemon>) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnMoveMiss) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_move_miss(env) {
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target.as_ref()));
|
||||
}
|
||||
}
|
||||
|
||||
fn change_move_type(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, move_type: &mut TypeIdentifier) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeMoveType) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_move_type(env) {
|
||||
let ptr = env.allocate_temp::<TypeIdentifier>(*move_type);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*move_type = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_effectiveness(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, effectiveness: &mut f32) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeEffectiveness) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_effectiveness(env) {
|
||||
let ptr = env.allocate_temp(*effectiveness);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*effectiveness = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn block_critical(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, block_critical: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::BlockCritical) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().block_critical(env) {
|
||||
let ptr = env.allocate_temp(*block_critical);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*block_critical = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn block_incoming_critical(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, block_critical: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::BlockIncomingCritical) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().block_incoming_critical(env) {
|
||||
let ptr = env.allocate_temp(*block_critical);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*block_critical = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_accuracy(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, accuracy: &mut u8) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeAccuracy) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_accuracy(env) {
|
||||
let ptr = env.allocate_temp(*accuracy);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*accuracy = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_critical_stage(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, stage: &mut u8) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeCriticalStage) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_critical_stage(env) {
|
||||
let ptr = env.allocate_temp(*stage);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*stage = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_critical_modifier(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, modifier: &mut f32) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeCriticalModifier) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_critical_modifier(env) {
|
||||
let ptr = env.allocate_temp(*modifier);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*modifier = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_stab_modifier(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, modifier: &mut f32) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeSTABModifier) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_stab_modifier(env) {
|
||||
let ptr = env.allocate_temp(*modifier);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*modifier = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_base_power(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, base_power: &mut u8) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeBasePower) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_base_power(env) {
|
||||
let ptr = env.allocate_temp(*base_power);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*base_power = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn bypass_defensive_stat_boost(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, bypass: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::BypassDefensiveStat) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().bypass_defensive_stat_boost(env) {
|
||||
let ptr = env.allocate_temp(*bypass);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*bypass = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn bypass_offensive_stat_boost(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, bypass: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::BypassOffensiveStat) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().bypass_offensive_stat_boost(env) {
|
||||
let ptr = env.allocate_temp(*bypass);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*bypass = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_offensive_stat_value(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, amount: &mut u32) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeOffensiveStatValue) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_offensive_stat_value(env) {
|
||||
let ptr = env.allocate_temp(*amount);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*amount = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_defensive_stat_value(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, amount: &mut u32) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeOffensiveStatValue) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_defensive_stat_value(env) {
|
||||
let ptr = env.allocate_temp(*amount);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*amount = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_damage_stat_modifier(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, modifier: &mut f32) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeStatModifier) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_damage_stat_modifier(env) {
|
||||
let ptr = env.allocate_temp(*modifier);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*modifier = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_damage_modifier(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, modifier: &mut f32) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeDamageModifier) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_damage_modifier(env) {
|
||||
let ptr = env.allocate_temp(*modifier);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*modifier = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_damage(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, damage: &mut u32) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeDamage) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_damage(env) {
|
||||
let ptr = env.allocate_temp(*damage);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*damage = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_incoming_damage(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, damage: &mut u32) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeIncomingDamage) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_incoming_damage(env) {
|
||||
let ptr = env.allocate_temp(*damage);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*damage = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn on_incoming_hit(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnIncomingHit) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_incoming_hit(env) {
|
||||
let target = target.as_ref();
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_opponent_faints(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFaintingOpponent) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_opponent_faints(env) {
|
||||
let target = target.as_ref();
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit);
|
||||
}
|
||||
}
|
||||
|
||||
fn prevent_stat_boost_change(
|
||||
&self,
|
||||
target: &Pokemon,
|
||||
stat: Statistic,
|
||||
amount: i8,
|
||||
self_inflicted: bool,
|
||||
prevent: &mut bool,
|
||||
) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventStatBoostChange) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().prevent_stat_boost_change(env) {
|
||||
let ptr = env.allocate_temp(*prevent);
|
||||
let self_inflicted = if self_inflicted { 1_u8 } else { 0_u8 };
|
||||
call_func!(
|
||||
func,
|
||||
env,
|
||||
self,
|
||||
ex_ref!(env, target),
|
||||
stat as u8,
|
||||
amount,
|
||||
self_inflicted,
|
||||
ptr.wasm_ptr
|
||||
);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn prevent_secondary_effect(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, prevent: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventSecondaryEffects) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().prevent_secondary_effect(env) {
|
||||
let ptr = env.allocate_temp(*prevent);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_effect_chance(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, chance: &mut f32) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeEffectChance) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_effect_chance(env) {
|
||||
let ptr = env.allocate_temp(*chance);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*chance = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_incoming_effect_chance(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, chance: &mut f32) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeIncomingEffectChance) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_incoming_effect_chance(env) {
|
||||
let ptr = env.allocate_temp(*chance);
|
||||
let target = target.as_ref();
|
||||
let w_ptr = ptr.wasm_ptr;
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*chance = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn on_secondary_effect(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFaintingOpponent) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_secondary_effect(env) {
|
||||
let target = target.as_ref();
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_after_hits(&self, mv: &ExecutingMove, target: &Arc<Pokemon>) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnAfterHits) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_after_hits(env) {
|
||||
let target = target.as_ref();
|
||||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target));
|
||||
}
|
||||
}
|
||||
|
||||
fn prevent_self_switch(&self, choice: &TurnChoice, prevent: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventSelfSwitch) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().prevent_self_switch(env) {
|
||||
let ptr = env.allocate_temp(*prevent);
|
||||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn prevent_opponent_switch(&self, choice: &TurnChoice, prevent: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventSelfSwitch) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().prevent_opponent_switch(env) {
|
||||
let ptr = env.allocate_temp(*prevent);
|
||||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn on_fail(&self, pokemon: &Pokemon) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFail) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_fail(env) {
|
||||
call_func!(func, env, self, ex_ref!(env, pokemon));
|
||||
}
|
||||
}
|
||||
|
||||
fn on_opponent_fail(&self, pokemon: &Pokemon) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFail) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_opponent_fail(env) {
|
||||
call_func!(func, env, self, ex_ref!(env, pokemon));
|
||||
}
|
||||
}
|
||||
|
||||
fn prevent_self_run_away(&self, choice: &TurnChoice, prevent: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventSelfRunAway) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().prevent_self_run_away(env) {
|
||||
let ptr = env.allocate_temp(*prevent);
|
||||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn prevent_opponent_run_away(&self, choice: &TurnChoice, prevent: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventOpponentRunAway) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().prevent_opponent_run_away(env) {
|
||||
let ptr = env.allocate_temp(*prevent);
|
||||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
}
|
||||
fn on_end_turn(&self) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnEndTurn) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_end_turn(env) {
|
||||
call_func!(func, env, self);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_damage(&self, pokemon: &Pokemon, source: DamageSource, old_health: u32, new_health: u32) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnDamage) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_damage(env) {
|
||||
let r = ex_ref!(env, pokemon);
|
||||
call_func!(func, env, self, r, source as u8, old_health, new_health);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_faint(&self, pokemon: &Pokemon, source: DamageSource) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFaint) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_faint(env) {
|
||||
call_func!(func, env, self, ex_ref!(env, pokemon), source as u8);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_switch_in(&self, pokemon: &Pokemon) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnSwitchIn) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_switch_in(env) {
|
||||
call_func!(func, env, self, ex_ref!(env, pokemon));
|
||||
}
|
||||
}
|
||||
|
||||
fn on_after_held_item_consume(&self, pokemon: &Pokemon, item: &Item) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnAfterHeldItemConsume) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_after_held_item_consume(env) {
|
||||
call_func!(func, env, self, ex_ref!(env, pokemon), ex_ref!(env, item));
|
||||
}
|
||||
}
|
||||
|
||||
fn change_experience_gained(&self, fainted_mon: &Pokemon, winning_mon: &Pokemon, amount: &mut u32) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeExperienceGain) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_experience_gained(env) {
|
||||
let ptr = env.allocate_temp(*amount);
|
||||
let fainted_mon = ex_ref!(env, fainted_mon);
|
||||
let winning_mon = ex_ref!(env, winning_mon);
|
||||
call_func!(func, env, self, fainted_mon, winning_mon, ptr.wasm_ptr);
|
||||
*amount = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn share_experience(&self, fainted_mon: &Pokemon, winning_mon: &Pokemon, shares: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::DoesShareExperience) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().share_experience(env) {
|
||||
let ptr = env.allocate_temp(*shares);
|
||||
let fainted_mon = ex_ref!(env, fainted_mon);
|
||||
let winning_mon = ex_ref!(env, winning_mon);
|
||||
call_func!(func, env, self, fainted_mon, winning_mon, ptr.wasm_ptr);
|
||||
*shares = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn block_weather(&self, battle: &Battle, blocked: &mut bool) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::BlockWeather) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().block_weather(env) {
|
||||
let ptr = env.allocate_temp(*blocked);
|
||||
call_func!(func, env, self, ex_ref!(env, battle), ptr.wasm_ptr);
|
||||
*blocked = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn change_capture_rate_bonus(&self, target: &Pokemon, pokeball: &Item, modifier: &mut u8) {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeCaptureRate) {
|
||||
return;
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_capture_rate_bonus(env) {
|
||||
let ptr = env.allocate_temp(*modifier);
|
||||
let target = ex_ref!(env, target);
|
||||
let pokeball = ex_ref!(env, pokeball);
|
||||
call_func!(func, env, self, target, pokeball, ptr.wasm_ptr);
|
||||
*modifier = *ptr.value();
|
||||
}
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::RwLock;
|
||||
use paste::paste;
|
||||
|
||||
use crate::dynamic_data::{DynamicLibrary, TurnChoice};
|
||||
use crate::dynamic_data::{Battle, DynamicLibrary, ExecutingMove, Pokemon, TurnChoice};
|
||||
use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef};
|
||||
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData;
|
||||
use crate::static_data::EffectParameter;
|
||||
use crate::static_data::{EffectParameter, Item, TypeIdentifier};
|
||||
use crate::StringKey;
|
||||
use wasmer::TypedFunction;
|
||||
use wasmer::{FromToNativeWasmType, TypedFunction};
|
||||
|
||||
/// A macro to generate the script function cache a bit easier.
|
||||
macro_rules! script_function_cache {
|
||||
|
@ -19,7 +20,7 @@ macro_rules! script_function_cache {
|
|||
) => {
|
||||
#[derive(Default)]
|
||||
#[allow(unused_parens)]
|
||||
pub struct ScriptFunctionCache {
|
||||
pub(super) struct ScriptFunctionCache {
|
||||
$(
|
||||
$name: RwLock<Option<TypedFunction<(u32$(, $par_type)*), ()>>>,
|
||||
)*
|
||||
|
@ -60,11 +61,112 @@ macro_rules! script_function_cache {
|
|||
}
|
||||
}
|
||||
|
||||
/// Helper struct to indicate WASM client pointer type. This makes it harder to pass the wrong type
|
||||
/// to a function by accident.
|
||||
#[derive(Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub(super) struct WasmPtr<T> {
|
||||
/// The memory size
|
||||
v: u32,
|
||||
/// Phantom data to store type.
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Clone for WasmPtr<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
v: self.v,
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Copy for WasmPtr<T> {}
|
||||
|
||||
impl<T> From<u32> for WasmPtr<T> {
|
||||
fn from(v: u32) -> Self {
|
||||
Self {
|
||||
v,
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<WasmPtr<T>> for u32 {
|
||||
fn from(v: WasmPtr<T>) -> Self {
|
||||
v.v
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> FromToNativeWasmType for WasmPtr<T> {
|
||||
type Native = i32;
|
||||
|
||||
fn from_native(native: Self::Native) -> Self {
|
||||
Self {
|
||||
v: native as u32,
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_native(self) -> Self::Native {
|
||||
self.v as i32
|
||||
}
|
||||
}
|
||||
|
||||
script_function_cache! {
|
||||
stack()
|
||||
on_remove()
|
||||
on_initialize(ExternRef<DynamicLibrary>, VecExternRef<EffectParameter>)
|
||||
on_before_turn(ExternRef<TurnChoice>)
|
||||
change_speed(ExternRef<TurnChoice>, u32)
|
||||
change_priority(ExternRef<TurnChoice>, u32)
|
||||
change_speed(ExternRef<TurnChoice>, WasmPtr<u32>)
|
||||
change_priority(ExternRef<TurnChoice>, WasmPtr<i8>)
|
||||
change_move(ExternRef<TurnChoice>, WasmPtr<ExternRef<StringKey>>)
|
||||
change_number_of_hits(ExternRef<TurnChoice>, WasmPtr<u8>)
|
||||
prevent_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
||||
fail_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
||||
stop_before_move(ExternRef<ExecutingMove>, WasmPtr<bool>)
|
||||
on_before_move(ExternRef<ExecutingMove>)
|
||||
fail_incoming_move(ExternRef<ExecutingMove>, ExternRef<Pokemon>, WasmPtr<bool>)
|
||||
is_invulnerable(ExternRef<ExecutingMove>, ExternRef<Pokemon>, WasmPtr<bool>)
|
||||
on_move_miss(ExternRef<ExecutingMove>, ExternRef<Pokemon>)
|
||||
change_move_type(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<TypeIdentifier>)
|
||||
change_effectiveness(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
block_critical(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
block_incoming_critical(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
change_accuracy(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
||||
change_critical_stage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
||||
change_critical_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
change_stab_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
change_base_power(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u8>)
|
||||
bypass_defensive_stat_boost(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
bypass_offensive_stat_boost(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
change_offensive_stat_value(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||
change_defensive_stat_value(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||
change_damage_stat_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
change_damage_modifier(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
change_damage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||
change_incoming_damage(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<u32>)
|
||||
on_incoming_hit(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
||||
on_opponent_faints(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
||||
prevent_stat_boost_change(ExternRef<Pokemon>, u8, i8, u8, WasmPtr<bool>)
|
||||
prevent_secondary_effect(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<bool>)
|
||||
change_effect_chance(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
change_incoming_effect_chance(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8, WasmPtr<f32>)
|
||||
on_secondary_effect(ExternRef<ExecutingMove>, ExternRef<Pokemon>, u8)
|
||||
on_after_hits(ExternRef<ExecutingMove>, ExternRef<Pokemon>)
|
||||
prevent_self_switch(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||
prevent_opponent_switch(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||
on_fail(ExternRef<Pokemon>)
|
||||
on_opponent_fail(ExternRef<Pokemon>)
|
||||
prevent_self_run_away(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||
prevent_opponent_run_away(ExternRef<TurnChoice>, WasmPtr<bool>)
|
||||
on_end_turn()
|
||||
on_damage(ExternRef<Pokemon>, u8, u32, u32)
|
||||
on_faint(ExternRef<Pokemon>, u8)
|
||||
on_switch_in(ExternRef<Pokemon>)
|
||||
on_after_held_item_consume(ExternRef<Pokemon>, ExternRef<Item>)
|
||||
change_experience_gained(ExternRef<Pokemon>, ExternRef<Pokemon>, WasmPtr<u32>)
|
||||
share_experience(ExternRef<Pokemon>, ExternRef<Pokemon>, WasmPtr<bool>)
|
||||
block_weather(ExternRef<Battle>, WasmPtr<bool>)
|
||||
change_capture_rate_bonus(ExternRef<Pokemon>, ExternRef<Item>, WasmPtr<u8>)
|
||||
|
||||
}
|
||||
|
|
|
@ -223,7 +223,7 @@ impl ScriptResolver for WebAssemblyScriptResolver {
|
|||
owner as *mut u8,
|
||||
script,
|
||||
capabilities.clone(),
|
||||
Arc::downgrade(&self.environment_data),
|
||||
self.environment_data.clone(),
|
||||
script_key.clone(),
|
||||
))))
|
||||
}
|
||||
|
@ -324,7 +324,7 @@ impl WebAssemblyEnvironmentData {
|
|||
}
|
||||
|
||||
///
|
||||
pub fn script_function_cache(&self) -> &ScriptFunctionCache {
|
||||
pub(super) fn script_function_cache(&self) -> &ScriptFunctionCache {
|
||||
&self.script_function_cache
|
||||
}
|
||||
|
||||
|
@ -361,7 +361,7 @@ impl WebAssemblyEnvironmentData {
|
|||
/// Allocate a piece of memory inside WASM with a very short lifespan. This is mainly used for
|
||||
/// rapid allocation of script function parameters, where WASM needs to write to a specific
|
||||
/// pointer.
|
||||
pub fn temp_allocate_mem_typed<T>(&self, value: T) -> AllocatedObject<T> {
|
||||
pub(super) fn allocate_temp<T>(&self, value: T) -> AllocatedObject<T> {
|
||||
self.temp_allocator.read().as_ref().unwrap().alloc::<T>(value)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::script_implementations::wasm::script_function_cache::WasmPtr;
|
||||
use std::mem::size_of;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
|
@ -40,7 +41,7 @@ impl TempWasmAllocator {
|
|||
}
|
||||
AllocatedObject::<T> {
|
||||
ptr,
|
||||
wasm_pointer: self.wasm_pointer + ptr_offset as u32,
|
||||
wasm_ptr: (self.wasm_pointer + ptr_offset as u32).into(),
|
||||
allocator: self as *const TempWasmAllocator,
|
||||
}
|
||||
}
|
||||
|
@ -56,11 +57,11 @@ impl TempWasmAllocator {
|
|||
}
|
||||
|
||||
/// A value allocated within WASM memory. Once this goes out of scope, it gets deallocated,
|
||||
pub struct AllocatedObject<T> {
|
||||
pub(super) struct AllocatedObject<T> {
|
||||
/// The pointer in host memory to where the object lives.
|
||||
pub ptr: *mut T,
|
||||
/// The pointer in client memory to where the object lives.
|
||||
pub wasm_pointer: u32,
|
||||
pub wasm_ptr: WasmPtr<T>,
|
||||
/// A raw pointer to the allocator we use, so we know where to deallocate to.
|
||||
allocator: *const TempWasmAllocator,
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ pub enum BattleItemCategory {
|
|||
|
||||
/// An item is an object which the player can pick up, keep in their Bag, and use in some manner
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))]
|
||||
pub struct Item {
|
||||
/// The name of the item.
|
||||
name: StringKey,
|
||||
|
|
Loading…
Reference in New Issue