Skip to content

Commit e02d804

Browse files
kichithewolfGin890
authored andcommitted
hyperspace reward reset
1 parent 7c05405 commit e02d804

File tree

3 files changed

+289
-0
lines changed

3 files changed

+289
-0
lines changed

SerialPrograms/Source/PokemonLZA/PokemonLZA_Panels.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "Programs/Farming/PokemonLZA_JacintheInfiniteFarmer.h"
2525
#include "Programs/Farming/PokemonLZA_FriendshipFarmer.h"
2626
#include "Programs/Farming/PokemonLZA_InPlaceCatcher.h"
27+
#include "Programs/Farming/PokemonLZA_HyperspaceRewardReset.h"
2728

2829
// Shiny Hunting
2930
#include "Programs/ShinyHunting/PokemonLZA_AutoFossil.h"
@@ -77,6 +78,7 @@ std::vector<PanelEntry> PanelListFactory::make_panels() const{
7778
ret.emplace_back(make_single_switch_program<JacintheInfiniteFarmer_Descriptor, JacintheInfiniteFarmer>());
7879
ret.emplace_back(make_single_switch_program<FriendshipFarmer_Descriptor, FriendshipFarmer>());
7980
ret.emplace_back(make_single_switch_program<InPlaceCatcher_Descriptor, InPlaceCatcher>());
81+
ret.emplace_back(make_single_switch_program<HyperspaceRewardReset_Descriptor, HyperspaceRewardReset>());
8082
if (IS_BETA_VERSION){
8183
}
8284

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
/* Hyperspace Reward Reset
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#include "CommonFramework/Logging/Logger.h"
8+
#include "CommonFramework/Exceptions/OperationFailedException.h"
9+
#include "CommonFramework/Notifications/ProgramNotifications.h"
10+
#include "CommonFramework/ProgramStats/StatsTracking.h"
11+
#include "CommonFramework/VideoPipeline/VideoFeed.h"
12+
#include "CommonTools/Images/ImageFilter.h"
13+
#include "CommonTools/Async/InferenceRoutines.h"
14+
#include "CommonTools/VisualDetectors/BlackScreenDetector.h"
15+
#include "CommonTools/StartupChecks/VideoResolutionCheck.h"
16+
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h"
17+
#include "NintendoSwitch/Programs/NintendoSwitch_GameEntry.h"
18+
#include "Pokemon/Pokemon_Strings.h"
19+
#include "PokemonLZA/Programs/PokemonLZA_GameEntry.h"
20+
#include "PokemonLZA/Inference/PokemonLZA_ButtonDetector.h"
21+
#include "PokemonLZA/Inference/PokemonLZA_DialogDetector.h"
22+
#include "PokemonLZA/Inference/PokemonLZA_HyperspaceRewardNameReader.h"
23+
#include "PokemonLZA/Resources/PokemonLZA_HyperspaceRewardNames.h"
24+
#include "PokemonLZA_HyperspaceRewardReset.h"
25+
26+
namespace PokemonAutomation{
27+
namespace NintendoSwitch{
28+
namespace PokemonLZA{
29+
30+
using namespace Pokemon;
31+
32+
HyperspaceRewardReset_Descriptor::HyperspaceRewardReset_Descriptor()
33+
: SingleSwitchProgramDescriptor(
34+
"PokemonLZA:HyperspaceRewardReset",
35+
STRING_POKEMON + " LZA", "Hyperspace Reward Reset",
36+
"Programs/PokemonLZA/HyperspaceRewardReset.html",
37+
"Reset in front of a Hyperspace Battle Zone trainer to receive a specific reward.",
38+
ProgramControllerClass::StandardController_NoRestrictions,
39+
FeedbackType::REQUIRED,
40+
AllowCommandsWhenRunning::DISABLE_COMMANDS
41+
)
42+
{}
43+
44+
struct HyperspaceRewardReset_Descriptor::Stats : public StatsTracker{
45+
Stats()
46+
: matches(m_stats["Items matched"])
47+
, resets(m_stats["Resets"])
48+
, errors(m_stats["Errors"])
49+
{
50+
m_display_order.emplace_back("Items matched");
51+
m_display_order.emplace_back("Resets");
52+
m_display_order.emplace_back("Errors", HIDDEN_IF_ZERO);
53+
}
54+
std::atomic<uint64_t>& matches;
55+
std::atomic<uint64_t>& resets;
56+
std::atomic<uint64_t>& errors;
57+
};
58+
std::unique_ptr<StatsTracker> HyperspaceRewardReset_Descriptor::make_stats() const{
59+
return std::unique_ptr<StatsTracker>(new Stats());
60+
}
61+
62+
HyperspaceRewardReset::HyperspaceRewardReset()
63+
: LANGUAGE(
64+
"<b>Game Language:</b><br>The language is needed to read the rewards.",
65+
HyperspaceRewardNameReader::instance().languages(),
66+
LockMode::LOCK_WHILE_RUNNING,
67+
true
68+
)
69+
, TARGET_ITEMS("<b>Items:</b>")
70+
, GO_HOME_WHEN_DONE(true)
71+
, NOTIFICATION_REWARD_MATCH("Matching Reward", true, false, ImageAttachmentMode::JPG, { "Notifs" })
72+
, NOTIFICATION_STATUS_UPDATE("Status Update", true, false, std::chrono::seconds(3600))
73+
, NOTIFICATIONS({
74+
&NOTIFICATION_REWARD_MATCH,
75+
&NOTIFICATION_STATUS_UPDATE,
76+
&NOTIFICATION_PROGRAM_FINISH,
77+
&NOTIFICATION_ERROR_FATAL,
78+
})
79+
{
80+
PA_ADD_OPTION(LANGUAGE);
81+
PA_ADD_OPTION(TARGET_ITEMS);
82+
PA_ADD_OPTION(GO_HOME_WHEN_DONE);
83+
PA_ADD_OPTION(NOTIFICATIONS);
84+
}
85+
86+
void HyperspaceRewardReset::talk_to_trainer(SingleSwitchProgramEnvironment& env, ProControllerContext& context){
87+
HyperspaceRewardReset_Descriptor::Stats& stats = env.current_stats<HyperspaceRewardReset_Descriptor::Stats>();
88+
context.wait_for_all_requests();
89+
90+
env.log("Looking for A button.");
91+
ButtonWatcher buttonA_watcher(
92+
COLOR_WHITE,
93+
ButtonType::ButtonA,
94+
{0.1, 0.1, 0.8, 0.8},
95+
&env.console.overlay()
96+
);
97+
int ret = wait_until(
98+
env.console, context,
99+
10s,
100+
{
101+
buttonA_watcher,
102+
}
103+
);
104+
if (ret == 0) {
105+
env.log("Detected A button.");
106+
pbf_press_button(context, BUTTON_A, 80ms, 40ms);
107+
}
108+
else {
109+
stats.errors++;
110+
env.update_stats();
111+
OperationFailedException::fire(
112+
ErrorReport::SEND_ERROR_REPORT,
113+
"talk_to_trainer(): Failed to detect A button.",
114+
env.console
115+
);
116+
}
117+
context.wait_for_all_requests();
118+
119+
BlueDialogWatcher blue_dialog_watcher(COLOR_BLUE, &env.console.overlay());
120+
env.log("Pressing A until item received dialog.");
121+
//First dialog box varies by trainer (hologram, regular, etc.)
122+
int ret_blue = run_until<ProControllerContext>(
123+
env.console, context,
124+
[](ProControllerContext& context){
125+
for (int i = 0; i < 20; i++) {
126+
pbf_press_button(context, BUTTON_A, 80ms, 100ms);
127+
pbf_wait(context, 1000ms);
128+
context.wait_for_all_requests();
129+
}
130+
},
131+
{ blue_dialog_watcher }
132+
);
133+
if (ret_blue != 0){
134+
stats.errors++;
135+
env.update_stats();
136+
OperationFailedException::fire(
137+
ErrorReport::SEND_ERROR_REPORT,
138+
"talk_to_trainer(): Failed to detect blue item received dialog after 20 A presses.",
139+
env.console
140+
);
141+
}
142+
context.wait_for_all_requests();
143+
}
144+
145+
//Check reward and notify if it matches filters
146+
bool HyperspaceRewardReset::check_reward(SingleSwitchProgramEnvironment& env, ProControllerContext& context){
147+
HyperspaceRewardReset_Descriptor::Stats& stats = env.current_stats<HyperspaceRewardReset_Descriptor::Stats>();
148+
149+
VideoSnapshot screen = env.console.video().snapshot();
150+
ImageFloatBox dialog_box(0.248, 0.792, 0.483, 0.147);
151+
ImageViewRGB32 dialog_image = extract_box_reference(screen, dialog_box);
152+
153+
/*
154+
bool replace_color_within_range = false;
155+
ImageRGB32 dialog_filtered = filter_rgb32_range(
156+
extract_box_reference(screen, dialog_box),
157+
combine_rgb(50, 135, 162), combine_rgb(167, 244, 255), Color(0), replace_color_within_range
158+
);
159+
dialog_filtered.save("./dialog_image.png");
160+
*/
161+
162+
const double LOG10P_THRESHOLD = -1.5;
163+
OCR::StringMatchResult result = PokemonLZA::HyperspaceRewardNameReader::instance().read_substring(
164+
env.console, LANGUAGE, dialog_image,
165+
OCR::BLUE_TEXT_FILTERS()
166+
);
167+
result.clear_beyond_log10p(LOG10P_THRESHOLD);
168+
if (result.results.empty()){
169+
env.log("No matching reward name found in dialog box.");
170+
send_program_status_notification(env, NOTIFICATION_STATUS_UPDATE);
171+
}
172+
for (const auto& r : result.results){
173+
env.console.log("Found reward: " + r.second.token);
174+
if (TARGET_ITEMS.find_item(r.second.token)){
175+
env.log("Reward matched");
176+
177+
stats.matches++;
178+
env.update_stats();
179+
180+
send_program_notification(
181+
env, NOTIFICATION_REWARD_MATCH,
182+
COLOR_GREEN, "Reward matched",
183+
{
184+
{ "Item:", get_hyperspace_reward_name(r.second.token).display_name() },
185+
}
186+
, "", screen);
187+
return true;
188+
break;
189+
}
190+
}
191+
return false;
192+
}
193+
194+
void HyperspaceRewardReset::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context){
195+
assert_16_9_720p_min(env.logger(), env.console);
196+
HyperspaceRewardReset_Descriptor::Stats& stats = env.current_stats<HyperspaceRewardReset_Descriptor::Stats>();
197+
198+
/*
199+
* In a Hyperspace Battle Zone:
200+
* Win a battle with a trainer that gives a prize.
201+
* Save the game and reset. Do not talk to the trainer.
202+
* (Reset is required because trainer position will move.)
203+
* Re-enter the game and then save again, this time in front of the trainer.
204+
* Start the program.
205+
*
206+
* Make sure you won't be spotted by another trainer.
207+
*/
208+
209+
bool item_found = false;
210+
while (!item_found){
211+
send_program_status_notification(env, NOTIFICATION_STATUS_UPDATE);
212+
213+
talk_to_trainer(env, context);
214+
item_found = check_reward(env, context);
215+
216+
if (item_found) {
217+
break;
218+
}
219+
220+
go_home(env.console, context);
221+
reset_game_from_home(env, env.console, context);
222+
stats.resets++;
223+
env.update_stats();
224+
}
225+
226+
send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH);
227+
GO_HOME_WHEN_DONE.run_end_of_program(context);
228+
}
229+
230+
}
231+
}
232+
}
233+
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* Hyperspace Reward Reset
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_PokemonLZA_HyperspaceRewardReset_H
8+
#define PokemonAutomation_PokemonLZA_HyperspaceRewardReset_H
9+
10+
#include "Common/Cpp/Options/BooleanCheckBoxOption.h"
11+
#include "Common/Cpp/Options/SimpleIntegerOption.h"
12+
#include "Common/Cpp/Options/ButtonOption.h"
13+
#include "CommonFramework/Notifications/EventNotificationsTable.h"
14+
#include "CommonTools/Options/LanguageOCROption.h"
15+
#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h"
16+
#include "NintendoSwitch/Options/NintendoSwitch_GoHomeWhenDoneOption.h"
17+
#include "PokemonLZA/Options/PokemonLZA_HyperspacerewardTable.h"
18+
19+
namespace PokemonAutomation{
20+
namespace NintendoSwitch{
21+
namespace PokemonLZA{
22+
23+
class HyperspaceRewardReset_Descriptor : public SingleSwitchProgramDescriptor{
24+
public:
25+
HyperspaceRewardReset_Descriptor();
26+
struct Stats;
27+
virtual std::unique_ptr<StatsTracker> make_stats() const override;
28+
};
29+
30+
class HyperspaceRewardReset : public SingleSwitchProgramInstance{
31+
public:
32+
HyperspaceRewardReset();
33+
virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override;
34+
35+
private:
36+
OCR::LanguageOCROption LANGUAGE;
37+
HyperspaceRewardTable TARGET_ITEMS;
38+
GoHomeWhenDoneOption GO_HOME_WHEN_DONE;
39+
40+
EventNotificationOption NOTIFICATION_REWARD_MATCH;
41+
EventNotificationOption NOTIFICATION_STATUS_UPDATE;
42+
EventNotificationsOption NOTIFICATIONS;
43+
44+
void talk_to_trainer(SingleSwitchProgramEnvironment& env, ProControllerContext& context);
45+
bool check_reward(SingleSwitchProgramEnvironment& env, ProControllerContext& context);
46+
};
47+
48+
}
49+
}
50+
}
51+
#endif
52+
53+
54+

0 commit comments

Comments
 (0)