Prevent overflows using saturating types for several script functions
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2023-06-30 16:53:28 +02:00
parent 653de5c919
commit ddaa2dab31
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
9 changed files with 570 additions and 517 deletions

View File

@ -4,6 +4,7 @@ pub use alloc::rc::Rc;
pub use alloc::vec::Vec; pub use alloc::vec::Vec;
pub use atomic_float::AtomicF32; pub use atomic_float::AtomicF32;
pub use core::any::Any; pub use core::any::Any;
pub use core::num::Saturating;
pub use core::sync::atomic::{AtomicBool, AtomicI8, AtomicU32, Ordering}; pub use core::sync::atomic::{AtomicBool, AtomicI8, AtomicU32, Ordering};
pub use pkmn_lib_interface::app_interface::{ pub use pkmn_lib_interface::app_interface::{
get_volatile_as, BattleSide, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, get_volatile_as, BattleSide, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove,

View File

@ -21,14 +21,10 @@ impl Script for Acrobatics {
mv: ExecutingMove, mv: ExecutingMove,
_target: Pokemon, _target: Pokemon,
_hit: u8, _hit: u8,
base_power: &mut u8, base_power: &mut Saturating<u8>,
) -> PkmnResult<()> { ) -> PkmnResult<()> {
if mv.user().held_item()?.is_none() { if mv.user().held_item()?.is_none() {
if *base_power >= 128_u8 { *base_power *= 2;
*base_power = 255
} else {
*base_power *= 2;
}
} }
Ok(()) Ok(())
} }
@ -65,11 +61,11 @@ mod tests {
let mv = mock_executing_move(false); let mv = mock_executing_move(false);
let script = Acrobatics::new(); let script = Acrobatics::new();
let mut base_power = 50u8; let mut base_power = Saturating(50u8);
script script
.change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power) .change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power)
.unwrap(); .unwrap();
assert_eq!(100, base_power); assert_eq!(100, base_power.0);
} }
#[test] #[test]
@ -77,11 +73,11 @@ mod tests {
let mv = mock_executing_move(false); let mv = mock_executing_move(false);
let script = Acrobatics::new(); let script = Acrobatics::new();
let mut base_power = 200u8; let mut base_power = Saturating(200u8);
script script
.change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power) .change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power)
.unwrap(); .unwrap();
assert_eq!(255, base_power); assert_eq!(255, base_power.0);
} }
#[test] #[test]
@ -89,10 +85,10 @@ mod tests {
let mv = mock_executing_move(true); let mv = mock_executing_move(true);
let script = Acrobatics::new(); let script = Acrobatics::new();
let mut base_power = 50u8; let mut base_power = Saturating(50u8);
script script
.change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power) .change_base_power(mv, Rc::new(MockPokemon::new()), 0, &mut base_power)
.unwrap(); .unwrap();
assert_eq!(50, base_power); assert_eq!(50, base_power.0);
} }
} }

View File

