BuildData/BuildSpecies.cpp

145 lines
7.2 KiB
C++
Raw Normal View History

#include "BuildSpecies.hpp"
#include <fstream>
#include <iostream>
#define GET(o, objectKey, key) \
auto _##objectKey = o[#objectKey]; \
if (_##objectKey.is_null()) { \
std::cout << "Failed to retrieve key '" << #objectKey << "' for object with key '" << key << "' in file '" \
<< path << "'\n"; \
return nullptr; \
}
PkmnLib::Library::SpeciesLibrary* BuildSpecies::BuildLibrary(const std::string& path,
const CreatureLib::Library::TypeLibrary* types,
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;
for (json::iterator it = j.begin(); it != j.end(); ++it) {
if (it.key().starts_with("$")) {
continue;
}
auto val = it.value();
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());
}
auto defaultForme = _formes["default"];
if (!defaultForme.is_null()) {
auto forme = BuildForme("default", defaultForme, it.key(), path, types, moveLibrary);
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);
}
for (json::iterator formeIt = _formes.begin(); formeIt != _formes.end(); ++formeIt) {
if (formeIt.key() == "default") {
continue;
}
auto forme = BuildForme(formeIt.key(), formeIt.value(), it.key(), path, types, moveLibrary);
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;
}
static CreatureLib::Library::StatisticSet<uint16_t> ParseStatistics(json& json) {
return CreatureLib::Library::StatisticSet<uint16_t>(
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>());
}
const PkmnLib::Library::PokemonForme* BuildSpecies::BuildForme(const std::string& name, json& forme,
const std::string& baseKeyName, const std::string& path,
const CreatureLib::Library::TypeLibrary* typeLibrary,
const PkmnLib::Library::MoveLibrary* moveLibrary) {
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);
auto typeStrings = _types.get<std::vector<std::string>>();
auto types = ArbUt::List<uint8_t>(typeStrings.size());
for (size_t i = 0; i < typeStrings.size(); i++) {
types.Append(typeLibrary->GetTypeId(ArbUt::StringView(typeStrings[i].c_str())));
}
auto stats = ParseStatistics(_baseStats);
auto abilityStrings = _abilities.get<std::vector<std::string>>();
auto abilities = ArbUt::List<ArbUt::StringView>(abilityStrings.size());
for (size_t i = 0; i < abilityStrings.size(); i++) {
abilities.Append(ArbUt::StringView(abilityStrings[i].c_str()));
}
auto hiddenAbilityStrings = _abilities.get<std::vector<std::string>>();
auto hiddenAbilities = ArbUt::List<ArbUt::StringView>(hiddenAbilityStrings.size());
for (size_t i = 0; i < hiddenAbilityStrings.size(); i++) {
hiddenAbilities.Append(ArbUt::StringView(abilityStrings[i].c_str()));
}
auto moves = new PkmnLib::Library::LearnableMoves(100);
auto movesJson = forme["moves"];
auto levelMovesJson = movesJson["levelMoves"];
for (auto& levelMoveObj : levelMovesJson) {
auto levelMoveName = levelMoveObj["name"].get<std::string>();
auto level = levelMoveObj["level"].get<u8>();
auto move = moveLibrary->Get(ArbUt::StringView(levelMoveName.c_str(), levelMoveName.size()));
moves->AddLevelAttack(level, move.ForceAs<const CreatureLib::Library::AttackData>());
}
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