use crate::script; use alloc::boxed::Box; use core::any::Any; use core::sync::atomic::{AtomicBool, Ordering}; use pkmn_lib_interface::app_interface::{ BattleSide, DamageSource, ExecutingMove, Pokemon, TurnChoice, }; use pkmn_lib_interface::handling::{Script, ScriptCapabilities}; script!(Assurance, "assurance"); impl Script for Assurance { fn new() -> Self { Self {} } fn get_name(&self) -> &'static str { Self::get_const_name() } fn get_capabilities(&self) -> &[ScriptCapabilities] { &[ ScriptCapabilities::OnBeforeTurn, ScriptCapabilities::ChangeBasePower, ] } fn on_before_turn(&self, choice: TurnChoice) { if let TurnChoice::Move(data) = &choice { let side: BattleSide = choice .user() .battle() .unwrap() .sides() .get(data.target_side() as u32) .unwrap(); side.add_volatile(Box::new(AssuranceData { for_position: data.target_index(), has_hit: AtomicBool::new(false), })); } } fn change_base_power( &self, _move: ExecutingMove, target: Pokemon, _hit: u8, base_power: &mut u8, ) { if let Some(s) = target .battle_side() .get_volatile::(AssuranceData::get_const_name()) { if s.has_hit.load(Ordering::Relaxed) { *base_power *= 2; } } } fn as_any(&self) -> &dyn Any { self } } script!( AssuranceData, "assurance_data", for_position: u8, has_hit: AtomicBool ); impl Script for AssuranceData { fn new() -> Self { Self { for_position: 0, has_hit: AtomicBool::new(false), } } fn get_name(&self) -> &'static str { Self::get_const_name() } fn get_capabilities(&self) -> &[ScriptCapabilities] { &[ScriptCapabilities::OnEndTurn, ScriptCapabilities::OnDamage] } fn on_end_turn(&self) { let side: BattleSide = self.get_owner().unwrap(); side.remove_volatile(self); } fn on_damage( &self, pokemon: Pokemon, _source: DamageSource, _old_health: u32, _new_health: u32, ) { if pokemon.battle_side_index() == self.for_position { self.has_hit.store(true, Ordering::Relaxed); } } fn as_any(&self) -> &dyn Any { self } }