#include "Pokemon.hpp" #include #include "../EventHooks/CaptureAttemptEvent.hpp" #include "../PkmnScriptCategory.hpp" void PkmnLib::Battling::Pokemon::Evolve(ArbUt::BorrowedPtr mon, ArbUt::BorrowedPtr forme) { // Set species and variant _species = mon.ForceAs(); ChangeVariant(forme.ForceAs()); // 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(_attacks.Count()); auto i = 0; for (auto* attack : _attacks) { if (attack == nullptr) { moves[i++] = nullptr; } else { moves[i++] = dynamic_cast(attack->Clone()); } } auto* c = new Pokemon(_library.ForceAs(), _species.ForceAs(), _variant.ForceAs(), _level, _experience, _uniqueIdentifier, _gender, _coloring, _heldItem.ForceAs(), _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(_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()->GetCaptureLibrary(); auto result = captureLibrary->TryCatch(this, catchItem, _battleData.Battle.GetValue()->GetRandom()); _battleData.Battle.GetValue()->TriggerEventListener(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; }