PkmnLib/src/Battling/Pokemon/Pokemon.cpp

108 lines
4.6 KiB
C++
Raw Normal View History

#include "Pokemon.hpp"
2020-06-10 10:33:51 +00:00
#include <CreatureLib/Battling/Models/Battle.hpp>
2022-03-26 15:23:24 +00:00
#include "../EventHooks/CaptureAttemptEvent.hpp"
2020-08-08 10:01:05 +00:00
#include "../PkmnScriptCategory.hpp"
2020-06-10 10:33:51 +00:00
void PkmnLib::Battling::Pokemon::Evolve(ArbUt::BorrowedPtr<const Library::PokemonSpecies> mon,
ArbUt::BorrowedPtr<const Library::PokemonForme> forme) {
2020-06-10 12:53:03 +00:00
// Set species and variant
2020-06-10 10:33:51 +00:00
_species = mon.ForceAs<const CreatureLib::Library::CreatureSpecies>();
2020-06-10 12:53:03 +00:00
ChangeVariant(forme.ForceAs<const CreatureLib::Library::SpeciesVariant>());
2020-06-10 10:33:51 +00:00
2020-06-10 12:53:03 +00:00
// If the pokemon is genderless, but it's new evolution is not, we want to set its gender
2020-06-10 10:33:51 +00:00
if (_gender != CreatureLib::Library::Gender::Genderless && _species->GetGenderRate() != -1) {
2020-06-10 12:53:03 +00:00
// If we are currently in battle, use the battle random so we can get predictable events.
2021-05-08 10:12:36 +00:00
if (_battleData.Battle.HasValue()) {
_gender = _species->GetRandomGender(_battleData.Battle.GetValue()->GetRandom()->GetRNG());
2020-06-10 12:53:03 +00:00
}
// 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.
2020-06-10 10:33:51 +00:00
} else if (_species->GetGenderRate() == -1 && _gender != CreatureLib::Library::Gender::Genderless) {
_gender = CreatureLib::Library::Gender::Genderless;
}
// TODO: Learn moves?
2020-06-10 12:53:03 +00:00
// TODO: Event hook
2020-06-10 10:33:51 +00:00
}
2020-08-08 10:01:05 +00:00
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;
2021-05-08 10:12:36 +00:00
c->_battleData.Battle = _battleData.Battle;
c->_battleData.Side = _battleData.Side;
c->_battleData.OnBattleField = _battleData.OnBattleField;
c->_battleData.Index = _battleData.Index;
2022-05-14 14:50:20 +00:00
if (_activeTalent.HasValue()) {
c->_activeTalent = _activeTalent.GetValue()->Clone(c);
}
c->_hasOverridenTalent = _hasOverridenTalent;
c->_overridenTalent = _overridenTalent;
2022-05-14 14:50:20 +00:00
if (_status.HasValue()) {
c->_status = _status.GetValue()->Clone(c);
}
_volatile.Clone(c, c->_volatile);
2022-05-28 10:35:31 +00:00
c->_types = ArbUt::List<u8>(_types);
c->_friendship = _friendship;
c->RecalculateFlatStats();
return c;
}
bool PkmnLib::Battling::Pokemon::IsUsable() const noexcept {
if (IsEgg()) {
return false;
}
2022-03-26 15:23:24 +00:00
if (_wasCaught) {
return false;
}
return Creature::IsUsable();
}
2022-03-26 15:23:24 +00:00
void PkmnLib::Battling::Pokemon::AttemptCapture(PkmnLib::Library::Item* catchItem) {
Ensure(_battleData.OnBattleField);
Ensure(_battleData.Battle.HasValue());
Ensure(_battleData.Side.HasValue());
Ensure(!IsFainted());
Ensure(IsUsable());
2022-06-07 21:23:40 +00:00
auto captureLibrary = GetLibrary().ForceAs<const BattleLibrary>()->GetCaptureLibrary();
2022-03-26 15:23:24 +00:00
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();
}
2022-03-26 15:23:24 +00:00
}
}
void PkmnLib::Battling::Pokemon::ClearBattleData() noexcept {
Creature::ClearBattleData();
_wasCaught = false;
}