From 48a713e40ee0d208386fa3d669faff598c78172b Mon Sep 17 00:00:00 2001 From: Phobos Date: Wed, 3 Dec 2025 13:35:21 -0300 Subject: [PATCH 1/5] adding weather finder and helioptile hunt for LZA --- .../Inference/PokemonLZA_WeatherDetector.cpp | 125 +++++++++ .../Inference/PokemonLZA_WeatherDetector.h | 65 +++++ .../Source/PokemonLZA/PokemonLZA_Panels.cpp | 6 + .../PokemonLZA_WeatherFinder.cpp | 245 ++++++++++++++++++ .../PokemonLZA_WeatherFinder.h | 53 ++++ .../PokemonLZA_ShinyHunt_HelioptileHunter.cpp | 227 ++++++++++++++++ .../PokemonLZA_ShinyHunt_HelioptileHunter.h | 50 ++++ SerialPrograms/SourceFiles.cmake | 6 + 8 files changed, 777 insertions(+) create mode 100644 SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_WeatherDetector.cpp create mode 100644 SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_WeatherDetector.h create mode 100644 SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp create mode 100644 SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h create mode 100644 SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_HelioptileHunter.cpp create mode 100644 SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_HelioptileHunter.h diff --git a/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_WeatherDetector.cpp b/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_WeatherDetector.cpp new file mode 100644 index 000000000..62da2d522 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_WeatherDetector.cpp @@ -0,0 +1,125 @@ +#include "CommonFramework/Globals.h" +#include "CommonFramework/ImageTools/ImageDiff.h" +#include "CommonTools/Images/ImageFilter.h" +#include "PokemonLZA_WeatherDetector.h" + +namespace PokemonAutomation { +namespace NintendoSwitch { +namespace PokemonLZA { + + +//----------------------------------------------------- +// Weather Info Table (two images per weather) +//----------------------------------------------------- + +static const WeatherTemplateInfo WEATHER_TABLE[] = { + + // Clear + { + "PokemonLZA/Weather/sun_drop.png", + "PokemonLZA/Weather/clear_core.png", + ImageFloatBox(0.8945, 0.0570, 0.0050, 0.0100), + ImageFloatBox(0.8910, 0.0360, 0.0110, 0.0210), + COLOR_RED, + COLOR_GREEN + }, + + // Sunny + { + "PokemonLZA/Weather/sun_drop.png", + "PokemonLZA/Weather/sunny_core.png", + ImageFloatBox(0.8945, 0.0570, 0.0050, 0.0100), + ImageFloatBox(0.8910, 0.0360, 0.0110, 0.0210), + COLOR_RED, + COLOR_GREEN + }, + + // Rain + { + "PokemonLZA/Weather/rain_cloud.png", + "PokemonLZA/Weather/rain_drop.png", + ImageFloatBox(0.8865, 0.0265, 0.0210, 0.0270), + ImageFloatBox(0.8885, 0.0525, 0.0050, 0.0150), + COLOR_RED, + COLOR_GREEN + }, + + // Cloudy + { + "PokemonLZA/Weather/cloudy_cloud.png", + "PokemonLZA/Weather/cloudy_drop.png", + ImageFloatBox(0.8895, 0.0430, 0.0210, 0.0265), + ImageFloatBox(0.8915, 0.0255, 0.0050, 0.0100), + COLOR_RED, + COLOR_GREEN + }, + + // Foggy + { + "PokemonLZA/Weather/foggy_tray_1.png", + "PokemonLZA/Weather/foggy_tray_2.png", + ImageFloatBox(0.8893, 0.0487, 0.0218, 0.0080), + ImageFloatBox(0.8880, 0.0555, 0.0225, 0.0080), + COLOR_RED, + COLOR_GREEN + }, + + // Rainbow + { + "PokemonLZA/Weather/rainbow_cloud.png", + "PokemonLZA/Weather/rainbow_arch.png", + ImageFloatBox(0.8840, 0.0465, 0.0140, 0.0165), + ImageFloatBox(0.8930, 0.0420, 0.0120, 0.0100), + COLOR_RED, + COLOR_GREEN + }, +}; + + +const WeatherTemplateInfo& weather_template_info(WeatherIconType icon){ + return WEATHER_TABLE[(int)icon]; +} + +//----------------------------------------------------- +// Detector +//----------------------------------------------------- + +WeatherIconDetector::WeatherIconDetector(WeatherIconType type, VideoOverlay* overlay) +{ + m_info = &weather_template_info(type); + + if (overlay){ + m_overlay1.emplace(*overlay, m_info->box1, m_info->color1); + m_overlay2.emplace(*overlay, m_info->box2, m_info->color2); + } +} + +void WeatherIconDetector::make_overlays(VideoOverlaySet& items) const { + items.add(m_info->color1, m_info->box1); + items.add(m_info->color2, m_info->box2); +} + +bool WeatherIconDetector::detect(const ImageViewRGB32& screen){ + + // Extract screen patches + ImageRGB32 c1 = extract_box_reference(screen, m_info->box1).copy(); + ImageRGB32 c2 = extract_box_reference(screen, m_info->box2).copy(); + + // Load templates + ImageRGB32 t1(RESOURCE_PATH() + m_info->path1); + ImageRGB32 t2(RESOURCE_PATH() + m_info->path2); + + if (t1.width() == 0 || t2.width() == 0){ + return false; + } + + double rms1 = ImageMatch::pixel_RMSD(c1, t1); + double rms2 = ImageMatch::pixel_RMSD(c2, t2); + + return rms1 < 90 && rms2 < 90; +} + + +} +} +} diff --git a/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_WeatherDetector.h b/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_WeatherDetector.h new file mode 100644 index 000000000..0d9bd10e8 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_WeatherDetector.h @@ -0,0 +1,65 @@ +#ifndef PokemonAutomation_PokemonLZA_WeatherDetector_H +#define PokemonAutomation_PokemonLZA_WeatherDetector_H + +#include +#include "Common/Cpp/Color.h" +#include "CommonFramework/ImageTools/ImageBoxes.h" +#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" +#include "CommonTools/VisualDetector.h" +#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" + +namespace PokemonAutomation { +namespace NintendoSwitch { +namespace PokemonLZA { + + +enum class WeatherIconType { + Clear, + Sunny, + Rain, + Cloudy, + Foggy, + Rainbow, + Unknown, +}; + + +//----------------------------------------------------- +// Template Info Struct +//----------------------------------------------------- +struct WeatherTemplateInfo{ + const char* path1; // template for box1 + const char* path2; // template for box2 + ImageFloatBox box1; + ImageFloatBox box2; + Color color1; + Color color2; +}; + + +const WeatherTemplateInfo& weather_template_info(WeatherIconType icon); + + +//----------------------------------------------------- +// Detector +//----------------------------------------------------- +class WeatherIconDetector : public StaticScreenDetector { +public: + WeatherIconDetector(WeatherIconType type, VideoOverlay* overlay = nullptr); + + virtual void make_overlays(VideoOverlaySet& items) const override; + + virtual bool detect(const ImageViewRGB32& screen) override; + +private: + const WeatherTemplateInfo* m_info; + + std::optional m_overlay1; + std::optional m_overlay2; +}; + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp index 65ca25361..1edcf6e30 100644 --- a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp +++ b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp @@ -35,9 +35,12 @@ #include "Programs/ShinyHunting/PokemonLZA_ShinyHunt_FlySpotReset.h" #include "Programs/ShinyHunting/PokemonLZA_ShuttleRun.h" #include "Programs/ShinyHunting/PokemonLZA_SewerHunter.h" +#include "Programs/ShinyHunting/PokemonLZA_ShinyHunt_OverworldMacro.h" +#include "Programs/ShinyHunting/PokemonLZA_ShinyHunt_HelioptileHunter.h" // Non-Shiny Hunting #include "Programs/NonShinyHunting/PokemonLZA_StatsReset.h" +#include "Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h" // Developer #include "Programs/TestPrograms/PokemonLZA_OverworldWatcher.h" @@ -86,6 +89,9 @@ std::vector PanelListFactory::make_panels() const{ ret.emplace_back(make_single_switch_program()); ret.emplace_back(make_single_switch_program()); if (IS_BETA_VERSION){ + ret.emplace_back(make_single_switch_program()); + ret.emplace_back(make_single_switch_program()); + ret.emplace_back(make_single_switch_program()); } if (PreloadSettings::instance().DEVELOPER_MODE){ ret.emplace_back(make_single_switch_program()); diff --git a/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp b/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp new file mode 100644 index 000000000..6b674ff41 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp @@ -0,0 +1,245 @@ +/* Weather Finder + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/ProgramStats/StatsTracking.h" +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonFramework/VideoPipeline/VideoFeed.h" +#include "CommonTools/StartupChecks/VideoResolutionCheck.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "Pokemon/Pokemon_Strings.h" +#include "PokemonLZA/Inference/Boxes/PokemonLZA_BoxDetection.h" +#include "PokemonLZA/Programs/PokemonLZA_BasicNavigation.h" +#include "PokemonLZA/Programs/PokemonLZA_MenuNavigation.h" +#include "PokemonLZA_WeatherFinder.h" +#include +#include +#include + + +namespace PokemonAutomation { + namespace NintendoSwitch { + namespace PokemonLZA { + + using namespace Pokemon; + + WeatherFinder_Descriptor::WeatherFinder_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonLZA:WeatherFinder", + STRING_POKEMON + " LZA", "Weather Finder", + "Programs/PokemonLZA/WeatherFinder.html", + "Reset the weather by siting on a bench until reach the desired value", + ProgramControllerClass::StandardController_NoRestrictions, + FeedbackType::REQUIRED, + AllowCommandsWhenRunning::DISABLE_COMMANDS, + {} + ) + { + } + + class WeatherFinder_Descriptor::Stats : public StatsTracker { + public: + Stats() + : loops(m_stats["Loops"]) + , errors(m_stats["Errors"]) + { + m_display_order.emplace_back("Loops"); + m_display_order.emplace_back("Errors", HIDDEN_IF_ZERO); + } + + std::atomic& loops; + std::atomic& errors; + }; + + std::unique_ptr WeatherFinder_Descriptor::make_stats() const { + return std::unique_ptr(new Stats()); + } + + + WeatherFinder::WeatherFinder() + : START_POSITION( + "Starting from day or night:", + { + {0, "day", "DAY"}, + {1, "night", "NIGHT"}, + }, + LockMode::LOCK_WHILE_RUNNING, + 0 + ) + , DESIRED_WEATHER( + "Stop on:", + { + {0, "day-clear", "Clear Day"}, + {1, "day-cloudy", "Cloudy Day"}, + {2, "day-rainy", "Rainy Day"}, + {3, "day-sunny", "Sunny Day"}, + {4, "day-foggy", "Foggy Day"}, + {5, "day-rainbow", "Rainbow Day"}, + }, + LockMode::LOCK_WHILE_RUNNING, + 0 + ) + , GO_HOME_WHEN_DONE(true) + , NOTIFICATION_STATUS("Status Update", true, false, std::chrono::seconds(3600)) + , NOTIFICATIONS({ + &NOTIFICATION_STATUS, + &NOTIFICATION_PROGRAM_FINISH, + &NOTIFICATION_ERROR_RECOVERABLE, + &NOTIFICATION_ERROR_FATAL, + }) + { + PA_ADD_OPTION(START_POSITION); + PA_ADD_OPTION(DESIRED_WEATHER); + PA_ADD_OPTION(GO_HOME_WHEN_DONE); + PA_ADD_OPTION(NOTIFICATIONS); + } + + // //Test Method + // void WeatherFinder::validate_weather(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { + // VideoSnapshot screen = env.console.video().snapshot(); + + // WeatherIconDetector clearDetector( + // WeatherIconType::Clear, + // &env.console.overlay() + // ); + // bool clearResult = clearDetector.detect(screen); + // env.log("Clear is " + std::to_string(clearResult)); + // // context.wait_for_all_requests(); + + // WeatherIconDetector sunnyDetector( + // WeatherIconType::Sunny, + // &env.console.overlay() + // ); + // bool sunnyResult = sunnyDetector.detect(screen); + // env.log("Sunny is " + std::to_string(sunnyResult)); + + // WeatherIconDetector rainyDetector( + // WeatherIconType::Rain, + // &env.console.overlay() + // ); + // bool rainyResult = rainyDetector.detect(screen); + // env.log("Rainy is " + std::to_string(rainyResult)); + + // WeatherIconDetector cloudyDetector( + // WeatherIconType::Cloudy, + // &env.console.overlay() + // ); + // bool cloudyResult = cloudyDetector.detect(screen); + // env.log("Cloudy is " + std::to_string(cloudyResult)); + + // WeatherIconDetector foggyDetector( + // WeatherIconType::Foggy, + // &env.console.overlay() + // ); + // bool foggyResult = foggyDetector.detect(screen); + // env.log("Foggy is " + std::to_string(foggyResult)); + + // WeatherIconDetector rainbowDetector( + // WeatherIconType::Rainbow, + // &env.console.overlay() + // ); + // bool rainbowResult = rainbowDetector.detect(screen); + // env.log("Rainbow is " + std::to_string(rainbowResult)); + // } + + WeatherIconType get_weather_type(size_t option) { + switch (option) { + case 0: + return WeatherIconType::Clear; + case 1: + return WeatherIconType::Cloudy; + case 2: + return WeatherIconType::Rain; + case 3: + return WeatherIconType::Sunny; + case 4: + return WeatherIconType::Foggy; + case 5: + return WeatherIconType::Rainbow; + default: + return WeatherIconType::Clear; + } + } + + std::string get_weather_name(size_t option) { + switch (option) { + case 0: + return "Clear"; + case 1: + return "Cloudy"; + case 2: + return "Rainy"; + case 3: + return "Sunny"; + case 4: + return "Foggy"; + case 5: + return "Rainbow"; + default: + return "Clear"; + } + } + + void bench_it(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { + sit_on_bench(env.console, context); + pbf_move_left_joystick(context, 128, 255, 500ms, 500ms); + context.wait_for_all_requests(); + } + + void WeatherFinder::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { + WeatherFinder_Descriptor::Stats& stats = env.current_stats(); + assert_16_9_720p_min(env.logger(), env.console); + + bool isDay = !START_POSITION.current_value(); + + //Reset to day time + if (!isDay) { + env.log("Resetting to Day"); + bench_it(env, context); + isDay = true; + } + + WeatherIconType weatherType = get_weather_type(DESIRED_WEATHER.current_value()); + std::string weatherName = get_weather_name(DESIRED_WEATHER.current_value()); + + WeatherIconDetector detector( + weatherType, + &env.console.overlay() + ); + + while (true) { + env.log("Looking for " + weatherName + " " + std::string(isDay ? "day" : "night")); + + open_map(env.console, context); + VideoSnapshot screen = env.console.video().snapshot(); + + bool result = detector.detect(screen); + context.wait_for_all_requests(); + + if (result == 1) { + env.log("Desired weather found."); + GO_HOME_WHEN_DONE.run_end_of_program(context); + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); + break; + } + else { + env.log("Desired weather not found. Continuing"); + pbf_press_button(context, BUTTON_PLUS, 500ms, 500ms); + for (uint8_t c = 0; c < 2; c++) { + bench_it(env, context); + isDay = !isDay; + env.log("Current time of day: " + std::string(isDay ? "DAY" : "NIGHT")); + } + stats.loops++; + context.wait_for_all_requests(); + } + env.update_stats(); + context.wait_for_all_requests(); + send_program_status_notification(env, NOTIFICATION_STATUS); + } + } + } + } +} diff --git a/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h b/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h new file mode 100644 index 000000000..1edd48f3b --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h @@ -0,0 +1,53 @@ +/* Weather Finder + * + * From: https://github.com/PokemonAutomation/ + * + * Reset the weather by siting on a bench until reach the desired value + */ + +#ifndef PokemonAutomation_PokemonLZA_WeatherFinder_H +#define PokemonAutomation_PokemonLZA_WeatherFinder_H + +#include "Common/Cpp/Options/EnumDropdownOption.h" +#include "CommonFramework/Notifications/EventNotificationOption.h" +#include "CommonFramework/Notifications/EventNotificationsTable.h" +#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" +#include "NintendoSwitch/Options/NintendoSwitch_GoHomeWhenDoneOption.h" +#include + +namespace PokemonAutomation { + namespace NintendoSwitch { + namespace PokemonLZA { + + + class WeatherFinder_Descriptor : public SingleSwitchProgramDescriptor { + public: + WeatherFinder_Descriptor(); + + class Stats; + virtual std::unique_ptr make_stats() const override; + }; + + + class WeatherFinder : public SingleSwitchProgramInstance { + public: + WeatherFinder(); + + virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; + + private: + IntegerEnumDropdownOption START_POSITION; + IntegerEnumDropdownOption DESIRED_WEATHER; + GoHomeWhenDoneOption GO_HOME_WHEN_DONE; + + EventNotificationOption NOTIFICATION_STATUS; + EventNotificationsOption NOTIFICATIONS; + }; + + + + + } + } +} +#endif diff --git a/SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_HelioptileHunter.cpp b/SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_HelioptileHunter.cpp new file mode 100644 index 000000000..2612b64c2 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_HelioptileHunter.cpp @@ -0,0 +1,227 @@ +/* Shiny Hunt - Helioptile Hunter + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "Common/Cpp/Options/ConfigOption.h" +#include "CommonFramework/ProgramStats/StatsTracking.h" +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonFramework/VideoPipeline/VideoFeed.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "CommonTools/StartupChecks/VideoResolutionCheck.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" +#include "NintendoSwitch/Controllers/NintendoSwitch_ControllerButtons.h" +#include "NintendoSwitch/Programs/NintendoSwitch_GameEntry.h" +#include "Pokemon/Pokemon_Strings.h" +#include "PokemonLZA/Inference/PokemonLZA_ButtonDetector.h" +#include "PokemonLZA/Inference/PokemonLZA_WeatherDetector.h" +#include "PokemonLZA_ShinyHunt_HelioptileHunter.h" +#include "PokemonLZA/Programs/PokemonLZA_BasicNavigation.h" +#include "PokemonLZA/Programs/PokemonLZA_Locations.h" +#include +#include + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + +using namespace Pokemon; + + + + + +ShinyHunt_HelioptileHunter_Descriptor::ShinyHunt_HelioptileHunter_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonLZA:ShinyHunt-HelioptileHunter", + STRING_POKEMON + " LZA", "Helioptile Hunter", + "Programs/PokemonLZA/ShinyHunt-HelioptileHunter.html", + "Hunts for Helioptile in Wild Zone by entering and resetting, checking for the right weather.", + ProgramControllerClass::StandardController_NoRestrictions, + FeedbackType::REQUIRED, + AllowCommandsWhenRunning::DISABLE_COMMANDS, + {} + ) +{} + +class ShinyHunt_HelioptileHunter_Descriptor::Stats : public StatsTracker{ +public: + Stats() + : cycles(m_stats["Cycles"]) + , loops(m_stats["Loops"]) + , errors(m_stats["Errors"]) + { + m_display_order.emplace_back("Cycles"); + m_display_order.emplace_back("Loops"); + m_display_order.emplace_back("Errors", HIDDEN_IF_ZERO); + } + + std::atomic& cycles; + std::atomic& loops; + std::atomic& errors; +}; + +std::unique_ptr ShinyHunt_HelioptileHunter_Descriptor::make_stats() const{ + return std::unique_ptr(new Stats()); +} + +ShinyHunt_HelioptileHunter::ShinyHunt_HelioptileHunter() + : END_AFTER_CYCLE("How Many cycles before stopping. 0 for never stop.", + LockMode::LOCK_WHILE_RUNNING, + 0, 0, 32*30 + ) + , NOTIFICATION_STATUS("Status Update", true, false, ImageAttachmentMode::JPG, {"Notifs"}, std::chrono::seconds(3600)) + , NOTIFICATIONS({ + &NOTIFICATION_STATUS, + &NOTIFICATION_PROGRAM_FINISH, + &NOTIFICATION_ERROR_RECOVERABLE, + &NOTIFICATION_ERROR_FATAL, + }) +{ + PA_ADD_OPTION(END_AFTER_CYCLE); + PA_ADD_OPTION(NOTIFICATIONS); +} + +bool proper_weather(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { + + open_map(env.console, context, true); + + WeatherIconDetector sunnyDetector( + WeatherIconType::Sunny, + &env.console.overlay() + ); + + WeatherIconDetector clearDetector( + WeatherIconType::Clear, + &env.console.overlay() + ); + VideoSnapshot screen = env.console.video().snapshot(); + + return (sunnyDetector.detect(screen) || clearDetector.detect(screen)); +} + +void bench_loop(SingleSwitchProgramEnvironment& env, ProControllerContext& context, size_t quantity) { + for(size_t i = 0; i < quantity; i++) { + sit_on_bench(env.console, context); + pbf_move_left_joystick(context, 128, 255, 500ms, 200ms); + } +} + +void find_weather(SingleSwitchProgramEnvironment& env, ProControllerContext& context, bool is_night_time) { + context.wait_for_all_requests(); + env.log("Starting weather loop"); + bench_loop(env, context, (is_night_time) ? 1 : 2); + + while (!proper_weather(env, context)) { + env.log("Weather not found"); + pbf_press_button(context, BUTTON_PLUS, 500ms, 500ms); + bench_loop(env, context, 2); + } + env.log("Weather found"); + context.wait_for_all_requests(); +} + +void reach_bench(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { + //Go to poke center + pbf_move_left_joystick(context, 110, 0, 100ms, 200ms); + pbf_press_button(context, BUTTON_A, 500ms, 500ms); + pbf_press_button(context, BUTTON_A, 500ms, 500ms); + pbf_wait(context, 3000ms); + //Go to bench + pbf_move_left_joystick(context, 0, 128, 700ms, 200ms); + pbf_move_left_joystick(context, 128, 0, 500ms, 200ms); +} + +void reach_gate( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context +){ + ButtonWatcher buttonA(COLOR_RED, ButtonType::ButtonA, {0.3, 0.2, 0.4, 0.7}, &env.console.overlay()); + run_until( + env.console, context, + [](ProControllerContext& context){ + for (int c = 0; c < 30; c++){ + ssf_press_button(context, BUTTON_B, 0ms, 2s, 0ms); + pbf_move_left_joystick(context, 128, 0, 2s, 200ms); + } + }, + {{buttonA}} + ); + env.log("Detected button A. At Wild Zone gate."); + env.console.overlay().add_log("Detect Entrance"); +} + +void reach_wild_zone(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { + pbf_move_left_joystick(context, 140, 255, 200ms, 200ms); + pbf_press_button(context, BUTTON_A, 500ms, 500ms); + pbf_press_button(context, BUTTON_A, 500ms, 500ms); + pbf_wait(context, 2000ms); +} + +void execute_fixed_routine(SingleSwitchProgramEnvironment& env, ConsoleHandle& console, ProControllerContext& context, EventNotificationOption& settings){ + context.wait_for_all_requests(); + console.overlay().add_log("Starting routine"); + + reach_gate(env, context); + context.wait_for_all_requests(); + pbf_press_button(context, BUTTON_A, 500ms, 1500ms); + + //moving forward + ssf_press_button(context, BUTTON_B, 0ms, 2000ms, 0ms); + pbf_move_left_joystick(context, 128, 0, 2000ms, 700ms); + context.wait_for_all_requests(); + send_program_status_notification(env, settings, "", env.console.video().snapshot()); + ssf_press_button(context, BUTTON_B, 0ms, 2500ms, 0ms); + pbf_move_left_joystick(context, 128, 0, 2500ms, 500ms); + + //moving back + ssf_press_button(context, BUTTON_B, 0ms, 5s, 0ms); + pbf_move_left_joystick(context, 128, 255, 5s, 500ms); + + //leave WZ + pbf_press_button(context, BUTTON_A, 500ms, 1500ms); + context.wait_for_all_requests(); +} + +void ShinyHunt_HelioptileHunter::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + assert_16_9_720p_min(env.logger(), env.console); + ShinyHunt_HelioptileHunter_Descriptor::Stats& stats = env.current_stats(); + + // This routine do not care for day/night change as is supposed to stop before time change. + while(true){ + + if (END_AFTER_CYCLE.current_value() > 0 && END_AFTER_CYCLE.current_value() == stats.cycles.load()) { + go_home(env.console, context); + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); + break; + } + + int hunt_loops = 0; + while (hunt_loops < 65) { + if (!proper_weather(env,context) || (hunt_loops == 0)) { + env.log("Not correct weather"); + reach_bench(env, context); + find_weather(env, context, false); + reach_wild_zone(env, context); + hunt_loops = 0; + } else { + env.log("Correct weather. Continuing"); + move_map_cursor_from_entrance_to_zone(env.console, context, WildZone::WILD_ZONE_14); + fly_from_map(env.console, context); + } + + execute_fixed_routine(env,env.console, context, NOTIFICATION_STATUS); + + stats.loops++; + hunt_loops++; + env.update_stats(); + } + stats.cycles++; + env.update_stats(); + } +} +} +} +} diff --git a/SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_HelioptileHunter.h b/SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_HelioptileHunter.h new file mode 100644 index 000000000..ca2bc627a --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_HelioptileHunter.h @@ -0,0 +1,50 @@ +/* Shiny Hunt - Helioptile Hunter + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonLZA_ShinyHunt_HelioptileHunter_H +#define PokemonAutomation_PokemonLZA_ShinyHunt_HelioptileHunter_H + +#include "Common/Cpp/Options/BooleanCheckBoxOption.h" +#include "Common/Cpp/Options/SimpleIntegerOption.h" +#include "Common/Cpp/Options/TimeDurationOption.h" +#include "CommonFramework/Notifications/EventNotificationsTable.h" +#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" +#include "PokemonLA/Options/PokemonLA_ShinyDetectedAction.h" +#include "PokemonLZA/Options/PokemonLZA_ShinyDetectedAction.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + + + + +class ShinyHunt_HelioptileHunter_Descriptor : public SingleSwitchProgramDescriptor{ +public: + ShinyHunt_HelioptileHunter_Descriptor(); + + class Stats; + virtual std::unique_ptr make_stats() const override; +}; + + +class ShinyHunt_HelioptileHunter : public SingleSwitchProgramInstance{ +public: + ShinyHunt_HelioptileHunter(); + + virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; + +private: + SimpleIntegerOption END_AFTER_CYCLE; + EventNotificationOption NOTIFICATION_STATUS; + EventNotificationsOption NOTIFICATIONS; +}; + + +} +} +} +#endif diff --git a/SerialPrograms/SourceFiles.cmake b/SerialPrograms/SourceFiles.cmake index a66f6e7a8..7e53c3688 100644 --- a/SerialPrograms/SourceFiles.cmake +++ b/SerialPrograms/SourceFiles.cmake @@ -1594,6 +1594,8 @@ file(GLOB LIBRARY_SOURCES Source/PokemonLZA/Inference/PokemonLZA_OverworldPartySelectionDetector.h Source/PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.cpp Source/PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.h + Source/PokemonLZA/Inference/PokemonLZA_WeatherDetector.cpp + Source/PokemonLZA/Inference/PokemonLZA_WeatherDetector.h Source/PokemonLZA/InferenceTraining/PokemonLZA_GenerateLocationNameOCR.cpp Source/PokemonLZA/InferenceTraining/PokemonLZA_GenerateLocationNameOCR.h Source/PokemonLZA/Options/PokemonLZA_BattleAIOption.cpp @@ -1616,6 +1618,8 @@ file(GLOB LIBRARY_SOURCES Source/PokemonLZA/Programs/Farming/PokemonLZA_RestaurantFarmer.h Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_StatsReset.cpp Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_StatsReset.h + Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp + Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h Source/PokemonLZA/Programs/PokemonLZA_BasicNavigation.cpp Source/PokemonLZA/Programs/PokemonLZA_BasicNavigation.h Source/PokemonLZA/Programs/PokemonLZA_ClothingBuyer.cpp @@ -1651,6 +1655,8 @@ file(GLOB LIBRARY_SOURCES Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_WildZoneCafe.h Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_WildZoneEntrance.cpp Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_WildZoneEntrance.h + Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_HelioptileHunter.cpp + Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_HelioptileHunter.h Source/PokemonLZA/Programs/TestPrograms/PokemonLZA_MoveBoxArrow.cpp Source/PokemonLZA/Programs/TestPrograms/PokemonLZA_MoveBoxArrow.h Source/PokemonLZA/Programs/TestPrograms/PokemonLZA_OverworldWatcher.cpp From 435d8fb3e2507853fc993653794fc0037cfd9c45 Mon Sep 17 00:00:00 2001 From: Phobos Date: Wed, 3 Dec 2025 15:20:14 -0300 Subject: [PATCH 2/5] removing wrong ref --- SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp index 1edcf6e30..a0b4a171b 100644 --- a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp +++ b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp @@ -35,7 +35,6 @@ #include "Programs/ShinyHunting/PokemonLZA_ShinyHunt_FlySpotReset.h" #include "Programs/ShinyHunting/PokemonLZA_ShuttleRun.h" #include "Programs/ShinyHunting/PokemonLZA_SewerHunter.h" -#include "Programs/ShinyHunting/PokemonLZA_ShinyHunt_OverworldMacro.h" #include "Programs/ShinyHunting/PokemonLZA_ShinyHunt_HelioptileHunter.h" // Non-Shiny Hunting @@ -90,7 +89,6 @@ std::vector PanelListFactory::make_panels() const{ ret.emplace_back(make_single_switch_program()); if (IS_BETA_VERSION){ ret.emplace_back(make_single_switch_program()); - ret.emplace_back(make_single_switch_program()); ret.emplace_back(make_single_switch_program()); } if (PreloadSettings::instance().DEVELOPER_MODE){ From 44b41650f7a9c87cc3cc6daa07d45450b3bef3a0 Mon Sep 17 00:00:00 2001 From: Phobos Date: Wed, 3 Dec 2025 15:25:48 -0300 Subject: [PATCH 3/5] Merge branch 'main' of phobos:PhobosLegacy/Arduino-Source --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 524cf123f..ca31c5706 100644 --- a/.gitignore +++ b/.gitignore @@ -62,3 +62,7 @@ __pycache__ *.ipynb CLAUDE.md + +build_*/ +.cache/* +Packages/* From ccf482a850d75e48c30fdb71c27a1c81a1bf0083 Mon Sep 17 00:00:00 2001 From: Phobos Date: Mon, 8 Dec 2025 06:36:21 -0300 Subject: [PATCH 4/5] removing spaces at the end --- .../Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp | 4 ++-- .../Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp b/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp index 6b674ff41..92024f444 100644 --- a/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp +++ b/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp @@ -240,6 +240,6 @@ namespace PokemonAutomation { send_program_status_notification(env, NOTIFICATION_STATUS); } } - } - } +} +} } diff --git a/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h b/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h index 1edd48f3b..0012bc774 100644 --- a/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h +++ b/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h @@ -43,11 +43,7 @@ namespace PokemonAutomation { EventNotificationOption NOTIFICATION_STATUS; EventNotificationsOption NOTIFICATIONS; }; - - - - - } - } +} +} } #endif From 122d8ad79432af06c4eafe22a58ff18791bd7e19 Mon Sep 17 00:00:00 2001 From: Phobos Date: Mon, 8 Dec 2025 06:40:30 -0300 Subject: [PATCH 5/5] removing spaces --- .../PokemonLZA_WeatherFinder.cpp | 424 +++++++++--------- .../PokemonLZA_WeatherFinder.h | 39 +- 2 files changed, 231 insertions(+), 232 deletions(-) diff --git a/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp b/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp index 92024f444..ee82e9c7d 100644 --- a/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp +++ b/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.cpp @@ -20,226 +20,226 @@ namespace PokemonAutomation { - namespace NintendoSwitch { - namespace PokemonLZA { - - using namespace Pokemon; - - WeatherFinder_Descriptor::WeatherFinder_Descriptor() - : SingleSwitchProgramDescriptor( - "PokemonLZA:WeatherFinder", - STRING_POKEMON + " LZA", "Weather Finder", - "Programs/PokemonLZA/WeatherFinder.html", - "Reset the weather by siting on a bench until reach the desired value", - ProgramControllerClass::StandardController_NoRestrictions, - FeedbackType::REQUIRED, - AllowCommandsWhenRunning::DISABLE_COMMANDS, - {} - ) - { - } +namespace NintendoSwitch { +namespace PokemonLZA { + +using namespace Pokemon; + +WeatherFinder_Descriptor::WeatherFinder_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonLZA:WeatherFinder", + STRING_POKEMON + " LZA", "Weather Finder", + "Programs/PokemonLZA/WeatherFinder.html", + "Reset the weather by siting on a bench until reach the desired value", + ProgramControllerClass::StandardController_NoRestrictions, + FeedbackType::REQUIRED, + AllowCommandsWhenRunning::DISABLE_COMMANDS, + {} + ) +{ +} - class WeatherFinder_Descriptor::Stats : public StatsTracker { - public: - Stats() - : loops(m_stats["Loops"]) - , errors(m_stats["Errors"]) - { - m_display_order.emplace_back("Loops"); - m_display_order.emplace_back("Errors", HIDDEN_IF_ZERO); - } - - std::atomic& loops; - std::atomic& errors; - }; - - std::unique_ptr WeatherFinder_Descriptor::make_stats() const { - return std::unique_ptr(new Stats()); - } +class WeatherFinder_Descriptor::Stats : public StatsTracker { +public: + Stats() + : loops(m_stats["Loops"]) + , errors(m_stats["Errors"]) + { + m_display_order.emplace_back("Loops"); + m_display_order.emplace_back("Errors", HIDDEN_IF_ZERO); + } + + std::atomic& loops; + std::atomic& errors; +}; + +std::unique_ptr WeatherFinder_Descriptor::make_stats() const { + return std::unique_ptr(new Stats()); +} - WeatherFinder::WeatherFinder() - : START_POSITION( - "Starting from day or night:", - { - {0, "day", "DAY"}, - {1, "night", "NIGHT"}, - }, - LockMode::LOCK_WHILE_RUNNING, - 0 - ) - , DESIRED_WEATHER( - "Stop on:", - { - {0, "day-clear", "Clear Day"}, - {1, "day-cloudy", "Cloudy Day"}, - {2, "day-rainy", "Rainy Day"}, - {3, "day-sunny", "Sunny Day"}, - {4, "day-foggy", "Foggy Day"}, - {5, "day-rainbow", "Rainbow Day"}, - }, - LockMode::LOCK_WHILE_RUNNING, - 0 - ) - , GO_HOME_WHEN_DONE(true) - , NOTIFICATION_STATUS("Status Update", true, false, std::chrono::seconds(3600)) - , NOTIFICATIONS({ - &NOTIFICATION_STATUS, - &NOTIFICATION_PROGRAM_FINISH, - &NOTIFICATION_ERROR_RECOVERABLE, - &NOTIFICATION_ERROR_FATAL, - }) - { - PA_ADD_OPTION(START_POSITION); - PA_ADD_OPTION(DESIRED_WEATHER); - PA_ADD_OPTION(GO_HOME_WHEN_DONE); - PA_ADD_OPTION(NOTIFICATIONS); - } +WeatherFinder::WeatherFinder() + : START_POSITION( + "Starting from day or night:", + { + {0, "day", "DAY"}, + {1, "night", "NIGHT"}, + }, + LockMode::LOCK_WHILE_RUNNING, + 0 + ) + , DESIRED_WEATHER( + "Stop on:", + { + {0, "day-clear", "Clear Day"}, + {1, "day-cloudy", "Cloudy Day"}, + {2, "day-rainy", "Rainy Day"}, + {3, "day-sunny", "Sunny Day"}, + {4, "day-foggy", "Foggy Day"}, + {5, "day-rainbow", "Rainbow Day"}, + }, + LockMode::LOCK_WHILE_RUNNING, + 0 + ) + , GO_HOME_WHEN_DONE(true) + , NOTIFICATION_STATUS("Status Update", true, false, std::chrono::seconds(3600)) + , NOTIFICATIONS({ + &NOTIFICATION_STATUS, + &NOTIFICATION_PROGRAM_FINISH, + &NOTIFICATION_ERROR_RECOVERABLE, + &NOTIFICATION_ERROR_FATAL, + }) +{ + PA_ADD_OPTION(START_POSITION); + PA_ADD_OPTION(DESIRED_WEATHER); + PA_ADD_OPTION(GO_HOME_WHEN_DONE); + PA_ADD_OPTION(NOTIFICATIONS); +} - // //Test Method - // void WeatherFinder::validate_weather(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { - // VideoSnapshot screen = env.console.video().snapshot(); - - // WeatherIconDetector clearDetector( - // WeatherIconType::Clear, - // &env.console.overlay() - // ); - // bool clearResult = clearDetector.detect(screen); - // env.log("Clear is " + std::to_string(clearResult)); - // // context.wait_for_all_requests(); - - // WeatherIconDetector sunnyDetector( - // WeatherIconType::Sunny, - // &env.console.overlay() - // ); - // bool sunnyResult = sunnyDetector.detect(screen); - // env.log("Sunny is " + std::to_string(sunnyResult)); - - // WeatherIconDetector rainyDetector( - // WeatherIconType::Rain, - // &env.console.overlay() - // ); - // bool rainyResult = rainyDetector.detect(screen); - // env.log("Rainy is " + std::to_string(rainyResult)); - - // WeatherIconDetector cloudyDetector( - // WeatherIconType::Cloudy, - // &env.console.overlay() - // ); - // bool cloudyResult = cloudyDetector.detect(screen); - // env.log("Cloudy is " + std::to_string(cloudyResult)); - - // WeatherIconDetector foggyDetector( - // WeatherIconType::Foggy, - // &env.console.overlay() - // ); - // bool foggyResult = foggyDetector.detect(screen); - // env.log("Foggy is " + std::to_string(foggyResult)); - - // WeatherIconDetector rainbowDetector( - // WeatherIconType::Rainbow, - // &env.console.overlay() - // ); - // bool rainbowResult = rainbowDetector.detect(screen); - // env.log("Rainbow is " + std::to_string(rainbowResult)); - // } - - WeatherIconType get_weather_type(size_t option) { - switch (option) { - case 0: - return WeatherIconType::Clear; - case 1: - return WeatherIconType::Cloudy; - case 2: - return WeatherIconType::Rain; - case 3: - return WeatherIconType::Sunny; - case 4: - return WeatherIconType::Foggy; - case 5: - return WeatherIconType::Rainbow; - default: - return WeatherIconType::Clear; - } - } +// //Test Method +// void WeatherFinder::validate_weather(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { +// VideoSnapshot screen = env.console.video().snapshot(); + +// WeatherIconDetector clearDetector( +// WeatherIconType::Clear, +// &env.console.overlay() +// ); +// bool clearResult = clearDetector.detect(screen); +// env.log("Clear is " + std::to_string(clearResult)); +// // context.wait_for_all_requests(); + +// WeatherIconDetector sunnyDetector( +// WeatherIconType::Sunny, +// &env.console.overlay() +// ); +// bool sunnyResult = sunnyDetector.detect(screen); +// env.log("Sunny is " + std::to_string(sunnyResult)); + +// WeatherIconDetector rainyDetector( +// WeatherIconType::Rain, +// &env.console.overlay() +// ); +// bool rainyResult = rainyDetector.detect(screen); +// env.log("Rainy is " + std::to_string(rainyResult)); + +// WeatherIconDetector cloudyDetector( +// WeatherIconType::Cloudy, +// &env.console.overlay() +// ); +// bool cloudyResult = cloudyDetector.detect(screen); +// env.log("Cloudy is " + std::to_string(cloudyResult)); + +// WeatherIconDetector foggyDetector( +// WeatherIconType::Foggy, +// &env.console.overlay() +// ); +// bool foggyResult = foggyDetector.detect(screen); +// env.log("Foggy is " + std::to_string(foggyResult)); + +// WeatherIconDetector rainbowDetector( +// WeatherIconType::Rainbow, +// &env.console.overlay() +// ); +// bool rainbowResult = rainbowDetector.detect(screen); +// env.log("Rainbow is " + std::to_string(rainbowResult)); +// } + +WeatherIconType get_weather_type(size_t option) { + switch (option) { + case 0: + return WeatherIconType::Clear; + case 1: + return WeatherIconType::Cloudy; + case 2: + return WeatherIconType::Rain; + case 3: + return WeatherIconType::Sunny; + case 4: + return WeatherIconType::Foggy; + case 5: + return WeatherIconType::Rainbow; + default: + return WeatherIconType::Clear; + } +} - std::string get_weather_name(size_t option) { - switch (option) { - case 0: - return "Clear"; - case 1: - return "Cloudy"; - case 2: - return "Rainy"; - case 3: - return "Sunny"; - case 4: - return "Foggy"; - case 5: - return "Rainbow"; - default: - return "Clear"; - } - } +std::string get_weather_name(size_t option) { + switch (option) { + case 0: + return "Clear"; + case 1: + return "Cloudy"; + case 2: + return "Rainy"; + case 3: + return "Sunny"; + case 4: + return "Foggy"; + case 5: + return "Rainbow"; + default: + return "Clear"; + } +} - void bench_it(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { - sit_on_bench(env.console, context); - pbf_move_left_joystick(context, 128, 255, 500ms, 500ms); - context.wait_for_all_requests(); - } +void bench_it(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { + sit_on_bench(env.console, context); + pbf_move_left_joystick(context, 128, 255, 500ms, 500ms); + context.wait_for_all_requests(); +} - void WeatherFinder::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { - WeatherFinder_Descriptor::Stats& stats = env.current_stats(); - assert_16_9_720p_min(env.logger(), env.console); - - bool isDay = !START_POSITION.current_value(); - - //Reset to day time - if (!isDay) { - env.log("Resetting to Day"); - bench_it(env, context); - isDay = true; - } - - WeatherIconType weatherType = get_weather_type(DESIRED_WEATHER.current_value()); - std::string weatherName = get_weather_name(DESIRED_WEATHER.current_value()); - - WeatherIconDetector detector( - weatherType, - &env.console.overlay() - ); - - while (true) { - env.log("Looking for " + weatherName + " " + std::string(isDay ? "day" : "night")); - - open_map(env.console, context); - VideoSnapshot screen = env.console.video().snapshot(); - - bool result = detector.detect(screen); - context.wait_for_all_requests(); - - if (result == 1) { - env.log("Desired weather found."); - GO_HOME_WHEN_DONE.run_end_of_program(context); - send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); - break; - } - else { - env.log("Desired weather not found. Continuing"); - pbf_press_button(context, BUTTON_PLUS, 500ms, 500ms); - for (uint8_t c = 0; c < 2; c++) { - bench_it(env, context); - isDay = !isDay; - env.log("Current time of day: " + std::string(isDay ? "DAY" : "NIGHT")); - } - stats.loops++; - context.wait_for_all_requests(); - } - env.update_stats(); - context.wait_for_all_requests(); - send_program_status_notification(env, NOTIFICATION_STATUS); - } +void WeatherFinder::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) { + WeatherFinder_Descriptor::Stats& stats = env.current_stats(); + assert_16_9_720p_min(env.logger(), env.console); + + bool isDay = !START_POSITION.current_value(); + + //Reset to day time + if (!isDay) { + env.log("Resetting to Day"); + bench_it(env, context); + isDay = true; + } + + WeatherIconType weatherType = get_weather_type(DESIRED_WEATHER.current_value()); + std::string weatherName = get_weather_name(DESIRED_WEATHER.current_value()); + + WeatherIconDetector detector( + weatherType, + &env.console.overlay() + ); + + while (true) { + env.log("Looking for " + weatherName + " " + std::string(isDay ? "day" : "night")); + + open_map(env.console, context); + VideoSnapshot screen = env.console.video().snapshot(); + + bool result = detector.detect(screen); + context.wait_for_all_requests(); + + if (result == 1) { + env.log("Desired weather found."); + GO_HOME_WHEN_DONE.run_end_of_program(context); + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); + break; + } + else { + env.log("Desired weather not found. Continuing"); + pbf_press_button(context, BUTTON_PLUS, 500ms, 500ms); + for (uint8_t c = 0; c < 2; c++) { + bench_it(env, context); + isDay = !isDay; + env.log("Current time of day: " + std::string(isDay ? "DAY" : "NIGHT")); } + stats.loops++; + context.wait_for_all_requests(); + } + env.update_stats(); + context.wait_for_all_requests(); + send_program_status_notification(env, NOTIFICATION_STATUS); + } +} } } } diff --git a/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h b/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h index 0012bc774..bb1572b98 100644 --- a/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h +++ b/SerialPrograms/Source/PokemonLZA/Programs/NonShinyHunting/PokemonLZA_WeatherFinder.h @@ -16,33 +16,32 @@ #include namespace PokemonAutomation { - namespace NintendoSwitch { - namespace PokemonLZA { +namespace NintendoSwitch { +namespace PokemonLZA { +class WeatherFinder_Descriptor : public SingleSwitchProgramDescriptor { +public: + WeatherFinder_Descriptor(); - class WeatherFinder_Descriptor : public SingleSwitchProgramDescriptor { - public: - WeatherFinder_Descriptor(); + class Stats; + virtual std::unique_ptr make_stats() const override; +}; - class Stats; - virtual std::unique_ptr make_stats() const override; - }; +class WeatherFinder : public SingleSwitchProgramInstance { +public: + WeatherFinder(); - class WeatherFinder : public SingleSwitchProgramInstance { - public: - WeatherFinder(); + virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; - virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; +private: + IntegerEnumDropdownOption START_POSITION; + IntegerEnumDropdownOption DESIRED_WEATHER; + GoHomeWhenDoneOption GO_HOME_WHEN_DONE; - private: - IntegerEnumDropdownOption START_POSITION; - IntegerEnumDropdownOption DESIRED_WEATHER; - GoHomeWhenDoneOption GO_HOME_WHEN_DONE; - - EventNotificationOption NOTIFICATION_STATUS; - EventNotificationsOption NOTIFICATIONS; - }; + EventNotificationOption NOTIFICATION_STATUS; + EventNotificationsOption NOTIFICATIONS; +}; } } }