diff --git a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Panels.cpp b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Panels.cpp index 700065e275..eac27d9c55 100644 --- a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Panels.cpp +++ b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Panels.cpp @@ -10,6 +10,7 @@ #include "PokemonFRLG_Settings.h" +#include "Programs/Farming/PokemonFRLG_NuggetBridgeFarmer.h" #include "Programs/ShinyHunting/PokemonFRLG_GiftReset.h" #include "Programs/ShinyHunting/PokemonFRLG_LegendaryReset.h" #include "Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.h" @@ -33,6 +34,11 @@ std::vector PanelListFactory::make_panels() const{ ret.emplace_back("---- Settings ----"); ret.emplace_back(make_settings()); + ret.emplace_back("---- Farming ----"); + if (PreloadSettings::instance().DEVELOPER_MODE) { + ret.emplace_back(make_single_switch_program()); + } + //ret.emplace_back("---- General ----"); ret.emplace_back("---- Shiny Hunting ----"); diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/Farming/PokemonFRLG_NuggetBridgeFarmer.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/Farming/PokemonFRLG_NuggetBridgeFarmer.cpp new file mode 100644 index 0000000000..06e233521b --- /dev/null +++ b/SerialPrograms/Source/PokemonFRLG/Programs/Farming/PokemonFRLG_NuggetBridgeFarmer.cpp @@ -0,0 +1,263 @@ +/* Nugget Bridge Farmer + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonFramework/ProgramStats/StatsTracking.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" +#include "Pokemon/Pokemon_Strings.h" +#include "PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.h" +#include "PokemonFRLG/Inference/Menus/PokemonFRLG_StartMenuDetector.h" +#include "PokemonFRLG/PokemonFRLG_Navigation.h" +#include "PokemonFRLG_NuggetBridgeFarmer.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonFRLG{ + +NuggetBridgeFarmer_Descriptor::NuggetBridgeFarmer_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonFRLG:NuggetBridgeFarmer", + Pokemon::STRING_POKEMON + " FRLG", "Nugget Bridge Farmer", + "Programs/PokemonFRLG/NuggetBridgeFarmer.html", + "Farm the Nugget Bridge for money.", + ProgramControllerClass::StandardController_RequiresPrecision, + FeedbackType::REQUIRED, + AllowCommandsWhenRunning::DISABLE_COMMANDS + ) +{} + +struct NuggetBridgeFarmer_Descriptor::Stats : public StatsTracker { + public: + Stats() + : nuggets(m_stats["Nuggets"]) + , errors(m_stats["Errors"]) + { + m_display_order.emplace_back("Nuggets"); + m_display_order.emplace_back("Errors", HIDDEN_IF_ZERO); + } + + std::atomic& nuggets; + std::atomic& errors; +}; + +std::unique_ptr NuggetBridgeFarmer_Descriptor::make_stats() const{ + return std::unique_ptr(new Stats()); +} + +NuggetBridgeFarmer::NuggetBridgeFarmer() + : STOP_AFTER_CURRENT("Nugget") + , NUM_NUGGETS( + "Number of Nuggets:
" + "Zero will run until 'Stop after Current Nugget' is pressed or the program is manually stopped.", + LockMode::UNLOCK_WHILE_RUNNING, + 120, // About 2 hours of farming. + 0 + ) + , GO_HOME_WHEN_DONE(false) + /*, PERIODIC_SAVE( + "Periodically Save:
" + "Save the game every this many nuggets. This reduces the loss to game crashes. Set to zero to disable.", + LockMode::UNLOCK_WHILE_RUNNING, + 10, + 0 + )*/ + , NOTIFICATION_STATUS_UPDATE("Status Update", true, false, std::chrono::seconds(3600)) + , NOTIFICATIONS({ + &NOTIFICATION_STATUS_UPDATE, + &NOTIFICATION_PROGRAM_FINISH, + &NOTIFICATION_ERROR_FATAL, + }) +{ + PA_ADD_OPTION(STOP_AFTER_CURRENT); + + PA_ADD_OPTION(NUM_NUGGETS); + PA_ADD_OPTION(GO_HOME_WHEN_DONE); + //PA_ADD_OPTION(PERIODIC_SAVE); + + PA_ADD_OPTION(NOTIFICATIONS); +} + +void NuggetBridgeFarmer::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { + + home_black_border_check(env.console, context); + + NuggetBridgeFarmer_Descriptor::Stats& stats = env.current_stats(); + DeferredStopButtonOption::ResetOnExit reset_on_exit(STOP_AFTER_CURRENT); + + //for (uint32_t nuggets_since_last_save = 0;; nuggets_since_last_save++) { + while (true) { + send_program_status_notification(env, NOTIFICATION_STATUS_UPDATE); + if (NUM_NUGGETS != 0 && stats.nuggets >= NUM_NUGGETS) { + break; + } + + env.console.log("Exiting Pokemon Center..."); + while (true){ + BlackScreenWatcher pokemon_ceter_exit(COLOR_RED); + + int ret = run_until( + env.console, context, + [](ProControllerContext& context) { + pbf_press_dpad(context, DPAD_DOWN, 2000ms, 0ms); + }, + { pokemon_ceter_exit } + ); + + if (ret == 0) { + break; + } + } + + env.console.log("Detecting overworld..."); + while (true) { + BlackScreenOverWatcher overworld_entered(COLOR_RED); + + int ret = wait_until( + env.console, context, + std::chrono::milliseconds(2000), + {overworld_entered} + ); + + if (ret == 0) { + break; + } + } + + // There is a small delay from seeing the overworld to being able to a actually move. + pbf_wait(context, 1000ms); + context.wait_for_all_requests(); + + env.console.log("Navigating to Team Rocket member..."); + + ssf_press_button(context, BUTTON_B, 0ms, 12000ms); + pbf_press_dpad(context, DPAD_LEFT, 590ms, 0ms); + pbf_press_dpad(context, DPAD_UP, 510ms, 0ms); + pbf_press_dpad(context, DPAD_LEFT, 1550ms, 0ms); + pbf_press_dpad(context, DPAD_UP, 1175ms, 0ms); + pbf_press_dpad(context, DPAD_RIGHT, 1950ms, 0ms); + pbf_press_dpad(context, DPAD_UP, 5300ms, 0ms); + + context.wait_for_all_requests(); + + env.console.log("Starting battle..."); + while (true){ + BattleMenuWatcher battle_menu(COLOR_RED); + + int ret = run_until( + env.console, context, + [](ProControllerContext& context) { + pbf_mash_button(context, BUTTON_B, 2000ms); + }, + { battle_menu } + ); + + if (ret == 0) { + break; + } + } + + env.console.log("Loosing battle..."); + while (true){ + BlackScreenWatcher battle_lost(COLOR_RED); + + int ret = run_until( + env.console, context, + [](ProControllerContext& context) { + pbf_mash_button(context, BUTTON_A, 2000ms); + }, + { battle_lost } + ); + + if (ret == 0) { + break; + } + } + + env.console.log("Talking to nurse joy..."); + while (true){ + WhiteDialogWatcher nurse_joy_dialog(COLOR_RED); + int ret = run_until( + env.console, context, + [](ProControllerContext& context) { + pbf_mash_button(context, BUTTON_B, 2000ms); + }, + { nurse_joy_dialog } + ); + + if (ret == 0) { + break; + } + } + + // Spam B till nurse joy stops talking + while (true){ + WhiteDialogWatcher nurse_joy_dialog(COLOR_RED); + int ret = run_until( + env.console, context, + [](ProControllerContext& context) { + pbf_mash_button(context, BUTTON_B, 2000ms); + }, + { nurse_joy_dialog } + ); + + if (ret != 0) { + break; + } + } + + //TODO: Implement periodic saving. The Save Menu keeps the last cursor position. Need to implement arrow dectection on the correct option + /*if (PERIODIC_SAVE != 0 && nuggets_since_last_save >= PERIODIC_SAVE) { + StartMenuWatcher start_menu = StartMenuWatcher(COLOR_RED); + + env.console.log("Saving game..."); + + while (true) + { + int ret = run_until( + env.console, context, + [](ProControllerContext& context) { + pbf_press_button(context, BUTTON_PLUS, 320ms, 640ms); + pbf_wait(context, 100ms); + context.wait_for_all_requests(); + }, + { start_menu } + ); + + if (ret == 0) { + break; + } + } + + pbf_press_dpad(context, DPAD_DOWN, 320ms, 320ms); + pbf_press_dpad(context, DPAD_DOWN, 320ms, 320ms); + pbf_press_dpad(context, DPAD_DOWN, 320ms, 320ms); + pbf_press_dpad(context, DPAD_DOWN, 320ms, 320ms); + + pbf_press_button(context, BUTTON_A, 320ms, 320ms); + pbf_press_button(context, BUTTON_A, 320ms, 320ms); + + pbf_mash_button(context, BUTTON_B, 2000ms); + nuggets_since_last_save = 0; + }*/ + + stats.nuggets++; + env.update_stats(); + + if (STOP_AFTER_CURRENT.should_stop()) { + break; + } + } + + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); + GO_HOME_WHEN_DONE.run_end_of_program(context); +} + + +} +} +} \ No newline at end of file diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/Farming/PokemonFRLG_NuggetBridgeFarmer.h b/SerialPrograms/Source/PokemonFRLG/Programs/Farming/PokemonFRLG_NuggetBridgeFarmer.h new file mode 100644 index 0000000000..e3b9a25c2e --- /dev/null +++ b/SerialPrograms/Source/PokemonFRLG/Programs/Farming/PokemonFRLG_NuggetBridgeFarmer.h @@ -0,0 +1,58 @@ +/* Nugget Bridge Farmer + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonFRLG_NuggetBridgeFarmer_H +#define PokemonAutomation_PokemonFRLG_NuggetBridgeFarmer_H + +#include "Common/Cpp/Options/SimpleIntegerOption.h" +#include "Common/Cpp/Options/ButtonOption.h" +#include "CommonFramework/Notifications/EventNotificationsTable.h" +#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" +#include "NintendoSwitch/Options/NintendoSwitch_GoHomeWhenDoneOption.h" + + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonFRLG{ + +class NuggetBridgeFarmer_Descriptor : public SingleSwitchProgramDescriptor{ +public: + NuggetBridgeFarmer_Descriptor(); + struct Stats; + virtual std::unique_ptr make_stats() const override; +}; + +class NuggetBridgeFarmer : public SingleSwitchProgramInstance { +public: + NuggetBridgeFarmer(); + virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; + virtual void start_program_border_check( + VideoStream& stream, + FeedbackType feedback_type + ) override { + } + +private: + + DeferredStopButtonOption STOP_AFTER_CURRENT; + SimpleIntegerOption NUM_NUGGETS; + GoHomeWhenDoneOption GO_HOME_WHEN_DONE; + + //SimpleIntegerOption PERIODIC_SAVE; + + EventNotificationOption NOTIFICATION_STATUS_UPDATE; + EventNotificationsOption NOTIFICATIONS; + +}; + +} +} +} + + + + +#endif \ No newline at end of file diff --git a/SerialPrograms/cmake/SourceFiles.cmake b/SerialPrograms/cmake/SourceFiles.cmake index 170e4026b5..867e36916d 100644 --- a/SerialPrograms/cmake/SourceFiles.cmake +++ b/SerialPrograms/cmake/SourceFiles.cmake @@ -1422,6 +1422,8 @@ file(GLOB LIBRARY_SOURCES Source/PokemonFRLG/PokemonFRLG_Panels.h Source/PokemonFRLG/PokemonFRLG_Settings.cpp Source/PokemonFRLG/PokemonFRLG_Settings.h + Source/PokemonFRLG/Programs/Farming/PokemonFRLG_NuggetBridgeFarmer.cpp + Source/PokemonFRLG/Programs/Farming/PokemonFRLG_NuggetBridgeFarmer.h Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.h Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp