use crate::dynamic_data::models::damage_source::DamageSource; 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(&self); fn remove_suppression(&self); // FIXME: add missing parameters fn stack(&self) {} fn on_remove(&self) {} fn on_initialize(&mut self, _pars: &[EffectParameter]) {} fn on_before_turn(&self) {} fn change_speed(&self) {} fn change_priority(&self) {} fn change_attack(&self) {} fn change_number_of_hits(&self) {} fn prevent_attack(&self) {} fn fail_attack(&self) {} fn stop_before_attack(&self) {} fn on_before_attack(&self) {} fn fail_incoming_attack(&self) {} fn is_invulnerable(&self) {} 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 } } }