diff --git a/SerialPrograms/Source/NintendoSwitch/Programs/NintendoSwitch_GameEntry.cpp b/SerialPrograms/Source/NintendoSwitch/Programs/NintendoSwitch_GameEntry.cpp index d3302e323a..8d4f2768ea 100644 --- a/SerialPrograms/Source/NintendoSwitch/Programs/NintendoSwitch_GameEntry.cpp +++ b/SerialPrograms/Source/NintendoSwitch/Programs/NintendoSwitch_GameEntry.cpp @@ -70,6 +70,7 @@ void ensure_at_home(ConsoleHandle& console, ControllerContext& context){ {home_menu} ); if (ret == 0){ + console.log("Home detected."); // While we're on the Home screen, we might as well read the // console type as well. if (console.state().console_type_confirmed()){ @@ -104,6 +105,7 @@ void ensure_at_home(ConsoleHandle& console, JoyconContext& context){ // void close_game_from_home(ConsoleHandle& console, ProControllerContext& context){ + console.log("close_game_from_home"); ensure_at_home(console, context); // Use mashing to ensure that the X press succeeds. If it fails, the SR @@ -124,6 +126,7 @@ void close_game_from_home(ConsoleHandle& console, ProControllerContext& context) pbf_mash_button(context, BUTTON_B, 350); } void close_game_from_home(ConsoleHandle& console, JoyconContext& context){ + console.log("close_game_from_home"); ensure_at_home(console, context); // Use mashing to ensure that the X press succeeds. If it fails, the SR // will fail and can kill a den for the autohosts. diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.cpp b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.cpp index 67be7aeb5d..331f148bc7 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.cpp +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.cpp @@ -3,6 +3,13 @@ * From: https://github.com/PokemonAutomation/ * */ + + +#include "ML/Inference/ML_YOLOv5Detector.h" +#include "CommonFramework/VideoPipeline/VideoFeed.h" +#include "CommonFramework/Exceptions/UnexpectedBattleException.h" + + #include "CommonFramework/Exceptions/OperationFailedException.h" #include "CommonTools/Async/InferenceRoutines.h" @@ -57,6 +64,11 @@ #include "PokemonSV_AutoStory_Segment_33.h" #include "PokemonSV_AutoStory_Segment_34.h" #include "PokemonSV_AutoStory_Segment_35.h" +#include "PokemonSV_AutoStory_Segment_36.h" +#include "PokemonSV_AutoStory_Segment_37.h" +#include "PokemonSV_AutoStory_Segment_38.h" +#include "PokemonSV_AutoStory_Segment_39.h" +#include "PokemonSV_AutoStory_Segment_40.h" #include "PokemonSV_AutoStory.h" #include @@ -70,6 +82,7 @@ namespace NintendoSwitch{ namespace PokemonSV{ using namespace Pokemon; +using namespace ML; static constexpr size_t INDEX_OF_LAST_TUTORIAL_SEGMENT = 9; static constexpr size_t INDEX_OF_LAST_TUTORIAL_CHECKPOINT = 20; @@ -112,8 +125,15 @@ 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()); + if (PreloadSettings::instance().DEVELOPER_MODE){ + 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()); + } return segment_list; }; @@ -276,6 +296,15 @@ std::vector> make_autoStory_checkpoint_lis checkpoint_list.emplace_back(std::make_unique()); checkpoint_list.emplace_back(std::make_unique()); + if (PreloadSettings::instance().DEVELOPER_MODE){ + checkpoint_list.emplace_back(std::make_unique()); + checkpoint_list.emplace_back(std::make_unique()); + checkpoint_list.emplace_back(std::make_unique()); + // checkpoint_list.emplace_back(std::make_unique()); + // checkpoint_list.emplace_back(std::make_unique()); + // checkpoint_list.emplace_back(std::make_unique()); + // checkpoint_list.emplace_back(std::make_unique()); + } return checkpoint_list; }; @@ -658,11 +687,34 @@ AutoStory::AutoStory() LockMode::UNLOCK_WHILE_RUNNING, 0 ) + , TEST_YOLO_BOX( + "TEST: get_yolo_box():", + LockMode::UNLOCK_WHILE_RUNNING, + false + ) + , YOLO_PATH( + false, + "YOLO Path:", + LockMode::LOCK_WHILE_RUNNING, + "PokemonSV/YOLO/yolo_area0_station1.onnx", + "<.onnx file>" + ) + , TARGET_LABEL( + false, + "YOLO Object Label:", + LockMode::LOCK_WHILE_RUNNING, + "rock-1", + "" + ) { if (PreloadSettings::instance().DEVELOPER_MODE){ PA_ADD_OPTION(m_advanced_options); + PA_ADD_OPTION(TEST_YOLO_BOX); + PA_ADD_OPTION(YOLO_PATH); + PA_ADD_OPTION(TARGET_LABEL); + PA_ADD_OPTION(FLYPOINT_TYPE); PA_ADD_OPTION(TEST_FLYPOINT_LOCATIONS); PA_ADD_OPTION(TEST_MOVE_CURSOR_OFFSET_FROM_FLYPOINT); @@ -1137,6 +1189,18 @@ void AutoStory::run_autostory(SingleSwitchProgramEnvironment& env, ProController void AutoStory::test_code(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + + if (TEST_YOLO_BOX){ + VideoOverlaySet overlays(env.console.overlay()); + YOLOv5Detector yolo_detector(RESOURCE_PATH() + std::string(YOLO_PATH)); + + ImageFloatBox target_box = get_yolo_box(env, context, overlays, yolo_detector, TARGET_LABEL); + + context.wait_for(Milliseconds(1000)); + return; + } + + if (TEST_FLYPOINT_LOCATIONS){ print_flypoint_location(env.program_info(), env.console, context, FLYPOINT_TYPE); // print_flypoint_location(env.program_info(), env.console, context, FlyPoint::FAST_TRAVEL); @@ -1200,6 +1264,11 @@ void AutoStory::test_code(SingleSwitchProgramEnvironment& env, ProControllerCont DirectionDetector direction; + YOLOv5Detector yolo_detector(RESOURCE_PATH() + "PokemonSV/YOLO/yolo_area0_station1.onnx"); + // move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "tree-tera", 0.294444); + // move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "tree-tera", 0.604688); + + return; } diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.h b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.h index ad74fea122..00a5d756cf 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.h +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory.h @@ -11,6 +11,7 @@ #include "Common/Cpp/Options/SimpleIntegerOption.h" #include "Common/Cpp/Options/FloatingPointOption.h" #include "Common/Cpp/Options/EnumDropdownOption.h" +#include "Common/Cpp/Options/StringOption.h" #include "CommonFramework/Notifications/EventNotificationsTable.h" #include "CommonTools/Options/StringSelectOption.h" #include "CommonTools/Options/LanguageOCROption.h" @@ -147,6 +148,12 @@ class AutoStory : public SingleSwitchProgramInstance, public ConfigOption::Liste BooleanCheckBoxOption TEST_MOVE_CURSOR_OFFSET_FROM_FLYPOINT; FloatingPointOption X_OFFSET; FloatingPointOption Y_OFFSET; + + BooleanCheckBoxOption TEST_YOLO_BOX; + StringOption YOLO_PATH; + StringOption TARGET_LABEL; + + }; const std::vector>& ALL_AUTO_STORY_SEGMENT_LIST(); diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.cpp b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.cpp index 76f42784be..523892dcc1 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.cpp +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.cpp @@ -17,6 +17,7 @@ #include "PokemonSV/Inference/Dialogs/PokemonSV_DialogDetector.h" #include "PokemonSV/Inference/Overworld/PokemonSV_OverworldDetector.h" #include "PokemonSV/Inference/Overworld/PokemonSV_StationaryOverworldWatcher.h" +#include "PokemonSV/Inference/Overworld/PokemonSV_NoMinimapDetector.h" #include "PokemonSV/Inference/PokemonSV_MainMenuDetector.h" #include "PokemonSV/Programs/PokemonSV_MenuNavigation.h" #include "PokemonSV/Programs/PokemonSV_GameEntry.h" @@ -82,10 +83,10 @@ void clear_dialog(VideoStream& stream, ProControllerContext& context, bool seen_dialog = false; WallClock start = current_time(); while (true){ - if (current_time() - start > std::chrono::minutes(3)){ + if (current_time() - start > std::chrono::minutes(5)){ OperationFailedException::fire( ErrorReport::SEND_ERROR_REPORT, - "clear_dialog(): Failed to clear dialog after 3 minutes.", + "clear_dialog(): Failed to clear dialog after 5 minutes.", stream ); } @@ -728,6 +729,79 @@ void do_action_and_monitor_for_battles( } } +void do_action_and_monitor_for_battles_early( + const ProgramInfo& info, + VideoStream& stream, + ProControllerContext& context, + std::function< + void(const ProgramInfo& info, + VideoStream& stream, + ProControllerContext& context) + >&& action +){ + NoMinimapWatcher no_minimap(stream.logger(), COLOR_RED, Milliseconds(250)); + int ret = run_until( + stream, context, + [&](ProControllerContext& context){ + context.wait_for_all_requests(); + action(info, stream, context); + }, + {no_minimap} + ); + if (ret == 0){ // if see no minimap. stop and see if we detect a battle. if so, throw Battl exception + do_action_and_monitor_for_battles(info, stream, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + pbf_wait(context, Seconds(15)); + }); + + // if no battle seen, then throw Exception. + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "do_action_and_monitor_for_battles_early(): Expected to see a battle, but didn't. Possible false positive on NoMinimapWatcher.", + stream + ); + } + +} + + +void do_action_until_dialog( + const ProgramInfo& info, + VideoStream& stream, + ProControllerContext& context, + std::function< + void(const ProgramInfo& info, + VideoStream& stream, + ProControllerContext& context) + >&& action +){ + AdvanceDialogWatcher dialog(COLOR_RED); + int ret = run_until( + stream, context, + [&](ProControllerContext& context){ + context.wait_for_all_requests(); + action(info, stream, context); + }, + {dialog} + ); + context.wait_for(std::chrono::milliseconds(100)); + + switch (ret){ + case 0: // dialog + stream.log("do_action_until_dialog(): Detected dialog."); + return; + default: + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "do_action_until_dialog(): Finished action. Did not detect dialog.", + stream + ); + } + +} + + + void handle_unexpected_battles( const ProgramInfo& info, @@ -1331,6 +1405,543 @@ void checkpoint_reattempt_loop_tutorial( } } +void move_player_forward( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + uint8_t num_rounds, + std::function&& recovery_action, + bool use_lets_go, + uint16_t forward_ticks, + uint8_t y, + uint16_t delay_after_forward_move, + uint16_t delay_after_lets_go +){ + + context.wait_for_all_requests(); + for (size_t i = 0; i < num_rounds; i++){ + try{ + do_action_and_monitor_for_battles_early(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + if (!use_lets_go){ + pbf_move_left_joystick(context, 128, y, forward_ticks, 0); + }else{ + pbf_press_button(context, BUTTON_R, 20, delay_after_lets_go); + pbf_move_left_joystick(context, 128, y, forward_ticks, delay_after_forward_move); + } + }); + }catch (UnexpectedBattleException&){ + recovery_action(); + // run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + } + } + +} + +ImageFloatBox get_yolo_box( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + VideoOverlaySet& overlays, + YOLOv5Detector& yolo_detector, + const std::string& target_label +){ + context.wait_for_all_requests(); + overlays.clear(); + const std::vector& detected_boxes = yolo_detector.detected_boxes(); + auto snapshot = env.console.video().snapshot(); + yolo_detector.detect(snapshot); + + ImageFloatBox target_box{-1, -1, -1, -1}; + for (YOLOv5Session::DetectionBox detected_box : detected_boxes){ + ImageFloatBox box = detected_box.box; + std::string label = yolo_detector.session()->label_name(detected_box.label_idx); + if (target_label == label){ + target_box = box; + overlays.add(COLOR_RED, box, label); + }else{ + overlays.add(COLOR_BLUE, box, label); + } + + } + + env.console.log(std::string(target_label) + ": {" + std::to_string(target_box.x) + ", " + std::to_string(target_box.y) + ", " + std::to_string(target_box.width) + ", " + std::to_string(target_box.height) + "}"); + env.console.log("center-y: " + std::to_string(target_box.y + target_box.height/2) + " center-x: " + std::to_string(target_box.x + target_box.width/2)); + + return target_box; +} + +void move_forward_until_yolo_object_above_min_size( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + double min_width, double min_height, + std::function&& recovery_action, + uint16_t forward_ticks, + uint8_t y, + uint16_t delay_after_forward_move, + uint16_t delay_after_lets_go +){ + context.wait_for_all_requests(); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + + VideoOverlaySet overlays(env.console.overlay()); + bool seen_object = false; + size_t not_detected_cont = 0; + size_t max_not_detected = 5; + size_t forward_move_count = 0; + bool reached_target = false; + bool exceed_times_not_detected = false; + while(!reached_target && !exceed_times_not_detected){ + forward_move_count++; + try{ + do_action_and_monitor_for_battles_early(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + context.wait_for_all_requests(); + ImageFloatBox target_box = get_yolo_box(env, context, overlays, yolo_detector, target_label); + + bool not_found_target = target_box.x == -1; + if (not_found_target){ + not_detected_cont++; + if (not_detected_cont > max_not_detected){ + exceed_times_not_detected = true; + return; // when too many failed attempts, just assume we're too close to the target to detect it. + } + context.wait_for(1000ms); // if we can't see the object, it might just be temporarily obscured. wait one second and reattempt. + return; + }else{ + seen_object = true; + not_detected_cont = 0; + } + + if (target_box.width > min_width && target_box.height > min_height){ + reached_target = true; + return; // stop when the target is above a certain size. i.e. we are close enough to the target. + } + + pbf_move_left_joystick(context, 128, y, forward_ticks, 0); + // pbf_press_button(context, BUTTON_R, 20, delay_after_lets_go); + // pbf_move_left_joystick(context, 128, y, forward_ticks, delay_after_forward_move); + }); + }catch (UnexpectedBattleException&){ + overlays.clear(); + recovery_action(); + // run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_camera_yolo(); + } + + if (forward_move_count > 50){ + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "move_forward_until_yolo_object_above_min_size(): Unable to reach target object after many attempts.", + env.console + ); + } + } + + if (!seen_object){ + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "move_forward_until_yolo_object_above_min_size(): Never detected the yolo object.", + env.console + ); + } +} + + + +void move_forward_until_yolo_object_detected( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + std::function&& recovery_action, + uint16_t max_rounds, + uint16_t forward_ticks, + uint8_t y, + uint16_t delay_after_forward_move, + uint16_t delay_after_lets_go +){ + context.wait_for_all_requests(); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + + VideoOverlaySet overlays(env.console.overlay()); + bool found_target = false; + size_t round_num = 0; + while(!found_target){ + try{ + do_action_and_monitor_for_battles_early(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + context.wait_for_all_requests(); + ImageFloatBox target_box = get_yolo_box(env, context, overlays, yolo_detector, target_label); + found_target = target_box.x != -1; + if (found_target){ + return; + } + + + + pbf_move_left_joystick(context, 128, y, forward_ticks, 0); + // pbf_press_button(context, BUTTON_R, 20, delay_after_lets_go); + // pbf_move_left_joystick(context, 128, y, forward_ticks, delay_after_forward_move); + }); + + }catch (UnexpectedBattleException&){ + overlays.clear(); + recovery_action(); + // run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_camera_yolo(); + } + + + round_num++; + if (round_num > max_rounds){ + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "move_forward_until_yolo_object_detected(): Unable to detect target object.", + env.console + ); + } + } +} + +void move_forward_until_yolo_object_not_detected( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + size_t times_not_seen_threshold, + std::function&& recovery_action, + uint16_t forward_ticks, + uint8_t y, + uint16_t delay_after_forward_move, + uint16_t delay_after_lets_go +){ + VideoOverlaySet overlays(env.console.overlay()); + bool target_visible = true; + size_t max_rounds = 50; + size_t times_not_seen = 0; + size_t round_num = 0; + while(times_not_seen < times_not_seen_threshold){ + try{ + do_action_and_monitor_for_battles_early(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + context.wait_for_all_requests(); + ImageFloatBox target_box = get_yolo_box(env, context, overlays, yolo_detector, target_label); + target_visible = target_box.x != -1; + if (!target_visible){ // stop when target not visible + times_not_seen++; + if (times_not_seen >= times_not_seen_threshold){ + return; + } + } + + pbf_move_left_joystick(context, 128, y, forward_ticks, 0); + // pbf_press_button(context, BUTTON_R, 20, delay_after_lets_go); + // pbf_move_left_joystick(context, 128, y, forward_ticks, delay_after_forward_move); + }); + + }catch (UnexpectedBattleException&){ + overlays.clear(); + recovery_action(); + // run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_camera_yolo(); + } + round_num++; + + if (round_num > max_rounds){ + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "move_forward_until_yolo_object_not_detected(): Unable to walk away from target object.", + env.console + ); + } + } +} + + +void move_camera_yolo( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + CameraAxis axis, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + double target_line, + std::function&& recovery_action +){ + VideoOverlaySet overlays(env.console.overlay()); + bool seen_object = false; + size_t max_attempts = 20; + size_t not_detected_count = 0; + size_t max_not_detected = 5; + bool reached_target_line = false; + bool exceed_max_not_detected = false; + for (size_t i = 0; i < max_attempts; i++){ + try{ + do_action_and_monitor_for_battles_early(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + context.wait_for_all_requests(); + ImageFloatBox target_box = get_yolo_box(env, context, overlays, yolo_detector, target_label); + + bool not_found_target = target_box.x == -1; + if (not_found_target){ + not_detected_count++; + if (not_detected_count > max_not_detected){ + exceed_max_not_detected = true; + return; // when too many failed attempts, just assume we're too close to the target to detect it. + } + context.wait_for(1000ms); // if we can't see the object, it might just be temporarily obscured. wait one second and reattempt. + return; + }else{ + not_detected_count = 0; + seen_object = true; + } + + + double diff; + switch(axis){ + case CameraAxis::X:{ + double object_x_pos = target_box.x + target_box.width/2; + diff = target_line - object_x_pos; + break; + } + case CameraAxis::Y:{ + double object_y_pos = target_box.y + target_box.height/2; + diff = target_line - object_y_pos; + break; + } + default: + throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "move_camera_yolo: Unknown CameraAxis enum."); + } + env.console.log("target_line: " + std::to_string(target_line)); + env.console.log("diff: " + std::to_string(diff)); + if (std::abs(diff) < 0.01){ + reached_target_line = true; + return; // close enough to target_line. stop. + } + + + double duration_scale_factor; + double push_magnitude_scale_factor; + switch(axis){ + case CameraAxis::X: + duration_scale_factor = 250 / std::sqrt(std::abs(diff)); + if (std::abs(diff) < 0.05){ + duration_scale_factor /= 2; + } + push_magnitude_scale_factor = 60 / std::sqrt(std::abs(diff)); + break; + case CameraAxis::Y: + duration_scale_factor = 100 / std::sqrt(std::abs(diff)); + if (std::abs(diff) < 0.1){ + duration_scale_factor *= 0.5; + } + push_magnitude_scale_factor = 60 / std::sqrt(std::abs(diff)); + break; + + default: + throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "move_camera_yolo: Unknown CameraAxis enum."); + } + + uint16_t push_duration = std::max(uint16_t(std::abs(diff * duration_scale_factor)), uint16_t(8)); + int16_t push_direction = (diff > 0) ? -1 : 1; + double push_magnitude = std::max(double(std::abs(diff * push_magnitude_scale_factor)), double(15)); + uint8_t axis_push = uint8_t(std::max(std::min(int(128 + (push_direction * push_magnitude)), 255), 0)); + + // env.console.log("object_x: {" + std::to_string(target_box.x) + ", " + std::to_string(target_box.y) + ", " + std::to_string(target_box.width) + ", " + std::to_string(target_box.height) + "}"); + // env.console.log("object_x_pos: " + std::to_string(object_x_pos)); + env.console.log("axis push: " + std::to_string(axis_push) + ", push duration: " + std::to_string(push_duration)); + switch(axis){ + case CameraAxis::X:{ + pbf_move_right_joystick(context, axis_push, 128, push_duration, 0); + break; + } + case CameraAxis::Y:{ + pbf_move_right_joystick(context, 128, axis_push, push_duration, 0); + break; + } + default: + throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "move_camera_yolo: Unknown CameraAxis enum."); + } + }); + + if(reached_target_line || exceed_max_not_detected){ + break; + } + + }catch (UnexpectedBattleException&){ + overlays.clear(); + recovery_action(); + // run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + } + } + + if (!seen_object){ + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "move_camera_yolo(): Never detected the yolo object.", + env.console + ); + } +} + +bool move_player_to_realign_via_yolo( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + double x_target +){ + + VideoOverlaySet overlays(env.console.overlay()); + bool seen_object = false; + size_t max_attempts = 10; + size_t not_detected_count = 0; + size_t max_not_detected = 5; + bool reached_target_line = false; + bool exceed_max_not_detected = false; + for (size_t i = 0; i < max_attempts; i++){ + try{ + do_action_and_monitor_for_battles_early(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + context.wait_for_all_requests(); + ImageFloatBox target_box = get_yolo_box(env, context, overlays, yolo_detector, target_label); + + bool not_found_target = target_box.x == -1; + if (not_found_target){ + not_detected_count++; + if (not_detected_count > max_not_detected){ + exceed_max_not_detected = true; + return; // when too many failed attempts, just assume we're too close to the target to detect it. + } + context.wait_for(1000ms); // if we can't see the object, it might just be temporarily obscured. wait one second and reattempt. + return; + }else{ + seen_object = true; + not_detected_count = 0; + } + + double object_x_pos = target_box.x + target_box.width/2; + double diff = x_target - object_x_pos; + + env.console.log("x_target: " + std::to_string(x_target)); + env.console.log("diff: " + std::to_string(diff)); + if (std::abs(diff) < 0.05){ + reached_target_line = true; + return; // close enough to target_line. stop. + } + + double duration_scale_factor = 500 / std::sqrt(std::abs(diff)); + // if (std::abs(diff) < 0.05){ + // duration_scale_factor /= 2; + // } + double push_magnitude_scale_factor = 60 / std::sqrt(std::abs(diff)); + + uint16_t push_duration = std::max(uint16_t(std::abs(diff * duration_scale_factor)), uint16_t(8)); + int16_t push_direction = (diff > 0) ? -1 : 1; + double push_magnitude = std::max(double(std::abs(diff * push_magnitude_scale_factor)), double(15)); + uint8_t x_push = uint8_t(std::max(std::min(int(128 + (push_direction * push_magnitude)), 255), 0)); + + // env.console.log("object_x: {" + std::to_string(target_box.x) + ", " + std::to_string(target_box.y) + ", " + std::to_string(target_box.width) + ", " + std::to_string(target_box.height) + "}"); + // env.console.log("object_x_pos: " + std::to_string(object_x_pos)); + env.console.log("x push: " + std::to_string(x_push) + ", push duration: " + std::to_string(push_duration)); + if (i == 0){ + pbf_move_left_joystick(context, x_push, 128, 10, 50); + pbf_press_button(context, BUTTON_R, 20, 105); + } + + pbf_move_left_joystick(context, x_push, 128, push_duration, 0); + + }); + + if (exceed_max_not_detected){ + return false; + } + + if(reached_target_line){ + return true; + } + + }catch (UnexpectedBattleException&){ + overlays.clear(); + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + } + } + + if (!seen_object){ + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "move_player_to_realign_via_yolo(): Never detected the yolo object.", + env.console + ); + } + + return false; +} + + +void move_player_to_realign_via_yolo_with_recovery( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + double x_target, + std::function&& recovery_action +){ + bool succeed_realign_attempt_1 = move_player_to_realign_via_yolo(env, context, yolo_detector, target_label, x_target); + if (!succeed_realign_attempt_1){ + recovery_action(); + move_player_to_realign_via_yolo(env, context, yolo_detector, target_label, x_target); // second attempt. + } +} + + +void move_camera_until_yolo_object_detected( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + uint8_t initial_x_move, + uint16_t initial_hold_ticks, + uint16_t max_rounds +){ + VideoOverlaySet overlays(env.console.overlay()); + bool found_target = false; + size_t round_num = 0; + uint8_t x_move = initial_x_move > 128 ? 255 : 0; + while(!found_target){ + try{ + do_action_and_monitor_for_battles_early(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + + if (round_num == 0){ + pbf_move_right_joystick(context, initial_x_move, 128, initial_hold_ticks, 50); + } + context.wait_for_all_requests(); + ImageFloatBox target_box = get_yolo_box(env, context, overlays, yolo_detector, target_label); + found_target = target_box.x != -1; + if (found_target){ + return; + } + + + + pbf_move_right_joystick(context, x_move, 128, 10, 50); + }); + + }catch (UnexpectedBattleException&){ + overlays.clear(); + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + } + round_num++; + if (round_num > max_rounds){ + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "move_camera_until_yolo_object_detected(): Unable to detect target object.", + env.console + ); + } + } +} diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.h b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.h index bf5809a9a9..78a5c03426 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.h +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStoryTools.h @@ -8,17 +8,18 @@ #define PokemonAutomation_PokemonSV_AutoStoryTools_H #include +#include "ML/Inference/ML_YOLOv5Detector.h" #include "CommonFramework/Language.h" #include "CommonFramework/ImageTools/ImageBoxes.h" #include "CommonFramework/ProgramStats/StatsTracking.h" #include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h" #include "PokemonSV/Programs/PokemonSV_WorldNavigation.h" -// #include "PokemonSV/Programs/PokemonSV_Navigation.h" namespace PokemonAutomation{ namespace NintendoSwitch{ namespace PokemonSV{ +using namespace ML; struct AutoStoryStats : public StatsTracker{ AutoStoryStats() @@ -74,6 +75,10 @@ enum class NavigationStopCondition{ STOP_BATTLE, }; +// struct MinimumDetectedSize{ +// double width; +// double height; +// }; struct AutoStoryOptions{ @@ -181,6 +186,31 @@ void do_action_and_monitor_for_battles( >&& action ); +// run the given `action`. if detect no minimap, stop the action. +// wait 15 seconds and see if we find a battle. if so, throw Battle exception. if no battle, then throw OperationFailedException +void do_action_and_monitor_for_battles_early( + const ProgramInfo& info, + VideoStream& stream, + ProControllerContext& context, + std::function< + void(const ProgramInfo& info, + VideoStream& stream, + ProControllerContext& context) + >&& action +); + +void do_action_until_dialog( + const ProgramInfo& info, + VideoStream& stream, + ProControllerContext& context, + std::function< + void(const ProgramInfo& info, + VideoStream& stream, + ProControllerContext& context) + >&& action +); + + // catch any UnexpectedBattle exceptions from `action`. then use run_battle_press_A until overworld, and re-try the `action`. void handle_unexpected_battles( const ProgramInfo& info, @@ -345,14 +375,134 @@ void checkpoint_reattempt_loop_tutorial( ); +// walk forward forward_ticks. repeat this for num_rounds. +// if detect battle, kill the Pokemon. then continue. If we run into a battle, this round is considered to be done and will not be repeated. +void move_player_forward( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + uint8_t num_rounds, + std::function&& recovery_action, + bool use_lets_go = false, + uint16_t forward_ticks = 100, + uint8_t y = 0, + uint16_t delay_after_forward_move = 50, + uint16_t delay_after_lets_go = 105 +); +// get the box of the target object +// return ImageFloatBox{-1, -1, -1, -1} if target object not found +ImageFloatBox get_yolo_box( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + VideoOverlaySet& overlays, + YOLOv5Detector& yolo_detector, + const std::string& target_label +); +// move forward until detected object is a certain width and height on screen (min_size) +// walk forward forward_ticks each time +// if caught in battle, run recovery_action +// throw exception if forward_move_count is above 50. +// throw exception if never detected yolo object +void move_forward_until_yolo_object_above_min_size( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + double min_width, double min_height, + std::function&& recovery_action, + uint16_t forward_ticks = 100, + uint8_t y = 0, + uint16_t delay_after_forward_move = 50, + uint16_t delay_after_lets_go = 105 +); +// walk forward forward_ticks each time +// walk until we find the target object. +// if caught in battle, run recovery_action +// throw exception if exceed max_rounds. +void move_forward_until_yolo_object_detected( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + std::function&& recovery_action, + uint16_t max_rounds, + uint16_t forward_ticks = 100, + uint8_t y = 0, + uint16_t delay_after_forward_move = 50, + uint16_t delay_after_lets_go = 105 +); +// walk forward forward_ticks each time +// walk until we no longer see the target object. and haven't seen `it times_not_seen_threshold` times. +// if caught in battle, run recovery_action +// throw exception if exceed max_rounds. +void move_forward_until_yolo_object_not_detected( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + size_t times_not_seen_threshold, + std::function&& recovery_action, + uint16_t forward_ticks = 100, + uint8_t y = 0, + uint16_t delay_after_forward_move = 50, + uint16_t delay_after_lets_go = 105 +); +enum class CameraAxis{ + X, + Y, +}; + +// move the camera along `axis` until the target object is aligned with target_line +// if caught in battle, run recovery_action +// throw exception if never detected yolo object +void move_camera_yolo( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + CameraAxis axis, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + double target_line, + std::function&& recovery_action +); + +// move the player sideways until the target object is aligned with x_target +// throw exception if never detected yolo object +bool move_player_to_realign_via_yolo( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + double x_target +); +// move the player sideways until the target object is aligned with x_target +// if failed. try recovery action once, then re-try. +void move_player_to_realign_via_yolo_with_recovery( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + double x_target, + std::function&& recovery_action +); +// move camera in X direction until we find the target object. +// if caught in battle, run recovery_action +// throw exception if exceed max_rounds. +void move_camera_until_yolo_object_detected( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + YOLOv5Detector& yolo_detector, + const std::string& target_label, + uint8_t initial_x_move, + uint16_t initial_hold_ticks, + uint16_t max_rounds = 50 +); } 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 02d1435ccb..da5c645e00 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.cpp +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.cpp @@ -244,14 +244,6 @@ void checkpoint_92(SingleSwitchProgramEnvironment& env, ProControllerContext& co }); } -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 446c41d488..361b12f0eb 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.h +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.h @@ -64,17 +64,7 @@ void checkpoint_91(SingleSwitchProgramEnvironment& env, ProControllerContext& co // end: Beat Arven. At Los Platos Pokecenter. 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); diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_35.cpp b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_35.cpp index 53c2f4c4af..f796be0d16 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_35.cpp +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_35.cpp @@ -4,6 +4,9 @@ * */ +#include "ML/Inference/ML_YOLOv5Detector.h" +#include "CommonFramework/VideoPipeline/VideoFeed.h" + #include "CommonFramework/Exceptions/OperationFailedException.h" #include "CommonTools/Async/InferenceRoutines.h" #include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" @@ -17,26 +20,24 @@ //#include //using std::cout; //using std::endl; -//#include -//#include namespace PokemonAutomation{ namespace NintendoSwitch{ namespace PokemonSV{ - +using namespace ML; std::string AutoStory_Segment_35::name() const{ - return ""; + return "35: Area Zero Gate, Station 1"; } std::string AutoStory_Segment_35::start_text() const{ - return "Start: "; + return "Start: Beat Nemona, Penny, and Arven. At Los Platos Pokecenter."; } std::string AutoStory_Segment_35::end_text() const{ - return "End: "; + return "End: At Area Zero Station 1. Deactivated the locks."; } void AutoStory_Segment_35::run_segment( @@ -52,13 +53,651 @@ void AutoStory_Segment_35::run_segment( context.wait_for_all_requests(); env.console.log("Start Segment " + name(), COLOR_ORANGE); - // checkpoint_(env, context, options.notif_status_update, stats); + AutoStory_Checkpoint_93().run_checkpoint(env, context, options, stats); + AutoStory_Checkpoint_94().run_checkpoint(env, context, options, stats); + AutoStory_Checkpoint_95().run_checkpoint(env, context, options, stats); + context.wait_for_all_requests(); env.console.log("End Segment " + name(), COLOR_GREEN); } +std::string AutoStory_Checkpoint_93::name() const{ return "093 - " + AutoStory_Segment_35().name(); } +std::string AutoStory_Checkpoint_93::start_text() const{ return "Beat Arven. At Los Platos Pokecenter.";} +std::string AutoStory_Checkpoint_93::end_text() const{ return "Entered Area Zero Gate. Flew down to Area Zero from the platform.";} +void AutoStory_Checkpoint_93::run_checkpoint(SingleSwitchProgramEnvironment& env, ProControllerContext& context, AutoStoryOptions options, AutoStoryStats& stats) const{ + checkpoint_93(env, context, options.notif_status_update, stats); +} + +std::string AutoStory_Checkpoint_94::name() const{ return "094 - " + AutoStory_Segment_35().name(); } +std::string AutoStory_Checkpoint_94::start_text() const{ return AutoStory_Checkpoint_93().end_text();} +std::string AutoStory_Checkpoint_94::end_text() const{ return "Outside Area Zero Station 1. Defeated Glimmora.";} +void AutoStory_Checkpoint_94::run_checkpoint(SingleSwitchProgramEnvironment& env, ProControllerContext& context, AutoStoryOptions options, AutoStoryStats& stats) const{ + checkpoint_94(env, context, options.notif_status_update, stats); +} + +std::string AutoStory_Checkpoint_95::name() const{ return "095 - " + AutoStory_Segment_35().name(); } +std::string AutoStory_Checkpoint_95::start_text() const{ return AutoStory_Checkpoint_94().end_text();} +std::string AutoStory_Checkpoint_95::end_text() const{ return "At Area Zero Station 1. Deactivated the locks.";} +void AutoStory_Checkpoint_95::run_checkpoint(SingleSwitchProgramEnvironment& env, ProControllerContext& context, AutoStoryOptions options, AutoStoryStats& stats) const{ + checkpoint_95(env, context, options.notif_status_update, stats); +} + +// std::string AutoStory_Checkpoint_96::name() const{ return "096 - " + AutoStory_Segment_3().name(); } +// std::string AutoStory_Checkpoint_96::start_text() const{ return "";} +// std::string AutoStory_Checkpoint_96::end_text() const{ return "";} +// void AutoStory_Checkpoint_96::run_checkpoint(SingleSwitchProgramEnvironment& env, ProControllerContext& context, AutoStoryOptions options, AutoStoryStats& stats) const{ +// checkpoint_96(env, context, options.notif_status_update, stats); +// } + +// std::string AutoStory_Checkpoint_97::name() const{ return "097 - " + AutoStory_Segment_3().name(); } +// std::string AutoStory_Checkpoint_97::start_text() const{ return "";} +// std::string AutoStory_Checkpoint_97::end_text() const{ return "";} +// void AutoStory_Checkpoint_97::run_checkpoint(SingleSwitchProgramEnvironment& env, ProControllerContext& context, AutoStoryOptions options, AutoStoryStats& stats) const{ +// checkpoint_97(env, context, options.notif_status_update, stats); +// } + +// std::string AutoStory_Checkpoint_98::name() const{ return "098 - " + AutoStory_Segment_3().name(); } +// std::string AutoStory_Checkpoint_98::start_text() const{ return "";} +// std::string AutoStory_Checkpoint_98::end_text() const{ return "";} +// void AutoStory_Checkpoint_98::run_checkpoint(SingleSwitchProgramEnvironment& env, ProControllerContext& context, AutoStoryOptions options, AutoStoryStats& stats) const{ +// checkpoint_98(env, context, options.notif_status_update, stats); +// } + +// std::string AutoStory_Checkpoint_99::name() const{ return "099 - " + AutoStory_Segment_3().name(); } +// std::string AutoStory_Checkpoint_99::start_text() const{ return "";} +// std::string AutoStory_Checkpoint_99::end_text() const{ return "";} +// void AutoStory_Checkpoint_99::run_checkpoint(SingleSwitchProgramEnvironment& env, ProControllerContext& context, AutoStoryOptions options, AutoStoryStats& stats) const{ +// checkpoint_99(env, context, options.notif_status_update, stats); +// } + +void checkpoint_93(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ + checkpoint_reattempt_loop(env, context, notif_status_update, stats, + [&](size_t attempt_number){ + // fly to Medali West + move_cursor_towards_flypoint_and_go_there(env.program_info(), env.console, context, {ZoomChange::ZOOM_OUT, 95, 0, 170}, FlyPoint::POKECENTER); + + // marker 1 {0.580729, 0.286111} + place_marker_offset_from_flypoint(env.program_info(), env.console, context, + {ZoomChange::KEEP_ZOOM, 0, 0, 0}, + FlyPoint::POKECENTER, + {0.580729, 0.286111} + ); + 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, 20, false); + }, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + pbf_move_left_joystick(context, 255, 255, 40, 50); + realign_player(env.program_info(), env.console, context, PlayerRealignMode::REALIGN_OLD_MARKER); + } + ); + + // marker 2 {0.475, 0.4} + place_marker_offset_from_flypoint(env.program_info(), env.console, context, + {ZoomChange::KEEP_ZOOM, 0, 0, 0}, + FlyPoint::POKECENTER, + {0.475, 0.4} + ); + 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, 20, 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.473958, 0.260185} {0.479687, 0.250926} + place_marker_offset_from_flypoint(env.program_info(), env.console, context, + {ZoomChange::KEEP_ZOOM, 0, 255, 30}, + FlyPoint::POKECENTER, + {0.479687, 0.250926} + ); + 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, 20, 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 4 {0.425, 0.289815} + place_marker_offset_from_flypoint(env.program_info(), env.console, context, + {ZoomChange::KEEP_ZOOM, 0, 0, 0}, + FlyPoint::POKECENTER, + {0.425, 0.289815} + ); + 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, 20, 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 5 {0.465104, 0.292593} + place_marker_offset_from_flypoint(env.program_info(), env.console, context, + {ZoomChange::KEEP_ZOOM, 255, 0, 20}, + FlyPoint::POKECENTER, + {0.465104, 0.292593} + ); + 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, 20, 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 6 {0.439583, 0.274074} + place_marker_offset_from_flypoint(env.program_info(), env.console, context, + {ZoomChange::ZOOM_OUT, 255, 255, 20}, + FlyPoint::POKECENTER, + {0.439583, 0.274074} + ); + 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, 40, 20, false); + }, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + pbf_move_left_joystick(context, 255, 255, 40, 50); + realign_player(env.program_info(), env.console, context, PlayerRealignMode::REALIGN_OLD_MARKER); + } + ); + + clear_dialog(env.console, context, ClearDialogMode::STOP_OVERWORLD, 120, {CallbackEnum::OVERWORLD, CallbackEnum::BLACK_DIALOG_BOX}); + pbf_move_left_joystick(context, 128, 0, 100, 50); + pbf_move_left_joystick(context, 255, 70, 300, 50); + mash_button_till_overworld(env.console, context, BUTTON_A); + // clear_dialog(env.console, context, ClearDialogMode::STOP_OVERWORLD, 120, {CallbackEnum::OVERWORLD, CallbackEnum::BLACK_DIALOG_BOX, CallbackEnum::PROMPT_DIALOG}); + + walk_forward_until_dialog(env.program_info(), env.console, context, NavigationMovementMode::DIRECTIONAL_ONLY, 30); + mash_button_till_overworld(env.console, context, BUTTON_A); // prompt, black dialog. random A press + + }); + +} + +void checkpoint_94(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ + checkpoint_reattempt_loop(env, context, notif_status_update, stats, + [&](size_t attempt_number){ + + + YOLOv5Detector yolo_detector(RESOURCE_PATH() + "PokemonSV/YOLO/yolo_area0_station1.onnx"); + + #if 0 + #endif + + move_player_forward(env, context, 6, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + } + ); + + // confirm we can see tree-tera + move_forward_until_yolo_object_detected(env, context, yolo_detector, "tree-tera", + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + }, + 5 + ); + // align to tree-tera. center-y: 0.294444 center-x: 0.604688 + move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "tree-tera", 0.294444, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "tree-tera", 0.277344); // x-position of tree-tera prior to camera move + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "tree-tera", 0.604688, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_player_to_realign_via_yolo(env, context, yolo_detector, "tree-tera", 0.6); // 0.277344 // set close to target x-position of target object + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + // move towards tree-tera until {0.721875, 0.277778, 0.146875, 0.180556} + move_forward_until_yolo_object_above_min_size(env, context, yolo_detector, "tree-tera", + 0.146, 0.180, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "tree-tera", 0.604688); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + // align to rock-1. center-y: 0.191667 center-x: 0.583594 + move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "rock-1", 0.191667, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-1", 0.578); // x-position of target object prior to camera move + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "rock-1", 0.583594, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-1", 0.58); // 0.578 // set close to target x-position of target object + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + // move towards rock-1 until {0.626563, 0.113889, 0.279688, 0.230556} + move_forward_until_yolo_object_above_min_size(env, context, yolo_detector, "rock-1", + 0.279, 0.230, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-1", 0.583594); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + + // align to rock-2. center-y: 0.194444 center-x: 0.508594 + move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "rock-2", 0.194444, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo_with_recovery(env, context, yolo_detector, "rock-2", 0.25, + [&](){ + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-1", 0.7); + } + ); + // move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-2", 0.5); // x-position of target object prior to camera move + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "rock-2", 0.508594, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_player_to_realign_via_yolo_with_recovery(env, context, yolo_detector, "rock-2", 0.5, + // [&](){ + // move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-1", 0.7); + // } + // ); + // move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-2", 0.5); // 0.223 // set close to target x-position of target object + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + + // move towards rock-2 until {0.471875, 0.244444, 0.103125, 0.266667} + move_forward_until_yolo_object_above_min_size(env, context, yolo_detector, "rock-2", + 0.103, 0.266, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-2", 0.508594); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + // align to rock-3. center-y: 0.190278 center-x: 0.566406 + move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "rock-3", 0.190278, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-3", 0.724); // x-position of target object prior to camera move + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "rock-3", 0.566406, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-3", 0.6); // 0.724 // set close to target x-position of target object + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + // move towards rock-3 until {0.598438, 0.186111, 0.121875, 0.136111} + move_forward_until_yolo_object_above_min_size(env, context, yolo_detector, "rock-3", + 0.121, 0.1, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-3", 0.566406); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + + // align to stream. center-y: 0.481944 center-x: 0.528906 + move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "stream", 0.481944, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "stream", 0.404); // x-position of target object prior to camera move + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "stream", 0.528906, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_player_to_realign_via_yolo(env, context, yolo_detector, "stream", 0.5); // 0.404 // set close to target x-position of target object + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + + // move forward until stream not detected + move_forward_until_yolo_object_not_detected(env, context, yolo_detector, "stream", + 3, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "stream", 0.5); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + pbf_press_button(context, BUTTON_L, 20, 50); + + move_camera_until_yolo_object_detected(env, context, yolo_detector, "rock-3", 255, 10); + + // align to rock-3. center-y: 0.291667 center-x: 0.501563 + move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "rock-3", 0.291667, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-3", 0.8); // x-position of target object prior to camera move + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "rock-3", 0.501563, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-3", 0.5015); // 0.8 // set close to target x-position of target object + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + + // move towards rock-3 until {0.245313, 0.001000, 0.404688, 0.394444} + move_forward_until_yolo_object_above_min_size(env, context, yolo_detector, "rock-3", + 0.404, 0.25, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-3", 0.501563); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + + + + // align to rock-4. center-y: 0.200000 center-x: 0.550781 + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "rock-4", 0.550781, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-4", 0.55); // 0.8 // set close to target x-position of target object + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "rock-4", 0.200000, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-4", 0.55); // set close to target x-position of target object + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + // move towards rock-4 until {0.621875, 0.202778, 0.262500, 0.177778} + move_forward_until_yolo_object_above_min_size(env, context, yolo_detector, "rock-4", + 0.25, 0.177, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-4", 0.550781); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + move_camera_until_yolo_object_detected(env, context, yolo_detector, "tree-1", 0, 70); + + // align to tree-1. center-y: 0.390278 center-x: 0.5 + move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "tree-1", 0.390278, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "tree-1", 0.3); // x-position of target object prior to camera move + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "tree-1", 0.5, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_player_to_realign_via_yolo(env, context, yolo_detector, "tree-1", 0.5); // 0.3 // set close to target x-position of target object + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + // move towards tree-1 until {0.064063, 0.002778, 0.523438, 0.305556} + move_forward_until_yolo_object_above_min_size(env, context, yolo_detector, "tree-1", + 0.52, 0.27, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "tree-1", 0.5); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + + // align to tree-1. center-y: 0.341667 center-x: 0.500000 + move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "tree-1", 0.341667, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "tree-1", 0.5); // x-position of target object prior to camera move + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "tree-1", 0.500000, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_player_to_realign_via_yolo(env, context, yolo_detector, "tree-1", 0.5); // set close to target x-position of target object + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + // move towards tree-1 until {-0.064063, -0.008333, 1.073438, 0.602778} + move_forward_until_yolo_object_above_min_size(env, context, yolo_detector, "tree-1", + 0.8, 0.500, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "tree-1", 0.500000); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + move_camera_until_yolo_object_detected(env, context, yolo_detector, "rock-5", 255, 50); + + // align to rock-5. center-y: 0.206944 center-x: 0.600000 + move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "rock-5", 0.206944, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-5", 0.7); // x-position of target object prior to camera move + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "rock-5", 0.600000, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-5", 0.6); // 0.7 // set close to target x-position of target object + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + // move towards rock-5 until {0.548438, -0.002778, 0.271875, 0.327778} + move_forward_until_yolo_object_above_min_size(env, context, yolo_detector, "rock-5", + 0.271875, 0.327778, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-5", 0.600000); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + move_camera_until_yolo_object_detected(env, context, yolo_detector, "rock-6", 255, 50); + + + + // align to rock-6. center-y: 0.333333 center-x: 0.372656 + move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "rock-6", 0.333333, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-6", 0.66); // 0.7 // x-position of target object prior to camera move + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "rock-6", 0.372656, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-6", 0.37); // set close to target x-position of target object + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + // move towards rock-6 until {0.148438, 0.313889, 0.225000, 0.119444} + move_forward_until_yolo_object_above_min_size(env, context, yolo_detector, "rock-6", + 0.22, 0.119, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock-6", 0.372656); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + + // align to station-1. center-y: 0.286111 center-x: 0.483594 + move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "station-1", 0.286111, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "station-1", 0.64); // x-position of target object prior to camera move + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "station-1", 0.483594, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + // move_player_to_realign_via_yolo(env, context, yolo_detector, "station-1", 0.5); // 0.64 // set close to target x-position of target object + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + do_action_until_dialog(env.program_info(), env.console, context, + [&](const ProgramInfo& info, VideoStream& stream, ProControllerContext& context){ + move_player_forward(env, context, 10, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "station-1", 0.5, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + } + ); + + clear_dialog(env.console, context, ClearDialogMode::STOP_BATTLE, 60, {CallbackEnum::BATTLE}); + run_trainer_double_battle_press_A(env.console, context, BattleStopCondition::STOP_DIALOG); + mash_button_till_overworld(env.console, context, BUTTON_A); + + + #if 0 + // align to rock. + // center before: + // center after: + move_camera_yolo(env, context, CameraAxis::Y, yolo_detector, "rock", 0.000, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock", 0.000); // x-position of target object prior to camera move + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + move_camera_yolo(env, context, CameraAxis::X, yolo_detector, "rock", 0.000, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + // move towards rock until box: + move_forward_until_yolo_object_above_min_size(env, context, yolo_detector, "rock", + 0.000, 0.000, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + move_player_to_realign_via_yolo(env, context, yolo_detector, "rock", 0.000); + pbf_move_left_joystick(context, 128, 0, 10, 50); // move forward to align with camera + } + ); + + #endif + + + + + + }); +} + +void checkpoint_95(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ + // checkpoint_reattempt_loop(env, context, notif_status_update, stats, + // [&](size_t attempt_number){ + #if 0 + move_player_forward(env, context, 5, + [&](){ + run_wild_battle_press_A(env.console, context, BattleStopCondition::STOP_OVERWORLD); + }, + true + ); + // pbf_move_left_joystick(context, 0, 128, 200, 50); + // clear_dialog(env.console, context, ClearDialogMode::STOP_OVERWORLD, 60, {CallbackEnum::BLACK_DIALOG_BOX}); + + pbf_move_left_joystick(context, 0, 128, 10, 0); + pbf_press_button(context, BUTTON_L, 20, 20); + #endif + + // enter Station 1 + walk_forward_until_dialog(env.program_info(), env.console, context, NavigationMovementMode::DIRECTIONAL_ONLY, 20); + mash_button_till_overworld(env.console, context, BUTTON_A); // black dialog + + // disable Lock at Station 1 + walk_forward_until_dialog(env.program_info(), env.console, context, NavigationMovementMode::DIRECTIONAL_SPAM_A, 20); + mash_button_till_overworld(env.console, context, BUTTON_A); // prompt, black dialog, + + + + // }); +} + +// void checkpoint_96(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ +// } + +// void checkpoint_97(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ +// } + +// void checkpoint_98(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ +// } + +// void checkpoint_99(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats){ +// } + + } diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_35.h b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_35.h index 982db9ee6f..83227f449a 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_35.h +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_35.h @@ -26,7 +26,57 @@ class AutoStory_Segment_35 : public AutoStory_Segment{ ) const override; }; +class AutoStory_Checkpoint_93 : public AutoStory_Checkpoint{ +public: + virtual std::string name() const override; + virtual std::string start_text() const override; + virtual std::string end_text() const override; + virtual void run_checkpoint(SingleSwitchProgramEnvironment& env, ProControllerContext& context, AutoStoryOptions options, AutoStoryStats& stats) const override; +}; + +class AutoStory_Checkpoint_94 : public AutoStory_Checkpoint{ +public: + virtual std::string name() const override; + virtual std::string start_text() const override; + virtual std::string end_text() const override; + virtual void run_checkpoint(SingleSwitchProgramEnvironment& env, ProControllerContext& context, AutoStoryOptions options, AutoStoryStats& stats) const override; +}; + +class AutoStory_Checkpoint_95 : public AutoStory_Checkpoint{ +public: + virtual std::string name() const override; + virtual std::string start_text() const override; + virtual std::string end_text() const override; + virtual void run_checkpoint(SingleSwitchProgramEnvironment& env, ProControllerContext& context, AutoStoryOptions options, AutoStoryStats& stats) const override; +}; + +// start: Beat Arven. At Los Platos Pokecenter. +// end: Entered Area Zero Gate. Flew down to Area Zero from the platform. +void checkpoint_93(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); + +// start: Entered Area Zero Gate. Flew down to Area Zero from the platform. +// end: Outside Area Zero Station 1. Defeated Glimmora. +void checkpoint_94(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); + +// start: Outside Area Zero Station 1. Defeated Glimmora. +// end: At Area Zero Station 1. Deactivated the locks. +void checkpoint_95(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); + +// start: +// end: +void checkpoint_96(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); + +// start: +// end: +void checkpoint_97(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); + +// start: +// end: +void checkpoint_98(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); +// start: +// end: +void checkpoint_99(SingleSwitchProgramEnvironment& env, ProControllerContext& context, EventNotificationOption& notif_status_update, AutoStoryStats& stats); } diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_36.cpp b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_36.cpp new file mode 100644 index 0000000000..9140320030 --- /dev/null +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_36.cpp @@ -0,0 +1,66 @@ +/* AutoStory + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/Exceptions/OperationFailedException.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "PokemonSV/Programs/PokemonSV_GameEntry.h" +#include "PokemonSV/Programs/PokemonSV_SaveGame.h" +#include "PokemonSV/Programs/PokemonSV_MenuNavigation.h" +#include "PokemonSV/Programs/PokemonSV_WorldNavigation.h" +#include "PokemonSV_AutoStoryTools.h" +#include "PokemonSV_AutoStory_Segment_36.h" + +//#include +//using std::cout; +//using std::endl; +//#include +//#include + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonSV{ + + + + +std::string AutoStory_Segment_36::name() const{ + return ""; +} + +std::string AutoStory_Segment_36::start_text() const{ + return "Start: "; +} + +std::string AutoStory_Segment_36::end_text() const{ + return "End: "; +} + +void AutoStory_Segment_36::run_segment( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + AutoStoryOptions options, + AutoStoryStats& stats +) const{ + + + stats.m_segment++; + env.update_stats(); + context.wait_for_all_requests(); + env.console.log("Start Segment " + name(), COLOR_ORANGE); + + // AutoStory_Checkpoint_9().run_checkpoint(env, context, options, stats); + + context.wait_for_all_requests(); + env.console.log("End Segment " + name(), COLOR_GREEN); + +} + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_36.h b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_36.h new file mode 100644 index 0000000000..d2ea31c292 --- /dev/null +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_36.h @@ -0,0 +1,35 @@ +/* Autostory + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonSV_AutoStory_Segment_36_H +#define PokemonAutomation_PokemonSV_AutoStory_Segment_36_H + +#include "PokemonSV_AutoStoryTools.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonSV{ + +class AutoStory_Segment_36 : public AutoStory_Segment{ +public: + virtual std::string name() const override; + virtual std::string start_text() const override; + virtual std::string end_text() const override; + virtual void run_segment( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + AutoStoryOptions options, + AutoStoryStats& stats + ) const override; +}; + + + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_37.cpp b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_37.cpp new file mode 100644 index 0000000000..25058db639 --- /dev/null +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_37.cpp @@ -0,0 +1,66 @@ +/* AutoStory + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/Exceptions/OperationFailedException.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "PokemonSV/Programs/PokemonSV_GameEntry.h" +#include "PokemonSV/Programs/PokemonSV_SaveGame.h" +#include "PokemonSV/Programs/PokemonSV_MenuNavigation.h" +#include "PokemonSV/Programs/PokemonSV_WorldNavigation.h" +#include "PokemonSV_AutoStoryTools.h" +#include "PokemonSV_AutoStory_Segment_37.h" + +//#include +//using std::cout; +//using std::endl; +//#include +//#include + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonSV{ + + + + +std::string AutoStory_Segment_37::name() const{ + return ""; +} + +std::string AutoStory_Segment_37::start_text() const{ + return "Start: "; +} + +std::string AutoStory_Segment_37::end_text() const{ + return "End: "; +} + +void AutoStory_Segment_37::run_segment( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + AutoStoryOptions options, + AutoStoryStats& stats +) const{ + + + stats.m_segment++; + env.update_stats(); + context.wait_for_all_requests(); + env.console.log("Start Segment " + name(), COLOR_ORANGE); + + // AutoStory_Checkpoint_9().run_checkpoint(env, context, options, stats); + + context.wait_for_all_requests(); + env.console.log("End Segment " + name(), COLOR_GREEN); + +} + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_37.h b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_37.h new file mode 100644 index 0000000000..a029548119 --- /dev/null +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_37.h @@ -0,0 +1,35 @@ +/* Autostory + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonSV_AutoStory_Segment_37_H +#define PokemonAutomation_PokemonSV_AutoStory_Segment_37_H + +#include "PokemonSV_AutoStoryTools.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonSV{ + +class AutoStory_Segment_37 : public AutoStory_Segment{ +public: + virtual std::string name() const override; + virtual std::string start_text() const override; + virtual std::string end_text() const override; + virtual void run_segment( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + AutoStoryOptions options, + AutoStoryStats& stats + ) const override; +}; + + + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_38.cpp b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_38.cpp new file mode 100644 index 0000000000..33158c60fb --- /dev/null +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_38.cpp @@ -0,0 +1,66 @@ +/* AutoStory + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/Exceptions/OperationFailedException.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "PokemonSV/Programs/PokemonSV_GameEntry.h" +#include "PokemonSV/Programs/PokemonSV_SaveGame.h" +#include "PokemonSV/Programs/PokemonSV_MenuNavigation.h" +#include "PokemonSV/Programs/PokemonSV_WorldNavigation.h" +#include "PokemonSV_AutoStoryTools.h" +#include "PokemonSV_AutoStory_Segment_38.h" + +//#include +//using std::cout; +//using std::endl; +//#include +//#include + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonSV{ + + + + +std::string AutoStory_Segment_38::name() const{ + return ""; +} + +std::string AutoStory_Segment_38::start_text() const{ + return "Start: "; +} + +std::string AutoStory_Segment_38::end_text() const{ + return "End: "; +} + +void AutoStory_Segment_38::run_segment( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + AutoStoryOptions options, + AutoStoryStats& stats +) const{ + + + stats.m_segment++; + env.update_stats(); + context.wait_for_all_requests(); + env.console.log("Start Segment " + name(), COLOR_ORANGE); + + // AutoStory_Checkpoint_9().run_checkpoint(env, context, options, stats); + + context.wait_for_all_requests(); + env.console.log("End Segment " + name(), COLOR_GREEN); + +} + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_38.h b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_38.h new file mode 100644 index 0000000000..c8e62174c0 --- /dev/null +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_38.h @@ -0,0 +1,35 @@ +/* Autostory + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonSV_AutoStory_Segment_38_H +#define PokemonAutomation_PokemonSV_AutoStory_Segment_38_H + +#include "PokemonSV_AutoStoryTools.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonSV{ + +class AutoStory_Segment_38 : public AutoStory_Segment{ +public: + virtual std::string name() const override; + virtual std::string start_text() const override; + virtual std::string end_text() const override; + virtual void run_segment( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + AutoStoryOptions options, + AutoStoryStats& stats + ) const override; +}; + + + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_39.cpp b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_39.cpp new file mode 100644 index 0000000000..bc9e910a70 --- /dev/null +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_39.cpp @@ -0,0 +1,66 @@ +/* AutoStory + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/Exceptions/OperationFailedException.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "PokemonSV/Programs/PokemonSV_GameEntry.h" +#include "PokemonSV/Programs/PokemonSV_SaveGame.h" +#include "PokemonSV/Programs/PokemonSV_MenuNavigation.h" +#include "PokemonSV/Programs/PokemonSV_WorldNavigation.h" +#include "PokemonSV_AutoStoryTools.h" +#include "PokemonSV_AutoStory_Segment_39.h" + +//#include +//using std::cout; +//using std::endl; +//#include +//#include + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonSV{ + + + + +std::string AutoStory_Segment_39::name() const{ + return ""; +} + +std::string AutoStory_Segment_39::start_text() const{ + return "Start: "; +} + +std::string AutoStory_Segment_39::end_text() const{ + return "End: "; +} + +void AutoStory_Segment_39::run_segment( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + AutoStoryOptions options, + AutoStoryStats& stats +) const{ + + + stats.m_segment++; + env.update_stats(); + context.wait_for_all_requests(); + env.console.log("Start Segment " + name(), COLOR_ORANGE); + + // AutoStory_Checkpoint_9().run_checkpoint(env, context, options, stats); + + context.wait_for_all_requests(); + env.console.log("End Segment " + name(), COLOR_GREEN); + +} + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_39.h b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_39.h new file mode 100644 index 0000000000..58760b7387 --- /dev/null +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_39.h @@ -0,0 +1,35 @@ +/* Autostory + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonSV_AutoStory_Segment_39_H +#define PokemonAutomation_PokemonSV_AutoStory_Segment_39_H + +#include "PokemonSV_AutoStoryTools.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonSV{ + +class AutoStory_Segment_39 : public AutoStory_Segment{ +public: + virtual std::string name() const override; + virtual std::string start_text() const override; + virtual std::string end_text() const override; + virtual void run_segment( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + AutoStoryOptions options, + AutoStoryStats& stats + ) const override; +}; + + + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_40.cpp b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_40.cpp new file mode 100644 index 0000000000..dc0c19231e --- /dev/null +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_40.cpp @@ -0,0 +1,66 @@ +/* AutoStory + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/Exceptions/OperationFailedException.h" +#include "CommonTools/Async/InferenceRoutines.h" +#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" +#include "PokemonSV/Programs/PokemonSV_GameEntry.h" +#include "PokemonSV/Programs/PokemonSV_SaveGame.h" +#include "PokemonSV/Programs/PokemonSV_MenuNavigation.h" +#include "PokemonSV/Programs/PokemonSV_WorldNavigation.h" +#include "PokemonSV_AutoStoryTools.h" +#include "PokemonSV_AutoStory_Segment_40.h" + +//#include +//using std::cout; +//using std::endl; +//#include +//#include + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonSV{ + + + + +std::string AutoStory_Segment_40::name() const{ + return ""; +} + +std::string AutoStory_Segment_40::start_text() const{ + return "Start: "; +} + +std::string AutoStory_Segment_40::end_text() const{ + return "End: "; +} + +void AutoStory_Segment_40::run_segment( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + AutoStoryOptions options, + AutoStoryStats& stats +) const{ + + + stats.m_segment++; + env.update_stats(); + context.wait_for_all_requests(); + env.console.log("Start Segment " + name(), COLOR_ORANGE); + + // AutoStory_Checkpoint_9().run_checkpoint(env, context, options, stats); + + context.wait_for_all_requests(); + env.console.log("End Segment " + name(), COLOR_GREEN); + +} + + + +} +} +} diff --git a/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_40.h b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_40.h new file mode 100644 index 0000000000..a34117ff7a --- /dev/null +++ b/SerialPrograms/Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_40.h @@ -0,0 +1,35 @@ +/* Autostory + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_PokemonSV_AutoStory_Segment_40_H +#define PokemonAutomation_PokemonSV_AutoStory_Segment_40_H + +#include "PokemonSV_AutoStoryTools.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ +namespace PokemonSV{ + +class AutoStory_Segment_40 : public AutoStory_Segment{ +public: + virtual std::string name() const override; + virtual std::string start_text() const override; + virtual std::string end_text() const override; + virtual void run_segment( + SingleSwitchProgramEnvironment& env, + ProControllerContext& context, + AutoStoryOptions options, + AutoStoryStats& stats + ) const override; +}; + + + + +} +} +} +#endif diff --git a/SerialPrograms/Source/PokemonSV/Programs/PokemonSV_WorldNavigation.cpp b/SerialPrograms/Source/PokemonSV/Programs/PokemonSV_WorldNavigation.cpp index bcd6d887fc..257a08d26c 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/PokemonSV_WorldNavigation.cpp +++ b/SerialPrograms/Source/PokemonSV/Programs/PokemonSV_WorldNavigation.cpp @@ -665,7 +665,7 @@ void walk_forward_until_dialog( int ret = run_until( stream, context, [&](ProControllerContext& context){ - ssf_press_left_joystick(context, 128, y, 0, seconds_timeout * TICKS_PER_SECOND); + ssf_press_left_joystick(context, x, y, 0, seconds_timeout * TICKS_PER_SECOND); if (movement_mode == NavigationMovementMode::DIRECTIONAL_ONLY){ pbf_wait(context, seconds_timeout * TICKS_PER_SECOND); } else if (movement_mode == NavigationMovementMode::DIRECTIONAL_SPAM_A){ @@ -861,13 +861,14 @@ void run_battle_press_A( AdvanceDialogWatcher dialog(COLOR_RED); DialogArrowWatcher dialog_arrow(COLOR_RED, stream.overlay(), {0.850, 0.820, 0.020, 0.050}, 0.8365, 0.846); GradientArrowWatcher next_pokemon(COLOR_BLUE, GradientArrowType::RIGHT, {0.50, 0.51, 0.30, 0.10}); + GradientArrowWatcher bag(COLOR_BLUE, GradientArrowType::RIGHT, {0.10, 0.10, 0.05, 0.90}); MoveSelectWatcher move_select_menu(COLOR_YELLOW); GradientArrowWatcher select_move_target(COLOR_BLUE, GradientArrowType::DOWN, {0.38, 0.08, 0.25, 0.1}); std::vector callbacks; std::vector enum_all_callbacks; // mandatory callbacks: Battle, Overworld, Advance Dialog, Swap menu, Move select - // optional callbacks: DIALOG_ARROW, NEXT_POKEMON, SELECT_MOVE_TARGET, + // optional callbacks: DIALOG_ARROW, NEXT_POKEMON, SELECT_MOVE_TARGET, BATTLE_BAG // merge the mandatory and optional callbacks as a set, to avoid duplicates. then convert to vector std::unordered_set enum_all_callbacks_set{CallbackEnum::BATTLE, CallbackEnum::OVERWORLD, CallbackEnum::ADVANCE_DIALOG, CallbackEnum::SWAP_MENU, CallbackEnum::MOVE_SELECT}; // mandatory callbacks @@ -900,6 +901,9 @@ void run_battle_press_A( case CallbackEnum::SELECT_MOVE_TARGET: callbacks.emplace_back(select_move_target); break; + case CallbackEnum::BATTLE_BAG: + callbacks.emplace_back(bag); + break; default: throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "run_battle_press_A: Unknown callback requested."); } @@ -986,6 +990,11 @@ void run_battle_press_A( stream.log("run_battle_press_A: Detected arrows to select move target. Press A."); pbf_mash_button(context, BUTTON_A, 100); break; + case CallbackEnum::BATTLE_BAG: + stream.log("run_battle_press_A: Detected Bag. Press B. Hold Dpad Up so cursor is back on 'Battle'."); + pbf_mash_button(context, BUTTON_B, 100); + pbf_press_dpad(context, DPAD_UP, 2000ms, 100ms); + break; default: throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "run_battle_press_A: Unknown callback triggered."); @@ -1022,6 +1031,7 @@ void run_wild_battle_press_A( std::unordered_set enum_optional_callbacks, bool detect_wipeout ){ + enum_optional_callbacks.insert(CallbackEnum::BATTLE_BAG); // check for Bag. run_battle_press_A(stream, context, stop_condition, enum_optional_callbacks, detect_wipeout); } diff --git a/SerialPrograms/Source/PokemonSV/Programs/PokemonSV_WorldNavigation.h b/SerialPrograms/Source/PokemonSV/Programs/PokemonSV_WorldNavigation.h index a7de9d897a..9f2a913999 100644 --- a/SerialPrograms/Source/PokemonSV/Programs/PokemonSV_WorldNavigation.h +++ b/SerialPrograms/Source/PokemonSV/Programs/PokemonSV_WorldNavigation.h @@ -58,6 +58,7 @@ enum class CallbackEnum{ SWAP_MENU, MOVE_SELECT, SELECT_MOVE_TARGET, + BATTLE_BAG, }; enum class ZoomChange{ diff --git a/SerialPrograms/SourceFiles.cmake b/SerialPrograms/SourceFiles.cmake index dbe36de3ea..14f5e83414 100644 --- a/SerialPrograms/SourceFiles.cmake +++ b/SerialPrograms/SourceFiles.cmake @@ -1897,6 +1897,16 @@ file(GLOB LIBRARY_SOURCES Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_34.h Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_35.cpp Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_35.h + Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_36.cpp + Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_36.h + Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_37.cpp + Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_37.h + Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_38.cpp + Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_38.h + Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_39.cpp + Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_39.h + Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_40.cpp + Source/PokemonSV/Programs/AutoStory/PokemonSV_AutoStory_Segment_40.h Source/PokemonSV/Programs/AutoStory/PokemonSV_MenuOption.cpp Source/PokemonSV/Programs/AutoStory/PokemonSV_MenuOption.h Source/PokemonSV/Programs/AutoStory/PokemonSV_MenuOptionDatabase.cpp