PkmnLib/src/Battling/Library/MiscLibrary.cpp

91 lines
4.4 KiB
C++

#include "MiscLibrary.hpp"
#include <CreatureLib/Battling/Models/Battle.hpp>
#include <CreatureLib/Battling/Models/LearnedAttack.hpp>
#include <CreatureLib/Battling/TurnChoices/AttackTurnChoice.hpp>
#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<const PkmnLib::Library::EvolutionData>& evolution,
const ArbUt::BorrowedPtr<const Pokemon>& 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<ScriptResolver*>(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();
}