diff --git a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp index f68768258..a686bce3b 100644 --- a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp +++ b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp @@ -32,6 +32,7 @@ #include "Programs/ShinyHunting/PokemonLZA_AutoFossil.h" #include "Programs/ShinyHunting/PokemonLZA_WildZoneEntrance.h" #include "Programs/ShinyHunting/PokemonLZA_ShinyHunt_FlySpotReset.h" +#include "Programs/ShinyHunting/PokemonLZA_ShuttleRun.h" // Non-Shiny Hunting #include "Programs/NonShinyHunting/PokemonLZA_StatsReset.h" @@ -85,6 +86,7 @@ std::vector PanelListFactory::make_panels() const{ } if (PreloadSettings::instance().DEVELOPER_MODE){ ret.emplace_back(make_single_switch_program()); + ret.emplace_back(make_single_switch_program()); } // ret.emplace_back("---- Non-Shiny Hunting ----"); diff --git a/SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShuttleRun.cpp b/SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShuttleRun.cpp new file mode 100644 index 000000000..ed3c03cc4 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShuttleRun.cpp @@ -0,0 +1,200 @@ +/* Shiny Hunt - Shuttle Run + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/Exceptions/OperationFailedException.h" +#include "CommonFramework/ProgramStats/StatsTracking.h" +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonFramework/VideoPipeline/VideoOverlay.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "NintendoSwitch/Programs/NintendoSwitch_GameEntry.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" +#include "Pokemon/Pokemon_Strings.h" +#include "PokemonLA/Inference/Sounds/PokemonLA_ShinySoundDetector.h" +#include "PokemonLZA/Programs/PokemonLZA_BasicNavigation.h" +#include "PokemonLZA_ShuttleRun.h" + +namespace PokemonAutomation { +namespace NintendoSwitch { +namespace PokemonLZA { + +using namespace Pokemon; + + +ShinyHunt_ShuttleRun_Descriptor::ShinyHunt_ShuttleRun_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonLZA:ShinyHunt-ShuttleRun", STRING_POKEMON + " LZA", + "Shuttle Run", + "Programs/PokemonLZA/ShinyHunt-ShuttleRun.html", + "Shiny hunt by repeatedly running back and forth between two points", + ProgramControllerClass::StandardController_NoRestrictions, FeedbackType::REQUIRED, + AllowCommandsWhenRunning::DISABLE_COMMANDS, {} + ) +{} +class ShinyHunt_ShuttleRun_Descriptor::Stats : public StatsTracker{ +public: + Stats() + : resets(m_stats["Rounds"]) + , shinies(m_stats["Shiny Sounds"]) + , errors(m_stats["Errors"]) + { + m_display_order.emplace_back("Rounds"); + m_display_order.emplace_back("Shiny Sounds"); + m_display_order.emplace_back("Errors", HIDDEN_IF_ZERO); + } + + std::atomic& resets; + std::atomic& shinies; + std::atomic& errors; +}; +std::unique_ptr ShinyHunt_ShuttleRun_Descriptor::make_stats() const{ + return std::unique_ptr(new Stats()); +} + + +ShinyHunt_ShuttleRun::ShinyHunt_ShuttleRun() + : DURATION("Duration:
Run the program this long.", LockMode::UNLOCK_WHILE_RUNNING, "5 h") + , ROUTE("Hunt Route:", + { + {Routes::KLEFKI, "klefki", "Sewers: Klefki"}, + {Routes::KLEFKI_INKAY_GOOMY, "klefki_inkay_goomy", "Sewers: Klefki+Inkay+Goomy"}, + {Routes::LITWICK, "litwick", "Sewers: Litwick"}, + {Routes::SKRELP, "skrelp", "Sewers: Skrelp"}, + // {Routes::SCRAGGY, "scraggy", "Sewers: Scraggy"}, + }, + LockMode::LOCK_WHILE_RUNNING, + Routes::KLEFKI) + , SHINY_DETECTED("Shiny Detected", "", "1000 ms", ShinySoundDetectedAction::NOTIFY_ON_FIRST_ONLY) + , NOTIFICATION_STATUS("Status Update", true, false, std::chrono::seconds(3600)) + , NOTIFICATIONS({ + &NOTIFICATION_STATUS, + &NOTIFICATION_PROGRAM_FINISH, + &NOTIFICATION_ERROR_RECOVERABLE, + &NOTIFICATION_ERROR_FATAL, + }) +{ + PA_ADD_STATIC(SHINY_REQUIRES_AUDIO); + PA_ADD_OPTION(DURATION); + PA_ADD_OPTION(ROUTE); + PA_ADD_OPTION(SHINY_DETECTED); + PA_ADD_OPTION(NOTIFICATIONS); +} + +namespace { + +void fly_back(ConsoleHandle& console, ProControllerContext& context) { + pbf_press_button(context, BUTTON_PLUS, 240ms, 80ms); // open map + context.wait_for_all_requests(); + pbf_wait(context, 500ms); + pbf_press_button(context, BUTTON_Y, 100ms, 100ms); // select fly point + pbf_mash_button(context, BUTTON_A, 1000ms); + wait_until_overworld(console, context, 10s); +} + +void route_klefki(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + context.wait_for_all_requests(); + ssf_press_button(context, BUTTON_B, 0ms, 500ms, 0ms); + pbf_move_left_joystick(context, 128, 0, 4900ms, 0ms); + pbf_move_left_joystick(context, 0, 128, 1000ms, 0ms); + pbf_press_button(context, BUTTON_L, 100ms, 500ms); + fly_back(env.console, context); +} + +void route_klefki_inkay_goomy(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + context.wait_for_all_requests(); + ssf_press_button(context, BUTTON_B, 0ms, 500ms, 0ms); + pbf_move_left_joystick(context, 128, 0, 8500ms, 0ms); + pbf_move_left_joystick(context, 255, 128, 1300ms, 0ms); + pbf_press_button(context, BUTTON_L, 100ms, 500ms); + fly_back(env.console, context); +} + +void route_litwick(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + context.wait_for_all_requests(); + ssf_press_button(context, BUTTON_B, 0ms, 500ms, 0ms); + pbf_move_left_joystick(context, 128, 0, 5000ms, 0ms); + pbf_move_left_joystick(context, 128, 255, 5500ms, 0ms); + pbf_wait(context, 500ms); +} + +void route_skrelp(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + context.wait_for_all_requests(); + ssf_press_button(context, BUTTON_B, 0ms, 500ms, 0ms); + pbf_move_left_joystick(context, 128, 255, 5000ms, 0ms); + pbf_move_left_joystick(context, 128, 0, 5500ms, 0ms); + pbf_wait(context, 500ms); +} + +void route_scraggy(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + +} +} // namespace + +void ShinyHunt_ShuttleRun::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + ShinyHunt_ShuttleRun_Descriptor::Stats& stats = + env.current_stats(); + ShinySoundHandler shiny_sound_handler(SHINY_DETECTED); + PokemonLA::ShinySoundDetector shiny_detector(env.console, [&](float error_coefficient) -> bool { + // Warning: This callback will be run from a different thread than this function. + stats.shinies++; + env.update_stats(); + env.console.overlay().add_log("Shiny Sound Detected!", COLOR_YELLOW); + return shiny_sound_handler.on_shiny_sound( + env, env.console, + stats.shinies, + error_coefficient + ); + }); + std::function loop; + switch (ROUTE) { + case Routes::KLEFKI: + loop = route_klefki; + break; + case Routes::KLEFKI_INKAY_GOOMY: + loop = route_klefki_inkay_goomy; + break; + case Routes::LITWICK: + loop = route_litwick; + break; + case Routes::SKRELP: + loop = route_skrelp; + break; + case Routes::SCRAGGY: + loop = route_scraggy; + break; + default: + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "route not implemented", + env.console + ); + } + WallClock start_time = current_time(); + pbf_press_button(context, BUTTON_L, 100ms, 100ms); // connect + + run_until( + env.console, context, + [&](ProControllerContext& context){ + do{ + shiny_sound_handler.process_pending(context); + send_program_status_notification(env, NOTIFICATION_STATUS); + stats.resets++; + loop(env, context); + env.update_stats(); + }while (current_time() < start_time + DURATION.get()); + }, + {{shiny_detector}} + ); + + shiny_sound_handler.process_pending(context); + go_home(env.console, context); + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); +} + + +} // namespace PokemonLZA +} // namespace NintendoSwitch +} // namespace PokemonAutomation diff --git a/SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShuttleRun.h b/SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShuttleRun.h new file mode 100644 index 000000000..4f8cbcd03 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShuttleRun.h @@ -0,0 +1,62 @@ +/* Shiny Hunt - Shuttle Run + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonLZA_Shuttle_Run_H +#define PokemonAutomation_PokemonLZA_Shuttle_Run_H + +#include "Common/Cpp/Options/EnumDropdownOption.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_ShuttleRun_Descriptor : public SingleSwitchProgramDescriptor { +public: + ShinyHunt_ShuttleRun_Descriptor(); + + class Stats; + virtual std::unique_ptr make_stats() const override; +}; + + +class ShinyHunt_ShuttleRun : public SingleSwitchProgramInstance { +public: + ShinyHunt_ShuttleRun(); + + virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; + + enum class Routes{ + KLEFKI, + KLEFKI_INKAY_GOOMY, + LITWICK, + SKRELP, + SCRAGGY, + WILD_ZONE_19, + FIRE_STARTERS, + DRATINI, + CUSTOMISED_MACRO = 255, + }; + +private: + PokemonLA::ShinyRequiresAudioText SHINY_REQUIRES_AUDIO; + MillisecondsOption DURATION; + EnumDropdownOption ROUTE; + ShinySoundDetectedActionOption SHINY_DETECTED; + EventNotificationOption NOTIFICATION_STATUS; + EventNotificationsOption NOTIFICATIONS; +}; + + +} // namespace PokemonLZA +} // namespace NintendoSwitch +} // namespace PokemonAutomation +#endif diff --git a/SerialPrograms/SourceFiles.cmake b/SerialPrograms/SourceFiles.cmake index 906aad2ab..0f6f30133 100644 --- a/SerialPrograms/SourceFiles.cmake +++ b/SerialPrograms/SourceFiles.cmake @@ -1635,6 +1635,8 @@ file(GLOB LIBRARY_SOURCES Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_FlySpotReset.h Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_OverworldReset.cpp Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_OverworldReset.h + Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShuttleRun.h + Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShuttleRun.cpp Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_WildZoneEntrance.cpp Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_WildZoneEntrance.h Source/PokemonLZA/Programs/TestPrograms/PokemonLZA_MoveBoxArrow.cpp