use crate::dynamic_data::{Event, Pokemon}; use crate::ffi::{ExternPointer, IdentifiablePointer}; /// The kind of the event. #[no_mangle] extern "C" fn event_kind(ptr: ExternPointer) -> u8 { match ptr.as_ref() { Event::Switch { .. } => 1, Event::Swap { .. } => 2, Event::SpeciesChange { .. } => 3, Event::FormChange { .. } => 4, Event::Damage { .. } => 5, Event::Heal { .. } => 6, Event::Faint { .. } => 7, Event::MoveUse { .. } => 8, Event::Miss { .. } => 9, Event::EndTurn => 10, Event::StatBoostChange { .. } => 11, } } /// Generates the entire FFI function we need for an event. macro_rules! event_ffi { ( $event_name:ident { $( $(#[doc = $doc:expr])? $par_name:ident: $par_type:ty, )+ }, $ctor:block ) => { paste::paste!{ /// A C struct to hold the data for the event #[repr(C)] struct [<$event_name Data>]{ $( $(#[doc = $doc])? $par_name: $par_type, )+ } /// The getter for the data for the relevant event. #[no_mangle] extern "C" fn [](ptr: ExternPointer) -> [<$event_name Data>] { if let Event::$event_name { $( $par_name, )+ } = ptr.as_ref() { $ctor } panic!(concat!("Event was not a ", stringify!($event_name), " data")); } } }; } event_ffi!( Switch { /// The side the Pokemon got switched from/on side_index: u8, /// The index of the Pokemon that got switched in/out on its side index: u8, /// The new Pokemon that will be on the spot. If none, the spot will be null. pokemon: IdentifiablePointer, }, { return SwitchData{ side_index: *side_index, index: *index, pokemon: pokemon.clone().into(), } } ); event_ffi!( Swap { /// The side the Pokemon swapped on. side_index: u8, /// The index on the side of the first Pokemon that was swapped. index_a: u8, /// The index on the side of the second pokemon that was swapped. index_b: u8, }, { return SwapData { side_index: *side_index, index_a: *index_a, index_b: *index_b, }; } );