Basic implementation of evolutions
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-07-29 12:57:52 +02:00
parent 3f91f80982
commit d8b8559c2e
25 changed files with 437 additions and 115 deletions

View File

@@ -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
}
}
}
}

View File

@@ -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;

View File

@@ -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)

View File

@@ -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(),

View File

@@ -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(())
}

View File

@@ -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,