@ -40,7 +40,7 @@ impl Script for Assurance {
_move: ExecutingMove, _move: ExecutingMove,
target: Pokemon, target: Pokemon,
_hit: u8, _hit: u8,
base_power: &mut u8, base_power: &mut Saturating<u8>,
) -> PkmnResult<()> { ) -> PkmnResult<()> {
if let Some(s) = get_volatile_as::<AssuranceData>( if let Some(s) = get_volatile_as::<AssuranceData>(
target.battle_side()?.as_ref(), target.battle_side()?.as_ref(),

View File

@ -21,7 +21,7 @@ impl Script for IncreasedCriticalStage {
_move: ExecutingMove, _move: ExecutingMove,
_target: Pokemon, _target: Pokemon,
_hit: u8, _hit: u8,
stage: &mut u8, stage: &mut Saturating<u8>,
) -> PkmnResult<()> { ) -> PkmnResult<()> {
*stage += 1; *stage += 1;
Ok(()) Ok(())

View File

@ -21,7 +21,11 @@ impl Script for MultiHitMove {
&[ScriptCapabilities::ChangeNumberOfHits] &[ScriptCapabilities::ChangeNumberOfHits]
} }
fn change_number_of_hits(&self, choice: TurnChoice, number_of_hits: &mut u8) -> PkmnResult<()> { fn change_number_of_hits(
&self,
choice: TurnChoice,
number_of_hits: &mut Saturating<u8>,
) -> PkmnResult<()> {
// 35% chance that it will hit 2 times, a 35% chance it will hit 3 times, a 15% chance it // 35% chance that it will hit 2 times, a 35% chance it will hit 3 times, a 15% chance it
// will hit 4 times, and a 15% chance it will hit 5 times. // will hit 4 times, and a 15% chance it will hit 5 times.
let rand_value = choice let rand_value = choice
@ -30,12 +34,12 @@ impl Script for MultiHitMove {
.unwrap() .unwrap()
.random() .random()
.get_between(0, 100)?; .get_between(0, 100)?;
*number_of_hits = match rand_value { number_of_hits.0 = match rand_value {
0..=34 => 2, 0..=34 => 2,
35..=69 => 3, 35..=69 => 3,
70..=84 => 4, 70..=84 => 4,
85..=100 => 5, 85..=100 => 5,
_ => *number_of_hits, _ => number_of_hits.0,
}; };
Ok(()) Ok(())
} }

View File

@ -23,9 +23,9 @@ impl Script for Struggle {
fn change_number_of_hits( fn change_number_of_hits(
&self, &self,
_choice: TurnChoice, _choice: TurnChoice,
number_of_hits: &mut u8, number_of_hits: &mut Saturating<u8>,
) -> PkmnResult<()> { ) -> PkmnResult<()> {
*number_of_hits = 1; number_of_hits.0 = 1;
Ok(()) Ok(())
} }

View File

@ -28,7 +28,7 @@ impl Script for AuroraVeilEffect {
mv: ExecutingMove, mv: ExecutingMove,
target: Pokemon, target: Pokemon,
hit: u8, hit: u8,
damage: &mut u32, damage: &mut Saturating<u32>,
) -> PkmnResult<()> { ) -> PkmnResult<()> {
if mv.get_hit_data(&target, hit)?.is_critical()? { if mv.get_hit_data(&target, hit)?.is_critical()? {
return Ok(()); return Ok(());
@ -48,7 +48,7 @@ impl Script for AuroraVeilEffect {
if target.battle()?.unwrap().pokemon_per_side()? > 1 { if target.battle()?.unwrap().pokemon_per_side()? > 1 {
modifier = 1.5 modifier = 1.5
} }
*damage = (*damage as f32 / modifier) as u32; damage.0 = (damage.0 as f32 / modifier) as u32;
Ok(()) Ok(())
} }

View File

@ -8,6 +8,8 @@ use alloc::rc::Rc;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::any::Any; use core::any::Any;
use core::fmt::{Debug, Display, Formatter}; use core::fmt::{Debug, Display, Formatter};
use core::num::Saturating;
type Result<T> = crate::result::PkmnResult<T>; type Result<T> = crate::result::PkmnResult<T>;
pub trait Script { pub trait Script {
@ -45,7 +47,7 @@ pub trait Script {
/// This function allows you to modify the effective speed of the Pokemon. This is ran before /// 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. /// turn ordering, so overriding here will allow you to put certain Pokemon before others.
fn change_speed(&self, _choice: TurnChoice, _speed: &mut u32) -> Result<()> { fn change_speed(&self, _choice: TurnChoice, _speed: &mut Saturating<u32>) -> Result<()> {
Ok(()) Ok(())
} }
/// This function allows you to modify the effective priority of the Pokemon. This is ran before /// This function allows you to modify the effective priority of the Pokemon. This is ran before
@ -63,7 +65,11 @@ pub trait Script {
/// This function allows you to change a move into a multi-hit move. The number of hits set here /// 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 /// gets used as the number of hits. If set to 0, this will behave as if the move missed on its
/// first hit. /// first hit.
fn change_number_of_hits(&self, _choice: TurnChoice, _number_of_hits: &mut u8) -> Result<()> { fn change_number_of_hits(
&self,
_choice: TurnChoice,
_number_of_hits: &mut Saturating<u8>,
) -> Result<()> {
Ok(()) Ok(())
} }
@ -157,7 +163,7 @@ pub trait Script {
_move: ExecutingMove, _move: ExecutingMove,
_target: Pokemon, _target: Pokemon,
_hit: u8, _hit: u8,
_accuracy: &mut u8, _accuracy: &mut Saturating<u8>,
) -> Result<()> { ) -> Result<()> {
Ok(()) Ok(())
} }
@ -168,7 +174,7 @@ pub trait Script {
_move: ExecutingMove, _move: ExecutingMove,
_target: Pokemon, _target: Pokemon,
_hit: u8, _hit: u8,
_stage: &mut u8, _stage: &mut Saturating<u8>,
) -> Result<()> { ) -> Result<()> {
Ok(()) Ok(())
} }
@ -201,7 +207,7 @@ pub trait Script {
_move: ExecutingMove, _move: ExecutingMove,
_target: Pokemon, _target: Pokemon,
_hit: u8, _hit: u8,
_base_power: &mut u8, _base_power: &mut Saturating<u8>,
) -> Result<()> { ) -> Result<()> {
Ok(()) Ok(())
} }
@ -231,7 +237,7 @@ pub trait Script {
_move: ExecutingMove, _move: ExecutingMove,
_target: Pokemon, _target: Pokemon,
_hit: u8, _hit: u8,
_amount: &mut u32, _amount: &mut Saturating<u32>,
) -> Result<()> { ) -> Result<()> {
Ok(()) Ok(())
} }
@ -241,7 +247,7 @@ pub trait Script {
_move: ExecutingMove, _move: ExecutingMove,
_target: Pokemon, _target: Pokemon,
_hit: u8, _hit: u8,
_amount: &mut u32, _amount: &mut Saturating<u32>,
) -> Result<()> { ) -> Result<()> {
Ok(()) Ok(())
} }
@ -273,7 +279,7 @@ pub trait Script {
_move: ExecutingMove, _move: ExecutingMove,
_target: Pokemon, _target: Pokemon,
_hit: u8, _hit: u8,
_damage: &mut u32, _damage: &mut Saturating<u32>,
) -> Result<()> { ) -> Result<()> {
Ok(()) Ok(())
} }
@ -283,7 +289,7 @@ pub trait Script {
_move: ExecutingMove, _move: ExecutingMove,
_target: Pokemon, _target: Pokemon,
_hit: u8, _hit: u8,
_damage: &mut u32, _damage: &mut Saturating<u32>,
) -> Result<()> { ) -> Result<()> {
Ok(()) Ok(())
} }
@ -428,7 +434,7 @@ pub trait Script {
&self, &self,
_fainted_mon: Pokemon, _fainted_mon: Pokemon,
_winning_mon: Pokemon, _winning_mon: Pokemon,
_amount: &mut u32, _amount: &mut Saturating<u32>,
) -> Result<()> { ) -> Result<()> {
Ok(()) Ok(())
} }
@ -454,7 +460,7 @@ pub trait Script {
&self, &self,
_target: Pokemon, _target: Pokemon,
_pokeball: Item, _pokeball: Item,
_modifier: &mut u8, _modifier: &mut Saturating<u8>,
) -> Result<()> { ) -> Result<()> {
Ok(()) Ok(())
} }

File diff suppressed because it is too large Load Diff