From aa0224a8ab3f5e450de0fcc1e53906029e6b93b1 Mon Sep 17 00:00:00 2001 From: LillyJadeKatrin Date: Tue, 23 May 2023 08:38:53 -0400 Subject: [PATCH] Added TallyScore method to AchievementManager Added a TallyScore method to AchievementManager to calculate the player's current scores (soft and hard) against the total number of points across all achievements. Includes a PointSpread structure to hold all points and counts. The Unlock Map now includes point values for each achievement to aid in this calculation; this is populated at insert time, and Unofficial achievements are tallied as zero. --- Source/Core/Core/AchievementManager.cpp | 31 +++++++++++++++++++++++-- Source/Core/Core/AchievementManager.h | 15 +++++++++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index 4420bec0cf..b6a1879642 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -185,8 +185,11 @@ void AchievementManager::ActivateDeactivateAchievements() bool encore = Config::Get(Config::RA_ENCORE_ENABLED); for (u32 ix = 0; ix < m_game_data.num_achievements; ix++) { - auto iter = - m_unlock_map.insert({m_game_data.achievements[ix].id, UnlockStatus{.game_data_index = ix}}); + u32 points = (m_game_data.achievements[ix].category == RC_ACHIEVEMENT_CATEGORY_UNOFFICIAL) ? + 0 : + m_game_data.achievements[ix].points; + auto iter = m_unlock_map.insert( + {m_game_data.achievements[ix].id, UnlockStatus{.game_data_index = ix, .points = points}}); ActivateDeactivateAchievement(iter.first->first, enabled, unofficial, encore); } } @@ -573,6 +576,30 @@ void AchievementManager::HandleLeaderboardTriggeredEvent(const rc_runtime_event_ } } +AchievementManager::PointSpread AchievementManager::TallyScore() const +{ + PointSpread spread{}; + for (const auto& entry : m_unlock_map) + { + u32 points = entry.second.points; + spread.total_count++; + spread.total_points += points; + if (entry.second.remote_unlock_status == UnlockStatus::UnlockType::HARDCORE || + (hardcore_mode_enabled && entry.second.session_unlock_count > 0)) + { + spread.hard_unlocks++; + spread.hard_points += points; + } + else if (entry.second.remote_unlock_status == UnlockStatus::UnlockType::SOFTCORE || + entry.second.session_unlock_count > 0) + { + spread.soft_unlocks++; + spread.soft_points += points; + } + } + return spread; +} + // Every RetroAchievements API call, with only a partial exception for fetch_image, follows // the same design pattern (here, X is the name of the call): // Create a specific rc_api_X_request_t struct and populate with the necessary values diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index 7c89be7c59..da11f930ce 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -41,6 +41,16 @@ public: }; using ResponseCallback = std::function; + struct PointSpread + { + u32 total_count; + u32 total_points; + u32 hard_unlocks; + u32 hard_points; + u32 soft_unlocks; + u32 soft_points; + }; + static AchievementManager* GetInstance(); void Init(); ResponseType Login(const std::string& password); @@ -84,6 +94,8 @@ private: void HandleLeaderboardCanceledEvent(const rc_runtime_event_t* runtime_event); void HandleLeaderboardTriggeredEvent(const rc_runtime_event_t* runtime_event); + PointSpread TallyScore() const; + template ResponseType Request(RcRequest rc_request, RcResponse* rc_response, const std::function& init_request, @@ -107,7 +119,8 @@ private: SOFTCORE, HARDCORE } remote_unlock_status = UnlockType::LOCKED; - int session_unlock_count = 0; + u32 session_unlock_count = 0; + u32 points = 0; }; std::unordered_map m_unlock_map;