2021-08-22 10:10:26 +00:00
|
|
|
#include "BuildSpecies.hpp"
|
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
#define GET(o, objectKey, key) \
|
2021-08-28 14:52:47 +00:00
|
|
|
auto& _##objectKey = o.at(#objectKey); \
|
2021-08-22 10:10:26 +00:00
|
|
|
if (_##objectKey.is_null()) { \
|
2021-08-28 13:56:08 +00:00
|
|
|
auto errorKeyFunc = [=]() { return key; }; \
|
|
|
|
std::cout << "Failed to retrieve key '" << #objectKey << "' for object with key '" << errorKeyFunc() \
|
|
|
|
<< "' in file '" << path << "'\n"; \
|
2021-08-22 10:10:26 +00:00
|
|
|
return nullptr; \
|
|
|
|
}
|
|
|
|
|
|
|
|
PkmnLib::Library::SpeciesLibrary* BuildSpecies::BuildLibrary(const std::string& path,
|
|
|
|
const CreatureLib::Library::TypeLibrary* types,
|
2021-11-20 08:55:09 +00:00
|
|
|
const CreatureLib::Library::TalentLibrary* talentLibrary,
|
2021-08-22 10:10:26 +00:00
|
|
|
const PkmnLib::Library::MoveLibrary* moveLibrary) {
|
|
|
|
std::ifstream fileStream(path.c_str());
|
|
|
|
if (fileStream.fail()) {
|
|
|
|
std::cout << "Failed to load Pokemon data file at '" << path << "'\n";
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
auto lib = new PkmnLib::Library::SpeciesLibrary();
|
|
|
|
json j;
|
|
|
|
fileStream >> j;
|
|
|
|
|
2021-08-28 13:56:08 +00:00
|
|
|
for (const auto& it : j.items()) {
|
2021-08-22 10:10:26 +00:00
|
|
|
if (it.key().starts_with("$")) {
|
|
|
|
continue;
|
|
|
|
}
|
2021-08-28 13:56:08 +00:00
|
|
|
auto& val = it.value();
|
2021-08-22 10:10:26 +00:00
|
|
|
GET(val, id, it.key());
|
|
|
|
GET(val, species, it.key());
|
|
|
|
GET(val, genderRatio, it.key());
|
|
|
|
GET(val, growthRate, it.key());
|
|
|
|
GET(val, baseHappiness, it.key());
|
|
|
|
GET(val, catchRate, it.key());
|
|
|
|
GET(val, color, it.key());
|
|
|
|
GET(val, genderDifference, it.key());
|
|
|
|
GET(val, eggGroups, it.key());
|
|
|
|
GET(val, eggCycles, it.key());
|
|
|
|
GET(val, tags, it.key());
|
|
|
|
GET(val, formes, it.key());
|
|
|
|
|
|
|
|
PkmnLib::Library::PokemonSpecies* species = nullptr;
|
|
|
|
|
|
|
|
ArbUt::List<ArbUt::StringView> eggGroups;
|
|
|
|
for (const auto& eg : _eggGroups) {
|
|
|
|
eggGroups.Append(eg.get<std::string>().c_str());
|
|
|
|
}
|
|
|
|
|
2021-08-28 13:56:08 +00:00
|
|
|
auto& defaultForme = _formes["default"];
|
2021-08-22 10:10:26 +00:00
|
|
|
if (!defaultForme.is_null()) {
|
2021-11-20 08:55:09 +00:00
|
|
|
auto forme = BuildForme("default", defaultForme, it.key(), path, types, talentLibrary, moveLibrary);
|
2021-08-22 10:10:26 +00:00
|
|
|
species = new PkmnLib::Library::PokemonSpecies(
|
|
|
|
_id.get<uint16_t>(), ArbUt::StringView(_species.get<std::string>().c_str()), forme,
|
|
|
|
_genderRatio.get<int8_t>() / static_cast<float>(100),
|
|
|
|
ArbUt::StringView(_growthRate.get<std::string>().c_str()), _catchRate.get<uint8_t>(),
|
|
|
|
_baseHappiness.get<uint8_t>(), eggGroups);
|
|
|
|
}
|
|
|
|
|
2021-08-28 13:56:08 +00:00
|
|
|
for (const auto& formeIt : _formes.items()) {
|
2021-08-22 10:10:26 +00:00
|
|
|
if (formeIt.key() == "default") {
|
|
|
|
continue;
|
|
|
|
}
|
2021-11-20 08:55:09 +00:00
|
|
|
auto forme = BuildForme(formeIt.key(), formeIt.value(), it.key(), path, types, talentLibrary, moveLibrary);
|
2021-08-22 10:10:26 +00:00
|
|
|
if (forme == nullptr)
|
|
|
|
return nullptr;
|
|
|
|
if (species == nullptr) {
|
|
|
|
species = new PkmnLib::Library::PokemonSpecies(
|
|
|
|
_id.get<uint16_t>(), ArbUt::StringView(_species.get<std::string>().c_str()), forme,
|
|
|
|
static_cast<float>(_genderRatio.get<int8_t>()) / static_cast<float>(100),
|
|
|
|
ArbUt::StringView(_growthRate.get<std::string>().c_str()), _catchRate.get<uint8_t>(),
|
|
|
|
_baseHappiness.get<uint8_t>(), eggGroups);
|
|
|
|
} else {
|
|
|
|
if (species->HasForme(ArbUt::StringView(formeIt.key().c_str()))) {
|
|
|
|
std::cout << "Species '" << it.key() << "' has duplicate forme '" << formeIt.key()
|
|
|
|
<< "'. Skipping.\n";
|
|
|
|
delete forme;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
species->SetVariant(ArbUt::StringView(formeIt.key().c_str()), forme);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (species == nullptr) {
|
|
|
|
std::cout << "Pokemon with key '" << it.key() << "' does not have any formes.\n";
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
lib->Insert(ArbUt::StringView(it.key().c_str()), species);
|
|
|
|
}
|
|
|
|
return lib;
|
|
|
|
}
|
|
|
|
|
2021-08-28 14:52:47 +00:00
|
|
|
static CreatureLib::Library::StatisticSet<uint16_t> ParseStatistics(const json& json) {
|
|
|
|
return {json["hp"].get<uint16_t>(),
|
|
|
|
json["attack"].get<uint16_t>(),
|
|
|
|
json["defense"].get<uint16_t>(),
|
|
|
|
json["specialAttack"].get<uint16_t>(),
|
|
|
|
json["specialDefense"].get<uint16_t>(),
|
|
|
|
json["speed"].get<uint16_t>()};
|
2021-08-22 10:10:26 +00:00
|
|
|
}
|
|
|
|
|
2021-08-28 14:52:47 +00:00
|
|
|
inline void BuildLevelMove(const json& levelMoveObj, const PkmnLib::Library::MoveLibrary* moveLibrary,
|
|
|
|
PkmnLib::Library::LearnableMoves* moves) {
|
|
|
|
auto levelMoveName = levelMoveObj.at("name").get<std::string>();
|
|
|
|
auto level = levelMoveObj.at("level").get<u8>();
|
|
|
|
auto move = moveLibrary->Get(ArbUt::StringView(levelMoveName.c_str(), levelMoveName.size()));
|
|
|
|
moves->AddLevelAttack(level, move.ForceAs<const CreatureLib::Library::AttackData>());
|
|
|
|
}
|
|
|
|
|
|
|
|
const PkmnLib::Library::PokemonForme* BuildSpecies::BuildForme(const std::string& name, const json& forme,
|
2021-08-22 10:10:26 +00:00
|
|
|
const std::string& baseKeyName, const std::string& path,
|
|
|
|
const CreatureLib::Library::TypeLibrary* typeLibrary,
|
2021-11-20 08:55:09 +00:00
|
|
|
const CreatureLib::Library::TalentLibrary* talentLibrary,
|
2021-08-22 10:10:26 +00:00
|
|
|
const PkmnLib::Library::MoveLibrary* moveLibrary) {
|
2021-08-28 13:56:08 +00:00
|
|
|
GET(forme, abilities, baseKeyName + " -> " + name);
|
|
|
|
GET(forme, hiddenAbilities, baseKeyName + " -> " + name);
|
|
|
|
GET(forme, baseStats, baseKeyName + " -> " + name);
|
|
|
|
GET(forme, evReward, baseKeyName + " -> " + name);
|
|
|
|
GET(forme, types, baseKeyName + " -> " + name);
|
|
|
|
GET(forme, height, baseKeyName + " -> " + name);
|
|
|
|
GET(forme, weight, baseKeyName + " -> " + name);
|
|
|
|
GET(forme, baseExp, baseKeyName + " -> " + name);
|
|
|
|
GET(forme, moves, baseKeyName + " -> " + name);
|
2021-08-22 10:10:26 +00:00
|
|
|
|
2021-08-28 14:52:47 +00:00
|
|
|
auto types = ArbUt::List<uint8_t>(_types.size());
|
|
|
|
for (const auto& t : _types.items()) {
|
|
|
|
auto s = t.value().get<std::string>();
|
|
|
|
types.Append(typeLibrary->GetTypeId(ArbUt::StringView(s.c_str(), s.length())));
|
2021-08-22 10:10:26 +00:00
|
|
|
}
|
|
|
|
auto stats = ParseStatistics(_baseStats);
|
|
|
|
|
2021-11-20 08:55:09 +00:00
|
|
|
auto abilities = ArbUt::List<ArbUt::BorrowedPtr<const CreatureLib::Library::Talent>>(_abilities.size());
|
2021-08-28 14:52:47 +00:00
|
|
|
for (const auto& ab : _abilities.items()) {
|
|
|
|
auto s = ab.value().get<std::string>();
|
2021-11-20 08:55:09 +00:00
|
|
|
auto tryAbility = talentLibrary->TryGet(ArbUt::StringView(s.c_str(), s.length()));
|
|
|
|
if (!tryAbility.has_value())
|
|
|
|
THROW("Unknown ability " << s);
|
|
|
|
abilities.Append(tryAbility.value());
|
2021-08-22 10:10:26 +00:00
|
|
|
}
|
2021-08-28 14:52:47 +00:00
|
|
|
|
2021-11-20 08:55:09 +00:00
|
|
|
auto hiddenAbilities = ArbUt::List<ArbUt::BorrowedPtr<const CreatureLib::Library::Talent>>(_hiddenAbilities.size());
|
2021-08-28 14:52:47 +00:00
|
|
|
for (const auto& ab : _hiddenAbilities.items()) {
|
|
|
|
auto s = ab.value().get<std::string>();
|
2021-11-20 08:55:09 +00:00
|
|
|
auto tryAbility = talentLibrary->TryGet(ArbUt::StringView(s.c_str(), s.length()));
|
|
|
|
if (!tryAbility.has_value())
|
|
|
|
THROW("Unknown ability " << s);
|
|
|
|
hiddenAbilities.Append(tryAbility.value());
|
2021-08-22 10:10:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto moves = new PkmnLib::Library::LearnableMoves(100);
|
2021-08-28 13:56:08 +00:00
|
|
|
auto& movesJson = forme["moves"];
|
2021-08-28 14:52:47 +00:00
|
|
|
auto& levelMovesJson = movesJson.at("levelMoves");
|
2021-08-22 10:10:26 +00:00
|
|
|
for (auto& levelMoveObj : levelMovesJson) {
|
2021-08-28 14:52:47 +00:00
|
|
|
BuildLevelMove(levelMoveObj, moveLibrary, moves);
|
2021-08-22 10:10:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return new PkmnLib::Library::PokemonForme(ArbUt::StringView(name.c_str()), _height.get<float>(),
|
|
|
|
_weight.get<float>(), _baseExp.get<uint32_t>(), types, stats, abilities,
|
|
|
|
hiddenAbilities, moves);
|
|
|
|
}
|
|
|
|
#undef GET
|