infinite-fusion 0.2.0

A simple crate for reading Pokemon Infinite Fusion's data
Documentation
//! Module for the base stats for a pokemon
//! note: u8 is opt-in since species data contains a couple entries with stats over 255.
//! If you're already doing some work to manually skip that data then opting into u8 saves a few bytes thus pushing [`BaseStats`]'s size under 8 bytes.

use serde::{Deserialize, Serialize};

// could've type aliased on "BaseStat" but that just doesn't feel as clean since it would make the API look weird and complicated in rust-analyser
// does come with the consequence i need to mirror changes between them but oh well
// also i really wanted to try out cfg_select lol
cfg_select! {
    feature = "u8_stats" => {
        #[doc = "Base stats for a given pokemon"]
        #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Deserialize, Serialize)]
        pub struct BaseStats {
            #[serde(rename = "HP")]
            pub hp: u8,
            #[serde(rename = "ATTACK")]
            pub atk: u8,
            #[serde(rename = "DEFENSE")]
            pub def: u8,
            #[serde(rename = "SPECIAL_ATTACK")]
            pub spa: u8,
            #[serde(rename = "SPECIAL_DEFENSE")]
            pub spd: u8,
            #[serde(rename = "SPEED")]
            pub spe: u8,
        }

        impl BaseStats {
            pub fn hp(&self) -> u8 {
                self.hp
            }

            pub fn atk(&self) -> u8 {
                self.atk
            }

            pub fn def(&self) -> u8 {
                self.def
            }

            pub fn spa(&self) -> u8 {
                self.spa
            }

            pub fn spd(&self) -> u8 {
                self.spd
            }

            pub fn spe(&self) -> u8 {
                self.spe
            }

            pub fn bst(&self) -> u16 {
                self.hp as u16
                + self.atk as u16
                + self.def as u16
                + self.spa as u16
                + self.spd as u16
                + self.spe as u16
            }
        }

        fn fuse_calc(dominant: u8, other: u8) -> u8 {
            (((dominant as f32 * 2.0) / 3.0) + (other as f32 / 3.0)).floor() as u8
        }
    }
    _ => {
        #[doc = "Base stats for a given pokemon"]
        #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Deserialize, Serialize)]
        pub struct BaseStats {
            #[serde(rename = "HP")]
            pub hp: u16,
            #[serde(rename = "ATTACK")]
            pub atk: u16,
            #[serde(rename = "DEFENSE")]
            pub def: u16,
            #[serde(rename = "SPECIAL_ATTACK")]
            pub spa: u16,
            #[serde(rename = "SPECIAL_DEFENSE")]
            pub spd: u16,
            #[serde(rename = "SPEED")]
            pub spe: u16,
        }

        impl BaseStats {
            pub fn hp(&self) -> u16 {
                self.hp
            }

            pub fn atk(&self) -> u16 {
                self.atk
            }

            pub fn def(&self) -> u16 {
                self.def
            }

            pub fn spa(&self) -> u16 {
                self.spa
            }

            pub fn spd(&self) -> u16 {
                self.spd
            }

            pub fn spe(&self) -> u16 {
                self.spe
            }

            pub fn bst(&self) -> u16 {
                self.hp
                + self.atk
                + self.def
                + self.spa
                + self.spd
                + self.spe
            }
        }

        fn fuse_calc(dominant: u16, other: u16) -> u16 {
            (((dominant as f32 * 2.0) / 3.0) + (other as f32 / 3.0)).floor() as u16
        }
    }
}

impl BaseStats {
    /// Fuse two sets of base stats, taking self as the head and the other as the body
    pub fn fuse(&self, body: &Self) -> BaseStats {
        // Head dominant
        let hp = fuse_calc(self.hp, body.hp);
        let spd = fuse_calc(self.spd, body.spd);
        let spa = fuse_calc(self.spa, body.spa);

        // Body dominant
        let atk = fuse_calc(body.atk, self.atk);
        let def = fuse_calc(body.def, self.def);
        let spe = fuse_calc(body.spe, self.spe);
        BaseStats {
            hp,
            atk,
            def,
            spa,
            spd,
            spe,
        }
    }
}