uxie 0.6.3

Data fetching library for Pokemon Gen 4 romhacking - map headers, C parsing, and more
Documentation
use binrw::{BinRead, BinWrite};
use serde::{Deserialize, Serialize};

pub const EVOLUTIONS_PER_SPECIES: usize = 7;
pub const EVOLUTION_ENTRY_SIZE: usize = 6;
pub const EVOLUTION_FILE_SIZE: usize = EVOLUTIONS_PER_SPECIES * EVOLUTION_ENTRY_SIZE;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[repr(u16)]
pub enum EvolutionMethod {
    None = 0,
    Happiness = 1,
    HappinessDay = 2,
    HappinessNight = 3,
    LevelUp = 4,
    Trade = 5,
    TradeWithItem = 6,
    UseItem = 7,
    LevelUpAtkGtDef = 8,
    LevelUpAtkEqDef = 9,
    LevelUpDefGtAtk = 10,
    LevelUpPersonalityLow = 11,
    LevelUpPersonalityHigh = 12,
    LevelUpSpawnPokemon = 13,
    LevelUpSpawnEmptySlot = 14,
    Beauty = 15,
    UseItemMale = 16,
    UseItemFemale = 17,
    LevelUpWithItem = 18,
    LevelUpWithMoveType = 19,
    LevelUpWithPartyMember = 20,
    LevelUpMale = 21,
    LevelUpFemale = 22,
    LevelUpAtLocation = 23,
    LevelUpAtMtCoronet = 24,
    LevelUpNearMossRock = 25,
    LevelUpNearIceRock = 26,
    Unknown(u16),
}

impl From<u16> for EvolutionMethod {
    fn from(v: u16) -> Self {
        match v {
            0 => Self::None,
            1 => Self::Happiness,
            2 => Self::HappinessDay,
            3 => Self::HappinessNight,
            4 => Self::LevelUp,
            5 => Self::Trade,
            6 => Self::TradeWithItem,
            7 => Self::UseItem,
            8 => Self::LevelUpAtkGtDef,
            9 => Self::LevelUpAtkEqDef,
            10 => Self::LevelUpDefGtAtk,
            11 => Self::LevelUpPersonalityLow,
            12 => Self::LevelUpPersonalityHigh,
            13 => Self::LevelUpSpawnPokemon,
            14 => Self::LevelUpSpawnEmptySlot,
            15 => Self::Beauty,
            16 => Self::UseItemMale,
            17 => Self::UseItemFemale,
            18 => Self::LevelUpWithItem,
            19 => Self::LevelUpWithMoveType,
            20 => Self::LevelUpWithPartyMember,
            21 => Self::LevelUpMale,
            22 => Self::LevelUpFemale,
            23 => Self::LevelUpAtLocation,
            24 => Self::LevelUpAtMtCoronet,
            25 => Self::LevelUpNearMossRock,
            26 => Self::LevelUpNearIceRock,
            n => Self::Unknown(n),
        }
    }
}

impl std::fmt::Display for EvolutionMethod {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::None => write!(f, "None"),
            Self::Happiness => write!(f, "Happiness"),
            Self::HappinessDay => write!(f, "HappinessDay"),
            Self::HappinessNight => write!(f, "HappinessNight"),
            Self::LevelUp => write!(f, "LevelUp"),
            Self::Trade => write!(f, "Trade"),
            Self::TradeWithItem => write!(f, "TradeWithItem"),
            Self::UseItem => write!(f, "UseItem"),
            Self::LevelUpAtkGtDef => write!(f, "LevelUpAtkGtDef"),
            Self::LevelUpAtkEqDef => write!(f, "LevelUpAtkEqDef"),
            Self::LevelUpDefGtAtk => write!(f, "LevelUpDefGtAtk"),
            Self::LevelUpPersonalityLow => write!(f, "LevelUpPersonalityLow"),
            Self::LevelUpPersonalityHigh => write!(f, "LevelUpPersonalityHigh"),
            Self::LevelUpSpawnPokemon => write!(f, "LevelUpSpawnPokemon"),
            Self::LevelUpSpawnEmptySlot => write!(f, "LevelUpSpawnEmptySlot"),
            Self::Beauty => write!(f, "Beauty"),
            Self::UseItemMale => write!(f, "UseItemMale"),
            Self::UseItemFemale => write!(f, "UseItemFemale"),
            Self::LevelUpWithItem => write!(f, "LevelUpWithItem"),
            Self::LevelUpWithMoveType => write!(f, "LevelUpWithMoveType"),
            Self::LevelUpWithPartyMember => write!(f, "LevelUpWithPartyMember"),
            Self::LevelUpMale => write!(f, "LevelUpMale"),
            Self::LevelUpFemale => write!(f, "LevelUpFemale"),
            Self::LevelUpAtLocation => write!(f, "LevelUpAtLocation"),
            Self::LevelUpAtMtCoronet => write!(f, "LevelUpAtMtCoronet"),
            Self::LevelUpNearMossRock => write!(f, "LevelUpNearMossRock"),
            Self::LevelUpNearIceRock => write!(f, "LevelUpNearIceRock"),
            Self::Unknown(n) => write!(f, "Unknown({})", n),
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, BinRead, BinWrite, Default)]
#[brw(little)]
pub struct EvolutionEntry {
    pub method: u16,
    pub param: u16,
    pub target_species: u16,
}

impl EvolutionEntry {
    pub fn is_empty(&self) -> bool {
        self.method == 0 && self.param == 0 && self.target_species == 0
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, BinRead, BinWrite)]
#[brw(little)]
pub struct EvolutionData {
    pub entries: [EvolutionEntry; EVOLUTIONS_PER_SPECIES],
}

impl Default for EvolutionData {
    fn default() -> Self {
        Self {
            entries: [EvolutionEntry::default(); EVOLUTIONS_PER_SPECIES],
        }
    }
}

impl EvolutionData {
    pub fn active_evolutions(&self) -> impl Iterator<Item = &EvolutionEntry> {
        self.entries.iter().filter(|e| !e.is_empty())
    }
}