Adds more comments.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2022-06-20 19:26:33 +02:00
parent 314e9dbe1a
commit 1c9edd4d9c
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
2 changed files with 97 additions and 7 deletions

View File

@ -167,13 +167,6 @@ impl<'own, 'library> Battle<'own, 'library> {
} }
} }
let number_of_hits = executing_move.number_of_hits(); let number_of_hits = executing_move.number_of_hits();
if number_of_hits == 0 {
script_hook!(on_move_miss, target, executing_move, target);
self.event_hook().trigger(Event::Miss {
user: executing_move.user().deref(),
});
return Ok(());
}
let target_hit_stat = executing_move.get_index_of_target(target)?; let target_hit_stat = executing_move.get_index_of_target(target)?;
for hit_index in 0..number_of_hits { for hit_index in 0..number_of_hits {
@ -252,6 +245,23 @@ impl<'own, 'library> Battle<'own, 'library> {
); );
hit_data.set_damage(damage); hit_data.set_damage(damage);
let mut accuracy = executing_move.use_move().accuracy();
script_hook!(
change_accuracy,
executing_move,
executing_move,
target,
hit_index,
&mut accuracy
);
if accuracy < 100 && self.random().get_max(100) as u8 >= accuracy {
script_hook!(on_move_miss, target, executing_move, target);
self.event_hook().trigger(Event::Miss {
user: executing_move.user().deref(),
});
break;
}
if used_move.category() == MoveCategory::Status { if used_move.category() == MoveCategory::Status {
if let Some(secondary_effect) = used_move.secondary_effect() { if let Some(secondary_effect) = used_move.secondary_effect() {
let secondary_effect_chance = secondary_effect.chance(); let secondary_effect_chance = secondary_effect.chance();
@ -316,6 +326,13 @@ impl<'own, 'library> Battle<'own, 'library> {
} }
} }
if number_of_hits == 0 {
script_hook!(on_move_miss, target, executing_move, target);
self.event_hook().trigger(Event::Miss {
user: executing_move.user().deref(),
});
}
if !executing_move.user().is_fainted() { if !executing_move.user().is_fainted() {
script_hook!(on_after_hits, executing_move, executing_move, target); script_hook!(on_after_hits, executing_move, executing_move, target);
} }

View File

@ -16,46 +16,101 @@ use crate::static_data::EffectParameter;
use crate::static_data::{Item, Statistic}; use crate::static_data::{Item, Statistic};
use crate::StringKey; use crate::StringKey;
/// The script trait is used to make changes to how a battle executes, without requiring hardcoded
/// changes. This allows for easily defining generational differences, and add effects that the
/// developer might require.
pub trait Script: Send + Sync { 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) -> &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).
fn get_marked_for_deletion(&self) -> &AtomicBool; fn get_marked_for_deletion(&self) -> &AtomicBool;
/// This marks the script for deletion, which will dispose of it as soon as possible.
fn mark_for_deletion(&self) { fn mark_for_deletion(&self) {
self.get_marked_for_deletion().store(true, Ordering::SeqCst); self.get_marked_for_deletion().store(true, Ordering::SeqCst);
} }
/// Helper function to get the value of the marked for deletion bool.
fn is_marked_for_deletion(&self) -> bool { fn is_marked_for_deletion(&self) -> bool {
self.get_marked_for_deletion().load(Ordering::SeqCst) self.get_marked_for_deletion().load(Ordering::SeqCst)
} }
/// A script can be suppressed by other scripts. If a script is suppressed by at least one script
/// we will not execute its methods. This should return the number of suppressions on the script.
fn get_suppressed_count(&self) -> &AtomicUsize; fn get_suppressed_count(&self) -> &AtomicUsize;
/// Helper function to check if there is at least one suppression on the script
fn is_suppressed(&self) -> bool { fn is_suppressed(&self) -> bool {
self.get_suppressed_count().load(Ordering::SeqCst) > 0 self.get_suppressed_count().load(Ordering::SeqCst) > 0
} }
/// Adds a suppression. This makes the script not run anymore. Note that adding this should also
/// remove the suppression later.
///
/// A common pattern for this is to run this in the [`Self::on_initialize`] function, and run the
/// remove in the [`Self::on_remove`] function.
fn add_suppression(&self) { fn add_suppression(&self) {
self.get_suppressed_count().fetch_add(1, Ordering::SeqCst); self.get_suppressed_count().fetch_add(1, Ordering::SeqCst);
} }
/// Removes a suppression. This allows the script to run again (provided other scripts are not
/// suppressing it). Note that running this should only occur if an add was run before.
fn remove_suppression(&self) { fn remove_suppression(&self) {
self.get_suppressed_count().fetch_sub(1, Ordering::SeqCst); self.get_suppressed_count().fetch_sub(1, Ordering::SeqCst);
} }
/// 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) {}
/// 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) {}
/// This function is ran when this script starts being in effect.
fn on_initialize(&self, _pars: &[EffectParameter]) {} fn on_initialize(&self, _pars: &[EffectParameter]) {}
/// This function is ran just before the start of the turn. Everyone has made its choices here,
/// and the turn is about to start. This is a great place to initialize data if you need to know
/// something has happened during a turn.
fn on_before_turn(&self, _choice: &TurnChoice) {} fn on_before_turn(&self, _choice: &TurnChoice) {}
/// This function allows you to modify the effective speed of the Pokemon. This is ran before
/// turn ordering, so overriding here will allow you to put certain Pokemon before others.
fn change_speed(&self, _choice: &TurnChoice, _speed: &mut u32) {} fn change_speed(&self, _choice: &TurnChoice, _speed: &mut u32) {}
/// This function allows you to modify the effective priority of the Pokemon. This is ran before
/// turn ordering, so overriding here will allow you to put certain Pokemon before others. Note
/// that this is only relevant on move choices, as other turn choice types do not have a priority.
fn change_priority(&self, _choice: &TurnChoice, _priority: &mut i8) {} fn change_priority(&self, _choice: &TurnChoice, _priority: &mut i8) {}
/// This function allows you to change the move that is used during execution. This is useful for
/// moves such as metronome, where the move chosen actually differs from the move used.
fn change_move(&self, _choice: &MoveChoice, _move_name: &mut StringKey) {} fn change_move(&self, _choice: &MoveChoice, _move_name: &mut StringKey) {}
/// This function allows you to change a move into a multi-hit move. The number of hits set here
/// gets used as the number of hits. If set to 0, this will behave as if the move missed on its
/// first hit.
fn change_number_of_hits(&self, _choice: &MoveChoice, _number_of_hits: &mut u8) {} fn change_number_of_hits(&self, _choice: &MoveChoice, _number_of_hits: &mut u8) {}
/// This function allows you to prevent a move from running. If this gets set to true, the move
/// ends execution here. No PP will be decreased in this case.
fn prevent_move(&self, _move: &ExecutingMove, _prevent: &mut bool) {} fn prevent_move(&self, _move: &ExecutingMove, _prevent: &mut bool) {}
/// This function makes the move fail. If the fail field gets set to true, the move ends execution,
/// and fail events get triggered.
fn fail_move(&self, _move: &ExecutingMove, _fail: &mut bool) {} fn fail_move(&self, _move: &ExecutingMove, _fail: &mut bool) {}
/// Similar to [`Self::prevent_move`]. This function will also stop execution, but PP will be
/// decreased.
fn stop_before_move(&self, _move: &ExecutingMove, _stop: &mut bool) {} fn stop_before_move(&self, _move: &ExecutingMove, _stop: &mut bool) {}
/// This function runs just before the move starts its execution.
fn on_before_move(&self, _move: &ExecutingMove) {} fn on_before_move(&self, _move: &ExecutingMove) {}
/// This function allows a script to prevent a move that is targeted at its owner. If set to true
/// the move fails, and fail events get triggered.
fn fail_incoming_move(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _fail: &mut bool) {} fn fail_incoming_move(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _fail: &mut bool) {}
/// This function allows a script to make its owner invulnerable to an incoming move.
fn is_invulnerable(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _invulnerable: &mut bool) {} fn is_invulnerable(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _invulnerable: &mut bool) {}
/// This function occurs when a move gets missed. This runs on the scripts belonging to the executing
/// move, which include the scripts that are attached to the owner of the script.
fn on_move_miss(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>) {} fn on_move_miss(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>) {}
/// This function allows the script to change the actual type that is used for the move on a target.
fn change_move_type(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _move_type: &mut u8) {} fn change_move_type(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _move_type: &mut u8) {}
/// 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) {}
/// 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) {}
/// This function allows a script to block an incoming move from being critical.
fn block_incoming_critical( fn block_incoming_critical(
&self, &self,
_move: &ExecutingMove, _move: &ExecutingMove,
@ -64,11 +119,23 @@ pub trait Script: Send + Sync {
_block_critical: &mut bool, _block_critical: &mut bool,
) { ) {
} }
/// This function allows a script to modify the accuracy of a move used. This value represents
/// the percentage accuracy, so anything above 100% will make it always hit.
fn change_accuracy(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _accuracy: &mut u8) {}
/// This function allows a script to change the critical stage of the move used.
fn change_critical_stage(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _stage: &mut u8) {} fn change_critical_stage(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _stage: &mut u8) {}
/// This function allows a script to change the damage modifier of a critical hit. This will only
/// run when a hit is critical.
fn change_critical_modifier(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _modifier: &mut f32) {} fn change_critical_modifier(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _modifier: &mut f32) {}
/// This function allows a script to change the damage modifier of a Same Type Attack Bonus, which
/// occurs when the user has the move type as one of its own types.
fn change_stab_modifier(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _modifier: &mut f32) {} fn change_stab_modifier(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _modifier: &mut f32) {}
/// This function allows a script to change the effective base power of a move hit.
fn change_base_power(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _base_power: &mut u8) {} fn change_base_power(&self, _move: &ExecutingMove, _target: &Arc<Pokemon>, _hit: u8, _base_power: &mut u8) {}
/// This function allows a script to change which Pokemons stats are used for the offensive side when
/// calculating damage.
fn change_damage_stats_user( fn change_damage_stats_user(
&self, &self,
_move: &ExecutingMove, _move: &ExecutingMove,
@ -77,13 +144,19 @@ pub trait Script: Send + Sync {
_stats_user: &mut Arc<Pokemon>, _stats_user: &mut Arc<Pokemon>,
) { ) {
} }
/// 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) {
} }
/// 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) {
} }
/// 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) {}
/// 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) {}
/// This function allows a script to change the raw modifier we retrieved from the stats of the
/// defender and attacker.
fn change_damage_stat_modifier( fn change_damage_stat_modifier(
&self, &self,
_move: &ExecutingMove, _move: &ExecutingMove,