xenua 1 year ago
parent
commit
e8ff4e1195
Signed by: xenua
GPG Key ID: 8F93B68BD37255B8
  1. 1183
      src/general.rs
  2. 178
      src/lib.rs
  3. 98
      src/pokemon/gen5.rs
  4. 76
      src/pokemon/mod.rs

1183
src/general.rs

File diff suppressed because it is too large Load Diff

178
src/lib.rs

@ -1,6 +1,10 @@ @@ -1,6 +1,10 @@
pub mod general;
pub mod pokemon;
use std::{
fmt::Display,
ops::{Index, IndexMut},
sync::atomic::{AtomicU32, Ordering},
};
pub struct Pokemon {
@ -10,7 +14,6 @@ pub struct Pokemon { @@ -10,7 +14,6 @@ pub struct Pokemon {
nickname: Option<String>,
language: Language,
gender: Gender,
isFatefulEncounter: bool,
}
pub enum TrainerId {
@ -36,156 +39,55 @@ impl Display for TrainerId { @@ -36,156 +39,55 @@ impl Display for TrainerId {
}
}
pub enum Generation {
One = 1,
Two = 2,
Three = 3,
Four = 4,
Five = 5,
Six = 6,
Seven = 7,
Eight = 8,
Nine = 9,
/// the Let's Go gamess
Gen7b,
/// Legends Arceus
Gen8a,
/// BDSP
Gen8b,
pub trait RNG {
fn get(&self) -> u32;
}
pub enum Nature {
Hardy = 0,
Lonely = 1,
Brave = 2,
Adamant = 3,
Naughty = 4,
Bold = 5,
Docile = 6,
Relaxed = 7,
Impish = 8,
Lax = 9,
Timid = 10,
Hasty = 11,
Serious = 12,
Jolly = 13,
Naive = 14,
Modest = 15,
Mild = 16,
Quiet = 17,
Bashful = 18,
Rash = 19,
Calm = 20,
Gentle = 21,
Sassy = 22,
Careful = 23,
Quirky = 24,
}
impl From<Nature> for Option<(Stat, Stat)> {
fn from(value: Nature) -> Self {
use Nature::*;
use Stat::*;
match value {
Hardy => None,
Lonely => Some((Attack, Defense)),
Brave => Some((Attack, Speed)),
Adamant => Some((Attack, SpAtk)),
Naughty => Some((Attack, SpDef)),
Bold => Some((Defense, Attack)),
Docile => None,
Relaxed => Some((Defense, Speed)),
Impish => Some((Defense, SpAtk)),
Lax => Some((Defense, SpDef)),
Timid => Some((Speed, Attack)),
Hasty => Some((Speed, Defense)),
Serious => None,
Jolly => Some((Speed, SpAtk)),
Naive => Some((Speed, SpDef)),
Modest => Some((SpAtk, Attack)),
Mild => Some((SpAtk, Defense)),
Quiet => Some((SpAtk, Speed)),
Bashful => None,
Rash => Some((SpAtk, SpDef)),
Calm => Some((SpDef, Attack)),
Gentle => Some((SpDef, Defense)),
Sassy => Some((SpDef, Speed)),
Careful => Some((SpDef, SpAtk)),
Quirky => None,
}
}
pub fn prng(prev: u32) -> u32 {
(0x41c64e6d * prev).wrapping_add(0x6073)
}
pub enum Stat {
HitPoints,
Attack,
Defense,
SpAtk,
SpDef,
Speed,
pub fn aprng(prev: u32) -> u32 {
(0x6c078965 * prev).wrapping_add(0x1)
}
pub enum Flavor {
Spicy,
Sour,
Dry,
Bitter,
Sweet,
}
/// the Pseudo-Random Number Generator used in pokemon.
///
/// used for:
/// - encrypting pokemon data in the save file (see http://projectpokemon.org/wiki/Pokemon_NDS_Structure?#Encryption)
/// - generating the personality value in wild pokemon
/// - generating the IVs in wild pokemon
/// - determining the species of wild pokemon
/// - determining the lottery number
pub struct PRng(AtomicU32);
impl From<Flavor> for Stat {
fn from(value: Flavor) -> Self {
use Flavor::*;
use Stat::*;
match value {
Spicy => Attack,
Sour => Defense,
Dry => SpAtk,
Bitter => SpDef,
Sweet => Speed,
}
impl RNG for PRng {
fn get(&self) -> u32 {
self.0
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |v| {
Some((0x41c64e6d * v).wrapping_add(0x6073))
})
.expect("closure never returns none")
}
}
impl From<Stat> for Option<Flavor> {
fn from(value: Stat) -> Self {
use Flavor::*;
use Stat::*;
match value {
HitPoints => None,
Attack => Some(Spicy),
Defense => Some(Sour),
SpAtk => Some(Dry),
SpDef => Some(Bitter),
Speed => Some(Sweet),
}
/// the Alternative Pseudo-Random Number Generator
///
/// "but what about second rng?"
///
/// see https://projectpokemon.org/docs/other/prng-in-pokémon-r38/
pub struct APRng(AtomicU32);
impl RNG for APRng {
fn get(&self) -> u32 {
self.0
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |v| {
Some((0x6c078965 * v).wrapping_add(0x1))
})
.expect("closure never returns none")
}
}
pub enum Language {
Hacked = 0,
Japanese = 1,
English = 2,
French = 3,
Italian = 4,
German = 5,
Unused6 = 6,
Spanish = 7,
Korean = 8,
ChineseS = 9,
ChineseT = 10,
}
pub enum Gender {
Male = 0,
Female = 1,
Genderless = 2,
}
pub struct IVs {
pub hp: u8,
pub atk: u8,

98
src/pokemon/gen5.rs

@ -0,0 +1,98 @@ @@ -0,0 +1,98 @@
use crate::general::BinaryGender;
/// https://projectpokemon.org/home/docs/gen-5/bw-save-structure-r60/
pub struct PK5 {
personality: u32,
checksum: u16,
pokedex_id: u16,
// block A
held_item: u16,
ot_id: u16,
ot_secret_id: u16,
experience: u32,
friendship: u8,
ability: u8,
markings: u8,
original_language: u8,
ev_hp: u8,
ev_attack: u8,
ev_defense: u8,
ev_speed: u8,
ev_sp_attack: u8,
ev_sp_defense: u8,
contest_value_cool: u8,
contest_value_beauty: u8,
contest_value_cute: u8,
contest_value_smart: u8,
contest_value_tough: u8,
contest_value_sheen: u8,
ribbon_set_sinnoh_1: u16,
ribbon_set_unova: u16,
// block B
move_1_id: u16,
move_2_id: u16,
move_3_id: u16,
move_4_id: u16,
move_1_current_pp: u8,
move_2_current_pp: u8,
move_3_current_pp: u8,
move_4_current_pp: u8,
move_pp_ups: u32,
ivs_isegg_isnicknamed: u32,
ribbon_set_hoenn_1: u16,
ribbon_set_hoenn_2: u16,
fateful_gender_altform: u8,
nature: u8,
dreamworld_ability_n_flags: u8,
unknown_1: u32,
// block C
nickname: String,
unknown_2: u8,
origin_game: u8,
ribbon_set_sinnoh_3: u16,
ribbon_set_sinnoh_4: u16,
// block D
ot_name: String,
date_egg_received: [u8; 3],
date_met: [u8; 3],
egg_location_dp: u16,
met_at_location_dp: u16,
pokerus: u8,
pokeball: u8,
met_at_level_ot_gender: u8,
encounter_type: u8,
// battle stats
status: u8,
unknown_flags: u8, // max 0xF0
unknown_3: u16,
level: u8,
capsule_index: u8,
current_hp: u16,
max_hp: u16,
attack: u16,
defense: u16,
speed: u16,
special_attack: u16,
special_defense: u16,
mail_message: Mail5,
}
pub struct Mail5 {
author_tid: u16,
author_sid: u16,
author_gender: BinaryGender,
author_language: u8,
author_version: u8,
mail_type: u8,
author_name: String,
message_ending: u16,
appear_pkm: u16,
message_data_1: u16,
message_data_2: u16,
message_data_3: u16,
}

76
src/pokemon/mod.rs

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
use std::io::Read;
pub mod gen5;
pub trait StringConverter {
fn to_string(bytes: impl Read) -> String;
fn to_bytes(string: String) -> Box<dyn Read>;
}
pub trait Pokemon {
// main
fn species(&self) -> Species;
fn nickname(&self) -> String;
fn held_item(&self) -> Item;
fn gender(&self) -> Gender;
fn nature(&self) -> Nature;
fn ability(&self) -> Ability;
fn form(&self) -> PokemonForm;
fn is_egg(&self) -> bool;
fn is_nicknamed(&self) -> bool;
fn exp(&self) -> u32;
fn ot_name(&self) -> String;
fn ot_gender(&self) -> BinaryGender;
fn level(&self) -> u8;
fn met_level(&self) -> u8;
// internal
fn tid16(&self) -> u16;
fn sid16(&self) -> u16;
fn id32(&self) -> u32;
fn ball(&self) -> PokeBall;
fn current_friendship(&self) -> i32;
fn version(&self) -> i32;
fn pokerus_strain(&self) -> i32;
fn pokerus_days(&self) -> i32;
fn encryption_constant(&self) -> u32;
fn pid(&self) -> u32;
// misc
fn language(&self) -> Language;
fn is_fateful_encounter(&self) -> bool;
// battle
fn move1(&self) -> u16;
fn move2(&self) -> u16;
fn move3(&self) -> u16;
fn move4(&self) -> u16;
fn pp_move1(&self) -> u8;
fn pp_move2(&self) -> u8;
fn pp_move3(&self) -> u8;
fn pp_move4(&self) -> u8;
fn pp_up_move1(&self) -> u8;
fn pp_up_move2(&self) -> u8;
fn pp_up_move3(&self) -> u8;
fn pp_up_move4(&self) -> u8;
fn ev_hp(&self) -> u8;
fn ev_attack(&self) -> u8;
fn ev_defense(&self) -> u8;
fn ev_speed(&self) -> u8;
fn ev_sp_attack(&self) -> u8;
fn ev_sp_defense(&self) -> u8;
fn iv_hp(&self) -> IV;
fn iv_attack(&self) -> IV;
fn iv_defense(&self) -> IV;
fn iv_speed(&self) -> IV;
fn iv_sp_attack(&self) -> IV;
fn iv_sp_defense(&self) -> IV;
fn status_condition(&self) -> StatusCondition;
fn stat_hp_max(&self) -> u16;
fn stat_hp_current(&self) -> u16;
fn stat_attack(&self) -> u16;
fn stat_defense(&self) -> u16;
fn stat_speed(&self) -> u16;
fn stat_sp_attack(&self) -> u16;
fn stat_sp_defense(&self) -> u16;
}
Loading…
Cancel
Save