PkmnLib/src/Battling/Pokemon/Pokemon.cpp

108 lines
4.6 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.HasValue()) {
c->_activeTalent = _activeTalent.GetValue()->Clone(c);
}
c->_hasOverridenTalent = _hasOverridenTalent;
c->_overridenTalent = _overridenTalent;
if (_status.HasValue()) {
c->_status = _status.GetValue()->Clone(c);
}
_volatile.Clone(c, c->_volatile);
c->_types = ArbUt::List<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());
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;
if (_battleData.Battle.HasValue() && _battleData.Side.HasValue()) {
auto sideIndex = _battleData.Side.GetValue()->GetCreatureIndex(this);
if (!_battleData.Battle.GetValue()->CanSlotBeFilled(_battleData.Side.GetValue()->GetSideIndex(),
sideIndex)) {
_battleData.Side.GetValue()->MarkSlotAsUnfillable(this);
}
_battleData.Battle.GetValue()->ValidateBattleState();
}
}
}
void PkmnLib::Battling::Pokemon::ClearBattleData() noexcept {
Creature::ClearBattleData();
_wasCaught = false;
}