Set up standard functions for building tools

This commit is contained in:
Deukhoofd 2021-08-22 12:10:26 +02:00
commit e69eacaa9b
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
13 changed files with 698 additions and 0 deletions

101
BuildItems.cpp Normal file
View File

@ -0,0 +1,101 @@
#include "BuildItems.hpp"
#include <fstream>
#include <iostream>
#include "../../extern/json.hpp"
using json = nlohmann::json;
#define GET(o, objectKey, key) \
auto _##objectKey = o[#objectKey]; \
if (_##objectKey.is_null()) { \
std::cout << "Failed to retrieve key '" << #objectKey << "' for object with value '" << key << "' in file '" \
<< path << "'\n"; \
return nullptr; \
}
static CreatureLib::Library::ItemCategory ParseItemCategory(std::string& in) {
std::transform(in.begin(), in.end(), in.end(), tolower);
if (in == "item")
return CreatureLib::Library::ItemCategory::MiscItem;
if (in == "medicine")
return CreatureLib::Library::ItemCategory::Medicine;
if (in == "berry")
return CreatureLib::Library::ItemCategory::Berry;
if (in == "mail")
return CreatureLib::Library::ItemCategory::Mail;
if (in == "key")
return CreatureLib::Library::ItemCategory::KeyItem;
if (in == "pokeball")
return CreatureLib::Library::ItemCategory::CaptureDevice;
if (in == "tm")
return CreatureLib::Library::ItemCategory::MoveLearner;
std::cout << "Unknown Item Type: '" << in << "'\n";
return static_cast<CreatureLib::Library::ItemCategory>(255);
}
PkmnLib::Library::ItemLibrary* BuildItems::Build(const std::string& path) {
std::ifstream fileStream(path.c_str());
if (fileStream.fail()) {
std::cout << "Failed to load Items data file at '" << path << "'\n";
return nullptr;
}
auto lib = new PkmnLib::Library::ItemLibrary();
json j;
fileStream >> j;
for (const auto& i : j.items()) {
if (i.key().starts_with("$")) {
continue;
}
auto val = i.value();
GET(val, name, i);
GET(val, itemType, i);
GET(val, flags, i);
GET(val, price, i);
GET(val, flingPower, i);
auto itemTypeStr = _itemType.get<std::string>();
CreatureLib::Library::ItemCategory itemType = ParseItemCategory(itemTypeStr);
if (static_cast<int>(itemType) == 255)
return nullptr;
auto flags = std::unordered_set<uint>();
for (auto flagIndex : _flags.items()) {
flags.insert(ArbUt::StringView(flagIndex.value().get<std::string>().c_str()));
}
CreatureLib::Library::SecondaryEffect* effect = nullptr;
auto effectJson = val["effect"];
if (effectJson != nullptr) {
auto effectName = effectJson["name"];
auto parametersJson = effectJson["parameters"];
ArbUt::List<CreatureLib::Library::EffectParameter*> parameters;
if (parametersJson != nullptr) {
for (auto& kv : parametersJson.items()) {
auto& p = kv.value();
auto t = p.type();
switch (t) {
case json::value_t::boolean:
parameters.Append(new CreatureLib::Library::EffectParameter(p.get<bool>()));
break;
case json::value_t::number_integer:
case json::value_t::number_unsigned:
parameters.Append(new CreatureLib::Library::EffectParameter(p.get<int64_t>()));
break;
case json::value_t::number_float:
parameters.Append(new CreatureLib::Library::EffectParameter(p.get<float>()));
break;
default: continue;
}
}
}
effect = new CreatureLib::Library::SecondaryEffect(
100, ArbUt::StringView(effectName.get<std::string>().c_str()), parameters);
}
auto item = new PkmnLib::Library::Item(ArbUt::StringView(_name.get<std::string>().c_str()), itemType,
CreatureLib::Library::BattleItemCategory::None, _price.get<int32_t>(),
effect, flags, _flingPower.get<uint8_t>());
lib->Insert(item->GetName(), item);
}
return lib;
}
#undef GET

10
BuildItems.hpp Normal file
View File

@ -0,0 +1,10 @@
#ifndef GEN7TESTS_BUILDITEMS_HPP
#define GEN7TESTS_BUILDITEMS_HPP
#include <PkmnLib/Library/Items/ItemLibrary.hpp>
class BuildItems {
public:
static PkmnLib::Library::ItemLibrary* Build(const std::string& path);
};
#endif // GEN7TESTS_BUILDITEMS_HPP

