sky_save/
stored.rs

1//! Handles loading and storing the stored Pokémon.
2
3use crate::offsets::stored::{moves, pokemon, STORED_MOVE_BIT_LEN, STORED_PKM_BIT_LEN};
4use crate::PmdString;
5use bitvec::prelude::*;
6use bitvec::BitArr;
7
8pub type IqMapBits = BitArr!(for 69, in u8, Lsb0);
9
10/// A static `BitArray` representing the bits of a `StoredPokemon`.
11pub type StoredPokemonBits = BitArr!(for STORED_PKM_BIT_LEN, in u8, Lsb0);
12/// A static `BitArray` representing the bits of a `StoredMove`.
13pub type StoredMoveBits = BitArr!(for STORED_MOVE_BIT_LEN, in u8, Lsb0);
14
15/// Represents each of the four moves in a `StoredPokemon`.
16#[derive(Debug, Default, Clone)]
17pub struct StoredMove {
18    pub valid: bool,
19    pub linked: bool,
20    pub switched: bool,
21    pub set: bool,
22    pub id: u16,
23    pub power_boost: u8,
24}
25
26impl StoredMove {
27    pub fn from_bitslice(bits: &BitSlice<u8, Lsb0>) -> Self {
28        Self {
29            valid: bits[moves::VALID],
30            linked: bits[moves::LINKED],
31            switched: bits[moves::SWITCHED],
32            set: bits[moves::SET],
33            id: bits[moves::ID].load_le(),
34            power_boost: bits[moves::POWER_BOOST].load_le(),
35        }
36    }
37
38    pub fn to_bits(&self) -> StoredMoveBits {
39        let mut bits = bitarr![u8, Lsb0; 0; STORED_MOVE_BIT_LEN];
40
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::POWER_BOOST].store_le(self.power_boost);
47
48        bits
49    }
50}
51
52/// Represents a recruited Pokémon in Chimecho's Assembly.
53/// Holds information that isn't critical in dungeon mode.
54#[derive(Debug, Default, Clone)]
55pub struct StoredPokemon {
56    pub valid: bool,
57    pub level: u8,
58    pub id: u16,
59    pub met_at: u8,
60    pub met_floor: u8,
61    pub unknown: bool,
62    pub evolved_at_1: u8,
63    pub evolved_at_2: u8,
64    pub iq: u16,
65    pub hp: u16,
66    pub attack: u8,
67    pub sp_attack: u8,
68    pub defense: u8,
69    pub sp_defense: u8,
70    pub exp: u32,
71    pub iq_map: IqMapBits,
72    pub tactic: u8,
73    pub move_1: StoredMove,
74    pub move_2: StoredMove,
75    pub move_3: StoredMove,
76    pub move_4: StoredMove,
77    pub name: PmdString,
78}
79
80impl StoredPokemon {
81    pub fn from_bitslice(value: &BitSlice<u8, Lsb0>) -> Self {
82        let mut iq: IqMapBits = bitarr![u8, Lsb0; 0; 69];
83        iq[0..69].copy_from_bitslice(&value[pokemon::IQ_MAP]);
84
85        let name_bytes = &value[pokemon::NAME];
86
87        Self {
88            valid: value[pokemon::VALID],
89            level: value[pokemon::LEVEL].load_le(),
90            id: value[pokemon::ID].load_le(),
91            met_at: value[pokemon::MET_AT].load_le(),
92            met_floor: value[pokemon::MET_FLOOR].load_le(),
93            unknown: value[pokemon::UNKNOWN],
94            evolved_at_1: value[pokemon::EVOLVED_AT_1].load_le(),
95            evolved_at_2: value[pokemon::EVOLVED_AT_2].load_le(),
96            iq: value[pokemon::IQ].load_le(),
97            hp: value[pokemon::HP].load_le(),
98            attack: value[pokemon::ATTACK].load_le(),
99            sp_attack: value[pokemon::SP_ATTACK].load_le(),
100            defense: value[pokemon::DEFENSE].load_le(),
101            sp_defense: value[pokemon::SP_DEFENSE].load_le(),
102            exp: value[pokemon::EXP].load_le(),
103            iq_map: iq,
104            tactic: value[pokemon::TACTIC].load_le(),
105            move_1: StoredMove::from_bitslice(&value[pokemon::MOVE_1]),
106            move_2: StoredMove::from_bitslice(&value[pokemon::MOVE_2]),
107            move_3: StoredMove::from_bitslice(&value[pokemon::MOVE_3]),
108            move_4: StoredMove::from_bitslice(&value[pokemon::MOVE_4]),
109            name: PmdString::from(name_bytes),
110        }
111    }
112
113    pub fn to_bits(&self) -> StoredPokemonBits {
114        let mut bits = bitarr![u8, Lsb0; 0; STORED_PKM_BIT_LEN];
115
116        bits.set(pokemon::VALID, self.valid);
117        bits[pokemon::LEVEL].store_le(self.level);
118        bits[pokemon::ID].store_le(self.id);
119        bits[pokemon::MET_AT].store_le(self.met_at);
120        bits[pokemon::MET_FLOOR].store_le(self.met_floor);
121        bits.set(34, self.unknown);
122        bits[pokemon::EVOLVED_AT_1].store_le(self.evolved_at_1);
123        bits[pokemon::EVOLVED_AT_2].store_le(self.evolved_at_2);
124        bits[pokemon::IQ].store_le(self.iq);
125        bits[pokemon::HP].store_le(self.hp);
126        bits[pokemon::ATTACK].store_le(self.attack);
127        bits[pokemon::SP_ATTACK].store_le(self.sp_attack);
128        bits[pokemon::DEFENSE].store_le(self.defense);
129        bits[pokemon::SP_DEFENSE].store_le(self.sp_defense);
130        bits[pokemon::EXP].store_le(self.exp);
131        bits[pokemon::IQ_MAP].copy_from_bitslice(&self.iq_map[0..69]);
132        bits[pokemon::TACTIC].store_le(self.tactic);
133        bits[pokemon::MOVE_1].copy_from_bitslice(&self.move_1.to_bits()[0..STORED_MOVE_BIT_LEN]);
134        bits[pokemon::MOVE_2].copy_from_bitslice(&self.move_2.to_bits()[0..STORED_MOVE_BIT_LEN]);
135        bits[pokemon::MOVE_3].copy_from_bitslice(&self.move_3.to_bits()[0..STORED_MOVE_BIT_LEN]);
136        bits[pokemon::MOVE_4].copy_from_bitslice(&self.move_4.to_bits()[0..STORED_MOVE_BIT_LEN]);
137        bits[pokemon::NAME].copy_from_bitslice(self.name.to_save_bytes().view_bits());
138
139        bits
140    }
141}