Support for errors from scripts through separate script error handling.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
a6f4b1d5c5
commit
eb68977290
|
@ -353,7 +353,7 @@ impl Battle {
|
|||
if let Some(script) = self.weather.get() {
|
||||
let lock = script.read();
|
||||
Ok(Some(
|
||||
lock.as_ref().ok_or(PkmnError::UnableToAcquireLock)?.name().clone(),
|
||||
lock.as_ref().ok_or(PkmnError::UnableToAcquireLock)?.name()?.clone(),
|
||||
))
|
||||
} else {
|
||||
Ok(None)
|
||||
|
|
|
@ -535,11 +535,18 @@ impl Pokemon {
|
|||
.library
|
||||
.load_script(self.into(), ScriptCategory::Ability, ability.name())?;
|
||||
if let Some(ability_script) = ability_script {
|
||||
self.ability_script
|
||||
let script_result = self
|
||||
.ability_script
|
||||
.set(ability_script)
|
||||
.as_ref()
|
||||
// Ensure the ability script gets initialized with the parameters for the ability.
|
||||
.on_initialize(&self.library, ability.parameters().to_vec())
|
||||
.on_initialize(&self.library, ability.parameters().to_vec());
|
||||
match script_result {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
crate::dynamic_data::script_handling::handle_script_error(&e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.ability_script.clear();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::sync::{Arc, LazyLock, Weak};
|
||||
|
||||
use parking_lot::RwLock;
|
||||
|
||||
|
@ -33,7 +33,12 @@ macro_rules! script_hook {
|
|||
if let Some(script) = script {
|
||||
if let Some(script) = script.read().as_deref() {
|
||||
if !script.is_suppressed() {
|
||||
script.$hook_name($($parameters),*);
|
||||
match script.$hook_name($($parameters),*) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
$crate::dynamic_data::script_handling::handle_script_error(&e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +58,12 @@ macro_rules! run_scripts {
|
|||
let s = s.read();
|
||||
if let Some(s) = s.deref() {
|
||||
if !s.is_suppressed() {
|
||||
s.$hook_name($($parameters),*);
|
||||
match s.$hook_name($($parameters),*) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
$crate::dynamic_data::script_handling::handle_script_error(&e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,8 +75,13 @@ macro_rules! run_scripts {
|
|||
if let Some(s) = s.get() {
|
||||
let s = s.read();
|
||||
if let Some(s) = s.deref() {
|
||||
if !s.is_suppressed() && set.has(s.name()) {
|
||||
s.$hook_name($($parameters),*);
|
||||
if !s.is_suppressed() && set.has(s.name()?) {
|
||||
match s.$hook_name($($parameters),*) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
$crate::dynamic_data::script_handling::handle_script_error(&e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +93,35 @@ macro_rules! run_scripts {
|
|||
};
|
||||
}
|
||||
|
||||
/// When a script encounters an error, this function should be called. This allows the implementation
|
||||
/// to define how to handle script errors.
|
||||
pub(crate) fn handle_script_error(e: &anyhow_ext::Error) {
|
||||
unsafe {
|
||||
(HANDLE_SCRIPT_ERROR_IMPL.read())(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of the function that is called when a script encounters an error.
|
||||
type ScriptErrorFunction = Box<dyn Fn(&anyhow_ext::Error)>;
|
||||
|
||||
/// The currently set script error handler.
|
||||
static mut HANDLE_SCRIPT_ERROR_IMPL: LazyLock<RwLock<ScriptErrorFunction>> =
|
||||
LazyLock::new(|| RwLock::new(Box::new(default_script_error_handler)));
|
||||
|
||||
/// The default script error handler. This will panic with the error message. As this can (and should)
|
||||
/// be changed by the implementation, we allow panics here.
|
||||
#[allow(clippy::panic)]
|
||||
fn default_script_error_handler(e: &anyhow_ext::Error) {
|
||||
panic!("Script error: {}", e);
|
||||
}
|
||||
|
||||
/// Sets the script error handler to the given function.
|
||||
pub fn set_script_error_handler(f: ScriptErrorFunction) {
|
||||
unsafe {
|
||||
*HANDLE_SCRIPT_ERROR_IMPL.write() = f;
|
||||
}
|
||||
}
|
||||
|
||||
/// The script source data is the basic data required for any script source.
|
||||
#[derive(Default, Debug)]
|
||||
pub struct ScriptSourceData {
|
||||
|
@ -279,8 +323,8 @@ mod tests {
|
|||
}
|
||||
|
||||
impl Script for TestScript {
|
||||
fn name(&self) -> &StringKey {
|
||||
&self.name
|
||||
fn name(&self) -> Result<&StringKey> {
|
||||
Ok(&self.name)
|
||||
}
|
||||
|
||||
fn get_marked_for_deletion(&self) -> &AtomicBool {
|
||||
|
@ -295,8 +339,9 @@ mod tests {
|
|||
|
||||
fn remove_suppression(&self) {}
|
||||
|
||||
fn stack(&self) {
|
||||
fn stack(&self) -> Result<()> {
|
||||
self.test_count.fetch_add(1, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
|
@ -314,7 +359,7 @@ mod tests {
|
|||
let scripts = vec![ScriptWrapper::from(&script)];
|
||||
let mut aggregator = ScriptIterator::new(&scripts as *const Vec<ScriptWrapper>);
|
||||
while let Some(v) = aggregator.get_next().unwrap() {
|
||||
v.get().unwrap().read().as_ref().unwrap().stack();
|
||||
v.get().unwrap().read().as_ref().unwrap().stack().unwrap();
|
||||
}
|
||||
let a = script.get_as::<TestScript>().unwrap();
|
||||
assert_eq!(a.test_count.load(Ordering::Relaxed), 1);
|
||||
|
@ -328,7 +373,7 @@ mod tests {
|
|||
for i in 1..11 {
|
||||
aggregator.reset();
|
||||
while let Some(v) = aggregator.get_next().unwrap() {
|
||||
v.get().unwrap().read().as_ref().unwrap().stack();
|
||||
v.get().unwrap().read().as_ref().unwrap().stack().unwrap();
|
||||
}
|
||||
let a = script.get_as::<TestScript>().unwrap();
|
||||
assert_eq!(a.test_count.load(Ordering::Relaxed), i);
|
||||
|
@ -347,7 +392,7 @@ mod tests {
|
|||
];
|
||||
let mut aggregator = ScriptIterator::new(&scripts as *const Vec<ScriptWrapper>);
|
||||
while let Some(v) = aggregator.get_next().unwrap() {
|
||||
v.get().unwrap().read().as_ref().unwrap().stack();
|
||||
v.get().unwrap().read().as_ref().unwrap().stack().unwrap();
|
||||
}
|
||||
let a = script1.get_as::<TestScript>().unwrap();
|
||||
assert_eq!(a.test_count.load(Ordering::Relaxed), 1);
|
||||
|
@ -371,7 +416,7 @@ mod tests {
|
|||
for i in 1..11 {
|
||||
aggregator.reset();
|
||||
while let Some(v) = aggregator.get_next().unwrap() {
|
||||
v.get().unwrap().read().as_ref().unwrap().stack();
|
||||
v.get().unwrap().read().as_ref().unwrap().stack().unwrap();
|
||||
}
|
||||
let a = script1.get_as::<TestScript>().unwrap();
|
||||
assert_eq!(a.test_count.load(Ordering::Relaxed), i);
|
||||
|
@ -385,38 +430,38 @@ mod tests {
|
|||
#[test]
|
||||
fn script_aggregator_property_iterates_script_set() {
|
||||
let set = Arc::new(ScriptSet::default());
|
||||
set.add(Arc::new(TestScript::new_with_name("test_a")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_b")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_c")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_a"))).unwrap();
|
||||
set.add(Arc::new(TestScript::new_with_name("test_b"))).unwrap();
|
||||
set.add(Arc::new(TestScript::new_with_name("test_c"))).unwrap();
|
||||
|
||||
let scripts = vec![ScriptWrapper::from(&set)];
|
||||
let mut aggregator = ScriptIterator::new(&scripts as *const Vec<ScriptWrapper>);
|
||||
for i in 1..11 {
|
||||
aggregator.reset();
|
||||
while let Some(v) = aggregator.get_next().unwrap() {
|
||||
v.get().unwrap().read().as_ref().unwrap().stack();
|
||||
v.get().unwrap().read().as_ref().unwrap().stack().unwrap();
|
||||
}
|
||||
let s = set.at(0).unwrap();
|
||||
let s = s.get_as::<TestScript>().unwrap();
|
||||
assert_eq!(s.test_count.load(Ordering::Relaxed), i);
|
||||
assert_eq!(s.name().str(), "test_a");
|
||||
assert_eq!(s.name().unwrap().str(), "test_a");
|
||||
let s = set.at(1).unwrap();
|
||||
let s = s.get_as::<TestScript>().unwrap();
|
||||
assert_eq!(s.test_count.load(Ordering::Relaxed), i);
|
||||
assert_eq!(s.name().str(), "test_b");
|
||||
assert_eq!(s.name().unwrap().str(), "test_b");
|
||||
let s = set.at(2).unwrap();
|
||||
let s = s.get_as::<TestScript>().unwrap();
|
||||
assert_eq!(s.test_count.load(Ordering::Relaxed), i);
|
||||
assert_eq!(s.name().str(), "test_c");
|
||||
assert_eq!(s.name().unwrap().str(), "test_c");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn script_aggregator_property_iterates_script_set_when_removing_last() {
|
||||
let set = Arc::new(ScriptSet::default());
|
||||
set.add(Arc::new(TestScript::new_with_name("test_a")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_b")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_c")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_a"))).unwrap();
|
||||
set.add(Arc::new(TestScript::new_with_name("test_b"))).unwrap();
|
||||
set.add(Arc::new(TestScript::new_with_name("test_c"))).unwrap();
|
||||
|
||||
let scripts = vec![ScriptWrapper::from(&set)];
|
||||
let mut aggregator = ScriptIterator::new(&scripts as *const Vec<ScriptWrapper>);
|
||||
|
@ -431,6 +476,7 @@ mod tests {
|
|||
.as_ref()
|
||||
.unwrap()
|
||||
.name()
|
||||
.unwrap()
|
||||
.str(),
|
||||
"test_a"
|
||||
);
|
||||
|
@ -445,6 +491,7 @@ mod tests {
|
|||
.as_ref()
|
||||
.unwrap()
|
||||
.name()
|
||||
.unwrap()
|
||||
.str(),
|
||||
"test_b"
|
||||
);
|
||||
|
@ -456,9 +503,9 @@ mod tests {
|
|||
#[test]
|
||||
fn script_aggregator_property_iterates_script_set_when_removing_middle() {
|
||||
let set = Arc::new(ScriptSet::default());
|
||||
set.add(Arc::new(TestScript::new_with_name("test_a")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_b")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_c")));
|
||||
set.add(Arc::new(TestScript::new_with_name("test_a"))).unwrap();
|
||||
set.add(Arc::new(TestScript::new_with_name("test_b"))).unwrap();
|
||||
set.add(Arc::new(TestScript::new_with_name("test_c"))).unwrap();
|
||||
|
||||
let scripts = vec![ScriptWrapper::from(&set)];
|
||||
let mut aggregator = ScriptIterator::new(&scripts as *const Vec<ScriptWrapper>);
|
||||
|
@ -473,6 +520,7 @@ mod tests {
|
|||
.as_ref()
|
||||
.unwrap()
|
||||
.name()
|
||||
.unwrap()
|
||||
.str(),
|
||||
"test_a"
|
||||
);
|
||||
|
@ -490,6 +538,7 @@ mod tests {
|
|||
.as_ref()
|
||||
.unwrap()
|
||||
.name()
|
||||
.unwrap()
|
||||
.str(),
|
||||
"test_c"
|
||||
);
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::StringKey;
|
|||
pub trait Script: Send + Sync {
|
||||
/// The name of a script is its unique identifier. This should generally be set on load, and be
|
||||
/// the same as the key that was used to load it.
|
||||
fn name(&self) -> &StringKey;
|
||||
fn name(&self) -> Result<&StringKey>;
|
||||
/// Returns an atomic bool for internal marking of deletion. This is currently only specifically
|
||||
/// used for deletion of a script while we are holding a reference to it (i.e. executing a script
|
||||
///hook on it).
|
||||
|
@ -61,50 +61,80 @@ pub trait Script: Send + Sync {
|
|||
|
||||
/// This function is ran when a volatile effect is added while that volatile effect already is
|
||||
/// in place. Instead of adding the volatile effect twice, it will execute this function instead.
|
||||
fn stack(&self) {}
|
||||
fn stack(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is ran when this script stops being in effect, and is removed from its owner.
|
||||
fn on_remove(&self) {}
|
||||
fn on_remove(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is ran when this script starts being in effect.
|
||||
fn on_initialize(&self, _library: &Arc<dyn DynamicLibrary>, _pars: Vec<EffectParameter>) {}
|
||||
fn on_initialize(&self, _library: &Arc<dyn DynamicLibrary>, _pars: Vec<EffectParameter>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is ran just before the start of the turn. Everyone has made its choices here,
|
||||
/// and the turn is about to start. This is a great place to initialize data if you need to know
|
||||
/// something has happened during a turn.
|
||||
fn on_before_turn(&self, _choice: &TurnChoice) {}
|
||||
fn on_before_turn(&self, _choice: &TurnChoice) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows you to modify the effective speed of the Pokemon. This is ran before
|
||||
/// turn ordering, so overriding here will allow you to put certain Pokemon before others.
|
||||
fn change_speed(&self, _choice: &TurnChoice, _speed: &mut u32) {}
|
||||
fn change_speed(&self, _choice: &TurnChoice, _speed: &mut u32) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows you to modify the effective priority of the Pokemon. This is ran before
|
||||
/// turn ordering, so overriding here will allow you to put certain Pokemon before others. Note
|
||||
/// that this is only relevant on move choices, as other turn choice types do not have a priority.
|
||||
fn change_priority(&self, _choice: &TurnChoice, _priority: &mut i8) {}
|
||||
fn change_priority(&self, _choice: &TurnChoice, _priority: &mut i8) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This function allows you to change the move that is used during execution. This is useful for
|
||||
/// moves such as metronome, where the move chosen actually differs from the move used.
|
||||
fn change_move(&self, _choice: &TurnChoice, _move_name: &mut StringKey) {}
|
||||
fn change_move(&self, _choice: &TurnChoice, _move_name: &mut StringKey) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows you to change a move into a multi-hit move. The number of hits set here
|
||||
/// gets used as the number of hits. If set to 0, this will behave as if the move missed on its
|
||||
/// first hit.
|
||||
fn change_number_of_hits(&self, _choice: &TurnChoice, _number_of_hits: &mut u8) {}
|
||||
fn change_number_of_hits(&self, _choice: &TurnChoice, _number_of_hits: &mut u8) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This function allows you to prevent a move from running. If this gets set to true, the move
|
||||
/// ends execution here. No PP will be decreased in this case.
|
||||
fn prevent_move(&self, _move: &ExecutingMove, _prevent: &mut bool) {}
|
||||
fn prevent_move(&self, _move: &ExecutingMove, _prevent: &mut bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function makes the move fail. If the fail field gets set to true, the move ends execution,
|
||||
/// and fail events get triggered.
|
||||
fn fail_move(&self, _move: &ExecutingMove, _fail: &mut bool) {}
|
||||
fn fail_move(&self, _move: &ExecutingMove, _fail: &mut bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// Similar to [`Self::prevent_move`]. This function will also stop execution, but PP will be
|
||||
/// decreased.
|
||||
fn stop_before_move(&self, _move: &ExecutingMove, _stop: &mut bool) {}
|
||||
fn stop_before_move(&self, _move: &ExecutingMove, _stop: &mut bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function runs just before the move starts its execution.
|
||||
fn on_before_move(&self, _move: &ExecutingMove) {}
|
||||
fn on_before_move(&self, _move: &ExecutingMove) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to prevent a move that is targeted at its owner. If set to true
|
||||
/// the move fails, and fail events get triggered.
|
||||
fn fail_incoming_move(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _fail: &mut bool) {}
|
||||
fn fail_incoming_move(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _fail: &mut bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to make its owner invulnerable to an incoming move.
|
||||
fn is_invulnerable(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _invulnerable: &mut bool) {}
|
||||
fn is_invulnerable(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _invulnerable: &mut bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function occurs when a move gets missed. This runs on the scripts belonging to the executing
|
||||
/// move, which include the scripts that are attached to the owner of the script.
|
||||
fn on_move_miss(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>) {}
|
||||
fn on_move_miss(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows the script to change the actual type that is used for the move on a target.
|
||||
fn change_move_type(
|
||||
&self,
|
||||
|
@ -112,12 +142,29 @@ pub trait Script: Send + Sync {
|
|||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_move_type: &mut TypeIdentifier,
|
||||
) {
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows the script to change how effective a move is on a target.
|
||||
fn change_effectiveness(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _effectiveness: &mut f32) {}
|
||||
fn change_effectiveness(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_effectiveness: &mut f32,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to block an outgoing move from being critical.
|
||||
fn block_critical(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _block_critical: &mut bool) {}
|
||||
fn block_critical(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_block_critical: &mut bool,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to block an incoming move from being critical.
|
||||
fn block_incoming_critical(
|
||||
&self,
|
||||
|
@ -125,33 +172,104 @@ pub trait Script: Send + Sync {
|
|||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_block_critical: &mut bool,
|
||||
) {
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to modify the accuracy of a move used. This value represents
|
||||
/// the percentage accuracy, so anything above 100% will make it always hit.
|
||||
fn change_accuracy(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _accuracy: &mut u8) {}
|
||||
fn change_accuracy(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_accuracy: &mut u8,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This function allows a script to change the critical stage of the move used.
|
||||
fn change_critical_stage(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _stage: &mut u8) {}
|
||||
fn change_critical_stage(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_stage: &mut u8,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to change the damage modifier of a critical hit. This will only
|
||||
/// run when a hit is critical.
|
||||
fn change_critical_modifier(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _modifier: &mut f32) {}
|
||||
fn change_critical_modifier(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_modifier: &mut f32,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to change the damage modifier of a Same Type Attack Bonus, which
|
||||
/// occurs when the user has the move type as one of its own types.
|
||||
fn change_stab_modifier(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _modifier: &mut f32) {}
|
||||
fn change_stab_modifier(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_modifier: &mut f32,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This function allows a script to change the effective base power of a move hit.
|
||||
fn change_base_power(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _base_power: &mut u8) {}
|
||||
fn change_base_power(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_base_power: &mut u8,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to bypass defensive stat boosts for a move hit.
|
||||
fn bypass_defensive_stat_boost(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _bypass: &mut bool) {
|
||||
fn bypass_defensive_stat_boost(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_bypass: &mut bool,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to bypass offensive stat boosts for a move hit.
|
||||
fn bypass_offensive_stat_boost(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _bypass: &mut bool) {
|
||||
fn bypass_offensive_stat_boost(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_bypass: &mut bool,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to change the actual offensive stat values used when calculating damage
|
||||
fn change_offensive_stat_value(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _amount: &mut u32) {}
|
||||
fn change_offensive_stat_value(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_amount: &mut u32,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to change the actual defensive stat values used when calculating damage.
|
||||
fn change_defensive_stat_value(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _amount: &mut u32) {}
|
||||
fn change_defensive_stat_value(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_amount: &mut u32,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// This function allows a script to change the raw modifier we retrieved from the stats of the
|
||||
/// defender and attacker.
|
||||
|
@ -161,19 +279,42 @@ pub trait Script: Send + Sync {
|
|||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_modifier: &mut f32,
|
||||
) {
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to apply a raw multiplier to the damage done by a move.
|
||||
fn change_damage_modifier(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _modifier: &mut f32) {}
|
||||
fn change_damage_modifier(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_modifier: &mut f32,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to modify the outgoing damage done by a move.
|
||||
fn change_damage(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _damage: &mut u32) {}
|
||||
fn change_damage(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _damage: &mut u32) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script to modify the incoming damage done by a move.
|
||||
fn change_incoming_damage(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _damage: &mut u32) {}
|
||||
fn change_incoming_damage(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_damage: &mut u32,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function triggers when an incoming hit happens. This triggers after the damage is done,
|
||||
/// but before the secondary effect of the move happens.
|
||||
fn on_incoming_hit(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8) {}
|
||||
fn on_incoming_hit(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function triggers when an opponent on the field faints.
|
||||
fn on_opponent_faints(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8) {}
|
||||
fn on_opponent_faints(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script attached to a Pokemon or its parents to prevent stat boost
|
||||
/// changes on that Pokemon.
|
||||
fn prevent_stat_boost_change(
|
||||
|
@ -183,21 +324,46 @@ pub trait Script: Send + Sync {
|
|||
_amount: i8,
|
||||
_self_inflicted: bool,
|
||||
_prevent: &mut bool,
|
||||
) {
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script attached to a Pokemon or its parents to modify the amount by
|
||||
/// which the stat boost will change. If the stat boost is done by the user itself, self
|
||||
/// inflicted will be true, otherwise it will be false.
|
||||
fn change_stat_boost_change(&self, _target: &Pokemon, _stat: Statistic, _self_inflicted: bool, _amount: &mut i8) {}
|
||||
fn change_stat_boost_change(
|
||||
&self,
|
||||
_target: &Pokemon,
|
||||
_stat: Statistic,
|
||||
_self_inflicted: bool,
|
||||
_amount: &mut i8,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script attached to a Pokemon or its parents to prevent an incoming
|
||||
/// secondary effect. This means the move will still hit and do damage, but not trigger its
|
||||
/// secondary effect. Note that this function is not called for status moves.
|
||||
fn prevent_secondary_effect(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _prevent: &mut bool) {}
|
||||
fn prevent_secondary_effect(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_prevent: &mut bool,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script attached to a move or its parents to change the chance the
|
||||
/// secondary effect of a move will trigger. The chance is depicted in percentage here, so
|
||||
/// changing this to above or equal to 100 will make it always hit, while setting it to equal or
|
||||
/// below 0 will make it never hit.
|
||||
fn change_effect_chance(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _chance: &mut f32) {}
|
||||
fn change_effect_chance(
|
||||
&self,
|
||||
_move: &ExecutingMove,
|
||||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_chance: &mut f32,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows a script attached to a Pokemon or its parents to change the chance the
|
||||
/// secondary effect of an incoming move will trigger. The chance is depicted in percentage here,
|
||||
/// so changing this to above or equal to 100 will make it always hit, while setting it to equal
|
||||
|
@ -208,53 +374,93 @@ pub trait Script: Send + Sync {
|
|||
_target: &Arc<Pokemon>,
|
||||
_hit: u8,
|
||||
_chance: &mut f32,
|
||||
) {
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function triggers when the move uses its secondary effect. Moves should implement their
|
||||
/// secondary effects here. Status moves should implement their actual functionality in this
|
||||
/// function as well, as status moves effects are defined as secondary effects for simplicity.
|
||||
fn on_secondary_effect(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8) {}
|
||||
fn on_secondary_effect(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function triggers on a move or its parents when all hits on a target are finished.
|
||||
fn on_after_hits(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>) {}
|
||||
fn on_after_hits(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function prevents the Pokemon it is attached to from being able to switch out.
|
||||
fn prevent_self_switch(&self, _choice: &TurnChoice, _prevent: &mut bool) {}
|
||||
fn prevent_self_switch(&self, _choice: &TurnChoice, _prevent: &mut bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows the prevention of switching for any opponent.
|
||||
fn prevent_opponent_switch(&self, _choice: &TurnChoice, _prevent: &mut bool) {}
|
||||
fn prevent_opponent_switch(&self, _choice: &TurnChoice, _prevent: &mut bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is called on a move and its parents when the move fails.
|
||||
fn on_fail(&self, _target: &Pokemon) {}
|
||||
fn on_fail(&self, _target: &Pokemon) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is called on a script when an opponent fails.
|
||||
fn on_opponent_fail(&self, _target: &Pokemon) {}
|
||||
fn on_opponent_fail(&self, _target: &Pokemon) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function allows preventing the running away of the Pokemon its attached to
|
||||
fn prevent_self_run_away(&self, _choice: &TurnChoice, _prevent: &mut bool) {}
|
||||
fn prevent_self_run_away(&self, _choice: &TurnChoice, _prevent: &mut bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function prevents a Pokemon on another side than where its attached to from running away.
|
||||
fn prevent_opponent_run_away(&self, _choice: &TurnChoice, _prevent: &mut bool) {}
|
||||
fn prevent_opponent_run_away(&self, _choice: &TurnChoice, _prevent: &mut bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function id triggered on all scripts active in the battle after all choices have finished
|
||||
/// running. Note that choices are not active anymore here, so their scripts do not call this
|
||||
/// function.
|
||||
fn on_end_turn(&self) {}
|
||||
fn on_end_turn(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon takes damage.
|
||||
fn on_damage(&self, _pokemon: &Pokemon, _source: DamageSource, _old_health: u32, _new_health: u32) {}
|
||||
fn on_damage(&self, _pokemon: &Pokemon, _source: DamageSource, _old_health: u32, _new_health: u32) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon faints.
|
||||
fn on_faint(&self, _pokemon: &Pokemon, _source: DamageSource) {}
|
||||
fn on_faint(&self, _pokemon: &Pokemon, _source: DamageSource) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon is switched into
|
||||
/// the battlefield.
|
||||
fn on_switch_in(&self, _pokemon: &Pokemon) {}
|
||||
fn on_switch_in(&self, _pokemon: &Pokemon) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon consumes the
|
||||
/// held item it had.
|
||||
fn on_after_held_item_consume(&self, _pokemon: &Pokemon, _item: &dyn Item) {}
|
||||
fn on_after_held_item_consume(&self, _pokemon: &Pokemon, _item: &dyn Item) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon gains experience,
|
||||
/// and allows for changing this amount of experience.
|
||||
fn change_experience_gained(&self, _fainted_mon: &Pokemon, _winning_mon: &Pokemon, _amount: &mut u32) {}
|
||||
fn change_experience_gained(
|
||||
&self,
|
||||
_fainted_mon: &Pokemon,
|
||||
_winning_mon: &Pokemon,
|
||||
_amount: &mut u32,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is triggered on a Pokemon and its parents when the given Pokemon gains experience,
|
||||
/// and allows for making the experience be shared across multiple Pokemon.
|
||||
fn share_experience(&self, _fainted_mon: &Pokemon, _winning_mon: &Pokemon, _shares: &mut bool) {}
|
||||
fn share_experience(&self, _fainted_mon: &Pokemon, _winning_mon: &Pokemon, _shares: &mut bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is triggered on a battle and its parents when something attempts to change the
|
||||
/// weather, and allows for blocking the weather change.
|
||||
fn block_weather(&self, _battle: &Battle, _blocked: &mut bool) {}
|
||||
fn block_weather(&self, _battle: &Battle, _blocked: &mut bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is called when a Pokeball is thrown at a Pokemon, and allows modifying the catch
|
||||
/// rate of this attempt. Pokeball modifier effects should be implemented here, as well as for
|
||||
/// example status effects that change capture rates.
|
||||
fn change_capture_rate_bonus(&self, _target: &Pokemon, _pokeball: &dyn Item, _modifier: &mut u8) {}
|
||||
fn change_capture_rate_bonus(&self, _target: &Pokemon, _pokeball: &dyn Item, _modifier: &mut u8) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Helper function to turn the self into an Any for downcasting.
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
|
@ -319,7 +525,13 @@ impl ScriptContainer {
|
|||
/// separate thread, and be replaced immediately after the script stops being active.
|
||||
pub fn set(&self, script: Arc<dyn Script>) -> Arc<dyn Script> {
|
||||
if let Some(v) = self.script.read().deref() {
|
||||
v.on_remove();
|
||||
let script_result = v.on_remove();
|
||||
match script_result {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
crate::dynamic_data::script_handling::handle_script_error(&e);
|
||||
}
|
||||
}
|
||||
v.mark_for_deletion();
|
||||
}
|
||||
// If we have a lock on the script, we can't replace it now. Wait until we can get the lock,
|
||||
|
@ -342,7 +554,13 @@ impl ScriptContainer {
|
|||
/// we just mark it as deleted. If we do this we remove the script later on.
|
||||
pub fn clear(&self) {
|
||||
if let Some(v) = self.script.read().deref() {
|
||||
v.on_remove();
|
||||
let script_result = v.on_remove();
|
||||
match script_result {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
crate::dynamic_data::script_handling::handle_script_error(&e);
|
||||
}
|
||||
}
|
||||
v.mark_for_deletion();
|
||||
}
|
||||
if !self.script.is_locked() {
|
||||
|
@ -418,8 +636,8 @@ mod tests {
|
|||
unsafe impl Send for TestScript {}
|
||||
|
||||
impl Script for TestScript {
|
||||
fn name(&self) -> &StringKey {
|
||||
&self.name
|
||||
fn name(&self) -> Result<&StringKey> {
|
||||
Ok(&self.name)
|
||||
}
|
||||
|
||||
fn get_marked_for_deletion(&self) -> &AtomicBool {
|
||||
|
@ -430,8 +648,9 @@ mod tests {
|
|||
&self.suppressed_count
|
||||
}
|
||||
|
||||
fn stack(&self) {
|
||||
fn stack(&self) -> Result<()> {
|
||||
unsafe { self.container.load(Ordering::Relaxed).as_ref().unwrap().clear() }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
|
@ -458,7 +677,7 @@ mod tests {
|
|||
drop(w);
|
||||
// Initialize with the script being taken as read lock. This prevents the script from actually
|
||||
// removing itself, as it's still doing things.
|
||||
container.script.read().as_ref().unwrap().stack();
|
||||
container.script.read().as_ref().unwrap().stack().unwrap();
|
||||
// If we now try and get the script, it will be none the first time. This has the side effect
|
||||
// of actually disposing of the script.
|
||||
assert!(container.get().is_none());
|
||||
|
@ -497,8 +716,8 @@ mod tests {
|
|||
unsafe impl Send for ReplaceTestScript {}
|
||||
|
||||
impl Script for ReplaceTestScript {
|
||||
fn name(&self) -> &StringKey {
|
||||
&self.name
|
||||
fn name(&self) -> Result<&StringKey> {
|
||||
Ok(&self.name)
|
||||
}
|
||||
|
||||
fn get_marked_for_deletion(&self) -> &AtomicBool {
|
||||
|
@ -544,7 +763,10 @@ mod tests {
|
|||
h.join().unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(container.script.read().as_ref().unwrap().name(), &"script2".into());
|
||||
assert_eq!(
|
||||
container.script.read().as_ref().unwrap().name().unwrap(),
|
||||
&"script2".into()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,22 +19,22 @@ pub struct ScriptSet {
|
|||
impl ScriptSet {
|
||||
/// Adds a script to the set. If the script with that name already exists in this set, this
|
||||
/// makes that script stack instead. The return value here is that script.
|
||||
pub fn add(&self, script: Arc<dyn Script>) -> ScriptContainer {
|
||||
if let Some(lock) = self.scripts.read().get(script.name()) {
|
||||
pub fn add(&self, script: Arc<dyn Script>) -> Result<ScriptContainer> {
|
||||
if let Some(lock) = self.scripts.read().get(script.name()?) {
|
||||
if let Some(existing) = lock.get() {
|
||||
let existing = existing.read();
|
||||
if let Some(v) = &*existing {
|
||||
v.stack();
|
||||
return lock.clone();
|
||||
v.stack()?;
|
||||
return Ok(lock.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the existing script does not exist, or is not a script, we can just add the new one.
|
||||
let name = script.name().clone();
|
||||
let name = script.name()?.clone();
|
||||
let container = ScriptContainer::new(script);
|
||||
self.scripts.write().insert(name, container.clone());
|
||||
container
|
||||
Ok(container)
|
||||
}
|
||||
|
||||
/// Adds a script with a name to the set. If the script with that name already exists in this
|
||||
|
@ -47,14 +47,20 @@ impl ScriptSet {
|
|||
if let Some(existing) = lock.get() {
|
||||
let existing = existing.read();
|
||||
if let Some(v) = &*existing {
|
||||
v.stack();
|
||||
let script_result = v.stack();
|
||||
match script_result {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
crate::dynamic_data::script_handling::handle_script_error(&e);
|
||||
}
|
||||
}
|
||||
return Ok(Some(lock.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
let script = instantiation()?;
|
||||
if let Some(script) = script {
|
||||
let name = script.name().clone();
|
||||
let name = script.name()?.clone();
|
||||
let arc = ScriptContainer::new(script);
|
||||
self.scripts.write().insert(name, arc.clone());
|
||||
Ok(Some(arc))
|
||||
|
@ -74,7 +80,14 @@ impl ScriptSet {
|
|||
if let Some(script) = value {
|
||||
if let Some(script) = script.get() {
|
||||
let script = script.read();
|
||||
script.as_ref().ok_or(PkmnError::UnableToAcquireLock)?.on_remove();
|
||||
let script_result = script.as_ref().ok_or(PkmnError::UnableToAcquireLock)?.on_remove();
|
||||
match script_result {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
crate::dynamic_data::script_handling::handle_script_error(&e);
|
||||
}
|
||||
}
|
||||
|
||||
script
|
||||
.as_ref()
|
||||
.ok_or(PkmnError::UnableToAcquireLock)?
|
||||
|
@ -90,7 +103,14 @@ impl ScriptSet {
|
|||
if let Some(script) = script.1.get() {
|
||||
let script = script.read();
|
||||
if let Some(script) = &*script {
|
||||
script.on_remove();
|
||||
let script_result = script.on_remove();
|
||||
match script_result {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
crate::dynamic_data::script_handling::handle_script_error(&e);
|
||||
}
|
||||
}
|
||||
|
||||
script.mark_for_deletion();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ pub trait VolatileScriptsOwner {
|
|||
/// Adds a volatile script by name.
|
||||
fn add_volatile_script_with_script(&self, script: Arc<dyn Script>) -> Result<Option<ScriptContainer>> {
|
||||
self.volatile_scripts()
|
||||
.stack_or_add(&script.name().clone(), &|| Ok(Some(script.clone())))
|
||||
.stack_or_add(&script.name()?.clone(), &|| Ok(Some(script.clone())))
|
||||
}
|
||||
|
||||
/// Removes a volatile script by name.
|
||||
|
|
|
@ -1,6 +1,17 @@
|
|||
use std::ffi::{c_char, CString};
|
||||
|
||||
/// The foreign function interfaces for the turn choices
|
||||
mod choices;
|
||||
/// The foreign function interfaces for the dynamic data libraries
|
||||
mod libraries;
|
||||
/// The foreign function interfaces for the dynamic data models
|
||||
mod models;
|
||||
|
||||
/// The library the battle uses for handling.
|
||||
#[no_mangle]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
extern "C" fn set_script_error_handler(func: unsafe extern "C" fn(*mut c_char)) {
|
||||
crate::dynamic_data::set_script_error_handler(Box::new(move |e: &anyhow_ext::Error| unsafe {
|
||||
func(CString::new(e.to_string()).unwrap().into_raw())
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use anyhow_ext::Result;
|
||||
use std::any::Any;
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize};
|
||||
use std::sync::Arc;
|
||||
|
@ -93,8 +94,8 @@ macro_rules! vec_ex_ref {
|
|||
}
|
||||
|
||||
impl Script for WebAssemblyScript {
|
||||
fn name(&self) -> &StringKey {
|
||||
&self.name
|
||||
fn name(&self) -> Result<&StringKey> {
|
||||
Ok(&self.name)
|
||||
}
|
||||
|
||||
fn get_marked_for_deletion(&self) -> &AtomicBool {
|
||||
|
@ -105,50 +106,54 @@ impl Script for WebAssemblyScript {
|
|||
&self.suppressed_count
|
||||
}
|
||||
|
||||
fn stack(&self) {
|
||||
fn stack(&self) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnStack) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().stack(env) {
|
||||
call_func!(func, env, self);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_remove(&self) {
|
||||
fn on_remove(&self) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnRemove) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_remove(env) {
|
||||
call_func!(func, env, self);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_initialize(&self, library: &Arc<dyn DynamicLibrary>, pars: Vec<EffectParameter>) {
|
||||
fn on_initialize(&self, library: &Arc<dyn DynamicLibrary>, pars: Vec<EffectParameter>) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::Initialize) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_before_turn(&self, choice: &TurnChoice) {
|
||||
fn on_before_turn(&self, choice: &TurnChoice) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnBeforeTurn) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
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));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_speed(&self, choice: &TurnChoice, speed: &mut u32) {
|
||||
fn change_speed(&self, choice: &TurnChoice, speed: &mut u32) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeSpeed) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let env = &self.environment;
|
||||
|
@ -157,11 +162,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*speed = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_priority(&self, choice: &TurnChoice, priority: &mut i8) {
|
||||
fn change_priority(&self, choice: &TurnChoice, priority: &mut i8) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangePriority) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let env = &self.environment;
|
||||
|
@ -170,11 +176,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*priority = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_move(&self, choice: &TurnChoice, move_name: &mut StringKey) {
|
||||
fn change_move(&self, choice: &TurnChoice, move_name: &mut StringKey) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeMove) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let env = &self.environment;
|
||||
|
@ -184,11 +191,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*move_name = ptr.value().value(env).unwrap().clone();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_number_of_hits(&self, choice: &TurnChoice, number_of_hits: &mut u8) {
|
||||
fn change_number_of_hits(&self, choice: &TurnChoice, number_of_hits: &mut u8) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeNumberOfHits) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let env = &self.environment;
|
||||
|
@ -197,11 +205,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*number_of_hits = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prevent_move(&self, mv: &ExecutingMove, prevent: &mut bool) {
|
||||
fn prevent_move(&self, mv: &ExecutingMove, prevent: &mut bool) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventMove) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let env = &self.environment;
|
||||
|
@ -210,11 +219,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ptr.wasm_ptr);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fail_move(&self, mv: &ExecutingMove, fail: &mut bool) {
|
||||
fn fail_move(&self, mv: &ExecutingMove, fail: &mut bool) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::FailMove) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let env = &self.environment;
|
||||
|
@ -223,11 +233,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ptr.wasm_ptr);
|
||||
*fail = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn stop_before_move(&self, mv: &ExecutingMove, stop: &mut bool) {
|
||||
fn stop_before_move(&self, mv: &ExecutingMove, stop: &mut bool) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::StopBeforeMove) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let env = &self.environment;
|
||||
|
@ -236,21 +247,23 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ptr.wasm_ptr);
|
||||
*stop = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_before_move(&self, mv: &ExecutingMove) {
|
||||
fn on_before_move(&self, mv: &ExecutingMove) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnBeforeMove) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
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));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fail_incoming_move(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, fail: &mut bool) {
|
||||
fn fail_incoming_move(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, fail: &mut bool) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::FailIncomingMove) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().fail_incoming_move(env) {
|
||||
|
@ -265,11 +278,12 @@ impl Script for WebAssemblyScript {
|
|||
);
|
||||
*fail = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_invulnerable(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, invulnerable: &mut bool) {
|
||||
fn is_invulnerable(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, invulnerable: &mut bool) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::IsInvulnerable) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().is_invulnerable(env) {
|
||||
|
@ -284,21 +298,29 @@ impl Script for WebAssemblyScript {
|
|||
);
|
||||
*invulnerable = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_move_miss(&self, mv: &ExecutingMove, target: &Arc<Pokemon>) {
|
||||
fn on_move_miss(&self, mv: &ExecutingMove, target: &Arc<Pokemon>) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnMoveMiss) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
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()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_move_type(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, move_type: &mut TypeIdentifier) {
|
||||
fn change_move_type(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
move_type: &mut TypeIdentifier,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeMoveType) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_move_type(env) {
|
||||
|
@ -308,11 +330,18 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*move_type = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_effectiveness(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, effectiveness: &mut f32) {
|
||||
fn change_effectiveness(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
effectiveness: &mut f32,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeEffectiveness) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_effectiveness(env) {
|
||||
|
@ -322,11 +351,18 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*effectiveness = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn block_critical(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, block_critical: &mut bool) {
|
||||
fn block_critical(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
block_critical: &mut bool,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::BlockCritical) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().block_critical(env) {
|
||||
|
@ -336,11 +372,18 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*block_critical = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn block_incoming_critical(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, block_critical: &mut bool) {
|
||||
fn block_incoming_critical(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
block_critical: &mut bool,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::BlockIncomingCritical) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().block_incoming_critical(env) {
|
||||
|
@ -350,11 +393,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*block_critical = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_accuracy(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, accuracy: &mut u8) {
|
||||
fn change_accuracy(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, accuracy: &mut u8) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeAccuracy) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_accuracy(env) {
|
||||
|
@ -364,11 +408,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*accuracy = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_critical_stage(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, stage: &mut u8) {
|
||||
fn change_critical_stage(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, stage: &mut u8) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeCriticalStage) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_critical_stage(env) {
|
||||
|
@ -378,11 +423,18 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*stage = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_critical_modifier(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, modifier: &mut f32) {
|
||||
fn change_critical_modifier(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
modifier: &mut f32,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeCriticalModifier) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_critical_modifier(env) {
|
||||
|
@ -392,11 +444,18 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*modifier = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_stab_modifier(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, modifier: &mut f32) {
|
||||
fn change_stab_modifier(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
modifier: &mut f32,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeSTABModifier) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_stab_modifier(env) {
|
||||
|
@ -406,11 +465,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*modifier = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_base_power(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, base_power: &mut u8) {
|
||||
fn change_base_power(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, base_power: &mut u8) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeBasePower) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_base_power(env) {
|
||||
|
@ -420,11 +480,18 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*base_power = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bypass_defensive_stat_boost(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, bypass: &mut bool) {
|
||||
fn bypass_defensive_stat_boost(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
bypass: &mut bool,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::BypassDefensiveStat) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().bypass_defensive_stat_boost(env) {
|
||||
|
@ -434,11 +501,18 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*bypass = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bypass_offensive_stat_boost(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, bypass: &mut bool) {
|
||||
fn bypass_offensive_stat_boost(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
bypass: &mut bool,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::BypassOffensiveStat) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().bypass_offensive_stat_boost(env) {
|
||||
|
@ -448,11 +522,18 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*bypass = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_offensive_stat_value(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, amount: &mut u32) {
|
||||
fn change_offensive_stat_value(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
amount: &mut u32,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeOffensiveStatValue) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_offensive_stat_value(env) {
|
||||
|
@ -462,11 +543,18 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*amount = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_defensive_stat_value(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, amount: &mut u32) {
|
||||
fn change_defensive_stat_value(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
amount: &mut u32,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeOffensiveStatValue) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_defensive_stat_value(env) {
|
||||
|
@ -476,11 +564,18 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*amount = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_damage_stat_modifier(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, modifier: &mut f32) {
|
||||
fn change_damage_stat_modifier(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
modifier: &mut f32,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeStatModifier) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_damage_stat_modifier(env) {
|
||||
|
@ -490,11 +585,18 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*modifier = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_damage_modifier(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, modifier: &mut f32) {
|
||||
fn change_damage_modifier(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
modifier: &mut f32,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeDamageModifier) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_damage_modifier(env) {
|
||||
|
@ -504,11 +606,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*modifier = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_damage(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, damage: &mut u32) {
|
||||
fn change_damage(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, damage: &mut u32) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeDamage) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_damage(env) {
|
||||
|
@ -518,11 +621,18 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*damage = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_incoming_damage(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, damage: &mut u32) {
|
||||
fn change_incoming_damage(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
damage: &mut u32,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeIncomingDamage) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_incoming_damage(env) {
|
||||
|
@ -532,28 +642,31 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*damage = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_incoming_hit(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8) {
|
||||
fn on_incoming_hit(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnIncomingHit) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
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);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_opponent_faints(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8) {
|
||||
fn on_opponent_faints(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFaintingOpponent) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
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);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prevent_stat_boost_change(
|
||||
|
@ -563,9 +676,9 @@ impl Script for WebAssemblyScript {
|
|||
amount: i8,
|
||||
self_inflicted: bool,
|
||||
prevent: &mut bool,
|
||||
) {
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventStatBoostChange) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().prevent_stat_boost_change(env) {
|
||||
|
@ -583,11 +696,18 @@ impl Script for WebAssemblyScript {
|
|||
);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prevent_secondary_effect(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, prevent: &mut bool) {
|
||||
fn prevent_secondary_effect(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
prevent: &mut bool,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventSecondaryEffects) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().prevent_secondary_effect(env) {
|
||||
|
@ -597,11 +717,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_effect_chance(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, chance: &mut f32) {
|
||||
fn change_effect_chance(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, chance: &mut f32) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeEffectChance) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_effect_chance(env) {
|
||||
|
@ -611,11 +732,18 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*chance = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_incoming_effect_chance(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8, chance: &mut f32) {
|
||||
fn change_incoming_effect_chance(
|
||||
&self,
|
||||
mv: &ExecutingMove,
|
||||
target: &Arc<Pokemon>,
|
||||
hit: u8,
|
||||
chance: &mut f32,
|
||||
) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeIncomingEffectChance) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_incoming_effect_chance(env) {
|
||||
|
@ -625,33 +753,36 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, mv), ex_ref!(env, target), hit, w_ptr);
|
||||
*chance = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_secondary_effect(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8) {
|
||||
fn on_secondary_effect(&self, mv: &ExecutingMove, target: &Arc<Pokemon>, hit: u8) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFaintingOpponent) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
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);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_after_hits(&self, mv: &ExecutingMove, target: &Arc<Pokemon>) {
|
||||
fn on_after_hits(&self, mv: &ExecutingMove, target: &Arc<Pokemon>) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnAfterHits) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
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));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prevent_self_switch(&self, choice: &TurnChoice, prevent: &mut bool) {
|
||||
fn prevent_self_switch(&self, choice: &TurnChoice, prevent: &mut bool) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventSelfSwitch) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().prevent_self_switch(env) {
|
||||
|
@ -659,11 +790,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prevent_opponent_switch(&self, choice: &TurnChoice, prevent: &mut bool) {
|
||||
fn prevent_opponent_switch(&self, choice: &TurnChoice, prevent: &mut bool) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventSelfSwitch) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().prevent_opponent_switch(env) {
|
||||
|
@ -671,31 +803,34 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_fail(&self, pokemon: &Pokemon) {
|
||||
fn on_fail(&self, pokemon: &Pokemon) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFail) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_fail(env) {
|
||||
call_func!(func, env, self, ex_ref!(env, pokemon));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_opponent_fail(&self, pokemon: &Pokemon) {
|
||||
fn on_opponent_fail(&self, pokemon: &Pokemon) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFail) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
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));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prevent_self_run_away(&self, choice: &TurnChoice, prevent: &mut bool) {
|
||||
fn prevent_self_run_away(&self, choice: &TurnChoice, prevent: &mut bool) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventSelfRunAway) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().prevent_self_run_away(env) {
|
||||
|
@ -703,11 +838,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prevent_opponent_run_away(&self, choice: &TurnChoice, prevent: &mut bool) {
|
||||
fn prevent_opponent_run_away(&self, choice: &TurnChoice, prevent: &mut bool) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::PreventOpponentRunAway) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().prevent_opponent_run_away(env) {
|
||||
|
@ -715,61 +851,67 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, choice), ptr.wasm_ptr);
|
||||
*prevent = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn on_end_turn(&self) {
|
||||
fn on_end_turn(&self) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnEndTurn) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().on_end_turn(env) {
|
||||
call_func!(func, env, self);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_damage(&self, pokemon: &Pokemon, source: DamageSource, old_health: u32, new_health: u32) {
|
||||
fn on_damage(&self, pokemon: &Pokemon, source: DamageSource, old_health: u32, new_health: u32) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnDamage) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
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);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_faint(&self, pokemon: &Pokemon, source: DamageSource) {
|
||||
fn on_faint(&self, pokemon: &Pokemon, source: DamageSource) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnFaint) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
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);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_switch_in(&self, pokemon: &Pokemon) {
|
||||
fn on_switch_in(&self, pokemon: &Pokemon) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnSwitchIn) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
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));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_after_held_item_consume(&self, pokemon: &Pokemon, item: &dyn Item) {
|
||||
fn on_after_held_item_consume(&self, pokemon: &Pokemon, item: &dyn Item) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::OnAfterHeldItemConsume) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
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));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_experience_gained(&self, fainted_mon: &Pokemon, winning_mon: &Pokemon, amount: &mut u32) {
|
||||
fn change_experience_gained(&self, fainted_mon: &Pokemon, winning_mon: &Pokemon, amount: &mut u32) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeExperienceGain) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_experience_gained(env) {
|
||||
|
@ -779,11 +921,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, fainted_mon, winning_mon, ptr.wasm_ptr);
|
||||
*amount = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn share_experience(&self, fainted_mon: &Pokemon, winning_mon: &Pokemon, shares: &mut bool) {
|
||||
fn share_experience(&self, fainted_mon: &Pokemon, winning_mon: &Pokemon, shares: &mut bool) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::DoesShareExperience) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().share_experience(env) {
|
||||
|
@ -793,11 +936,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, fainted_mon, winning_mon, ptr.wasm_ptr);
|
||||
*shares = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn block_weather(&self, battle: &Battle, blocked: &mut bool) {
|
||||
fn block_weather(&self, battle: &Battle, blocked: &mut bool) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::BlockWeather) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().block_weather(env) {
|
||||
|
@ -805,11 +949,12 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, ex_ref!(env, battle), ptr.wasm_ptr);
|
||||
*blocked = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn change_capture_rate_bonus(&self, target: &Pokemon, pokeball: &dyn Item, modifier: &mut u8) {
|
||||
fn change_capture_rate_bonus(&self, target: &Pokemon, pokeball: &dyn Item, modifier: &mut u8) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::ChangeCaptureRate) {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().change_capture_rate_bonus(env) {
|
||||
|
@ -819,6 +964,7 @@ impl Script for WebAssemblyScript {
|
|||
call_func!(func, env, self, target, pokeball, ptr.wasm_ptr);
|
||||
*modifier = *ptr.value();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
|
|
|
@ -119,7 +119,7 @@ fn validate_assurance() {
|
|||
|
||||
let mv = p1.learned_moves().read()[0].as_ref().unwrap().clone();
|
||||
let choice = TurnChoice::Move(MoveChoice::new(p1.clone(), mv.clone(), 1, 0));
|
||||
script.on_before_turn(&choice);
|
||||
script.on_before_turn(&choice).unwrap();
|
||||
assert!(battle.sides()[1].has_volatile_script(&"assurance_data".into()));
|
||||
|
||||
let executing_move = ExecutingMove::new(
|
||||
|
@ -131,19 +131,19 @@ fn validate_assurance() {
|
|||
ScriptContainer::default(),
|
||||
);
|
||||
let mut v = 20_u8;
|
||||
script.change_base_power(&executing_move, &p2, 0, &mut v);
|
||||
script.change_base_power(&executing_move, &p2, 0, &mut v).unwrap();
|
||||
assert_eq!(v, 20_u8);
|
||||
|
||||
let s = battle.sides()[1].get_volatile_script(&"assurance_data".into());
|
||||
let binding = s.as_ref().unwrap().get().unwrap().read();
|
||||
let data_script = binding.as_ref().unwrap();
|
||||
|
||||
data_script.on_damage(&p2, DamageSource::Misc, 100, 50);
|
||||
data_script.on_damage(&p2, DamageSource::Misc, 100, 50).unwrap();
|
||||
|
||||
let mut v = 20_u8;
|
||||
script.change_base_power(&executing_move, &p2, 0, &mut v);
|
||||
script.change_base_power(&executing_move, &p2, 0, &mut v).unwrap();
|
||||
assert_eq!(v, 40_u8);
|
||||
|
||||
data_script.on_end_turn();
|
||||
data_script.on_end_turn().unwrap();
|
||||
assert!(!battle.sides()[1].has_volatile_script(&"assurance_data".into()));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue