فهرست منبع

Keep repeated perk draws out of the stack merge

Zach 3 هفته پیش
والد
کامیت
a0f931ad7f

+ 16 - 0
Sunrise/Sunrise.vcxproj

@@ -104,6 +104,22 @@
     <ClCompile Include="src\state\rewards\reward_resolver.cpp" />
     <ClCompile Include="src\state\build_data\rewards\reward_catalog.cpp" />
     <ClCompile Include="src\state\build_data\rewards\reward_build_data_runtime.cpp" />
+    <ClCompile Include="src\client\diagnostics\studio\studio_link.cpp" />
+    <ClCompile Include="src\client\diagnostics\studio\studio_world_reader.cpp" />
+    <ClCompile Include="src\client\diagnostics\studio\studio_world_link.cpp" />
+    <ClCompile Include="src\client\diagnostics\studio\studio_pose_capture.cpp" />
+    <!-- Uncounted observer boundaries must not call compiler debug helpers. -->
+    <ClCompile Include="src\client\diagnostics\studio\studio_pose_link.cpp">
+      <SupportJustMyCode>false</SupportJustMyCode>
+      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
+    </ClCompile>
+    <ClCompile Include="src\client\diagnostics\studio\studio_object_link.cpp" />
+    <ClCompile Include="src\client\diagnostics\studio\studio_cui_reader.cpp" />
+    <ClCompile Include="src\client\diagnostics\studio\studio_cui_link.cpp" />
+    <ClCompile Include="src\client\diagnostics\studio\studio_cui_observer.cpp">
+      <SupportJustMyCode>false</SupportJustMyCode>
+      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
+    </ClCompile>
     <ClCompile Include="src\state\gameplay\external\entity_object_types.cpp" />
     <ClCompile Include="src\state\investment\investment_account_store.cpp" />
     <ClCompile Include="src\state\investment\investment_database.cpp" />

+ 1 - 0
Sunrise/src/middleware/content/packages/tables/definition_index_table.cpp

@@ -2,6 +2,7 @@
 
 #include <limits>
 
