Work on FFI, fixes for learned_move::restore_uses
This commit is contained in:
parent
1b627378f6
commit
a6a9cb573f
|
@ -58,7 +58,7 @@ pub enum Event<'own> {
|
||||||
/// The index of the Pokemon that got switched in/out on its side
|
/// The index of the Pokemon that got switched in/out on its side
|
||||||
index: u8,
|
index: u8,
|
||||||
/// The new Pokemon that will be on the spot. If none, the spot will now be empty.
|
/// The new Pokemon that will be on the spot. If none, the spot will now be empty.
|
||||||
pokemon: Option<&'own Pokemon>,
|
pokemon: Option<Arc<Pokemon>>,
|
||||||
},
|
},
|
||||||
/// A swap event happens when two Pokemon on a side swap positions. Note that this is rare.
|
/// A swap event happens when two Pokemon on a side swap positions. Note that this is rare.
|
||||||
Swap {
|
Swap {
|
||||||
|
|
|
@ -193,7 +193,7 @@ impl BattleSide {
|
||||||
battle.event_hook().trigger(Event::Switch {
|
battle.event_hook().trigger(Event::Switch {
|
||||||
side_index: self.index,
|
side_index: self.index,
|
||||||
index,
|
index,
|
||||||
pokemon: Some(pokemon),
|
pokemon: Some(pokemon.clone()),
|
||||||
});
|
});
|
||||||
script_hook!(on_switch_in, pokemon, pokemon);
|
script_hook!(on_switch_in, pokemon, pokemon);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -86,7 +86,7 @@ impl LearnedMove {
|
||||||
if x + uses > self.max_pp {
|
if x + uses > self.max_pp {
|
||||||
uses = self.max_pp - x;
|
uses = self.max_pp - x;
|
||||||
}
|
}
|
||||||
Some(x)
|
Some(x + uses)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -97,3 +97,29 @@ impl ValueIdentifiable for LearnedMove {
|
||||||
self.identifier
|
self.identifier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::static_data::{MoveCategory, MoveTarget};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_learned_move_restore_uses() {
|
||||||
|
let data = Arc::new(MoveData::new(
|
||||||
|
&"foo".into(),
|
||||||
|
0u8.into(),
|
||||||
|
MoveCategory::Special,
|
||||||
|
100,
|
||||||
|
20,
|
||||||
|
30,
|
||||||
|
MoveTarget::All,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
Default::default(),
|
||||||
|
));
|
||||||
|
let learned_move = LearnedMove::new(&data, MoveLearnMethod::Level);
|
||||||
|
assert!(learned_move.try_use(15));
|
||||||
|
learned_move.restore_uses(5);
|
||||||
|
assert_eq!(20, learned_move.remaining_pp());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
use crate::dynamic_data::{Event, Pokemon};
|
||||||
|
use crate::ffi::{ExternPointer, IdentifiablePointer};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
/// The kind of the event.
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn event_kind(ptr: ExternPointer<Event>) -> 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 [<event_ $event_name:snake _data>](ptr: ExternPointer<Event>) -> [<$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<Arc<Pokemon>>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::dynamic_data::{LearnedMove, MoveLearnMethod};
|
use crate::dynamic_data::{LearnedMove, MoveLearnMethod};
|
||||||
use crate::ffi::{ExternPointer, IdentifiablePointer};
|
use crate::ffi::{ExternPointer, IdentifiablePointer, OwnedPtr};
|
||||||
use crate::static_data::MoveData;
|
use crate::static_data::MoveData;
|
||||||
|
use std::ptr::drop_in_place;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Instantiate a new learned move.
|
/// Instantiate a new learned move.
|
||||||
|
@ -12,6 +13,12 @@ extern "C" fn learned_move_new(
|
||||||
Arc::new(LearnedMove::new(move_data.as_ref(), learn_method)).into()
|
Arc::new(LearnedMove::new(move_data.as_ref(), learn_method)).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Drops a learned move.
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn learned_move_drop(learned_move: OwnedPtr<Arc<LearnedMove>>) {
|
||||||
|
unsafe { drop_in_place(learned_move) }
|
||||||
|
}
|
||||||
|
|
||||||
/// The immutable move information of the move.
|
/// The immutable move information of the move.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn learned_move_move_data(
|
extern "C" fn learned_move_move_data(
|
||||||
|
@ -39,7 +46,7 @@ extern "C" fn learned_move_learn_method(learned_move: ExternPointer<Arc<LearnedM
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try and reduce the PP by a certain amount. If the amount is higher than the current uses,
|
/// Try and reduce the PP by a certain amount. If the amount is higher than the current uses,
|
||||||
/// return false. Otherwise, reduce the PP, and return true.
|
/// return 0. Otherwise, reduce the PP, and return 1.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn learned_move_try_use(learned_move: ExternPointer<Arc<LearnedMove>>, amount: u8) -> u8 {
|
extern "C" fn learned_move_try_use(learned_move: ExternPointer<Arc<LearnedMove>>, amount: u8) -> u8 {
|
||||||
u8::from(learned_move.as_ref().try_use(amount))
|
u8::from(learned_move.as_ref().try_use(amount))
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
mod battle;
|
mod battle;
|
||||||
/// The foreign function interface for a battle wrapper of a party.
|
/// The foreign function interface for a battle wrapper of a party.
|
||||||
mod battle_party;
|
mod battle_party;
|
||||||
|
/// The foreign function interface for a battle event
|
||||||
|
mod event;
|
||||||
/// The foreign function interface for a Learned Move.
|
/// The foreign function interface for a Learned Move.
|
||||||
mod learned_move;
|
mod learned_move;
|
||||||
/// Wrapper classed for the event hooks.
|
/// Wrapper classed for the event hooks.
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use crate::dynamic_data::Event;
|
use crate::dynamic_data::Event;
|
||||||
|
use crate::ffi::BorrowedPtr;
|
||||||
|
|
||||||
/// Wrapper class for easier use of an external function pointer.
|
/// Wrapper class for easier use of an external function pointer.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub(super) struct NativeEventHook {
|
pub(super) struct NativeEventHook {
|
||||||
/// The actual C function to be called.
|
/// The actual C function to be called.
|
||||||
f: extern "C" fn(*const Event),
|
f: extern "C" fn(BorrowedPtr<Event>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NativeEventHook {
|
impl NativeEventHook {
|
||||||
|
|
|
@ -139,6 +139,20 @@ impl<T: ValueIdentifiable> From<Arc<T>> for IdentifiablePointer<Arc<T>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: ValueIdentifiable> From<Option<Arc<T>>> for IdentifiablePointer<Arc<T>> {
|
||||||
|
fn from(v: Option<Arc<T>>) -> Self {
|
||||||
|
if let Some(v) = v {
|
||||||
|
let id = unsafe { transmute(v.value_identifier()) };
|
||||||
|
Self {
|
||||||
|
ptr: Box::into_raw(Box::new(v)),
|
||||||
|
id,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
IdentifiablePointer::none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: ValueIdentifiable> From<Box<T>> for IdentifiablePointer<T> {
|
impl<T: ValueIdentifiable> From<Box<T>> for IdentifiablePointer<T> {
|
||||||
fn from(v: Box<T>) -> Self {
|
fn from(v: Box<T>) -> Self {
|
||||||
let id = unsafe { transmute(v.value_identifier()) };
|
let id = unsafe { transmute(v.value_identifier()) };
|
||||||
|
|
Loading…
Reference in New Issue