Skip to content

Commit 9b2d1dc

Browse files
author
Gin
committed
refactor shiny sound routine
1 parent b116c61 commit 9b2d1dc

File tree

3 files changed

+108
-78
lines changed

3 files changed

+108
-78
lines changed

SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_ShinyDetectedAction.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ ShinySoundDetectedActionOption::ShinySoundDetectedActionOption(
4141
true
4242
)
4343
, SCREENSHOT_DELAY(
44-
"<b>Screenshot Delay:</b><br>"
45-
"Wait this long before taking a screenshot + video of the shiny.<br>"
44+
"<b>Video Delay:</b><br>"
45+
"Wait this long before taking a video of the shiny.<br>"
4646
"Don't set this too large or the shiny may run away!",
4747
LockMode::UNLOCK_WHILE_RUNNING,
4848
std::move(default_delay)
@@ -84,19 +84,27 @@ bool ShinySoundDetectedActionOption::on_shiny_sound(
8484
return false;
8585
}
8686

87+
if (TAKE_VIDEO){
88+
context.wait_for(SCREENSHOT_DELAY);
89+
pbf_press_button(context, BUTTON_CAPTURE, 2 * TICKS_PER_SECOND, 0);
90+
}
91+
92+
send_shiny_sound_notification(env, stream, error_coefficient);
93+
94+
return action == ShinySoundDetectedAction::STOP_PROGRAM;
95+
}
96+
97+
98+
void ShinySoundDetectedActionOption::send_shiny_sound_notification(
99+
ProgramEnvironment& env, VideoStream& stream, float error_coefficient
100+
){
87101
{
88102
std::ostringstream ss;
89103
ss << "Detected Shiny Sound! (error coefficient = " << error_coefficient << ")";
90104
stream.log(ss.str(), COLOR_BLUE);
91105
}
92106

93-
if (TAKE_VIDEO){
94-
context.wait_for(SCREENSHOT_DELAY);
95-
pbf_press_button(context, BUTTON_CAPTURE, 2 * TICKS_PER_SECOND, 0);
96-
}
97-
98107
std::vector<std::pair<std::string, std::string>> embeds;
99-
100108
{
101109
std::ostringstream ss;
102110
ss << "Error Coefficient: ";
@@ -112,8 +120,6 @@ bool ShinySoundDetectedActionOption::on_shiny_sound(
112120
embeds, "",
113121
stream.video().snapshot(), true
114122
);
115-
116-
return action == ShinySoundDetectedAction::STOP_PROGRAM;
117123
}
118124

119125

@@ -134,7 +140,6 @@ bool ShinySoundDetectedActionOption::on_shiny_sound(
134140

135141

136142

137-
138143

139144

140145
}

SerialPrograms/Source/PokemonLZA/Options/PokemonLZA_ShinyDetectedAction.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ namespace PokemonLZA{
2323

2424

2525
enum class ShinySoundDetectedAction{
26-
STOP_PROGRAM,
27-
NOTIFY_ON_FIRST_ONLY,
28-
NOTIFY_ON_ALL,
26+
STOP_PROGRAM, // stop program at first detected shiny sound
27+
NOTIFY_ON_FIRST_ONLY, // notify user only on the first shiny sound, keep running the program
28+
NOTIFY_ON_ALL, // notify on all shiny sounds, keep running the program
2929
};
3030

3131

@@ -37,12 +37,22 @@ class ShinySoundDetectedActionOption : public GroupOption, public ConfigOption::
3737
ShinySoundDetectedAction default_action
3838
);
3939

40+
// Handle shiny sound according to ACTION.
41+
// May log the sound, take a video and send notification.
42+
// Return whether to stop the program according to ACTION.
4043
bool on_shiny_sound(
4144
ProgramEnvironment& env, VideoStream& stream, ProControllerContext& context,
4245
size_t current_count,
4346
float error_coefficient
4447
);
4548

49+
// Assuming a shiny sound is detected, this function logs and sends a notification.
50+
// This function is called by `on_shiny_sound()`.
51+
void send_shiny_sound_notification(
52+
ProgramEnvironment& env, VideoStream& stream,
53+
float error_coefficient
54+
);
55+
4656
StaticTextOption DESCRIPTION;
4757
EnumDropdownOption<ShinySoundDetectedAction> ACTION;
4858
BooleanCheckBoxOption TAKE_VIDEO;

SerialPrograms/Source/PokemonLZA/Programs/ShinyHunting/PokemonLZA_ShinyHunt_BenchSit.cpp

Lines changed: 79 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -141,81 +141,96 @@ void reapproach_bench_after_getting_up(SingleSwitchProgramEnvironment& env, ProC
141141
void ShinyHunt_BenchSit::program(SingleSwitchProgramEnvironment& env, ProControllerContext& context){
142142
ShinyHunt_BenchSit_Descriptor::Stats& stats = env.current_stats<ShinyHunt_BenchSit_Descriptor::Stats>();
143143

144-
while (true){
145-
float shiny_coefficient = 1.0;
146-
PokemonLA::ShinySoundDetector shiny_detector(env.console, [&](float error_coefficient) -> bool{
147-
// Warning: This callback will be run from a different thread than this function.
148-
stats.shinies++;
149-
env.update_stats();
150-
shiny_coefficient = error_coefficient;
151-
if (SHINY_DETECTED.ACTION != ShinySoundDetectedAction::NOTIFY_ON_FIRST_ONLY){
152-
return true;
144+
std::atomic<uint8_t> to_take_shiny_sound_video{0};
145+
// Store shiny detection time as milliseconds since epoch for thread-safe access
146+
std::atomic<int64_t> shiny_detection_time_ms{0};
147+
148+
// once shiny sound detector finds a shiny and user decides to take a video of it,
149+
// we need to take the video on Switch as part of the program loop.
150+
auto handle_shiny_sound_video_request = [&]() -> void {
151+
if (to_take_shiny_sound_video.load(std::memory_order_relaxed) && SHINY_DETECTED.TAKE_VIDEO){
152+
// Calculate elapsed time since shiny detection
153+
int64_t detection_time_ms = shiny_detection_time_ms.load(std::memory_order_relaxed);
154+
WallDuration elapsed = current_time() - WallClock(Milliseconds(detection_time_ms));
155+
auto elapsed_ms = std::chrono::duration_cast<Milliseconds>(elapsed);
156+
157+
// Calculate remaining time to wait
158+
Milliseconds requested_delay = SHINY_DETECTED.SCREENSHOT_DELAY.get();
159+
if (requested_delay > elapsed_ms){
160+
context.wait_for(requested_delay - elapsed_ms);
153161
}
162+
// Otherwise, take screenshot immediately (no additional wait needed)
154163

155-
return stats.shinies == 1;
156-
});
157-
158-
int ret = run_until<ProControllerContext>(
159-
env.console, context,
160-
[&](ProControllerContext& context){
161-
while (true){
162-
send_program_status_notification(env, NOTIFICATION_STATUS);
163-
sit_on_bench(env.console, context);
164-
stats.resets++;
165-
env.update_stats();
166-
Milliseconds duration = WALK_FORWARD_DURATION;
167-
if (duration > Milliseconds::zero()){
168-
if (WALK_DIRECTION.current_value() == 0){ // forward
169-
ssf_press_button(context, BUTTON_B, 0ms, 2 * duration, 0ms);
170-
pbf_move_left_joystick(context, 128, 0, duration, 0ms);
171-
pbf_move_left_joystick(context, 128, 255, duration + 500ms, 0ms);
172-
} else if (WALK_DIRECTION.current_value() == 1){ // left
173-
ssf_press_button(context, BUTTON_B, 0ms, duration, 0ms);
174-
pbf_move_left_joystick(context, 0, 128, duration, 0ms);
175-
pbf_press_button(context, BUTTON_L, 100ms, 400ms);
176-
ssf_press_button(context, BUTTON_B, 0ms, duration, 0ms);
177-
pbf_move_left_joystick(context, 128, 255, duration, 0ms);
178-
pbf_move_left_joystick(context, 0, 128, 100ms, 0ms);
179-
} else if (WALK_DIRECTION.current_value() == 2){ // right
180-
ssf_press_button(context, BUTTON_B, 0ms, duration, 0ms);
181-
pbf_move_left_joystick(context, 255, 128, duration, 0ms);
182-
pbf_press_button(context, BUTTON_L, 100ms, 400ms);
183-
ssf_press_button(context, BUTTON_B, 0ms, duration, 0ms);
184-
pbf_move_left_joystick(context, 128, 255, duration, 0ms);
185-
pbf_move_left_joystick(context, 255, 128, 100ms, 0ms);
186-
}
187-
}
188-
else{
189-
reapproach_bench_after_getting_up(env, context);
190-
}
191-
}
192-
},
193-
{{shiny_detector}}
194-
);
164+
pbf_press_button(context, BUTTON_CAPTURE, 2 * TICKS_PER_SECOND, 0);
165+
to_take_shiny_sound_video.store(0, std::memory_order_relaxed);
166+
}
167+
};
195168

196-
// This should never happen.
197-
if (ret != 0){
198-
continue;
169+
PokemonLA::ShinySoundDetector shiny_detector(env.console, [&](float error_coefficient) -> bool{
170+
// Warning: This callback will be run from a different thread than this function.
171+
stats.shinies++;
172+
env.update_stats();
173+
174+
if ((SHINY_DETECTED.ACTION == ShinySoundDetectedAction::STOP_PROGRAM) || stats.shinies == 1){
175+
// Record the detection time for video delay calculation
176+
WallClock now = current_time();
177+
int64_t now_ms = std::chrono::duration_cast<Milliseconds>(now.time_since_epoch()).count();
178+
shiny_detection_time_ms.store(now_ms, std::memory_order_relaxed);
179+
180+
SHINY_DETECTED.send_shiny_sound_notification(env, env.console, error_coefficient);
181+
to_take_shiny_sound_video.store(1, std::memory_order_relaxed);
199182
}
200183

201-
pbf_mash_button(context, BUTTON_B, 1000ms);
184+
return SHINY_DETECTED.ACTION == ShinySoundDetectedAction::STOP_PROGRAM;
185+
});
202186

203-
bool exit = SHINY_DETECTED.on_shiny_sound(
204-
env, env.console, context,
205-
stats.shinies,
206-
shiny_coefficient
207-
);
187+
run_until<ProControllerContext>(
188+
env.console, context,
189+
[&](ProControllerContext& context){
190+
while (true){
191+
send_program_status_notification(env, NOTIFICATION_STATUS);
192+
sit_on_bench(env.console, context);
193+
handle_shiny_sound_video_request();
194+
stats.resets++;
195+
env.update_stats();
196+
Milliseconds duration = WALK_FORWARD_DURATION;
197+
if (duration > Milliseconds::zero()){
198+
if (WALK_DIRECTION.current_value() == 0){ // forward
199+
ssf_press_button(context, BUTTON_B, 0ms, 2 * duration, 0ms);
200+
pbf_move_left_joystick(context, 128, 0, duration, 0ms);
201+
pbf_move_left_joystick(context, 128, 255, duration + 500ms, 0ms);
202+
} else if (WALK_DIRECTION.current_value() == 1){ // left
203+
ssf_press_button(context, BUTTON_B, 0ms, duration, 0ms);
204+
pbf_move_left_joystick(context, 0, 128, duration, 0ms);
205+
pbf_press_button(context, BUTTON_L, 100ms, 400ms);
206+
ssf_press_button(context, BUTTON_B, 0ms, duration, 0ms);
207+
pbf_move_left_joystick(context, 128, 255, duration, 0ms);
208+
pbf_move_left_joystick(context, 0, 128, 100ms, 0ms);
209+
} else if (WALK_DIRECTION.current_value() == 2){ // right
210+
ssf_press_button(context, BUTTON_B, 0ms, duration, 0ms);
211+
pbf_move_left_joystick(context, 255, 128, duration, 0ms);
212+
pbf_press_button(context, BUTTON_L, 100ms, 400ms);
213+
ssf_press_button(context, BUTTON_B, 0ms, duration, 0ms);
214+
pbf_move_left_joystick(context, 128, 255, duration, 0ms);
215+
pbf_move_left_joystick(context, 255, 128, 100ms, 0ms);
216+
}
217+
}
218+
else{
219+
reapproach_bench_after_getting_up(env, context);
220+
}
208221

209-
pbf_move_left_joystick(context, 128, 255, WALK_FORWARD_DURATION, 0ms);
222+
handle_shiny_sound_video_request();
223+
}
224+
},
225+
{{shiny_detector}}
226+
);
210227

211-
if (exit){
212-
break;
213-
}
214-
}
228+
// Shiny sound detected and user requested stopping the program when detected shiny sound
229+
230+
handle_shiny_sound_video_request();
215231

216232
go_home(env.console, context);
217233
send_program_finished_notification(env, NOTIFICATION_PROGRAM_FINISH);
218-
219234
}
220235

221236

0 commit comments

Comments
 (0)