use crate::dynamic_data::choices::TurnChoice; 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::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); // FIXME: add missing parameters, and make all these mut 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_attack(&mut self, _choice: &TurnChoice, _move_name: &mut StringKey) {} fn change_number_of_hits(&mut self, _choice: &TurnChoice, _number_of_hits: &mut u8) {} fn prevent_attack(&mut self, _move: &ExecutingMove, _prevent: &mut bool) {} fn fail_attack(&mut self, _move: &ExecutingMove, _fail: &mut bool) {} fn stop_before_attack(&mut self, _move: &ExecutingMove, _stop: &mut bool) {} fn on_before_attack(&mut self, _move: &ExecutingMove) {} fn fail_incoming_attack(&mut self, _move: &ExecutingMove, _target: &Pokemon, _fail: &mut bool) { } fn is_invulnerable( &mut self, _move: &ExecutingMove, _target: &Pokemon, _invulnerable: &mut bool, ) { } fn on_attack_miss(&self) {} fn change_attack_type(&self) {} fn block_critical(&self) {} fn override_base_power(&self) {} fn change_damage_stats_user(&self) {} fn bypass_defensive_stat(&self) {} fn bypass_offensive_stat(&self) {} fn change_stat_modifier(&self) {} fn change_damage_modifier(&self) {} fn change_damage(&self) {} fn change_incoming_damage(&self) {} fn on_incoming_hit(&self) {} fn on_opponent_faints(&self) {} fn prevent_stat_boost_change(&self) {} fn change_stat_boost_change(&self) {} fn on_secondary_effect(&self) {} fn on_after_hits(&self) {} fn prevent_self_switch(&self) {} fn prevent_opponent_switch(&self) {} fn modify_effect_chance(&self) {} fn modify_incoming_effect_change(&self) {} fn on_fail(&self) {} fn on_opponent_fail(&self) {} fn prevent_self_run_away(&self) {} fn prevent_opponent_run_away(&self) {} fn on_end_turn(&self) {} fn on_damage( &self, _pokemon: &Pokemon, _source: DamageSource, _old_health: u32, _new_health: u32, ) { } fn on_faint(&self, _pokemon: &Pokemon, _source: DamageSource) {} fn on_switch_in(&self, _pokemon: &Pokemon) {} fn on_after_held_item_consume(&self) {} 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 } } }