Pokered Save Editor 2
Pokemon Red & Blue save file editor - Qt 6 C++/QML
Loading...
Searching...
No Matches
playerpokedex.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 Twilight
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15*/
16
22#include "playerpokedex.h"
23#include "../../savefile.h"
26#include <pse-db/names.h>
27#include <pse-db/pokemon.h>
28#include <pse-common/random.h>
29
31{
32 load(saveFile);
33}
34
36
38{
39 reset();
40
41 if(saveFile == nullptr) {
42 return;
43 }
44
45 // Load Owned
46 QVector<bool> tmp;
47 loadPokedex(saveFile, &tmp, 0x25A3);
48
49 for(var8 i = 0; i < maxPokedex && i < tmp.size(); i++) {
50 owned[i] = tmp.at(i);
52 }
53
54 tmp.clear();
55
56 // Load Seen
57 loadPokedex(saveFile, &tmp, 0x25B6);
58
59 for(var8 i = 0; i < maxPokedex && i < tmp.size(); i++) {
60 seen[i] = tmp.at(i);
62 }
63
64 tmp.clear();
65
66 dexChanged();
67}
68
70{
71 QVector<bool> tmp;
72
73 // Save owned
74 for(var8 i = 0; i < maxPokedex; i++)
75 tmp.append(owned[i]);
76
77 savePokedex(saveFile, &tmp, 0x25A3);
78 tmp.clear();
79
80 // Save seen
81 for(var8 i = 0; i < maxPokedex; i++)
82 tmp.append(seen[i]);
83
84 savePokedex(saveFile, &tmp, 0x25B6);
85 tmp.clear();
86}
87
89{
90 // memset's 2nd arg is the fill VALUE, 3rd is the byte COUNT. This must blank
91 // the dex, so the fill value is 0 (every seen/owned bool -> false). (It used to
92 // pass pokemonDexCount as the value, filling each byte with 151 -> every bool
93 // read as true, i.e. reset() marked the WHOLE dex seen+owned. Caught by
94 // tst_pokedex's markAll_and_reset.)
95 memset(owned, 0, maxPokedex * sizeof(bool));
96 memset(seen, 0, maxPokedex * sizeof(bool));
97}
98
99// Gives all Pokedex entries a 2 out of 5 chance (40% chance) of being
100// seen and/or owned.
102{
103 reset();
104
105 for(var8 i = 0; i < 151; i++)
106 {
107 // 15% chance of having them seen or owned
108 bool markSeen = Random::inst()->chanceSuccess(15);
109 bool markOwned = Random::inst()->chanceSuccess(15);
110
111 owned[i] = markOwned;
112 seen[i] = markSeen;
113
115 }
116
117 dexChanged();
118}
119
121{
122 bool valSeen = seen[0];
123 bool valOwn = owned[0];
124
125 // Toggle between these 3 states in this order
126 // 1. None
127 // 2. Seen
128 // 3. Owned
129
130 if(valOwn) // Owned (3) -> None (1)
132 else if(valSeen) // Seen (2) -> Owned (3)
134 else // None (1) -> Seen (2)
136}
137
139{
140 bool valSeen = seen[val];
141 bool valOwn = owned[val];
142
143 if(valOwn) { // Owned (3) -> None (1)
144 this->seen[val] = false;
145 this->owned[val] = false;
146 }
147 else if(valSeen) { // Seen (2) -> Owned (3)
148 this->seen[val] = true;
149 this->owned[val] = true;
150 }
151 else { // None (1) -> Seen (2)
152 this->seen[val] = true;
153 this->owned[val] = false;
154 }
155
156 // Notify Changes
157 dexItemChanged(val);
158 dexChanged();
159}
160
162{
163 // Start with None
164 bool owned = false;
165 bool seen = false;
166
167 // If seen only, then mark seen
168 if(val == DexSeen)
169 seen = true;
170
171 // If owned, then mark both true
172 else if(val == DexOwned) {
173 seen = true;
174 owned = true;
175 }
176
177 // Apply changes to all
178 for(int i = 0; i < maxPokedex; i++) {
179 this->seen[i] = seen;
180 this->owned[i] = owned;
182 }
183
184 // Notify changes
185 dexChanged();
186}
187
188void PlayerPokedex::loadPokedex(SaveFile* saveFile, QVector<bool>* toArr, var16 fromOffset)
189{
190 // Get Toolset
191 auto toolset = saveFile->toolset;
192
193 // Erase Array
194 toArr->clear();
195
196 // Obtain new array from sav file
197 auto ret = toolset->getBitField(fromOffset, 0x13);
198
199 // Merge it into main array
200 for(auto entry : ret)
201 toArr->append(entry);
202
203 // Trim end off to stay within 151 Pokemon
204 // One of the complications of bit-fields is that retrieving a bitfield
205 // retrives the whole byte
206 toArr->pop_back();
207}
208
209void PlayerPokedex::savePokedex(SaveFile* saveFile, QVector<bool>* fromArr, var16 toOffset)
210{
211 // Get Toolset
212 auto toolset = saveFile->toolset;
213
214 // Apply bitfield to sav file
215 // fromArr is already the correct size and doesn't need to be trimmed
216 // it will be applied correctly
217 toolset->setBitField(toOffset, 0x13, *fromArr);
218}
219
221{
222 int ret = 0;
223
224 for(int i = 0; i < maxPokedex; i++) {
225 if(owned[i])
226 ret++;
227 }
228
229 return ret;
230}
231
233{
234 int ret = 0;
235
236 for(int i = 0; i < maxPokedex; i++) {
237 if(seen[i])
238 ret++;
239 }
240
241 return ret;
242}
243
245{
246 return maxPokedex;
247}
248
250{
251 return owned[ind];
252}
253
254void PlayerPokedex::ownedSet(int ind, bool val)
255{
256 owned[ind] = val;
257 dexChanged();
258 dexItemChanged(ind);
259}
260
262{
263 return maxPokedex;
264}
265
267{
268 return seen[ind];
269}
270
271void PlayerPokedex::seenSet(int ind, bool val)
272{
273 seen[ind] = val;
274 dexChanged();
275 dexItemChanged(ind);
276}
277
279{
280 bool valSeen = seen[ind];
281 bool valOwn = owned[ind];
282
283 if(valOwn) { // Owned (3)
284 return DexOwned;
285 }
286 else if(valSeen) { // Seen (2)
287 return DexSeen;
288 }
289 else { // None (1)
290 return DexNone;
291 }
292}
bool seenAt(int ind)
Is species ind seen?
void markAll(int val)
Mark every entry to a state (e.g. all owned/seen/none).
void savePokedex(SaveFile *saveFile, QVector< bool > *fromArr, var16 toOffset)
Flatten one bool array back into a dex bit-field (toOffset).
void reset()
Blank the whole dex.
PlayerPokedex(SaveFile *saveFile=nullptr)
void ownedSet(int ind, bool val)
Set/clear owned for ind.
void save(SaveFile *saveFile)
Flatten both dex bit-fields back to the save.
void randomize()
Randomize the dex (constrained).
@ DexNone
Neither seen nor owned.
@ DexOwned
Owned (implies seen).
@ DexSeen
Seen but not owned.
protected::void dexChanged()
Any dex change (refreshes counts).
bool seen[maxPokedex]
Seen flag per species (0-based).
int seenCount()
Count of set seen flags (backs the property).
int ownedCount()
Count of set owned flags (backs the property).
int ownedMax()
Max owned index (maxPokedex).
void toggleOne(int val)
Flip a single entry val.
bool ownedAt(int ind)
Is species ind owned?
void seenSet(int ind, bool val)
Set/clear seen for ind.
void toggleAll()
Flip every entry.
int seenMax()
Max seen index (maxPokedex).
virtual ~PlayerPokedex()
void dexItemChanged(int ind)
A single entry ind changed.
void load(SaveFile *saveFile=nullptr)
Expand both dex bit-fields from the save.
bool owned[maxPokedex]
Owned flag per species (0-based).
int getState(int ind)
Combined DexEntryState for ind.
void loadPokedex(SaveFile *saveFile, QVector< bool > *toArr, var16 fromOffset)
Expand one dex bit-field (fromOffset) into a bool array.
bool chanceSuccess(const int percent) const
Did a percent chance succeed?
Definition random.cpp:73
static Random * inst()
< Convenience 50% coin flip (integer path), readable from QML.
Definition random.cpp:31
void setBitField(var16 addr, var16 size, QVector< bool > src)
Sets an entire bitfield from a vector of bools.
QVector< bool > getBitField(var16 addr, var16 size)
Gets an entire bitfield as a vector of bools.
One loaded save: the raw 32 KB bytes, their expanded object tree, and the tools that move between the...
Definition savefile.h:46
SaveFileToolset * toolset
Tools to operate directly on the raw sav file data.
Definition savefile.h:117
var8e var8
Everyday 8-bit alias. Exact (not "fastest") to dodge the pointer-width bug noted above.
Definition types.h:124
var16e var16
Everyday 16-bit alias. Exact width to avoid the "fastest" widening bug.
Definition types.h:125
constexpr var8 maxPokedex
Number of Gen 1 species (dex slots).