Skip to content

Commit 54d133b

Browse files
authored
Added nugget bridge farmer (PokemonAutomation#1123)
* Added nugget bridge farmer * typo * Fix tabs * tabs attempt 2 * Remove unused variable * BlackScreenOverWatcher, HomeBlackBorderCheck, Cleanup. * use pbf
1 parent 24e719f commit 54d133b

4 files changed

Lines changed: 329 additions & 0 deletions

File tree

SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Panels.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "PokemonFRLG_Settings.h"
1212

13+
#include "Programs/Farming/PokemonFRLG_NuggetBridgeFarmer.h"
1314
#include "Programs/ShinyHunting/PokemonFRLG_GiftReset.h"
1415
#include "Programs/ShinyHunting/PokemonFRLG_LegendaryReset.h"
1516
#include "Programs/ShinyHunting/PokemonFRLG_LegendaryRunAway.h"
@@ -33,6 +34,11 @@ std::vector<PanelEntry> PanelListFactory::make_panels() const{
3334
ret.emplace_back("---- Settings ----");
3435
ret.emplace_back(make_settings<GameSettings_Descriptor, GameSettingsPanel>());
3536

37+
ret.emplace_back("---- Farming ----");
38+
if (PreloadSettings::instance().DEVELOPER_MODE) {
39+
ret.emplace_back(make_single_switch_program<NuggetBridgeFarmer_Descriptor, NuggetBridgeFarmer>());
40+
}
41+
3642
//ret.emplace_back("---- General ----");
3743

3844
ret.emplace_back("---- Shiny Hunting ----");
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
/* Nugget Bridge Farmer
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#include "CommonFramework/Notifications/ProgramNotifications.h"
8+
#include "CommonFramework/ProgramStats/StatsTracking.h"
9+
#include "CommonTools/Async/InferenceRoutines.h"
10+
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h"
11+
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h"
12+
#include "Pokemon/Pokemon_Strings.h"
13+
#include "PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.h"
14+
#include "PokemonFRLG/Inference/Menus/PokemonFRLG_StartMenuDetector.h"
15+
#include "PokemonFRLG/PokemonFRLG_Navigation.h"
16+
#include "PokemonFRLG_NuggetBridgeFarmer.h"
17+
18+
namespace PokemonAutomation{
19+
namespace NintendoSwitch{
20+
namespace PokemonFRLG{
21+
22+
NuggetBridgeFarmer_Descriptor::NuggetBridgeFarmer_Descriptor()
23+
: SingleSwitchProgramDescriptor(
24+
"PokemonFRLG:NuggetBridgeFarmer",
25+
Pokemon::STRING_POKEMON + " FRLG", "Nugget Bridge Farmer",
26+
"Programs/PokemonFRLG/NuggetBridgeFarmer.html",
27+
"Farm the Nugget Bridge for money.",
28+
ProgramControllerClass::StandardController_RequiresPrecision,
29+
FeedbackType::REQUIRED,
30+
AllowCommandsWhenRunning::DISABLE_COMMANDS
31+
)
32+
{}
33+
34+
struct NuggetBridgeFarmer_Descriptor::Stats : public StatsTracker {
35+
public:
36+
Stats()
37+
: nuggets(m_stats["Nuggets"])
38+
, errors(m_stats["Errors"])
39+
{
40+
m_display_order.emplace_back("Nuggets");
41+
m_display_order.emplace_back("Errors", HIDDEN_IF_ZERO);
42+
}
43+
44+
std::atomic<uint64_t>& nuggets;
45+
std::atomic<uint64_t>& errors;
46+
};
47+
48+
std::unique_ptr<StatsTracker> NuggetBridgeFarmer_Descriptor::make_stats() const{
49+
return std::unique_ptr<StatsTracker>(new Stats());
50+
}
51+
52+
NuggetBridgeFarmer::NuggetBridgeFarmer()
53+
: STOP_AFTER_CURRENT("Nugget")
54+
, NUM_NUGGETS(
55+
"<b>Number of Nuggets:</b><br>"
56+
"Zero will run until 'Stop after Current Nugget' is pressed or the program is manually stopped.",
57+
LockMode::UNLOCK_WHILE_RUNNING,
58+
120, // About 2 hours of farming.
59+
0
60+
)
61+
, GO_HOME_WHEN_DONE(false)
62+
/*, PERIODIC_SAVE(
63+
"<b>Periodically Save:</b><br>"
64+
"Save the game every this many nuggets. This reduces the loss to game crashes. Set to zero to disable.",
65+
LockMode::UNLOCK_WHILE_RUNNING,
66+
10,
67+
0
68+
)*/
69+
, NOTIFICATION_STATUS_UPDATE("Status Update", true, false, std::chrono::seconds(3600))
70+
, NOTIFICATIONS({
71+
&NOTIFICATION_STATUS_UPDATE,
72+
&NOTIFICATION_PROGRAM_FINISH,
73+
&NOTIFICATION_ERROR_FATAL,
74+
})
75+
{
76+
PA_ADD_OPTION(STOP_AFTER_CURRENT);
77+
78+
PA_ADD_OPTION(NUM_NUGGETS);
79+
PA_ADD_OPTION(GO_HOME_WHEN_DONE);
80+
//PA_ADD_OPTION(PERIODIC_SAVE);
81+
82+
PA_ADD_OPTION(NOTIFICATIONS);
83+
}
84+
85+
void NuggetBridgeFarmer::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) {
86+
87+
home_black_border_check(env.console, context);
88+
89+
NuggetBridgeFarmer_Descriptor::Stats& stats = env.current_stats<NuggetBridgeFarmer_Descriptor::Stats>();
90+
DeferredStopButtonOption::ResetOnExit reset_on_exit(STOP_AFTER_CURRENT);
91+
92+
//for (uint32_t nuggets_since_last_save = 0;; nuggets_since_last_save++) {
93+
while (true) {
94+
send_program_status_notification(env, NOTIFICATION_STATUS_UPDATE);
95+
if (NUM_NUGGETS != 0 && stats.nuggets >= NUM_NUGGETS) {
96+
break;
97+
}
98+
99+
env.console.log("Exiting Pokemon Center...");
100+
while (true){
101+
BlackScreenWatcher pokemon_ceter_exit(COLOR_RED);
102+
103+
int ret = run_until<ProControllerContext>(
104+
env.console, context,
105+
[](ProControllerContext& context) {
106+
pbf_press_dpad(context, DPAD_DOWN, 2000ms, 0ms);
107+
},
108+
{ pokemon_ceter_exit }
109+
);
110+
111+
if (ret == 0) {
112+
break;
113+
}
114+
}
115+
116+
env.console.log("Detecting overworld...");
117+
while (true) {
118+
BlackScreenOverWatcher overworld_entered(COLOR_RED);
119+
120+
int ret = wait_until(
121+
env.console, context,
122+
std::chrono::milliseconds(2000),
123+
{overworld_entered}
124+
);
125+
126+
if (ret == 0) {
127+
break;
128+
}
129+
}
130+
131+
// There is a small delay from seeing the overworld to being able to a actually move.
132+
pbf_wait(context, 1000ms);
133+
context.wait_for_all_requests();
134+
135+
env.console.log("Navigating to Team Rocket member...");
136+
137+
ssf_press_button(context, BUTTON_B, 0ms, 12000ms);
138+
pbf_press_dpad(context, DPAD_LEFT, 590ms, 0ms);
139+
pbf_press_dpad(context, DPAD_UP, 510ms, 0ms);
140+
pbf_press_dpad(context, DPAD_LEFT, 1550ms, 0ms);
141+
pbf_press_dpad(context, DPAD_UP, 1175ms, 0ms);
142+
pbf_press_dpad(context, DPAD_RIGHT, 1950ms, 0ms);
143+
pbf_press_dpad(context, DPAD_UP, 5300ms, 0ms);
144+
145+
context.wait_for_all_requests();
146+
147+
env.console.log("Starting battle...");
148+
while (true){
149+
BattleMenuWatcher battle_menu(COLOR_RED);
150+
151+
int ret = run_until<ProControllerContext>(
152+
env.console, context,
153+
[](ProControllerContext& context) {
154+
pbf_mash_button(context, BUTTON_B, 2000ms);
155+
},
156+
{ battle_menu }
157+
);
158+
159+
if (ret == 0) {
160+
break;
161+
}
162+
}
163+
164+
env.console.log("Loosing battle...");
165+
while (true){
166+
BlackScreenWatcher battle_lost(COLOR_RED);
167+
168+
int ret = run_until<ProControllerContext>(
169+
env.console, context,
170+
[](ProControllerContext& context) {
171+
pbf_mash_button(context, BUTTON_A, 2000ms);
172+
},
173+
{ battle_lost }
174+
);
175+
176+
if (ret == 0) {
177+
break;
178+
}
179+
}
180+
181+
env.console.log("Talking to nurse joy...");
182+
while (true){
183+
WhiteDialogWatcher nurse_joy_dialog(COLOR_RED);
184+
int ret = run_until<ProControllerContext>(
185+
env.console, context,
186+
[](ProControllerContext& context) {
187+
pbf_mash_button(context, BUTTON_B, 2000ms);
188+
},
189+
{ nurse_joy_dialog }
190+
);
191+
192+
if (ret == 0) {
193+
break;
194+
}
195+
}
196+
197+
// Spam B till nurse joy stops talking
198+
while (true){
199+
WhiteDialogWatcher nurse_joy_dialog(COLOR_RED);
200+
int ret = run_until<ProControllerContext>(
201+
env.console, context,
202+
[](ProControllerContext& context) {
203+
pbf_mash_button(context, BUTTON_B, 2000ms);
204+
},
205+
{ nurse_joy_dialog }
206+
);
207+
208+
if (ret != 0) {
209+
break;
210+
}
211+
}
212+
213+
//TODO: Implement periodic saving. The Save Menu keeps the last cursor position. Need to implement arrow dectection on the correct option
214+
/*if (PERIODIC_SAVE != 0 && nuggets_since_last_save >= PERIODIC_SAVE) {
215+
StartMenuWatcher start_menu = StartMenuWatcher(COLOR_RED);
216+
217+
env.console.log("Saving game...");
218+
219+
while (true)
220+
{
221+
int ret = run_until<ProControllerContext>(
222+
env.console, context,
223+
[](ProControllerContext& context) {
224+
pbf_press_button(context, BUTTON_PLUS, 320ms, 640ms);
225+
pbf_wait(context, 100ms);
226+
context.wait_for_all_requests();
227+
},
228+
{ start_menu }
229+
);
230+
231+
if (ret == 0) {
232+
break;
233+
}
234+
}
235+
236+
pbf_press_dpad(context, DPAD_DOWN, 320ms, 320ms);
237+
pbf_press_dpad(context, DPAD_DOWN, 320ms, 320ms);
238+
pbf_press_dpad(context, DPAD_DOWN, 320ms, 320ms);
239+
pbf_press_dpad(context, DPAD_DOWN, 320ms, 320ms);
240+
241+
pbf_press_button(context, BUTTON_A, 320ms, 320ms);
242+
pbf_press_button(context, BUTTON_A, 320ms, 320ms);
243+
244+
pbf_mash_button(context, BUTTON_B, 2000ms);
245+
nuggets_since_last_save = 0;
246+
}*/
247+
248+
stats.nuggets++;
249+
env.update_stats();
250+
251+
if (STOP_AFTER_CURRENT.should_stop()) {
252+
break;
253+
}
254+
}
255+
256+
send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH);
257+
GO_HOME_WHEN_DONE.run_end_of_program(context);
258+
}
259+
260+
261+
}
262+
}
263+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* Nugget Bridge Farmer
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_PokemonFRLG_NuggetBridgeFarmer_H
8+
#define PokemonAutomation_PokemonFRLG_NuggetBridgeFarmer_H
9+
10+
#include "Common/Cpp/Options/SimpleIntegerOption.h"
11+
#include "Common/Cpp/Options/ButtonOption.h"
12+
#include "CommonFramework/Notifications/EventNotificationsTable.h"
13+
#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h"
14+
#include "NintendoSwitch/Options/NintendoSwitch_GoHomeWhenDoneOption.h"
15+
16+
17+
namespace PokemonAutomation{
18+
namespace NintendoSwitch{
19+
namespace PokemonFRLG{
20+
21+
class NuggetBridgeFarmer_Descriptor : public SingleSwitchProgramDescriptor{
22+
public:
23+
NuggetBridgeFarmer_Descriptor();
24+
struct Stats;
25+
virtual std::unique_ptr<StatsTracker> make_stats() const override;
26+
};
27+
28+
class NuggetBridgeFarmer : public SingleSwitchProgramInstance {
29+
public:
30+
NuggetBridgeFarmer();
31+
virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override;
32+
virtual void start_program_border_check(
33+
VideoStream& stream,
34+
FeedbackType feedback_type
35+
) override {
36+
}
37+
38+
private:
39+
40+
DeferredStopButtonOption STOP_AFTER_CURRENT;
41+
SimpleIntegerOption<uint32_t> NUM_NUGGETS;
42+
GoHomeWhenDoneOption GO_HOME_WHEN_DONE;
43+
44+
//SimpleIntegerOption<uint32_t> PERIODIC_SAVE;
45+
46+
EventNotificationOption NOTIFICATION_STATUS_UPDATE;
47+
EventNotificationsOption NOTIFICATIONS;
48+
49+
};
50+
51+
}
52+
}
53+
}
54+
55+
56+
57+
58+
#endif

SerialPrograms/cmake/SourceFiles.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,8 @@ file(GLOB LIBRARY_SOURCES
14221422
Source/PokemonFRLG/PokemonFRLG_Panels.h
14231423
Source/PokemonFRLG/PokemonFRLG_Settings.cpp
14241424
Source/PokemonFRLG/PokemonFRLG_Settings.h
1425+
Source/PokemonFRLG/Programs/Farming/PokemonFRLG_NuggetBridgeFarmer.cpp
1426+
Source/PokemonFRLG/Programs/Farming/PokemonFRLG_NuggetBridgeFarmer.h
14251427
Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp
14261428
Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.h
14271429
Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp

0 commit comments

Comments
 (0)