PkmnLib/src/Battling/Pokemon/CreatePokemon.cpp

166 lines
6.8 KiB
C++

#include "CreatePokemon.hpp"
namespace PkmnLib::Battling {
CreatePokemon& CreatePokemon::WithRandomIndividualValues(ArbUt::Random& rand) {
_ivHp = rand.Get(0, 32);
_ivAttack = rand.Get(0, 32);
_ivDefense = rand.Get(0, 32);
_ivSpAtt = rand.Get(0, 32);
_ivSpDef = rand.Get(0, 32);
_ivSpeed = rand.Get(0, 32);
return *this;
}
CreatePokemon& CreatePokemon::WithIndividualValue(CreatureLib::Library::Statistic stat, u8 value) {
switch (stat) {
case PkmnLib::Library::Statistic::HealthPoints: _ivHp = value; break;
case PkmnLib::Library::Statistic::PhysicalAttack: _ivAttack = value; break;
case PkmnLib::Library::Statistic::PhysicalDefense: _ivDefense = value; break;
case PkmnLib::Library::Statistic::SpecialAttack: _ivSpAtt = value; break;
case PkmnLib::Library::Statistic::SpecialDefense: _ivSpDef = value; break;
case PkmnLib::Library::Statistic::Speed: _ivSpeed = value; break;
}
return *this;
}
CreatePokemon& CreatePokemon::WithEffortValue(CreatureLib::Library::Statistic stat, u8 value) {
switch (stat) {
case PkmnLib::Library::Statistic::HealthPoints: _evHp = value; break;
case PkmnLib::Library::Statistic::PhysicalAttack: _evAttack = value; break;
case PkmnLib::Library::Statistic::PhysicalDefense: _evDefense = value; break;
case PkmnLib::Library::Statistic::SpecialAttack: _evSpAtt = value; break;
case PkmnLib::Library::Statistic::SpecialDefense: _evSpDef = value; break;
case PkmnLib::Library::Statistic::Speed: _evSpeed = value; break;
}
return *this;
}
Pokemon* CreatePokemon::Build(ArbUt::Random& rand) {
auto species = this->_library->GetSpeciesLibrary()->TryGet(this->_species);
if (!species.has_value()) {
std::stringstream err;
err << "Invalid species '" << _species << "'.";
throw ArbUt::Exception(err.str());
}
auto forme = species.value()->TryGetForme(this->_forme);
if (!forme.has_value()) {
std::stringstream err;
err << "Invalid forme '" << _forme << "' for species '" << _forme << "'.";
throw ArbUt::Exception(err.str());
}
CreatureLib::Library::TalentIndex ability;
if (this->_ability.IsEmpty()) {
ability = forme.value()->GetRandomTalent(rand);
} else {
ability = forme.value()->GetTalentIndex(this->_ability);
}
auto identifier = this->_identifier;
if (identifier == 0) {
identifier = rand.GetUnsigned();
}
auto gender = this->_gender;
if (gender == static_cast<CreatureLib::Library::Gender>(-1)) {
gender = species.value()->GetRandomGender(rand);
}
ArbUt::OptionalBorrowedPtr<const Library::Item> heldItem = nullptr;
if (!this->_heldItem.IsEmpty()) {
auto item = _library->GetItemLibrary()->TryGet(this->_heldItem);
if (!item.has_value()) {
THROW("Unknown Item: ", this->_heldItem.std_str());
}
heldItem = item.value();
}
auto experience =
_library->GetGrowthRateLibrary()->CalculateExperience(species.value()->GetGrowthRate(), _level);
auto attacks = std::vector<CreatureLib::Battling::LearnedAttack*>(_attacks.Count());
for (size_t i = 0; i < _attacks.Count(); i++) {
auto& kv = _attacks[i];
auto move = kv.Move;
if (move.HasValue()) {
attacks[i] = new LearnedMove(move.GetValue(), kv.LearnMethod);
}
}
auto ivs = CreatureLib::Library::ClampedStatisticSet<u8, 0, 31>(_ivHp, _ivAttack, _ivDefense, _ivSpAtt,
_ivSpDef, _ivSpeed);
auto evs = CreatureLib::Library::ClampedStatisticSet<u8, 0, 252>(_evHp, _evAttack, _evDefense, _evSpAtt,
_evSpDef, _evSpeed);
if (_nature.IsEmpty()) {
_nature = _library->GetNatureLibrary()->GetRandomNatureName(rand);
}
auto nature = _library->GetNatureLibrary()->GetNatureByName(_nature);
auto shiny = false;
if (_shininessSet) {
shiny = _isShiny;
} else {
shiny = rand.Get(_library->GetSettings()->GetShinyRate()) == 0;
}
auto pkmn = new Pokemon(_library, species.value(), forme.value(), _level, experience, identifier, gender, shiny,
heldItem, _nickname, ability, attacks, ivs, evs, nature, _allowedExperienceGain);
pkmn->Initialize();
return pkmn;
}
CreatePokemon& CreatePokemon::WithNature(const ArbUt::StringView& nature) {
_nature = nature;
return *this;
}
CreatePokemon& CreatePokemon::WithIndividualValues(u8 hp, u8 att, u8 def, u8 spAtt, u8 spDef, u8 speed) {
_ivHp = hp;
_ivAttack = att;
_ivDefense = def;
_ivSpAtt = spAtt;
_ivSpDef = spDef;
_ivSpeed = speed;
return *this;
}
CreatePokemon& CreatePokemon::WithEffortValues(u8 hp, u8 att, u8 def, u8 spAtt, u8 spDef, u8 speed) {
_evHp = hp;
_evAttack = att;
_evDefense = def;
_evSpAtt = spAtt;
_evSpDef = spDef;
_evSpeed = speed;
return *this;
}
CreatePokemon& CreatePokemon::WithForme(const ArbUt::StringView& forme) {
_forme = forme;
return *this;
}
CreatePokemon& CreatePokemon::WithGender(CreatureLib::Library::Gender gender) {
_gender = gender;
return *this;
}
CreatePokemon& CreatePokemon::IsShiny(bool value) {
_shininessSet = true;
_isShiny = value;
return *this;
}
CreatePokemon& CreatePokemon::WithHeldItem(const ArbUt::StringView& item) {
_heldItem = item;
return *this;
}
CreatePokemon& CreatePokemon::LearnMove(const ArbUt::StringView& moveName,
CreatureLib::Battling::AttackLearnMethod method) {
auto v = _library->GetMoveLibrary()->TryGet(moveName);
if (!v.has_value()) {
THROW("Invalid Move given: ", moveName.std_str());
}
if (_currentMove >= _library->GetSettings()->GetMaximalAttacks()) {
throw ArbUt::Exception("This pokemon already has the maximal allowed moves.");
}
_attacks.Append(ToLearnMethod(v.value(), method));
return *this;
}
CreatePokemon& CreatePokemon::IsAllowedExperienceGain(bool value) {
_allowedExperienceGain = value;
return *this;
}
CreatePokemon& CreatePokemon::WithNickname(const std::string& nickname) {
_nickname = nickname;
return *this;
}
}