Pokered Save Editor 2
Pokemon Red & Blue save file editor - Qt 6 C++/QML
Loading...
Searching...
No Matches
pokemon.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2019 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
23#include <QJsonArray>
24#include <QJsonObject>
25#include <QQmlEngine>
26#include <pse-common/utility.h>
27
28#ifdef QT_DEBUG
29#include <QtDebug>
30#endif
31
32#include "./pokemon.h"
33#include "./util/gamedata.h"
34#include "./itemsdb.h"
36#include "./moves.h"
37#include "./types.h"
38
39// ── PokemonDBEntryEvolution ──────────────────────────────────────────────────
40
44 : parent(parent)
45{
46 toName = data["toName"].toString();
47 if (data["level"].isDouble()) level = static_cast<var8>(data["level"].toDouble());
48 if (data["trade"].isBool()) trade = data["trade"].toBool();
49 if (data["item"].isString()) item = data["item"].toString();
50}
51
53{
55 if (!item.isEmpty())
57
58#ifdef QT_DEBUG
59 if (!toEvolution) qCritical() << "Evolution:" << toName << "could not be deep linked.";
60 if (!deEvolution) qCritical() << "Evolution:" << toName << "null deEvolution provided.";
61 if (!item.isEmpty() && !toItem) qCritical() << "Evolution item:" << item << "could not be deep linked.";
62#endif
63
64 if (toEvolution) {
65 toEvolution->toDeEvolution = deEvolution;
66 toDeEvolution = deEvolution;
67 }
68 if (toItem)
69 toItem->toEvolvePokemon.append(this);
70}
71
72// ── PokemonDBEntryMove ───────────────────────────────────────────────────────
73
76 : parent(parent)
77{
78 level = static_cast<var8>(data["level"].toDouble());
79 move = data["move"].toString();
80}
81
83{
85#ifdef QT_DEBUG
86 if (!toMove) qCritical() << "Pokemon move:" << move << "could not be deep linked.";
87#endif
88 if (toMove)
89 toMove->toPokemonLearned.append(this);
90}
91
92// ── PokemonDBEntry ───────────────────────────────────────────────────────────
93
96{
97 name = data["name"].toString();
98 ind = static_cast<var8>(data["ind"].toDouble());
99 readable = data["readable"].toString();
100
101 if (data["pokedex"].isDouble()) pokedex = static_cast<var8>(data["pokedex"].toDouble());
102 if (data["growthRate"].isDouble()) growthRate = static_cast<var8>(data["growthRate"].toDouble());
103 if (data["baseHp"].isDouble()) baseHp = static_cast<var8>(data["baseHp"].toDouble());
104 if (data["baseAttack"].isDouble()) baseAttack = static_cast<var8>(data["baseAttack"].toDouble());
105 if (data["baseDefense"].isDouble()) baseDefense = static_cast<var8>(data["baseDefense"].toDouble());
106 if (data["baseSpeed"].isDouble()) baseSpeed = static_cast<var8>(data["baseSpeed"].toDouble());
107 if (data["baseSpecial"].isDouble()) baseSpecial = static_cast<var8>(data["baseSpecial"].toDouble());
108 if (data["baseExpYield"].isDouble()) baseExpYield = static_cast<var8>(data["baseExpYield"].toDouble());
109 if (data["catchRate"].isDouble()) catchRate = static_cast<var8>(data["catchRate"].toDouble());
110 if (data["type1"].isString()) type1 = data["type1"].toString();
111 if (data["type2"].isString()) type2 = data["type2"].toString();
112 if (data["glitch"].isBool()) glitch = data["glitch"].toBool();
113
114 if (data["moves"].isArray())
115 for (QJsonValue e : data["moves"].toArray())
116 moves.append(new PokemonDBEntryMove(e, this));
117
118 if (data["initial"].isArray())
119 for (QJsonValue e : data["initial"].toArray())
120 initial.append(e.toString());
121
122 if (data["tmHm"].isArray())
123 for (QJsonValue e : data["tmHm"].toArray())
124 tmHm.append(static_cast<var8>(e.toDouble()));
125
126 if (data["evolution"].isArray()) {
127 for (QJsonValue e : data["evolution"].toArray())
128 evolution.append(new PokemonDBEntryEvolution(e, this));
129 } else if (data["evolution"].isObject()) {
130 auto tmp = data["evolution"];
131 evolution.append(new PokemonDBEntryEvolution(tmp, this));
132 }
133}
134
136{
137 if (!type1.isEmpty()) {
139 if (toType1) toType1->toPokemon.append(this);
140#ifdef QT_DEBUG
141 if (!toType1) qCritical() << "Pokemon type1:" << type1 << "could not be deep linked.";
142#endif
143 }
144 if (!type2.isEmpty()) {
146 if (toType2) toType2->toPokemon.append(this);
147#ifdef QT_DEBUG
148 if (!toType2) qCritical() << "Pokemon type2:" << type2 << "could not be deep linked.";
149#endif
150 }
151
152 for (auto* evolEntry : evolution)
153 evolEntry->deepLink(this);
154
155 for (auto* pokeMoveEntry : moves)
156 pokeMoveEntry->deepLink();
157
158 for (const auto& initMove : initial) {
159 auto* link = MovesDB::inst()->getIndAt(initMove);
160 toInitial.append(link);
161#ifdef QT_DEBUG
162 if (!link) qCritical() << "Pokemon initial move:" << initMove << "could not be deep linked.";
163#endif
164 if (link) link->toPokemonInitial.append(this);
165 }
166
167 for (auto tmHmMove : tmHm) {
168 auto* moveLink = MovesDB::inst()->getIndAt("tm" + QString::number(tmHmMove));
169 auto* itemLink = ItemsDB::inst()->getIndAt("tm" + QString::number(tmHmMove));
170 toTmHmMove.append(moveLink);
171 toTmHmItem.append(itemLink);
172#ifdef QT_DEBUG
173 if (!moveLink) qCritical() << "Pokemon TM/HM move:" << tmHmMove << "could not be deep linked.";
174 if (!itemLink) qCritical() << "Pokemon TM/HM item:" << tmHmMove << "could not be deep linked.";
175#endif
176 if (moveLink) moveLink->toPokemonTmHm.append(this);
177 if (itemLink) itemLink->toTeachPokemon.append(this);
178 }
179}
180
181// ── PokemonDB ────────────────────────────────────────────────────────────────
182
183PokemonDB* PokemonDB::inst()
184{
185 static PokemonDB* _inst = new PokemonDB;
186 return _inst;
187}
188
189const QVector<PokemonDBEntry*> PokemonDB::getStore() const { return store; }
190const QHash<QString, PokemonDBEntry*> PokemonDB::getInd() const { return ind; }
191int PokemonDB::getStoreSize() const { return store.size(); }
192
194{
195 if (idx < 0 || idx >= store.size()) return nullptr;
196 return store.at(idx);
197}
198
199PokemonDBEntry* PokemonDB::getIndAt(const QString& key) const
200{
201 return ind.value(key, nullptr);
202}
203
205{
206 static bool once = false;
207 if (once) return;
208 auto jsonData = GameData::inst()->json("pokemon");
209 for (QJsonValue entry : jsonData.array())
210 store.append(new PokemonDBEntry(entry));
211 once = true;
212}
213
215{
216 static bool once = false;
217 if (once) return;
218 for (auto* entry : store) {
219 ind.insert(entry->name, entry);
220 ind.insert(QString::number(entry->ind), entry);
221 ind.insert(entry->readable, entry);
222 if (entry->pokedex)
223 ind.insert("dex" + QString::number(*entry->pokedex), entry);
224 }
225 once = true;
226}
227
229{
230 static bool once = false;
231 if (once) return;
232 for (auto* entry : store)
233 entry->deepLink();
234 once = true;
235}
236
237void PokemonDB::qmlProtect(const QQmlEngine* const engine) const
238{
239 Utility::qmlProtectUtil(this, engine);
240}
241
242void PokemonDB::qmlRegister() const
243{
244 static bool once = false;
245 if (once) return;
246 qmlRegisterUncreatableType<PokemonDB>("PSE.DB.PokemonDB", 1, 0, "PokemonDB", "Can't instantiate in QML");
247 once = true;
248}
249
250PokemonDB::PokemonDB()
251{
252 qmlRegister();
253}
const QJsonDocument json(const QString filename) const
Parsed document for filename.
Definition gamedata.cpp:45
static GameData * inst()
The process-wide GameData singleton.
Definition gamedata.cpp:71
ItemDBEntry * getIndAt(const QString val) const
Item by name key (for QML).
Definition itemsdb.cpp:66
static ItemsDB * inst()
< Number of items.
Definition itemsdb.cpp:37
MoveDBEntry * getIndAt(const QString &key) const
Move by name key (for QML).
Definition moves.cpp:88
static MovesDB * inst()
< Number of moves.
Definition moves.cpp:72
void qmlProtect(const QQmlEngine *const engine) const
Pin to C++ ownership.
Definition pokemon.cpp:237
static PokemonDB * inst()
< Number of species.
Definition pokemon.cpp:183
void deepLink()
Resolve every species' cross-reference web.
Definition pokemon.cpp:228
PokemonDBEntry * getStoreAt(int idx) const
Species by store index (for QML).
Definition pokemon.cpp:193
int getStoreSize() const
Species count.
Definition pokemon.cpp:191
const QHash< QString, PokemonDBEntry * > getInd() const
Name->species index.
Definition pokemon.cpp:190
void index()
Build the name->species index.
Definition pokemon.cpp:214
const QVector< PokemonDBEntry * > getStore() const
All species.
Definition pokemon.cpp:189
void load()
Load species from JSON.
Definition pokemon.cpp:204
PokemonDBEntry * getIndAt(const QString &key) const
Species by name key (for QML).
Definition pokemon.cpp:199
TypeDBEntry * getIndAt(const QString &key) const
Type by name key (for QML).
Definition types.cpp:53
static TypesDB * inst()
< Number of types.
Definition types.cpp:37
static void qmlProtectUtil(const QObject *const obj, const QQmlEngine *const engine)
Pin obj to C++ ownership so the QML engine never garbage-collects it.
Definition utility.cpp:63
var8e var8
Everyday 8-bit alias. Exact (not "fastest") to dodge the pointer-width bug noted above.
Definition types.h:124
One evolution edge of a species: how it evolves (and de-evolves).
Definition pokemon.h:52
QString item
Evolution item, if any.
Definition pokemon.h:59
void deepLink(PokemonDBEntry *deEvolution)
Resolve target/item; set deEvolution back-link.
Definition pokemon.cpp:52
std::optional< var8 > level
Evolution level, if level-based.
Definition pokemon.h:60
PokemonDBEntry * toDeEvolution
Resolved pre-evolution.
Definition pokemon.h:62
PokemonDBEntry * toEvolution
Resolved evolved species.
Definition pokemon.h:63
ItemDBEntry * toItem
Resolved evolution item.
Definition pokemon.h:64
QString toName
Name of the species this evolves into.
Definition pokemon.h:57
PokemonDBEntry * parent
Owning species.
Definition pokemon.h:65
PokemonDBEntryEvolution()
Empty edge.
Definition pokemon.cpp:41
bool trade
Evolves on trade.
Definition pokemon.h:58
One learnable move of a species, with the level it's learned at.
Definition pokemon.h:74
void deepLink()
Resolve the move link.
Definition pokemon.cpp:82
PokemonDBEntryMove()
Empty learn entry.
Definition pokemon.cpp:74
QString move
Move name (resolved to toMove).
Definition pokemon.h:80
MoveDBEntry * toMove
Resolved move.
Definition pokemon.h:82
var8 level
Level the move is learned at.
Definition pokemon.h:79
PokemonDBEntry * parent
Owning species.
Definition pokemon.h:83
One species' complete static data – the richest entry in the db layer.
Definition pokemon.h:98
QString type1
Primary type name (resolved to toType1).
Definition pokemon.h:107
PokemonDBEntry()
Empty species.
Definition pokemon.cpp:94
bool glitch
Whether this is a glitch species.
Definition pokemon.h:106
std::optional< var8 > baseHp
Base HP.
Definition pokemon.h:117
QVector< ItemDBEntry * > toTmHmItem
Resolved TM/HM items.
Definition pokemon.h:130
QString type2
Secondary type name (resolved to toType2).
Definition pokemon.h:108
std::optional< var8 > baseDefense
Base Defense.
Definition pokemon.h:119
std::optional< var8 > catchRate
Catch rate.
Definition pokemon.h:123
QVector< MoveDBEntry * > toTmHmMove
Resolved TM/HM moves.
Definition pokemon.h:129
std::optional< var8 > growthRate
EXP growth-rate group.
Definition pokemon.h:116
QString name
Internal species name (key).
Definition pokemon.h:103
QVector< PokemonDBEntryMove * > moves
Level-up learnset.
Definition pokemon.h:110
void deepLink()
Resolve the full cross-reference web (the to* members).
Definition pokemon.cpp:135
std::optional< var8 > baseSpeed
Base Speed.
Definition pokemon.h:120
QVector< MoveDBEntry * > toInitial
Resolved capture moves.
Definition pokemon.h:128
var8 ind
Internal species index.
Definition pokemon.h:104
QVector< var8 > tmHm
TM/HM numbers it can learn.
Definition pokemon.h:112
std::optional< var8 > baseSpecial
Base Special.
Definition pokemon.h:121
QVector< QString > initial
Moves known at capture (resolved to toInitial).
Definition pokemon.h:111
QString readable
Human-readable species name.
Definition pokemon.h:105
std::optional< var8 > baseExpYield
Base EXP yield.
Definition pokemon.h:122
QVector< PokemonDBEntryEvolution * > evolution
Evolution edges.
Definition pokemon.h:113
TypeDBEntry * toType1
Resolved primary type.
Definition pokemon.h:125
TypeDBEntry * toType2
Resolved secondary type.
Definition pokemon.h:126
std::optional< var8 > baseAttack
Base Attack.
Definition pokemon.h:118
std::optional< var8 > pokedex
Pokedex number, if assigned.
Definition pokemon.h:115