PkmnLib_rs/src/dynamic_data/libraries/battle_stat_calculator.rs

117 lines
4.7 KiB
Rust
Executable File

use std::fmt::Debug;
use crate::dynamic_data::Pokemon;
use crate::static_data::Statistic;
use crate::static_data::StatisticSet;
/// A battle stat calculator is used to calculate stats for a Pokemon.
pub trait BattleStatCalculator: Debug {
/// Calculate all the flat stats of a Pokemon, disregarding stat boosts.
fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<u32>);
/// Calculate a single flat stat of a Pokemon, disregarding stat boost
fn calculate_flat_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32;
/// Calculate all the boosted stats of a Pokemon, including stat boosts.
fn calculate_boosted_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<u32>);
/// Calculate a single boosted stat of a Pokemon, including stat boosts.
fn calculate_boosted_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32;
}
/// A basic implementation of the Gen 7 stat calculator.
#[derive(Debug)]
pub struct Gen7BattleStatCalculator {}
impl Gen7BattleStatCalculator {
/// The calculation used for health points.
fn calculate_health_stat(&self, pokemon: &Pokemon) -> u32 {
let base = pokemon.form().get_base_stat(Statistic::HP) as u32;
let iv = pokemon.individual_values().hp() as u32;
let ev = pokemon.effort_values().hp() as u32;
let level = pokemon.level() as u32;
(((2 * base + iv + (ev / 4)) * level) / 100) + level + 10
}
/// The calculation used for all other stats
fn calculate_other_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 {
let base = pokemon.form().get_base_stat(stat) as u32;
let iv = pokemon.individual_values().get_stat(stat) as u32;
let ev = pokemon.effort_values().get_stat(stat) as u32;
let level = pokemon.level() as u32;
let unmodified = (((2 * base + iv + (ev / 4)) * level) / 100) + 5;
return (unmodified as f32 * pokemon.nature().get_stat_modifier(stat)) as u32;
}
/// This functions returns the modifier we need to do to a stat for a given stat boost.
fn get_stat_boost_modifier(&self, pokemon: &Pokemon, stat: Statistic) -> f32 {
let boost = pokemon.stat_boost(stat);
match boost {
-6 => 2.0 / 8.0,
-5 => 2.0 / 7.0,
-4 => 2.0 / 6.0,
-3 => 2.0 / 5.0,
-2 => 2.0 / 4.0,
-1 => 2.0 / 3.0,
0 => 1.0,
1 => 3.0 / 2.0,
2 => 4.0 / 2.0,
3 => 5.0 / 2.0,
4 => 6.0 / 2.0,
5 => 7.0 / 2.0,
6 => 8.0 / 2.0,
_ => panic!("Stat boost was out of expected range of -6 to 6"),
}
}
}
impl BattleStatCalculator for Gen7BattleStatCalculator {
fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<u32>) {
stats.set_stat(Statistic::HP, self.calculate_health_stat(pokemon));
stats.set_stat(Statistic::Attack, self.calculate_other_stat(pokemon, Statistic::Attack));
stats.set_stat(
Statistic::Defense,
self.calculate_other_stat(pokemon, Statistic::Defense),
);
stats.set_stat(
Statistic::SpecialAttack,
self.calculate_other_stat(pokemon, Statistic::SpecialAttack),
);
stats.set_stat(
Statistic::SpecialDefense,
self.calculate_other_stat(pokemon, Statistic::SpecialDefense),
);
stats.set_stat(Statistic::Speed, self.calculate_other_stat(pokemon, Statistic::Speed));
}
fn calculate_flat_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 {
if stat == Statistic::HP {
self.calculate_health_stat(pokemon)
} else {
self.calculate_other_stat(pokemon, stat)
}
}
fn calculate_boosted_stats(&self, pokemon: &Pokemon, stats: &StatisticSet<u32>) {
stats.set_stat(Statistic::HP, self.calculate_boosted_stat(pokemon, Statistic::HP));
stats.set_stat(
Statistic::Attack,
self.calculate_boosted_stat(pokemon, Statistic::Attack),
);
stats.set_stat(
Statistic::Defense,
self.calculate_boosted_stat(pokemon, Statistic::Defense),
);
stats.set_stat(
Statistic::SpecialAttack,
self.calculate_boosted_stat(pokemon, Statistic::SpecialAttack),
);
stats.set_stat(
Statistic::SpecialDefense,
self.calculate_boosted_stat(pokemon, Statistic::SpecialDefense),
);
stats.set_stat(Statistic::Speed, self.calculate_boosted_stat(pokemon, Statistic::Speed));
}
fn calculate_boosted_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 {
(self.calculate_flat_stat(pokemon, stat) as f32 * self.get_stat_boost_modifier(pokemon, stat)) as u32
}
}