@@ -305,6 +305,74 @@ static void rcheevos_show_subset_completion_placard(const rc_client_subset_t* su
305305 rcheevos_show_completion_placard (subset -> title , subset -> badge_name );
306306}
307307
308+ #if defined(HAVE_GFX_WIDGETS )
309+
310+ static void rcheevos_show_achievement_popup (const rc_client_achievement_t * cheevo , float rarity )
311+ {
312+ char title [128 ], subtitle [96 ];
313+
314+ if (rarity >= 10.0 )
315+ snprintf (title , sizeof (title ), "%s - %0.2f%%" ,
316+ msg_hash_to_str (MSG_ACHIEVEMENT_UNLOCKED ), rarity );
317+ else if (rarity > 0.0 )
318+ snprintf (title , sizeof (title ), "%s - %0.2f%%" ,
319+ msg_hash_to_str (MSG_RARE_ACHIEVEMENT_UNLOCKED ), rarity );
320+ else
321+ strlcpy (title ,
322+ msg_hash_to_str (MSG_ACHIEVEMENT_UNLOCKED ), sizeof (title ));
323+
324+ snprintf (subtitle , sizeof (subtitle ), "%s (%lu)" , cheevo -> title , (unsigned long )cheevo -> points );
325+
326+ gfx_widgets_push_achievement (title , subtitle , cheevo -> badge_name );
327+
328+ /* if all badges haven't been loaded, preload the next one assuming it will be the next needed */
329+ if (!rcheevos_locals .badges_loaded )
330+ {
331+ const rc_client_achievement_t * next_locked_achievement =
332+ rc_client_get_next_achievement_info (rcheevos_locals .client , cheevo , RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED );
333+ if (next_locked_achievement )
334+ rcheevos_client_download_badge_from_url (next_locked_achievement -> badge_url , next_locked_achievement -> badge_name );
335+ }
336+ }
337+
338+ struct rcheevos_retry_achievement_info_t
339+ {
340+ uint32_t achievement_id ;
341+ float rarity ;
342+ };
343+
344+ static void rcheevos_retry_achievement_popup (retro_task_t * task )
345+ {
346+ struct rcheevos_retry_achievement_info_t * info = (struct rcheevos_retry_achievement_info_t * )task -> user_data ;
347+ const rc_client_achievement_t * cheevo = rc_client_get_achievement_info (rcheevos_locals .client , info -> achievement_id );
348+ if (!cheevo )
349+ {
350+ /* achievement not found, assume game unloaded and don't show the popup */
351+ }
352+ else if (task -> progress > 4 || rcheevos_is_badge_available (cheevo -> badge_name , false))
353+ {
354+ /* badge is available now, or we've reached the retry limit. show the popup */
355+ rcheevos_show_achievement_popup (cheevo , info -> rarity );
356+ }
357+ else
358+ {
359+ /* second retry in 200ms, third is 400ms, fourth in 800ms. if not available after 1500ms
360+ * (100+200+400+800), then just show the popup with the placeholder. */
361+ task -> progress <<= 1 ;
362+ task -> when = cpu_features_get_time_usec () + 100000 * task -> progress ; /* first retry in 100ms */
363+ return ;
364+ }
365+
366+ /* cleanup the user data */
367+ task -> user_data = NULL ;
368+ free (info );
369+
370+ /* mark task as complete so it will get cleaned up */
371+ task_set_flags (task , RETRO_TASK_FLG_FINISHED , true);
372+ }
373+
374+ #endif /* HAVE_GFX_WIDGETS */
375+
308376static void rcheevos_award_achievement (const rc_client_achievement_t * cheevo )
309377{
310378 const settings_t * settings = config_get_ptr ();
@@ -318,31 +386,37 @@ static void rcheevos_award_achievement(const rc_client_achievement_t* cheevo)
318386#if defined(HAVE_GFX_WIDGETS )
319387 if (gfx_widgets_ready ())
320388 {
321- char title [128 ], subtitle [96 ];
322389 float rarity = rc_client_get_hardcore_enabled (rcheevos_locals .client ) ?
323390 cheevo -> rarity_hardcore : cheevo -> rarity ;
324391
325- if (rarity >= 10.0 )
326- snprintf (title , sizeof (title ), "%s - %0.2f%%" ,
327- msg_hash_to_str (MSG_ACHIEVEMENT_UNLOCKED ), rarity );
328- else if (rarity > 0.0 )
329- snprintf (title , sizeof (title ), "%s - %0.2f%%" ,
330- msg_hash_to_str (MSG_RARE_ACHIEVEMENT_UNLOCKED ), rarity );
392+ if (rcheevos_locals .badges_loaded || rcheevos_is_badge_available (cheevo -> badge_name , false))
393+ {
394+ rcheevos_show_achievement_popup (cheevo , rarity );
395+ }
331396 else
332- strlcpy (title ,
333- msg_hash_to_str (MSG_ACHIEVEMENT_UNLOCKED ), sizeof (title ));
397+ {
398+ retro_task_t * task ;
399+ rcheevos_client_download_badge_from_url (cheevo -> badge_url , cheevo -> badge_name );
334400
335- snprintf (subtitle , sizeof (subtitle ), "%s (%lu)" , cheevo -> title , (unsigned long )cheevo -> points );
401+ task = task_init ();
402+ if (!task )
403+ {
404+ rcheevos_show_achievement_popup (cheevo , rarity );
405+ }
406+ else
407+ {
408+ struct rcheevos_retry_achievement_info_t * info ;
409+ info = (struct rcheevos_retry_achievement_info_t * )malloc (sizeof (* info ));
410+ info -> achievement_id = cheevo -> id ;
411+ info -> rarity = rarity ;
336412
337- gfx_widgets_push_achievement (title , subtitle , cheevo -> badge_name );
413+ task -> handler = rcheevos_retry_achievement_popup ;
414+ task -> user_data = info ;
415+ task -> progress = 1 ;
416+ task -> when = cpu_features_get_time_usec () + 100000 ; /* first retry in 100ms */
338417
339- /* if all badges haven't been loaded, preload the next one assuming it will be the next needed */
340- if (!rcheevos_locals .badges_loaded )
341- {
342- const rc_client_achievement_t * next_locked_achievement =
343- rc_client_get_next_achievement_info (rcheevos_locals .client , cheevo , RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED );
344- if (next_locked_achievement )
345- rcheevos_client_download_badge_from_url (next_locked_achievement -> badge_url , next_locked_achievement -> badge_name );
418+ task_queue_push (task );
419+ }
346420 }
347421 }
348422 else
0 commit comments