use crate::dynamic_data::choices::TurnChoice; use crate::dynamic_data::models::battle::Battle; use crate::dynamic_data::models::damage_source::DamageSource; use crate::dynamic_data::models::executing_move::ExecutingMove; use crate::dynamic_data::models::pokemon::Pokemon; use crate::static_data::moves::secondary_effect::EffectParameter; use crate::static_data::{Item, Statistic}; use crate::StringKey; use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; use std::any::Any; use std::fmt::{Debug, Formatter}; use std::sync::Arc; pub trait Script { fn name(&self) -> &StringKey; fn is_suppressed(&self) -> bool { self.get_suppressed_count() > 0 } fn get_suppressed_count(&self) -> usize; fn add_suppression(&mut self); fn remove_suppression(&mut self); fn stack(&mut self) {} fn on_remove(&mut self) {} fn on_initialize(&mut self, _pars: &[EffectParameter]) {} fn on_before_turn(&mut self, _choice: &TurnChoice) {} fn change_speed(&mut self, _choice: &TurnChoice, _speed: &mut u32) {} fn change_priority(&mut self, _choice: &TurnChoice, _priority: &mut i8) {} fn change_move(&mut self, _choice: &TurnChoice, _move_name: &mut StringKey) {} fn change_number_of_hits(&mut self, _choice: &TurnChoice, _number_of_hits: &mut u8) {} fn prevent_move(&mut self, _move: &ExecutingMove, _prevent: &mut bool) {} fn fail_move(&mut self, _move: &ExecutingMove, _fail: &mut bool) {} fn stop_before_move(&mut self, _move: &ExecutingMove, _stop: &mut bool) {} fn on_before_move(&mut self, _move: &ExecutingMove) {} fn fail_incoming_move(&mut self, _move: &ExecutingMove, _target: &Pokemon, _fail: &mut bool) {} fn is_invulnerable( &mut self, _move: &ExecutingMove, _target: &Pokemon, _invulnerable: &mut bool, ) { } fn on_move_miss(&mut self, _move: &ExecutingMove, _target: &Pokemon) {} fn change_move_type(&mut self, _move: &ExecutingMove, _target: &Pokemon, _move_type: &mut u8) {} fn change_effectiveness( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _effectiveness: &mut f32, ) { } fn block_critical( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _block_critical: &mut bool, ) { } fn block_incoming_critical( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _block_critical: &mut bool, ) { } fn change_critical_stage( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _stage: &mut u8, ) { } fn change_critical_modifier( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _modifier: &mut f32, ) { } fn change_stab_modifier( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _modifier: &mut f32, ) { } fn change_base_power( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _base_power: &mut u8, ) { } fn change_damage_stats_user( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _stats_user: &mut Pokemon, ) { } fn bypass_defensive_stat( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _bypass: &mut bool, ) { } fn bypass_offensive_stat( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _bypass: &mut bool, ) { } fn change_offensive_stat( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _amount: &mut f32, ) { } fn change_defensive_stat( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _amount: &mut f32, ) { } fn change_stat_modifier( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _modifier: &mut f32, ) { } fn change_damage_modifier( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _modifier: &mut f32, ) { } fn change_damage( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _damage: &mut u32, ) { } fn change_incoming_damage( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _damage: &mut u32, ) { } fn on_incoming_hit(&mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8) {} fn on_opponent_faints(&mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8) {} fn prevent_stat_boost_change( &mut self, _target: &Pokemon, _stat: Statistic, _amount: i8, _self_inflicted: bool, _prevent: &mut bool, ) { } fn change_stat_boost_change( &mut self, _target: &Pokemon, _stat: Statistic, _self_inflicted: bool, _amount: *mut i8, ) { } fn prevent_secondary_effect( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _prevent: &mut bool, ) { } fn change_effect_chance( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _chance: &mut f32, ) { } fn change_incoming_effect_change( &mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8, _chance: &mut f32, ) { } fn on_secondary_effect(&mut self, _move: &ExecutingMove, _target: &Pokemon, _hit: u8) {} fn on_after_hits(&mut self, _move: &ExecutingMove, _target: &Pokemon) {} fn prevent_self_switch(&mut self, _choice: &TurnChoice, _prevent: &mut bool) {} fn prevent_opponent_switch(&mut self, _choice: &TurnChoice, _prevent: &mut bool) {} fn on_fail(&mut self, _target: &Pokemon) {} fn on_opponent_fail(&mut self, _target: &Pokemon) {} fn prevent_self_run_away(&mut self, _choice: &TurnChoice, _prevent: &mut bool) {} fn prevent_opponent_run_away(&mut self, _choice: &TurnChoice, _prevent: &mut bool) {} fn on_end_turn(&mut self) {} fn on_damage( &mut self, _pokemon: &Pokemon, _source: DamageSource, _old_health: u32, _new_health: u32, ) { } fn on_faint(&mut self, _pokemon: &Pokemon, _source: DamageSource) {} fn on_switch_in(&mut self, _pokemon: &Pokemon) {} fn on_after_held_item_consume(&mut self, _pokemon: &Pokemon, _item: &Item) {} fn change_experience_gained( &mut self, _fainted_mon: &Pokemon, _winning_mon: &Pokemon, _amount: &mut u32, ) { } fn share_experience( &mut self, _fainted_mon: &Pokemon, _winning_mon: &Pokemon, _shares: &mut bool, ) { } fn block_weather(&mut self, _battle: &Battle, _blocked: &mut bool) {} fn change_capture_rate_bonus( &mut self, _target: &Pokemon, _pokeball: &Item, _modifier: &mut u8, ) { } fn as_any(&self) -> &dyn Any; } impl Debug for dyn Script { fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { Ok(()) } } type ScriptHolder = Arc>>>; #[derive(Default, Debug, Clone)] pub struct ScriptContainer { script: ScriptHolder, } impl ScriptContainer { pub fn new(script: Box) -> ScriptContainer { Self { script: Arc::new(RwLock::new(Some(script))), } } pub fn get(&self) -> RwLockWriteGuard<'_, Option>> { self.script.write() } pub fn set(&self, script: Box) { self.script.write().replace(script); } pub fn clear(&self) { self.script.write().take(); } pub fn arc(&self) -> &ScriptHolder { &self.script } pub fn get_as(&self) -> MappedRwLockReadGuard { RwLockReadGuard::map(self.script.read(), |a| unsafe { let ptr = a.as_ref().as_ref().unwrap().as_ref() as *const dyn Script; let any = ptr.as_ref().unwrap().as_any(); any.downcast_ref::().unwrap() }) } } impl From for ScriptContainer { fn from(a: ScriptHolder) -> Self { Self { script: a } } }