Achievements: Infer and display beaten/completed time

pull/3501/head
Stenzek 1 year ago
parent 5c48f853da
commit e38039873e
No known key found for this signature in database

@ -216,6 +216,9 @@ typedef struct rc_client_user_game_summary_t {
uint32_t points_core;
uint32_t points_unlocked;
time_t beaten_time; /* 0 if not beaten, otherwise the time the game was beaten */
time_t completed_time; /* 0 if not mastered, otherwise the time the game was mastered */
} rc_client_user_game_summary_t;
/**

@ -923,6 +923,10 @@ static void rc_client_subset_get_user_game_summary(const rc_client_subset_info_t
{
rc_client_achievement_info_t* achievement = subset->achievements;
rc_client_achievement_info_t* stop = achievement + subset->public_.num_achievements;
uint32_t num_progression_achievements = 0, unlocked_progression_achievements = 0;
uint32_t num_win_condition_achievements = 0;
time_t last_progression_unlock = 0, first_win_condition_unlock = 0;
time_t last_achievement_unlock = 0;
for (; achievement < stop; ++achievement) {
switch (achievement->public_.category) {
case RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE:
@ -932,6 +936,29 @@ static void rc_client_subset_get_user_game_summary(const rc_client_subset_info_t
if (achievement->public_.unlocked & unlock_bit) {
++summary->num_unlocked_achievements;
summary->points_unlocked += achievement->public_.points;
last_achievement_unlock = (achievement->public_.unlock_time > last_achievement_unlock) ?
achievement->public_.unlock_time :
last_achievement_unlock;
if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION)
{
++unlocked_progression_achievements;
last_progression_unlock = (achievement->public_.unlock_time > last_progression_unlock) ?
achievement->public_.unlock_time :
last_progression_unlock;
}
else if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_WIN)
{
++num_win_condition_achievements;
first_win_condition_unlock = (first_win_condition_unlock == 0) ?
achievement->public_.unlock_time :
first_win_condition_unlock;
}
} else {
if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION)
++num_progression_achievements;
else if (achievement->public_.type == RC_CLIENT_ACHIEVEMENT_TYPE_WIN)
++num_win_condition_achievements;
}
if (achievement->public_.bucket == RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED) {
++summary->num_unsupported_achievements;
@ -947,6 +974,19 @@ static void rc_client_subset_get_user_game_summary(const rc_client_subset_info_t
continue;
}
}
/* Game considered beaten when all progression achievements are unlocked and any win condition achievement
* is unlocked, or all progression achievements are unlocked and no there are no win condition achievements. */
summary->beaten_time = 0;
if (num_progression_achievements > 0 && unlocked_progression_achievements == num_progression_achievements &&
(num_win_condition_achievements == 0 || first_win_condition_unlock > 0)) {
summary->beaten_time = (num_win_condition_achievements == 0) ? last_progression_unlock : first_win_condition_unlock;
}
/* Game considered completed when all achievements are unlocked */
summary->completed_time = 0;
if (summary->num_unlocked_achievements == summary->num_core_achievements)
summary->completed_time = last_achievement_unlock;
}
void rc_client_get_user_game_summary(const rc_client_t* client, rc_client_user_game_summary_t* summary)

@ -2769,7 +2769,8 @@ void Achievements::DrawAchievementsWindow()
static constexpr float alpha = 0.8f;
static constexpr float heading_alpha = 0.95f;
static constexpr float heading_height_unscaled = 110.0f;
const float heading_height_unscaled =
(s_state.game_summary.beaten_time > 0 || s_state.game_summary.completed_time) ? 140.0f : 110.0f;
const ImVec4 background = ImGuiFullscreen::ModAlpha(UIStyle.BackgroundColor, alpha);
const ImVec4 heading_background = ImGuiFullscreen::ModAlpha(UIStyle.BackgroundColor, heading_alpha);
@ -2845,6 +2846,41 @@ void Achievements::DrawAchievementsWindow()
ImGui::GetColorU32(ImGuiFullscreen::DarkerColor(ImGui::GetStyle().Colors[ImGuiCol_Text])),
text, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &summary_bb);
if (s_state.game_summary.beaten_time > 0 || s_state.game_summary.completed_time > 0)
{
text.clear();
if (s_state.game_summary.beaten_time > 0)
{
const std::string beaten_time =
Host::FormatNumber(Host::NumberFormatType::ShortDate, static_cast<s64>(s_state.game_summary.beaten_time));
if (s_state.game_summary.completed_time > 0)
{
const std::string completion_time =
Host::FormatNumber(Host::NumberFormatType::ShortDate, static_cast<s64>(s_state.game_summary.beaten_time));
text.format(TRANSLATE_FS("Achievements", "Game was beaten on {0}, and completed on {1}."), beaten_time,
completion_time);
}
else
{
text.format(TRANSLATE_FS("Achievements", "Game was beaten on {0}."), beaten_time);
}
}
else
{
const std::string completion_time =
Host::FormatNumber(Host::NumberFormatType::ShortDate, static_cast<s64>(s_state.game_summary.beaten_time));
text.format(TRANSLATE_FS("Achievements", "Game was completed on {0}."), completion_time);
}
const ImRect beaten_bb(ImVec2(left, top), ImVec2(right, top + UIStyle.MediumFontSize));
RenderShadowedTextClipped(
UIStyle.Font, UIStyle.MediumFontSize, UIStyle.BoldFontWeight, beaten_bb.Min, beaten_bb.Max,
ImGui::GetColorU32(ImGuiFullscreen::DarkerColor(ImGui::GetStyle().Colors[ImGuiCol_Text])), text, nullptr,
ImVec2(0.0f, 0.0f), 0.0f, &beaten_bb);
top += UIStyle.MediumFontSize + spacing;
}
if (s_state.game_summary.num_core_achievements > 0)
{
const float progress_height = LayoutScale(20.0f);

Loading…
Cancel
Save