Skip to content

Commit 6c2244a

Browse files
authored
frlg detectors for selected party slot (#1151)
* frlg detectors for selected party slot * Update PokemonFRLG_PartyMenuDetector.h
1 parent ba21d1a commit 6c2244a

4 files changed

Lines changed: 140 additions & 6 deletions

File tree

SerialPrograms/Source/PokemonFRLG/Inference/Menus/PokemonFRLG_PartyMenuDetector.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*
55
*/
66

7+
#include "Common/Cpp/Exceptions.h"
78
#include "CommonFramework/ImageTools/ImageBoxes.h"
89
#include "CommonFramework/ImageTypes/ImageRGB32.h"
910
#include "CommonFramework/ImageTools/ImageStats.h"
@@ -72,6 +73,57 @@ bool PartySelectionDetector::detect(const ImageViewRGB32& screen){
7273
return false;
7374
}
7475

76+
ImageFloatBox PartySlotDetector::party_slot_boxes(PartySlot position){
77+
switch (position){
78+
case PartySlot::ONE:
79+
return ImageFloatBox(0.130000, 0.163000, 0.200000, 0.009000);
80+
case PartySlot::TWO:
81+
return ImageFloatBox(0.710000, 0.063000, 0.260000, 0.009000);
82+
case PartySlot::THREE:
83+
return ImageFloatBox(0.710000, 0.213000, 0.260000, 0.009000);
84+
case PartySlot::FOUR:
85+
return ImageFloatBox(0.710000, 0.363000, 0.260000, 0.009000);
86+
case PartySlot::FIVE:
87+
return ImageFloatBox(0.710000, 0.513000, 0.260000, 0.009000);
88+
case PartySlot::SIX:
89+
return ImageFloatBox(0.710000, 0.663000, 0.260000, 0.009000);
90+
default:
91+
break;
92+
}
93+
throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Invalid FRLG Party Slot Position");
94+
}
95+
PartySlotDetector::PartySlotDetector(
96+
Color color,
97+
const ImageFloatBox& box
98+
)
99+
: m_color(color)
100+
, m_party_box(box)
101+
{}
102+
PartySlotDetector::PartySlotDetector(
103+
Color color,
104+
PartySlot position
105+
)
106+
: m_color(color)
107+
, m_party_box(party_slot_boxes(position))
108+
{}
109+
void PartySlotDetector::make_overlays(VideoOverlaySet& items) const{
110+
const BoxOption& GAME_BOX = GameSettings::instance().GAME_BOX;
111+
items.add(m_color, GAME_BOX.inner_to_outer(m_party_box));
112+
}
113+
bool PartySlotDetector::detect(const ImageViewRGB32& screen){
114+
ImageViewRGB32 game_screen = extract_box_reference(screen, GameSettings::instance().GAME_BOX);
115+
116+
ImageViewRGB32 target_box_party = extract_box_reference(game_screen, m_party_box);
117+
118+
//orange FF701C border. light/dark blues in the selected box are close to each other.
119+
if (is_solid(target_box_party, { 0.6455696, 0.2835, 0.070886 }, 0.25, 20)
120+
){
121+
return true;
122+
}
123+
return false;
124+
}
125+
126+
75127

76128
}
77129
}

SerialPrograms/Source/PokemonFRLG/Inference/Menus/PokemonFRLG_PartyMenuDetector.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ namespace PokemonAutomation{
2121
namespace NintendoSwitch{
2222
namespace PokemonFRLG{
2323

24+
enum class PartySlot{
25+
ONE,
26+
TWO,
27+
THREE,
28+
FOUR,
29+
FIVE,
30+
SIX
31+
//CXL
32+
};
2433

2534
// The Party menu has a white box on the bottom
2635
// The background around the edges is dark teal/navy
@@ -63,6 +72,40 @@ class PartySelectionWatcher : public DetectorToFinder<PartySelectionDetector>{
6372
};
6473

6574

75+
class PartySlotDetector : public StaticScreenDetector{
76+
public:
77+
PartySlotDetector(
78+
Color color,
79+
const ImageFloatBox& box
80+
);
81+
82+
PartySlotDetector(
83+
Color color,
84+
PartySlot position
85+
);
86+
87+
static ImageFloatBox party_slot_boxes(PartySlot position);
88+
89+
virtual void make_overlays(VideoOverlaySet& items) const override;
90+
virtual bool detect(const ImageViewRGB32& screen) override;
91+
92+
private:
93+
const Color m_color;
94+
const ImageFloatBox m_party_box;
95+
};
96+
class PartySlotWatcher : public DetectorToFinder<PartySlotDetector>{
97+
public:
98+
PartySlotWatcher(
99+
Color color,
100+
PartySlot position,
101+
std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250)
102+
)
103+
: DetectorToFinder("PartySlotWatcher", hold_duration, color, party_slot_boxes(position))
104+
{
105+
}
106+
};
107+
108+
66109

67110
}
68111
}

SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ bool try_open_slot_six(ConsoleHandle& console, ProControllerContext& context){
147147
}
148148

149149
console.log("Navigating to party menu.");
150-
BlackScreenOverWatcher blk1(COLOR_RED);
150+
PartyMenuWatcher blk1(COLOR_RED);
151151

152152
int pm = run_until<ProControllerContext>(
153153
console, context,
@@ -166,8 +166,25 @@ bool try_open_slot_six(ConsoleHandle& console, ProControllerContext& context){
166166
context.wait_for_all_requests();
167167

168168
//Press up twice to get to the last slot
169-
pbf_press_dpad(context, DPAD_UP, 320ms, 320ms);
170-
pbf_press_dpad(context, DPAD_UP, 320ms, 320ms);
169+
PartySlotWatcher last_slot(COLOR_RED, PartySlot::SIX);
170+
int ps = run_until<ProControllerContext>(
171+
console, context,
172+
[](ProControllerContext& context){
173+
for (int i = 0; i < 15; i++) { //Enough to cycle through 6pty+cxl twice
174+
pbf_wait(context, 320ms);
175+
context.wait_for_all_requests();
176+
pbf_press_dpad(context, DPAD_UP, 320ms, 320ms);
177+
}
178+
},
179+
{ last_slot }
180+
);
181+
context.wait_for_all_requests();
182+
if (ps == 0){
183+
console.log("Moved selection to slot six.");
184+
} else{
185+
console.log("open_slot_six(): Unable to move selection to slot six.", COLOR_RED);
186+
return false;
187+
}
171188

172189
//Two presses to open summary
173190
BlackScreenOverWatcher blk2(COLOR_RED);

SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h"
1414
#include "Pokemon/Pokemon_Strings.h"
1515
#include "PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.h"
16+
#include "PokemonFRLG/Inference/Menus/PokemonFRLG_PartyMenuDetector.h"
1617
#include "PokemonFRLG/Inference/Menus/PokemonFRLG_StartMenuDetector.h"
1718
#include "PokemonFRLG/Inference/Menus/PokemonFRLG_SummaryDetector.h"
1819
#include "PokemonFRLG/Inference/PokemonFRLG_ShinySymbolDetector.h"
@@ -293,7 +294,7 @@ bool GiftReset::try_open_summary(SingleSwitchProgramEnvironment& env, ProControl
293294
}
294295

295296
//Open party menu
296-
BlackScreenOverWatcher blk1(COLOR_RED);
297+
PartyMenuWatcher blk1(COLOR_RED);
297298

298299
int pm = run_until<ProControllerContext>(
299300
env.console, context,
@@ -318,8 +319,29 @@ bool GiftReset::try_open_summary(SingleSwitchProgramEnvironment& env, ProControl
318319

319320
//Press up twice to get to the last slot
320321
if (TARGET != Target::starters){
321-
pbf_press_dpad(context, DPAD_UP, 320ms, 320ms);
322-
pbf_press_dpad(context, DPAD_UP, 320ms, 320ms);
322+
PartySlotWatcher last_slot(COLOR_RED, PartySlot::SIX);
323+
int ps = run_until<ProControllerContext>(
324+
env.console, context,
325+
[](ProControllerContext& context){
326+
for (int i = 0; i < 15; i++) { //Enough to cycle through 6pty+cxl twice
327+
pbf_wait(context, 320ms);
328+
context.wait_for_all_requests();
329+
pbf_press_dpad(context, DPAD_UP, 320ms, 320ms);
330+
}
331+
},
332+
{ last_slot }
333+
);
334+
context.wait_for_all_requests();
335+
if (ps == 0){
336+
env.log("Moved selection to slot six.");
337+
} else{
338+
env.log("open_summary(): Unable to move selection to slot six.", COLOR_RED);
339+
send_program_recoverable_error_notification(
340+
env, NOTIFICATION_ERROR_RECOVERABLE,
341+
"open_summary(): Unable to move selection to slot six."
342+
);
343+
return false;
344+
}
323345
}
324346

325347
//Two presses to open summary

0 commit comments

Comments
 (0)