Skip to content

Commit f851adb

Browse files
committed
Add a way to buy more than one kind of item in StallBuyer
1 parent a1547a9 commit f851adb

File tree

2 files changed

+135
-105
lines changed

2 files changed

+135
-105
lines changed

SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_StallBuyer.cpp

Lines changed: 115 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,47 @@
1717
#include "PokemonLZA/Inference/PokemonLZA_SelectionArrowDetector.h"
1818
#include "PokemonLZA/Inference/PokemonLZA_DialogDetector.h"
1919
#include "PokemonLZA_StallBuyer.h"
20+
#include <array>
2021

2122
namespace PokemonAutomation{
2223
namespace NintendoSwitch{
2324
namespace PokemonLZA{
2425

2526
using namespace Pokemon;
2627

28+
StallBuyerRow::StallBuyerRow(int index, std::string&& ordinal)
29+
: StaticTableRow(ordinal)
30+
, item(LockMode::LOCK_WHILE_RUNNING, "The number of the " + ordinal + " item you want to purchase.")
31+
, quantity(LockMode::LOCK_WHILE_RUNNING, 0, 0, 999)
32+
, ordinal(std::move(ordinal))
33+
, index(index)
34+
{
35+
PA_ADD_STATIC(item);
36+
PA_ADD_OPTION(quantity);
37+
}
38+
39+
StallBuyerTable::StallBuyerTable()
40+
: StaticTableOption("<b>Number to Purchase:</b><br>The number of items you want to purchase.", LockMode::LOCK_WHILE_RUNNING)
41+
{
42+
add_row(std::make_unique<StallBuyerRow>(0, "first"));
43+
add_row(std::make_unique<StallBuyerRow>(1, "second"));
44+
add_row(std::make_unique<StallBuyerRow>(2, "third"));
45+
add_row(std::make_unique<StallBuyerRow>(3, "fourth"));
46+
add_row(std::make_unique<StallBuyerRow>(4, "fifth"));
47+
add_row(std::make_unique<StallBuyerRow>(5, "sixth"));
48+
add_row(std::make_unique<StallBuyerRow>(6, "seventh"));
49+
50+
finish_construction();
51+
}
52+
std::vector<std::string> StallBuyerTable::make_header() const{
53+
std::vector<std::string> ret{
54+
"Item",
55+
"Quantity"
56+
};
57+
return ret;
58+
}
59+
60+
2761
StallBuyer_Descriptor::StallBuyer_Descriptor()
2862
: SingleSwitchProgramDescriptor(
2963
"PokemonLZA:StallBuyer",
@@ -55,34 +89,14 @@ std::unique_ptr<StatsTracker> StallBuyer_Descriptor::make_stats() const{
5589

5690

5791
StallBuyer::StallBuyer()
58-
: ITEM_POSITION(
59-
"<b>Item Position to Purchase:</b>",
60-
{
61-
{ItemPosition::FirstItem, "FirstItem", "First Item" },
62-
{ItemPosition::SecondItem, "SecondItem", "Second Item" },
63-
{ItemPosition::ThirdItem, "ThirdItem", "Third Item" },
64-
{ItemPosition::FourthItem, "FourthItem", "Fourth Item" },
65-
{ItemPosition::FifthItem, "FifthItem", "Fifth Item" },
66-
{ItemPosition::SixthItem, "SixthItem", "Sixth Item" },
67-
{ItemPosition::SeventhItem, "SeventhItem", "Seventh Item" },
68-
},
69-
LockMode::LOCK_WHILE_RUNNING,
70-
ItemPosition::FirstItem
71-
)
72-
, NUM_PURCHASE(
73-
"<b>Number to Purchase:</b><br>The number of items you want to purchase.",
74-
LockMode::LOCK_WHILE_RUNNING,
75-
100, 1, 999
76-
)
77-
, GO_HOME_WHEN_DONE(false)
92+
: GO_HOME_WHEN_DONE(false)
7893
, NOTIFICATION_STATUS_UPDATE("Status Update", true, false, std::chrono::seconds(3600))
7994
, NOTIFICATIONS({
8095
&NOTIFICATION_STATUS_UPDATE,
8196
&NOTIFICATION_PROGRAM_FINISH,
8297
&NOTIFICATION_ERROR_FATAL,
8398
})
8499
{
85-
PA_ADD_OPTION(ITEM_POSITION);
86100
PA_ADD_OPTION(NUM_PURCHASE);
87101
PA_ADD_OPTION(GO_HOME_WHEN_DONE);
88102
PA_ADD_OPTION(NOTIFICATIONS);
@@ -146,88 +160,95 @@ void StallBuyer::program(SingleSwitchProgramEnvironment& env, ProControllerConte
146160
StallBuyer_Descriptor::Stats& stats = env.current_stats<StallBuyer_Descriptor::Stats>();
147161
assert_16_9_720p_min(env.logger(), env.console);
148162

149-
while (true) {
150-
context.wait_for_all_requests();
163+
for (StaticTableRow* row : NUM_PURCHASE.table()){
164+
StallBuyerRow& stall_buyer_row = static_cast<StallBuyerRow&>(*row);
151165

152-
ButtonWatcher buttonA(
153-
COLOR_RED,
154-
ButtonType::ButtonA,
155-
{0.1, 0.1, 0.8, 0.8},
156-
&env.console.overlay()
157-
);
158-
SelectionArrowWatcher select(
159-
COLOR_YELLOW, &env.console.overlay(),
160-
SelectionArrowType::RIGHT,
161-
{0.715, 0.165, 0.045, 0.440}
162-
);
163-
SelectionArrowWatcher confirm(
164-
COLOR_YELLOW, &env.console.overlay(),
165-
SelectionArrowType::RIGHT,
166-
{0.665, 0.600, 0.145, 0.080}
167-
);
168-
FlatWhiteDialogWatcher dialog(COLOR_RED, &env.console.overlay());
166+
for (int purchases = 0; purchases < stall_buyer_row.quantity; /* do not increment, it will be done in the loop*/){
167+
context.wait_for_all_requests();
169168

170-
int ret = wait_until(
171-
env.console, context,
172-
30000ms,
173-
{
174-
buttonA,
175-
select,
176-
confirm,
177-
dialog,
178-
}
169+
ButtonWatcher buttonA(
170+
COLOR_RED,
171+
ButtonType::ButtonA,
172+
{0.1, 0.1, 0.8, 0.8},
173+
&env.console.overlay()
179174
);
180-
context.wait_for(100ms);
181-
182-
switch (ret){
183-
case 0:
184-
env.log("Detected A button.");
185-
pbf_press_button(context, BUTTON_A, 160ms, 80ms);
186-
continue;
187-
188-
case 1:
189-
{
190-
env.log("Detected item selection screen.");
191-
int stall_amount_item = detect_stall_amount_item(env, stats);
192-
env.log("Detected stall with " + std::to_string(stall_amount_item) + " items to sell.");
193-
auto [direction, presses] = compute_needed_inputs(static_cast<int>(ITEM_POSITION.get()), stall_amount_item);
194-
for (int i = 0; i < presses; i++){
195-
pbf_press_dpad(context, direction, 160ms, 80ms);
196-
}
197-
pbf_press_button(context, BUTTON_A, 160ms, 80ms);
198-
continue;
199-
}
200-
case 2:
201-
env.log("Detected purchase confirm screen.");
202-
pbf_press_button(context, BUTTON_A, 160ms, 80ms);
203-
stats.purchases++;
204-
env.update_stats();
205-
206-
if (stats.purchases == NUM_PURCHASE) {
207-
// pbf_mash_button(context, BUTTON_B, 5000ms);
208-
// intentionally don't leave the purchase menu to not get attacked
209-
GO_HOME_WHEN_DONE.run_end_of_program(context);
210-
send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH);
211-
return;
175+
SelectionArrowWatcher select(
176+
COLOR_YELLOW, &env.console.overlay(),
177+
SelectionArrowType::RIGHT,
178+
{0.715, 0.165, 0.045, 0.440}
179+
);
180+
SelectionArrowWatcher confirm(
181+
COLOR_YELLOW, &env.console.overlay(),
182+
SelectionArrowType::RIGHT,
183+
{0.665, 0.600, 0.145, 0.080}
184+
);
185+
FlatWhiteDialogWatcher dialog(COLOR_RED, &env.console.overlay());
186+
187+
int ret = wait_until(
188+
env.console, context,
189+
30000ms,
190+
{
191+
buttonA,
192+
select,
193+
confirm,
194+
dialog,
195+
}
196+
);
197+
context.wait_for(100ms);
198+
199+
switch (ret){
200+
case 0:
201+
env.log("Detected A button.");
202+
pbf_press_button(context, BUTTON_A, 160ms, 80ms);
203+
continue;
204+
205+
case 1:
206+
{
207+
env.log("Detected item selection screen.");
208+
int stall_amount_item = detect_stall_amount_item(env, stats);
209+
env.log("Detected stall with " + std::to_string(stall_amount_item) + " items to sell.");
210+
auto [direction, presses] = compute_needed_inputs(stall_buyer_row.index, stall_amount_item);
211+
for (int i = 0; i < presses; i++){
212+
pbf_press_dpad(context, direction, 160ms, 80ms);
213+
}
214+
pbf_press_button(context, BUTTON_A, 160ms, 80ms);
215+
continue;
212216
}
217+
case 2:
218+
env.log("Detected purchase confirm screen.");
219+
pbf_press_button(context, BUTTON_A, 160ms, 80ms);
220+
stats.purchases++;
221+
purchases++;
222+
env.update_stats();
213223

214-
continue;
224+
if (purchases == stall_buyer_row.quantity){
225+
std::stringstream ss;
226+
ss << "Purchased " << stall_buyer_row.quantity << " of " << stall_buyer_row.ordinal << " item.";
227+
send_program_status_notification(env, NOTIFICATION_STATUS_UPDATE, ss.str());
228+
break;
229+
}
215230

216-
case 3:
217-
env.log("Detected white dialog.");
218-
pbf_press_button(context, BUTTON_A, 160ms, 80ms);
219-
continue;
231+
continue;
220232

221-
default:
222-
stats.errors++;
223-
env.update_stats();
224-
OperationFailedException::fire(
225-
ErrorReport::SEND_ERROR_REPORT,
226-
"No recognized state after 30 seconds.",
227-
env.console
228-
);
233+
case 3:
234+
env.log("Detected white dialog.");
235+
pbf_press_button(context, BUTTON_A, 160ms, 80ms);
236+
continue;
237+
238+
default:
239+
stats.errors++;
240+
env.update_stats();
241+
OperationFailedException::fire(
242+
ErrorReport::SEND_ERROR_REPORT,
243+
"No recognized state after 30 seconds.",
244+
env.console
245+
);
246+
}
229247
}
230248
}
249+
// intentionally don't leave the purchase menu to not get attacked
250+
GO_HOME_WHEN_DONE.run_end_of_program(context);
251+
send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH);
231252
}
232253

233254

SerialPrograms/Source/PokemonLZA/Programs/PokemonLZA_StallBuyer.h

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "Common/Cpp/Options/SimpleIntegerOption.h"
1111
#include "CommonFramework/Notifications/EventNotificationsTable.h"
12+
#include "CommonFramework/Options/LabelCellOption.h"
1213
#include "NintendoSwitch/NintendoSwitch_SingleSwitchProgram.h"
1314
#include "NintendoSwitch/Options/NintendoSwitch_GoHomeWhenDoneOption.h"
1415

@@ -18,6 +19,24 @@ namespace PokemonLZA{
1819

1920

2021

22+
class StallBuyerRow : public StaticTableRow{
23+
public:
24+
StallBuyerRow(int index, std::string&& ordinal);
25+
26+
LabelCellOption item;
27+
SimpleIntegerCell<uint16_t> quantity;
28+
std::string ordinal;
29+
int index;
30+
};
31+
32+
class StallBuyerTable : public StaticTableOption {
33+
public:
34+
StallBuyerTable();
35+
virtual std::vector<std::string> make_header() const;
36+
};
37+
38+
39+
2140
class StallBuyer_Descriptor : public SingleSwitchProgramDescriptor{
2241
public:
2342
StallBuyer_Descriptor();
@@ -35,17 +54,7 @@ class StallBuyer : public SingleSwitchProgramInstance{
3554
virtual void program(SingleSwitchProgramEnvironment& env, ProControllerContext& context) override;
3655

3756
private:
38-
enum class ItemPosition{
39-
FirstItem,
40-
SecondItem,
41-
ThirdItem,
42-
FourthItem,
43-
FifthItem,
44-
SixthItem,
45-
SeventhItem
46-
};
47-
EnumDropdownOption<ItemPosition> ITEM_POSITION;
48-
SimpleIntegerOption<uint16_t> NUM_PURCHASE;
57+
StallBuyerTable NUM_PURCHASE;
4958
GoHomeWhenDoneOption GO_HOME_WHEN_DONE;
5059
EventNotificationOption NOTIFICATION_STATUS_UPDATE;
5160
EventNotificationsOption NOTIFICATIONS;

0 commit comments

Comments
 (0)