using PkmnLib.Dynamic.Libraries; using PkmnLib.Dynamic.Models; using PkmnLib.Static; namespace PkmnLib.Plugin.Gen7.Libraries; public class Gen7BattleStatCalculator : IBattleStatCalculator { /// public void CalculateFlatStats(IPokemon pokemon, StatisticSet stats) { stats.SetStatistic(Statistic.Hp, CalculateHealthStat(pokemon)); stats.SetStatistic(Statistic.Attack, CalculateNormalStat(pokemon, Statistic.Attack)); stats.SetStatistic(Statistic.Defense, CalculateNormalStat(pokemon, Statistic.Defense)); stats.SetStatistic(Statistic.SpecialAttack, CalculateNormalStat(pokemon, Statistic.SpecialAttack)); stats.SetStatistic(Statistic.SpecialDefense, CalculateNormalStat(pokemon, Statistic.SpecialDefense)); stats.SetStatistic(Statistic.Speed, CalculateNormalStat(pokemon, Statistic.Speed)); } /// public uint CalculateFlatStat(IPokemon pokemon, Statistic stat) { return stat switch { Statistic.Hp => CalculateHealthStat(pokemon), _ => CalculateNormalStat(pokemon, stat), }; } /// public void CalculateBoostedStats(IPokemon pokemon, StatisticSet stats) { stats.SetStatistic(Statistic.Hp, CalculateBoostedStat(pokemon, Statistic.Hp)); stats.SetStatistic(Statistic.Attack, CalculateBoostedStat(pokemon, Statistic.Attack)); stats.SetStatistic(Statistic.Defense, CalculateBoostedStat(pokemon, Statistic.Defense)); stats.SetStatistic(Statistic.SpecialAttack, CalculateBoostedStat(pokemon, Statistic.SpecialAttack)); stats.SetStatistic(Statistic.SpecialDefense, CalculateBoostedStat(pokemon, Statistic.SpecialDefense)); stats.SetStatistic(Statistic.Speed, CalculateBoostedStat(pokemon, Statistic.Speed)); } /// public uint CalculateBoostedStat(IPokemon pokemon, Statistic stat) { var flatStat = CalculateFlatStat(pokemon, stat); var boostModifier = GetStatBoostModifier(pokemon, stat); var boostedStat = flatStat * boostModifier; if (boostedStat > uint.MaxValue) boostedStat = uint.MaxValue; return (uint)boostedStat; } private static uint CalculateHealthStat(IPokemon pokemon) { var baseValue = (ulong)pokemon.Form.BaseStats.Hp; var iv = (ulong)pokemon.IndividualValues.Hp; var ev = (ulong)pokemon.EffortValues.Hp; var level = (ulong)pokemon.Level; var health = (((2 * baseValue + iv + (ev / 4)) * level) / 100) + level + 10; if (health > uint.MaxValue) health = uint.MaxValue; return (uint)health; } private static uint CalculateNormalStat(IPokemon pokemon, Statistic statistic) { var baseValue = (ulong)pokemon.Form.BaseStats.GetStatistic(statistic); var iv = (ulong)pokemon.IndividualValues.GetStatistic(statistic); var ev = (ulong)pokemon.EffortValues.GetStatistic(statistic); var level = (ulong)pokemon.Level; var unmodified = (((2 * baseValue + iv + (ev / 4)) * level) / 100) + 5; var natureModifier = pokemon.Nature.GetStatModifier(statistic); var modified = (unmodified * natureModifier); if (modified > uint.MaxValue) modified = uint.MaxValue; return (uint)modified; } private static float GetStatBoostModifier(IPokemon pokemon, Statistic statistic) { var boost = pokemon.StatBoost.GetStatistic(statistic); return boost switch { -6 => 2.0f / 8.0f, -5 => 2.0f / 7.0f, -4 => 2.0f / 6.0f, -3 => 2.0f / 5.0f, -2 => 2.0f / 4.0f, -1 => 2.0f / 3.0f, 0 => 1.0f, 1 => 3.0f / 2.0f, 2 => 4.0f / 2.0f, 3 => 5.0f / 2.0f, 4 => 6.0f / 2.0f, 5 => 7.0f / 2.0f, 6 => 8.0f / 2.0f, _ => throw new System.ArgumentException("Stat boost was out of expected range of -6 to 6"), }; } }