Make SecondaryEffect a trait
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
e04f61d9e6
commit
1c0b953d9a
|
@ -6,7 +6,7 @@ use hashbrown::HashSet;
|
|||
use crate::dynamic_data::choices::{MoveChoice, TurnChoice};
|
||||
use crate::dynamic_data::Pokemon;
|
||||
use crate::dynamic_data::{LearnedMove, MoveLearnMethod};
|
||||
use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffect};
|
||||
use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffectImpl};
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
|
||||
/// The misc library holds several misc functions required for the battle to run.
|
||||
|
@ -40,7 +40,11 @@ impl Gen7MiscLibrary {
|
|||
255,
|
||||
MoveTarget::Any,
|
||||
0,
|
||||
Some(SecondaryEffect::new(-1.0, StringKey::new("struggle"), vec![])),
|
||||
Some(Box::new(SecondaryEffectImpl::new(
|
||||
-1.0,
|
||||
StringKey::new("struggle"),
|
||||
vec![],
|
||||
))),
|
||||
HashSet::new(),
|
||||
));
|
||||
let struggle_learned_move = Arc::new(LearnedMove::new(&struggle_data, MoveLearnMethod::Unknown));
|
||||
|
|
|
@ -139,7 +139,7 @@ impl<T: ValueIdentifiable + ?Sized> From<Arc<T>> for IdentifiablePointer<Arc<T>>
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ValueIdentifiable> From<Option<Arc<T>>> for IdentifiablePointer<Arc<T>> {
|
||||
impl<T: ValueIdentifiable + ?Sized> 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()) };
|
||||
|
@ -153,6 +153,46 @@ impl<T: ValueIdentifiable> From<Option<Arc<T>>> for IdentifiablePointer<Arc<T>>
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ValueIdentifiable + ?Sized> From<Box<T>> for IdentifiablePointer<Box<T>> {
|
||||
fn from(v: Box<T>) -> Self {
|
||||
let id = unsafe { transmute(v.value_identifier()) };
|
||||
Self {
|
||||
ptr: Box::into_raw(Box::new(v)),
|
||||
id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ValueIdentifiable + ?Sized> From<Option<Box<T>>> for IdentifiablePointer<Box<T>> {
|
||||
fn from(v: Option<Box<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 + ?Sized> From<&Option<Box<T>>> for IdentifiablePointer<Box<T>> {
|
||||
fn from(v: &Option<Box<T>>) -> Self {
|
||||
if let Some(v) = v {
|
||||
let id = unsafe { transmute(v.value_identifier()) };
|
||||
unsafe {
|
||||
Self {
|
||||
ptr: *Box::into_raw(Box::new(v as *const Box<T>)),
|
||||
id,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ValueIdentifiable> From<Box<T>> for IdentifiablePointer<T> {
|
||||
fn from(v: Box<T>) -> Self {
|
||||
let id = unsafe { transmute(v.value_identifier()) };
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use crate::ffi::{ffi_arc_getter, BorrowedPtr, ExternPointer, IdentifiablePointer, OwnedPtr};
|
||||
use crate::static_data::{EffectParameter, MoveCategory, MoveData, MoveTarget, SecondaryEffect, TypeIdentifier};
|
||||
use crate::static_data::{
|
||||
EffectParameter, MoveCategory, MoveData, MoveTarget, SecondaryEffect, SecondaryEffectImpl, TypeIdentifier,
|
||||
};
|
||||
use crate::StringKey;
|
||||
use hashbrown::HashSet;
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
|
@ -17,7 +19,7 @@ unsafe extern "C" fn move_data_new(
|
|||
base_usages: u8,
|
||||
target: MoveTarget,
|
||||
priority: i8,
|
||||
secondary_effect: *mut SecondaryEffect,
|
||||
secondary_effect: *mut Box<dyn SecondaryEffect>,
|
||||
flags: *const *const c_char,
|
||||
flags_length: usize,
|
||||
) -> IdentifiablePointer<Arc<MoveData>> {
|
||||
|
@ -72,13 +74,8 @@ ffi_arc_getter!(MoveData, priority, i8);
|
|||
#[no_mangle]
|
||||
unsafe extern "C" fn move_data_secondary_effect(
|
||||
ptr: ExternPointer<Arc<MoveData>>,
|
||||
) -> IdentifiablePointer<SecondaryEffect> {
|
||||
let effect = ptr.as_ref().secondary_effect();
|
||||
if let Some(v) = effect {
|
||||
(v as *const SecondaryEffect).into()
|
||||
} else {
|
||||
IdentifiablePointer::none()
|
||||
}
|
||||
) -> IdentifiablePointer<Box<dyn SecondaryEffect>> {
|
||||
ptr.as_ref().secondary_effect().into()
|
||||
}
|
||||
|
||||
/// Arbitrary flags that can be applied to the move.
|
||||
|
@ -95,49 +92,49 @@ unsafe extern "C" fn secondary_effect_new(
|
|||
effect_name: BorrowedPtr<c_char>,
|
||||
parameters: *mut OwnedPtr<EffectParameter>,
|
||||
parameters_length: usize,
|
||||
) -> IdentifiablePointer<SecondaryEffect> {
|
||||
) -> IdentifiablePointer<Box<dyn SecondaryEffect>> {
|
||||
let parameter_slice = std::slice::from_raw_parts(parameters, parameters_length);
|
||||
let mut parameters = Vec::with_capacity(parameters_length);
|
||||
for parameter in parameter_slice {
|
||||
parameters.push(*Box::from_raw(*parameter))
|
||||
}
|
||||
|
||||
Box::new(SecondaryEffect::new(
|
||||
let b: Box<dyn SecondaryEffect> = Box::new(SecondaryEffectImpl::new(
|
||||
chance,
|
||||
CStr::from_ptr(effect_name).into(),
|
||||
parameters,
|
||||
))
|
||||
.into()
|
||||
));
|
||||
b.into()
|
||||
}
|
||||
|
||||
/// Drop a secondary effect.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn secondary_effect_drop(ptr: OwnedPtr<SecondaryEffect>) {
|
||||
unsafe extern "C" fn secondary_effect_drop(ptr: OwnedPtr<Box<dyn SecondaryEffect>>) {
|
||||
drop_in_place(ptr)
|
||||
}
|
||||
|
||||
/// The chance the effect triggers.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn secondary_effect_chance(ptr: ExternPointer<SecondaryEffect>) -> f32 {
|
||||
unsafe extern "C" fn secondary_effect_chance(ptr: ExternPointer<Box<dyn SecondaryEffect>>) -> f32 {
|
||||
ptr.as_ref().chance()
|
||||
}
|
||||
|
||||
/// The name of the effect.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn secondary_effect_effect_name(ptr: ExternPointer<SecondaryEffect>) -> OwnedPtr<c_char> {
|
||||
unsafe extern "C" fn secondary_effect_effect_name(ptr: ExternPointer<Box<dyn SecondaryEffect>>) -> OwnedPtr<c_char> {
|
||||
CString::new(ptr.as_ref().effect_name().str()).unwrap().into_raw()
|
||||
}
|
||||
|
||||
/// The length of parameters of the effect.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn secondary_effect_parameter_length(ptr: ExternPointer<SecondaryEffect>) -> usize {
|
||||
unsafe extern "C" fn secondary_effect_parameter_length(ptr: ExternPointer<Box<dyn SecondaryEffect>>) -> usize {
|
||||
ptr.as_ref().parameters().len()
|
||||
}
|
||||
|
||||
/// Get a parameter of the effect.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn secondary_effect_parameter_get(
|
||||
ptr: ExternPointer<SecondaryEffect>,
|
||||
ptr: ExternPointer<Box<dyn SecondaryEffect>>,
|
||||
index: usize,
|
||||
) -> IdentifiablePointer<EffectParameter> {
|
||||
if let Some(v) = ptr.as_ref().parameters().get(index) {
|
||||
|
|
|
@ -60,7 +60,7 @@ pub enum MoveTarget {
|
|||
}
|
||||
|
||||
/// A move is the skill Pokémon primarily use in battle. This is the data related to that.
|
||||
#[derive(PartialEq, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct MoveData {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
|
@ -82,7 +82,7 @@ pub struct MoveData {
|
|||
/// The priority of the move. A higher priority means the move should go before other moves.
|
||||
priority: i8,
|
||||
/// The optional secondary effect the move has.
|
||||
secondary_effect: Option<SecondaryEffect>,
|
||||
secondary_effect: Option<Box<dyn SecondaryEffect>>,
|
||||
/// Arbitrary flags that can be applied to the move.
|
||||
flags: HashSet<StringKey>,
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ impl MoveData {
|
|||
base_usages: u8,
|
||||
target: MoveTarget,
|
||||
priority: i8,
|
||||
secondary_effect: Option<SecondaryEffect>,
|
||||
secondary_effect: Option<Box<dyn SecondaryEffect>>,
|
||||
flags: HashSet<StringKey>,
|
||||
) -> MoveData {
|
||||
MoveData {
|
||||
|
@ -151,7 +151,7 @@ impl MoveData {
|
|||
}
|
||||
|
||||
/// The optional secondary effect the move has.
|
||||
pub fn secondary_effect(&self) -> &Option<SecondaryEffect> {
|
||||
pub fn secondary_effect(&self) -> &Option<Box<dyn SecondaryEffect>> {
|
||||
&self.secondary_effect
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
use crate::static_data::EffectParameter;
|
||||
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// A secondary effect is an effect on a move that happens after it hits.
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct SecondaryEffect {
|
||||
pub trait SecondaryEffect: Debug + ValueIdentifiable {
|
||||
/// The chance in percentages that the effect triggers. -1 to make it always trigger.
|
||||
fn chance(&self) -> f32;
|
||||
/// The name of the effect.
|
||||
fn effect_name(&self) -> &StringKey;
|
||||
/// A list of parameters for the effect.
|
||||
fn parameters(&self) -> &Vec<EffectParameter>;
|
||||
}
|
||||
|
||||
/// A secondary effect is an effect on a move that happens after it hits.
|
||||
#[derive(Debug)]
|
||||
pub struct SecondaryEffectImpl {
|
||||
/// A unique identifier so we know what value this is.
|
||||
identifier: ValueIdentifier,
|
||||
/// The chance in percentages that the effect triggers. -1 to make it always trigger.
|
||||
|
@ -14,32 +25,34 @@ pub struct SecondaryEffect {
|
|||
parameters: Vec<EffectParameter>,
|
||||
}
|
||||
|
||||
impl SecondaryEffect {
|
||||
impl SecondaryEffectImpl {
|
||||
/// Instantiates a new Secondary Effect.
|
||||
pub fn new(chance: f32, effect_name: StringKey, parameters: Vec<EffectParameter>) -> SecondaryEffect {
|
||||
SecondaryEffect {
|
||||
pub fn new(chance: f32, effect_name: StringKey, parameters: Vec<EffectParameter>) -> Self {
|
||||
Self {
|
||||
identifier: Default::default(),
|
||||
chance,
|
||||
effect_name,
|
||||
parameters,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SecondaryEffect for SecondaryEffectImpl {
|
||||
/// The chance in percentages that the effect triggers. -1 to make it always trigger.
|
||||
pub fn chance(&self) -> f32 {
|
||||
fn chance(&self) -> f32 {
|
||||
self.chance
|
||||
}
|
||||
/// The name of the effect.
|
||||
pub fn effect_name(&self) -> &StringKey {
|
||||
fn effect_name(&self) -> &StringKey {
|
||||
&self.effect_name
|
||||
}
|
||||
/// A list of parameters for the effect.
|
||||
pub fn parameters(&self) -> &Vec<EffectParameter> {
|
||||
fn parameters(&self) -> &Vec<EffectParameter> {
|
||||
&self.parameters
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueIdentifiable for SecondaryEffect {
|
||||
impl ValueIdentifiable for SecondaryEffectImpl {
|
||||
fn value_identifier(&self) -> ValueIdentifier {
|
||||
self.identifier
|
||||
}
|
||||
|
@ -50,14 +63,15 @@ mod tests {
|
|||
use assert_approx_eq::assert_approx_eq;
|
||||
|
||||
use crate::static_data::moves::secondary_effect::SecondaryEffect;
|
||||
use crate::static_data::SecondaryEffectImpl;
|
||||
|
||||
#[test]
|
||||
fn create_secondary_effect() {
|
||||
let empty = SecondaryEffect::new(0.0, "".into(), vec![]);
|
||||
let empty = SecondaryEffectImpl::new(0.0, "".into(), vec![]);
|
||||
assert_approx_eq!(empty.chance(), 0.0);
|
||||
assert_eq!(empty.effect_name(), &"".into());
|
||||
assert_eq!(empty.parameters().len(), 0);
|
||||
let set = SecondaryEffect::new(50.0, "foo".into(), Vec::new());
|
||||
let set = SecondaryEffectImpl::new(50.0, "foo".into(), Vec::new());
|
||||
assert_approx_eq!(set.chance(), 50.0);
|
||||
assert_eq!(set.effect_name(), &"foo".into());
|
||||
assert_eq!(set.parameters().len(), 0);
|
||||
|
|
|
@ -18,7 +18,7 @@ use pkmn_lib::script_implementations::wasm::script_resolver::WebAssemblyScriptRe
|
|||
use pkmn_lib::static_data::{
|
||||
AbilityImpl, AbilityLibrary, BattleItemCategory, DataLibrary, EffectParameter, Form, GrowthRateLibrary, ItemImpl,
|
||||
ItemLibrary, LearnableMoves, LibrarySettings, LookupGrowthRate, MoveData, MoveLibrary, NatureImpl, NatureLibrary,
|
||||
SecondaryEffect, Species, StaticData, StaticStatisticSet, Statistic, TypeLibrary,
|
||||
SecondaryEffect, SecondaryEffectImpl, Species, StaticData, StaticStatisticSet, Statistic, TypeLibrary,
|
||||
};
|
||||
use pkmn_lib::StringKey;
|
||||
|
||||
|
@ -182,7 +182,7 @@ pub fn load_moves(path: &String, lib: &mut StaticData) {
|
|||
let pp = move_data.get("pp").unwrap().as_i64().unwrap() as u8;
|
||||
let target = serde_json::from_value(move_data.get("target").unwrap().clone()).unwrap();
|
||||
let priority = move_data.get("priority").unwrap().as_i64().unwrap() as i8;
|
||||
let secondary_effect = if let Some(v) = move_data.get("effect") {
|
||||
let secondary_effect: Option<Box<dyn SecondaryEffect>> = if let Some(v) = move_data.get("effect") {
|
||||
let mut chance = -1.0;
|
||||
if let Some(chance_value) = v.get("chance") {
|
||||
chance = chance_value.as_f64().unwrap() as f32;
|
||||
|
@ -195,11 +195,11 @@ pub fn load_moves(path: &String, lib: &mut StaticData) {
|
|||
}
|
||||
}
|
||||
|
||||
Some(SecondaryEffect::new(
|
||||
Some(Box::new(SecondaryEffectImpl::new(
|
||||
chance,
|
||||
v.get("name").unwrap().as_str().unwrap().into(),
|
||||
parameters,
|
||||
))
|
||||
)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue