102 lines
4.4 KiB
C++
102 lines
4.4 KiB
C++
#include "Pokemon.hpp"
|
|
#include <CreatureLib/Battling/Models/Battle.hpp>
|
|
#include "../EventHooks/CaptureAttemptEvent.hpp"
|
|
#include "../PkmnScriptCategory.hpp"
|
|
|
|
void PkmnLib::Battling::Pokemon::Evolve(ArbUt::BorrowedPtr<const Library::PokemonSpecies> mon,
|
|
ArbUt::BorrowedPtr<const Library::PokemonForme> forme) {
|
|
// Set species and variant
|
|
_species = mon.ForceAs<const CreatureLib::Library::CreatureSpecies>();
|
|
ChangeVariant(forme.ForceAs<const CreatureLib::Library::SpeciesVariant>());
|
|
|
|
// If the pokemon is genderless, but it's new evolution is not, we want to set its gender
|
|
if (_gender != CreatureLib::Library::Gender::Genderless && _species->GetGenderRate() != -1) {
|
|
// If we are currently in battle, use the battle random so we can get predictable events.
|
|
if (_battleData.Battle.HasValue()) {
|
|
_gender = _species->GetRandomGender(_battleData.Battle.GetValue()->GetRandom()->GetRNG());
|
|
}
|
|
// Else create a new random.
|
|
else {
|
|
ArbUt::Random rand;
|
|
_gender = _species->GetRandomGender(rand);
|
|
}
|
|
// Else if the new pokemon species is genderless, but the pokemon has a gender, make the Pokemon genderless.
|
|
} else if (_species->GetGenderRate() == -1 && _gender != CreatureLib::Library::Gender::Genderless) {
|
|
_gender = CreatureLib::Library::Gender::Genderless;
|
|
}
|
|
// TODO: Learn moves?
|
|
// TODO: Event hook
|
|
}
|
|
|
|
CreatureLib::Battling::Creature* PkmnLib::Battling::Pokemon::Clone() const {
|
|
auto moves = std::vector<CreatureLib::Battling::LearnedAttack*>(_attacks.Count());
|
|
auto i = 0;
|
|
for (auto* attack : _attacks) {
|
|
if (attack == nullptr) {
|
|
moves[i++] = nullptr;
|
|
} else {
|
|
moves[i++] = dynamic_cast<LearnedMove*>(attack->Clone());
|
|
}
|
|
}
|
|
|
|
auto* c = new Pokemon(_library.ForceAs<const BattleLibrary>(), _species.ForceAs<const Library::PokemonSpecies>(),
|
|
_variant.ForceAs<const Library::PokemonForme>(), _level, _experience, _uniqueIdentifier,
|
|
_gender, _coloring, _heldItem.ForceAs<const Library::Item>(), _nickname, _talentIndex, moves,
|
|
_individualValues, _effortValues, _nature, _allowedExperienceGain);
|
|
c->_displaySpecies = _displaySpecies;
|
|
c->_displayVariant = _displayVariant;
|
|
c->_currentHealth = _currentHealth;
|
|
c->_statBoost = _statBoost;
|
|
c->_flatStats = _flatStats;
|
|
c->_boostedStats = _boostedStats;
|
|
c->_battleData.Battle = _battleData.Battle;
|
|
c->_battleData.Side = _battleData.Side;
|
|
c->_battleData.OnBattleField = _battleData.OnBattleField;
|
|
c->_battleData.Index = _battleData.Index;
|
|
if (_activeTalent != nullptr) {
|
|
c->_activeTalent = std::unique_ptr<PkmnScript::BattleScript>(_activeTalent->Clone(c));
|
|
}
|
|
c->_hasOverridenTalent = _hasOverridenTalent;
|
|
c->_overridenTalent = _overridenTalent;
|
|
if (_status != nullptr) {
|
|
c->_status = std::unique_ptr<PkmnScript::BattleScript>(_status->Clone(c));
|
|
}
|
|
_volatile.Clone(c, c->_volatile);
|
|
c->_types = std::vector<u8>(_types);
|
|
c->_friendship = _friendship;
|
|
c->RecalculateFlatStats();
|
|
|
|
return c;
|
|
}
|
|
bool PkmnLib::Battling::Pokemon::IsUsable() const noexcept {
|
|
if (IsEgg()) {
|
|
return false;
|
|
}
|
|
if (_wasCaught) {
|
|
return false;
|
|
}
|
|
return Creature::IsUsable();
|
|
}
|
|
void PkmnLib::Battling::Pokemon::AttemptCapture(PkmnLib::Library::Item* catchItem) {
|
|
Ensure(_battleData.OnBattleField);
|
|
Ensure(_battleData.Battle.HasValue());
|
|
Ensure(_battleData.Side.HasValue());
|
|
Ensure(!IsFainted());
|
|
Ensure(IsUsable());
|
|
Ensure(!GetBattleSide().GetValue()->IsSlotUnfillabe(this)) auto captureLibrary =
|
|
GetLibrary().ForceAs<const BattleLibrary>()->GetCaptureLibrary();
|
|
auto result = captureLibrary->TryCatch(this, catchItem, _battleData.Battle.GetValue()->GetRandom());
|
|
_battleData.Battle.GetValue()->TriggerEventListener<CaptureAttemptEvent>(this, result);
|
|
|
|
if (result.WasCaught) {
|
|
// By marking the pokemon as caught, it becomes no longer usable for switch in.
|
|
_wasCaught = true;
|
|
// As the pokemon is caught now, we replace it with an empty space.
|
|
_battleData.Side.GetValue()->SetCreature(nullptr, _battleData.Index.GetCreatureIndex());
|
|
}
|
|
}
|
|
void PkmnLib::Battling::Pokemon::ClearBattleData() noexcept {
|
|
Creature::ClearBattleData();
|
|
_wasCaught = false;
|
|
}
|