#include "MiscLibrary.hpp" #include #include #include #include "../PkmnScriptHook.hpp" #include "../Pokemon/LearnedMove.hpp" #include "../Pokemon/Pokemon.hpp" bool PkmnLib::Battling::MiscLibrary::IsCritical(CreatureLib::Battling::ExecutingAttack* non_null attack, CreatureLib::Battling::Creature* non_null target, uint8_t hit) const { bool preventCrit = false; PKMN_HOOK(PreventIncomingCritical, target, attack, target, hit, &preventCrit); if (preventCrit) { return false; } uint8_t critStage = 0; PKMN_HOOK(ModifyCriticalStage, attack, attack, target, hit, &critStage); Ensure(target->GetBattle().HasValue()); auto rand = target->GetBattle().GetValue()->GetRandom(); switch (critStage) { case 0: return rand->Get(24) == 0; case 1: return rand->Get(8) == 0; case 2: return rand->Get(2) == 0; default: return true; } } bool PkmnLib::Battling::MiscLibrary::CanFlee(CreatureLib::Battling::FleeTurnChoice* non_null switchChoice) const { return CreatureLib::Battling::MiscLibrary::CanFlee(switchChoice); } CreatureLib::Battling::BaseTurnChoice* non_null PkmnLib::Battling::MiscLibrary::ReplacementAttack( CreatureLib::Battling::Creature* non_null user, CreatureLib::Battling::CreatureIndex target) const { return new CreatureLib::Battling::AttackTurnChoice(user, GetReplacementAttack(), target); } using TimeOfDay = PkmnLib::Library::TimeOfDay; bool PkmnLib::Battling::MiscLibrary::CanEvolveFromLevelUp( const ArbUt::BorrowedPtr& evolution, const ArbUt::BorrowedPtr& pokemon) { auto time = GetTime(); switch (evolution->GetMethod()) { case Library::EvolutionMethod::Level: return pokemon->GetLevel() >= evolution->GetDataAt(0)->AsInt(); case Library::EvolutionMethod::HighFriendship: return pokemon->GetFriendship() >= evolution->GetDataAt(0)->AsInt(); case Library::EvolutionMethod::HighFriendshipTime: return pokemon->GetFriendship() >= evolution->GetDataAt(0)->AsInt() && time >= (TimeOfDay)evolution->GetDataAt(1)->AsInt() && time <= (TimeOfDay)evolution->GetDataAt(2)->AsInt(); case Library::EvolutionMethod::KnownMove: { auto v = evolution->GetDataAt(0)->AsString(); return std::any_of(pokemon->GetMoves().begin(), pokemon->GetMoves().end(), [v](const auto& move) { return move.HasValue() && move.GetValue()->GetMoveData()->GetName() == v; }); } case Library::EvolutionMethod::LocationBased: // TODO: Implement this return false; case Library::EvolutionMethod::TimeBased: return time >= (TimeOfDay)evolution->GetDataAt(0)->AsInt() && time <= (TimeOfDay)evolution->GetDataAt(1)->AsInt(); case Library::EvolutionMethod::HoldsItem: return pokemon->HasHeldItem(evolution->GetDataAt(0)->AsString()); case Library::EvolutionMethod::HoldsItemTime: return pokemon->HasHeldItem(evolution->GetDataAt(0)->AsString()) && time >= (TimeOfDay)evolution->GetDataAt(0)->AsInt() && time <= (TimeOfDay)evolution->GetDataAt(1)->AsInt(); case Library::EvolutionMethod::IsGenderAndLevel: return pokemon->GetLevel() >= evolution->GetDataAt(1)->AsInt() && pokemon->GetGender() == (CreatureLib::Library::Gender)evolution->GetDataAt(0)->AsInt(); case Library::EvolutionMethod::Custom: { auto script = dynamic_cast(pokemon->GetLibrary()->GetScriptResolver().get()) ->LoadEvolutionScript(evolution->GetDataAt(0)->AsString()); if (!script.HasValue()) { return false; } auto v = false; script.GetValue()->DoesEvolveFromLevelUp(evolution, pokemon, &v); return v; } case Library::EvolutionMethod::EvolutionItemUse: case Library::EvolutionMethod::EvolutionItemUseWithGender: case Library::EvolutionMethod::Trade: case Library::EvolutionMethod::TradeWithHeldItem: case Library::EvolutionMethod::TradeWithSpecificPokemon: return false; } __builtin_unreachable(); }