diff --git a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp index 892ed6afdc..8991d91676 100644 --- a/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp +++ b/SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp @@ -11,6 +11,7 @@ #include "PokemonLZA_Settings.h" #include "Programs/PokemonLZA_RestaurantFarmer.h" +#include "Programs/PokemonLZA_ClothingBuyer.h" #include "Programs/TestPrograms/PokemonLZA_OverworldWatcher.h" namespace PokemonAutomation{ @@ -31,6 +32,7 @@ std::vector PanelListFactory::make_panels() const{ ret.emplace_back("---- General ----"); 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/Programs/PokemonLZA_ClothingBuyer.cpp b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ClothingBuyer.cpp new file mode 100644 index 0000000000..89a029689c --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ClothingBuyer.cpp @@ -0,0 +1,189 @@ +/* Clothing Buyer + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/Notifications/ProgramNotifications.h" +#include "CommonFramework/Exceptions/OperationFailedException.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "CommonTools/StartupChecks/VideoResolutionCheck.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "Pokemon/Pokemon_Strings.h" +#include "PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.h" +#include "PokemonLZA/Inference/PokemonLZA_DialogDetector.h" +#include "PokemonLZA_ClothingBuyer.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + +using namespace Pokemon; + +ClothingBuyer_Descriptor::ClothingBuyer_Descriptor() + : SingleSwitchProgramDescriptor( + "PokemonLZA:ClothingBuyer", + STRING_POKEMON + " LZA", "Clothing Buyer", + "Programs/PokemonLZA/ClothingBuyer.html", + "Buy all the clothing in a store.", + ProgramControllerClass::StandardController_NoRestrictions, + FeedbackType::REQUIRED, + AllowCommandsWhenRunning::DISABLE_COMMANDS + ) +{} + +ClothingBuyer::ClothingBuyer() + : NUM_CATEGORY( + "Number of Categories:
The number of categories of clothing the shop has.", + LockMode::LOCK_WHILE_RUNNING, + 1, 1, 9 + ) + , GO_HOME_WHEN_DONE(false) + , NOTIFICATION_STATUS_UPDATE("Status Update", true, false, std::chrono::seconds(3600)) + , NOTIFICATIONS({ + &NOTIFICATION_STATUS_UPDATE, + &NOTIFICATION_PROGRAM_FINISH, + &NOTIFICATION_ERROR_FATAL, + }) +{ + PA_ADD_OPTION(NUM_CATEGORY); + PA_ADD_OPTION(GO_HOME_WHEN_DONE); + PA_ADD_OPTION(NOTIFICATIONS); +} + +void ClothingBuyer::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + assert_16_9_720p_min(env.logger(), env.console); + + /* + * Similar to SV clothing buyer. + * Start at the top of the first category in clothing shop menu. + * Buy everything in num of categories, can set num category, will wrap around. + * Stop conditions: hit category count + * Can't detect out of money, same dialog box as already bought. + * Hairstyles all seem to be hat compatible in this game. Tried w/pigtails, which wasn't compatible in SV. + */ + + uint8_t category_rotation_count = 0; + //bool finish_program = false; + while (category_rotation_count < NUM_CATEGORY){ + pbf_press_button(context, BUTTON_A, 160ms, 80ms); + + //In sub-menu for item. + while (true) { + pbf_press_button(context, BUTTON_A, 160ms, 180ms); + + SelectionArrowWatcher buy_yes_no( + COLOR_YELLOW, &env.console.overlay(), + SelectionArrowType::RIGHT, + { 0.714, 0.599, 0.033, 0.066 } + ); + FlatWhiteDialogWatcher already_bought(COLOR_RED, &env.console.overlay()); + int ret = wait_until( + env.console, context, + std::chrono::seconds(2), + { buy_yes_no, already_bought } + ); + switch (ret) { + case 0: + env.log("Purchase item."); + //Purchase Y/N detected. + pbf_press_button(context, BUTTON_A, 160ms, 500ms); + pbf_wait(context, 1000ms); + context.wait_for_all_requests(); + + //Would you like to wear this out today? (No.) + pbf_press_button(context, BUTTON_B, 160ms, 500ms); + pbf_wait(context, 1000ms); + context.wait_for_all_requests(); + + send_program_status_notification( + env, NOTIFICATION_STATUS_UPDATE, + "Clothing purchased. Selecting next item." + ); + break; + case 1: + //Item already bought or out of money. Close dialog. + env.log("Item already bought or out of money."); + send_program_status_notification( + env, NOTIFICATION_STATUS_UPDATE, + "Item already bought or out of money." + ); + pbf_press_button(context, BUTTON_A, 160ms, 180ms); + break; + default: + env.log("Error looking for purchase prompt."); + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "Error looking for purchase prompt.", + env.console + ); + break; + } + context.wait_for_all_requests(); + + env.log("Moving on to next item."); + pbf_press_dpad(context, DPAD_DOWN, 80ms, 180ms); + context.wait_for_all_requests(); + + //Check if we are back at the top of the sub-menu + SelectionArrowWatcher top_category_item( + COLOR_YELLOW, &env.console.overlay(), + SelectionArrowType::RIGHT, + { 0.034, 0.465, 0.033, 0.071 } + ); + int retCatTop = wait_until( + env.console, context, + 1000ms, + { top_category_item } + ); + context.wait_for_all_requests(); + if (retCatTop == 0) { + env.log("Reached top of the item sub-menu."); + break; + } + } + + //Exit sub-menu + pbf_press_button(context, BUTTON_B, 160ms, 200ms); + context.wait_for_all_requests(); + + //Next item on top menu + env.log("Moving on to next item."); + pbf_press_dpad(context, DPAD_DOWN, 80ms, 80ms); + context.wait_for_all_requests(); + + + //Check if category complete + SelectionArrowWatcher top_item( + COLOR_YELLOW, &env.console.overlay(), + SelectionArrowType::RIGHT, + {0.033, 0.350, 0.033, 0.070} + ); + int retTop = wait_until( + env.console, context, + std::chrono::seconds(1), + { top_item } + ); + if (retTop == 0){ + env.log("Reached top of category."); + if (NUM_CATEGORY > 1){ + env.log("Category rotation set. Moving to next category."); + pbf_press_button(context, BUTTON_R, 80ms, 100ms); + context.wait_for_all_requests(); + category_rotation_count++; + }else{ + env.log("No category rotation. Ending program."); + break; + } + } + } + env.log("Category num hit. Ending program."); + GO_HOME_WHEN_DONE.run_end_of_program(context); + send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH); +} + + +} +} +} + diff --git a/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ClothingBuyer.h b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ClothingBuyer.h new file mode 100644 index 0000000000..116cc37f01 --- /dev/null +++ b/SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_ClothingBuyer.h @@ -0,0 +1,45 @@ +/* Clothing Buyer + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonLZA_ClothingBuyer_H +#define PokemonAutomation_PokemonLZA_ClothingBuyer_H + +#include "CommonFramework/ImageTypes/ImageRGB32.h" +#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" +#include "CommonFramework/Notifications/EventNotificationsTable.h" +#include "NintendoSwitch/Options/NintendoSwitch_GoHomeWhenDoneOption.h" +#include "Common/Cpp/Options/SimpleIntegerOption.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonLZA{ + +class ClothingBuyer_Descriptor : public SingleSwitchProgramDescriptor{ +public: + ClothingBuyer_Descriptor(); +}; + +class ClothingBuyer : public SingleSwitchProgramInstance{ +public: + ClothingBuyer(); + + virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override; + +private: + SimpleIntegerOption NUM_CATEGORY; + GoHomeWhenDoneOption GO_HOME_WHEN_DONE; + EventNotificationOption NOTIFICATION_STATUS_UPDATE; + EventNotificationsOption NOTIFICATIONS; +}; + + + + + +} +} +} +#endif diff --git a/SerialPrograms/SourceFiles.cmake b/SerialPrograms/SourceFiles.cmake index bd9faf9795..062f821efd 100644 --- a/SerialPrograms/SourceFiles.cmake +++ b/SerialPrograms/SourceFiles.cmake @@ -1547,6 +1547,8 @@ file(GLOB LIBRARY_SOURCES Source/PokemonLZA/PokemonLZA_Panels.h Source/PokemonLZA/PokemonLZA_Settings.cpp Source/PokemonLZA/PokemonLZA_Settings.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