diff --git a/SerialPrograms/BuildInstructions/Build-Windows-Qt6.8.3.md b/SerialPrograms/BuildInstructions/Build-Windows-Qt6.8.3.md index 21165e9ff4..e54cf6386d 100644 --- a/SerialPrograms/BuildInstructions/Build-Windows-Qt6.8.3.md +++ b/SerialPrograms/BuildInstructions/Build-Windows-Qt6.8.3.md @@ -7,13 +7,13 @@ The installation order here is important. While other orderings may work, this is the specific order that we have tested. And the Qt installation must be the last thing installed. 1. Install Visual Studio 2022: - 1. [Download Page](https://docs.microsoft.com/en-us/visualstudio/releases/2022/release-notes) - 2. Make sure you select the C++ development tools. + 1. [Download Page](https://docs.microsoft.com/en-us/visualstudio/releases/2022/release-notes) + 2. Make sure you select the C++ development tools. 2. Install Windows Development SDK: - 1. [Download Page](https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/) + 1. [Download Page](https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/) 3. Install CMake: - 1. [Download Page](https://cmake.org/download/) - 2. When prompted select, "Add CMake to the system PATH for all users". + 1. [Download Page](https://cmake.org/download/) + 2. When prompted select, "Add CMake to the system PATH for all users". ## Install Qt 6.8.3: @@ -23,16 +23,16 @@ Unlike with Qt 5.12, there is no offline installer for it. So you have two optio If you are ok with creating an account with Qt and using their online installer, then use this method. -1. Download the online installer from here: https://www.qt.io/download-qt-Images/ -3. Select the following options: - - Qt 6.8.3 - - MSVC 2022 64-bit - - Sources - - Additional Libraries - - Qt Image Formats - - Qt Multimedia - - Qt Serial Port - - Qt Debug Information Files +1. Download the online installer from here: https://www.qt.io/download-qt-installer-oss/ +2. Select the following options: + - Qt 6.8.3 + - MSVC 2022 64-bit + - Sources + - Additional Libraries + - Qt Image Formats + - Qt Multimedia + - Qt Serial Port + - Qt Debug Information Files ![](Images/Windows-Install-Qt6.8.3-Custom.png) ![](Images/Windows-Install-Qt6.8.3-Components.png) @@ -43,12 +43,12 @@ If you repeatedly run into an error involving "SSL handshake failed", you will n If you are unable or unwilling to use the online installer, the alternative is to copy an installation directly into your system. To do this, you will need to download the installation from us, and copy it into your C drive. -1. Join our [Discord server](https://discord.gg/cQ4gWxN) and ask for the link to the Qt6 standalone. Someone will DM you with a link*. +1. Join our [Discord server](https://discord.gg/cQ4gWxN) and ask for the link to the Qt6 standalone. Someone will DM you with a link\*. 2. Download `Qt6.8.3.7z` and decompress it. You can use [7-zip](https://www.7-zip.org/) to decompress it. This will create a folder with the same name. 3. Move this folder to `C:\`. It will probably ask you for permissions to do it. 4. Navigate to: `C:\Qt6.8.3\Tools\QtCreator\bin\` and create a shortcut to `qtcreator.exe`. Copy this shortcut to somewhere convenient. (By default this shortcut is named, `Qt Creator 16.0.0 (Community)`) -*This Qt6 standalone file is 3GB in size and is being hosted by our staff for our own developers. We don't want the entire world converging here and overrunning the server. +\*This Qt6 standalone file is 3GB in size and is being hosted by our staff for our own developers. We don't want the entire world converging here and overrunning the server. ## Setup: @@ -62,8 +62,8 @@ If you are unable or unwilling to use the online installer, the alternative is t 5. Click on `File` -> `Open File or Project`. 6. Navigate to `SerialPrograms` and select `CMakeLists.txt`. 7. It will then ask you to configure the project. Ensure `Desktop Qt 6.8.3 MSVC2022 64bit` and `Release with Debug Information` are selected. - - Ensure the build directory for `Desktop_Qt_6_8_2_MSVC2022_64bit-RelWithDebInfo` is located in the root of the `Arduino-Source` repo, and not buried in subfolders (e.g. `build` or `SerialPrograms`). - - Click `Configure Project`. + - Ensure the build directory for `Desktop_Qt_6_8_2_MSVC2022_64bit-RelWithDebInfo` is located in the root of the `Arduino-Source` repo, and not buried in subfolders (e.g. `build` or `SerialPrograms`). + - Click `Configure Project`. ![](Images/Windows-configure-project-qt-creator-13.png) @@ -79,13 +79,13 @@ If you are unable or unwilling to use the online installer, the alternative is t - Click `Projects` on the left sidebar. - In `Build directory`, ensure the build directory for `Desktop_Qt_6_8_3_MSVC2022_64bit-RelWithDebInfo` is located in the root of the `Arduino-Source` repo, and not buried in subfolders (e.g. `build` or `SerialPrograms`). - - e.g. change the default build directory from: `Arduino-Source/SerialPrograms/build/Desktop_Qt_6_8_3_MSVC2022_64bit-RelWithDebInfo` + - e.g. change the default build directory from: `Arduino-Source/SerialPrograms/build/Desktop_Qt_6_8_3_MSVC2022_64bit-RelWithDebInfo` - to: `Arduino-Source/build-SerialPrograms-Desktop_Qt_6_8_3_MSVC2022_64bit-RelWithDebInfo` - ## Upgrading Qt components ### Installing newer Qt version + If you have already have older versions of Qt installed, but need to upgrade Qt components, you can use the Maintenance tool, which comes pre-instaled with Qt (C:\Qt\MaintenanceTool.exe). - When prompted, in `Maintenance Actions`, choose `Add or remove components`. @@ -93,15 +93,16 @@ If you have already have older versions of Qt installed, but need to upgrade Qt - Optional: In `Maintenance Actions`, you may also choose `Update components` as well. To update Qt Creator, and other components. ### Building with the newer Qt version + - Open the `SerialPrograms` project in Qt, as outlined in the "Setup" section above. - In the toolbar, click `Edit` -> `Preferences` - Under `Kits` tab, choose the newer Qt version (e.g. Desktop Qt 6.8.3) - + - Under `Compiler`, set it to Microsoft Visual C++ Compiler or Visual Studio, if not already set. - Click `Ok`, to save Kits preferences. - Click the Monitor symbol at the bottom left - + - Under `Kit`: choose the desired Qt version. - Under `Build`: choose `Release with Debug Information` @@ -109,18 +110,17 @@ If you have already have older versions of Qt installed, but need to upgrade Qt - Optional: Move the `UserSettings` folder from the old build folder to the new build folder, to keep your old settings, such as the dev key. ### Upgrade compiler + - Upgrade the compiler by installing a new version of Visual Studio. Ensure `Desktop development with C++` is checked, so the latest MSVC compiler is also installed. - Open the `SerialPrograms` project in Qt, as outlined in the "Setup" section above. - In the toolbar, click `Edit` -> `Preferences` -- Click the `Kits` tab on the left. Then click the `Compilers` tab, click `Re-detect` to refresh the list of compilers. Then click `Apply` in the bottom right. +- Click the `Kits` tab on the left. Then click the `Compilers` tab, click `Re-detect` to refresh the list of compilers. Then click `Apply` in the bottom right. - Back in the `Kits` tab, your newly installed compilers should now show up in the list of compilers. When building, if you get the error `yvals_core.h:931: error: STL1001: Unexpected compiler version, expected MSVC 19.42 or newer` (or something similar), consider deleting the old build folder, and rebuilding from scratch.
-**Discord Server:** - +**Discord Server:** [](https://discord.gg/cQ4gWxN) - diff --git a/SerialPrograms/Source/CommonFramework/Globals.cpp b/SerialPrograms/Source/CommonFramework/Globals.cpp index a705e5d631..5b4305a9a6 100644 --- a/SerialPrograms/Source/CommonFramework/Globals.cpp +++ b/SerialPrograms/Source/CommonFramework/Globals.cpp @@ -25,7 +25,7 @@ namespace PokemonAutomation{ const bool IS_BETA_VERSION = true; const int PROGRAM_VERSION_MAJOR = 0; -const int PROGRAM_VERSION_MINOR = 58; +const int PROGRAM_VERSION_MINOR = 59; const int PROGRAM_VERSION_PATCH = 3; const std::string PROGRAM_VERSION_BASE = diff --git a/SerialPrograms/Source/CommonFramework/ImageTypes/ImageViewPlanar32.h b/SerialPrograms/Source/CommonFramework/ImageTypes/ImageViewPlanar32.h index 3c03c9c6e8..1ae09f6733 100644 --- a/SerialPrograms/Source/CommonFramework/ImageTypes/ImageViewPlanar32.h +++ b/SerialPrograms/Source/CommonFramework/ImageTypes/ImageViewPlanar32.h @@ -9,6 +9,7 @@ #include #include "Common/Compiler.h" +#include "Common/Cpp/ImageResolution.h" namespace PokemonAutomation{ @@ -35,6 +36,7 @@ class ImageViewPlanar32{ PA_FORCE_INLINE size_t bytes_per_row () const{ return m_bytes_per_row; } PA_FORCE_INLINE size_t width () const{ return m_width; } PA_FORCE_INLINE size_t height () const{ return m_height; } + PA_FORCE_INLINE Resolution size () const{ return Resolution(m_width, m_height); } PA_FORCE_INLINE size_t total_pixels () const{ return m_width * m_height; } // Direct Pixel Access diff --git a/SerialPrograms/Source/CommonFramework/ProgramStats/StatsDatabase.cpp b/SerialPrograms/Source/CommonFramework/ProgramStats/StatsDatabase.cpp index b7c44799a5..394a4c48c9 100644 --- a/SerialPrograms/Source/CommonFramework/ProgramStats/StatsDatabase.cpp +++ b/SerialPrograms/Source/CommonFramework/ProgramStats/StatsDatabase.cpp @@ -35,6 +35,7 @@ const std::map STATS_DATABASE_ALIASES{ {"Shiny Hunt Autonomous - Fishing", "PokemonSwSh:ShinyHuntAutonomousFishing"}, {"Shiny Hunt Autonomous - Overworld", "PokemonSwSh:ShinyHuntAutonomousOverworld"}, {"PokemonSV:StatsResetBloodmoon", "PokemonSV:StatsResetEventBattle"}, + {"PokemonLZA:ShinyHunt-Bench", "PokemonLZA:ShinyHunt-BenchSit"}, }; diff --git a/SerialPrograms/Source/CommonTools/ImageMatch/WaterfillTemplateMatcher.cpp b/SerialPrograms/Source/CommonTools/ImageMatch/WaterfillTemplateMatcher.cpp index fa87444d7b..966fe83988 100644 --- a/SerialPrograms/Source/CommonTools/ImageMatch/WaterfillTemplateMatcher.cpp +++ b/SerialPrograms/Source/CommonTools/ImageMatch/WaterfillTemplateMatcher.cpp @@ -77,8 +77,8 @@ WaterfillTemplateMatcher::WaterfillTemplateMatcher( } } -double WaterfillTemplateMatcher::rmsd(const ImageViewRGB32& image) const{ - if (!image || !check_image(image)){ +double WaterfillTemplateMatcher::rmsd(Resolution input_resolution, const ImageViewRGB32& image) const{ + if (!image || !check_image(input_resolution, image)){ return 99999.; } return m_matcher->rmsd(image); @@ -125,7 +125,11 @@ bool WaterfillTemplateMatcher::check_area_ratio(double candidate_area_ratio) con return pass; } -double WaterfillTemplateMatcher::rmsd_precropped(const ImageViewRGB32& cropped_image, const WaterfillObject& object) const{ +double WaterfillTemplateMatcher::rmsd_precropped( + Resolution input_resolution, + const ImageViewRGB32& cropped_image, + const WaterfillObject& object +) const{ // XXX // dump_debug_image(global_logger_command_line(), "CommonFramework/WaterfillTemplateMatcher", "rmsd_precropped_input", cropped_image); @@ -142,7 +146,7 @@ double WaterfillTemplateMatcher::rmsd_precropped(const ImageViewRGB32& cropped_i // static int c = 0; // cout << c << endl; - double rmsd = this->rmsd(cropped_image); + double rmsd = this->rmsd(input_resolution, cropped_image); // cout << "rmsd = " << rmsd << endl; @@ -153,7 +157,11 @@ double WaterfillTemplateMatcher::rmsd_precropped(const ImageViewRGB32& cropped_i return rmsd; } -double WaterfillTemplateMatcher::rmsd_original(const ImageViewRGB32& original_image, const WaterfillObject& object) const{ +double WaterfillTemplateMatcher::rmsd_original( + Resolution input_resolution, + const ImageViewRGB32& original_image, + const WaterfillObject& object +) const{ if (PreloadSettings::debug().IMAGE_TEMPLATE_MATCHING){ cout << "rmsd_original()" << endl; @@ -172,7 +180,10 @@ double WaterfillTemplateMatcher::rmsd_original(const ImageViewRGB32& original_im return 99999.; } - double rmsd = this->rmsd(extract_box_reference(original_image, object)); + double rmsd = this->rmsd( + input_resolution, + extract_box_reference(original_image, object) + ); if (PreloadSettings::debug().IMAGE_TEMPLATE_MATCHING){ cout << "Passed aspect and area ratio check, rmsd = " << rmsd << endl; } diff --git a/SerialPrograms/Source/CommonTools/ImageMatch/WaterfillTemplateMatcher.h b/SerialPrograms/Source/CommonTools/ImageMatch/WaterfillTemplateMatcher.h index 120e652989..742cf51c73 100644 --- a/SerialPrograms/Source/CommonTools/ImageMatch/WaterfillTemplateMatcher.h +++ b/SerialPrograms/Source/CommonTools/ImageMatch/WaterfillTemplateMatcher.h @@ -9,6 +9,7 @@ #include #include "Common/Cpp/Color.h" +#include "Common/Cpp/ImageResolution.h" #include "CommonFramework/ImageTools/ImageBoxes.h" #include "CommonTools/ImageMatch/ExactImageMatcher.h" @@ -51,7 +52,7 @@ class WaterfillTemplateMatcher{ // In case the image is invalid, return a large value. // It also calls the virtual function `check_image()` on the image. // If the function returns false, then return a large value. - double rmsd(const ImageViewRGB32& image) const; + double rmsd(Resolution input_resolution, const ImageViewRGB32& image) const; // Compute RMSD of the object on the image against the template. // The input `cropped_image` is already cropped from a full image using the bounding box of the input waterfill `object`. @@ -59,7 +60,11 @@ class WaterfillTemplateMatcher{ // The waterfill object's aspect ratio and area ratio are checked against template's. Return a large value // if the check fails. // See `double rmsd(const ImageViewRGB32& image) const` on the details of comparing the image against the template. - virtual double rmsd_precropped(const ImageViewRGB32& cropped_image, const WaterfillObject& object) const; + virtual double rmsd_precropped( + Resolution input_resolution, + const ImageViewRGB32& cropped_image, + const WaterfillObject& object + ) const; // Compute RMSD of the object on the image against the template. // It will crop the original image using the bounding box of the waterfill object, then compare the cropped @@ -67,13 +72,17 @@ class WaterfillTemplateMatcher{ // The waterfill object's aspect ratio and area ratio are checked against template's. Return a large value // if the check fails. // See `double rmsd(const ImageViewRGB32& image) const` on the details of comparing the image against the template. - virtual double rmsd_original(const ImageViewRGB32& original_image, const WaterfillObject& object) const; + virtual double rmsd_original( + Resolution input_resolution, + const ImageViewRGB32& original_image, + const WaterfillObject& object + ) const; // Return the image template mesh const ImageRGB32& image_template() const { return m_matcher->image_template(); } protected: - virtual bool check_image(const ImageViewRGB32& image) const{ return true; }; + virtual bool check_image(Resolution input_resolution, const ImageViewRGB32& image) const{ return true; }; bool check_aspect_ratio(size_t candidate_width, size_t candidate_height) const; bool check_area_ratio(double candidate_area_ratio) const; diff --git a/SerialPrograms/Source/CommonTools/Images/WaterfillUtilities.cpp b/SerialPrograms/Source/CommonTools/Images/WaterfillUtilities.cpp index fffb14ad68..0482162799 100644 --- a/SerialPrograms/Source/CommonTools/Images/WaterfillUtilities.cpp +++ b/SerialPrograms/Source/CommonTools/Images/WaterfillUtilities.cpp @@ -74,10 +74,11 @@ std::pair remove_center_pixels( } bool match_template_by_waterfill( - const ImageViewRGB32 &image, - const ImageMatch::WaterfillTemplateMatcher &matcher, - const std::vector> &filters, - const std::pair &area_thresholds, + Resolution input_resolution, + const ImageViewRGB32& image, + const ImageMatch::WaterfillTemplateMatcher& matcher, + const std::vector>& filters, + const std::pair& area_thresholds, double rmsd_threshold, std::function check_matched_object) { @@ -133,12 +134,18 @@ bool match_template_by_waterfill( if (object.area > area_thresholds.second){ continue; } - double rmsd = matcher.rmsd_original(image, object); + double rmsd = matcher.rmsd_original(input_resolution, image, object); if (PreloadSettings::debug().IMAGE_TEMPLATE_MATCHING){ std::cout << "Object rmsd: " << rmsd << std::endl; } if (rmsd < rmsd_threshold){ +#if 0 + std::cout << "Object rmsd: " << rmsd << std::endl; +// static int c = 0; +// extract_box_reference(image, object).save("match-" + std::to_string(c++) + ".png"); +#endif + detected = true; if (check_matched_object(object)){ diff --git a/SerialPrograms/Source/CommonTools/Images/WaterfillUtilities.h b/SerialPrograms/Source/CommonTools/Images/WaterfillUtilities.h index 40c05bc048..5020c7dba5 100644 --- a/SerialPrograms/Source/CommonTools/Images/WaterfillUtilities.h +++ b/SerialPrograms/Source/CommonTools/Images/WaterfillUtilities.h @@ -10,6 +10,7 @@ #include #include +#include "Common/Cpp/ImageResolution.h" #include "CommonFramework/ImageTypes/BinaryImage.h" namespace PokemonAutomation{ @@ -54,10 +55,11 @@ std::pair remove_center_pixels( // check_matched_object: if a matcher is found, pass the matched object to this function. If the function returns true, stop the // entire template matching operation. bool match_template_by_waterfill( - const ImageViewRGB32 &image, - const ImageMatch::WaterfillTemplateMatcher &matcher, + Resolution input_resolution, + const ImageViewRGB32& image, + const ImageMatch::WaterfillTemplateMatcher& matcher, const std::vector> &filters, - const std::pair &area_thresholds, + const std::pair& area_thresholds, double rmsd_threshold, std::function check_matched_object); diff --git a/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp b/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp index 54e8dfcd69..31e566f23e 100644 --- a/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp +++ b/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp @@ -146,6 +146,7 @@ #include "PokemonLGPE/Inference/Battles/PokemonLGPE_BattleArrowDetector.h" #include "PokemonLZA/Inference/PokemonLZA_DialogDetector.h" #include "PokemonLZA/Programs/PokemonLZA_GameEntry.h" +#include "PokemonLZA/Programs/PokemonLZA_BasicNavigation.h" @@ -274,6 +275,7 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope& // using namespace PokemonBDSP; // using namespace PokemonLA; // using namespace PokemonSV; + using namespace PokemonLZA; [[maybe_unused]] Logger& logger = env.logger(); [[maybe_unused]] ConsoleHandle& console = env.consoles[0]; @@ -284,7 +286,13 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope& VideoOverlaySet overlays(overlay); + while (true){ + sit_on_bench(console, context); + } + + +#if 0 while (true){ ssf_press_button(context, BUTTON_ZL, 160ms, 800ms, 200ms); ssf_press_button(context, BUTTON_PLUS, 320ms, 840ms); @@ -293,7 +301,7 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope& pbf_press_button(context, BUTTON_X, 80ms, 24ms); pbf_press_button(context, BUTTON_B, 80ms, 24ms); } - +#endif #if 0 diff --git a/SerialPrograms/Source/PanelLists.cpp b/SerialPrograms/Source/PanelLists.cpp index 57f4d04a3c..d9d186a643 100644 --- a/SerialPrograms/Source/PanelLists.cpp +++ b/SerialPrograms/Source/PanelLists.cpp @@ -54,7 +54,9 @@ ProgramSelect::ProgramSelect(QWidget& parent, PanelHolder& holder) add(std::make_unique()); add(std::make_unique()); - add(std::make_unique()); + if (PreloadSettings::instance().DEVELOPER_MODE){ + add(std::make_unique()); + } add(std::make_unique()); diff --git a/SerialPrograms/Source/PokemonBDSP/PokemonBDSP_Settings.cpp b/SerialPrograms/Source/PokemonBDSP/PokemonBDSP_Settings.cpp index 8f66de723e..718f19a741 100644 --- a/SerialPrograms/Source/PokemonBDSP/PokemonBDSP_Settings.cpp +++ b/SerialPrograms/Source/PokemonBDSP/PokemonBDSP_Settings.cpp @@ -39,17 +39,17 @@ GameSettings::GameSettings() ) , m_start_game_timings("Start Game Timings:") , START_GAME_WAIT0( - "2. Start Game Wait:
Wait this long for the game to load.", + "Start Game Wait:
Wait this long for the game to load.", LockMode::LOCK_WHILE_RUNNING, "300 s" ) , ENTER_GAME_MASH0( - "3. Enter Game Mash:
Mash A for this long to enter the game.", + "Enter Game Mash:
Mash A for this long to enter the game.", LockMode::LOCK_WHILE_RUNNING, "5000 ms" ) , ENTER_GAME_WAIT0( - "4. Enter Game Wait:
Wait this long for the game to enter the overworld.", + "Enter Game Wait:
Wait this long for the game to enter the overworld.", LockMode::LOCK_WHILE_RUNNING, "300 s" ) diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcDetector.cpp b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcDetector.cpp index 57f32cf7d6..142330c97f 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcDetector.cpp +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcDetector.cpp @@ -69,7 +69,11 @@ ArcDetector::ArcDetector() } ) {} -void ArcDetector::process_object(const ImageViewRGB32& image, const WaterfillObject& object){ +void ArcDetector::process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object +){ ImagePixelBox object_box; if (ArcMatcher::left().matches(object_box, image, object)){ m_left.emplace_back(object_box); diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcDetector.h b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcDetector.h index b38b66a07b..a8b8a58ad7 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcDetector.h +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcDetector.h @@ -18,7 +18,11 @@ namespace PokemonLA{ class ArcDetector : public WhiteObjectDetector{ public: ArcDetector(); - virtual void process_object(const ImageViewRGB32& image, const WaterfillObject& object) override; + virtual void process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object + ) override; virtual void finish(const ImageViewRGB32& image) override; private: diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcPhoneDetector.cpp b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcPhoneDetector.cpp index 963c0c42ae..acb98277ff 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcPhoneDetector.cpp +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcPhoneDetector.cpp @@ -45,7 +45,11 @@ ArcPhoneTracker::ArcPhoneTracker() ) {} -void ArcPhoneTracker::process_object(const ImageViewRGB32& image, const WaterfillObject& object){ +void ArcPhoneTracker::process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object +){ // cout << "asdf" << endl; // static int c = 0; // cout << "c = " << c << endl; @@ -60,7 +64,7 @@ void ArcPhoneTracker::process_object(const ImageViewRGB32& image, const Waterfil // cout << (double)object.width() / image.width() << endl; - double rmsd = ArcPhoneMatcher::instance().rmsd_original(image, object); + double rmsd = ArcPhoneMatcher::instance().rmsd_original(input_resolution, image, object); // cout << "rmsd = " << rmsd << endl; if (rmsd < 80){ // cout << "rmsd = " << rmsd << endl; diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcPhoneDetector.h b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcPhoneDetector.h index e46c714033..a3c97ed86c 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcPhoneDetector.h +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ArcPhoneDetector.h @@ -31,7 +31,11 @@ class ArcPhoneTracker : public WhiteObjectDetector{ public: ArcPhoneTracker(); - virtual void process_object(const ImageViewRGB32& image, const WaterfillObject& object) override; + virtual void process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object + ) override; virtual void finish(const ImageViewRGB32& image) override; }; diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BattleSpriteArrowDetector.cpp b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BattleSpriteArrowDetector.cpp index e779bdf70f..690a7afe01 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BattleSpriteArrowDetector.cpp +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BattleSpriteArrowDetector.cpp @@ -42,8 +42,16 @@ BattleSpriteArrowTracker::BattleSpriteArrowTracker() ) {} -void BattleSpriteArrowTracker::process_object(const ImageViewRGB32& image, const WaterfillObject& object){ - double rmsd = BattleSpriteArrowMatcher::instance().rmsd_original(image, object); +void BattleSpriteArrowTracker::process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object +){ + double rmsd = BattleSpriteArrowMatcher::instance().rmsd_original( + input_resolution, + image, + object + ); if (rmsd < 80){ m_detections.emplace_back(object); } diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BattleSpriteArrowDetector.h b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BattleSpriteArrowDetector.h index 1512bfce42..6a14332d26 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BattleSpriteArrowDetector.h +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BattleSpriteArrowDetector.h @@ -32,7 +32,11 @@ class BattleSpriteArrowTracker : public WhiteObjectDetector{ public: BattleSpriteArrowTracker(); - virtual void process_object(const ImageViewRGB32& image, const WaterfillObject& object) override; + virtual void process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object + ) override; virtual void finish(const ImageViewRGB32& image) override; }; diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BubbleDetector.cpp b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BubbleDetector.cpp index e19c7661b5..b7132522fb 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BubbleDetector.cpp +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BubbleDetector.cpp @@ -56,7 +56,11 @@ class BubbleMatcher : public ImageMatch::SubObjectTemplateMatcher{ BubbleDetector::BubbleDetector() : WhiteObjectDetector(COLOR_GREEN, {Color(0xffb0b0b0)}) {} -void BubbleDetector::process_object(const ImageViewRGB32& image, const WaterfillObject& object){ +void BubbleDetector::process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object +){ if (object.area < 200){ return; } diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BubbleDetector.h b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BubbleDetector.h index 6f0d3d41fa..77b6881a3e 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BubbleDetector.h +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_BubbleDetector.h @@ -18,7 +18,11 @@ namespace PokemonLA{ class BubbleDetector : public WhiteObjectDetector{ public: BubbleDetector(); - virtual void process_object(const ImageViewRGB32& image, const WaterfillObject& object) override; + virtual void process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object + ) override; virtual void finish(const ImageViewRGB32& image) override; }; diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ButtonDetector.cpp b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ButtonDetector.cpp index 632d2b2bf7..d69efec3b4 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ButtonDetector.cpp +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ButtonDetector.cpp @@ -17,7 +17,7 @@ namespace PokemonLA{ namespace{ -const char* templatePath(ButtonType type){ +const char* template_path(ButtonType type){ switch (type){ case ButtonType::ButtonA: return "PokemonLA/Buttons/ButtonA-Template.png"; @@ -55,7 +55,7 @@ const char* button_name(ButtonType type){ } } -const ButtonMatcher& getButtonMatcher(ButtonType type){ +const ButtonMatcher& get_button_matcher(ButtonType type){ switch (type){ case ButtonType::ButtonA: return ButtonMatcher::A(); @@ -76,12 +76,15 @@ const ButtonMatcher& getButtonMatcher(ButtonType type){ } -ButtonMatcher::ButtonMatcher(ButtonType type, size_t min_width, size_t max_width, double max_rmsd) +ButtonMatcher::ButtonMatcher(ButtonType type, size_t min_width, size_t min_height, double max_rmsd) : WaterfillTemplateMatcher( - templatePath(type), Color(0xff808008), Color(0xffffffff), 100 + template_path(type), + Color(0xff808008), + Color(0xffffffff), + 100 ) , m_min_width(min_width) - , m_min_height(max_width) + , m_min_height(min_height) , m_max_rmsd(max_rmsd) {} const ButtonMatcher& ButtonMatcher::A(){ @@ -125,17 +128,25 @@ ButtonTracker::ButtonTracker(ButtonType type) Color(0xffd0d0d0), } ) - , m_matcher(getButtonMatcher(type)) + , m_matcher(get_button_matcher(type)) {} -void ButtonTracker::process_object(const ImageViewRGB32& image, const WaterfillObject& object){ +void ButtonTracker::process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object +){ // cout << "asdf" << endl; // static int c = 0; // extract_box(image, object).save("test-" + std::to_string(c++) + ".png"); // image.save("test-" + std::to_string(c++) + "-A.png"); // extract_box(image, object).save("test-" + std::to_string(c++) + "-B.png"); - double rmsd = m_matcher.rmsd_precropped(extract_box_reference(image, object), object); + double rmsd = m_matcher.rmsd_precropped( + input_resolution, + extract_box_reference(image, object), + object + ); // cout << "rmsd = " << rmsd << endl; // cout << "max = " << m_matcher.m_max_rmsd << endl; if (rmsd < m_matcher.m_max_rmsd){ diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ButtonDetector.h b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ButtonDetector.h index 024297e215..fdd9a52e31 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ButtonDetector.h +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_ButtonDetector.h @@ -31,7 +31,7 @@ enum class ButtonType{ class ButtonMatcher : public ImageMatch::WaterfillTemplateMatcher{ public: - ButtonMatcher(ButtonType type, size_t min_width, size_t max_width, double max_rmsd); + ButtonMatcher(ButtonType type, size_t min_width, size_t min_height, double max_rmsd); static const ButtonMatcher& A(); static const ButtonMatcher& B(); static const ButtonMatcher& Plus(); @@ -39,7 +39,7 @@ class ButtonMatcher : public ImageMatch::WaterfillTemplateMatcher{ static const ButtonMatcher& ArrowLeft(); static const ButtonMatcher& ArrowRight(); - virtual bool check_image(const ImageViewRGB32& image) const override{ + virtual bool check_image(Resolution input_resolution, const ImageViewRGB32& image) const override{ return image.width() >= m_min_width && image.height() >= m_min_height; }; @@ -55,7 +55,11 @@ class ButtonTracker : public WhiteObjectDetector{ public: ButtonTracker(ButtonType type); - virtual void process_object(const ImageViewRGB32& image, const WaterfillObject& object) override; + virtual void process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object + ) override; virtual void finish(const ImageViewRGB32& image) override; private: diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_DialogueEllipseDetector.cpp b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_DialogueEllipseDetector.cpp index d25f55f81b..92f75488dd 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_DialogueEllipseDetector.cpp +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_DialogueEllipseDetector.cpp @@ -42,8 +42,12 @@ DialogueEllipseTracker::DialogueEllipseTracker() ) {} -void DialogueEllipseTracker::process_object(const ImageViewRGB32& image, const WaterfillObject& object){ - double rmsd = DialogueEllipseMatcher::instance().rmsd_original(image, object); +void DialogueEllipseTracker::process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object +){ + double rmsd = DialogueEllipseMatcher::instance().rmsd_original(input_resolution, image, object); if (rmsd < 80){ m_detections.emplace_back(object); } diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_DialogueEllipseDetector.h b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_DialogueEllipseDetector.h index 3f72aba30c..985d065bb4 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_DialogueEllipseDetector.h +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_DialogueEllipseDetector.h @@ -33,7 +33,11 @@ class DialogueEllipseTracker : public WhiteObjectDetector{ public: DialogueEllipseTracker(); - virtual void process_object(const ImageViewRGB32& image, const WaterfillObject& object) override; + virtual void process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object + ) override; virtual void finish(const ImageViewRGB32& image) override; }; diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_DialogueYellowArrowDetector.cpp b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_DialogueYellowArrowDetector.cpp index 3a4392508a..d824e613a8 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_DialogueYellowArrowDetector.cpp +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_DialogueYellowArrowDetector.cpp @@ -77,6 +77,7 @@ bool DialogueYellowArrowDetector::process_frame(const ImageViewRGB32& frame, Wal const size_t min_size = size_t(200 * screen_scale * screen_scale); const bool detected = match_template_by_waterfill( + frame.size(), extract_box_reference(frame, YELLOW_ARROW_BOX), DialogueYellowArrowMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_FlagDetector.cpp b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_FlagDetector.cpp index ddfefb848c..9e69063369 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_FlagDetector.cpp +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_FlagDetector.cpp @@ -105,7 +105,11 @@ FlagDetector::FlagDetector() } ) {} -void FlagDetector::process_object(const ImageViewRGB32& image, const WaterfillObject& object){ +void FlagDetector::process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object +){ // cout << "FlagDetector::process_object()" << endl; if (object.area < 50){ return; @@ -234,13 +238,17 @@ std::vector> make_digit_matchers(){ } -std::pair read_digit(const ImageViewRGB32& image, const WaterfillObject& object){ +std::pair read_digit( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object +){ static const std::vector> MATCHERS = make_digit_matchers(); double best_rmsd = 99999; int best_digit = -1; for (const auto& item : MATCHERS){ // cout << item.first << " : " << << endl; - double rmsd = item.second.rmsd_original(image, object); + double rmsd = item.second.rmsd_original(input_resolution, image, object); if (best_rmsd > rmsd){ best_rmsd = rmsd; best_digit = item.first; @@ -307,7 +315,7 @@ int read_flag_distance(const ImageViewRGB32& screen, double flag_x, double flag_ // static int c = 0; // extract_box_reference(image, object).save("image-" + std::to_string(c++) + ".png"); - std::pair digit = read_digit(image, object); + std::pair digit = read_digit(screen.size(), image, object); if (digit.second >= 0){ hits.emplace( object.min_x, diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_FlagDetector.h b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_FlagDetector.h index a9c17b2f0b..0e99befafd 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_FlagDetector.h +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_FlagDetector.h @@ -18,7 +18,11 @@ namespace PokemonLA{ class FlagDetector : public WhiteObjectDetector{ public: FlagDetector(); - virtual void process_object(const ImageViewRGB32& image, const WaterfillObject& object) override; + virtual void process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object + ) override; virtual void finish(const ImageViewRGB32& image) override; private: diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_MMOQuestionMarkDetector.cpp b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_MMOQuestionMarkDetector.cpp index ac72a3f917..d60a56a677 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_MMOQuestionMarkDetector.cpp +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_MMOQuestionMarkDetector.cpp @@ -85,7 +85,7 @@ const std::array hisui_map_boxes{{ }}; -bool detect_MMO_question_mark(const PokemonAutomation::ImageViewRGB32 &frame, const ImageFloatBox& box){ +bool detect_MMO_question_mark(const PokemonAutomation::ImageViewRGB32& frame, const ImageFloatBox& box){ auto image = extract_box_reference(frame, box); const double screen_rel_size = (frame.height() / 1080.0); @@ -99,6 +99,7 @@ bool detect_MMO_question_mark(const PokemonAutomation::ImageViewRGB32 &frame, co }; bool detected = match_template_by_waterfill( + frame.size(), image, MMOQuestionMarkBackgroundMatcher::instance(), { @@ -116,6 +117,7 @@ bool detect_MMO_question_mark(const PokemonAutomation::ImageViewRGB32 &frame, co const size_t min_curve_size = 250; const size_t max_curve_size = 450; detected = match_template_by_waterfill( + frame.size(), image, MMOQuestionMarkCurveMatcher::instance(), {{combine_rgb(180, 180, 180), combine_rgb(255, 255, 255)}}, {scale(min_curve_size), scale(max_curve_size)}, 100, @@ -181,6 +183,7 @@ std::vector MMOQuestionMarkDetector::detect_MMOs_on_region_map(co }; match_template_by_waterfill( + frame.size(), map_image, MMOQuestionMarkBackgroundMatcher::instance(), {{combine_rgb(0, 5, 30), combine_rgb(100, 130, 130)}}, {scale(min_bg_size), scale(max_bg_size)}, 110, diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_QuestMarkDetector.cpp b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_QuestMarkDetector.cpp index ddcfa54a2a..6cc4e68ac1 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_QuestMarkDetector.cpp +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_QuestMarkDetector.cpp @@ -63,7 +63,11 @@ QuestMarkDetector::QuestMarkDetector() } ) {} -void QuestMarkDetector::process_object(const ImageViewRGB32& image, const WaterfillObject& object){ +void QuestMarkDetector::process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object +){ ImagePixelBox object_box; if (QuestMarkMatcher::instance().matches(object_box, image, object)){ m_detections.emplace_back(object_box); diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_QuestMarkDetector.h b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_QuestMarkDetector.h index 2301f3f6af..dbb1e8541f 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_QuestMarkDetector.h +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_QuestMarkDetector.h @@ -18,7 +18,11 @@ namespace PokemonLA{ class QuestMarkDetector : public WhiteObjectDetector{ public: QuestMarkDetector(); - virtual void process_object(const ImageViewRGB32& image, const WaterfillObject& object) override; + virtual void process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object + ) override; }; diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_WhiteObjectDetector.cpp b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_WhiteObjectDetector.cpp index 739cd7def6..2ffa5aa5b5 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_WhiteObjectDetector.cpp +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_WhiteObjectDetector.cpp @@ -22,6 +22,7 @@ using namespace Kernels::Waterfill; void find_overworld_white_objects( + Resolution input_resolution, const std::vector>& detectors, const ImageViewRGB32& image ){ @@ -62,7 +63,7 @@ void find_overworld_white_objects( for (const auto& detector : detectors){ const std::set& thresholds = detector.first.thresholds(); if (thresholds.find((Color)filters[c].first) != thresholds.end()){ - detector.first.process_object(image, object); + detector.first.process_object(input_resolution, image, object); } } } @@ -132,7 +133,11 @@ bool WhiteObjectWatcher::process_frame(const ImageViewRGB32& frame, WallClock ti detector.first.clear(); } - find_overworld_white_objects(m_detectors, extract_box_reference(frame, m_box)); + find_overworld_white_objects( + frame.size(), + m_detectors, + extract_box_reference(frame, m_box) + ); m_overlays.clear(); for (auto& detector : m_detectors){ diff --git a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_WhiteObjectDetector.h b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_WhiteObjectDetector.h index aa19a31a83..b5de188476 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_WhiteObjectDetector.h +++ b/SerialPrograms/Source/PokemonLA/Inference/Objects/PokemonLA_WhiteObjectDetector.h @@ -48,7 +48,11 @@ class WhiteObjectDetector{ const std::vector& detections() const{ return m_detections; } void clear(){ m_detections.clear(); } - virtual void process_object(const ImageViewRGB32& image, const WaterfillObject& object) = 0; + virtual void process_object( + Resolution input_resolution, + const ImageViewRGB32& image, + const WaterfillObject& object + ) = 0; virtual void finish(const ImageViewRGB32& image){} protected: @@ -66,6 +70,7 @@ class WhiteObjectDetector{ void find_overworld_white_objects( + Resolution input_resolution, const std::vector>& detectors, const ImageViewRGB32& screen ); diff --git a/SerialPrograms/Source/PokemonLA/Inference/PokemonLA_MountDetector.cpp b/SerialPrograms/Source/PokemonLA/Inference/PokemonLA_MountDetector.cpp index b56ac640d4..f2e0eda279 100644 --- a/SerialPrograms/Source/PokemonLA/Inference/PokemonLA_MountDetector.cpp +++ b/SerialPrograms/Source/PokemonLA/Inference/PokemonLA_MountDetector.cpp @@ -58,17 +58,17 @@ ImageRGB32 make_MountMatcher2Image(const char* path){ ImageViewRGB32 cropped = extract_box_reference(image, object); // cropped.save("test-" + std::to_string(c++) + ".png"); - double current_rmsd_plus = ButtonMatcher::Plus().rmsd_precropped(cropped, object); + double current_rmsd_plus = ButtonMatcher::Plus().rmsd_precropped(image.size(), cropped, object); if (rmsd_plus > current_rmsd_plus){ rmsd_plus = current_rmsd_plus; plus = object; } - double current_rmsd_arrowL = ButtonMatcher::ArrowLeft().rmsd_precropped(cropped, object); + double current_rmsd_arrowL = ButtonMatcher::ArrowLeft().rmsd_precropped(image.size(), cropped, object); if (rmsd_arrowL > current_rmsd_arrowL){ rmsd_arrowL = current_rmsd_arrowL; arrowL = object; } - double current_rmsd_arrowR = ButtonMatcher::ArrowRight().rmsd_precropped(cropped, object); + double current_rmsd_arrowR = ButtonMatcher::ArrowRight().rmsd_precropped(image.size(), cropped, object); if (rmsd_arrowR > current_rmsd_arrowR){ rmsd_arrowR = current_rmsd_arrowR; arrowR = object; @@ -430,19 +430,19 @@ MountState MountDetector::detect(const ImageViewRGB32& screen) const{ // Read the buttons. - double current_rmsd_plus = ButtonMatcher::Plus().rmsd_precropped(cropped, object); + double current_rmsd_plus = ButtonMatcher::Plus().rmsd_precropped(screen.size(), cropped, object); if (rmsd_plus > current_rmsd_plus){ rmsd_plus = current_rmsd_plus; plus = object; } // cout << "Arrow (left)" << endl; - double current_rmsd_arrowL = ButtonMatcher::ArrowLeft().rmsd_precropped(cropped, object); + double current_rmsd_arrowL = ButtonMatcher::ArrowLeft().rmsd_precropped(screen.size(), cropped, object); if (rmsd_arrowL > current_rmsd_arrowL){ rmsd_arrowL = current_rmsd_arrowL; arrowL = object; } // cout << "Arrow (right)" << endl; - double current_rmsd_arrowR = ButtonMatcher::ArrowRight().rmsd_precropped(cropped, object); + double current_rmsd_arrowR = ButtonMatcher::ArrowRight().rmsd_precropped(screen.size(), cropped, object); // cout << "rmsd_arrowR = " << rmsd_arrowR << endl; if (rmsd_arrowR > current_rmsd_arrowR){ rmsd_arrowR = current_rmsd_arrowR; @@ -459,16 +459,16 @@ MountState MountDetector::detect(const ImageViewRGB32& screen) const{ ImageViewRGB32 filtered_cropped = extract_box_reference(filtered.image, object); #if 1 - candidates.add_filtered(MountWyrdeerMatcher ::off().rmsd_precropped(filtered_cropped, object), MountState::WYRDEER_OFF); - candidates.add_direct (MountWyrdeerMatcher ::off().rmsd_precropped(cropped , object), MountState::WYRDEER_OFF); - candidates.add_filtered(MountUrsalunaMatcher ::off().rmsd_precropped(filtered_cropped, object), MountState::URSALUNA_OFF); - candidates.add_direct (MountUrsalunaMatcher ::off().rmsd_precropped(cropped , object), MountState::URSALUNA_OFF); - candidates.add_filtered(MountBasculegionMatcher ::off().rmsd_precropped(filtered_cropped, object), MountState::BASCULEGION_OFF); - candidates.add_direct (MountBasculegionMatcher ::off().rmsd_precropped(cropped , object), MountState::BASCULEGION_OFF); - candidates.add_filtered(MountSneaslerMatcher ::off().rmsd_precropped(filtered_cropped, object), MountState::SNEASLER_OFF); - candidates.add_direct (MountSneaslerMatcher ::off().rmsd_precropped(cropped , object), MountState::SNEASLER_OFF); - candidates.add_filtered(MountBraviaryMatcher ::off().rmsd_precropped(filtered_cropped, object), MountState::BRAVIARY_OFF); - candidates.add_direct (MountBraviaryMatcher ::off().rmsd_precropped(cropped , object), MountState::BRAVIARY_OFF); + candidates.add_filtered(MountWyrdeerMatcher ::off().rmsd_precropped(screen.size(), filtered_cropped, object), MountState::WYRDEER_OFF); + candidates.add_direct (MountWyrdeerMatcher ::off().rmsd_precropped(screen.size(), cropped , object), MountState::WYRDEER_OFF); + candidates.add_filtered(MountUrsalunaMatcher ::off().rmsd_precropped(screen.size(), filtered_cropped, object), MountState::URSALUNA_OFF); + candidates.add_direct (MountUrsalunaMatcher ::off().rmsd_precropped(screen.size(), cropped , object), MountState::URSALUNA_OFF); + candidates.add_filtered(MountBasculegionMatcher ::off().rmsd_precropped(screen.size(), filtered_cropped, object), MountState::BASCULEGION_OFF); + candidates.add_direct (MountBasculegionMatcher ::off().rmsd_precropped(screen.size(), cropped , object), MountState::BASCULEGION_OFF); + candidates.add_filtered(MountSneaslerMatcher ::off().rmsd_precropped(screen.size(), filtered_cropped, object), MountState::SNEASLER_OFF); + candidates.add_direct (MountSneaslerMatcher ::off().rmsd_precropped(screen.size(), cropped , object), MountState::SNEASLER_OFF); + candidates.add_filtered(MountBraviaryMatcher ::off().rmsd_precropped(screen.size(), filtered_cropped, object), MountState::BRAVIARY_OFF); + candidates.add_direct (MountBraviaryMatcher ::off().rmsd_precropped(screen.size(), cropped , object), MountState::BRAVIARY_OFF); #endif } @@ -548,16 +548,16 @@ MountState MountDetector::detect(const ImageViewRGB32& screen) const{ ImageViewRGB32 cropped = extract_box_reference(image, object); ImageViewRGB32 filtered_cropped = extract_box_reference(filtered.image, object); #if 1 - candidates.add_filtered(MountWyrdeerMatcher ::on().rmsd(filtered_cropped), MountState::WYRDEER_ON); - candidates.add_direct (MountWyrdeerMatcher ::on().rmsd(cropped ), MountState::WYRDEER_ON); - candidates.add_filtered(MountUrsalunaMatcher ::on().rmsd(filtered_cropped), MountState::URSALUNA_ON); - candidates.add_direct (MountUrsalunaMatcher ::on().rmsd(cropped ), MountState::URSALUNA_ON); - candidates.add_filtered(MountBasculegionMatcher ::on().rmsd(filtered_cropped), MountState::BASCULEGION_ON); - candidates.add_direct (MountBasculegionMatcher ::on().rmsd(cropped ), MountState::BASCULEGION_ON); - candidates.add_filtered(MountSneaslerMatcher ::on().rmsd(filtered_cropped), MountState::SNEASLER_ON); - candidates.add_direct (MountSneaslerMatcher ::on().rmsd(cropped ), MountState::SNEASLER_ON); - candidates.add_filtered(MountBraviaryMatcher ::on().rmsd(filtered_cropped), MountState::BRAVIARY_ON); - candidates.add_direct (MountBraviaryMatcher ::on().rmsd(cropped ), MountState::BRAVIARY_ON); + candidates.add_filtered(MountWyrdeerMatcher ::on().rmsd(screen.size(), filtered_cropped), MountState::WYRDEER_ON); + candidates.add_direct (MountWyrdeerMatcher ::on().rmsd(screen.size(), cropped ), MountState::WYRDEER_ON); + candidates.add_filtered(MountUrsalunaMatcher ::on().rmsd(screen.size(), filtered_cropped), MountState::URSALUNA_ON); + candidates.add_direct (MountUrsalunaMatcher ::on().rmsd(screen.size(), cropped ), MountState::URSALUNA_ON); + candidates.add_filtered(MountBasculegionMatcher ::on().rmsd(screen.size(), filtered_cropped), MountState::BASCULEGION_ON); + candidates.add_direct (MountBasculegionMatcher ::on().rmsd(screen.size(), cropped ), MountState::BASCULEGION_ON); + candidates.add_filtered(MountSneaslerMatcher ::on().rmsd(screen.size(), filtered_cropped), MountState::SNEASLER_ON); + candidates.add_direct (MountSneaslerMatcher ::on().rmsd(screen.size(), cropped ), MountState::SNEASLER_ON); + candidates.add_filtered(MountBraviaryMatcher ::on().rmsd(screen.size(), filtered_cropped), MountState::BRAVIARY_ON); + candidates.add_direct (MountBraviaryMatcher ::on().rmsd(screen.size(), cropped ), MountState::BRAVIARY_ON); #endif // extract_box(image, object).save("test-" + std::to_string(i) + ".png"); // i++; diff --git a/SerialPrograms/Source/PokemonLA/PokemonLA_Settings.cpp b/SerialPrograms/Source/PokemonLA/PokemonLA_Settings.cpp index bf12f0db7b..c5618aa52c 100644 --- a/SerialPrograms/Source/PokemonLA/PokemonLA_Settings.cpp +++ b/SerialPrograms/Source/PokemonLA/PokemonLA_Settings.cpp @@ -40,17 +40,17 @@ GameSettings::GameSettings() ) , m_start_game_timings("Start Game Timings:") , START_GAME_WAIT1( - "2. Start Game Wait:
Wait this long for the game to load.", + "Start Game Wait:
Wait this long for the game to load.", LockMode::LOCK_WHILE_RUNNING, "40 s" ) , ENTER_GAME_MASH0( - "3. Enter Game Mash:
Mash A for this long to enter the game.", + "Enter Game Mash:
Mash A for this long to enter the game.", LockMode::LOCK_WHILE_RUNNING, "5000 ms" ) , ENTER_GAME_WAIT0( - "4. Enter Game Wait:
Wait this long for the game to enter the overworld.", + "Enter Game Wait:
Wait this long for the game to enter the overworld.", LockMode::LOCK_WHILE_RUNNING, "15 s" ) diff --git a/SerialPrograms/Source/PokemonLGPE/PokemonLGPE_Settings.cpp b/SerialPrograms/Source/PokemonLGPE/PokemonLGPE_Settings.cpp index 844cc33bdc..d1554c0638 100644 --- a/SerialPrograms/Source/PokemonLGPE/PokemonLGPE_Settings.cpp +++ b/SerialPrograms/Source/PokemonLGPE/PokemonLGPE_Settings.cpp @@ -29,17 +29,17 @@ GameSettings::GameSettings() ) , m_start_game_timings("Start Game Timings:") , START_GAME_WAIT1( - "2. Start Game Wait:
Wait this long for the game to load.", + "Start Game Wait:
Wait this long for the game to load.", LockMode::LOCK_WHILE_RUNNING, "20 s" ) , ENTER_GAME_MASH0( - "3. Enter Game Mash:
Mash A for this long to enter the game.", + "Enter Game Mash:
Mash A for this long to enter the game.", LockMode::LOCK_WHILE_RUNNING, "5 s" ) , ENTER_GAME_WAIT0( - "4. Enter Game Wait:
Wait this long for the opening animations to finish.", + "Enter Game Wait:
Wait this long for the opening animations to finish.", LockMode::LOCK_WHILE_RUNNING, "15 s" ) diff --git a/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_ButtonDetector.cpp b/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_ButtonDetector.cpp new file mode 100644 index 0000000000..31a9e9f2f9 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_ButtonDetector.cpp @@ -0,0 +1,189 @@ +/* Button Detector + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "Kernels/Waterfill/Kernels_Waterfill_Types.h" +#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" +#include "CommonTools/Images/WaterfillUtilities.h" +#include "PokemonLZA_ButtonDetector.h" + +//#include +//using std::cout; +//using std::endl; + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + +const char* template_path(ButtonType type){ + switch (type){ + case ButtonType::ButtonA: + return "PokemonLZA/Buttons/ButtonA.png"; + case ButtonType::ButtonB: + return "PokemonLZA/Buttons/ButtonB.png"; + case ButtonType::ButtonX: + return "PokemonLZA/Buttons/ButtonX.png"; + case ButtonType::ButtonY: + return "PokemonLZA/Buttons/ButtonY.png"; + case ButtonType::ButtonL: + return "PokemonLZA/Buttons/ButtonL.png"; + case ButtonType::ButtonR: + return "PokemonLZA/Buttons/ButtonR.png"; + case ButtonType::ButtonPlus: + return "PokemonLZA/Buttons/ButtonPlus.png"; + case ButtonType::ButtonMinus: + return "PokemonLZA/Buttons/ButtonMinus.png"; + case ButtonType::ButtonRight: + return "PokemonLZA/Buttons/ButtonRight.png"; + default: + return ""; + } +} + +const char* button_name(ButtonType type){ + switch (type){ + case ButtonType::ButtonA: + return "A"; + case ButtonType::ButtonB: + return "B"; + case ButtonType::ButtonX: + return "X"; + case ButtonType::ButtonY: + return "Y"; + case ButtonType::ButtonL: + return "L"; + case ButtonType::ButtonR: + return "R"; + case ButtonType::ButtonPlus: + return "+"; + case ButtonType::ButtonMinus: + return "-"; + case ButtonType::ButtonRight: + return ">"; + default: + return ""; + } +} + +const ButtonMatcher& get_button_matcher(ButtonType type){ + switch (type){ + case ButtonType::ButtonA: + return ButtonMatcher::A(); + case ButtonType::ButtonB: + return ButtonMatcher::B(); + case ButtonType::ButtonX: + return ButtonMatcher::X(); + case ButtonType::ButtonY: + return ButtonMatcher::Y(); + case ButtonType::ButtonL: + return ButtonMatcher::L(); + case ButtonType::ButtonR: + return ButtonMatcher::R(); + case ButtonType::ButtonPlus: + return ButtonMatcher::Plus(); + case ButtonType::ButtonMinus: + return ButtonMatcher::Minus(); + case ButtonType::ButtonRight: + return ButtonMatcher::Right(); + default: + throw std::runtime_error("No corresponding ButtonMatcher for ButtonType"); + } +} + + +ButtonMatcher::ButtonMatcher(ButtonType type, size_t min_width, size_t min_height, double max_rmsd) + : WaterfillTemplateMatcher( + template_path(type), + Color(0xff808008), + Color(0xffffffff), + 100 + ) + , m_min_width(min_width) + , m_min_height(min_height) + , m_max_rmsd(max_rmsd) +{} + + + +ButtonDetector::ButtonDetector( + Color color, + ButtonType button_type, + const ImageFloatBox& box, + VideoOverlay* overlay +) + : m_color(color) + , m_matcher(get_button_matcher(button_type)) + , m_box(box) + , m_overlay(overlay) +{ + +} +void ButtonDetector::make_overlays(VideoOverlaySet& items) const{ + items.add(m_color, m_box); +} +bool ButtonDetector::detect(const ImageViewRGB32& screen){ + + double screen_rel_size = (screen.height() / 2160.0); + double screen_rel_size_2 = screen_rel_size * screen_rel_size; + + double min_area_3840p = 1000.0; +// double rmsd_threshold = 120.0; + size_t min_area = size_t(screen_rel_size_2 * min_area_3840p); + + const std::vector> FILTERS = { + {0xffc0c0c0, 0xffffffff}, + {0xffb0b0b0, 0xffffffff}, + {0xffa0a0a0, 0xffffffff}, + {0xff909090, 0xffffffff}, + {0xff808080, 0xffffffff}, + }; + + bool found = match_template_by_waterfill( + screen.size(), + extract_box_reference(screen, m_box), + m_matcher, + FILTERS, + {min_area, SIZE_MAX}, + m_matcher.m_max_rmsd, + [&](Kernels::Waterfill::WaterfillObject& object) -> bool { +// cout << "width = " << object.width() << ", height = " << object.height() << endl; + m_last_detected = translate_to_parent(screen, m_box, object); + return true; + } + ); + + if (m_overlay){ + if (found){ + m_last_detected_box.emplace(*m_overlay, m_last_detected, COLOR_GREEN); + }else{ + m_last_detected_box.reset(); + } + } + + return found; +} + + + + + + + + + + + + + + + + + + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_ButtonDetector.h b/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_ButtonDetector.h new file mode 100644 index 0000000000..f9bbf53547 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_ButtonDetector.h @@ -0,0 +1,126 @@ +/* Button Detector + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonLZA_ButtonDetector_H +#define PokemonAutomation_PokemonLZA_ButtonDetector_H + +#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" +#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" +#include "CommonTools/VisualDetector.h" +#include "CommonTools/InferenceCallbacks/VisualInferenceCallback.h" + +namespace PokemonAutomation{ + class Logger; +namespace NintendoSwitch{ +namespace PokemonLZA{ + + +enum class ButtonType{ + ButtonA, + ButtonB, + ButtonX, + ButtonY, + ButtonL, + ButtonR, + ButtonPlus, + ButtonMinus, + ButtonRight, +}; + + +class ButtonMatcher : public ImageMatch::WaterfillTemplateMatcher{ +public: + ButtonMatcher(ButtonType type, size_t min_width, size_t min_height, double max_rmsd); + static const ButtonMatcher& A(){ + static ButtonMatcher matcher(ButtonType::ButtonA, 60, 60, 70); + return matcher; + } + static const ButtonMatcher& B(){ + static ButtonMatcher matcher(ButtonType::ButtonB, 60, 60, 70); + return matcher; + } + static const ButtonMatcher& X(){ + static ButtonMatcher matcher(ButtonType::ButtonX, 60, 60, 70); + return matcher; + } + static const ButtonMatcher& Y(){ + static ButtonMatcher matcher(ButtonType::ButtonY, 60, 60, 70); + return matcher; + } + static const ButtonMatcher& L(){ + static ButtonMatcher matcher(ButtonType::ButtonL, 60, 60, 70); + return matcher; + } + static const ButtonMatcher& R(){ + static ButtonMatcher matcher(ButtonType::ButtonR, 60, 60, 70); + return matcher; + } + static const ButtonMatcher& Plus(){ + static ButtonMatcher matcher(ButtonType::ButtonPlus, 60, 60, 70); + return matcher; + } + static const ButtonMatcher& Minus(){ + static ButtonMatcher matcher(ButtonType::ButtonMinus, 60, 60, 70); + return matcher; + } + static const ButtonMatcher& Right(){ + static ButtonMatcher matcher(ButtonType::ButtonRight, 60, 60, 70); + return matcher; + } + + virtual bool check_image(Resolution input_resolution, const ImageViewRGB32& image) const override{ + size_t min_width = m_min_width * input_resolution.width / 3840; + size_t min_height = m_min_height * input_resolution.height / 2160; + return image.width() >= min_width && image.height() >= min_height; + }; + + size_t m_min_width; + size_t m_min_height; + double m_max_rmsd; +}; + + +class ButtonDetector : public StaticScreenDetector{ +public: + ButtonDetector( + Color color, + ButtonType button_type, + const ImageFloatBox& box, + VideoOverlay* overlay = nullptr + ); + virtual void make_overlays(VideoOverlaySet& items) const override; + virtual bool detect(const ImageViewRGB32& screen) override; + +private: + Color m_color; + const ButtonMatcher& m_matcher; + ImageFloatBox m_box; + VideoOverlay* m_overlay; + + ImageFloatBox m_last_detected; + std::optional m_last_detected_box; +}; +class ButtonWatcher : public DetectorToFinder{ +public: + ButtonWatcher( + Color color, + ButtonType button_type, + const ImageFloatBox& box, + VideoOverlay* overlay = nullptr, + std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250) + ) + : DetectorToFinder("ButtonWatcher", hold_duration, color, button_type, box, overlay) + {} +}; + + + + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_DialogDetector.cpp b/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_DialogDetector.cpp index 7b12a35690..6d07228099 100644 --- a/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_DialogDetector.cpp +++ b/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_DialogDetector.cpp @@ -9,15 +9,14 @@ //#include "CommonTools/Images/SolidColorTest.h" #include "PokemonLZA_DialogDetector.h" #include "CommonTools/Images/SolidColorTest.h" -#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" #include "CommonTools/Images/WaterfillUtilities.h" +#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" #include "CommonFramework/VideoPipeline/VideoOverlay.h" #include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" -// REMOVE -#include -using std::cout; -using std::endl; +//#include +//using std::cout; +//using std::endl; namespace PokemonAutomation{ namespace NintendoSwitch{ @@ -138,6 +137,7 @@ bool NormalDialogDetector::process_frame(const ImageViewRGB32& frame, WallClock const double green_line_rmsd_threshold = 50.0; const size_t min_green_line_size = size_t(screen_rel_size_2 * min_green_line_size_1080P); match_template_by_waterfill( + frame.size(), extract_box_reference(frame, m_title_green_line_box), DialogTitleGreenLineMatcher::instance(), green_line_filters, @@ -160,6 +160,7 @@ bool NormalDialogDetector::process_frame(const ImageViewRGB32& frame, WallClock const double black_arrow_rmsd_threshold = 120.0; const size_t min_black_arrow_size = size_t(screen_rel_size_2 * min_black_arrow_size_1080P); match_template_by_waterfill( + frame.size(), extract_box_reference(frame, m_black_arrow_box), DialogBlackArrowMatcher::instance(), black_arrow_filters, @@ -235,6 +236,7 @@ bool FlatWhiteDialogDetector::detect(const ImageViewRGB32& screen){ }; bool found = match_template_by_waterfill( + screen.size(), extract_box_reference(screen, m_arrow_box), DialogBlackArrowMatcher::instance(), FILTERS, @@ -296,6 +298,7 @@ bool BlueDialogDetector::detect(const ImageViewRGB32& screen){ }; bool found = match_template_by_waterfill( + screen.size(), extract_box_reference(screen, m_arrow_box), DialogWhiteArrowMatcher::instance(), FILTERS, @@ -345,6 +348,7 @@ bool ItemReceiveDetector::detect(const ImageViewRGB32& screen){ }; bool found = match_template_by_waterfill( + screen.size(), extract_box_reference(screen, m_arrow_box), DialogWhiteArrowMatcher::instance(), FILTERS, @@ -390,6 +394,7 @@ bool TealDialogDetector::detect(const ImageViewRGB32& screen){ }; bool found = match_template_by_waterfill( + screen.size(), extract_box_reference(screen, m_arrow_box), DialogTealArrowMatcher::instance(), FILTERS, diff --git a/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.cpp b/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.cpp index e208807b4c..6d3bd71918 100644 --- a/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.cpp +++ b/SerialPrograms/Source/PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.cpp @@ -72,16 +72,21 @@ bool SelectionArrowDetector::detect(const ImageViewRGB32& screen){ double screen_rel_size = (screen.height() / 1080.0); double screen_rel_size_2 = screen_rel_size * screen_rel_size; - double min_area_1080p = 700.0; - double rmsd_threshold = 120.0; + double min_area_1080p = 700; + double rmsd_threshold = 80; size_t min_area = size_t(screen_rel_size_2 * min_area_1080p); const std::vector> FILTERS = { + {0xff808000, 0xffffff7f}, + {0xff808000, 0xffdfff7f}, + {0xff80a000, 0xffffff7f}, + {0xff80a000, 0xffdfff7f}, {0xff80c000, 0xffffff7f}, {0xff80c000, 0xffdfff7f}, }; bool found = match_template_by_waterfill( + screen.size(), extract_box_reference(screen, m_arrow_box), SelectionArrowMatcher::matcher(m_type), FILTERS, diff --git a/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_ShinyDetectedAction.cpp b/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_ShinyDetectedAction.cpp new file mode 100644 index 0000000000..9609eea57b --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_ShinyDetectedAction.cpp @@ -0,0 +1,142 @@ +/* Shiny Detected Action + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include +//#include "Common/Cpp/Exceptions.h" +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonFramework/VideoPipeline/VideoFeed.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "Pokemon/Pokemon_Notification.h" +#include "PokemonLZA_ShinyDetectedAction.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + + + +ShinySoundDetectedActionOption::ShinySoundDetectedActionOption( + std::string label, std::string description, + std::string default_delay, + ShinySoundDetectedAction default_action +) + : GroupOption(std::move(label), LockMode::UNLOCK_WHILE_RUNNING) + , DESCRIPTION(std::move(description)) + , ACTION( + "Action:", + { + {ShinySoundDetectedAction::STOP_PROGRAM, "stop", "Stop program and go Home. Send notification."}, + {ShinySoundDetectedAction::NOTIFY_ON_FIRST_ONLY, "notify-first", "Keep running. Notify on first shiny sound only."}, + {ShinySoundDetectedAction::NOTIFY_ON_ALL, "notify-all", "Keep running. Notify on all shiny sounds."}, + }, + LockMode::UNLOCK_WHILE_RUNNING, + default_action + ) + , TAKE_VIDEO( + "Take Video:", + LockMode::UNLOCK_WHILE_RUNNING, + true + ) + , SCREENSHOT_DELAY( + "Screenshot Delay:
" + "Wait this long before taking a screenshot + video of the shiny.
" + "Set to zero to skip this. Don't set this too large or the shiny may run away!", + LockMode::UNLOCK_WHILE_RUNNING, + std::move(default_delay) + ) + , NOTIFICATIONS( + this->label(), + true, true, + ImageAttachmentMode::JPG, + {"Notifs", "Showcase"} + ) + , NOTES( + "" + "The shiny sound is not a reliable measure of shinies encountered:
" + "1. The sound only plays on a smaller radius than the spawn radius, so the vast majority of shinies are inaudible. " + "You will still need to manually run around to see if any shinies spawned out-of-range. " + "
" + "2. Secondly, it may play multiple times for the same shiny, so it may overcount. " + "If a shiny spawns next to you, it may play the sound on every reset afterwards. <\font>" + ) +{ + if (!DESCRIPTION.text().empty()){ + PA_ADD_STATIC(DESCRIPTION); + } + PA_ADD_OPTION(ACTION); + PA_ADD_OPTION(TAKE_VIDEO); + PA_ADD_OPTION(SCREENSHOT_DELAY); + + PA_ADD_STATIC(NOTES); +} + +bool ShinySoundDetectedActionOption::on_shiny_sound( + ProgramEnvironment& env, VideoStream& stream, ProControllerContext& context, + size_t current_count, + float error_coefficient +){ + ShinySoundDetectedAction action = ACTION; + + if (action == ShinySoundDetectedAction::NOTIFY_ON_FIRST_ONLY && current_count > 1){ + return false; + } + + { + std::ostringstream ss; + ss << "Detected Shiny Sound! (error coefficient = " << error_coefficient << ")"; + stream.log(ss.str(), COLOR_BLUE); + } + + if (TAKE_VIDEO){ + context.wait_for(SCREENSHOT_DELAY); + pbf_press_button(context, BUTTON_CAPTURE, 2 * TICKS_PER_SECOND, 0); + } + + std::vector> embeds; + + { + std::ostringstream ss; + ss << "Error Coefficient: "; + ss << error_coefficient; + ss << "\n(Shiny may not be visible on the screen.)"; + embeds.emplace_back("Detection Results:", ss.str()); + } + + send_program_notification( + env, NOTIFICATIONS, + Pokemon::COLOR_STAR_SHINY, + "Detected Shiny Sound", + embeds, "", + stream.video().snapshot(), true + ); + + return action == ShinySoundDetectedAction::STOP_PROGRAM; +} + + + + + + + + + + + + + + + + + + + + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_ShinyDetectedAction.h b/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_ShinyDetectedAction.h new file mode 100644 index 0000000000..6db0a5c538 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_ShinyDetectedAction.h @@ -0,0 +1,62 @@ +/* Shiny Detected Action + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonLZA_ShinyDetectedAction_H +#define PokemonAutomation_PokemonLZA_ShinyDetectedAction_H + +#include "Common/Cpp/Options/GroupOption.h" +#include "Common/Cpp/Options/StaticTextOption.h" +#include "Common/Cpp/Options/BooleanCheckBoxOption.h" +#include "Common/Cpp/Options//TimeDurationOption.h" +//#include "Common/Cpp/Options/SimpleIntegerOption.h" +#include "CommonFramework/Notifications/EventNotificationOption.h" +#include "CommonFramework/Tools/VideoStream.h" +#include "NintendoSwitch/Controllers/NintendoSwitch_ProController.h" + +namespace PokemonAutomation{ + class ProgramEnvironment; +namespace NintendoSwitch{ +namespace PokemonLZA{ + + +enum class ShinySoundDetectedAction{ + STOP_PROGRAM, + NOTIFY_ON_FIRST_ONLY, + NOTIFY_ON_ALL, +}; + + +class ShinySoundDetectedActionOption : public GroupOption, public ConfigOption::Listener{ +public: + ShinySoundDetectedActionOption( + std::string label, std::string description, + std::string default_delay, + ShinySoundDetectedAction default_action + ); + + bool on_shiny_sound( + ProgramEnvironment& env, VideoStream& stream, ProControllerContext& context, + size_t current_count, + float error_coefficient + ); + + StaticTextOption DESCRIPTION; + EnumDropdownOption ACTION; + BooleanCheckBoxOption TAKE_VIDEO; + MillisecondsOption SCREENSHOT_DELAY; + EventNotificationOption NOTIFICATIONS; + + StaticTextOption NOTES; +}; + + + + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp index 8991d91676..56a3634f1d 100644 --- a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp +++ b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp @@ -10,8 +10,11 @@ #include "PokemonLZA_Settings.h" -#include "Programs/PokemonLZA_RestaurantFarmer.h" +#include "Programs/PokemonLZA_BeldumHunter.h" #include "Programs/PokemonLZA_ClothingBuyer.h" +#include "Programs/PokemonLZA_RestaurantFarmer.h" +#include "Programs/PokemonLZA_ShinyHunt_BenchSit.h" +#include "Programs/PokemonLZA_ShinyHunt_OverworldReset.h" #include "Programs/TestPrograms/PokemonLZA_OverworldWatcher.h" namespace PokemonAutomation{ @@ -31,8 +34,15 @@ std::vector PanelListFactory::make_panels() const{ ret.emplace_back(make_settings()); ret.emplace_back("---- General ----"); - 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("---- Shiny Hunting ----"); + 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){ diff --git a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Settings.cpp b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Settings.cpp index b68ea9db7f..74e6345838 100644 --- a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Settings.cpp +++ b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Settings.cpp @@ -24,17 +24,17 @@ GameSettings::GameSettings() , m_general("General Settings:") , m_start_game_timings("Start Game Timings:") , START_GAME_WAIT( - "2. Start Game Wait:
Wait this long for the game to load.", + "Start Game Wait:
Wait this long for the game to load.", LockMode::LOCK_WHILE_RUNNING, "40 s" ) - , ENTER_GAME_MASH( - "3. Enter Game Mash:
Mash A for this long to enter the game.", + , ENTER_GAME_MASH0( + "Enter Game Mash:
Mash A for this long to enter the game.", LockMode::LOCK_WHILE_RUNNING, - "5000 ms" + "3000 ms" ) , ENTER_GAME_WAIT( - "4. Enter Game Wait:
Wait this long for the game to enter the overworld.", + "Enter Game Wait:
Wait this long for the game to enter the overworld.", LockMode::LOCK_WHILE_RUNNING, "15 s" ) @@ -46,7 +46,7 @@ GameSettings::GameSettings() PA_ADD_STATIC(m_start_game_timings); PA_ADD_OPTION(START_GAME_WAIT); - PA_ADD_OPTION(ENTER_GAME_MASH); + PA_ADD_OPTION(ENTER_GAME_MASH0); PA_ADD_OPTION(ENTER_GAME_WAIT); PA_ADD_STATIC(m_advanced_options); diff --git a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Settings.h b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Settings.h index 29817d5198..dac97374d5 100644 --- a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Settings.h +++ b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Settings.h @@ -26,7 +26,7 @@ class GameSettings : public BatchOption{ SectionDividerOption m_start_game_timings; MillisecondsOption START_GAME_WAIT; - MillisecondsOption ENTER_GAME_MASH; + MillisecondsOption ENTER_GAME_MASH0; MillisecondsOption ENTER_GAME_WAIT; SectionDividerOption m_advanced_options; diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_BasicNavigation.cpp b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_BasicNavigation.cpp new file mode 100644 index 0000000000..63edff2330 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_BasicNavigation.cpp @@ -0,0 +1,132 @@ +/* Basic Navigation + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/Exceptions/OperationFailedException.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "CommonTools/VisualDetectors/BlackScreenDetector.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" +#include "PokemonLZA/Inference/PokemonLZA_ButtonDetector.h" +#include "PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.h" +#include "PokemonLZA/Inference/PokemonLZA_DialogDetector.h" +#include "PokemonLZA_BasicNavigation.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + + + +void sit_on_bench( + ConsoleHandle& console, ProControllerContext& context +){ +#if 0 + while (true){ + ButtonWatcher buttonA(COLOR_RED, ButtonType::ButtonA, {0, 0, 1, 1}, &console.overlay()); + BlueDialogWatcher dialog(COLOR_YELLOW, &console.overlay()); + SelectionArrowWatcher arrow(COLOR_BLUE, &console.overlay(), SelectionArrowType::RIGHT, {0.5, 0.4, 0.3, 0.3}); + BlackScreenOverWatcher black_screen(COLOR_BLUE); + + int ret = wait_until( + console, context, + 10000ms, + { + buttonA, + dialog, + arrow, + black_screen, + } + ); + context.wait_for(100ms); + + switch (ret){ + case 0: + console.log("Detected floating A button..."); + pbf_press_button(context, BUTTON_A, 200ms, 200ms); + continue; + case 1: + console.log("Detected dialog..."); + pbf_press_button(context, BUTTON_B, 200ms, 200ms); + continue; + case 2: + console.log("Detected selection arrow..."); + pbf_press_button(context, BUTTON_A, 200ms, 200ms); + continue; + case 3: + console.log("Detected day change."); + break; + default: + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "sit_on_bench(): No recognized state after 10 seconds.", + console + ); + } + } +#endif + + { + BlackScreenOverWatcher black_screen(COLOR_BLUE); + + int ret = run_until( + console, context, + [](ProControllerContext& context){ + pbf_mash_button(context, BUTTON_A, 5000ms); + for (int c = 0; c < 3; c++){ + pbf_move_left_joystick(context, 128, 255, 1000ms, 0ms); + pbf_mash_button(context, BUTTON_B, 1000ms); + pbf_mash_button(context, BUTTON_A, 5000ms); + } + }, + {black_screen} + ); + + switch (ret){ + case 0: + console.log("Detected day change."); + break; + default: + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "sit_on_bench(): No transition detected after 4 attempts.", + console + ); + } + } + { + ButtonWatcher buttonA(COLOR_RED, ButtonType::ButtonA, {0, 0, 1, 1}, &console.overlay()); + + int ret = run_until( + console, context, + [](ProControllerContext& context){ + // Can't just hold it down since sometimes it doesn't register. + for (int c = 0; c < 60; c++){ + pbf_move_left_joystick(context, 128, 255, 800ms, 200ms); + } + }, + {buttonA} + ); + + switch (ret){ + case 0: + console.log("Detected floating A button..."); + break; + default: + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "sit_on_bench(): Unable to detect bench after 60 seconds.", + console + ); + } + } + +} + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_BasicNavigation.h b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_BasicNavigation.h new file mode 100644 index 0000000000..d1c1e85e4b --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_BasicNavigation.h @@ -0,0 +1,27 @@ +/* Basic Navigation + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonLZA_BasicNavigation_H +#define PokemonAutomation_PokemonLZA_BasicNavigation_H + +#include "NintendoSwitch/Controllers/NintendoSwitch_ProController.h" +#include "NintendoSwitch/NintendoSwitch_ConsoleHandle.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + + +void sit_on_bench( + ConsoleHandle& console, ProControllerContext& context +); + + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_BeldumHunter.cpp b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_BeldumHunter.cpp new file mode 100644 index 0000000000..2f71c7542d --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_BeldumHunter.cpp @@ -0,0 +1,210 @@ +/* Beldum Hunter + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/Exceptions/OperationFailedException.h" +#include "CommonFramework/ProgramStats/StatsTracking.h" +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonFramework/VideoPipeline/VideoFeed.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "CommonTools/VisualDetectors/BlackScreenDetector.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" +#include "Pokemon/Pokemon_Strings.h" +#include "PokemonLZA/PokemonLZA_Settings.h" +#include "PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.h" +#include "PokemonLZA/Inference/PokemonLZA_DialogDetector.h" +#include "PokemonLZA/Programs/PokemonLZA_GameEntry.h" +#include "PokemonLA/Inference/Sounds/PokemonLA_ShinySoundDetector.h" +#include "PokemonLZA_BeldumHunter.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + +using namespace Pokemon; + +BeldumHunter_Descriptor::BeldumHunter_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonLZA:ShinyHunt-Beldum", + STRING_POKEMON + " LZA", "Shiny Hunt - Beldum", + "Programs/PokemonLZA/BeldumHunter.html", + "Repeatedly enter Lysandre Labs to shiny hunt Beldum.", + ProgramControllerClass::StandardController_NoRestrictions, + FeedbackType::VIDEO_AUDIO, + AllowCommandsWhenRunning::DISABLE_COMMANDS + ) +{} +class BeldumHunter_Descriptor::Stats : public StatsTracker, public PokemonLA::ShinyStatIncrementer{ +public: + Stats() + : attempts(m_stats["Attempts"]) + , errors(m_stats["Errors"]) + , shinies(m_stats["Shinies"]) + { + m_display_order.emplace_back("Attempts"); + m_display_order.emplace_back("Errors", HIDDEN_IF_ZERO); + m_display_order.emplace_back("Shinies"); + } + virtual void add_shiny() override{ + shinies++; + } + + std::atomic& attempts; + std::atomic& errors; + std::atomic& shinies; +}; +std::unique_ptr BeldumHunter_Descriptor::make_stats() const{ + return std::unique_ptr(new Stats()); +} + + +BeldumHunter::BeldumHunter() + : TAKE_VIDEO("Take Video:", LockMode::UNLOCK_WHILE_RUNNING, true) + , NOTIFICATION_SHINY( + "Shiny Found", + true, true, ImageAttachmentMode::JPG, + {"Notifs", "Showcase"} + ) + , NOTIFICATION_STATUS("Status Update", true, false, std::chrono::seconds(3600)) + , NOTIFICATIONS({ + &NOTIFICATION_SHINY, + &NOTIFICATION_STATUS, + &NOTIFICATION_PROGRAM_FINISH, + &NOTIFICATION_ERROR_RECOVERABLE, + &NOTIFICATION_ERROR_FATAL, + }) +{ + PA_ADD_STATIC(SHINY_REQUIRES_AUDIO); + PA_ADD_OPTION(TAKE_VIDEO); + PA_ADD_OPTION(NOTIFICATIONS); +} + +bool BeldumHunter::run_iteration(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + BeldumHunter_Descriptor::Stats& stats = env.current_stats(); + stats.attempts++; + { + float shiny_coefficient = 1.0; + PokemonLA::ShinySoundDetector shiny_detector(env.logger(), [&](float error_coefficient) -> bool { + shiny_coefficient = error_coefficient; + return true; + }); + + BlackScreenOverWatcher entered(COLOR_RED, { 0.074, 0.044, 0.826, 0.278 }); + + env.log("Entering the lab."); + context.wait_for_all_requests(); + int ret = run_until( + env.console, context, + [&](ProControllerContext& context) { + pbf_controller_state(context, BUTTON_B, DPAD_NONE, 128, 0, 128, 128, 100); + pbf_wait(context, 5000ms); + }, + { {entered} } + ); + if (ret == 0) { + env.log("Entered the lab."); + } else { + env.log("Failed to enter the lab."); + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "Failed to warp.", + env.console + ); + } + pbf_wait(context, 1000ms); + context.wait_for_all_requests(); + + int res = run_until( + env.console, context, + [&](ProControllerContext& context) { + + env.log("Go straight toward the elevator."); + pbf_controller_state(context, BUTTON_B, DPAD_NONE, 128, 0, 128, 128, 460); + + env.log("Go left to where the Noivern spawns, then forward and then left."); + pbf_controller_state(context, BUTTON_B, DPAD_NONE, 0, 128, 128, 128, 300); + pbf_controller_state(context, BUTTON_B, DPAD_NONE, 128, 0, 128, 128, 80); + pbf_controller_state(context, BUTTON_B, DPAD_NONE, 0, 128, 128, 128, 180); + + env.log("Through the Houndoom room and down the hallway."); + pbf_controller_state(context, BUTTON_B, DPAD_NONE, 128, 255, 128, 128, 140); + pbf_controller_state(context, BUTTON_B, DPAD_NONE, 0, 128, 128, 128, 200); + pbf_controller_state(context, BUTTON_B, DPAD_NONE, 128, 0, 128, 128, 340); + + env.log("Final hallway to Beldum room."); + pbf_controller_state(context, BUTTON_B, DPAD_NONE, 0, 128, 128, 128, 400); + pbf_press_button(context, BUTTON_L, 40ms, 40ms); + context.wait_for_all_requests(); + }, + { {shiny_detector} } + ); + shiny_detector.throw_if_no_sound(); + + if (res == 0) { + env.log("Shiny detected!"); + if (TAKE_VIDEO) { + pbf_press_button(context, BUTTON_CAPTURE, 2 * TICKS_PER_SECOND, 0); + } + + return true; + } + } + env.console.log("No shiny detected. Resetting."); + + pbf_press_button(context, BUTTON_HOME, 160ms, 3000ms); + reset_game_from_home(env, env.console, context, false); + + return false; +} + + +void BeldumHunter::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + BeldumHunter_Descriptor::Stats& stats = env.current_stats(); + + /* + * Setup: Face the opening to the labs. Save the game. + * + * Program will enter the Labs and then run to the Beldum room. + * No shiny, reset the game. Repeat. + * Every time we enter the Beldum will reroll. We reset the game instead of running back + * due to the wild Pokemon spawns. + * This can also hunt Noivern, Houndour, and Houndoom. + */ + + while (true){ + env.update_stats(); + send_program_status_notification(env, NOTIFICATION_STATUS); + try{ + bool shiny_found = run_iteration(env, context); + if (shiny_found) { + stats.shinies++; + env.update_stats(); + + pbf_press_button(context, BUTTON_HOME, 160ms, 3000ms); + + send_program_notification(env, NOTIFICATION_SHINY, + COLOR_YELLOW, "Shiny sound detected!", {}, + "", env.console.video().snapshot(), true); + break; + } + }catch (OperationFailedException& e){ + stats.errors++; + e.send_notification(env, NOTIFICATION_ERROR_RECOVERABLE); + + pbf_press_button(context, BUTTON_HOME, 160ms, 3000ms); + reset_game_from_home(env, env.console, context, false); + } + } + + env.update_stats(); + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); +} + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_BeldumHunter.h b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_BeldumHunter.h new file mode 100644 index 0000000000..efb7e61482 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_BeldumHunter.h @@ -0,0 +1,51 @@ +/* Beldum Hunter + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonLZA_BeldumHunter_H +#define PokemonAutomation_PokemonLZA_BeldumHunter_H + +#include "CommonFramework/Notifications/EventNotificationsTable.h" +#include "Common/Cpp/Options/BooleanCheckBoxOption.h" +#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" +#include "PokemonLA/Options/PokemonLA_ShinyDetectedAction.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + + +class BeldumHunter_Descriptor : public SingleSwitchProgramDescriptor{ +public: + BeldumHunter_Descriptor(); + + class Stats; + virtual std::unique_ptr make_stats() const override; +}; + + +class BeldumHunter : public SingleSwitchProgramInstance{ +public: + BeldumHunter(); + virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; + +private: + bool run_iteration(SingleSwitchProgramEnvironment& env, ProControllerContext& context); + +private: + PokemonLA::ShinyRequiresAudioText SHINY_REQUIRES_AUDIO; + + BooleanCheckBoxOption TAKE_VIDEO; + + EventNotificationOption NOTIFICATION_SHINY; + EventNotificationOption NOTIFICATION_STATUS; + EventNotificationsOption NOTIFICATIONS; +}; + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ClothingBuyer.cpp b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ClothingBuyer.cpp index 89a029689c..eee5335b1d 100644 --- a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ClothingBuyer.cpp +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ClothingBuyer.cpp @@ -80,7 +80,7 @@ void ClothingBuyer::program(SingleSwitchProgramEnvironment& env, ProControllerCo FlatWhiteDialogWatcher already_bought(COLOR_RED, &env.console.overlay()); int ret = wait_until( env.console, context, - std::chrono::seconds(2), + std::chrono::seconds(30), { buy_yes_no, already_bought } ); switch (ret) { diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_GameEntry.cpp b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_GameEntry.cpp index 330f1d522b..2f338a9945 100644 --- a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_GameEntry.cpp +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_GameEntry.cpp @@ -4,7 +4,13 @@ * */ +#include "CommonFramework/Tools/ErrorDumper.h" +#include "CommonFramework/Tools/ProgramEnvironment.h" #include "CommonTools/Async/InferenceRoutines.h" +#include "CommonTools/VisualDetectors/BlackScreenDetector.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" +#include "NintendoSwitch/Programs/NintendoSwitch_GameEntry.h" #include "PokemonLZA/PokemonLZA_Settings.h" #include "PokemonLZA_GameEntry.h" @@ -12,16 +18,81 @@ namespace PokemonAutomation{ namespace NintendoSwitch{ namespace PokemonLZA{ +bool reset_game_to_gamemenu( + ConsoleHandle& console, ProControllerContext& context +){ + from_home_close_and_reopen_game(console, context, true); + + // Now the game has opened: + return openedgame_to_gamemenu(console, context, GameSettings::instance().START_GAME_WAIT); +} + +// From the game menu screen (where "Press A" is displayed to enter the game), +// mash A to enter the game and wait until the black screen is gone. +bool gamemenu_to_ingame( + VideoStream& stream, ProControllerContext& context, + Milliseconds mash_duration, Milliseconds enter_game_timeout +){ + stream.log("Mashing A to enter game..."); + BlackScreenOverWatcher detector(COLOR_RED, {0.074, 0.044, 0.826, 0.278}); + pbf_mash_button(context, BUTTON_A, mash_duration); + context.wait_for_all_requests(); + stream.log("Waiting to enter game..."); + int ret = wait_until( + stream, context, + std::chrono::milliseconds(enter_game_timeout), + {{detector}} + ); + if (ret == 0){ + stream.log("Entered game!"); + return true; + }else{ + stream.log("Timed out waiting to enter game.", COLOR_RED); + return false; + } +} + +bool reset_game_from_home( + ProgramEnvironment& env, + ConsoleHandle& console, ProControllerContext& context, + bool backup_save, + Milliseconds enter_game_mash, + Milliseconds enter_game_timeout, + Milliseconds post_wait_time +){ + bool ok = true; + ok &= reset_game_to_gamemenu(console, context); + + if (backup_save){ + console.log("Loading backup save!"); + pbf_wait(context, 1000ms); + ssf_press_dpad(context, DPAD_UP, 0ms, 200ms); + ssf_press_button(context, BUTTON_B | BUTTON_X, 1000ms, 200ms); + } + + ok &= gamemenu_to_ingame( + console, context, + enter_game_mash, + enter_game_timeout + ); + if (!ok){ + dump_image(console.logger(), env.program_info(), console.video(), "StartGame"); + } + console.log("Entered game! Waiting out grace period."); + pbf_wait(context, post_wait_time); + context.wait_for_all_requests(); + return ok; +} bool reset_game_from_home( ProgramEnvironment& env, ConsoleHandle& console, ProControllerContext& context, bool backup_save, Milliseconds post_wait_time ){ - return PokemonLA::reset_game_from_home( + return reset_game_from_home( env, console, context, backup_save, - GameSettings::instance().ENTER_GAME_MASH, + GameSettings::instance().ENTER_GAME_MASH0, GameSettings::instance().ENTER_GAME_WAIT, post_wait_time ); diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_GameEntry.h b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_GameEntry.h index e0eecf635a..cb4bad6196 100644 --- a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_GameEntry.h +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_GameEntry.h @@ -9,7 +9,6 @@ #include "NintendoSwitch/Controllers/NintendoSwitch_ProController.h" #include "NintendoSwitch/NintendoSwitch_ConsoleHandle.h" -#include "PokemonLA/Programs/PokemonLA_GameEntry.h" namespace PokemonAutomation{ class ProgramEnvironment; @@ -22,11 +21,9 @@ using namespace std::chrono_literals; // From Switch Home menu, reset game and wait until the game menu screen (where // "Press A" is displayed to enter the game) is shown. -inline bool reset_game_to_gamemenu( +bool reset_game_to_gamemenu( ConsoleHandle& console, ProControllerContext& context -){ - return PokemonLA::reset_game_to_gamemenu(console, context); -} +); // From Switch Home menu, start game and wait until the player character // appears in game. @@ -36,6 +33,14 @@ bool reset_game_from_home( ProgramEnvironment& env, ConsoleHandle& console, ProControllerContext& context, bool backup_save, + Milliseconds enter_game_mash, + Milliseconds enter_game_timeout, + Milliseconds post_wait_time +); +bool reset_game_from_home( + ProgramEnvironment& env, + ConsoleHandle& console, ProControllerContext& context, + bool backup_save = false, Milliseconds post_wait_time = 1000ms ); diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_RestaurantFarmer.cpp b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_RestaurantFarmer.cpp index 1b959b515e..6ab41f5885 100644 --- a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_RestaurantFarmer.cpp +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_RestaurantFarmer.cpp @@ -14,6 +14,7 @@ #include "Pokemon/Pokemon_Strings.h" #include "PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.h" #include "PokemonLZA/Inference/PokemonLZA_DialogDetector.h" +#include "PokemonLZA/Inference/PokemonLZA_ButtonDetector.h" #include "PokemonLZA_RestaurantFarmer.h" namespace PokemonAutomation{ @@ -57,11 +58,17 @@ RestaurantFarmer::RestaurantFarmer(){} void RestaurantFarmer::run_lobby(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ -// RestaurantFarmer_Descriptor::Stats& stats = env.current_stats(); + RestaurantFarmer_Descriptor::Stats& stats = env.current_stats(); while (true){ context.wait_for_all_requests(); + ButtonWatcher buttonA( + COLOR_RED, + ButtonType::ButtonA, + {0.1, 0.1, 0.8, 0.8}, + &env.console.overlay() + ); SelectionArrowWatcher arrow( COLOR_YELLOW, &env.console.overlay(), SelectionArrowType::RIGHT, @@ -69,37 +76,55 @@ void RestaurantFarmer::run_lobby(SingleSwitchProgramEnvironment& env, ProControl ); FlatWhiteDialogWatcher dialog0(COLOR_RED, &env.console.overlay()); BlueDialogWatcher dialog1(COLOR_RED, &env.console.overlay()); + ItemReceiveWatcher item_receive(COLOR_RED, &env.console.overlay()); int ret = wait_until( env.console, context, - 1000ms, + 10000ms, { + buttonA, arrow, dialog0, dialog1, + item_receive, } ); context.wait_for(100ms); switch (ret){ case 0: + env.log("Detected A button."); + pbf_press_button(context, BUTTON_A, 160ms, 80ms); + continue; + + case 1: env.log("Detected selection arrow."); pbf_mash_button(context, BUTTON_A, 5000ms); return; - case 1: + case 2: env.log("Detected white dialog."); pbf_press_button(context, BUTTON_B, 160ms, 80ms); continue; - case 2: + case 3: env.log("Detected blue dialog."); pbf_press_button(context, BUTTON_B, 160ms, 80ms); continue; - default: - env.log("Detected nothing."); + case 4: + env.log("Detected item receive."); pbf_press_button(context, BUTTON_A, 160ms, 80ms); + continue; + + default: + stats.errors++; + env.update_stats(); + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "run_lobby(): No recognized state after 60 seconds.", + env.console + ); } } } @@ -114,7 +139,7 @@ void RestaurantFarmer::run_battle(SingleSwitchProgramEnvironment& env, ProContro SelectionArrowType::RIGHT, {0.654308, 0.481553, 0.295529, 0.312621} ); - ItemReceiveWatcher dialog0(COLOR_RED, &env.console.overlay(), 1000ms); + ItemReceiveWatcher item_receive(COLOR_RED, &env.console.overlay(), 1000ms); BlueDialogWatcher dialog1(COLOR_RED, &env.console.overlay()); @@ -132,7 +157,7 @@ void RestaurantFarmer::run_battle(SingleSwitchProgramEnvironment& env, ProContro }, { arrow, - dialog0, + item_receive, dialog1, } ); diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_RestaurantFarmer.h b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_RestaurantFarmer.h index cbef2aeaee..b9cedc0833 100644 --- a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_RestaurantFarmer.h +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_RestaurantFarmer.h @@ -7,7 +7,6 @@ #ifndef PokemonAutomation_PokemonLZA_RestaurantFarmer_H #define PokemonAutomation_PokemonLZA_RestaurantFarmer_H -#include "CommonFramework/ImageTypes/ImageRGB32.h" #include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" namespace PokemonAutomation{ diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_BenchSit.cpp b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_BenchSit.cpp new file mode 100644 index 0000000000..4bafcaee56 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_BenchSit.cpp @@ -0,0 +1,151 @@ +/* Shiny Hunt - Bench Sit + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/ProgramStats/StatsTracking.h" +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "NintendoSwitch/Programs/NintendoSwitch_GameEntry.h" +#include "Pokemon/Pokemon_Strings.h" +#include "PokemonLA/Inference/Sounds/PokemonLA_ShinySoundDetector.h" +#include "PokemonLZA/Programs/PokemonLZA_BasicNavigation.h" +#include "PokemonLZA_ShinyHunt_BenchSit.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + +using namespace Pokemon; + + + + + +ShinyHunt_BenchSit_Descriptor::ShinyHunt_BenchSit_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonLZA:ShinyHunt-BenchSit", + STRING_POKEMON + " LZA", "Shiny Hunt - Bench Sit", + "Programs/PokemonLZA/ShinyHunt-BenchSit.html", + "Shiny hunt by repeatedly sitting on a bench to reset spawns.", + ProgramControllerClass::StandardController_NoRestrictions, + FeedbackType::REQUIRED, + AllowCommandsWhenRunning::DISABLE_COMMANDS, + {} + ) +{} +class ShinyHunt_BenchSit_Descriptor::Stats : public StatsTracker{ +public: + Stats() + : resets(m_stats["Bench Sits"]) + , shinies(m_stats["Shiny Sounds"]) + , errors(m_stats["Errors"]) + { + m_display_order.emplace_back("Bench Sits"); + m_display_order.emplace_back("Shiny Sounds"); + m_display_order.emplace_back("Errors", HIDDEN_IF_ZERO); + + m_aliases["Shinies"] = "Shiny Sounds"; + m_aliases["Shinies Detected"] = "Shiny Sounds"; + } + + std::atomic& resets; + std::atomic& shinies; + std::atomic& errors; +}; +std::unique_ptr ShinyHunt_BenchSit_Descriptor::make_stats() const{ + return std::unique_ptr(new Stats()); +} + + + + + +ShinyHunt_BenchSit::ShinyHunt_BenchSit() + : SHINY_DETECTED( + "Shiny Detected", "", + "2000 ms", + ShinySoundDetectedAction::NOTIFY_ON_FIRST_ONLY + ) + , NOTIFICATION_STATUS("Status Update", true, false, std::chrono::seconds(3600)) + , NOTIFICATIONS({ + &NOTIFICATION_STATUS, + &SHINY_DETECTED.NOTIFICATIONS, + &NOTIFICATION_PROGRAM_FINISH, + &NOTIFICATION_ERROR_RECOVERABLE, + &NOTIFICATION_ERROR_FATAL, + }) +{ + PA_ADD_STATIC(SHINY_REQUIRES_AUDIO); + PA_ADD_OPTION(SHINY_DETECTED); + PA_ADD_OPTION(NOTIFICATIONS); +} + +void ShinyHunt_BenchSit::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + ShinyHunt_BenchSit_Descriptor::Stats& stats = env.current_stats(); + + uint8_t shiny_count = 0; + + while (true){ + float shiny_coefficient = 1.0; + PokemonLA::ShinySoundDetector shiny_detector(env.console, [&](float error_coefficient) -> bool{ + // Warning: This callback will be run from a different thread than this function. + shiny_count++; + stats.shinies++; + env.update_stats(); + shiny_coefficient = error_coefficient; + return true; + }); + + int ret = run_until( + env.console, context, + [&](ProControllerContext& context){ + while (true){ + send_program_status_notification(env, NOTIFICATION_STATUS); + sit_on_bench(env.console, context); + stats.resets++; + env.update_stats(); + } + }, + {{shiny_detector}} + ); + + // This should never happen. + if (ret != 0){ + continue; + } + + // Wait for the day/night transition to finish. + context.wait_for(std::chrono::milliseconds(2000)); + + if (SHINY_DETECTED.on_shiny_sound( + env, env.console, context, + shiny_count, + shiny_coefficient + )){ + break; + } + } + + go_home(env.console, context); + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); + +} + + + + + + + + + + + + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_BenchSit.h b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_BenchSit.h new file mode 100644 index 0000000000..9c05a50d5e --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_BenchSit.h @@ -0,0 +1,53 @@ +/* Shiny Hunt - Bench Sit + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonLZA_ShinyHunt_BenchSit_H +#define PokemonAutomation_PokemonLZA_ShinyHunt_BenchSit_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_BenchSit_Descriptor : public SingleSwitchProgramDescriptor{ +public: + ShinyHunt_BenchSit_Descriptor(); + + class Stats; + virtual std::unique_ptr make_stats() const override; +}; + + +class ShinyHunt_BenchSit : public SingleSwitchProgramInstance{ +public: + ShinyHunt_BenchSit(); + + virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; + +private: + PokemonLA::ShinyRequiresAudioText SHINY_REQUIRES_AUDIO; + + ShinySoundDetectedActionOption SHINY_DETECTED; + + EventNotificationOption NOTIFICATION_STATUS; + EventNotificationsOption NOTIFICATIONS; +}; + + + + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_OverworldReset.cpp b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_OverworldReset.cpp new file mode 100644 index 0000000000..890b5967d1 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_OverworldReset.cpp @@ -0,0 +1,161 @@ +/* Shiny Hunt - Overworld Reset + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/ProgramStats/StatsTracking.h" +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "NintendoSwitch/Programs/NintendoSwitch_GameEntry.h" +#include "Pokemon/Pokemon_Strings.h" +#include "PokemonLA/Inference/Sounds/PokemonLA_ShinySoundDetector.h" +#include "PokemonLZA/Programs/PokemonLZA_GameEntry.h" +#include "PokemonLZA_ShinyHunt_OverworldReset.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + +using namespace Pokemon; + + + + + +ShinyHunt_OverworldReset_Descriptor::ShinyHunt_OverworldReset_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonLZA:ShinyHunt-OverworldReset", + STRING_POKEMON + " LZA", "Shiny Hunt - Overworld Reset", + "Programs/PokemonLZA/ShinyHunt-OverworldReset.html", + "Shiny hunt by repeatedly sitting on a bench to reset spawns.", + ProgramControllerClass::StandardController_NoRestrictions, + FeedbackType::REQUIRED, + AllowCommandsWhenRunning::DISABLE_COMMANDS, + {} + ) +{} +class ShinyHunt_OverworldReset_Descriptor::Stats : public StatsTracker{ +public: + Stats() + : resets(m_stats["Resets"]) + , shinies(m_stats["Shinies"]) + , errors(m_stats["Errors"]) + { + m_display_order.emplace_back("Resets"); + m_display_order.emplace_back("Shinies"); + m_display_order.emplace_back("Errors", HIDDEN_IF_ZERO); + } + + std::atomic& resets; + std::atomic& shinies; + std::atomic& errors; +}; +std::unique_ptr ShinyHunt_OverworldReset_Descriptor::make_stats() const{ + return std::unique_ptr(new Stats()); +} + + + + + +ShinyHunt_OverworldReset::ShinyHunt_OverworldReset() + : RESET_DELAY( + "Reset Delay:
Wait this long after the game loads before resetting.", + LockMode::UNLOCK_WHILE_RUNNING, + "5000 ms" + ) + , ROTATE_CAMERA( + "Rotate Camera:
Rotate camera upon entering the game.", + LockMode::UNLOCK_WHILE_RUNNING, + false + ) + , SHINY_DETECTED( + "Shiny Detected", "", + "5000 ms", + ShinySoundDetectedAction::STOP_PROGRAM + ) + , NOTIFICATION_STATUS("Status Update", true, false, std::chrono::seconds(3600)) + , NOTIFICATIONS({ + &NOTIFICATION_STATUS, + &SHINY_DETECTED.NOTIFICATIONS, + &NOTIFICATION_PROGRAM_FINISH, + &NOTIFICATION_ERROR_RECOVERABLE, + &NOTIFICATION_ERROR_FATAL, + }) +{ + PA_ADD_STATIC(SHINY_REQUIRES_AUDIO); + PA_ADD_OPTION(RESET_DELAY); + PA_ADD_OPTION(ROTATE_CAMERA); + PA_ADD_OPTION(SHINY_DETECTED); + PA_ADD_OPTION(NOTIFICATIONS); +} + +void ShinyHunt_OverworldReset::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + ShinyHunt_OverworldReset_Descriptor::Stats& stats = env.current_stats(); + + uint8_t shiny_count = 0; + + while (true){ + go_home(env.console, context); + send_program_status_notification(env, NOTIFICATION_STATUS); + + + float shiny_coefficient = 1.0; + PokemonLA::ShinySoundDetector shiny_detector(env.console, [&](float error_coefficient) -> bool{ + // Warning: This callback will be run from a different thread than this function. + shiny_count++; + stats.shinies++; + env.update_stats(); + shiny_coefficient = error_coefficient; + return true; + }); + + int ret = run_until( + env.console, context, + [&](ProControllerContext& context){ + reset_game_from_home(env, env.console, context); + + if (ROTATE_CAMERA){ + pbf_move_right_joystick(context, 255, 128, RESET_DELAY, 0ms); + }else{ + pbf_wait(context, RESET_DELAY); + } + + stats.resets++; + env.update_stats(); + }, + {{shiny_detector}} + ); + shiny_detector.throw_if_no_sound(); + + if (ret < 0){ + continue; + } + + if (SHINY_DETECTED.on_shiny_sound( + env, env.console, context, + shiny_count, + shiny_coefficient + )){ + break; + } + } + + go_home(env.console, context); + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); +} + + + + + + + + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_OverworldReset.h b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_OverworldReset.h new file mode 100644 index 0000000000..c601651dfb --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_OverworldReset.h @@ -0,0 +1,58 @@ +/* Shiny Hunt - Overworld Reset + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonLZA_ShinyHunt_OverworldReset_H +#define PokemonAutomation_PokemonLZA_ShinyHunt_OverworldReset_H + +#include "Common/Cpp/Options/BooleanCheckBoxOption.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_OverworldReset_Descriptor : public SingleSwitchProgramDescriptor{ +public: + ShinyHunt_OverworldReset_Descriptor(); + + class Stats; + virtual std::unique_ptr make_stats() const override; +}; + + +class ShinyHunt_OverworldReset : public SingleSwitchProgramInstance{ +public: + ShinyHunt_OverworldReset(); + + virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; + +private: + PokemonLA::ShinyRequiresAudioText SHINY_REQUIRES_AUDIO; + + MillisecondsOption RESET_DELAY; + BooleanCheckBoxOption ROTATE_CAMERA; + + ShinySoundDetectedActionOption SHINY_DETECTED; + + EventNotificationOption NOTIFICATION_STATUS; + EventNotificationsOption NOTIFICATIONS; +}; + + + + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonLZA/Programs/TestPrograms/PokemonLZA_OverworldWatcher.cpp b/SerialPrograms/Source/PokemonLZA/Programs/TestPrograms/PokemonLZA_OverworldWatcher.cpp index 7d6f67f4bb..d5f8fb52eb 100644 --- a/SerialPrograms/Source/PokemonLZA/Programs/TestPrograms/PokemonLZA_OverworldWatcher.cpp +++ b/SerialPrograms/Source/PokemonLZA/Programs/TestPrograms/PokemonLZA_OverworldWatcher.cpp @@ -8,6 +8,7 @@ #include "Pokemon/Pokemon_Strings.h" #include "PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.h" #include "PokemonLZA/Inference/PokemonLZA_DialogDetector.h" +#include "PokemonLZA/Inference/PokemonLZA_ButtonDetector.h" #include "PokemonLZA_OverworldWatcher.h" namespace PokemonAutomation{ @@ -44,6 +45,7 @@ void OverworldWatcher::program(SingleSwitchProgramEnvironment& env, ProControlle TealDialogWatcher dialog_teal(COLOR_RED, &overlay); SelectionArrowWatcher selection_arrow_right(COLOR_RED, &overlay, SelectionArrowType::RIGHT, {0, 0, 1, 1}); SelectionArrowWatcher selection_arrow_down(COLOR_RED, &overlay, SelectionArrowType::DOWN, {0, 0, 1, 1}); + ButtonWatcher buttonA(COLOR_RED, ButtonType::ButtonA, {0, 0, 1, 1}, &overlay); CancellableHolder scope(*context.scope()); InferenceSession session( @@ -54,6 +56,7 @@ void OverworldWatcher::program(SingleSwitchProgramEnvironment& env, ProControlle dialog_teal, selection_arrow_right, selection_arrow_down, + buttonA, } ); context.wait_until_cancel(); diff --git a/SerialPrograms/Source/PokemonSV/Inference/Boxes/PokemonSV_BoxEggDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/Boxes/PokemonSV_BoxEggDetector.cpp index d54d3d4a0a..4834a6329d 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/Boxes/PokemonSV_BoxEggDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/Boxes/PokemonSV_BoxEggDetector.cpp @@ -86,6 +86,7 @@ bool BoxEggDetector::detect(const ImageViewRGB32& frame){ const size_t min_size = size_t(screen_rel_size * screen_rel_size * 700); return match_template_by_waterfill( + frame.size(), extract_box_reference(frame, m_box), EggMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonSV/Inference/Dialogs/PokemonSV_DialogArrowDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/Dialogs/PokemonSV_DialogArrowDetector.cpp index 8322006a48..58b91819f6 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/Dialogs/PokemonSV_DialogArrowDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/Dialogs/PokemonSV_DialogArrowDetector.cpp @@ -144,6 +144,7 @@ std::pair DialogArrowDetector::locate_dialog_arrow(const ImageVi ImagePixelBox pixel_search_area = floatbox_to_pixelbox(screen.width(), screen.height(), m_box); match_template_by_waterfill( + screen.size(), cropped, DialogArrowMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_DestinationMarkerDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_DestinationMarkerDetector.cpp index 3db683ede7..b13b2c3cf3 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_DestinationMarkerDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_DestinationMarkerDetector.cpp @@ -97,6 +97,7 @@ std::vector DestinationMarkerDetector::detect_all(const ImageView ImagePixelBox pixel_search_area = floatbox_to_pixelbox(screen.width(), screen.height(), m_box); match_template_by_waterfill( + screen.size(), extract_box_reference(screen, m_box), DestinationMarkerMatcher::instance(), filters, @@ -136,6 +137,7 @@ std::vector DestinationMarkerDetector::detect_all_yellow(const Im ImagePixelBox pixel_search_area = floatbox_to_pixelbox(screen.width(), screen.height(), m_box); match_template_by_waterfill( + screen.size(), extract_box_reference(screen, m_box), DestinationMarkerYellowMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_FastTravelDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_FastTravelDetector.cpp index b226e9a1c3..31589ef349 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_FastTravelDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_FastTravelDetector.cpp @@ -90,6 +90,7 @@ std::vector FastTravelDetector::detect_all(const ImageViewRGB32& ImagePixelBox pixel_search_area = floatbox_to_pixelbox(screen.width(), screen.height(), m_box); match_template_by_waterfill( + screen.size(), extract_box_reference(screen, m_box), FastTravelMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_MapDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_MapDetector.cpp index 423f4faafd..971d107bb6 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_MapDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_MapDetector.cpp @@ -78,6 +78,7 @@ bool MapFixedViewDetector::detect(const ImageViewRGB32& frame){ const size_t min_size = size_t(screen_rel_size * screen_rel_size * 150.0); const bool detected = match_template_by_waterfill( + frame.size(), extract_box_reference(frame, m_arrow_box), MapOrangleFixedViewArrowMatcher::instance(), filters, @@ -106,6 +107,7 @@ bool MapRotatedViewDetector::detect(const ImageViewRGB32& frame){ const size_t min_size = size_t(screen_rel_size * screen_rel_size * 450.0); const bool detected = match_template_by_waterfill( + frame.size(), extract_box_reference(frame, m_arrow_box), MapOrangleRotatedViewArrowMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_MapPokeCenterIconDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_MapPokeCenterIconDetector.cpp index b83300695c..e25963a64b 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_MapPokeCenterIconDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/Map/PokemonSV_MapPokeCenterIconDetector.cpp @@ -70,6 +70,7 @@ std::vector MapPokeCenterIconDetector::detect_all(const ImageView ImagePixelBox pixel_search_area = floatbox_to_pixelbox(screen.width(), screen.height(), m_box); match_template_by_waterfill( + screen.size(), extract_box_reference(screen, m_box), MapPokeCenterIconMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonSV/Inference/Overworld/PokemonSV_DirectionDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/Overworld/PokemonSV_DirectionDetector.cpp index d2f56f3dec..56d5cfb670 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/Overworld/PokemonSV_DirectionDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/Overworld/PokemonSV_DirectionDetector.cpp @@ -88,6 +88,7 @@ std::pair DirectionDetector::locate_north(Logger& logger, const ImagePixelBox pixel_search_area = floatbox_to_pixelbox(screen.width(), screen.height(), m_minimap_box); match_template_by_waterfill( + screen.size(), extract_box_reference(screen, m_minimap_box), DirectionMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonSV/Inference/Overworld/PokemonSV_OliveDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/Overworld/PokemonSV_OliveDetector.cpp index 196ab42bf1..4b90cd35d8 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/Overworld/PokemonSV_OliveDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/Overworld/PokemonSV_OliveDetector.cpp @@ -67,7 +67,12 @@ std::pair box_center(ImageFloatBox& box){ return std::make_pair(x, y); } -ImageFloatBox OliveDetector::get_olive_floatbox(const ImageViewRGB32& screen, ProControllerContext& context, uint8_t rgb_gap, ImageFloatBox box){ +ImageFloatBox OliveDetector::get_olive_floatbox( + const ImageViewRGB32& screen, + ProControllerContext& context, + uint8_t rgb_gap, + ImageFloatBox box +){ const std::vector> filters = { {combine_rgb(0, 10, 0), combine_rgb(255, 255, 255)}, }; @@ -85,6 +90,7 @@ ImageFloatBox OliveDetector::get_olive_floatbox(const ImageViewRGB32& screen, Pr ImageViewRGB32 cropped = extract_box_reference(green_only, box); ImagePixelBox pixel_search_area = floatbox_to_pixelbox(screen.width(), screen.height(), box); match_template_by_waterfill( + screen.size(), cropped, OliveMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonSV/Inference/Overworld/PokemonSV_OverworldDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/Overworld/PokemonSV_OverworldDetector.cpp index 56c04af2d5..458d1817c3 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/Overworld/PokemonSV_OverworldDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/Overworld/PokemonSV_OverworldDetector.cpp @@ -103,6 +103,7 @@ std::pair OverworldDetector::locate_ball(const ImageViewRGB32& s ImageViewRGB32 cropped = extract_box_reference(screen, m_ball); ImagePixelBox pixel_box = floatbox_to_pixelbox(screen.width(), screen.height(), m_ball); match_template_by_waterfill( + screen.size(), cropped, RadarBallMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonSV/Inference/Picnics/PokemonSV_SandwichHandDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/Picnics/PokemonSV_SandwichHandDetector.cpp index c888e21d0d..9f8c7780bd 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/Picnics/PokemonSV_SandwichHandDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/Picnics/PokemonSV_SandwichHandDetector.cpp @@ -104,6 +104,7 @@ std::pair SandwichHandLocator::locate_sandwich_hand(const ImageV ImagePixelBox pixel_box = floatbox_to_pixelbox(frame.width(), frame.height(), area_to_search); match_template_by_waterfill( + frame.size(), extract_box_reference(frame, area_to_search), ((m_type == HandType::FREE) ? SandwichFreeHandMatcher::instance() : SandwichGrabbingHandMatcher::instance()), filters, diff --git a/SerialPrograms/Source/PokemonSV/Inference/Picnics/PokemonSV_SandwichIngredientDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/Picnics/PokemonSV_SandwichIngredientDetector.cpp index ba3eafd039..401ccae150 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/Picnics/PokemonSV_SandwichIngredientDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/Picnics/PokemonSV_SandwichIngredientDetector.cpp @@ -119,6 +119,7 @@ bool SandwichCondimentsPageDetector::detect(const ImageViewRGB32& screen){ const size_t min_size = size_t(screen_rel_size * screen_rel_size * 700); return match_template_by_waterfill( + screen.size(), extract_box_reference(screen, m_box), SandwichCondimentsPageMatcher::instance(), filters, @@ -146,6 +147,7 @@ bool SandwichPicksPageDetector::detect(const ImageViewRGB32& screen){ const size_t min_size = size_t(screen_rel_size * screen_rel_size * 300); return match_template_by_waterfill( + screen.size(), extract_box_reference(screen, m_box), SandwichPicksPageMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonSV/Inference/PokemonSV_WhiteButtonDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/PokemonSV_WhiteButtonDetector.cpp index 024fc02ffd..2e106badb4 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/PokemonSV_WhiteButtonDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/PokemonSV_WhiteButtonDetector.cpp @@ -162,7 +162,7 @@ std::vector WhiteButtonDetector::detect_all(const ImageViewRGB32& ){ continue; } - double rmsd = m_matcher.rmsd_original(region, object); + double rmsd = m_matcher.rmsd_original(screen.size(), region, object); // cout << "rmsd = " << rmsd << endl; if (rmsd < m_matcher.m_max_rmsd){ hits.emplace_back(translate_to_parent(screen, m_box, object)); diff --git a/SerialPrograms/Source/PokemonSV/Inference/PokemonSV_WhiteButtonDetector.h b/SerialPrograms/Source/PokemonSV/Inference/PokemonSV_WhiteButtonDetector.h index 95b62650b8..9e7f38c939 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/PokemonSV_WhiteButtonDetector.h +++ b/SerialPrograms/Source/PokemonSV/Inference/PokemonSV_WhiteButtonDetector.h @@ -50,7 +50,7 @@ class WhiteButtonMatcher : public ImageMatch::WaterfillTemplateMatcher{ static const WhiteButtonMatcher& ArrowRight(); static const WhiteButtonMatcher& LStick(); - virtual bool check_image(const ImageViewRGB32& image) const override{ + virtual bool check_image(Resolution input_resolution, const ImageViewRGB32& image) const override{ return image.width() >= m_min_width && image.height() >= m_min_height; }; diff --git a/SerialPrograms/Source/PokemonSV/Inference/PokemonSV_WhiteTriangleDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/PokemonSV_WhiteTriangleDetector.cpp index dbea2213b9..25f21cc471 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/PokemonSV_WhiteTriangleDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/PokemonSV_WhiteTriangleDetector.cpp @@ -71,6 +71,7 @@ bool WhiteTriangleDetector::detect(const ImageViewRGB32& screen) { bool is_found = false; match_template_by_waterfill( + screen.size(), extract_box_reference(screen, m_box), WhiteTriangleMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonSV/Inference/Tera/PokemonSV_TeraRaidSearchDetector.cpp b/SerialPrograms/Source/PokemonSV/Inference/Tera/PokemonSV_TeraRaidSearchDetector.cpp index 33c224fb4f..149c1a09c3 100644 --- a/SerialPrograms/Source/PokemonSV/Inference/Tera/PokemonSV_TeraRaidSearchDetector.cpp +++ b/SerialPrograms/Source/PokemonSV/Inference/Tera/PokemonSV_TeraRaidSearchDetector.cpp @@ -64,7 +64,7 @@ bool TeraRaidSearchDetector::detect_search_location(ImageFloatBox& box, const Im // cout << "yellow = " << object.area << endl; // extract_box_reference(screen, object).save("object-" + std::to_string(c++) + ".png"); // yellows.emplace_back(std::move(object)); - double rmsd = MATCHER.rmsd(extract_box_reference(screen, object)); + double rmsd = MATCHER.rmsd(screen.size(), extract_box_reference(screen, object)); // cout << "rmsd = " << rmsd << endl; if (rmsd < 100){ diff --git a/SerialPrograms/Source/PokemonSV/PokemonSV_Settings.cpp b/SerialPrograms/Source/PokemonSV/PokemonSV_Settings.cpp index d8e081f68a..d7cea5c984 100644 --- a/SerialPrograms/Source/PokemonSV/PokemonSV_Settings.cpp +++ b/SerialPrograms/Source/PokemonSV/PokemonSV_Settings.cpp @@ -30,17 +30,17 @@ GameSettings::GameSettings() ) , m_start_game_timings("Start Game Timings:") , START_GAME_WAIT0( - "2. Start Game Wait:
Wait this long for the game to load.", + "Start Game Wait:
Wait this long for the game to load.", LockMode::LOCK_WHILE_RUNNING, "60 s" ) , ENTER_GAME_MASH0( - "3. Enter Game Mash:
Mash A for this long to enter the game.", + "Enter Game Mash:
Mash A for this long to enter the game.", LockMode::LOCK_WHILE_RUNNING, "5000 ms" ) , ENTER_GAME_WAIT0( - "4. Enter Game Wait:
Wait this long for the game to enter the overworld.", + "Enter Game Wait:
Wait this long for the game to enter the overworld.", LockMode::LOCK_WHILE_RUNNING, "60 s" ) diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.h b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.h index fb4c227761..b2d6149b6e 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.h +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.h @@ -26,24 +26,22 @@ class AutoStory_Segment_34 : public AutoStory_Segment{ ) const override; }; -static constexpr std::string segment_num = "34"; +static constexpr const char* segment_num = "34"; - - -inline std::string checkpoint90_start(){ return segment_num + ": Beat Geeta. At Pokemon League Pokecenter.";} -inline std::string checkpoint90_end(){ return segment_num + ": Beat Nemona. At dormitory room, next to bed.";} +inline std::string checkpoint90_start(){ return std::string(segment_num) + ": Beat Geeta. At Pokemon League Pokecenter.";} +inline std::string checkpoint90_end(){ return std::string(segment_num) + ": Beat Nemona. At dormitory room, next to bed.";} // start: Beat Geeta. At Pokemon League Pokecenter. // end: Beat Nemona. At dormitory room, next to bed. void checkpoint_90(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); inline std::string checkpoint91_start(){ return checkpoint90_end();} -inline std::string checkpoint91_end(){ return segment_num + ": Beat Penny. At Academy fly point.";} +inline std::string checkpoint91_end(){ return std::string(segment_num) + ": Beat Penny. At Academy fly point.";} // start: Beat Nemona. At dormitory room, next to bed." // end: Beat Penny. At Academy fly point. void checkpoint_91(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); inline std::string checkpoint92_start(){ return checkpoint91_end();} -inline std::string checkpoint92_end(){ return segment_num + ": Beat Arven. At Los Platos Pokecenter.";} +inline std::string checkpoint92_end(){ return std::string(segment_num) + ": Beat Arven. At Los Platos Pokecenter.";} // start: Beat Penny. At Academy fly point. // end: Beat Arven. At Los Platos Pokecenter. void checkpoint_92(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); diff --git a/SerialPrograms/Source/PokemonSwSh/Inference/PokemonSwSh_DialogTriangleDetector.cpp b/SerialPrograms/Source/PokemonSwSh/Inference/PokemonSwSh_DialogTriangleDetector.cpp index fa6b7ef28b..cbb4cf7f5a 100644 --- a/SerialPrograms/Source/PokemonSwSh/Inference/PokemonSwSh_DialogTriangleDetector.cpp +++ b/SerialPrograms/Source/PokemonSwSh/Inference/PokemonSwSh_DialogTriangleDetector.cpp @@ -75,6 +75,7 @@ bool DialogTriangleDetector::process_frame(const ImageViewRGB32& frame, WallCloc const size_t min_size = size_t(screen_rel_size * screen_rel_size * 500.0); const bool detected = match_template_by_waterfill( + frame.size(), extract_box_reference(frame, BLACK_TRIANGLE_BOX), DialogTriangleMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonSwSh/Inference/PokemonSwSh_YCommDetector.cpp b/SerialPrograms/Source/PokemonSwSh/Inference/PokemonSwSh_YCommDetector.cpp index a167a0ca7f..314c7cec19 100644 --- a/SerialPrograms/Source/PokemonSwSh/Inference/PokemonSwSh_YCommDetector.cpp +++ b/SerialPrograms/Source/PokemonSwSh/Inference/PokemonSwSh_YCommDetector.cpp @@ -105,6 +105,7 @@ bool YCommIconDetector::process_frame(const ImageViewRGB32& frame, WallClock tim const size_t min_size = (size_t)(350. * frame.total_pixels() / (1920 * 1080.)); const bool detected = match_template_by_waterfill( + frame.size(), extract_box_reference(frame, YCOMM_ICON_BOX), YCommIconMatcher::instance(), filters, diff --git a/SerialPrograms/Source/PokemonSwSh/MaxLair/Program/PokemonSwSh_MaxLair_Run_Battle.cpp b/SerialPrograms/Source/PokemonSwSh/MaxLair/Program/PokemonSwSh_MaxLair_Run_Battle.cpp index 678a2ddba1..3675b7963c 100644 --- a/SerialPrograms/Source/PokemonSwSh/MaxLair/Program/PokemonSwSh_MaxLair_Run_Battle.cpp +++ b/SerialPrograms/Source/PokemonSwSh/MaxLair/Program/PokemonSwSh_MaxLair_Run_Battle.cpp @@ -255,10 +255,10 @@ StateMachineAction run_move_select( // If we had trouble selecting a move, then we're probably stuck in a self-target loop. // Force target the opponent. stream.log("Force targeting opponent due to inability to select a move after multiple attempts...", COLOR_RED); - pbf_press_button(context, BUTTON_A, 20, 2 * TICKS_PER_SECOND); - pbf_press_dpad(context, DPAD_UP, 2 * TICKS_PER_SECOND, 0); + pbf_press_button(context, BUTTON_A, 160ms, 2000ms); + pbf_press_dpad(context, DPAD_UP, 2000ms, 0ms); } - pbf_mash_button(context, BUTTON_A, 2 * TICKS_PER_SECOND); + pbf_mash_button(context, BUTTON_A, 2000ms); context.wait_for_all_requests(); // inference.stop(); @@ -268,7 +268,7 @@ StateMachineAction run_move_select( int result = run_until( stream, context, [](ProControllerContext& context){ - pbf_mash_button(context, BUTTON_B, 5 * TICKS_PER_SECOND); + pbf_mash_button(context, BUTTON_B, 5000ms); }, {{detector}}, INFERENCE_RATE @@ -300,9 +300,10 @@ StateMachineAction run_move_select( state_tracker.push_update(console_index); // Reset position. - pbf_press_button(context, BUTTON_A, 10, TICKS_PER_SECOND); - pbf_press_dpad(context, DPAD_RIGHT, 2 * TICKS_PER_SECOND, 0); - pbf_press_dpad(context, DPAD_UP, 2 * TICKS_PER_SECOND, 0); + pbf_mash_button(context, BUTTON_B, 2000ms); + pbf_press_button(context, BUTTON_A, 160ms, 1000ms); + pbf_press_dpad(context, DPAD_RIGHT, 2000ms, 0ms); + pbf_press_dpad(context, DPAD_UP, 2000ms, 0ms); state.move_slot = 0; inferred = state_tracker.infer_actual_state(console_index); diff --git a/SerialPrograms/Source/PokemonSwSh/MaxLair/Program/PokemonSwSh_MaxLair_Run_EnterLobby.cpp b/SerialPrograms/Source/PokemonSwSh/MaxLair/Program/PokemonSwSh_MaxLair_Run_EnterLobby.cpp index cc56e4d16e..005d389481 100644 --- a/SerialPrograms/Source/PokemonSwSh/MaxLair/Program/PokemonSwSh_MaxLair_Run_EnterLobby.cpp +++ b/SerialPrograms/Source/PokemonSwSh/MaxLair/Program/PokemonSwSh_MaxLair_Run_EnterLobby.cpp @@ -68,7 +68,7 @@ std::shared_ptr enter_lobby( size_t boss_slot, bool connect_to_internet, ReadableQuantity999& ore ){ - pbf_mash_button(context, BUTTON_B, 2 * TICKS_PER_SECOND); + pbf_mash_button(context, BUTTON_B, 2000ms); if (connect_to_internet){ connect_to_internet_with_inference(info, stream, context); @@ -89,7 +89,7 @@ std::shared_ptr enter_lobby( size_t ore_dialog_count = 0; while (presses < 50){ presses++; - pbf_press_button(context, BUTTON_A, 10, TICKS_PER_SECOND); + pbf_press_button(context, BUTTON_A, 160ms, 1000ms); context.wait_for_all_requests(); VideoSnapshot screen = stream.video().snapshot(); @@ -141,7 +141,7 @@ std::shared_ptr enter_lobby( stream.log("Detected save dialog."); context.wait_for_all_requests(); VideoSnapshot entrance = stream.video().snapshot(); - pbf_press_button(context, BUTTON_A, 10, 5 * TICKS_PER_SECOND); + pbf_press_button(context, BUTTON_A, 160ms, 5000ms); context.wait_for_all_requests(); return std::move(entrance.frame); } @@ -151,11 +151,11 @@ std::shared_ptr enter_lobby( stream.log("Detected boss selection."); if (boss_slot > 0){ for (size_t c = 1; c < boss_slot; c++){ - pbf_press_dpad(context, DPAD_DOWN, 10, 50); + pbf_press_dpad(context, DPAD_DOWN, 160ms, 400ms); } - pbf_press_button(context, BUTTON_A, 10, TICKS_PER_SECOND); + pbf_press_button(context, BUTTON_A, 160ms, 1000ms); }else{ - pbf_press_button(context, BUTTON_B, 10, TICKS_PER_SECOND); + pbf_press_button(context, BUTTON_B, 160ms, 1000ms); } } } diff --git a/SerialPrograms/Source/PokemonSwSh/MaxLair/Program/PokemonSwSh_MaxLair_Run_Entrance.cpp b/SerialPrograms/Source/PokemonSwSh/MaxLair/Program/PokemonSwSh_MaxLair_Run_Entrance.cpp index eb3a6bdc9e..a86a977f62 100644 --- a/SerialPrograms/Source/PokemonSwSh/MaxLair/Program/PokemonSwSh_MaxLair_Run_Entrance.cpp +++ b/SerialPrograms/Source/PokemonSwSh/MaxLair/Program/PokemonSwSh_MaxLair_Run_Entrance.cpp @@ -39,12 +39,12 @@ void run_entrance( OverlayBoxScope box(stream.overlay(), {0.782, 0.850, 0.030, 0.050}); - pbf_wait(context, 2 * TICKS_PER_SECOND); + pbf_wait(context, 2000ms); while (true){ if (save_path){ - pbf_press_button(context, BUTTON_A, 10, TICKS_PER_SECOND); + pbf_press_button(context, BUTTON_A, 160ms, 1000ms); }else{ - pbf_press_button(context, BUTTON_B, 10, TICKS_PER_SECOND); + pbf_press_button(context, BUTTON_B, 160ms, 1000ms); } context.wait_for_all_requests(); diff --git a/SerialPrograms/Source/PokemonSwSh/PokemonSwSh_Settings.cpp b/SerialPrograms/Source/PokemonSwSh/PokemonSwSh_Settings.cpp index 1674c46268..6ba90e0a88 100644 --- a/SerialPrograms/Source/PokemonSwSh/PokemonSwSh_Settings.cpp +++ b/SerialPrograms/Source/PokemonSwSh/PokemonSwSh_Settings.cpp @@ -90,17 +90,17 @@ GameSettings::GameSettings() ) , m_start_game_timings("Start Game Timings:") , START_GAME_WAIT0( - "2. Start Game Wait:
Wait this long for the game to load.", + "Start Game Wait:
Wait this long for the game to load.", LockMode::LOCK_WHILE_RUNNING, "20000 ms" ) , ENTER_GAME_MASH0( - "3. Enter Game Mash:
Mash A for this long to enter the game.", + "Enter Game Mash:
Mash A for this long to enter the game.", LockMode::LOCK_WHILE_RUNNING, "3000 ms" ) , ENTER_GAME_WAIT0( - "4. Enter Game Wait:
Wait this long for the game to enter the overworld.", + "Enter Game Wait:
Wait this long for the game to enter the overworld.", LockMode::LOCK_WHILE_RUNNING, "11000 ms" ) diff --git a/SerialPrograms/Source/ZeldaTotK/ZeldaTotK_Settings.cpp b/SerialPrograms/Source/ZeldaTotK/ZeldaTotK_Settings.cpp index fe0ad09736..0bd8e002a9 100644 --- a/SerialPrograms/Source/ZeldaTotK/ZeldaTotK_Settings.cpp +++ b/SerialPrograms/Source/ZeldaTotK/ZeldaTotK_Settings.cpp @@ -31,17 +31,17 @@ GameSettings::GameSettings() "2000 ms" ) , START_GAME_WAIT0( - "2. Start Game Wait:
Wait this long for the game to load.", + "Start Game Wait:
Wait this long for the game to load.", LockMode::LOCK_WHILE_RUNNING, "60 s" ) , ENTER_GAME_MASH0( - "3. Enter Game Mash:
Mash A for this long to enter the game.", + "Enter Game Mash:
Mash A for this long to enter the game.", LockMode::LOCK_WHILE_RUNNING, "5000 ms" ) , ENTER_GAME_WAIT0( - "4. Enter Game Wait:
Wait this long for the game to enter the overworld.", + "Enter Game Wait:
Wait this long for the game to enter the overworld.", LockMode::LOCK_WHILE_RUNNING, "60 s" ) diff --git a/SerialPrograms/SourceFiles.cmake b/SerialPrograms/SourceFiles.cmake index 062f821efd..9c023e5981 100644 --- a/SerialPrograms/SourceFiles.cmake +++ b/SerialPrograms/SourceFiles.cmake @@ -1539,20 +1539,32 @@ file(GLOB LIBRARY_SOURCES Source/PokemonLGPE/Programs/ShinyHunting/PokemonLGPE_LegendaryReset.h Source/PokemonLGPE/Programs/TestPrograms/PokemonLGPE_SoundListener.cpp Source/PokemonLGPE/Programs/TestPrograms/PokemonLGPE_SoundListener.h + Source/PokemonLZA/Inference/PokemonLZA_ButtonDetector.cpp + Source/PokemonLZA/Inference/PokemonLZA_ButtonDetector.h Source/PokemonLZA/Inference/PokemonLZA_DialogDetector.cpp Source/PokemonLZA/Inference/PokemonLZA_DialogDetector.h Source/PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.cpp Source/PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.h + Source/PokemonLZA/Options/PokemonLZA_ShinyDetectedAction.cpp + Source/PokemonLZA/Options/PokemonLZA_ShinyDetectedAction.h Source/PokemonLZA/PokemonLZA_Panels.cpp Source/PokemonLZA/PokemonLZA_Panels.h Source/PokemonLZA/PokemonLZA_Settings.cpp Source/PokemonLZA/PokemonLZA_Settings.h + Source/PokemonLZA/Programs/PokemonLZA_BasicNavigation.cpp + Source/PokemonLZA/Programs/PokemonLZA_BasicNavigation.h + Source/PokemonLZA/Programs/PokemonLZA_BeldumHunter.cpp + Source/PokemonLZA/Programs/PokemonLZA_BeldumHunter.h Source/PokemonLZA/Programs/PokemonLZA_ClothingBuyer.cpp Source/PokemonLZA/Programs/PokemonLZA_ClothingBuyer.h Source/PokemonLZA/Programs/PokemonLZA_GameEntry.cpp Source/PokemonLZA/Programs/PokemonLZA_GameEntry.h Source/PokemonLZA/Programs/PokemonLZA_RestaurantFarmer.cpp Source/PokemonLZA/Programs/PokemonLZA_RestaurantFarmer.h + Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_BenchSit.cpp + Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_BenchSit.h + Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_OverworldReset.cpp + Source/PokemonLZA/Programs/PokemonLZA_ShinyHunt_OverworldReset.h Source/PokemonLZA/Programs/TestPrograms/PokemonLZA_OverworldWatcher.cpp Source/PokemonLZA/Programs/TestPrograms/PokemonLZA_OverworldWatcher.h Source/PokemonRSE/Inference/Dialogs/PokemonRSE_DialogDetector.cpp diff --git a/SerialPrograms/cmake/MacOSXBundleInfo.plist.in b/SerialPrograms/cmake/MacOSXBundleInfo.plist.in index 3cd45dde73..b23642e29e 100644 --- a/SerialPrograms/cmake/MacOSXBundleInfo.plist.in +++ b/SerialPrograms/cmake/MacOSXBundleInfo.plist.in @@ -31,10 +31,10 @@ NSHumanReadableCopyright ${MACOSX_BUNDLE_COPYRIGHT} NSCameraUsageDescription - The cameras are listed to choose the Switch video stream from the captrue card. + The cameras are listed to choose the Switch video stream from the capture card. NSCameraUseContinuityCameraDeviceType NSMicrophoneUsageDescription - The microphones are listed to choose the Switch audio stream from the captrue card. + The microphones are listed to choose the Switch audio stream from the capture card.