diff --git a/src/dynamic_data/choices.rs b/src/dynamic_data/choices.rs index fbd4705..cf5efde 100755 --- a/src/dynamic_data/choices.rs +++ b/src/dynamic_data/choices.rs @@ -7,10 +7,13 @@ use crate::dynamic_data::Pokemon; use crate::dynamic_data::ScriptContainer; use crate::dynamic_data::{LearnedMove, ScriptWrapper}; use crate::dynamic_data::{ScriptSource, ScriptSourceData}; +use crate::{ValueIdentifiable, ValueIdentifier}; /// The data on a turn choice that should be contained in every turn choice, regardless of type. #[derive(Debug)] struct CommonChoiceData { + /// A unique identifier so we know what value this is. + identifier: ValueIdentifier, /// The user of the turn choice user: Arc, /// The speed of the user at the beginning of the turn. @@ -185,6 +188,7 @@ impl MoveChoice { script: Default::default(), priority: 0, choice_data: Box::new(CommonChoiceData { + identifier: Default::default(), user, speed: 0, random_value: 0, @@ -256,6 +260,7 @@ impl ItemChoice { pub fn new(user: Arc) -> Self { Self { choice_data: Box::new(CommonChoiceData { + identifier: Default::default(), user, speed: 0, random_value: 0, @@ -294,6 +299,7 @@ impl SwitchChoice { pub fn new(user: Arc) -> Self { Self { choice_data: Box::new(CommonChoiceData { + identifier: Default::default(), user, speed: 0, random_value: 0, @@ -332,6 +338,7 @@ impl FleeChoice { pub fn new(user: Arc) -> Self { Self { choice_data: Box::new(CommonChoiceData { + identifier: Default::default(), user, speed: 0, random_value: 0, @@ -370,6 +377,7 @@ impl PassChoice { pub fn new(user: Arc) -> Self { Self { choice_data: Box::new(CommonChoiceData { + identifier: Default::default(), user, speed: 0, random_value: 0, @@ -470,3 +478,9 @@ impl Ord for TurnChoice { } } } + +impl ValueIdentifiable for TurnChoice { + fn value_identifier(&self) -> ValueIdentifier { + self.choice_data().identifier + } +} diff --git a/src/ffi/dynamic_data/choices.rs b/src/ffi/dynamic_data/choices.rs new file mode 100644 index 0000000..c772319 --- /dev/null +++ b/src/ffi/dynamic_data/choices.rs @@ -0,0 +1,104 @@ +use crate::dynamic_data::{FleeChoice, LearnedMove, MoveChoice, PassChoice, Pokemon, TurnChoice}; +use crate::ffi::{ExternPointer, IdentifiablePointer, OwnedPtr}; +use std::ptr::drop_in_place; +use std::sync::Arc; + +/// Disposes a turn choice. +#[no_mangle] +extern "C" fn turn_choice_drop(choice: OwnedPtr) { + unsafe { drop_in_place(choice) } +} + +/// Get the user of the given choice. +#[no_mangle] +extern "C" fn turn_choice_user(choice: ExternPointer) -> IdentifiablePointer> { + choice.as_ref().user().clone().into() +} + +/// Get the speed of the user for the choice. Note that this speed is the speed of the Pokemon +/// at the start of the turn! +#[no_mangle] +extern "C" fn turn_choice_speed(choice: ExternPointer) -> u32 { + choice.as_ref().speed() +} + +/// Gets whether or not the choice has failed. If we notice this when we execute the choice, we +/// will not execute it. +#[no_mangle] +extern "C" fn turn_choice_has_failed(choice: ExternPointer) -> u8 { + u8::from(choice.as_ref().has_failed()) +} + +/// Fails the choice. This will prevent it from executing and run a specific fail handling during +/// execution. Note that this can not be undone. +#[no_mangle] +extern "C" fn turn_choice_fail(choice: ExternPointer) { + choice.as_ref().fail() +} + +/// Creates a new Turn Choice with a move to use. +#[no_mangle] +extern "C" fn turn_choice_move_new( + user: ExternPointer>, + learned_move: ExternPointer>, + target_side: u8, + target_index: u8, +) -> IdentifiablePointer { + Box::new(TurnChoice::Move(MoveChoice::new( + user.as_ref().clone(), + learned_move.as_ref().clone(), + target_side, + target_index, + ))) + .into() +} + +/// The actual learned move on the Pokemon we use for this choice. +#[no_mangle] +extern "C" fn turn_choice_move_learned_move( + choice: ExternPointer, +) -> IdentifiablePointer> { + if let TurnChoice::Move(c) = choice.as_ref() { + return c.used_move().clone().into(); + } + panic!("Turn choice was not a learned move"); +} + +/// The target side the move is aimed at. +#[no_mangle] +extern "C" fn turn_choice_move_target_side(choice: ExternPointer) -> u8 { + if let TurnChoice::Move(c) = choice.as_ref() { + return c.target_side(); + } + panic!("Turn choice was not a learned move"); +} + +/// The Pokemon index on the side we're aiming at. +#[no_mangle] +extern "C" fn turn_choice_move_target_index(choice: ExternPointer) -> u8 { + if let TurnChoice::Move(c) = choice.as_ref() { + return c.target_index(); + } + panic!("Turn choice was not a learned move"); +} + +/// The priority of the move choice at the beginning of the turn. +#[no_mangle] +extern "C" fn turn_choice_move_priority(choice: ExternPointer) -> i8 { + if let TurnChoice::Move(c) = choice.as_ref() { + return c.priority(); + } + panic!("Turn choice was not a learned move"); +} + +/// Creates a new Turn Choice for the user to flee. +#[no_mangle] +extern "C" fn turn_choice_flee_new(user: ExternPointer>) -> IdentifiablePointer { + Box::new(TurnChoice::Flee(FleeChoice::new(user.as_ref().clone()))).into() +} + +/// Creates a new Turn Choice for the user to pass the turn. +#[no_mangle] +extern "C" fn turn_choice_pass_new(user: ExternPointer>) -> IdentifiablePointer { + Box::new(TurnChoice::Pass(PassChoice::new(user.as_ref().clone()))).into() +} diff --git a/src/ffi/dynamic_data/mod.rs b/src/ffi/dynamic_data/mod.rs index df1e5ff..044a575 100644 --- a/src/ffi/dynamic_data/mod.rs +++ b/src/ffi/dynamic_data/mod.rs @@ -1,3 +1,5 @@ +/// The foreign function interfaces for the turn choices +mod choices; /// The foreign function interfaces for the dynamic data libraries mod libraries; /// The foreign function interfaces for the dynamic data models