#include "BuildSpecies.hpp" #include #include #define GET(o, objectKey, key) \ auto& _##objectKey = o[#objectKey]; \ if (_##objectKey.is_null()) { \ auto errorKeyFunc = [=]() { return key; }; \ std::cout << "Failed to retrieve key '" << #objectKey << "' for object with key '" << errorKeyFunc() \ << "' 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 (const auto& it : j.items()) { 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 eggGroups; for (const auto& eg : _eggGroups) { eggGroups.Append(eg.get().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(), ArbUt::StringView(_species.get().c_str()), forme, _genderRatio.get() / static_cast(100), ArbUt::StringView(_growthRate.get().c_str()), _catchRate.get(), _baseHappiness.get(), eggGroups); } for (const auto& formeIt : _formes.items()) { 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(), ArbUt::StringView(_species.get().c_str()), forme, static_cast(_genderRatio.get()) / static_cast(100), ArbUt::StringView(_growthRate.get().c_str()), _catchRate.get(), _baseHappiness.get(), 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 ParseStatistics(json& json) { return CreatureLib::Library::StatisticSet( json["hp"].get(), json["attack"].get(), json["defense"].get(), json["specialAttack"].get(), json["specialDefense"].get(), json["speed"].get()); } 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>(); auto types = ArbUt::List(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>(); auto abilities = ArbUt::List(abilityStrings.size()); for (size_t i = 0; i < abilityStrings.size(); i++) { abilities.Append(ArbUt::StringView(abilityStrings[i].c_str())); } auto hiddenAbilityStrings = _hiddenAbilities.get>(); auto hiddenAbilities = ArbUt::List(hiddenAbilityStrings.size()); for (size_t i = 0; i < hiddenAbilityStrings.size(); i++) { hiddenAbilities.Append(ArbUt::StringView(hiddenAbilityStrings[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(); auto level = levelMoveObj["level"].get(); auto move = moveLibrary->Get(ArbUt::StringView(levelMoveName.c_str(), levelMoveName.size())); moves->AddLevelAttack(level, move.ForceAs()); } return new PkmnLib::Library::PokemonForme(ArbUt::StringView(name.c_str()), _height.get(), _weight.get(), _baseExp.get(), types, stats, abilities, hiddenAbilities, moves); } #undef GET