From 258c497982fbc1187c52e660ebcc1dee7a4624cd Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Fri, 6 Jan 2023 11:10:30 +0100 Subject: [PATCH] Rework ScriptOwners to be a little easier to use --- gen_7_scripts/src/moves/assurance.rs | 4 +- gen_7_scripts/src/moves/aurora_veil.rs | 3 +- pkmn_lib_interface/src/handling/script.rs | 111 ++++++++++++++++++---- pkmn_lib_interface/src/lib.rs | 1 + 4 files changed, 96 insertions(+), 23 deletions(-) diff --git a/gen_7_scripts/src/moves/assurance.rs b/gen_7_scripts/src/moves/assurance.rs index 49100f0..c75975a 100755 --- a/gen_7_scripts/src/moves/assurance.rs +++ b/gen_7_scripts/src/moves/assurance.rs @@ -5,6 +5,7 @@ use core::sync::atomic::{AtomicBool, Ordering}; use pkmn_lib_interface::app_interface::{ BattleSide, DamageSource, ExecutingMove, Pokemon, TurnChoice, WithVolatile, }; +use pkmn_lib_interface::handling::script::ScriptOwner; use pkmn_lib_interface::handling::{Script, ScriptCapabilities}; script!(Assurance, "assurance"); @@ -86,9 +87,8 @@ impl Script for AssuranceData { &[ScriptCapabilities::OnEndTurn, ScriptCapabilities::OnDamage] } - #[cfg(not(test))] fn on_end_turn(&self) { - let side: pkmn_lib_interface::app_interface::BattleSideImpl = self.get_owner().unwrap(); + let side = self.get_owner().unwrap().as_side(); side.remove_volatile(self); } diff --git a/gen_7_scripts/src/moves/aurora_veil.rs b/gen_7_scripts/src/moves/aurora_veil.rs index 2af9187..815d8da 100644 --- a/gen_7_scripts/src/moves/aurora_veil.rs +++ b/gen_7_scripts/src/moves/aurora_veil.rs @@ -63,7 +63,6 @@ impl Script for AuroraVeilEffect { &[ScriptCapabilities::ChangeIncomingDamage, OnEndTurn] } - #[cfg(not(test))] fn change_incoming_damage( &self, mv: ExecutingMove, @@ -74,7 +73,7 @@ impl Script for AuroraVeilEffect { if mv.get_hit_data(&target, hit).is_critical() { return; } - let side: pkmn_lib_interface::app_interface::BattleSideImpl = self.get_owner().unwrap(); + let side = self.get_owner().unwrap().as_side(); if side.has_volatile(ReflectEffect::get_const_name()) && mv.use_move().category() == MoveCategory::Physical { diff --git a/pkmn_lib_interface/src/handling/script.rs b/pkmn_lib_interface/src/handling/script.rs index 0845091..466d83e 100755 --- a/pkmn_lib_interface/src/handling/script.rs +++ b/pkmn_lib_interface/src/handling/script.rs @@ -1,13 +1,14 @@ use crate::app_interface::list::ImmutableList; use crate::app_interface::{ - Battle, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Item, Pokemon, Statistic, - TurnChoice, TypeIdentifier, + Battle, BattleSide, DamageSource, DynamicLibrary, EffectParameter, ExecutingMove, Item, + Pokemon, Statistic, TurnChoice, TypeIdentifier, }; use crate::handling::ScriptCapabilities; use crate::{ExternRef, ExternalReferenceType, StringKey}; use alloc::rc::Rc; use core::any::Any; -use core::fmt::Debug; +use core::fmt::{Debug, Display, Formatter}; +use core::panicking::panic; pub trait Script { fn new() -> Self @@ -346,25 +347,11 @@ pub trait Script { fn as_any(&self) -> &dyn Any; - #[cfg(not(feature = "mock_data"))] - fn get_owner(&self) -> Option - where - T: ExternalReferenceType, - Self: Sized, - { - unsafe { - script_get_owner(crate::implementation::ScriptPtr::from_existing(self)) - .cast::() - .get_value() - } - } - - #[cfg(feature = "mock_data")] - fn get_owner(&self) -> Option + fn get_owner(&self) -> Option where Self: Sized, { - unimplemented!() + ScriptOwner::from_script(self) } } @@ -376,5 +363,91 @@ impl Debug for dyn Script { #[cfg(not(feature = "mock_data"))] extern "wasm" { + fn script_get_owner_kind(pointer: crate::implementation::ScriptPtr) -> u8; fn script_get_owner(pointer: crate::implementation::ScriptPtr) -> ExternRef; } + +pub enum ScriptOwner { + Pokemon(Pokemon), + BattleSide(BattleSide), + Battle(Battle), + None, +} + +impl ScriptOwner { + #[cfg(not(feature = "mock_data"))] + fn from_script(script: &dyn Script) -> Option { + let script_ptr = crate::implementation::ScriptPtr::from_existing(script); + unsafe { + let kind = script_get_owner_kind(script_ptr); + match kind { + 0 => { + let r = script_get_owner(script_ptr) + .cast::() + .get_value(); + if r.is_none() { + None + } else { + Some(ScriptOwner::Pokemon(Rc::new(r.unwrap()))) + } + } + 1 => { + let r = script_get_owner(script_ptr) + .cast::() + .get_value(); + if r.is_none() { + None + } else { + Some(ScriptOwner::BattleSide(Rc::new(r.unwrap()))) + } + } + 2 => { + let r = script_get_owner(script_ptr) + .cast::() + .get_value(); + if r.is_none() { + None + } else { + Some(ScriptOwner::Battle(Rc::new(r.unwrap()))) + } + } + _ => panic!("Unknown script owner kind: {}", kind), + } + } + } + + #[cfg(feature = "mock_data")] + fn from_script(script: &dyn Script) -> Option { + unimplemented!(); + } + + pub fn as_pokemon(&self) -> Pokemon { + if let ScriptOwner::Pokemon(p) = self { + return p.clone(); + } + panic!("ScriptOwner was not a Pokemon, but a {self}"); + } + pub fn as_side(&self) -> BattleSide { + if let ScriptOwner::BattleSide(p) = self { + return p.clone(); + } + panic!("ScriptOwner was not a BattleSide, but a {self}"); + } + pub fn as_battle(&self) -> Battle { + if let ScriptOwner::Battle(p) = self { + return p.clone(); + } + panic!("ScriptOwner was not a Battle, but a {self}"); + } +} + +impl Display for ScriptOwner { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + ScriptOwner::Pokemon(_) => f.write_str("Pokemon"), + ScriptOwner::BattleSide(_) => f.write_str("BattleSide"), + ScriptOwner::Battle(_) => f.write_str("Battle"), + ScriptOwner::None => f.write_str("None"), + } + } +} diff --git a/pkmn_lib_interface/src/lib.rs b/pkmn_lib_interface/src/lib.rs index afb7316..05f12d7 100755 --- a/pkmn_lib_interface/src/lib.rs +++ b/pkmn_lib_interface/src/lib.rs @@ -80,6 +80,7 @@ mod implementation { static mut SCRIPT_INDEX_COUNTER: AtomicU32 = AtomicU32::new(1); #[repr(C)] + #[derive(Copy, Clone)] pub struct ScriptPtr { index: u32, }