Browse Source

Show the Triumph score on the fireteam roster card

The member record carries the Triumph score the fireteam row shows
under the Power at +0x2C. It was left zero. Write the account Triumph
score the record store already totals (the same value the character
header shows), and add it to the social_roster log line.
Gage Fulwood 5 days ago
parent
commit
df19698052

+ 18 - 5
Sunrise/src/server/bap/encrypted/push/snapshot/social_roster_snapshot.cpp

@@ -8,6 +8,7 @@
 #include <array>
 #include <cstdio>
 #include <cstring>
+#include <limits>
 #include <span>
 
 #include "../../../../../core/logging/log.h"
@@ -16,6 +17,7 @@
 #include "../../../../../state/build_data/items/item_catalog.h"
 #include "../../../../../state/equipment/light/resolution/configured_equipment_light_resolver.h"
 #include "../../../../../state/runtime/runtime.h"
+#include "../../../../../state/unlocks/unlocks_records.h"
 #include "internal.h"
 #include "snapshot_storage.h"
 
@@ -30,6 +32,8 @@ constexpr std::size_t kPowerOffset = 20;
 /** Where the member record carries the emblem the panel row reads. */
 constexpr std::size_t kEmblemDefinitionOffset = 36;
 constexpr std::size_t kEmblemVariantOffset = 38;
+/** Where the member record carries the Triumph score the fireteam row shows under the Power. */
+constexpr std::size_t kTriumphScoreOffset = 44;
 
 /**
  * Absent definition index. The variant field always takes it, because a real value there indexes
@@ -118,6 +122,11 @@ bool prepare_social_roster(Scratch& scratch,
     if (!selected_character_power(account, power)) {
         power = 0;
     }
+    // The client reads the score as a signed 32-bit value; the store never publishes it negative.
+    const std::uint32_t storedScore = state::unlocks::records::score();
+    const std::int32_t triumphScore = static_cast<std::int32_t>(
+        (std::min)(storedScore,
+                   static_cast<std::uint32_t>((std::numeric_limits<std::int32_t>::max)())));
 
     Prepared staged{};
     std::size_t objectCount = 0;
@@ -127,11 +136,12 @@ bool prepare_social_roster(Scratch& scratch,
     /**
      * Writes one object and stages it.
      * Both lookups match on the first qword, so the directory leads with the account soid and
-     * repeats it at +8 as the link the member record leads with. Only the member has the Power
-     * and the emblem.
+     * repeats it at +8 as the link the member record leads with. Only the member has the Power,
+     * the emblem and the Triumph score.
      */
     const auto emit = [&](std::size_t size, std::uint32_t id, bool directory) noexcept {
-        if (objectCount >= staged.objects.size() || size < kEmblemVariantOffset + sizeof emblem) {
+        if (objectCount >= staged.objects.size()
+            || size < kTriumphScoreOffset + sizeof triumphScore) {
             return false;
         }
         const auto body = destination.subspan(rawUsed, size);
@@ -148,6 +158,7 @@ bool prepare_social_roster(Scratch& scratch,
             std::memcpy(body.data() + kEmblemVariantOffset,
                         &kEmptyDefinitionIndex,
                         sizeof kEmptyDefinitionIndex);
+            std::memcpy(body.data() + kTriumphScoreOffset, &triumphScore, sizeof triumphScore);
         }
         std::size_t compressedSize = 0;
         if (!compress_object(scratch,
@@ -196,13 +207,15 @@ bool prepare_social_roster(Scratch& scratch,
     const int written = std::snprintf(line.data(),
                                       line.size(),
                                       "ev=queuez stage=social_roster result=ok soid=0x%016llX"
-                                      " objects=%zu bytes=%zu emblem=%u hash=0x%08X power=%d",
+                                      " objects=%zu bytes=%zu emblem=%u hash=0x%08X power=%d"
+                                      " score=%d",
                                       static_cast<unsigned long long>(account.primarySoid),
                                       objectCount,
                                       rawUsed,
                                       static_cast<unsigned>(emblem),
                                       static_cast<unsigned>(emblemHash),
-                                      static_cast<int>(power));
+                                      static_cast<int>(power),
+                                      static_cast<int>(triumphScore));
     if (written > 0) {
         core::log::write(core::log::Channel::server,
                          core::log::Level::info,