Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* Prize Select Detector
*
* From: https://github.com/PokemonAutomation/
*
*/

#include "CommonTools/Images/SolidColorTest.h"
#include "CommonTools/Images/ImageFilter.h"
#include "CommonFramework/ImageTools/ImageBoxes.h"
#include "CommonFramework/ImageTypes/ImageRGB32.h"
#include "CommonFramework/ImageTools/ImageStats.h"
#include "CommonFramework/ImageTypes/ImageViewRGB32.h"
#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h"
#include "CommonTools/Images/SolidColorTest.h"
#include "CommonTools/Images/WaterfillUtilities.h"
#include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h"
#include "CommonFramework/VideoPipeline/VideoOverlay.h"
#include "PokemonFRLG_PrizeSelectDetector.h"

namespace PokemonAutomation{
namespace NintendoSwitch{
namespace PokemonFRLG{

PrizeSelectDetector::PrizeSelectDetector(Color color)
: m_right_box(0.812, 0.726, 0.013, 0.169)
, m_top_box(0.175, 0.715, 0.649, 0.005)
, m_bottom_box(0.177, 0.896, 0.645, 0.008)
, m_selection_box(0.667, 0.514, 0.173, 0.058)
{}
void PrizeSelectDetector::make_overlays(VideoOverlaySet& items) const{
items.add(COLOR_RED, m_right_box);
items.add(COLOR_RED, m_top_box);
items.add(COLOR_RED, m_bottom_box);
items.add(COLOR_RED, m_selection_box);
}
bool PrizeSelectDetector::detect(const ImageViewRGB32& screen){
ImageViewRGB32 right_image = extract_box_reference(screen, m_right_box);
ImageViewRGB32 top_image = extract_box_reference(screen, m_top_box);
ImageViewRGB32 bottom_image = extract_box_reference(screen, m_bottom_box);
ImageViewRGB32 selection_image = extract_box_reference(screen, m_selection_box);
if (is_solid(right_image, { 0.25, 0.38, 0.369 })
&& is_solid(top_image, { 0.25, 0.38, 0.369 })
&& is_solid(bottom_image, { 0.25, 0.38, 0.369 })
&& is_solid(selection_image, { 0.25, 0.38, 0.369 })
){
return true;
}
return false;
}


}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* Prize Select Detector
*
* From: https://github.com/PokemonAutomation/
*
*/

#ifndef PokemonAutomation_PokemonFRLG_PrizeSelectDetector_H
#define PokemonAutomation_PokemonFRLG_PrizeSelectDetector_H

#include <chrono>
#include <atomic>
#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h"
#include "Common/Cpp/Color.h"
#include "CommonFramework/ImageTools/ImageBoxes.h"
#include "CommonTools/VisualDetector.h"
#include "CommonTools/InferenceCallbacks/VisualInferenceCallback.h"

namespace PokemonAutomation{
class CancellableScope;
class VideoFeed;
namespace NintendoSwitch{
namespace PokemonFRLG{

// Same as WhiteDialogDetector, but also looks for the white on the final line of the prize select box
// All 3 prize booths have 5 items, however the width of the box varies so we have to go by height
// (also I'm not sure if width varies by language)
// can't use the coin count in the top left, as that appears as soon as you talk to the booth
// a future improvement might be to look for the selection arrow, but keep in mind width varies
class PrizeSelectDetector : public StaticScreenDetector{
public:
PrizeSelectDetector(Color color);

virtual void make_overlays(VideoOverlaySet& items) const override;
virtual bool detect(const ImageViewRGB32& screen) override;

private:
ImageFloatBox m_right_box;
ImageFloatBox m_top_box;
ImageFloatBox m_bottom_box;
ImageFloatBox m_selection_box;
};
class PrizeSelectWatcher : public DetectorToFinder<PrizeSelectDetector>{
public:
PrizeSelectWatcher(Color color)
: DetectorToFinder("PrizeSelectWatcher", std::chrono::milliseconds(250), color)
{}
};




}
}
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ float ShinySoundDetector::get_score_threshold() const{
std::unique_ptr<SpectrogramMatcher> ShinySoundDetector::build_spectrogram_matcher(size_t sample_rate){
return std::make_unique<SpectrogramMatcher>(
"Shiny Sound",
AudioTemplateCache::instance().get_throw("PokemonRSE/ShinySound", sample_rate),
AudioTemplateCache::instance().get_throw("PokemonFRLG/ShinySound", sample_rate),
SpectrogramMatcher::Mode::SPIKE_CONV, sample_rate,
GameSettings::instance().SHINY_SOUND_LOW_FREQUENCY
);
Expand Down
82 changes: 82 additions & 0 deletions SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@
#include "CommonTools/VisualDetectors/BlackScreenDetector.h"
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h"
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h"
#include "NintendoSwitch/Controllers/Procon/NintendoSwitch_ProController.h"
#include "NintendoSwitch/NintendoSwitch_ConsoleHandle.h"
#include "PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.h"
#include "PokemonFRLG/Inference/Sounds/PokemonFRLG_ShinySoundDetector.h"
#include "PokemonFRLG/Inference/Menus/PokemonFRLG_StartMenuDetector.h"
#include "PokemonFRLG/PokemonFRLG_Settings.h"
#include "PokemonFRLG_Navigation.h"

Expand Down Expand Up @@ -54,6 +57,85 @@ void soft_reset(const ProgramInfo& info, VideoStream& stream, ProControllerConte
context.wait_for_all_requests();
}

void open_slot_six(ConsoleHandle& console, ProControllerContext& context){
//Attempt to exit any dialog and open the start menu
StartMenuWatcher start_menu(COLOR_RED);

int ret = run_until<ProControllerContext>(
console, context,
[](ProControllerContext& context) {
for (int i = 0; i < 10; i++) {
pbf_press_button(context, BUTTON_B, 320ms, 640ms);
pbf_wait(context, 100ms);
context.wait_for_all_requests();
pbf_press_button(context, BUTTON_PLUS, 320ms, 640ms);
}
},
{ start_menu }
);
context.wait_for_all_requests();
if (ret < 0){
OperationFailedException::fire(
ErrorReport::SEND_ERROR_REPORT,
"open_slot_six(): Unable to open Start menu.",
console
);
}

console.log("Navigating to party menu.");
pbf_wait(context, 200ms);
context.wait_for_all_requests();
pbf_press_dpad(context, DPAD_DOWN, 320ms, 320ms);
context.wait_for_all_requests();

pbf_press_button(context, BUTTON_A, 320ms, 640ms);

BlackScreenOverWatcher blk1(COLOR_RED, {0.282, 0.064, 0.448, 0.871});
int ret1 = wait_until(
console, context,
5s,
{blk1}
);
if (ret1 == 0){
console.log("Entered party menu.");
}else{
console.log("Unable to enter Party menu.", COLOR_RED);
OperationFailedException::fire(
ErrorReport::SEND_ERROR_REPORT,
"open_slot_six(): Unable to enter Party menu.",
console
);
}
context.wait_for_all_requests();

//Press up twice to get to the last slot
pbf_press_dpad(context, DPAD_UP, 320ms, 320ms);
pbf_press_dpad(context, DPAD_UP, 320ms, 320ms);

//Two presses to open summary
pbf_press_button(context, BUTTON_A, 320ms, 640ms);
pbf_press_button(context, BUTTON_A, 320ms, 640ms);

BlackScreenOverWatcher blk2(COLOR_RED, {0.282, 0.064, 0.448, 0.871});
int ret2 = wait_until(
console, context,
5s,
{blk2}
);
if (ret2 == 0){
console.log("Entered summary.");
}else{
console.log("Unable to enter summary.", COLOR_RED);
OperationFailedException::fire(
ErrorReport::SEND_ERROR_REPORT,
"open_slot_six(): Unable to enter summary.",
console
);
}
pbf_wait(context, 1000ms);
context.wait_for_all_requests();
}

/*
bool handle_encounter(VideoStream& stream, ProControllerContext& context, bool send_out_lead) {
float shiny_coefficient = 1.0;
Expand Down
7 changes: 6 additions & 1 deletion SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,19 @@
#include "NintendoSwitch/Controllers/Procon/NintendoSwitch_ProController.h"

namespace PokemonAutomation{
struct ProgramInfo;
namespace NintendoSwitch{
class ConsoleHandle;
class ProController;
using ProControllerContext = ControllerContext<ProController>;
namespace PokemonFRLG{

// Press A+B+Select+Start at the same time to soft reset, then re-enters the game.
// For now this assumes no dry battery.
void soft_reset(const ProgramInfo& info, VideoStream& stream, ProControllerContext &context);

// From the overworld, open the summary of the Pokemon in slot 6. This assumes the menu cursor is in the top slot (POKEDEX)
void open_slot_six(ConsoleHandle& console, ProControllerContext& context);

// After press A/walking up to enter a battle, run this handle the battle start and to check if opponent is shiny.
// Set send_out_lead to true and then use flee_battle() after if game is Emerald.
// For R/S, send_out_lead as false and then soft_reset() to save time.
Expand Down
2 changes: 2 additions & 0 deletions SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Panels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "PokemonFRLG_Settings.h"

#include "Programs/ShinyHunting/PokemonFRLG_GiftReset.h"
#include "Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.h"
#include "Programs/TestPrograms/PokemonFRLG_SoundListener.h"

namespace PokemonAutomation{
Expand All @@ -33,6 +34,7 @@ std::vector<PanelEntry> PanelListFactory::make_panels() const{

ret.emplace_back("---- Shiny Hunting ----");
ret.emplace_back(make_single_switch_program<GiftReset_Descriptor, GiftReset>());
ret.emplace_back(make_single_switch_program<PrizeCornerReset_Descriptor, PrizeCornerReset>());


if (PreloadSettings::instance().DEVELOPER_MODE){
Expand Down
4 changes: 2 additions & 2 deletions SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ GameSettings::GameSettings()
, SHINY_SOUND_THRESHOLD(
"<b>Shiny Sound Threshold:</b><br>Maximum error coefficient to trigger a shiny detection.",
LockMode::LOCK_WHILE_RUNNING,
0.97, 0, 1.0
0.80, 0, 1.0 //0.87
)
, SHINY_SOUND_LOW_FREQUENCY(
"<b>Shiny Sound Low Frequency (Hz):</b><br>High pass filter frequency for shiny sound.",
LockMode::LOCK_WHILE_RUNNING,
5000, 0, 48000
1000, 0, 48000 //2000
)
{
PA_ADD_STATIC(m_soft_reset_timings);
Expand Down
Loading