Basic implementation of evolutions
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
3f91f80982
commit
d8b8559c2e
|
@ -0,0 +1,57 @@
|
|||
use crate::dynamic_data::Pokemon;
|
||||
use crate::static_data::{EvolutionMethod, TimeOfDay};
|
||||
|
||||
/// A library for handling the checking of evolution requirements.
|
||||
pub trait EvolutionLibrary {
|
||||
/// Checks if the given Pokemon fulfills the given evolution conditions.
|
||||
fn pokemon_fulfills_evolution_conditions(&self, pokemon: &Pokemon, method: &EvolutionMethod) -> bool;
|
||||
}
|
||||
|
||||
/// A standard implementation of the Evolution Library.
|
||||
pub struct EvolutionLibraryImpl;
|
||||
|
||||
impl EvolutionLibrary for EvolutionLibraryImpl {
|
||||
fn pokemon_fulfills_evolution_conditions(&self, pokemon: &Pokemon, method: &EvolutionMethod) -> bool {
|
||||
match method {
|
||||
EvolutionMethod::Level { level } => pokemon.level() >= *level,
|
||||
EvolutionMethod::LevelGender { level, gender } => pokemon.level() >= *level && pokemon.gender() == *gender,
|
||||
EvolutionMethod::Item { .. } => false,
|
||||
EvolutionMethod::ItemGender { .. } => false,
|
||||
EvolutionMethod::HoldItem { item } => pokemon.has_held_item(item),
|
||||
EvolutionMethod::DayHoldItem { item } => {
|
||||
let time_of_day = pokemon.library().misc_library().time_of_day();
|
||||
pokemon.has_held_item(item) && time_of_day == TimeOfDay::Morning || time_of_day == TimeOfDay::Day
|
||||
}
|
||||
EvolutionMethod::NightHoldItem { item } => {
|
||||
let time_of_day = pokemon.library().misc_library().time_of_day();
|
||||
pokemon.has_held_item(item) && time_of_day == TimeOfDay::Evening || time_of_day == TimeOfDay::Night
|
||||
}
|
||||
EvolutionMethod::HasMove { move_name } => pokemon
|
||||
.learned_moves()
|
||||
.read()
|
||||
.iter()
|
||||
.any(|learned_move| learned_move.as_ref().is_some_and(|v| v.move_data().name() == move_name)),
|
||||
EvolutionMethod::Happiness { happiness } => pokemon.happiness() >= *happiness,
|
||||
EvolutionMethod::HappinessDay { happiness } => {
|
||||
let time_of_day = pokemon.library().misc_library().time_of_day();
|
||||
pokemon.happiness() >= *happiness && time_of_day == TimeOfDay::Morning || time_of_day == TimeOfDay::Day
|
||||
}
|
||||
EvolutionMethod::HappinessNight { happiness } => {
|
||||
let time_of_day = pokemon.library().misc_library().time_of_day();
|
||||
pokemon.happiness() >= *happiness && time_of_day == TimeOfDay::Evening
|
||||
|| time_of_day == TimeOfDay::Night
|
||||
}
|
||||
EvolutionMethod::Trade => false,
|
||||
EvolutionMethod::TradeSpecies { .. } => false,
|
||||
EvolutionMethod::TradeItem { .. } => false,
|
||||
EvolutionMethod::Location { .. } => {
|
||||
// TODO: Implement this.
|
||||
false
|
||||
}
|
||||
EvolutionMethod::Custom { .. } => {
|
||||
// TODO: Implement this.
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,3 +19,5 @@ pub(crate) mod dynamic_library;
|
|||
mod misc_library;
|
||||
/// Data for dynamically resolving scripts during battles.
|
||||
mod script_resolver;
|
||||
/// Handling for checking evolution requirements.
|
||||
mod evolution_library;
|
||||
|
|
|
@ -68,6 +68,9 @@ struct PokemonData {
|
|||
/// The height of the Pokemon in meters.
|
||||
height: Atomic<f32>,
|
||||
|
||||
/// The happiness of the Pokemon. Also known as friendship.
|
||||
happiness: AtomicU8,
|
||||
|
||||
/// The stats of the Pokemon when disregarding any stat boosts.
|
||||
flat_stats: Arc<StatisticSet<u32>>,
|
||||
/// The statistics boosts of the Pokemon. Will prevent the value from going above 6, and below
|
||||
|
@ -158,6 +161,7 @@ impl Pokemon {
|
|||
.calculate_experience(species.growth_rate(), level)?;
|
||||
let weight = form.weight();
|
||||
let height = form.height();
|
||||
let base_happiness = species.base_happiness();
|
||||
let nature = library
|
||||
.static_data()
|
||||
.natures()
|
||||
|
@ -198,6 +202,7 @@ impl Pokemon {
|
|||
status_script: ScriptContainer::default(),
|
||||
volatile: Default::default(),
|
||||
script_source_data: Default::default(),
|
||||
happiness: AtomicU8::new(base_happiness),
|
||||
};
|
||||
|
||||
let pokemon = Self {
|
||||
|
@ -326,11 +331,16 @@ impl Pokemon {
|
|||
pub fn set_weight(&self, weight: f32) {
|
||||
self.data.weight.store(weight, Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// The height of the Pokemon in meters.
|
||||
pub fn height(&self) -> f32 {
|
||||
self.data.height.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// The current happiness of the Pokemon. Also known as friendship.
|
||||
pub fn happiness(&self) -> u8 {
|
||||
self.data.happiness.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// An optional nickname of the Pokemon.
|
||||
pub fn nickname(&self) -> &Option<String> {
|
||||
&self.data.nickname
|
||||
|
@ -921,6 +931,7 @@ impl Pokemon {
|
|||
current_health: AtomicU32::new(value.current_health),
|
||||
weight: Atomic::new(value.weight),
|
||||
height: Atomic::new(value.height),
|
||||
happiness: AtomicU8::new(value.happiness),
|
||||
flat_stats: Arc::new(Default::default()),
|
||||
stat_boost: Arc::new(value.stat_boosts.clone()),
|
||||
boosted_stats: Arc::new(Default::default()),
|
||||
|
@ -1163,6 +1174,7 @@ pub mod test {
|
|||
});
|
||||
species.expect_growth_rate().return_const(StringKey::empty());
|
||||
species.expect_name().return_const(StringKey::new("test_species"));
|
||||
species.expect_base_happiness().return_const(100);
|
||||
|
||||
let s: Arc<dyn Species> = Arc::new(species);
|
||||
Some(s)
|
||||
|
|
|
@ -34,6 +34,8 @@ pub struct SerializedPokemon {
|
|||
pub weight: f32,
|
||||
/// The height of the Pokemon.
|
||||
pub height: f32,
|
||||
/// The happiness of the Pokemon.
|
||||
pub happiness: u8,
|
||||
/// The stat boosts of the Pokemon.
|
||||
pub stat_boosts: ClampedStatisticSet<i8, -6, 6>,
|
||||
/// The individual values of the Pokemon.
|
||||
|
@ -101,6 +103,7 @@ impl Into<anyhow_ext::Result<SerializedPokemon>> for &Pokemon {
|
|||
current_health: self.current_health(),
|
||||
weight: self.weight(),
|
||||
height: self.height(),
|
||||
happiness: self.happiness(),
|
||||
stat_boosts: self.stat_boosts().deref().deref().clone(),
|
||||
individual_values: self.individual_values().deref().deref().clone(),
|
||||
effort_values: self.effort_values().deref().deref().clone(),
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::dynamic_data::Pokemon;
|
||||
use crate::static_data::EffectParameter;
|
||||
use crate::static_data::Parameter;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// The script functions that are relevant to item use.
|
||||
pub trait ItemScript {
|
||||
/// Initializes the script with the given parameters for a specific item
|
||||
fn on_initialize(&self, _pars: Vec<Arc<EffectParameter>>) -> anyhow_ext::Result<()> {
|
||||
fn on_initialize(&self, _pars: Vec<Arc<Parameter>>) -> anyhow_ext::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ use crate::dynamic_data::{Battle, DynamicLibrary};
|
|||
use crate::dynamic_data::{BattleSide, DamageSource};
|
||||
use crate::dynamic_data::{ExecutingMove, WeakBattleReference, WeakPokemonReference};
|
||||
use crate::dynamic_data::{Pokemon, WeakBattleSideReference};
|
||||
use crate::static_data::{EffectParameter, TypeIdentifier};
|
||||
use crate::static_data::{Item, Statistic};
|
||||
use crate::static_data::{Parameter, TypeIdentifier};
|
||||
use crate::StringKey;
|
||||
|
||||
/// The script trait is used to make changes to how a battle executes, without requiring hardcoded
|
||||
|
@ -69,7 +69,7 @@ pub trait Script: Send + Sync {
|
|||
Ok(())
|
||||
}
|
||||
/// This function is ran when this script starts being in effect.
|
||||
fn on_initialize(&self, _library: &Arc<dyn DynamicLibrary>, _pars: Vec<Arc<EffectParameter>>) -> Result<()> {
|
||||
fn on_initialize(&self, _library: &Arc<dyn DynamicLibrary>, _pars: Vec<Arc<Parameter>>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// This function is ran just before the start of the turn. Everyone has made its choices here,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::static_data::{
|
||||
Ability, EffectParameter, Form, GrowthRate, Item, LearnableMoves, MoveData, Nature, SecondaryEffect, Species,
|
||||
Ability, Form, GrowthRate, Item, LearnableMoves, MoveData, Nature, Parameter, SecondaryEffect, Species,
|
||||
StaticStatisticSet, StatisticSet,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
|
@ -60,7 +60,7 @@ impl<T> Default for FFIHandle<T> {
|
|||
#[allow(clippy::missing_docs_in_private_items)] // I'm not documenting these items.
|
||||
pub(super) enum FFIObject {
|
||||
Ability(Arc<dyn Ability>),
|
||||
EffectParameter(Arc<EffectParameter>),
|
||||
EffectParameter(Arc<Parameter>),
|
||||
StatisticSetU8(Arc<StatisticSet<u8>>),
|
||||
StatisticSetI8(Arc<StatisticSet<i8>>),
|
||||
StatisticSetU32(Arc<StatisticSet<u32>>),
|
||||
|
@ -307,7 +307,7 @@ macro_rules! ffi_obj_conversions {
|
|||
}
|
||||
|
||||
ffi_obj_conversions!(Arc<dyn Ability>, Ability);
|
||||
ffi_obj_conversions!(Arc<EffectParameter>, EffectParameter);
|
||||
ffi_obj_conversions!(Arc<Parameter>, EffectParameter);
|
||||
ffi_obj_conversions!(Arc<StatisticSet<i8>>, StatisticSetI8);
|
||||
ffi_obj_conversions!(Arc<StatisticSet<u8>>, StatisticSetU8);
|
||||
ffi_obj_conversions!(Arc<StatisticSet<u32>>, StatisticSetU32);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::ffi::FFIHandle;
|
||||
use crate::ffi::FromFFIHandle;
|
||||
use crate::ffi::{FFIResult, OwnedPtrString};
|
||||
use crate::static_data::{Ability, AbilityImpl, EffectParameter};
|
||||
use crate::static_data::{Ability, AbilityImpl, Parameter};
|
||||
use crate::StringKey;
|
||||
use anyhow::anyhow;
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
|
@ -12,11 +12,11 @@ use std::sync::Arc;
|
|||
unsafe extern "C" fn ability_new(
|
||||
name: *const c_char,
|
||||
effect: *const c_char,
|
||||
parameters: *const FFIHandle<Arc<EffectParameter>>,
|
||||
parameters: *const FFIHandle<Arc<Parameter>>,
|
||||
parameters_length: usize,
|
||||
) -> FFIResult<FFIHandle<Arc<dyn Ability>>> {
|
||||
let parameters = std::slice::from_raw_parts(parameters, parameters_length);
|
||||
let mut parameters_vec: Vec<Arc<EffectParameter>> = Vec::with_capacity(parameters_length);
|
||||
let mut parameters_vec: Vec<Arc<Parameter>> = Vec::with_capacity(parameters_length);
|
||||
for parameter in parameters {
|
||||
parameters_vec.push(parameter.from_ffi_handle());
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ unsafe extern "C" fn ability_parameter_length(ptr: FFIHandle<Arc<dyn Ability>>)
|
|||
unsafe extern "C" fn ability_parameter_get(
|
||||
ptr: FFIHandle<Arc<dyn Ability>>,
|
||||
index: usize,
|
||||
) -> FFIHandle<Arc<EffectParameter>> {
|
||||
) -> FFIHandle<Arc<Parameter>> {
|
||||
if let Some(p) = ptr.from_ffi_handle().parameters().get(index) {
|
||||
FFIHandle::get_handle(p.clone().into())
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::ffi::ffi_handle::{FFIHandle, FFIObject, FromFFIHandle};
|
||||
use crate::ffi::{FFIResult, OwnedPtrString};
|
||||
use crate::static_data::EffectParameter;
|
||||
use crate::static_data::Parameter;
|
||||
use crate::{PkmnError, StringKey};
|
||||
use anyhow::anyhow;
|
||||
use std::ffi::{c_char, CStr, CString};
|
||||
|
@ -30,50 +30,50 @@ mod statistic_set;
|
|||
|
||||
/// Instantiates an effect parameter with a boolean.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_new_bool(value: u8) -> FFIHandle<Arc<EffectParameter>> {
|
||||
FFIHandle::get_handle(FFIObject::EffectParameter(Arc::new(EffectParameter::from(value == 1))))
|
||||
extern "C" fn effect_parameter_new_bool(value: u8) -> FFIHandle<Arc<Parameter>> {
|
||||
FFIHandle::get_handle(FFIObject::EffectParameter(Arc::new(Parameter::from(value == 1))))
|
||||
}
|
||||
|
||||
/// Instantiates an effect parameter with an integer.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_new_int(value: i64) -> FFIHandle<Arc<EffectParameter>> {
|
||||
FFIHandle::get_handle(FFIObject::EffectParameter(Arc::new(EffectParameter::from(value))))
|
||||
extern "C" fn effect_parameter_new_int(value: i64) -> FFIHandle<Arc<Parameter>> {
|
||||
FFIHandle::get_handle(FFIObject::EffectParameter(Arc::new(Parameter::from(value))))
|
||||
}
|
||||
|
||||
/// Instantiates an effect parameter with a float.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_new_float(value: f32) -> FFIHandle<Arc<EffectParameter>> {
|
||||
FFIHandle::get_handle(FFIObject::EffectParameter(Arc::new(EffectParameter::from(value))))
|
||||
extern "C" fn effect_parameter_new_float(value: f32) -> FFIHandle<Arc<Parameter>> {
|
||||
FFIHandle::get_handle(FFIObject::EffectParameter(Arc::new(Parameter::from(value))))
|
||||
}
|
||||
|
||||
/// Instantiates an effect parameter with a string.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn effect_parameter_new_string(value: *const c_char) -> FFIResult<FFIHandle<Arc<EffectParameter>>> {
|
||||
unsafe extern "C" fn effect_parameter_new_string(value: *const c_char) -> FFIResult<FFIHandle<Arc<Parameter>>> {
|
||||
let sk: StringKey = match CStr::from_ptr(value).to_str() {
|
||||
Ok(sk) => sk.into(),
|
||||
Err(_) => return FFIResult::err(PkmnError::InvalidCString.into()),
|
||||
};
|
||||
FFIResult::ok(FFIHandle::get_handle(FFIObject::EffectParameter(Arc::new(
|
||||
EffectParameter::from(sk),
|
||||
Parameter::from(sk),
|
||||
))))
|
||||
}
|
||||
|
||||
/// Get the type of an effect parameter.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_get_type(ptr: FFIHandle<Arc<EffectParameter>>) -> u8 {
|
||||
extern "C" fn effect_parameter_get_type(ptr: FFIHandle<Arc<Parameter>>) -> u8 {
|
||||
match ptr.from_ffi_handle().deref() {
|
||||
EffectParameter::Bool(_) => 0,
|
||||
EffectParameter::Int(_) => 1,
|
||||
EffectParameter::Float(_) => 2,
|
||||
EffectParameter::String(_) => 3,
|
||||
Parameter::Bool(_) => 0,
|
||||
Parameter::Int(_) => 1,
|
||||
Parameter::Float(_) => 2,
|
||||
Parameter::String(_) => 3,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the boolean contained in the effect parameter, panics if the effect parameter is not a bool.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_get_as_bool(ptr: FFIHandle<Arc<EffectParameter>>) -> FFIResult<u8> {
|
||||
extern "C" fn effect_parameter_get_as_bool(ptr: FFIHandle<Arc<Parameter>>) -> FFIResult<u8> {
|
||||
let p = ptr.from_ffi_handle();
|
||||
if let EffectParameter::Bool(b) = p.deref() {
|
||||
if let Parameter::Bool(b) = p.deref() {
|
||||
FFIResult::ok(u8::from(*b))
|
||||
} else {
|
||||
FFIResult::err(anyhow!("Unexpected effect parameter. Expected bool, was: {}", p))
|
||||
|
@ -82,9 +82,9 @@ extern "C" fn effect_parameter_get_as_bool(ptr: FFIHandle<Arc<EffectParameter>>)
|
|||
|
||||
/// Get the int contained in the effect parameter, panics if the effect parameter is not a int.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_get_as_int(ptr: FFIHandle<Arc<EffectParameter>>) -> FFIResult<i64> {
|
||||
extern "C" fn effect_parameter_get_as_int(ptr: FFIHandle<Arc<Parameter>>) -> FFIResult<i64> {
|
||||
let p = ptr.from_ffi_handle();
|
||||
if let EffectParameter::Int(b) = p.deref() {
|
||||
if let Parameter::Int(b) = p.deref() {
|
||||
FFIResult::ok(*b)
|
||||
} else {
|
||||
FFIResult::err(anyhow!("Unexpected effect parameter. Expected int, was: {}", p))
|
||||
|
@ -93,9 +93,9 @@ extern "C" fn effect_parameter_get_as_int(ptr: FFIHandle<Arc<EffectParameter>>)
|
|||
|
||||
/// Get the float contained in the effect parameter, panics if the effect parameter is not a float.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_get_as_float(ptr: FFIHandle<Arc<EffectParameter>>) -> FFIResult<f32> {
|
||||
extern "C" fn effect_parameter_get_as_float(ptr: FFIHandle<Arc<Parameter>>) -> FFIResult<f32> {
|
||||
let p = ptr.from_ffi_handle();
|
||||
if let EffectParameter::Float(b) = p.deref() {
|
||||
if let Parameter::Float(b) = p.deref() {
|
||||
FFIResult::ok(*b)
|
||||
} else {
|
||||
FFIResult::err(anyhow!("Unexpected effect parameter. Expected float, was: {}", p))
|
||||
|
@ -104,9 +104,9 @@ extern "C" fn effect_parameter_get_as_float(ptr: FFIHandle<Arc<EffectParameter>>
|
|||
|
||||
/// Get the string contained in the effect parameter, panics if the effect parameter is not a string.
|
||||
#[no_mangle]
|
||||
extern "C" fn effect_parameter_get_as_string(ptr: FFIHandle<Arc<EffectParameter>>) -> FFIResult<OwnedPtrString> {
|
||||
extern "C" fn effect_parameter_get_as_string(ptr: FFIHandle<Arc<Parameter>>) -> FFIResult<OwnedPtrString> {
|
||||
let p = ptr.from_ffi_handle();
|
||||
if let EffectParameter::String(b) = p.deref() {
|
||||
if let Parameter::String(b) = p.deref() {
|
||||
match CString::new(b.str().to_string()) {
|
||||
Ok(cstr) => FFIResult::ok(OwnedPtrString(cstr.into_raw())),
|
||||
Err(_) => FFIResult::err(PkmnError::InvalidCString.into()),
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use crate::ffi::ffi_handle::{FFIHandle, FromFFIHandle};
|
||||
use crate::ffi::{ffi_handle_arc_dyn_getter, FFIResult, NonOwnedPtrString, OwnedPtrString};
|
||||
use crate::static_data::{
|
||||
EffectParameter, MoveCategory, MoveData, MoveDataImpl, MoveTarget, SecondaryEffect, SecondaryEffectImpl,
|
||||
TypeIdentifier,
|
||||
MoveCategory, MoveData, MoveDataImpl, MoveTarget, Parameter, SecondaryEffect, SecondaryEffectImpl, TypeIdentifier,
|
||||
};
|
||||
use crate::StringKey;
|
||||
use anyhow::anyhow;
|
||||
|
@ -100,7 +99,7 @@ unsafe extern "C" fn move_data_has_flag(ptr: FFIHandle<Arc<dyn MoveData>>, flag:
|
|||
unsafe extern "C" fn secondary_effect_new(
|
||||
chance: f32,
|
||||
effect_name: NonOwnedPtrString,
|
||||
parameters: *mut FFIHandle<Arc<EffectParameter>>,
|
||||
parameters: *mut FFIHandle<Arc<Parameter>>,
|
||||
parameters_length: usize,
|
||||
) -> FFIHandle<Box<dyn SecondaryEffect>> {
|
||||
let parameter_slice = std::slice::from_raw_parts(parameters, parameters_length);
|
||||
|
@ -148,7 +147,7 @@ unsafe extern "C" fn secondary_effect_parameter_length(ptr: FFIHandle<Arc<dyn Se
|
|||
unsafe extern "C" fn secondary_effect_parameter_get(
|
||||
ptr: FFIHandle<Arc<dyn SecondaryEffect>>,
|
||||
index: usize,
|
||||
) -> FFIHandle<Arc<EffectParameter>> {
|
||||
) -> FFIHandle<Arc<Parameter>> {
|
||||
if let Some(v) = ptr.from_ffi_handle().parameters().get(index) {
|
||||
FFIHandle::get_handle(v.clone().into())
|
||||
} else {
|
||||
|
|
|
@ -50,8 +50,10 @@ unsafe extern "C" fn species_new(
|
|||
gender_rate,
|
||||
&growth_rate,
|
||||
capture_rate,
|
||||
120,
|
||||
default_form.clone(),
|
||||
flags_set,
|
||||
Vec::new(),
|
||||
));
|
||||
FFIResult::ok(FFIHandle::get_handle(a.into()))
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use wasmer::{FunctionEnv, FunctionEnvMut, Imports, StoreMut};
|
|||
|
||||
use crate::script_implementations::wasm::extern_ref::ExternRef;
|
||||
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
|
||||
use crate::static_data::EffectParameter;
|
||||
use crate::static_data::Parameter;
|
||||
use crate::StringKey;
|
||||
|
||||
/// Dynamic data registration
|
||||
|
@ -140,51 +140,39 @@ fn string_key_get_str(env: FunctionEnvMut<WebAssemblyEnv>, string_key: ExternRef
|
|||
}
|
||||
|
||||
/// Gets the type of an EffectParameter
|
||||
fn effect_parameter_get_type(
|
||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
parameter: ExternRef<EffectParameter>,
|
||||
) -> WasmResult<u8> {
|
||||
fn effect_parameter_get_type(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<Parameter>) -> WasmResult<u8> {
|
||||
let value = get_value_arc!(parameter, env);
|
||||
wasm_ok(match value.deref() {
|
||||
EffectParameter::Bool(_) => 1,
|
||||
EffectParameter::Int(_) => 2,
|
||||
EffectParameter::Float(_) => 3,
|
||||
EffectParameter::String(_) => 4,
|
||||
Parameter::Bool(_) => 1,
|
||||
Parameter::Int(_) => 2,
|
||||
Parameter::Float(_) => 3,
|
||||
Parameter::String(_) => 4,
|
||||
})
|
||||
}
|
||||
|
||||
/// Gets the inner bool data of an EffectParameter. Panics if it's not a bool.
|
||||
fn effect_parameter_as_bool(
|
||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
parameter: ExternRef<EffectParameter>,
|
||||
) -> WasmResult<u8> {
|
||||
fn effect_parameter_as_bool(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<Parameter>) -> WasmResult<u8> {
|
||||
let value = get_value_arc!(parameter, env);
|
||||
match value.deref() {
|
||||
EffectParameter::Bool(b) => wasm_ok(<u8 as From<bool>>::from(*b)),
|
||||
Parameter::Bool(b) => wasm_ok(<u8 as From<bool>>::from(*b)),
|
||||
_ => wasm_err::<u8>(anyhow!("Unexpected parameter type. Expected bool, got {}", value), &env),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the inner int data of an EffectParameter. Panics if it's not an int.
|
||||
fn effect_parameter_as_int(
|
||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
parameter: ExternRef<EffectParameter>,
|
||||
) -> WasmResult<i64> {
|
||||
fn effect_parameter_as_int(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<Parameter>) -> WasmResult<i64> {
|
||||
let value = get_value_arc!(parameter, env);
|
||||
match value.deref() {
|
||||
EffectParameter::Int(i) => wasm_ok(*i),
|
||||
Parameter::Int(i) => wasm_ok(*i),
|
||||
_ => wasm_err::<i64>(anyhow!("Unexpected parameter type. Expected int, got {}", value), &env),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the inner float data of an EffectParameter. Panics if it's not a float.
|
||||
fn effect_parameter_as_float(
|
||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
parameter: ExternRef<EffectParameter>,
|
||||
) -> WasmResult<f32> {
|
||||
fn effect_parameter_as_float(env: FunctionEnvMut<WebAssemblyEnv>, parameter: ExternRef<Parameter>) -> WasmResult<f32> {
|
||||
let value = get_value_arc!(parameter, env);
|
||||
match value.deref() {
|
||||
EffectParameter::Float(f) => wasm_ok(*f),
|
||||
Parameter::Float(f) => wasm_ok(*f),
|
||||
_ => wasm_err::<f32>(
|
||||
anyhow!("Unexpected parameter type. Expected float, got {}", value),
|
||||
&env,
|
||||
|
@ -195,11 +183,11 @@ fn effect_parameter_as_float(
|
|||
/// Gets the inner string data of an EffectParameter. Panics if it's not a string.
|
||||
fn effect_parameter_as_string(
|
||||
env: FunctionEnvMut<WebAssemblyEnv>,
|
||||
parameter: ExternRef<EffectParameter>,
|
||||
parameter: ExternRef<Parameter>,
|
||||
) -> WasmResult<ExternRef<StringKey>> {
|
||||
let value = get_value_arc!(parameter, env);
|
||||
match value.deref() {
|
||||
EffectParameter::String(s) => wasm_ok(ExternRef::<StringKey>::func_new(&env, s.clone().into())),
|
||||
Parameter::String(s) => wasm_ok(ExternRef::<StringKey>::func_new(&env, s.clone().into())),
|
||||
_ => wasm_err::<ExternRef<StringKey>>(
|
||||
anyhow!("Unexpected parameter type. Expected string, got {}", value),
|
||||
&env,
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::script_implementations::wasm::export_registry::FunctionEnvMut;
|
|||
use crate::script_implementations::wasm::export_registry::{register, try_wasm, wasm_ok, WasmResult};
|
||||
use crate::script_implementations::wasm::extern_ref::ExternRef;
|
||||
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnv;
|
||||
use crate::static_data::{Ability, EffectParameter};
|
||||
use crate::static_data::{Ability, Parameter};
|
||||
use crate::StringKey;
|
||||
|
||||
register! {
|
||||
|
@ -32,7 +32,7 @@ fn ability_get_parameters(
|
|||
let parameters = ability.parameters();
|
||||
let mut vec : Vec<u32> = Vec::with_capacity(parameters.len());
|
||||
for parameter in parameters {
|
||||
vec.push(ExternRef::<EffectParameter>::func_new(&env, parameter.into()).index() as u32);
|
||||
vec.push(ExternRef::<Parameter>::func_new(&env, parameter.into()).index() as u32);
|
||||
}
|
||||
let wasm_ptr = try_wasm!(env.data().data().copy_value_vec_to_wasm(&vec), env);
|
||||
let r: u64 = unsafe { std::mem::transmute((wasm_ptr, vec.len() as u32)) };
|
||||
|
|
|
@ -9,7 +9,7 @@ use std::sync::{Arc, Weak};
|
|||
pub(crate) enum WasmObject {
|
||||
// Static data
|
||||
StringKey(crate::StringKey),
|
||||
EffectParameter(Weak<crate::static_data::EffectParameter>),
|
||||
EffectParameter(Weak<crate::static_data::Parameter>),
|
||||
|
||||
MoveData(Weak<dyn crate::static_data::MoveData>),
|
||||
Species(Weak<dyn crate::static_data::Species>),
|
||||
|
@ -182,13 +182,13 @@ impl FromWasmObj for crate::StringKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&Arc<crate::static_data::EffectParameter>> for WasmObject {
|
||||
fn from(value: &Arc<crate::static_data::EffectParameter>) -> Self {
|
||||
impl From<&Arc<crate::static_data::Parameter>> for WasmObject {
|
||||
fn from(value: &Arc<crate::static_data::Parameter>) -> Self {
|
||||
Self::EffectParameter(Arc::downgrade(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl_from_wasm_obj!(EffectParameter, Arc<crate::static_data::EffectParameter>);
|
||||
impl_from_wasm_obj!(EffectParameter, Arc<crate::static_data::Parameter>);
|
||||
|
||||
impl From<&Arc<dyn crate::static_data::MoveData>> for WasmObject {
|
||||
fn from(value: &Arc<dyn crate::static_data::MoveData>) -> Self {
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::dynamic_data::{ItemScript, Pokemon};
|
|||
use crate::script_implementations::wasm::export_registry::WasmVoidResultExtension;
|
||||
use crate::script_implementations::wasm::extern_ref::ExternRef;
|
||||
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData;
|
||||
use crate::static_data::EffectParameter;
|
||||
use crate::static_data::Parameter;
|
||||
use crate::StringKey;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -64,12 +64,12 @@ macro_rules! ex_ref {
|
|||
}
|
||||
|
||||
impl ItemScript for WebAssemblyItemScript {
|
||||
fn on_initialize(&self, pars: Vec<Arc<EffectParameter>>) -> anyhow_ext::Result<()> {
|
||||
fn on_initialize(&self, pars: Vec<Arc<Parameter>>) -> anyhow_ext::Result<()> {
|
||||
let env = &self.environment;
|
||||
if let Some(func) = env.script_function_cache().item_on_initialize(env) {
|
||||
let pars = pars
|
||||
.into_iter()
|
||||
.map(|p| ExternRef::<EffectParameter>::new(env, (&p).into()).index() as u32)
|
||||
.map(|p| ExternRef::<Parameter>::new(env, (&p).into()).index() as u32)
|
||||
.collect::<Vec<_>>();
|
||||
let wasm_ptr = env.copy_value_vec_to_wasm(&pars)?;
|
||||
let r: u64 = unsafe { std::mem::transmute((wasm_ptr, pars.len() as u32)) };
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::script_implementations::wasm::export_registry::WasmVoidResultExtensio
|
|||
use crate::script_implementations::wasm::extern_ref::ExternRef;
|
||||
use crate::script_implementations::wasm::script_resolver::WebAssemblyEnvironmentData;
|
||||
use crate::script_implementations::wasm::WebAssemblyScriptCapabilities;
|
||||
use crate::static_data::{EffectParameter, Item, Statistic, TypeIdentifier};
|
||||
use crate::static_data::{Item, Parameter, Statistic, TypeIdentifier};
|
||||
use crate::StringKey;
|
||||
|
||||
/// A WebAssemblyScript is there to implement the Script trait within WebAssemblyScript.
|
||||
|
@ -125,7 +125,7 @@ impl Script for WebAssemblyScript {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn on_initialize(&self, library: &Arc<dyn DynamicLibrary>, pars: Vec<Arc<EffectParameter>>) -> Result<()> {
|
||||
fn on_initialize(&self, library: &Arc<dyn DynamicLibrary>, pars: Vec<Arc<Parameter>>) -> Result<()> {
|
||||
if !self.has_capability(&WebAssemblyScriptCapabilities::Initialize) {
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ impl Script for WebAssemblyScript {
|
|||
if let Some(func) = env.script_function_cache().on_initialize(env) {
|
||||
let pars = pars
|
||||
.into_iter()
|
||||
.map(|p| ExternRef::<EffectParameter>::new(env, (&p).into()).index() as u32)
|
||||
.map(|p| ExternRef::<Parameter>::new(env, (&p).into()).index() as u32)
|
||||
.collect::<Vec<_>>();
|
||||
let wasm_ptr = env.copy_value_vec_to_wasm(&pars)?;
|
||||
let r: u64 = unsafe { std::mem::transmute((wasm_ptr, pars.len() as u32)) };
|
||||
|
|
|
@ -65,6 +65,7 @@ pub mod tests {
|
|||
0.5,
|
||||
&"test_growthrate".into(),
|
||||
0,
|
||||
120,
|
||||
Arc::new(FormImpl::new(
|
||||
&"default".into(),
|
||||
0.0,
|
||||
|
@ -78,6 +79,7 @@ pub mod tests {
|
|||
HashSet::new(),
|
||||
)),
|
||||
HashSet::new(),
|
||||
Vec::new(),
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ mod time_of_day;
|
|||
/// A parameter for an effect. This is basically a simple way to dynamically store multiple different
|
||||
/// primitives on data.
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub enum EffectParameter {
|
||||
pub enum Parameter {
|
||||
/// A boolean value.
|
||||
Bool(bool),
|
||||
/// An integer value. Stored as a 64 bit int to deal with potentially large numbers.
|
||||
|
@ -70,37 +70,37 @@ pub enum EffectParameter {
|
|||
String(StringKey),
|
||||
}
|
||||
|
||||
impl From<bool> for EffectParameter {
|
||||
impl From<bool> for Parameter {
|
||||
fn from(b: bool) -> Self {
|
||||
EffectParameter::Bool(b)
|
||||
Parameter::Bool(b)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for EffectParameter {
|
||||
impl From<i64> for Parameter {
|
||||
fn from(i: i64) -> Self {
|
||||
EffectParameter::Int(i)
|
||||
Parameter::Int(i)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for EffectParameter {
|
||||
impl From<f32> for Parameter {
|
||||
fn from(f: f32) -> Self {
|
||||
EffectParameter::Float(f)
|
||||
Parameter::Float(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StringKey> for EffectParameter {
|
||||
impl From<StringKey> for Parameter {
|
||||
fn from(s: StringKey) -> Self {
|
||||
EffectParameter::String(s)
|
||||
Parameter::String(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for EffectParameter {
|
||||
impl Display for Parameter {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
EffectParameter::Bool(v) => f.write_fmt(format_args!("EffectParameter::Bool({v})")),
|
||||
EffectParameter::Int(v) => f.write_fmt(format_args!("EffectParameter::Int({v})")),
|
||||
EffectParameter::Float(v) => f.write_fmt(format_args!("EffectParameter::Float({v})")),
|
||||
EffectParameter::String(v) => f.write_fmt(format_args!("EffectParameter::String({v})")),
|
||||
Parameter::Bool(v) => f.write_fmt(format_args!("EffectParameter::Bool({v})")),
|
||||
Parameter::Int(v) => f.write_fmt(format_args!("EffectParameter::Int({v})")),
|
||||
Parameter::Float(v) => f.write_fmt(format_args!("EffectParameter::Float({v})")),
|
||||
Parameter::String(v) => f.write_fmt(format_args!("EffectParameter::String({v})")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::static_data::EffectParameter;
|
||||
use crate::static_data::Parameter;
|
||||
use crate::StringKey;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
@ -10,7 +10,7 @@ pub trait SecondaryEffect: Debug {
|
|||
/// The name of the effect.
|
||||
fn effect_name(&self) -> &StringKey;
|
||||
/// A list of parameters for the effect.
|
||||
fn parameters(&self) -> &Vec<Arc<EffectParameter>>;
|
||||
fn parameters(&self) -> &Vec<Arc<Parameter>>;
|
||||
}
|
||||
|
||||
/// A secondary effect is an effect on a move that happens after it hits.
|
||||
|
@ -21,12 +21,12 @@ pub struct SecondaryEffectImpl {
|
|||
/// The name of the effect.
|
||||
effect_name: StringKey,
|
||||
/// A list of parameters for the effect.
|
||||
parameters: Vec<Arc<EffectParameter>>,
|
||||
parameters: Vec<Arc<Parameter>>,
|
||||
}
|
||||
|
||||
impl SecondaryEffectImpl {
|
||||
/// Instantiates a new Secondary Effect.
|
||||
pub fn new(chance: f32, effect_name: StringKey, parameters: Vec<Arc<EffectParameter>>) -> Self {
|
||||
pub fn new(chance: f32, effect_name: StringKey, parameters: Vec<Arc<Parameter>>) -> Self {
|
||||
Self {
|
||||
chance,
|
||||
effect_name,
|
||||
|
@ -45,7 +45,7 @@ impl SecondaryEffect for SecondaryEffectImpl {
|
|||
&self.effect_name
|
||||
}
|
||||
/// A list of parameters for the effect.
|
||||
fn parameters(&self) -> &Vec<Arc<EffectParameter>> {
|
||||
fn parameters(&self) -> &Vec<Arc<Parameter>> {
|
||||
&self.parameters
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ pub(crate) mod tests {
|
|||
impl SecondaryEffect for SecondaryEffect {
|
||||
fn chance(&self) -> f32;
|
||||
fn effect_name(&self) -> &StringKey;
|
||||
fn parameters(&self) -> &Vec<Arc<EffectParameter>>;
|
||||
fn parameters(&self) -> &Vec<Arc<Parameter >>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::static_data::EffectParameter;
|
||||
use crate::static_data::Parameter;
|
||||
use crate::StringKey;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
@ -10,7 +10,7 @@ pub trait Ability: Debug {
|
|||
/// The name of the script effect of the ability.
|
||||
fn effect(&self) -> &StringKey;
|
||||
/// The parameters for the script effect of the ability.
|
||||
fn parameters(&self) -> &Vec<Arc<EffectParameter>>;
|
||||
fn parameters(&self) -> &Vec<Arc<Parameter>>;
|
||||
}
|
||||
|
||||
/// An ability is a passive effect in battle that is attached to a Pokemon.
|
||||
|
@ -21,12 +21,12 @@ pub struct AbilityImpl {
|
|||
/// The name of the script effect of the ability.
|
||||
effect: StringKey,
|
||||
/// The parameters for the script effect of the ability.
|
||||
parameters: Vec<Arc<EffectParameter>>,
|
||||
parameters: Vec<Arc<Parameter>>,
|
||||
}
|
||||
|
||||
impl AbilityImpl {
|
||||
/// Instantiates a new ability.
|
||||
pub fn new(name: &StringKey, effect: &StringKey, parameters: Vec<Arc<EffectParameter>>) -> Self {
|
||||
pub fn new(name: &StringKey, effect: &StringKey, parameters: Vec<Arc<Parameter>>) -> Self {
|
||||
Self {
|
||||
name: name.clone(),
|
||||
effect: effect.clone(),
|
||||
|
@ -45,7 +45,7 @@ impl Ability for AbilityImpl {
|
|||
&self.effect
|
||||
}
|
||||
/// The parameters for the script effect of the ability.
|
||||
fn parameters(&self) -> &Vec<Arc<EffectParameter>> {
|
||||
fn parameters(&self) -> &Vec<Arc<Parameter>> {
|
||||
&self.parameters
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ pub(crate) mod tests {
|
|||
impl Ability for Ability {
|
||||
fn name(&self) -> &StringKey;
|
||||
fn effect(&self) -> &StringKey;
|
||||
fn parameters(&self) -> &Vec<Arc<EffectParameter>>;
|
||||
fn parameters(&self) -> &Vec<Arc<Parameter >>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
use crate::defines::LevelInt;
|
||||
use crate::static_data::{Gender, Parameter};
|
||||
use crate::StringKey;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// The different ways a Pokemon can evolve.
|
||||
#[derive(Debug)]
|
||||
pub enum EvolutionMethod {
|
||||
/// Evolves when a certain level is reached.
|
||||
Level {
|
||||
/// The level at which the Pokemon evolves.
|
||||
level: LevelInt,
|
||||
},
|
||||
/// Evolves when a certain level is reached, and the Pokemon is a specific gender.
|
||||
LevelGender {
|
||||
/// The level at which the Pokemon evolves.
|
||||
level: LevelInt,
|
||||
/// The gender the Pokemon needs to be.
|
||||
gender: Gender,
|
||||
},
|
||||
/// Evolves when an item is used.
|
||||
Item {
|
||||
/// The item that needs to be used.
|
||||
item: StringKey,
|
||||
},
|
||||
/// Evolves when an item is used, and the Pokemon is a specific gender.
|
||||
ItemGender {
|
||||
/// The item that needs to be used.
|
||||
item: StringKey,
|
||||
/// The gender the Pokemon needs to be.
|
||||
gender: Gender,
|
||||
},
|
||||
/// Evolves if an item is held.
|
||||
HoldItem {
|
||||
/// The item that needs to be held.
|
||||
item: StringKey,
|
||||
},
|
||||
/// Evolves if a held item is held, and it's day.
|
||||
DayHoldItem {
|
||||
/// The item that needs to be held.
|
||||
item: StringKey,
|
||||
},
|
||||
/// Evolves if a held item is held, and it's night.
|
||||
NightHoldItem {
|
||||
/// The item that needs to be held.
|
||||
item: StringKey,
|
||||
},
|
||||
/// Evolves if the Pokemon knows a certain move.
|
||||
HasMove {
|
||||
/// The move that needs to be known.
|
||||
move_name: StringKey,
|
||||
},
|
||||
/// Evolves when above a certain happiness level.
|
||||
Happiness {
|
||||
/// The happiness level that needs to be reached.
|
||||
happiness: u8,
|
||||
},
|
||||
/// Evolves when above a certain happiness level, and it's day.
|
||||
HappinessDay {
|
||||
/// The happiness level that needs to be reached.
|
||||
happiness: u8,
|
||||
},
|
||||
/// Evolves when above a certain happiness level, and it's night.
|
||||
HappinessNight {
|
||||
/// The happiness level that needs to be reached.
|
||||
happiness: u8,
|
||||
},
|
||||
/// Evolves when traded.
|
||||
Trade,
|
||||
/// Evolves when traded with a certain species.
|
||||
TradeSpecies {
|
||||
/// The species that needs to be traded with.
|
||||
species: StringKey,
|
||||
},
|
||||
/// Evolves when traded while it's holding a certain item.
|
||||
TradeItem {
|
||||
/// The item that needs to be held.
|
||||
item: StringKey,
|
||||
},
|
||||
/// Evolves in a certain location.
|
||||
Location {
|
||||
/// The location the Pokemon needs to be in.
|
||||
location: StringKey,
|
||||
},
|
||||
/// A custom evolution method, implemented by the user.
|
||||
Custom {
|
||||
/// The name of the custom evolution method.
|
||||
name: StringKey,
|
||||
/// The parameters of the custom evolution method.
|
||||
params: Vec<Arc<Parameter>>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Data about how and into which Pokemon a species can evolve.
|
||||
pub struct EvolutionData {
|
||||
/// The method of evolution.
|
||||
method: EvolutionMethod,
|
||||
/// The Pokemon the species evolves into.
|
||||
to: StringKey,
|
||||
}
|
||||
|
||||
impl EvolutionData {
|
||||
/// Creates a new evolution data instance.
|
||||
pub fn new(method: EvolutionMethod, to: StringKey) -> Self {
|
||||
Self { method, to }
|
||||
}
|
||||
|
||||
/// Returns the method of evolution.
|
||||
pub fn method(&self) -> &EvolutionMethod {
|
||||
&self.method
|
||||
}
|
||||
|
||||
/// Returns the Pokemon the species evolves into.
|
||||
pub fn to(&self) -> &StringKey {
|
||||
&self.to
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
#[doc(inline)]
|
||||
pub use ability::*;
|
||||
#[doc(inline)]
|
||||
pub use evolution_data::*;
|
||||
#[doc(inline)]
|
||||
pub use form::*;
|
||||
#[doc(inline)]
|
||||
pub use gender::*;
|
||||
|
@ -19,6 +21,8 @@ pub(crate) mod tests {
|
|||
|
||||
/// An ability is a passive effect in battle that is attached to a Pokemon.
|
||||
mod ability;
|
||||
/// Data regarding into which Pokemon a species can evolve.
|
||||
mod evolution_data;
|
||||
/// A form is a variant of a specific species. A species always has at least one form, but can have
|
||||
/// many more.
|
||||
mod form;
|
||||
|
|
|
@ -6,6 +6,7 @@ use hashbrown::{HashMap, HashSet};
|
|||
use parking_lot::lock_api::RwLockReadGuard;
|
||||
use parking_lot::{RawRwLock, RwLock};
|
||||
|
||||
use crate::static_data::species_data::evolution_data::EvolutionData;
|
||||
use crate::static_data::Form;
|
||||
use crate::static_data::Gender;
|
||||
use crate::Random;
|
||||
|
@ -24,6 +25,8 @@ pub trait Species: Debug {
|
|||
/// How hard it is to capture a Pokemon. 255 means this will be always caught, 0 means this is
|
||||
/// uncatchable.
|
||||
fn capture_rate(&self) -> u8;
|
||||
/// The base happiness of the Pokemon.
|
||||
fn base_happiness(&self) -> u8;
|
||||
/// The forms that belong to this Pokemon.
|
||||
fn forms(&self) -> RwLockReadGuard<'_, RawRwLock, HashMap<StringKey, Arc<dyn Form>>>;
|
||||
/// The arbitrary flags that can be set on a Pokemon for script use.
|
||||
|
@ -42,6 +45,8 @@ pub trait Species: Debug {
|
|||
fn has_flag(&self, key: &StringKey) -> bool;
|
||||
/// Check whether the Pokemon has a specific flag set.
|
||||
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
|
||||
/// The data regarding into which Pokemons this species can evolve, and how.
|
||||
fn evolution_data(&self) -> &Vec<EvolutionData>;
|
||||
}
|
||||
|
||||
/// The data belonging to a Pokemon with certain characteristics.
|
||||
|
@ -58,10 +63,14 @@ pub struct SpeciesImpl {
|
|||
/// How hard it is to capture a Pokemon. 255 means this will be always caught, 0 means this is
|
||||
/// uncatchable.
|
||||
capture_rate: u8,
|
||||
/// The base happiness of the Pokemon.
|
||||
base_happiness: u8,
|
||||
/// The forms that belong to this Pokemon.
|
||||
forms: RwLock<HashMap<StringKey, Arc<dyn Form>>>,
|
||||
/// The arbitrary flags that can be set on a Pokemon for script use.
|
||||
flags: HashSet<StringKey>,
|
||||
/// The data regarding into which Pokemons this species can evolve, and how.
|
||||
evolution_data: Vec<EvolutionData>,
|
||||
}
|
||||
|
||||
/// A cached String Key to get the default form.
|
||||
|
@ -80,8 +89,10 @@ impl SpeciesImpl {
|
|||
gender_rate: f32,
|
||||
growth_rate: &StringKey,
|
||||
capture_rate: u8,
|
||||
base_happiness: u8,
|
||||
default_form: Arc<dyn Form>,
|
||||
flags: HashSet<StringKey>,
|
||||
evolution_data: Vec<EvolutionData>,
|
||||
) -> Self {
|
||||
let mut forms = HashMap::with_capacity(1);
|
||||
forms.insert_unique_unchecked(get_default_key(), default_form);
|
||||
|
@ -91,8 +102,10 @@ impl SpeciesImpl {
|
|||
gender_rate,
|
||||
growth_rate: growth_rate.clone(),
|
||||
capture_rate,
|
||||
base_happiness,
|
||||
forms: RwLock::new(forms),
|
||||
flags,
|
||||
evolution_data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -119,6 +132,11 @@ impl Species for SpeciesImpl {
|
|||
fn capture_rate(&self) -> u8 {
|
||||
self.capture_rate
|
||||
}
|
||||
|
||||
fn base_happiness(&self) -> u8 {
|
||||
self.base_happiness
|
||||
}
|
||||
|
||||
/// The forms that belong to this Pokemon.
|
||||
fn forms(&self) -> RwLockReadGuard<'_, RawRwLock, HashMap<StringKey, Arc<dyn Form>>> {
|
||||
self.forms.read()
|
||||
|
@ -171,6 +189,10 @@ impl Species for SpeciesImpl {
|
|||
fn has_flag_by_hash(&self, key_hash: u32) -> bool {
|
||||
self.flags.contains::<u32>(&key_hash)
|
||||
}
|
||||
|
||||
fn evolution_data(&self) -> &Vec<EvolutionData> {
|
||||
&self.evolution_data
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -188,6 +210,7 @@ pub(crate) mod tests {
|
|||
fn gender_rate(&self) -> f32;
|
||||
fn growth_rate(&self) -> &StringKey;
|
||||
fn capture_rate(&self) -> u8;
|
||||
fn base_happiness(&self) -> u8;
|
||||
fn forms(&self) -> RwLockReadGuard<'_, RawRwLock, HashMap<StringKey, Arc<dyn Form>>>;
|
||||
fn flags(&self) -> &HashSet<StringKey>;
|
||||
fn add_form(&self, id: StringKey, form: Arc<dyn Form>);
|
||||
|
@ -197,6 +220,7 @@ pub(crate) mod tests {
|
|||
fn get_random_gender(&self, rand: &mut Random) -> Gender;
|
||||
fn has_flag(&self, key: &StringKey) -> bool;
|
||||
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
|
||||
fn evolution_data(&self) -> &Vec<EvolutionData>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,12 @@ use pkmn_lib::dynamic_data::Gen7MiscLibrary;
|
|||
use pkmn_lib::dynamic_data::{DynamicLibrary, DynamicLibraryImpl};
|
||||
use pkmn_lib::dynamic_data::{Gen7BattleStatCalculator, ScriptResolver};
|
||||
use pkmn_lib::static_data::{
|
||||
AbilityImpl, AbilityLibrary, AbilityLibraryImpl, BattleItemCategory, DataLibrary, EffectParameter, Form, FormImpl,
|
||||
GrowthRateLibrary, GrowthRateLibraryImpl, ItemImpl, ItemLibrary, ItemLibraryImpl, LearnableMoves,
|
||||
LearnableMovesImpl, LibrarySettingsImpl, LookupGrowthRate, MoveDataImpl, MoveLibrary, MoveLibraryImpl, NatureImpl,
|
||||
NatureLibrary, NatureLibraryImpl, SecondaryEffect, SecondaryEffectImpl, SpeciesImpl, SpeciesLibrary,
|
||||
SpeciesLibraryImpl, StaticDataImpl, StaticStatisticSet, Statistic, TimeOfDay, TypeLibrary, TypeLibraryImpl,
|
||||
AbilityImpl, AbilityLibrary, AbilityLibraryImpl, BattleItemCategory, DataLibrary, EvolutionData, EvolutionMethod,
|
||||
Form, FormImpl, Gender, GrowthRateLibrary, GrowthRateLibraryImpl, ItemImpl, ItemLibrary, ItemLibraryImpl,
|
||||
LearnableMoves, LearnableMovesImpl, LibrarySettingsImpl, LookupGrowthRate, MoveDataImpl, MoveLibrary,
|
||||
MoveLibraryImpl, NatureImpl, NatureLibrary, NatureLibraryImpl, Parameter, SecondaryEffect, SecondaryEffectImpl,
|
||||
SpeciesImpl, SpeciesLibrary, SpeciesLibraryImpl, StaticDataImpl, StaticStatisticSet, Statistic, TimeOfDay,
|
||||
TypeLibrary, TypeLibraryImpl,
|
||||
};
|
||||
use pkmn_lib::StringKey;
|
||||
|
||||
|
@ -225,7 +226,7 @@ pub fn load_abilities(path: &String) -> Arc<dyn AbilityLibrary> {
|
|||
let mut parameters = Vec::new();
|
||||
if let Some(p) = value.get("parameters") {
|
||||
for par in p.as_array().unwrap() {
|
||||
parameters.push(parse_effect_parameter(par));
|
||||
parameters.push(parse_parameter(par));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,7 +262,7 @@ pub fn load_moves(path: &String, types: &Arc<dyn TypeLibrary>) -> Arc<dyn MoveLi
|
|||
if let Some(pars) = v.get("parameters") {
|
||||
let pars = pars.as_array().unwrap();
|
||||
for par in pars {
|
||||
parameters.push(parse_effect_parameter(par));
|
||||
parameters.push(parse_parameter(par));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -321,7 +322,7 @@ pub fn load_species(
|
|||
let id = value.get("id").unwrap().as_i64().unwrap();
|
||||
let gender_rate = value.get("genderRatio").unwrap().as_f64().unwrap();
|
||||
let growth_rate_name = value.get("growthRate").unwrap().as_str().unwrap().into();
|
||||
let _base_happiness = value.get("baseHappiness").unwrap().as_i64().unwrap();
|
||||
let base_happiness = value.get("baseHappiness").unwrap().as_i64().unwrap();
|
||||
let catch_rate = value.get("catchRate").unwrap().as_i64().unwrap();
|
||||
let _color = value.get("color").unwrap().as_str().unwrap();
|
||||
// let egg_groups = value.get("eggGroups").unwrap()
|
||||
|
@ -332,7 +333,11 @@ pub fn load_species(
|
|||
// .collect();
|
||||
let _egg_cycle = value.get("eggCycles").unwrap().as_i64().unwrap();
|
||||
// TODO: tags
|
||||
// TODO: evolutions
|
||||
let evolutions = if let Some(evolutions) = value.get("evolutions") {
|
||||
evolutions.as_array().unwrap().iter().map(parse_evolution).collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let forms = value.get("formes").unwrap().as_object().unwrap();
|
||||
let default_form_value = forms.get("default").unwrap();
|
||||
|
@ -344,14 +349,108 @@ pub fn load_species(
|
|||
gender_rate as f32,
|
||||
&growth_rate_name,
|
||||
catch_rate as u8,
|
||||
base_happiness as u8,
|
||||
default_form,
|
||||
Default::default(),
|
||||
evolutions,
|
||||
);
|
||||
species_library.add(&name, Arc::new(species));
|
||||
}
|
||||
Arc::new(species_library)
|
||||
}
|
||||
|
||||
fn parse_evolution(value: &Value) -> EvolutionData {
|
||||
let species = StringKey::new(value.get("species").unwrap().as_str().unwrap());
|
||||
let method = value.get("method").unwrap().as_str().unwrap();
|
||||
let method = match method {
|
||||
"level" => {
|
||||
let level = value.get("data").unwrap().as_i64().unwrap() as LevelInt;
|
||||
EvolutionMethod::Level { level }
|
||||
}
|
||||
"levelfemale" => {
|
||||
let level = value.get("data").unwrap().as_i64().unwrap() as LevelInt;
|
||||
EvolutionMethod::LevelGender {
|
||||
level,
|
||||
gender: Gender::Female,
|
||||
}
|
||||
}
|
||||
"levelmale" => {
|
||||
let level = value.get("data").unwrap().as_i64().unwrap() as LevelInt;
|
||||
EvolutionMethod::LevelGender {
|
||||
level,
|
||||
gender: Gender::Male,
|
||||
}
|
||||
}
|
||||
"happiness" => {
|
||||
let happiness = value.get("data").unwrap().as_i64().unwrap() as u8;
|
||||
EvolutionMethod::Happiness { happiness }
|
||||
}
|
||||
"happinessday" => {
|
||||
let happiness = value.get("data").unwrap().as_i64().unwrap() as u8;
|
||||
EvolutionMethod::HappinessDay { happiness }
|
||||
}
|
||||
"happinessnight" => {
|
||||
let happiness = value.get("data").unwrap().as_i64().unwrap() as u8;
|
||||
EvolutionMethod::HappinessNight { happiness }
|
||||
}
|
||||
"item" => {
|
||||
let item = StringKey::new(value.get("data").unwrap().as_str().unwrap());
|
||||
EvolutionMethod::Item { item }
|
||||
}
|
||||
"itemmale" => {
|
||||
let item = StringKey::new(value.get("data").unwrap().as_str().unwrap());
|
||||
EvolutionMethod::ItemGender {
|
||||
item,
|
||||
gender: Gender::Male,
|
||||
}
|
||||
}
|
||||
"itemfemale" => {
|
||||
let item = StringKey::new(value.get("data").unwrap().as_str().unwrap());
|
||||
EvolutionMethod::ItemGender {
|
||||
item,
|
||||
gender: Gender::Female,
|
||||
}
|
||||
}
|
||||
"holditem" => {
|
||||
let item = StringKey::new(value.get("data").unwrap().as_str().unwrap());
|
||||
EvolutionMethod::HoldItem { item }
|
||||
}
|
||||
"dayholditem" => {
|
||||
let item = StringKey::new(value.get("data").unwrap().as_str().unwrap());
|
||||
EvolutionMethod::DayHoldItem { item }
|
||||
}
|
||||
"nightholditem" => {
|
||||
let item = StringKey::new(value.get("data").unwrap().as_str().unwrap());
|
||||
EvolutionMethod::NightHoldItem { item }
|
||||
}
|
||||
"hasmove" => {
|
||||
let move_name = StringKey::new(value.get("data").unwrap().as_str().unwrap());
|
||||
EvolutionMethod::HasMove { move_name }
|
||||
}
|
||||
"trade" => EvolutionMethod::Trade,
|
||||
"tradespecies" => {
|
||||
let species = StringKey::new(value.get("data").unwrap().as_str().unwrap());
|
||||
EvolutionMethod::TradeSpecies { species }
|
||||
}
|
||||
"tradeitem" => {
|
||||
let item = StringKey::new(value.get("data").unwrap().as_str().unwrap());
|
||||
EvolutionMethod::TradeItem { item }
|
||||
}
|
||||
"location" => {
|
||||
let location = StringKey::new(value.get("data").unwrap().as_str().unwrap());
|
||||
EvolutionMethod::Location { location }
|
||||
}
|
||||
"custom" => {
|
||||
let data = value.get("data").unwrap().as_array().unwrap();
|
||||
let name = StringKey::new(data[0].as_str().unwrap());
|
||||
let params = data[1..].iter().map(parse_parameter).collect();
|
||||
EvolutionMethod::Custom { name, params }
|
||||
}
|
||||
_ => panic!("Unknown evolution method: {}", method),
|
||||
};
|
||||
EvolutionData::new(method, species)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "wasm"))]
|
||||
fn load_script_resolver(path: &String) -> Arc<dyn ScriptResolver> {
|
||||
Arc::new(EmptyScriptResolver::default())
|
||||
|
@ -471,7 +570,7 @@ fn parse_moves(value: &Value, move_library: &Arc<dyn MoveLibrary>) -> Arc<dyn Le
|
|||
Arc::new(moves)
|
||||
}
|
||||
|
||||
fn parse_effect_parameter(value: &Value) -> Arc<EffectParameter> {
|
||||
fn parse_parameter(value: &Value) -> Arc<Parameter> {
|
||||
Arc::new(match value {
|
||||
Value::Null => {
|
||||
panic!("Unexpected type")
|
||||
|
|
|
@ -8390,8 +8390,16 @@
|
|||
}
|
||||
},
|
||||
"evolutions": [
|
||||
{ "species": "wormadam", "method": "levelfemale", "data": "20" },
|
||||
{ "species": "mothim", "method": "levelmale", "data": "20" }
|
||||
{
|
||||
"species": "wormadam",
|
||||
"method": "levelfemale",
|
||||
"data": 20
|
||||
},
|
||||
{
|
||||
"species": "mothim",
|
||||
"method": "levelmale",
|
||||
"data": 20
|
||||
}
|
||||
]
|
||||
},
|
||||
"butterfree": {
|
||||
|
@ -12710,7 +12718,11 @@
|
|||
}
|
||||
},
|
||||
"evolutions": [
|
||||
{ "species": "vespiquen", "method": "levelfemale", "data": "21" }
|
||||
{
|
||||
"species": "vespiquen",
|
||||
"method": "levelfemale",
|
||||
"data": 21
|
||||
}
|
||||
]
|
||||
},
|
||||
"combusken": {
|
||||
|
|
Loading…
Reference in New Issue