sky_save/
active.rs

1//! Handles loading and storing the active Pokémon in the party.
2
3use crate::offsets::active::{moves, pokemon, ACTIVE_MOVE_BIT_LEN, ACTIVE_PKM_BIT_LEN};
4use crate::{IqMapBits, PmdString};
5use bitvec::prelude::*;
6
7/// A static `BitArray` representing the bits of an `ActivePokemon`.
8pub type ActivePokemonBits = BitArr!(for ACTIVE_PKM_BIT_LEN, in u8, Lsb0);
9/// A static `BitArray` representing the bits of a `StoredMove`.
10pub type ActiveMoveBits = BitArr!(for ACTIVE_MOVE_BIT_LEN, in u8, Lsb0);
11
12/// Represents each of the four moves in an `ActivePokemon`.
13#[derive(Debug, Default, Clone)]
14pub struct ActiveMove {
15    pub valid: bool,
16    pub linked: bool,
17    pub switched: bool,
18    pub set: bool,
19    pub sealed: bool,
20    pub id: u16,
21    pub pp: u8,
22    pub power_boost: u8,
23}
24
25impl ActiveMove {
26    pub fn from_bitslice(bits: &BitSlice<u8, Lsb0>) -> Self {
27        Self {
28            valid: bits[moves::VALID],
29            linked: bits[moves::LINKED],
30            switched: bits[moves::SWITCHED],
31            set: bits[moves::SET],
32            sealed: bits[moves::SEALED],
33            id: bits[moves::ID].load_le(),
34            pp: bits[moves::PP].load_le(),
35            power_boost: bits[moves::POWER_BOOST].load_le(),
36        }
37    }
38
39    pub fn to_bits(&self) -> ActiveMoveBits {
40        let mut bits = bitarr![u8, Lsb0; 0; ACTIVE_MOVE_BIT_LEN];
41        bits.set(moves::VALID, self.valid);
42        bits.set(moves::LINKED, self.linked);
43        bits.set(moves::SWITCHED, self.switched);
44        bits.set(moves::SET, self.set);
45        bits[moves::ID].store_le(self.id);
46        bits[moves::PP].store_le(self.pp);
47        bits[moves::POWER_BOOST].store_le(self.power_boost);
48        bits
49    }
50}
51
52/// Represents one of the four active Pokémon in the party.
53#[derive(Debug, Default, Clone)]
54pub struct ActivePokemon {
55    pub valid: bool,
56    pub unknown_1: u8,
57    pub level: u8,
58    pub met_at: u8,
59    pub met_floor: u8,
60    pub unknown_2: bool,
61    pub iq: u16,
62    pub roaster_number: u16,
63    pub unknown_3: u32,
64    pub id: u16,
65    pub current_hp: u16,
66    pub max_hp: u16,
67    pub attack: u8,
68    pub sp_attack: u8,
69    pub defense: u8,
70    pub sp_defense: u8,
71    pub exp: u32,
72    pub move_1: ActiveMove,
73    pub move_2: ActiveMove,
74    pub move_3: ActiveMove,
75    pub move_4: ActiveMove,
76    pub unknown_4: u128,
77    pub iq_map: IqMapBits,
78    pub tactic: u8,
79    pub unknown_5: u16,
80    pub name: PmdString,
81}
82
83impl ActivePokemon {
84    pub fn from_bitslice(value: &BitSlice<u8, Lsb0>) -> Self {
85        let mut iq: IqMapBits = bitarr!(u8, Lsb0; 0; 69);
86        iq[0..69].copy_from_bitslice(&value[pokemon::IQ_MAP]);
87
88        let name_bytes = &value[pokemon::NAME];
89
90        Self {
91            valid: value[pokemon::VALID],
92            unknown_1: value[pokemon::UNKNOWN_1].load_le(),
93            level: value[pokemon::LEVEL].load_le(),
94            met_at: value[pokemon::MET_AT].load_le(),
95            met_floor: value[pokemon::MET_FLOOR].load_le(),
96            unknown_2: value[pokemon::UNKNOWN_2],
97            iq: value[pokemon::IQ].load_le(),
98            roaster_number: value[pokemon::ROASTER_NUMBER].load_le(),
99            unknown_3: value[pokemon::UNKNOWN_3].load_le(),
100            id: value[pokemon::ID].load_le(),
101            current_hp: value[pokemon::CURRENT_HP].load_le(),
102            max_hp: value[pokemon::MAX_HP].load_le(),
103            attack: value[pokemon::ATTACK].load_le(),
104            sp_attack: value[pokemon::SP_ATTACK].load_le(),
105            defense: value[pokemon::DEFENSE].load_le(),
106            sp_defense: value[pokemon::SP_DEFENSE].load_le(),
107            exp: value[pokemon::EXP].load_le(),
108            move_1: ActiveMove::from_bitslice(&value[pokemon::MOVE_1]),
109            move_2: ActiveMove::from_bitslice(&value[pokemon::MOVE_2]),
110            move_3: ActiveMove::from_bitslice(&value[pokemon::MOVE_3]),
111            move_4: ActiveMove::from_bitslice(&value[pokemon::MOVE_4]),
112            unknown_4: value[pokemon::UNKNOWN_4].load_le(),
113            iq_map: iq,
114            tactic: value[pokemon::TACTIC].load_le(),
115            unknown_5: value[pokemon::UNKNOWN_5].load_le(),
116            name: PmdString::from(name_bytes),
117        }
118    }
119
120    pub fn to_bits(&self) -> ActivePokemonBits {
121        let mut bits = bitarr![u8, Lsb0; 0; ACTIVE_PKM_BIT_LEN];
122
123        bits.set(pokemon::VALID, self.valid);
124        bits[pokemon::UNKNOWN_1].store_le(self.unknown_1);
125        bits[pokemon::LEVEL].store_le(self.level);
126        bits[pokemon::MET_AT].store_le(self.met_at);
127        bits[pokemon::MET_FLOOR].store_le(self.met_floor);
128        bits.set(pokemon::UNKNOWN_2, self.unknown_2);
129        bits[pokemon::IQ].store_le(self.iq);
130        bits[pokemon::ROASTER_NUMBER].store_le(self.roaster_number);
131        bits[pokemon::UNKNOWN_3].store_le(self.unknown_3);
132        bits[pokemon::ID].store_le(self.id);
133        bits[pokemon::CURRENT_HP].store_le(self.current_hp);
134        bits[pokemon::MAX_HP].store_le(self.max_hp);
135        bits[pokemon::ATTACK].store_le(self.attack);
136        bits[pokemon::SP_ATTACK].store_le(self.sp_attack);
137        bits[pokemon::DEFENSE].store_le(self.defense);
138        bits[pokemon::SP_DEFENSE].store_le(self.sp_defense);
139        bits[pokemon::EXP].store_le(self.exp);
140        bits[pokemon::MOVE_1].copy_from_bitslice(&self.move_1.to_bits()[0..ACTIVE_MOVE_BIT_LEN]);
141        bits[pokemon::MOVE_2].copy_from_bitslice(&self.move_2.to_bits()[0..ACTIVE_MOVE_BIT_LEN]);
142        bits[pokemon::MOVE_3].copy_from_bitslice(&self.move_3.to_bits()[0..ACTIVE_MOVE_BIT_LEN]);
143        bits[pokemon::MOVE_4].copy_from_bitslice(&self.move_4.to_bits()[0..ACTIVE_MOVE_BIT_LEN]);
144        bits[pokemon::UNKNOWN_4].store_le(self.unknown_4);
145        bits[pokemon::IQ_MAP].copy_from_bitslice(&self.iq_map[0..69]);
146        bits[pokemon::TACTIC].store_le(self.tactic);
147        bits[pokemon::UNKNOWN_5].store_le(self.unknown_5);
148        bits[pokemon::NAME].copy_from_bitslice(self.name.to_save_bytes().view_bits::<Lsb0>());
149
150        bits
151    }
152}