Explorar el Código

Drive lore book parent bars from the index their record names

A book's parent bar was written to the node's own valueIndex, which
resolves for only some books, and with the parent counted among its own
children so an untouched book read 1 of N.

Write the count to the index the parent record's field-136 expression
names instead, generated into parent_bar_table.h for the eighteen books
that name a value there. Where no entry exists, fall back to the slot
derived from the shipped allocation run, which drove those bars before
and still does -- eight books have no expression of their own. Drop the
parent from the count, and skip the category write when it would land on
the index the parent bar already took.

Twelve books remain unresolved. They name a flag at field 136 and a flag
in their node row, their raw slot has no entry in the value map, and no
record in the build populates categoryValueIndex, so no value index for
their bar is expressed anywhere in either definition row. The count is
correct for them -- Ghost Stories reports two claimed chapters -- only
the destination is unknown.
Millie hace 2 semanas
padre
commit
4991a44041

+ 10 - 2
Sunrise/src/client/content/items/packages/package_record_build.cpp

@@ -179,19 +179,27 @@ bool build_records(const reader::Source& source,
                     continue;
                 }
                 const std::int16_t named = isValue ? raw : rawFlag;
+                // Both maps, always. Twelve books name only a flag here and their bars stay dead;
+                // if the same raw number also resolves in the value map, that index is the bar's
+                // source and nobody has looked because the flag reading answered first.
                 int mapped = -1;
+                int asValue = -1;
                 if (addressable_slot(named) && static_cast<std::size_t>(named) < kSlotSpace) {
                     mapped = isValue ? static_cast<int>(valueIndexBySlot[
                                            static_cast<std::size_t>(named)])
                                      : static_cast<int>(indexBySlot[
                                            static_cast<std::size_t>(named)]);
+                    asValue = !valueIndexBySlot.empty()
+                                  ? static_cast<int>(
+                                        valueIndexBySlot[static_cast<std::size_t>(named)])
+                                  : -1;
                 }
                 std::array<char, 160> line{};
                 const int told = std::snprintf(
                     line.data(), line.size(),
-                    "ev=records stage=parent_expr row=%llu field=%zu kind=%s raw=%d mapped=%d",
+                    "ev=records stage=parent_expr row=%llu field=%zu kind=%s raw=%d mapped=%d as_value=%d",
                     static_cast<unsigned long long>(row), field, isValue ? "value" : "flag",
-                    static_cast<int>(named), mapped);
+                    static_cast<int>(named), mapped, asValue);
                 if (told > 0) {
                     core::log::write(core::log::Channel::client, core::log::Level::info,
                                      {line.data(), static_cast<std::size_t>(told)});

+ 10 - 4
Sunrise/src/state/record_claims/record_claims.cpp

@@ -552,10 +552,16 @@ std::size_t apply_node_progress(std::span<std::int32_t> objectiveValues) noexcep
                     break;
                 }
             }
-            // The category's own bar, where the node resolved a slot for it.
-            if (node.valueIndex != build_data::nodes::kUnavailableValueIndex
-                && static_cast<std::size_t>(node.valueIndex) < state->values.size()) {
-                state->values[node.valueIndex] = chapters + (haveParent ? 1 : 0);
+            // Eight books name no value at field 136 and so have no table entry, but their parent
+            // slot is still derivable from the shipped allocation -- the slot just past the run of
+            // their children. That derivation drove their bars before this table existed and is
+            // kept as the fallback, not replaced by it: the table is more trustworthy where it
+            // applies, and this is the only source where it does not.
+            if (parentSlot < 0
+                && node.parentValueIndex != build_data::nodes::kUnavailableValueIndex
+                && static_cast<std::size_t>(node.parentValueIndex) < state->values.size()) {
+                state->values[node.parentValueIndex] = chapters;
+                parentSlot = static_cast<std::int32_t>(node.parentValueIndex);
                 ++state->written;
             }
             std::array<char, 160> line{};