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