diff --git a/src/ffi/dynamic_data/libraries/damage_library.rs b/src/ffi/dynamic_data/libraries/damage_library.rs index 592e80c..ac26f52 100644 --- a/src/ffi/dynamic_data/libraries/damage_library.rs +++ b/src/ffi/dynamic_data/libraries/damage_library.rs @@ -5,8 +5,8 @@ use std::ptr::drop_in_place; /// Creates a new generation 7 damage library. `has_randomness` defines whether a random damage /// modifier (0.85x - 1.00x) is applied to the calculated damage. #[no_mangle] -extern "C" fn gen_7_damage_library_new(randomness: u8) -> IdentifiablePointer> { - let v: Box = Box::new(Gen7DamageLibrary::new(randomness == 1)); +extern "C" fn gen_7_damage_library_new(has_randomness: u8) -> IdentifiablePointer> { + let v: Box = Box::new(Gen7DamageLibrary::new(has_randomness == 1)); let id = v.value_identifier(); let ptr = Box::into_raw(Box::new(v)); IdentifiablePointer::new(ptr, id) diff --git a/src/ffi/static_data/libraries/library_settings.rs b/src/ffi/static_data/libraries/library_settings.rs index a5b7b8d..bb2bf2e 100644 --- a/src/ffi/static_data/libraries/library_settings.rs +++ b/src/ffi/static_data/libraries/library_settings.rs @@ -4,9 +4,16 @@ use crate::static_data::{LibrarySettings, LibrarySettingsImpl}; use std::ptr::drop_in_place; /// Creates a new settings library. +/// - `maximum_level` is the highest level a Pokemon can be. +/// - `shiny_rate` is the chance of a Pokemon being shiny, as the denominator of a fraction, where +/// the nominator is 1. For example, if this is 1000, then the chance of a Pokemon being shiny is +/// 1/1000. #[no_mangle] -extern "C" fn library_settings_new(max_level: LevelInt) -> IdentifiablePointer> { - let b: Box = Box::new(LibrarySettingsImpl::new(max_level)); +extern "C" fn library_settings_new( + max_level: LevelInt, + shiny_rate: u32, +) -> IdentifiablePointer> { + let b: Box = Box::new(LibrarySettingsImpl::new(max_level, shiny_rate)); b.into() } @@ -21,3 +28,10 @@ unsafe extern "C" fn library_settings_drop(ptr: OwnedPtr>) -> LevelInt { ptr.as_ref().maximum_level() } + +/// The chance of a Pokemon being shiny, as the denominator of a fraction, where the nominator +/// is 1. For example, if this is 1000, then the chance of a Pokemon being shiny is 1/1000. +#[no_mangle] +extern "C" fn library_settings_shiny_rate(ptr: ExternPointer>) -> u32 { + ptr.as_ref().shiny_rate() +} diff --git a/src/ffi/static_data/libraries/nature_library.rs b/src/ffi/static_data/libraries/nature_library.rs index 063f7ab..982f949 100644 --- a/src/ffi/static_data/libraries/nature_library.rs +++ b/src/ffi/static_data/libraries/nature_library.rs @@ -1,5 +1,6 @@ use crate::ffi::{BorrowedPtr, ExternPointer, IdentifiablePointer, OwnedPtr}; use crate::static_data::{Nature, NatureLibrary, NatureLibraryImpl}; +use crate::Random; use std::ffi::{c_char, CStr, CString}; use std::ptr::drop_in_place; use std::sync::Arc; @@ -41,6 +42,16 @@ unsafe extern "C" fn nature_library_get_nature( } } +/// Gets a random nature. +#[no_mangle] +unsafe extern "C" fn nature_library_get_random_nature( + ptr: ExternPointer>, + seed: u64, +) -> IdentifiablePointer> { + let mut rand = Random::new(seed as u128); + ptr.as_ref().get_random_nature(&mut rand).into() +} + /// Finds a nature name by nature. #[no_mangle] unsafe extern "C" fn nature_library_get_nature_name( diff --git a/src/static_data/libraries/library_settings.rs b/src/static_data/libraries/library_settings.rs index 5526911..56f19c3 100755 --- a/src/static_data/libraries/library_settings.rs +++ b/src/static_data/libraries/library_settings.rs @@ -6,6 +6,10 @@ use std::fmt::Debug; pub trait LibrarySettings: Debug + ValueIdentifiable { /// The highest level a Pokemon can be. fn maximum_level(&self) -> LevelInt; + + /// The chance of a Pokemon being shiny, as the denominator of a fraction, where the nominator + /// is 1. For example, if this is 1000, then the chance of a Pokemon being shiny is 1/1000. + fn shiny_rate(&self) -> u32; } /// This library holds several misc settings for the library. @@ -15,23 +19,35 @@ pub struct LibrarySettingsImpl { identifier: ValueIdentifier, /// The highest level a Pokemon can be. maximum_level: LevelInt, + /// The chance of a Pokemon being shiny, as the denominator of a fraction, where the nominator + /// is 1. For example, if this is 1000, then the chance of a Pokemon being shiny is 1/1000. + shiny_rate: u32, } impl LibrarySettingsImpl { /// Creates a new settings library. - pub fn new(maximum_level: LevelInt) -> Self { + /// - `maximum_level` is the highest level a Pokemon can be. + /// - `shiny_rate` is the chance of a Pokemon being shiny, as the denominator of a fraction, where + /// the nominator is 1. For example, if this is 1000, then the chance of a Pokemon being shiny is + /// 1/1000. + pub fn new(maximum_level: LevelInt, shiny_rate: u32) -> Self { + assert!(shiny_rate >= 1); + assert!(maximum_level >= 1); Self { identifier: Default::default(), maximum_level, + shiny_rate, } } } impl LibrarySettings for LibrarySettingsImpl { - /// The highest level a Pokemon can be. fn maximum_level(&self) -> LevelInt { self.maximum_level } + fn shiny_rate(&self) -> u32 { + self.shiny_rate + } } impl ValueIdentifiable for LibrarySettingsImpl { diff --git a/src/static_data/libraries/nature_library.rs b/src/static_data/libraries/nature_library.rs index 158e65e..994f1f8 100644 --- a/src/static_data/libraries/nature_library.rs +++ b/src/static_data/libraries/nature_library.rs @@ -1,6 +1,6 @@ use crate::static_data::Nature; -use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; -use hashbrown::HashMap; +use crate::{Random, StringKey, ValueIdentifiable, ValueIdentifier}; +use indexmap::IndexMap; use std::fmt::Debug; use std::sync::Arc; @@ -10,6 +10,8 @@ pub trait NatureLibrary: Debug + ValueIdentifiable { fn load_nature(&mut self, name: StringKey, nature: Arc); /// Gets a nature by name. fn get_nature(&self, key: &StringKey) -> Option>; + /// Gets a random nature. + fn get_random_nature(&self, rand: &mut Random) -> Arc; /// Finds a nature name by nature. fn get_nature_name(&self, nature: &Arc) -> StringKey; } @@ -20,7 +22,7 @@ pub struct NatureLibraryImpl { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, /// The underlying data structure. - map: HashMap>, + map: IndexMap>, } impl NatureLibraryImpl { @@ -28,7 +30,7 @@ impl NatureLibraryImpl { pub fn new(capacity: usize) -> Self { Self { identifier: Default::default(), - map: HashMap::with_capacity(capacity), + map: IndexMap::with_capacity(capacity), } } } @@ -44,6 +46,11 @@ impl NatureLibrary for NatureLibraryImpl { self.map.get(key).cloned() } + fn get_random_nature(&self, rand: &mut Random) -> Arc { + let i = rand.get_between(0, self.map.len() as i32); + return self.map.get_index(i as usize).unwrap().1.clone(); + } + /// Finds a nature name by nature. fn get_nature_name(&self, nature: &Arc) -> StringKey { for kv in &self.map { @@ -87,6 +94,7 @@ pub mod tests { fn load_nature(&mut self, name: StringKey, nature: Arc); fn get_nature(&self, key: &StringKey) -> Option>; fn get_nature_name(&self, nature: &Arc) -> StringKey; + fn get_random_nature(&self, rand: &mut Random) -> Arc; } impl ValueIdentifiable for NatureLibrary { fn value_identifier(&self) -> ValueIdentifier{ diff --git a/src/static_data/libraries/static_data.rs b/src/static_data/libraries/static_data.rs index 79e3808..7c98076 100755 --- a/src/static_data/libraries/static_data.rs +++ b/src/static_data/libraries/static_data.rs @@ -199,7 +199,7 @@ pub mod test { pub fn build() -> StaticDataImpl { StaticDataImpl { identifier: Default::default(), - settings: Box::new(LibrarySettingsImpl::new(100)), + settings: Box::new(LibrarySettingsImpl::new(100, 100)), species: crate::static_data::libraries::species_library::tests::build(), moves: crate::static_data::libraries::move_library::tests::build(), items: crate::static_data::libraries::item_library::tests::build(), diff --git a/tests/common/library_loader.rs b/tests/common/library_loader.rs index d6c3b3d..bdba6f5 100755 --- a/tests/common/library_loader.rs +++ b/tests/common/library_loader.rs @@ -65,7 +65,7 @@ pub fn load_library() -> LoadResult { let species_load_time = t2 - t1; let data = StaticDataImpl::new( - Box::new(LibrarySettingsImpl::new(100)), + Box::new(LibrarySettingsImpl::new(100, 100)), species, moves, items,