diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.cpp b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.cpp index bded3f8e97..f2aafabb2d 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.cpp +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.cpp @@ -109,7 +109,7 @@ std::vector> make_autoStory_segment_list(){ segment_list.emplace_back(std::make_unique()); segment_list.emplace_back(std::make_unique()); segment_list.emplace_back(std::make_unique()); - // segment_list.emplace_back(std::make_unique()); + segment_list.emplace_back(std::make_unique()); // segment_list.emplace_back(std::make_unique()); // segment_list.emplace_back(std::make_unique()); @@ -253,7 +253,7 @@ AutoStory::AutoStory() "For Start Points that are at Pokecenters, ensure that you fly there so that your character is in the exactly correct start position." } , MAINSTORY_NOTE{ - "Ensure you have a level 100 Gardevoir with the moves in the following order: Moonblast, Dazzling Gleam, Psychic, Mystical Fire.
" + "Ensure you have a level 100 Gardevoir with the moves in the following order: Moonblast, Dazzling Gleam, Mystical Fire, Misty Terrain.
" "Also, make sure you have two other strong pokemon (e.g. level 100 Talonflames)
" "Refer to the documentation on github for more details." } @@ -537,10 +537,10 @@ AutoStory::AutoStory() } void AutoStory::on_config_value_changed(void* object){ - ConfigOptionState state = (STARTPOINT_TUTORIAL.index() <= 1 && STORY_SECTION == StorySection::TUTORIAL) - ? ConfigOptionState::ENABLED - : ConfigOptionState::HIDDEN; - STARTERCHOICE.set_visibility(state); + // ConfigOptionState state = (STARTPOINT_TUTORIAL.index() <= 1 && STORY_SECTION == StorySection::TUTORIAL) + // ? ConfigOptionState::ENABLED + // : ConfigOptionState::HIDDEN; + // STARTERCHOICE.set_visibility(state); if (STORY_SECTION == StorySection::TUTORIAL){ STARTPOINT_TUTORIAL.set_visibility(ConfigOptionState::ENABLED); @@ -730,10 +730,15 @@ void AutoStory::test_checkpoints( checkpoint_list.push_back([&](){checkpoint_84(env, context, notif_status_update, stats);}); checkpoint_list.push_back([&](){checkpoint_85(env, context, notif_status_update, stats);}); checkpoint_list.push_back([&](){checkpoint_86(env, context, notif_status_update, stats);}); - checkpoint_list.push_back([&](){checkpoint_87(env, context, notif_status_update, stats);}); + checkpoint_list.push_back([&](){checkpoint_87(env, context, notif_status_update, stats, language, starter_choice);}); checkpoint_list.push_back([&](){checkpoint_88(env, context, notif_status_update, stats);}); checkpoint_list.push_back([&](){checkpoint_89(env, context, notif_status_update, stats);}); checkpoint_list.push_back([&](){checkpoint_90(env, context, notif_status_update, stats);}); + checkpoint_list.push_back([&](){checkpoint_91(env, context, notif_status_update, stats);}); + checkpoint_list.push_back([&](){checkpoint_92(env, context, notif_status_update, stats);}); + checkpoint_list.push_back([&](){checkpoint_93(env, context, notif_status_update, stats);}); + checkpoint_list.push_back([&](){checkpoint_94(env, context, notif_status_update, stats);}); + checkpoint_list.push_back([&](){checkpoint_95(env, context, notif_status_update, stats);}); if (end == 0){ diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.cpp b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.cpp index 0752a60a4c..9177558492 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.cpp +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.cpp @@ -92,7 +92,7 @@ void clear_dialog(VideoStream& stream, ProControllerContext& context, AdvanceDialogWatcher advance_dialog(COLOR_RED); OverworldWatcher overworld(stream.logger(), COLOR_CYAN); - PromptDialogWatcher prompt(COLOR_YELLOW, {0.50, 0.30, 0.40, 0.60}); + PromptDialogWatcher prompt(COLOR_YELLOW, {0.50, 0.25, 0.40, 0.65}); WhiteButtonWatcher whitebutton(COLOR_GREEN, WhiteButton::ButtonA_DarkBackground, {0.725, 0.833, 0.024, 0.045}); // {0.650, 0.650, 0.140, 0.240} DialogArrowWatcher dialog_arrow(COLOR_RED, stream.overlay(), {0.850, 0.820, 0.020, 0.050}, 0.8365, 0.846); NormalBattleMenuWatcher battle(COLOR_ORANGE); @@ -653,6 +653,40 @@ void handle_unexpected_battles( } } +void do_action_and_monitor_for_overworld( + const ProgramInfo& info, + VideoStream& stream, + ProControllerContext& context, + std::function< + void(const ProgramInfo& info, + VideoStream& stream, + ProControllerContext& context) + >&& action +){ + + OverworldWatcher overworld(stream.logger(), COLOR_CYAN); + + int ret = run_until( + stream, context, + [&](ProControllerContext& context){ + context.wait_for_all_requests(); + action(info, stream, context); + }, + {overworld} + ); + if (ret < 0){ + // successfully completed action detecting the overworld + return; + }else if (ret == 0){ + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "do_action_and_monitor_for_overworld(): Failed to complete action. Detected overworld.", + stream + ); + } + +} + void handle_when_stationary_in_overworld( const ProgramInfo& info, VideoStream& stream, diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.h b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.h index eac63b9ad0..f8a69121b6 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.h +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.h @@ -180,6 +180,16 @@ void handle_unexpected_battles( >&& action ); +// run the given `action`. if detect the overworld, stop the action, and throw exception +void do_action_and_monitor_for_overworld( + const ProgramInfo& info, + VideoStream& stream, + ProControllerContext& context, + std::function&& action +); + // if stationary in overworld for an amount of time (seconds_stationary), run `recovery_action` then try `action` again // return once successfully completed `action` // throw exception if fails to complete `action` within a certain amount of time (minutes_timeout). diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_33.cpp b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_33.cpp index 10c6f52dd8..276d4939e7 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_33.cpp +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_33.cpp @@ -3,6 +3,13 @@ * From: https://github.com/PokemonAutomation/ * */ +#include "CommonFramework/VideoPipeline/VideoFeed.h" +#include "CommonTools/Images/SolidColorTest.h" +#include "Pokemon/Inference/Pokemon_NameReader.h" +#include "CommonFramework/Notifications/ProgramInfo.h" +#include "PokemonSV/Inference/Overworld/PokemonSV_DirectionDetector.h" +#include "PokemonSV/Programs/Battles/PokemonSV_SinglesBattler.h" +#include "PokemonSV/Programs/Battles/PokemonSV_Battles.h" #include "CommonFramework/Exceptions/OperationFailedException.h" #include "CommonTools/Async/InferenceRoutines.h" @@ -28,15 +35,15 @@ namespace PokemonSV{ std::string AutoStory_Segment_33::name() const{ - return ""; + return "33: Clavell battle, Elite Four"; } std::string AutoStory_Segment_33::start_text() const{ - return "Start: "; + return "Start: Beat Alfornada Gym (Psychic). At Alfornada Pokecenter."; } std::string AutoStory_Segment_33::end_text() const{ - return "End: "; + return "End: Beat Clavell. Beat Elite Four. At Pokemon League Pokecenter."; } void AutoStory_Segment_33::run_segment( @@ -52,7 +59,9 @@ void AutoStory_Segment_33::run_segment( context.wait_for_all_requests(); env.console.log("Start Segment " + name(), COLOR_ORANGE); - // checkpoint_(env, context, options.notif_status_update, stats); + checkpoint_85(env, context, options.notif_status_update, stats); + checkpoint_86(env, context, options.notif_status_update, stats); + checkpoint_87(env, context, options.notif_status_update, stats, options.language, options.starter_choice); context.wait_for_all_requests(); env.console.log("End Segment " + name(), COLOR_GREEN); @@ -63,29 +72,380 @@ void AutoStory_Segment_33::run_segment( void checkpoint_85(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ checkpoint_reattempt_loop(env, context, notif_status_update, stats, [&](size_t attempt_number){ + move_cursor_towards_flypoint_and_go_there(env.program_info(), env.console, context, {ZoomChange::KEEP_ZOOM, 255, 50, 320}, FlyPoint::FAST_TRAVEL); + realign_player(env.program_info(), env.console, context, PlayerRealignMode::REALIGN_NEW_MARKER, 128, 0, 80); + walk_forward_until_dialog(env.program_info(), env.console, context, NavigationMovementMode::DIRECTIONAL_ONLY, 30); + clear_dialog(env.console, context, ClearDialogMode::STOP_BATTLE, 60, {CallbackEnum::PROMPT_DIALOG, CallbackEnum::BATTLE, CallbackEnum:: DIALOG_ARROW}); + + env.console.log("Battle Clavell."); + run_trainer_battle_press_A(env.console, context, BattleStopCondition::STOP_DIALOG); + mash_button_till_overworld(env.console, context, BUTTON_A); + + move_cursor_towards_flypoint_and_go_there(env.program_info(), env.console, context, {ZoomChange::ZOOM_IN, 0, 0, 0}, FlyPoint::FAST_TRAVEL); }); } - void checkpoint_86(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ + checkpoint_reattempt_loop(env, context, notif_status_update, stats, + [&](size_t attempt_number){ + + realign_player(env.program_info(), env.console, context, PlayerRealignMode::REALIGN_NEW_MARKER, 0, 128, 50); + DirectionDetector direction; + direction.change_direction(env.program_info(), env.console, context, 1.222127); + pbf_move_left_joystick(context, 128, 0, 1100, 50); + + get_on_ride(env.program_info(), env.console, context); + direction.change_direction(env.program_info(), env.console, context, 1.484555); + + pbf_move_left_joystick(context, 128, 0, 1506ms, 0ms); + pbf_controller_state(context, BUTTON_B, DPAD_NONE, 128, 0, 128, 128, 703ms); + pbf_move_left_joystick(context, 128, 0, 233ms, 0ms); + pbf_controller_state(context, BUTTON_B, DPAD_NONE, 128, 0, 128, 128, 5098ms); + pbf_move_left_joystick(context, 128, 0, 1000ms, 0ms); + + wait_for_overworld(env.program_info(), env.console, context); + + // marker 1 {0.429688, 0.299074} + place_marker_offset_from_flypoint(env.program_info(), env.console, context, + {ZoomChange::KEEP_ZOOM, 0, 0, 0}, + FlyPoint::POKECENTER, + {0.429688, 0.299074} + ); + handle_when_stationary_in_overworld(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + overworld_navigation(env.program_info(), env.console, context, + NavigationStopCondition::STOP_MARKER, NavigationMovementMode::DIRECTIONAL_ONLY, + 128, 0, 30, 10, false); + }, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + pbf_move_left_joystick(context, 0, 255, 40, 50); + realign_player(env.program_info(), env.console, context, PlayerRealignMode::REALIGN_OLD_MARKER); + } + ); + + + // marker 2 {0.482812, 0.378704} + place_marker_offset_from_flypoint(env.program_info(), env.console, context, + {ZoomChange::ZOOM_IN, 0, 0, 50}, + FlyPoint::POKECENTER, + {0.482812, 0.378704} + ); + handle_when_stationary_in_overworld(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + overworld_navigation(env.program_info(), env.console, context, + NavigationStopCondition::STOP_MARKER, NavigationMovementMode::DIRECTIONAL_ONLY, + 128, 0, 40, 10, false); + }, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + pbf_move_left_joystick(context, 0, 255, 40, 50); + realign_player(env.program_info(), env.console, context, PlayerRealignMode::REALIGN_OLD_MARKER); + } + ); + + + // marker 3 {0.638021, 0.676852} + place_marker_offset_from_flypoint(env.program_info(), env.console, context, + {ZoomChange::KEEP_ZOOM, 0, 0, 50}, + FlyPoint::POKECENTER, + {0.638021, 0.676852} + ); + handle_when_stationary_in_overworld(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + overworld_navigation(env.program_info(), env.console, context, + NavigationStopCondition::STOP_DIALOG, NavigationMovementMode::DIRECTIONAL_ONLY, + 128, 0, 60, 30, false); + }, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + pbf_move_left_joystick(context, 0, 255, 40, 50); + realign_player(env.program_info(), env.console, context, PlayerRealignMode::REALIGN_OLD_MARKER); + } + ); + + // clear_dialog(env.console, context, ClearDialogMode::STOP_OVERWORLD, 60, {CallbackEnum::OVERWORLD}); + mash_button_till_overworld(env.console, context, BUTTON_A); + + }); } -void checkpoint_87(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ +void checkpoint_87(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats, Language language, StarterChoice starter_choice){ + GameTitle game_title = GameTitle::UNKNOWN; + checkpoint_reattempt_loop(env, context, notif_status_update, stats, + [&](size_t attempt_number){ + if (game_title == GameTitle::UNKNOWN){ + game_title = get_game_title(env, context); + press_Bs_to_back_to_overworld(env.program_info(), env.console, context); + } + + realign_player(env.program_info(), env.console, context, PlayerRealignMode::REALIGN_OLD_MARKER); + + do_action_and_monitor_for_battles(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + walk_forward_while_clear_front_path(env.program_info(), env.console, context, 100); + walk_forward_until_dialog(env.program_info(), env.console, context, NavigationMovementMode::DIRECTIONAL_SPAM_A); + } + ); + // talk to door man + // clear_dialog(env.console, context, ClearDialogMode::STOP_OVERWORLD, 60, {CallbackEnum::OVERWORLD, CallbackEnum::PROMPT_DIALOG}); + mash_button_till_overworld(env.console, context, BUTTON_A); + + do_action_and_monitor_for_overworld(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + // move left to sit down + pbf_move_left_joystick(context, 0, 128, 100, 50); + + // talk to Rika 1. Choose first option. Walked here. + clear_dialog(env.console, context, ClearDialogMode::STOP_PROMPT, 60, {CallbackEnum::PROMPT_DIALOG}); + pbf_mash_button(context, BUTTON_A, 1000ms); + + // talk to Rika 2. Choose option based on your game title + clear_dialog(env.console, context, ClearDialogMode::STOP_PROMPT, 60, {CallbackEnum::PROMPT_DIALOG}); + + switch(game_title){ + case GameTitle::SCARLET: + pbf_press_dpad(context, DPAD_DOWN, 13, 20); + break; + case GameTitle::VIOLET: + pbf_press_dpad(context, DPAD_DOWN, 13, 20); + pbf_press_dpad(context, DPAD_DOWN, 13, 20); + break; + default: + throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "We don't know what game we are playing. We should know at this point."); + break; + } + pbf_mash_button(context, BUTTON_A, 1000ms); + + // talk to Rika 3. Came to become a Champion + clear_dialog(env.console, context, ClearDialogMode::STOP_PROMPT, 60, {CallbackEnum::PROMPT_DIALOG}); + pbf_press_dpad(context, DPAD_DOWN, 13, 20); + pbf_mash_button(context, BUTTON_A, 1000ms); + + // talk to Rika 4. Become stronger + clear_dialog(env.console, context, ClearDialogMode::STOP_PROMPT, 60, {CallbackEnum::PROMPT_DIALOG}); + pbf_mash_button(context, BUTTON_A, 1000ms); + + // talk to Rika 5. Difficult gym: Alfornada + clear_dialog(env.console, context, ClearDialogMode::STOP_PROMPT, 60, {CallbackEnum::PROMPT_DIALOG}); + pbf_press_dpad(context, DPAD_UP, 13, 20); + pbf_mash_button(context, BUTTON_A, 1000ms); + + // talk to Rika 6. Difficult gym leader name: Tulip + clear_dialog(env.console, context, ClearDialogMode::STOP_PROMPT, 60, {CallbackEnum::PROMPT_DIALOG}); + pbf_press_dpad(context, DPAD_UP, 13, 20); + pbf_mash_button(context, BUTTON_A, 1000ms); + + // talk to Rika 7. Difficult gym leader type: Psychic + clear_dialog(env.console, context, ClearDialogMode::STOP_PROMPT, 60, {CallbackEnum::PROMPT_DIALOG}); + pbf_press_dpad(context, DPAD_UP, 13, 20); + pbf_press_dpad(context, DPAD_UP, 13, 20); + pbf_mash_button(context, BUTTON_A, 1000ms); + + // talk to Rika 8. Starter pokemon: Grass/Fire/Water + clear_dialog(env.console, context, ClearDialogMode::STOP_PROMPT, 60, {CallbackEnum::PROMPT_DIALOG}); + switch(starter_choice){ + case StarterChoice::SPRIGATITO: + break; + case StarterChoice::FUECOCO: + pbf_press_dpad(context, DPAD_DOWN, 13, 20); + break; + case StarterChoice::QUAXLY: + pbf_press_dpad(context, DPAD_DOWN, 13, 20); + pbf_press_dpad(context, DPAD_DOWN, 13, 20); + break; + default: + throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Invalid starter pokemon type. This shouldn't happen."); + break; + } + size_t num_extra_clicks = attempt_number % 3; // we add extra clicks when attempt_number > 0, to account for the fact that the user might not be enterint the correct starter. + for (size_t i = 0; i < num_extra_clicks; i++){ + pbf_press_dpad(context, DPAD_DOWN, 13, 20); + } + + pbf_mash_button(context, BUTTON_A, 1000ms); + + // talk to Rika 9. Become stronger + // talk to Rika 10. do you like pokemon + clear_dialog(env.console, context, ClearDialogMode::STOP_TIMEOUT, 20, {CallbackEnum::PROMPT_DIALOG}); + + }); + + pbf_move_left_joystick(context, 128, 0, 100, 50); // stand up + + + }); } + void checkpoint_88(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ + checkpoint_reattempt_loop(env, context, notif_status_update, stats, + [&](size_t attempt_number){ + // standing in front of Rika + // now done talking to Rika. walk around Rika's desk. + + pbf_move_left_joystick(context, 0, 128, 50, 50); // go left + pbf_move_left_joystick(context, 128, 0, 200, 50); // straight + pbf_move_left_joystick(context, 255, 128, 50, 50); // right + + walk_forward_until_dialog(env.program_info(), env.console, context, NavigationMovementMode::DIRECTIONAL_ONLY, 60); + clear_dialog(env.console, context, ClearDialogMode::STOP_BATTLE, 60, {CallbackEnum::BATTLE, CallbackEnum::DIALOG_ARROW}); + + + env.console.log("Battle Elite Four 1."); + SinglesMoveEntry move1{SinglesMoveType::Move1, false}; // Moonblast + SinglesMoveEntry move3{SinglesMoveType::Move3, false}; // Mystical Fire + SinglesMoveEntry move4{SinglesMoveType::Move4, false}; // Misty Terrain + std::vector move_table1 = {move1, move4, move1}; + bool terastallized = false; + bool is_won = run_pokemon(env.console, context, move_table1, true, terastallized); + + // finished battle + mash_button_till_overworld(env.console, context, BUTTON_A); + + // heal + auto_heal_from_menu_or_overworld(env.program_info(), env.console, context, 0, true); + + // engage next battle + walk_forward_until_dialog(env.program_info(), env.console, context, NavigationMovementMode::DIRECTIONAL_ONLY, 60); + clear_dialog(env.console, context, ClearDialogMode::STOP_BATTLE, 60, {CallbackEnum::BATTLE, CallbackEnum::DIALOG_ARROW, CallbackEnum::PROMPT_DIALOG}); + + env.console.log("Battle Elite Four 2."); // select move 3, which should be a fire move. to battle the steel trainer + std::vector move_table2 = {move3}; + is_won = run_pokemon(env.console, context, move_table2, true, terastallized); + if (!is_won){// throw exception if we lose + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "Failed to beat the Steel trainer. Reset.", + env.console + ); + } + + // finished battle + mash_button_till_overworld(env.console, context, BUTTON_A); + + // heal + auto_heal_from_menu_or_overworld(env.program_info(), env.console, context, 0, true); + + // engage next battle + walk_forward_until_dialog(env.program_info(), env.console, context, NavigationMovementMode::DIRECTIONAL_ONLY, 60); + clear_dialog(env.console, context, ClearDialogMode::STOP_BATTLE, 60, {CallbackEnum::BATTLE, CallbackEnum::DIALOG_ARROW, CallbackEnum::PROMPT_DIALOG}); + + env.console.log("Battle Elite Four 3."); + run_trainer_battle_press_A(env.console, context, BattleStopCondition::STOP_DIALOG); + + // finished battle + mash_button_till_overworld(env.console, context, BUTTON_A); + + // engage next battle + walk_forward_until_dialog(env.program_info(), env.console, context, NavigationMovementMode::DIRECTIONAL_ONLY, 60); + clear_dialog(env.console, context, ClearDialogMode::STOP_BATTLE, 60, {CallbackEnum::BATTLE, CallbackEnum::DIALOG_ARROW, CallbackEnum::PROMPT_DIALOG}); + + env.console.log("Battle Elite Four 4."); + run_trainer_battle_press_A(env.console, context, BattleStopCondition::STOP_DIALOG); + + // finished battle + clear_dialog(env.console, context, ClearDialogMode::STOP_OVERWORLD, 60, {CallbackEnum::OVERWORLD}); + + }); } void checkpoint_89(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ + checkpoint_reattempt_loop(env, context, notif_status_update, stats, + [&](size_t attempt_number){ + walk_forward_until_dialog(env.program_info(), env.console, context, NavigationMovementMode::DIRECTIONAL_ONLY, 60); + clear_dialog(env.console, context, ClearDialogMode::STOP_BATTLE, 60, {CallbackEnum::BATTLE, CallbackEnum::DIALOG_ARROW, CallbackEnum::PROMPT_DIALOG}); + + env.console.log("Battle Elite Four 4."); + run_trainer_battle_press_A(env.console, context, BattleStopCondition::STOP_DIALOG); + + // finished battle + mash_button_till_overworld(env.console, context, BUTTON_A); + + // move to Pokecenter + handle_unexpected_battles(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + realign_player(env.program_info(), env.console, context, PlayerRealignMode::REALIGN_NEW_MARKER, 255, 50, 50); + }); + overworld_navigation(env.program_info(), env.console, context, + NavigationStopCondition::STOP_TIME, NavigationMovementMode::DIRECTIONAL_ONLY, + 128, 15, 12, 12, false); // can't wrap in handle_when_stationary_in_overworld(), since we expect to be stationary when walking into the pokecenter + + + fly_to_overlapping_flypoint(env.program_info(), env.console, context); + + }); } -void checkpoint_90(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ + + +GameTitle get_game_title(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + GameTitle game_title = GameTitle::UNKNOWN; + enter_menu_from_overworld(env.program_info(), env.console, context, 0, MenuSide::RIGHT); + context.wait_for_all_requests(); + + VideoSnapshot screen = env.console.video().snapshot(); + ImageFloatBox box = {0.03, 0.94, 0.40, 0.04}; + ImageStats bottom_stats = image_stats(extract_box_reference(screen, box)); + + if (is_solid(bottom_stats, {0.648549, 0.2861580, 0.0652928}, 0.15, 25)){ + game_title = GameTitle::SCARLET; + env.console.log("Game title detected: Scarlet"); + } else if (is_solid(bottom_stats, {0.367816, 0.0746615, 0.5575230}, 0.15, 25)){ + game_title = GameTitle::VIOLET; + env.console.log("Game title detected: Violet"); + } + + if (game_title == GameTitle::UNKNOWN){ + throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Unable to determine what game we are playing. The color of the bottom bar in the Pokemon Summary page doesn't match of the expected colors."); + } + + return game_title; + } +std::string get_ride_pokemon_name(SingleSwitchProgramEnvironment& env, ProControllerContext& context, Language language){ + enter_menu_from_overworld(env.program_info(), env.console, context, -1); + + ImageFloatBox box = {0.116223, 0.895000, 0.194915, 0.051724}; + ImageViewRGB32 image = extract_box_reference(env.console.video().snapshot(), box); + + OCR::StringMatchResult ocr_result = Pokemon::PokemonNameReader::instance().read_substring( + env.console.logger(), language, image, + OCR::WHITE_TEXT_FILTERS() + ); + std::multimap results; + if (!ocr_result.results.empty()){ + for (const auto& result : ocr_result.results){ + results.emplace(result.first, result.second); + } + } + + if (results.empty()){ + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "AutoStory_Segment_34::checkpoint_86(): Unable to read selected item. No valid results.\n" + language_warning(language), + env.console + ); + } + + if (results.size() > 1){ + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "AutoStory_Segment_34::checkpoint_86(): Unable to read selected item. Ambiguous or multiple results.\n" + language_warning(language), + env.console + ); + } + + std::string ride_pokemon = results.begin()->second.token; + + // cout << ride_pokemon << endl; + return ride_pokemon; +} + + + diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_33.h b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_33.h index ae91b4335e..8a699641bf 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_33.h +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_33.h @@ -26,30 +26,36 @@ class AutoStory_Segment_33 : public AutoStory_Segment{ ) const override; }; +enum class GameTitle{ + UNKNOWN, + SCARLET, + VIOLET, +}; + // start: Beat Alfornada gym challenge. Beat Alfornada gym. At Alfronada Pokecenter. -// end: +// end: Beat Clavell. At Academy fly point. void checkpoint_85(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); -// start: -// end: +// start: Beat Clavell. At Academy fly point. +// end: At Pokemon League entrance. void checkpoint_86(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); -// start: -// end: -void checkpoint_87(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); +// start: At Pokemon League entrance. +// end: Finished the Entrance quiz. Standing in front of Rika. +void checkpoint_87(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats, Language language, StarterChoice starter_choice); -// start: -// end: +// start: Finished the Entrance quiz. Standing in front of Rika. +// end: Beat Elite Four. void checkpoint_88(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); -// start: -// end: +// start: Beat Elite Four. +// end: Beat Geeta. At Pokemon League Pokecenter. void checkpoint_89(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); -// start: -// end: -void checkpoint_90(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); +GameTitle get_game_title(SingleSwitchProgramEnvironment& env, ProControllerContext& context); + +std::string get_ride_pokemon_name(SingleSwitchProgramEnvironment& env, ProControllerContext& context, Language language); diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.cpp b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.cpp index 01bdc929f1..b38c7af64e 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.cpp +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.cpp @@ -4,6 +4,7 @@ * */ + #include "CommonFramework/Exceptions/OperationFailedException.h" #include "CommonTools/Async/InferenceRoutines.h" #include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" @@ -28,11 +29,11 @@ namespace PokemonSV{ std::string AutoStory_Segment_34::name() const{ - return ""; + return "35: "; } std::string AutoStory_Segment_34::start_text() const{ - return "Start: "; + return "Start: Beat Clavell. Beat Elite Four. At Pokemon League Pokecenter."; } std::string AutoStory_Segment_34::end_text() const{ @@ -61,6 +62,27 @@ void AutoStory_Segment_34::run_segment( +void checkpoint_90(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ +} + +void checkpoint_91(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ +} + +void checkpoint_92(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ +} + +void checkpoint_93(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ +} + +void checkpoint_94(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ +} + +void checkpoint_95(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ +} + + + + } } } 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 e38ad1621f..8c374db0fd 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.h +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.h @@ -28,6 +28,33 @@ class AutoStory_Segment_34 : public AutoStory_Segment{ +// start: +// end: +void checkpoint_90(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); + +// start: +// end: +void checkpoint_91(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); + +// start: +// end: +void checkpoint_92(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); + +// start: +// end: +void checkpoint_93(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); + +// start: +// end: +void checkpoint_94(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); + +// start: +// end: +void checkpoint_95(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); + + + + } }