61
BuildLibrary.hpp Normal file
View File

@ -0,0 +1,61 @@
#ifndef PKMNLIB_AI_BUILDLIBRARY_HPP
#define PKMNLIB_AI_BUILDLIBRARY_HPP
#include <PkmnLib/Battling/Library/BattleLibrary.hpp>
#include <filesystem>
#include "BuildMoves.hpp"
#include "BuildNatures.hpp"
#include "BuildSpecies.hpp"
#include "BuildTypes.hpp"
#include "GrowthRatesBuilder.hpp"
class BuildLibrary {
static PkmnLib::Library::TimeOfDay GetTime() { return PkmnLib::Library::TimeOfDay::Morning; }
public:
static PkmnLib::Battling::BattleLibrary* Build(const std::string& pathString) {
auto path = std::filesystem::path(pathString);
auto* typesLibrary = BuildTypes::Build(path / "Types.csv");
auto* natureLibrary = BuildNatures::Build(path / "Natures.csv");
auto* movesLibrary = BuildMoves::Build(path / "Moves.json", typesLibrary);
auto* speciesLibrary = BuildSpecies::BuildLibrary(path / "Pokemon.json", typesLibrary, movesLibrary);
auto* itemsLibrary = BuildItems::Build(path / "Items.json");
auto* growthRates = GrowthRatesBuilder::Build(path / "GrowthRates.json");
auto scriptsPath = path / "Scripts";
if (typesLibrary == nullptr || speciesLibrary == nullptr || natureLibrary == nullptr ||
movesLibrary == nullptr || itemsLibrary == nullptr || growthRates == nullptr) {
return nullptr;
}
auto settings = new PkmnLib::Library::LibrarySettings(100, 4, 4096);
auto staticLibrary = new PkmnLib::Library::PokemonLibrary(settings, speciesLibrary, movesLibrary, itemsLibrary,
growthRates, typesLibrary, natureLibrary);
auto scriptResolver = PkmnLib::Battling::BattleLibrary::CreateScriptResolver();
auto battleLib = new PkmnLib::Battling::BattleLibrary(
staticLibrary, new PkmnLib::Battling::StatCalculator(), new PkmnLib::Battling::DamageLibrary(),
new PkmnLib::Battling::ExperienceLibrary(), scriptResolver, new PkmnLib::Battling::MiscLibrary(GetTime));
scriptResolver->Initialize(battleLib);
auto asScriptResolver = dynamic_cast<AngelScriptResolver*>(scriptResolver);
for (const auto& dirEntry : std::filesystem::recursive_directory_iterator(scriptsPath)) {
if (dirEntry.is_directory())
continue;
if (dirEntry.path().parent_path().stem() == "Interfaces")
continue;
if (dirEntry.path().extension() != ".as")
continue;
std::ifstream in(dirEntry.path());
std::string contents((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
asScriptResolver->CreateScript(dirEntry.path().c_str(), contents.c_str());
}
asScriptResolver->FinalizeModule();
return battleLib;
}
};
#endif // PKMNLIB_AI_BUILDLIBRARY_HPP

113
BuildMoves.cpp Normal file
View File

@ -0,0 +1,113 @@
#include "BuildMoves.hpp"
#include <fstream>
#include <iostream>
#include "../../extern/json.hpp"
using json = nlohmann::json;
#define GET(o, objectKey, key) \
auto _##objectKey = o[#objectKey]; \
if (_##objectKey.is_null()) { \
std::cout << "Failed to retrieve key '" << #objectKey << "' for object with value '" << key << "' in file '" \
<< path << "'\n"; \
return nullptr; \
}
static PkmnLib::Library::MoveCategory ParseCategory(const std::string& input) {
if (input == "physical")
return PkmnLib::Library::MoveCategory::Physical;
else if (input == "special")
return PkmnLib::Library::MoveCategory::Special;
else if (input == "status")
return PkmnLib::Library::MoveCategory::Status;
std::cout << "Invalid move category '" << input << ".\n";
return static_cast<PkmnLib::Library::MoveCategory>(255);
}
PkmnLib::Library::MoveLibrary* BuildMoves::Build(const std::string& path,
const CreatureLib::Library::TypeLibrary* types) {
std::ifstream fileStream(path.c_str());
if (fileStream.fail()) {
std::cout << "Failed to load Move data file at '" << path << "'\n";
return nullptr;
}
auto lib = new PkmnLib::Library::MoveLibrary();
json j;
fileStream >> j;
for (const auto& i : j["data"].items()) {
auto val = i.value();
GET(val, name, i);
GET(val, type, i);
GET(val, power, i);
GET(val, pp, i);
GET(val, accuracy, i);
GET(val, priority, i);
GET(val, target, i);
GET(val, category, i);
GET(val, flags, i);
if (_pp.get<uint8_t>() == 0)
continue;
auto type = types->GetTypeId(ArbUt::StringView(_type.get<std::string>().c_str()));
auto category = ParseCategory(_category.get<std::string>());
if (static_cast<int>(category) == 255)
return nullptr;
CreatureLib::Library::AttackTarget target;
if (!CreatureLib::Library::AttackTargetHelper::TryParse(_target.get<std::string>().c_str(), target)) {
std::cout << "Invalid target: '" << _target.get<std::string>() << "' for move with name '"
<< _name.get<std::string>() << "'\n";
return nullptr;
}
auto flags = std::unordered_set<uint32_t>();
for (auto flagIndex : _flags.items()) {
flags.insert(ArbUt::StringView(flagIndex.value().get<std::string>().c_str()));
}
CreatureLib::Library::SecondaryEffect* effect = nullptr;
auto jsonEffect = val["effect"];
if (jsonEffect != nullptr) {
auto name = jsonEffect["name"];
auto chanceJson = jsonEffect["chance"];
auto parametersJson = jsonEffect["parameters"];
if (name != nullptr) {
ArbUt::List<CreatureLib::Library::EffectParameter*> parameters;
auto chance = -1.0f;
if (chanceJson != nullptr) {
chance = chanceJson.get<float>();
}
if (parametersJson != nullptr) {
for (auto& kv : parametersJson.items()) {
auto& p = kv.value();
auto t = p.type();
switch (t) {
case json::value_t::boolean:
parameters.Append(new CreatureLib::Library::EffectParameter(p.get<bool>()));
break;
case json::value_t::number_integer:
case json::value_t::number_unsigned:
parameters.Append(new CreatureLib::Library::EffectParameter(p.get<int64_t>()));
break;
case json::value_t::number_float:
parameters.Append(new CreatureLib::Library::EffectParameter(p.get<float>()));
break;
default: continue;
}
}
}
effect = new CreatureLib::Library::SecondaryEffect(
chance, ArbUt::StringView(name.get<std::string>().c_str()), parameters);
}
}
if (effect == nullptr) {
effect = new CreatureLib::Library::SecondaryEffect();
}
auto move = new PkmnLib::Library::MoveData(ArbUt::StringView(_name.get<std::string>().c_str()), type, category,
_power.get<uint8_t>(), _accuracy.get<uint8_t>(), _pp.get<uint8_t>(),
target, _priority.get<int8_t>(), effect, flags);
lib->Insert(ArbUt::StringView(move->GetName().c_str()), move);
}
return lib;
}
#undef GET

11
BuildMoves.hpp Normal file
View File

@ -0,0 +1,11 @@
#ifndef GEN7TESTS_BUILDMOVES_HPP
#define GEN7TESTS_BUILDMOVES_HPP
#include <CreatureLib/Library/TypeLibrary.hpp>
#include <PkmnLib/Library/Moves/MoveLibrary.hpp>
class BuildMoves {
public:
static PkmnLib::Library::MoveLibrary* Build(const std::string& path, const CreatureLib::Library::TypeLibrary* types);
};
#endif // GEN7TESTS_BUILDMOVES_HPP

86
BuildNatures.cpp Normal file
View File

@ -0,0 +1,86 @@
#include "BuildNatures.hpp"
#include <cstring>
#include <fstream>
#include <iostream>
static CreatureLib::Library::Statistic ParseStatistic(const std::string& stat) {
if (stat.empty())
return static_cast<CreatureLib::Library::Statistic>(255);
if (stat == "Attack")
return CreatureLib::Library::Statistic::PhysicalAttack;
if (stat == "Defense")
return CreatureLib::Library::Statistic::PhysicalDefense;
if (stat == "SpecialAttack")
return CreatureLib::Library::Statistic::MagicalAttack;
if (stat == "SpecialDefense")
return CreatureLib::Library::Statistic::MagicalDefense;
if (stat == "Speed")
return CreatureLib::Library::Statistic::Speed;
std::cout << "Invalid stat was given: '" << stat << "'.\n";
return static_cast<CreatureLib::Library::Statistic>(254);
}
PkmnLib::Library::NatureLibrary* BuildNatures::Build(const std::string& path) {
std::ifstream file(path);
if (file.fail()) {
std::cout << "Failed to load Natures data file at '" << path << "'\n";
return nullptr;
}
std::string line;
if (!std::getline(file, line)) {
std::cout << "Failed to read Natures data file at '" << path << "'\n";
return nullptr;
}
auto divider = ',';
if (strncmp(line.c_str(), "sep=", 4) == 0) {
divider = line[4];
std::getline(file, line);
}
auto library = new PkmnLib::Library::NatureLibrary();
std::string substr;
while (std::getline(file, line)) {
size_t lastStart = 0;
uint8_t current = 0;
std::string natureName;
std::string increasedStat;
std::string decreasedStat;
for (size_t i = 0; i < line.length(); i++) {
if (line[i] == divider) {
switch (current) {
case 0: natureName = line.substr(lastStart, i - lastStart); break;
case 1: increasedStat = line.substr(lastStart, i - lastStart); break;
case 2: decreasedStat = line.substr(lastStart, i - lastStart); break;
default:
std::cout << "Unknown field in nature data: '" << line.substr(lastStart, i - lastStart)
<< "'.\n";
return nullptr;
}
lastStart = i + 1;
current++;
}
}
if (current == 2)
decreasedStat = line.substr(lastStart, line.length() - lastStart);
auto parsedIncreased = ParseStatistic(increasedStat);
float increasedModifier = 1.1;
if (static_cast<int>(parsedIncreased) == 254)
return nullptr;
if (static_cast<int>(parsedIncreased) == 255)
increasedModifier = 1.0;
auto parsedDecreased = ParseStatistic(decreasedStat);
float decreasedModifier = 0.9;
if (static_cast<int>(parsedDecreased) == 254)
return nullptr;
if (static_cast<int>(parsedDecreased) == 255)
decreasedModifier = 1.0;
library->LoadNature(
ArbUt::StringView(natureName.c_str()),
new PkmnLib::Library::Nature(parsedIncreased, parsedDecreased, increasedModifier, decreasedModifier));
}
return library;
}

10
BuildNatures.hpp Normal file
View File

@ -0,0 +1,10 @@
#ifndef GEN7TESTS_BUILDNATURES_HPP
#define GEN7TESTS_BUILDNATURES_HPP
#include <PkmnLib/Library/Natures/NatureLibrary.hpp>
class BuildNatures {
public:
static PkmnLib::Library::NatureLibrary* Build(const std::string& path);
};
#endif // GEN7TESTS_BUILDNATURES_HPP

145
BuildSpecies.cpp Normal file
View File

@ -0,0 +1,145 @@
#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

22
BuildSpecies.hpp Normal file
View File

@ -0,0 +1,22 @@
#ifndef GEN7TESTS_BUILDSPECIES_HPP
#define GEN7TESTS_BUILDSPECIES_HPP
#define LEVEL_U8 1
#include <CreatureLib/Library/TypeLibrary.hpp>
#include <PkmnLib/Library/PokemonLibrary.hpp>
#include <string>
#include "../../extern/json.hpp"
using json = nlohmann::json;
class BuildSpecies {
static const PkmnLib::Library::PokemonForme* 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);
public:
static PkmnLib::Library::SpeciesLibrary* BuildLibrary(const std::string& path,
const CreatureLib::Library::TypeLibrary* types,
const PkmnLib::Library::MoveLibrary* moveLibrary);
};
#endif // GEN7TESTS_BUILDSPECIES_HPP

68
BuildTypes.cpp Normal file
View File

@ -0,0 +1,68 @@
#include "BuildTypes.hpp"
CreatureLib::Library::TypeLibrary* BuildTypes::Build(const std::string& path) {
std::ifstream file(path);
if (file.fail()) {
std::cout << "Failed to load Types data file at '" << path << "'\n";
return nullptr;
}
std::string line;
if (!std::getline(file, line)) {
std::cout << "Failed to read Types data file at '" << path << "'\n";
return nullptr;
}
auto divider = ',';
if (strncmp(line.c_str(), "sep=", 4) == 0) {
divider = line[4];
std::getline(file, line);
}
auto* library = new CreatureLib::Library::TypeLibrary();
bool hasSkippedFirst = false;
size_t lastStart = 0;
std::vector<uint8_t> types;
for (size_t i = 0; i < line.length(); i++) {
if (line[i] == divider) {
auto substr = line.substr(lastStart, i - lastStart);
lastStart = i + 1;
if (hasSkippedFirst) {
auto val = library->RegisterType(ArbUt::StringView(substr.c_str()));
types.push_back(val);
} else {
hasSkippedFirst = true;
}
i++;
}
}
auto substr = line.substr(lastStart, line.length() - lastStart);
auto val = library->RegisterType(ArbUt::StringView(substr.c_str()));
types.push_back(val);
while (std::getline(file, line)) {
uint8_t attackingType = 0;
bool gotType = false;
lastStart = 0;
int current = 0;
for (size_t i = 0; i < line.length(); i++) {
if (line[i] == divider) {
substr = line.substr(lastStart, i - lastStart);
lastStart = i + 1;
if (gotType) {
auto eff = std::atof(substr.c_str());
library->SetEffectiveness(attackingType, types[current], eff);
current++;
} else {
gotType = true;
attackingType = library->GetTypeId(ArbUt::StringView(substr.c_str()));
}
i++;
}
}
substr = line.substr(lastStart, line.length() - lastStart);
auto eff = std::atof(substr.c_str());
library->SetEffectiveness(attackingType, types[current], eff);
}
return library;
}

13
BuildTypes.hpp Normal file
View File

@ -0,0 +1,13 @@
#ifndef GEN7TESTS_BUILDTYPES_HPP
#define GEN7TESTS_BUILDTYPES_HPP
#include <CreatureLib/Library/TypeLibrary.hpp>
#include <cstring>
#include <fstream>
#include <iostream>
class BuildTypes {
public:
static CreatureLib::Library::TypeLibrary* Build(const std::string& path);
};
#endif // GEN7TESTS_BUILDTYPES_HPP

25
GrowthRatesBuilder.cpp Normal file
View File

@ -0,0 +1,25 @@
#include "GrowthRatesBuilder.hpp"
#include <fstream>
#include <iostream>
#include "../../extern/json.hpp"
using json = nlohmann::json;
CreatureLib::Library::GrowthRateLibrary* GrowthRatesBuilder::Build(const std::string& path) {
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 CreatureLib::Library::GrowthRateLibrary();
json j;
fileStream >> j;
for (const auto& i : j.items()) {
const auto& name = i.key();
auto values = i.value();
lib->AddGrowthRate(ArbUt::StringView(name.c_str()),
new LookupGrowthRate(values.get<std::vector<uint32_t>>()));
}
return lib;
}

33
GrowthRatesBuilder.hpp Normal file
View File

@ -0,0 +1,33 @@
#ifndef GEN7TESTS_GROWTHRATESBUILDER_HPP
#define GEN7TESTS_GROWTHRATESBUILDER_HPP
#define LEVEL_U8 1
#include <CreatureLib/Library/GrowthRates/GrowthRate.hpp>
#include <CreatureLib/Library/GrowthRates/GrowthRateLibrary.hpp>
#include <utility>
#include <vector>
class LookupGrowthRate : public CreatureLib::Library::GrowthRate {
std::vector<uint32_t> _experience;
public:
LookupGrowthRate(std::vector<uint32_t> experience) : _experience(std::move(experience)) {}
[[nodiscard]] uint8_t CalculateLevel(uint32_t experience) const override {
for (size_t i = 0; i < _experience.size(); i++) {
if (_experience[i] > experience) {
return i;
}
}
return _experience[_experience.size() - 1];
}
[[nodiscard]] uint32_t CalculateExperience(uint8_t level) const override { return _experience[level - 1]; }
};
class GrowthRatesBuilder {
public:
static CreatureLib::Library::GrowthRateLibrary* Build(const std::string& file);
};
#endif // GEN7TESTS_GROWTHRATESBUILDER_HPP