diff --git a/src/dynamic_data/models/battle.rs b/src/dynamic_data/models/battle.rs index 749c871..026a8f7 100755 --- a/src/dynamic_data/models/battle.rs +++ b/src/dynamic_data/models/battle.rs @@ -405,3 +405,10 @@ pub enum BattleResult { /// The battle has a winner, with the inner value being the index of the side that has won. Conclusive(u8), } + +impl BattleResult { + /// Whether or not the battle has a winner. + pub fn is_conclusive(&self) -> bool { + matches!(self, Self::Conclusive(_)) + } +} diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/battle.rs b/src/script_implementations/wasm/export_registry/dynamic_data/battle.rs index a81ef6d..6268c28 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/battle.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/battle.rs @@ -1,5 +1,5 @@ use crate::dynamic_data::{ - Battle, BattleParty, BattleRandom, BattleSide, ChoiceQueue, DynamicLibrary, Pokemon, PokemonParty, + Battle, BattleParty, BattleRandom, BattleResult, BattleSide, ChoiceQueue, DynamicLibrary, Pokemon, PokemonParty, }; use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; @@ -82,6 +82,66 @@ register! { ExternRef::null() } + fn battle_get_pokemon( + env: FunctionEnvMut, + battle: ExternRef, + side: u8, index: u8 + ) -> ExternRef { + let battle = battle.value_func(&env).unwrap(); + let pokemon = battle.get_pokemon(side, index); + if let Some(pokemon) = pokemon { + ExternRef::func_new(&env, &pokemon) + } else { + ExternRef::null() + } + } + + fn battle_get_can_flee( + env: FunctionEnvMut, + battle: ExternRef, + ) -> u8 { + if battle.value_func(&env).unwrap().can_flee() { 1 } else { 0 } + } + + fn battle_get_number_of_sides( + env: FunctionEnvMut, + battle: ExternRef, + ) -> u8 { + battle.value_func(&env).unwrap().number_of_sides() + } + + fn battle_get_has_ended( + env: FunctionEnvMut, + battle: ExternRef, + ) -> u8 { + if battle.value_func(&env).unwrap().has_ended() { 1 } else { 0 } + } + + fn battle_get_has_ended_conclusively( + env: FunctionEnvMut, + battle: ExternRef, + ) -> u8 { + if battle.value_func(&env).unwrap().result().is_conclusive() { 1 } else { 0 } + } + + fn battle_get_winning_side( + env: FunctionEnvMut, + battle: ExternRef, + ) -> u8 { + if let BattleResult::Conclusive(result) = battle.value_func(&env).unwrap().result() { + result + } else { + 0 + } + } + + fn battle_get_current_turn( + env: FunctionEnvMut, + battle: ExternRef, + ) -> u32 { + battle.value_func(&env).unwrap().current_turn() + } + fn battle_party_get_party( env: FunctionEnvMut, battle_party: ExternRef, diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/battle_side.rs b/src/script_implementations/wasm/export_registry/dynamic_data/battle_side.rs index 871205a..b68a269 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/battle_side.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/battle_side.rs @@ -55,6 +55,20 @@ register! { } } + fn battle_side_get_has_fled_battle( + env: FunctionEnvMut, + side: ExternRef, + ) -> u8 { + if side.value_func(&env).unwrap().has_fled_battle() { 1 } else { 0 } + } + + fn battle_side_get_is_defeated( + env: FunctionEnvMut, + side: ExternRef, + ) -> u8 { + if side.value_func(&env).unwrap().is_defeated() { 1 } else { 0 } + } + fn battleside_add_volatile_by_name( env: FunctionEnvMut, side: ExternRef, diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs b/src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs index cc84a62..37d4a8a 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/executing_move.rs @@ -1,6 +1,7 @@ use crate::dynamic_data::{ExecutingMove, HitData, LearnedMove, Pokemon}; use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::extern_ref::ExternRef; +use crate::script_implementations::wasm::script::WebAssemblyScript; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::static_data::MoveData; use wasmer::FunctionEnvMut; @@ -42,4 +43,38 @@ register! { ) -> ExternRef { ExternRef::func_new(&env, executing_move.value_func(&env).unwrap().get_hit_data(target.value_func(&env).unwrap(), hit).unwrap()) } + + fn executing_move_get_number_of_targets( + env: FunctionEnvMut, + executing_move: ExternRef, + ) -> u32 { + executing_move.value_func(&env).unwrap().target_count() as u32 + } + + fn executing_move_is_pokemon_target( + env: FunctionEnvMut, + executing_move: ExternRef, + pokemon: ExternRef + ) -> u8 { + let pokemon = pokemon.value_func_arc(&env).unwrap(); + if executing_move.value_func(&env).unwrap().is_pokemon_target(&pokemon) { 1 } else { 0 } + } + + + + fn executing_move_get_script( + env: FunctionEnvMut, + executing_move: ExternRef, + ) -> (u32 , u32) { + let executing_move = executing_move.value_func(&env).unwrap(); + if let Some(script) = executing_move.script().get() { + let read_lock = script.read(); + if let Some(script) = read_lock.as_ref() { + let s = script.as_any().downcast_ref::().unwrap().get_wasm_pointer(); + return (s, s + 4) + } + } + (0, 0) + } + } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/hit_data.rs b/src/script_implementations/wasm/export_registry/dynamic_data/hit_data.rs index c09417c..cffcf17 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/hit_data.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/hit_data.rs @@ -25,4 +25,58 @@ register! { ) { hit.value_func(&env).unwrap().fail() } + + fn hit_data_get_base_power( + env: FunctionEnvMut, + hit: ExternRef, + ) -> u8 { + hit.value_func(&env).unwrap().base_power() + } + + fn hit_data_get_effectiveness( + env: FunctionEnvMut, + hit: ExternRef, + ) -> f32 { + hit.value_func(&env).unwrap().effectiveness() + } + + fn hit_data_get_move_type( + env: FunctionEnvMut, + hit: ExternRef, + ) -> u8 { + hit.value_func(&env).unwrap().move_type().into() + } + + fn hit_data_set_critical( + env: FunctionEnvMut, + hit: ExternRef, + value: u8 + ) { + hit.value_func(&env).unwrap().set_critical(value == 1) + } + + fn hit_data_set_effectiveness( + env: FunctionEnvMut, + hit: ExternRef, + effectiveness: f32 + ) { + hit.value_func(&env).unwrap().set_effectiveness(effectiveness) + } + + fn hit_data_set_damage( + env: FunctionEnvMut, + hit: ExternRef, + damage: u32 + ) { + hit.value_func(&env).unwrap().set_damage(damage) + } + + fn hit_data_set_move_type( + env: FunctionEnvMut, + hit: ExternRef, + move_type: u8 + ) { + hit.value_func(&env).unwrap().set_move_type(move_type.into()) + } + } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/learned_move.rs b/src/script_implementations/wasm/export_registry/dynamic_data/learned_move.rs index 002be07..f6ec264 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/learned_move.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/learned_move.rs @@ -23,4 +23,20 @@ register! { ) -> ExternRef { ExternRef::func_new(&env, turn_choice.value_func(&env).unwrap().move_data()) } + + fn learned_move_restore_all_uses( + env: FunctionEnvMut, + turn_choice: ExternRef, + ) { + turn_choice.value_func(&env).unwrap().restore_all_uses(); + } + + fn learned_move_restore_uses( + env: FunctionEnvMut, + turn_choice: ExternRef, + amount: u8, + ) { + turn_choice.value_func(&env).unwrap().restore_uses(amount); + } + } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/mod.rs b/src/script_implementations/wasm/export_registry/dynamic_data/mod.rs index 2eb5444..b028bb2 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/mod.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/mod.rs @@ -55,6 +55,24 @@ register! { } } + fn script_get_owner_kind( + env: FunctionEnvMut, + script: u32, + ) -> u8 { + let script = env.data().data().get_loaded_script(script); + if let Some(script) = script { + match script.get_owner() { + ScriptOwnerData::Pokemon(_) => 0, + ScriptOwnerData::BattleSide(_) => 1, + ScriptOwnerData::Battle(_) => 2, + ScriptOwnerData::None => 3, + } + } else { + 0 + } + } + + manual manual_register } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/pokemon.rs b/src/script_implementations/wasm/export_registry/dynamic_data/pokemon.rs index 4379150..7c23e9c 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/pokemon.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/pokemon.rs @@ -1,14 +1,15 @@ use std::mem::transmute; +use crate::defines::LevelInt; use crate::dynamic_data::{Battle, DynamicLibrary, LearnedMove, Pokemon, VolatileScriptsOwner}; use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script::WebAssemblyScript; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; -use crate::static_data::{ClampedStatisticSet, Species}; +use crate::static_data::{Ability, ClampedStatisticSet, Form, Nature, Species}; use crate::static_data::{Item, StatisticSet}; use crate::ScriptCategory; -use std::ffi::{c_char, CStr}; +use std::ffi::{c_char, CStr, CString}; use wasmer::FunctionEnvMut; register! { @@ -209,6 +210,200 @@ register! { pokemon.value_func(&env).unwrap().clear_status() } + fn pokemon_get_active_ability( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> ExternRef { + ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().active_ability()) + } + + fn pokemon_get_real_ability( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> (u8, u8) { + let index = &pokemon.value_func(&env).unwrap().real_ability(); + (if index.hidden { 1 } else { 0 }, index.index) + } + + fn pokemon_get_is_ability_overriden( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> u8 { + if pokemon.value_func(&env).unwrap().is_ability_overriden() { 1 } else { 0 } + } + + fn pokemon_get_allowed_experience_gain( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> u8 { + if pokemon.value_func(&env).unwrap().allowed_experience_gain() { 1 } else { 0 } + } + + fn pokemon_get_is_usable( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> u8 { + if pokemon.value_func(&env).unwrap().is_usable() { 1 } else { 0 } + } + + + fn pokemon_set_held_item( + env: FunctionEnvMut, + pokemon: ExternRef, + item: ExternRef + ) -> ExternRef { + let item = item.value_func_arc(&env).unwrap(); + let old_item = pokemon.value_func(&env).unwrap().set_held_item(&item); + if let Some(old_item) = old_item { + ExternRef::func_new(&env, &old_item) + } else { + ExternRef::null() + } + } + + fn pokemon_remove_held_item( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> ExternRef { + let old_item = pokemon.value_func(&env).unwrap().remove_held_item(); + if let Some(old_item) = old_item { + ExternRef::func_new(&env, &old_item) + } else { + ExternRef::null() + } + } + + fn pokemon_consume_held_item( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> u8 { + if pokemon.value_func(&env).unwrap().consume_held_item() { 1 } else { 0 } + } + + fn pokemon_get_types_length( + env: FunctionEnvMut, + pokemon: ExternRef + ) -> u32 { + pokemon.value_func(&env).unwrap().types().len() as u32 + } + + fn pokemon_get_type( + env: FunctionEnvMut, + pokemon: ExternRef, + index: u32 + ) -> u8 { + (*pokemon.value_func(&env).unwrap().types().get(index as usize).unwrap()).into() + } + + fn pokemon_has_type( + env: FunctionEnvMut, + pokemon: ExternRef, + t: u8 + ) -> u8 { + if pokemon.value_func(&env).unwrap().types().contains(&t.into()) { 1 } else { 0 } + } + + fn pokemon_change_species( + env: FunctionEnvMut, + pokemon: ExternRef, + species: ExternRef, + form: ExternRef, + ) { + pokemon.value_func(&env).unwrap().change_species( + species.value_func_arc(&env).unwrap(), + form.value_func_arc(&env).unwrap(), + ); + } + + fn pokemon_change_form( + env: FunctionEnvMut, + pokemon: ExternRef, + form: ExternRef, + ) { + pokemon.value_func(&env).unwrap().change_form( + &form.value_func_arc(&env).unwrap(), + ); + } + + fn pokemon_get_current_health( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> u32 { + pokemon.value_func(&env).unwrap().current_health() + } + + fn pokemon_get_nature( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> ExternRef { + ExternRef::func_new(&env, pokemon.value_func(&env).unwrap().nature()) + } + + fn pokemon_get_form( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> ExternRef { + ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().form()) + } + + fn pokemon_get_display_species( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> ExternRef { + ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().display_species()) + } + + fn pokemon_get_display_form( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> ExternRef { + ExternRef::func_new(&env, &pokemon.value_func(&env).unwrap().display_form()) + } + + fn pokemon_get_level( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> LevelInt { + pokemon.value_func(&env).unwrap().level() + } + + fn pokemon_get_experience( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> u32 { + pokemon.value_func(&env).unwrap().experience() + } + + fn pokemon_get_unique_identifier( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> u32 { + pokemon.value_func(&env).unwrap().unique_identifier() + } + + fn pokemon_get_coloring( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> u8 { + pokemon.value_func(&env).unwrap().coloring() + } + + fn pokemon_get_nickname( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> u32 { + let pokemon = pokemon.value_func(&env).unwrap(); + let nickname = pokemon.nickname(); + if let Some(nickname) = nickname { + let nickname: CString = CString::new(nickname.as_str()).unwrap(); + env.data().data().copy_value_vec_to_wasm(nickname.as_bytes()) + } else { + 0 + } + } + + + fn pokemon_add_volatile_by_name( env: FunctionEnvMut, pokemon: ExternRef, @@ -288,4 +483,18 @@ register! { } } + fn pokemon_get_ability_script( + env: FunctionEnvMut, + pokemon: ExternRef, + ) -> u32 { + let pokemon = pokemon.value_func(&env).unwrap(); + if let Some(script) = pokemon.ability_script().get() { + let read_lock = script.read(); + if let Some(script) = read_lock.as_ref() { + return script.as_any().downcast_ref::().unwrap().get_wasm_pointer() + } + } + 0 + } + } diff --git a/src/script_implementations/wasm/export_registry/dynamic_data/turn_choice.rs b/src/script_implementations/wasm/export_registry/dynamic_data/turn_choice.rs index c85ffbc..5cca35b 100755 --- a/src/script_implementations/wasm/export_registry/dynamic_data/turn_choice.rs +++ b/src/script_implementations/wasm/export_registry/dynamic_data/turn_choice.rs @@ -3,6 +3,7 @@ use std::ops::Deref; use crate::dynamic_data::{LearnedMove, Pokemon, TurnChoice}; use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::extern_ref::ExternRef; +use crate::script_implementations::wasm::script::WebAssemblyScript; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use wasmer::FunctionEnvMut; @@ -29,6 +30,38 @@ register! { } } + fn turn_choice_get_speed( + env: FunctionEnvMut, + turn_choice: ExternRef, + ) -> u32 { + turn_choice.value_func(&env).unwrap().speed() + } + + fn turn_choice_has_failed( + env: FunctionEnvMut, + turn_choice: ExternRef, + ) -> u8 { + if turn_choice.value_func(&env).unwrap().has_failed() { 1 } else { 0 } + } + + fn turn_choice_fail( + env: FunctionEnvMut, + turn_choice: ExternRef, + ) { + turn_choice.value_func(&env).unwrap().fail(); + } + + + fn turn_choice_move_priority( + env: FunctionEnvMut, + turn_choice: ExternRef, + ) -> i8 { + if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() { + return d.priority() + } + panic!("Invalid turn choice"); + } + fn turn_choice_move_used_move( env: FunctionEnvMut, turn_choice: ExternRef, @@ -59,11 +92,21 @@ register! { panic!("Invalid turn choice"); } - fn turn_choice_fail( + fn turn_choice_move_script( env: FunctionEnvMut, turn_choice: ExternRef, - ) { - turn_choice.value_func(&env).unwrap().fail(); + ) -> u32 { + if let TurnChoice::Move(d) = turn_choice.value_func(&env).unwrap() { + if let Some(script) = d.script().get() { + let read_lock = script.read(); + if let Some(script) = read_lock.as_ref() { + return script.as_any().downcast_ref::().unwrap().get_wasm_pointer() + } + } + return 0; + } + panic!("Invalid turn choice"); } + } diff --git a/src/script_implementations/wasm/export_registry/static_data/ability.rs b/src/script_implementations/wasm/export_registry/static_data/ability.rs new file mode 100644 index 0000000..4055a07 --- /dev/null +++ b/src/script_implementations/wasm/export_registry/static_data/ability.rs @@ -0,0 +1,34 @@ +use crate::script_implementations::wasm::export_registry::register; +use crate::script_implementations::wasm::export_registry::FunctionEnvMut; +use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; +use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; +use crate::static_data::{Ability, EffectParameter}; +use crate::StringKey; + +register! { + +fn ability_get_name( + env: FunctionEnvMut, + ability: ExternRef +) -> ExternRef { + let ability = ability.value_func_arc(&env).unwrap(); + ExternRef::func_new(&env, ability.name()) +} + +fn ability_get_effect( + env: FunctionEnvMut, + ability: ExternRef +) -> ExternRef { + let ability = ability.value_func_arc(&env).unwrap(); + ExternRef::func_new(&env, ability.effect()) +} + +fn ability_get_parameters( + env: FunctionEnvMut, + ability: ExternRef +) -> VecExternRef { + let ability = ability.value_func_arc(&env).unwrap(); + VecExternRef::new(env.data().data().as_ref(), ability.parameters()) +} + +} diff --git a/src/script_implementations/wasm/export_registry/static_data/form.rs b/src/script_implementations/wasm/export_registry/static_data/form.rs new file mode 100644 index 0000000..d592df2 --- /dev/null +++ b/src/script_implementations/wasm/export_registry/static_data/form.rs @@ -0,0 +1,82 @@ +use crate::script_implementations::wasm::export_registry::register; +use crate::script_implementations::wasm::export_registry::FunctionEnvMut; +use crate::script_implementations::wasm::extern_ref::{ExternRef, VecExternRef}; +use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; +use crate::static_data::{Form, StatisticSet}; +use crate::StringKey; + +register! { + +fn form_get_name( + env: FunctionEnvMut, + form: ExternRef +) -> ExternRef { + let form = form.value_func_arc(&env).unwrap(); + ExternRef::func_new(&env, form.name()) +} + +fn form_get_types( + env: FunctionEnvMut, + form: ExternRef +) -> (u32, u32) { + let form = form.value_func_arc(&env).unwrap(); + let vec = form.types(); + let wasm_ptr = env.data().data().copy_value_vec_to_wasm(vec); + (wasm_ptr, vec.len() as u32) +} + +fn form_get_height( + env: FunctionEnvMut, + form: ExternRef +) -> f32 { + form.value_func_arc(&env).unwrap().height() +} + +fn form_get_weight( + env: FunctionEnvMut, + form: ExternRef +) -> f32 { + form.value_func_arc(&env).unwrap().weight() +} + +fn form_get_base_experience( + env: FunctionEnvMut, + form: ExternRef +) -> u32 { + form.value_func_arc(&env).unwrap().base_experience() +} + +fn form_get_base_stats( + env: FunctionEnvMut, + form: ExternRef +) -> ExternRef> { + let form = form.value_func_arc(&env).unwrap(); + ExternRef::func_new(&env, form.base_stats()) +} + +fn form_get_abilities( + env: FunctionEnvMut, + form: ExternRef +) -> VecExternRef { + let form = form.value_func_arc(&env).unwrap(); + VecExternRef::new(env.data().data().as_ref(), form.abilities()) +} + +fn form_get_hidden_abilities( + env: FunctionEnvMut, + form: ExternRef +) -> VecExternRef { + let form = form.value_func_arc(&env).unwrap(); + VecExternRef::new(env.data().data().as_ref(), form.hidden_abilities()) +} + +fn form_has_flag_by_hash( + env: FunctionEnvMut, + form: ExternRef, + flag_hash: u32, +) -> u8 { + if form.value_func_arc(&env).unwrap().has_flag_by_hash(flag_hash) { 1 } else { 0 } +} + + +} diff --git a/src/script_implementations/wasm/export_registry/static_data/item.rs b/src/script_implementations/wasm/export_registry/static_data/item.rs index 67221e3..be8c750 100755 --- a/src/script_implementations/wasm/export_registry/static_data/item.rs +++ b/src/script_implementations/wasm/export_registry/static_data/item.rs @@ -32,7 +32,6 @@ register! { } } - fn item_get_price( env: FunctionEnvMut, item: ExternRef, @@ -60,4 +59,13 @@ register! { ) -> u8 { unsafe { transmute(item.value_func_arc(&env).unwrap().battle_category()) } } + + fn item_has_flag( + env: FunctionEnvMut, + item: ExternRef, + key: ExternRef + ) -> u8 { + if item.value_func_arc(&env).unwrap().has_flag(key.value_func(&env).unwrap()) { 1 } else { 0 } + } + } diff --git a/src/script_implementations/wasm/export_registry/static_data/mod.rs b/src/script_implementations/wasm/export_registry/static_data/mod.rs index ea0e88d..9f46317 100755 --- a/src/script_implementations/wasm/export_registry/static_data/mod.rs +++ b/src/script_implementations/wasm/export_registry/static_data/mod.rs @@ -6,15 +6,24 @@ use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; use crate::static_data::{ - ItemLibrary, LibrarySettings, MoveLibrary, SpeciesLibrary, StaticData, StatisticSet, TypeLibrary, + ItemLibrary, LibrarySettings, MoveLibrary, SpeciesLibrary, StaticData, StaticStatisticSet, StatisticSet, + TypeLibrary, }; +/// Ability data registration +mod ability; +/// Form data registration +mod form; /// Item registration. mod item; /// Moves data registration mod moves; +/// Nature data registration +mod nature; /// Species data registration mod species; +/// Types data registration +mod types; register! { fn static_data_get_move_library(env: FunctionEnvMut, data_library: ExternRef) -> ExternRef { @@ -47,12 +56,38 @@ register! { data_library.value_func_box(&env).unwrap().maximum_level() } + fn static_statistics_set_get_stat(env: FunctionEnvMut, statistics_set: ExternRef>, stat: u8) -> u32 { + unsafe { + statistics_set.value_func(&env).unwrap().get_stat(transmute(stat)) as u32 + } + } + fn statistic_set_get(env: FunctionEnvMut, statistics_set: ExternRef>, stat: u8) -> i64 { unsafe { statistics_set.value_func(&env).unwrap().get_stat(transmute(stat)) as i64 } } + fn statistic_set_set(env: FunctionEnvMut, statistics_set: ExternRef>, stat: u8, value: u64) { + unsafe { + statistics_set.value_func(&env).unwrap().set_stat(transmute(stat), value as u32) + } + } + + fn statistic_set_increase_stat(env: FunctionEnvMut, statistics_set: ExternRef>, stat: u8, value: u64) { + unsafe { + statistics_set.value_func(&env).unwrap().increase_stat(transmute(stat), value as u32) + } + } + + fn statistic_set_decrease_stat(env: FunctionEnvMut, statistics_set: ExternRef>, stat: u8, value: u64) { + unsafe { + statistics_set.value_func(&env).unwrap().decrease_stat(transmute(stat), value as u32) + } + } + + + manual manual_registration } @@ -61,4 +96,8 @@ fn manual_registration(imports: &mut Imports, store: &mut StoreMut, env: &Functi moves::register(imports, store, env); species::register(imports, store, env); item::register(imports, store, env); + nature::register(imports, store, env); + form::register(imports, store, env); + ability::register(imports, store, env); + types::register(imports, store, env); } diff --git a/src/script_implementations/wasm/export_registry/static_data/nature.rs b/src/script_implementations/wasm/export_registry/static_data/nature.rs new file mode 100644 index 0000000..f370c49 --- /dev/null +++ b/src/script_implementations/wasm/export_registry/static_data/nature.rs @@ -0,0 +1,33 @@ +use crate::script_implementations::wasm::export_registry::register; +use crate::script_implementations::wasm::extern_ref::ExternRef; +use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; +use crate::static_data::Nature; +use std::mem::transmute; +use wasmer::FunctionEnvMut; + +register! { +fn nature_get_increase_stat( + env: FunctionEnvMut, + nature: ExternRef +) -> u8 { + unsafe { transmute(nature.value_func_box(&env).unwrap().increased_stat()) } +} +fn nature_get_decrease_stat( + env: FunctionEnvMut, + nature: ExternRef +) -> u8 { + unsafe { transmute(nature.value_func_box(&env).unwrap().decreased_stat()) } +} +fn nature_get_increase_modifier( + env: FunctionEnvMut, + nature: ExternRef +) -> f32 { + nature.value_func_box(&env).unwrap().increased_modifier() +} +fn nature_get_decrease_modifier( + env: FunctionEnvMut, + nature: ExternRef +) -> f32 { + nature.value_func_box(&env).unwrap().decreased_modifier() +} +} diff --git a/src/script_implementations/wasm/export_registry/static_data/species.rs b/src/script_implementations/wasm/export_registry/static_data/species.rs index 68aea50..5793c16 100755 --- a/src/script_implementations/wasm/export_registry/static_data/species.rs +++ b/src/script_implementations/wasm/export_registry/static_data/species.rs @@ -1,8 +1,8 @@ use crate::script_implementations::wasm::export_registry::register; use crate::script_implementations::wasm::extern_ref::ExternRef; use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; -use crate::static_data::Species; use crate::static_data::SpeciesLibrary; +use crate::static_data::{Form, Species}; use crate::StringKey; use wasmer::FunctionEnvMut; @@ -59,5 +59,27 @@ fn species_get_id( species.value_func_arc(&env).unwrap().id() } +fn species_get_form_by_hash( + env: FunctionEnvMut, + species: ExternRef, + form_hash: u32 +) -> ExternRef { + let species = species.value_func_arc(&env).unwrap(); + let form = species.get_form_by_hash(form_hash); + if let Some(form) = form { + ExternRef::func_new(&env, &form) + } else { + ExternRef::null() + } +} + +fn species_has_flag_by_hash( + env: FunctionEnvMut, + species: ExternRef, + flag_hash: u32 +) -> u8 { + if species.value_func_arc(&env).unwrap().has_flag_by_hash(flag_hash) { 1 } else { 0 } +} + } diff --git a/src/script_implementations/wasm/export_registry/static_data/types.rs b/src/script_implementations/wasm/export_registry/static_data/types.rs new file mode 100644 index 0000000..81ac68f --- /dev/null +++ b/src/script_implementations/wasm/export_registry/static_data/types.rs @@ -0,0 +1,35 @@ +use crate::script_implementations::wasm::export_registry::register; +use crate::script_implementations::wasm::export_registry::FunctionEnvMut; +use crate::script_implementations::wasm::extern_ref::ExternRef; +use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv; +use crate::static_data::TypeLibrary; +use crate::StringKey; + +register! { + + fn type_library_get_type_by_name( + env: FunctionEnvMut, + lib: ExternRef, + name: ExternRef + ) -> u8 { + let lib = lib.value_func_arc(&env).unwrap(); + let name = name.value_func(&env).unwrap(); + let type_id = lib.get_type_id(name); + if let Some(type_id) = type_id { + type_id.into() + } else { + 0 + } + } + + fn type_library_get_single_effectiveness( + env: FunctionEnvMut, + lib: ExternRef, + attacking: u8, + defending: u8 + ) -> f32 { + let lib = lib.value_func_arc(&env).unwrap(); + lib.get_single_effectiveness(attacking.into(), defending.into()) + } + +} diff --git a/src/script_implementations/wasm/script_resolver.rs b/src/script_implementations/wasm/script_resolver.rs index 698fc72..1edb730 100755 --- a/src/script_implementations/wasm/script_resolver.rs +++ b/src/script_implementations/wasm/script_resolver.rs @@ -344,6 +344,27 @@ impl WebAssemblyEnvironmentData { unsafe { (self.memory().offset(wasm_ptr as isize), wasm_ptr) } } + /// Allocates a raw array in wasm, and copy the values from a given slice to it. Returns the + /// pointer in wasm memory. + pub fn copy_value_vec_to_wasm(&self, v: &[T]) -> u32 { + let wasm_ptr = self + .allocate_mem_fn + .read() + .as_ref() + .unwrap() + .call( + &mut self.store_mut(), + (size_of::() * v.len()) as u32, + align_of::() as u32, + ) + .unwrap(); + unsafe { + let raw = self.memory().offset(wasm_ptr as isize) as *mut T; + v.as_ptr().copy_to(raw, v.len()); + } + wasm_ptr + } + /// 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. diff --git a/src/static_data/natures.rs b/src/static_data/natures.rs index e80aff8..d8382c8 100755 --- a/src/static_data/natures.rs +++ b/src/static_data/natures.rs @@ -12,6 +12,12 @@ pub trait Nature: ValueIdentifiable + Debug { /// The stat that should receive the decreased modifier. fn decreased_stat(&self) -> Statistic; + /// The amount that the increased stat gets modified by. + fn increased_modifier(&self) -> f32; + + /// The amount that the decreased stat gets modified by. + fn decreased_modifier(&self) -> f32; + /// Calculates the modifier for a given stat. If it's the increased stat, returns the increased /// modifier, if it's the decreased stat, returns the decreased modifier. Otherwise returns 1.0 fn get_stat_modifier(&self, stat: Statistic) -> f32; @@ -62,6 +68,14 @@ impl Nature for NatureImpl { self.decrease_stat } + fn increased_modifier(&self) -> f32 { + self.increase_modifier + } + + fn decreased_modifier(&self) -> f32 { + self.decrease_modifier + } + /// Calculates the modifier for a given stat. If it's the increased stat, returns the increased /// modifier, if it's the decreased stat, returns the decreased modifier. Otherwise returns 1.0 fn get_stat_modifier(&self, stat: Statistic) -> f32 { @@ -91,6 +105,8 @@ pub(crate) mod tests { impl Nature for Nature { fn increased_stat(&self) -> Statistic; fn decreased_stat(&self) -> Statistic; + fn increased_modifier(&self) -> f32; + fn decreased_modifier(&self) -> f32; fn get_stat_modifier(&self, stat: Statistic) -> f32; } impl ValueIdentifiable for Nature { diff --git a/src/static_data/species_data/form.rs b/src/static_data/species_data/form.rs index 53b8b5a..cb5df3a 100755 --- a/src/static_data/species_data/form.rs +++ b/src/static_data/species_data/form.rs @@ -51,6 +51,9 @@ pub trait Form: ValueIdentifiable + Debug { /// Check if the form has a specific flag set. fn has_flag(&self, key: &StringKey) -> bool; + + /// Arbitrary flags that can be applied to the move. + fn has_flag_by_hash(&self, key_hash: u32) -> bool; } /// A form is a variant of a specific species. A species always has at least one form, but can have @@ -207,6 +210,10 @@ impl Form for FormImpl { fn has_flag(&self, key: &StringKey) -> bool { self.flags.contains(key) } + + fn has_flag_by_hash(&self, key_hash: u32) -> bool { + self.flags.contains::(&key_hash) + } } impl ValueIdentifiable for FormImpl { @@ -240,6 +247,7 @@ pub(crate) mod tests { fn get_random_ability(&self, rand: &mut Random) -> &StringKey; fn get_random_hidden_ability(&self, rand: &mut Random) -> &StringKey; fn has_flag(&self, key: &StringKey) -> bool; + fn has_flag_by_hash(&self, key_hash: u32) -> bool; } impl ValueIdentifiable for Form { fn value_identifier(&self) -> ValueIdentifier { diff --git a/src/static_data/species_data/species.rs b/src/static_data/species_data/species.rs index 18352d3..29bd86a 100755 --- a/src/static_data/species_data/species.rs +++ b/src/static_data/species_data/species.rs @@ -31,12 +31,16 @@ pub trait Species: ValueIdentifiable + Debug { fn add_form(&self, id: StringKey, form: Arc); /// Gets a form by name. fn get_form(&self, id: &StringKey) -> Option>; + /// Gets a form by the hash of its name. + fn get_form_by_hash(&self, name_hash: u32) -> Option>; /// Gets the form the Pokemon will have by default, if no other form is specified. fn get_default_form(&self) -> Arc; /// Gets a random gender. fn get_random_gender(&self, rand: &mut Random) -> Gender; /// Check whether the Pokemon has a specific flag set. fn has_flag(&self, key: &StringKey) -> bool; + /// Check whether the Pokemon has a specific flag set. + fn has_flag_by_hash(&self, key_hash: u32) -> bool; } /// The data belonging to a Pokemon with certain characteristics. @@ -136,6 +140,10 @@ impl Species for SpeciesImpl { self.forms.read().get(id).cloned() } + fn get_form_by_hash(&self, name_hash: u32) -> Option> { + self.forms.read().get::(&name_hash).cloned() + } + /// Gets the form the Pokemon will have by default, if no other form is specified. fn get_default_form(&self) -> Arc { self.forms.read().get(&get_default_key()).unwrap().clone() @@ -156,6 +164,10 @@ impl Species for SpeciesImpl { fn has_flag(&self, key: &StringKey) -> bool { self.flags.contains(key) } + + fn has_flag_by_hash(&self, key_hash: u32) -> bool { + self.flags.contains::(&key_hash) + } } impl ValueIdentifiable for SpeciesImpl { @@ -181,9 +193,11 @@ pub(crate) mod tests { fn flags(&self) -> &HashSet; fn add_form(&self, id: StringKey, form: Arc); fn get_form(&self, id: &StringKey) -> Option>; + fn get_form_by_hash(&self, name_hash: u32) -> Option>; fn get_default_form(&self) -> Arc; fn get_random_gender(&self, rand: &mut Random) -> Gender; fn has_flag(&self, key: &StringKey) -> bool; + fn has_flag_by_hash(&self, key_hash: u32) -> bool; } impl ValueIdentifiable for Species { fn value_identifier(&self) -> ValueIdentifier { diff --git a/tests/data/gen7_scripts.wasm b/tests/data/gen7_scripts.wasm index 4ccdd18..6cb4d83 100755 Binary files a/tests/data/gen7_scripts.wasm and b/tests/data/gen7_scripts.wasm differ