use std::sync::{Arc, LazyLock}; use hashbrown::{HashMap, HashSet}; use crate::static_data::Form; use crate::static_data::Gender; use crate::Random; use crate::StringKey; /// The data belonging to a Pokemon with certain characteristics. #[derive(Debug)] #[cfg_attr(feature = "wasm", derive(unique_type_id_derive::UniqueTypeId))] pub struct Species { /// The national dex identifier of the Pokemon. id: u16, /// The name of the Pokemon. name: StringKey, /// The chance between 0.0 and 1.0 that a Pokemon is female. gender_rate: f32, /// How much experience is required for a level. growth_rate: StringKey, /// How hard it is to capture a Pokemon. 255 means this will be always caught, 0 means this is /// uncatchable. capture_rate: u8, /// The forms that belong to this Pokemon. forms: HashMap>, /// The arbitrary flags that can be set on a Pokemon for script use. flags: HashSet, } /// A cached String Key to get the default form. static DEFAULT_KEY: LazyLock = LazyLock::new(|| StringKey::new("default")); /// Gets the StringKey for "default". Initialises it if it does not exist. fn get_default_key() -> StringKey { DEFAULT_KEY.clone() } impl Species { /// Creates a new species. pub fn new( id: u16, name: &StringKey, gender_rate: f32, growth_rate: &StringKey, capture_rate: u8, default_form: Form, flags: HashSet, ) -> Species { let mut forms = HashMap::with_capacity(1); forms.insert_unique_unchecked(get_default_key(), Arc::new(default_form)); Species { id, name: name.clone(), gender_rate, growth_rate: growth_rate.clone(), capture_rate, forms, flags, } } /// The national dex identifier of the Pokemon. pub fn id(&self) -> u16 { self.id } /// The name of the Pokemon. pub fn name(&self) -> &StringKey { &self.name } /// The chance between 0.0 and 1.0 that a Pokemon is female. pub fn gender_rate(&self) -> f32 { self.gender_rate } /// How much experience is required for a level. pub fn growth_rate(&self) -> &StringKey { &self.growth_rate } /// How hard it is to capture a Pokemon. 255 means this will be always caught, 0 means this is /// uncatchable. pub fn capture_rate(&self) -> u8 { self.capture_rate } /// The forms that belong to this Pokemon. pub fn forms(&self) -> &HashMap> { &self.forms } /// The arbitrary flags that can be set on a Pokemon for script use. pub fn flags(&self) -> &HashSet { &self.flags } /// Adds a new form to the species. pub fn add_form(&mut self, id: StringKey, form: Form) { self.forms.insert(id, Arc::new(form)); } /// Gets a form by name. pub fn get_form(&self, id: &StringKey) -> Option<&Arc
> { self.forms.get(id) } /// Gets the form the Pokemon will have by default, if no other form is specified. pub fn get_default_form(&self) -> &Arc { self.forms.get(&get_default_key()).unwrap() } /// Gets a random gender. pub fn get_random_gender(&self, rand: &mut Random) -> Gender { if self.gender_rate < 0.0 { Gender::Genderless } else if rand.get_float() >= self.gender_rate { Gender::Female } else { Gender::Male } } /// Check whether the Pokemon has a specific flag set. pub fn has_flag(&self, key: &StringKey) -> bool { self.flags.contains(key) } }