+#include "../reader/layout.h"
 #include "field_reader.h"
 
 namespace sunrise::middleware::content::packages::tables {

+ 2 - 11
Sunrise/src/middleware/content/packages/tables/definition_index_table.h

@@ -95,11 +95,8 @@ inline constexpr std::size_t kUnlockInstructionOperandOffset = 4;
 /** An expression field is a 64-bit count then a 64-bit self-relative offset. */
 inline constexpr std::size_t kUnlockExpressionFieldSize = 16;
 inline constexpr std::size_t kUnlockExpressionPointerOffset = 8;
-/**
- * Record and node field detection accepts a field only when every opcode is at most 20. This is a
- * detection bound, not the opcode range: installed reward conditions also use opcode 22.
- */
-inline constexpr std::uint32_t kUnlockOpcodeCeiling = 20;
+/** The evaluator's opcodes run to 27; anything wider means the field is not an expression. */
+inline constexpr std::uint32_t kUnlockOpcodeCeiling = 27;
 /** The opcode that reads a value slot. */
 inline constexpr std::uint32_t kUnlockReadValueOpcode = 10;
 /** The opcode that tests a flag. */
@@ -110,12 +107,6 @@ inline constexpr std::uint32_t kUnlockLiteralOpcode = 11;
 inline constexpr std::uint32_t kUnlockExpressionOpcode = 12;
 /** The opcode that tests greater than or equal. */
 inline constexpr std::uint32_t kUnlockGreaterEqualOpcode = 14;
-/** The opcode that inverts the value on top of the stack. Its operand is unused. */
-inline constexpr std::uint32_t kUnlockNotOpcode = 2;
-/** The opcode that folds the top two values with logical and. */
-inline constexpr std::uint32_t kUnlockAndOpcode = 4;
-/** The opcode that tests the top two values for equality. */
-inline constexpr std::uint32_t kUnlockEqualOpcode = 8;
 /** High half every installed array marker and element class carries. */
 inline constexpr std::uint32_t kDefinitionClassHigh = 0x8080U;
 /** Shift that leaves `kDefinitionClassHigh` from a marker or element class. */

+ 2 - 3
Sunrise/src/state/build_data/build_data_runtime.cpp

@@ -118,9 +118,8 @@ bool initialize(void* module, std::uint64_t configuredEquipmentHash) noexcept {
         domains.constants.weaponPowerStatRow,
         domains.constants.characterStatRows,
     };
-    if (status != cache::LoadStatus::loaded || !constants::replace(cachedConstants)
-        || !content::replace(domains.named) || !content::seal() || !items::replace(domains.items)
-        || !collectibles::replace(domains.collectibles)
+    if (!constants::replace(cachedConstants) || !content::replace(domains.named) || !content::seal()
+        || !items::replace(domains.items) || !collectibles::replace(domains.collectibles)
         || !rewards::replace({domains.rewardPools,
                               domains.rewardEntries,
                               domains.rewardItems,

+ 2 - 2
Sunrise/src/state/build_data/cache/records/format.h

@@ -32,7 +32,7 @@ namespace sunrise::state::build_data::cache::records {
 /** These 8 ASCII bytes mark a Sunrise build-data file. */
 inline constexpr std::array<char, 8> kCacheMagic{'S', 'U', 'N', 'R', 'I', 'S', 'E', 'B'};
 /** Bump when stored layouts or extracted values change; other versions are rebuilt. */
-inline constexpr std::uint32_t kCacheFormatVersion = 72;
+inline constexpr std::uint32_t kCacheFormatVersion = 73;
 /** Signed -1 on disk means there is no equipment slot. */
 inline constexpr std::int8_t kAbsentEquipmentSlot = -1;
 /** The standard 64-bit FNV-1a offset basis starts the payload checksum. */
@@ -674,7 +674,7 @@ static_assert(sizeof(Prefix) == kCacheMagic.size() + sizeof(std::uint32_t));
 static_assert(sizeof(InvestmentConstants)
               == constants::kCharacterStatRowCount + 3 * sizeof(std::uint8_t));
 static_assert(sizeof(Header)
-              == kCacheMagic.size() + 44 * sizeof(std::uint32_t) + 2 * sizeof(std::uint64_t)
+              == kCacheMagic.size() + 44 * sizeof(std::uint32_t) + 3 * sizeof(std::uint64_t)
                      + sizeof(InvestmentConstants)
                      + sizeof(gameplay::entity_position_profiles::Fingerprint));
 static_assert(sizeof(SpawnPointRecord)

+ 6 - 3
Sunrise/src/state/runtime/state_account_reward_grant_runtime.cpp

@@ -183,12 +183,15 @@ apply_reward_sockets(const item_details::Definition& detail,
     std::size_t kept = 0;
     for (std::size_t index = 0; index < resolved.count; ++index) {
         const reward_resolution::Grant grant = resolved.grants[index];
+        build_data::items::Definition item{};
         item_details::Definition detail{};
-        const bool stackable =
-            grant.socketCount == 0
+        // A perk grants its account flag, never an inventory stack.
+        const bool inventoryStack =
+            grant.socketCount == 0 && build_data::find_item_definition_index(grant.itemIndex, item)
+            && item.bucketId != inventory_buckets::kPerkBucketId
             && build_data::find_configured_item_detail(grant.itemIndex, detail)
             && detail.instancedDefinitionState == item_details::InstancedDefinitionState::stackable;
-        auto* const merged = stackable ? kept_stack(resolved, kept, grant.itemIndex) : nullptr;
+        auto* const merged = inventoryStack ? kept_stack(resolved, kept, grant.itemIndex) : nullptr;
         if (merged == nullptr) {
             resolved.grants[kept++] = grant;
             continue;