inventory_state.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #pragma once
  2. #include <array>
  3. #include <cstddef>
  4. #include <cstdint>
  5. #include <optional>
  6. #include <string_view>
  7. #include "item_state.h"
  8. namespace sunrise::state::account::inventory {
  9. /** Authored equipment exposes the 16 named slots the first State supports. */
  10. enum class EquipmentSlot : std::uint8_t {
  11. kinetic,
  12. energy,
  13. heavy,
  14. helmet,
  15. gauntlets,
  16. chest,
  17. legs,
  18. classItem,
  19. ghost,
  20. vehicle,
  21. ship,
  22. subclass,
  23. clanBanner,
  24. emblem,
  25. emote,
  26. finisher,
  27. count,
  28. };
  29. /** One fixed entry exists for every semantic equipment slot. */
  30. inline constexpr std::size_t kEquipmentSlotCount = static_cast<std::size_t>(EquipmentSlot::count);
  31. /** An authored item can pick at most 12 ordinary socket lanes. */
  32. inline constexpr std::size_t kPlugCapacity = 12;
  33. /** The engine no-definition hash cannot identify an authored item or plug. */
  34. inline constexpr std::uint32_t kNoDefinitionHash = 0x811C9DC5U;
  35. /** Says whether Middleware uses native socket defaults or authored lanes. */
  36. enum class SocketPolicy : std::uint8_t {
  37. nativeDefaults,
  38. authored,
  39. };
  40. /** Fixed authored socket choices. An empty optional is an explicit empty lane. */
  41. struct Sockets {
  42. SocketPolicy policy{SocketPolicy::nativeDefaults};
  43. std::array<std::optional<std::uint32_t>, kPlugCapacity> plugs{};
  44. std::size_t plugCount{};
  45. };
  46. /** Account-wide stacks can occupy every row of the native 701-row profile inventory. */
  47. inline constexpr std::size_t kProfileItemCapacity = 701;
  48. /** The supported mod and shader profile bucket runs reserve 50 action-source rows each. */
  49. inline constexpr std::size_t kProfileActionSourceCapacity = 100;
  50. /** Runtime-owned SOIDs for profile stacks use a namespace separate from created item instances. */
  51. inline constexpr std::uint64_t kFirstProfileItemInstanceSoid = 0x5000000000000001ULL;
  52. /**
  53. * The 16 supported character equipment buckets reserve 151 native rows in this build. One row
  54. * * per semantic slot can be equipped, leaving at most 135 simultaneously unequipped instances.
  55. */
  56. inline constexpr std::size_t kCharacterItemCapacity = 135;
  57. /**
  58. * Definition hash of the real, non-equippable "Emotes" collection item. The Client opens its own
  59. * wheel-configuration screen for this exact item once it is equipped with valid socket data.
  60. */
  61. inline constexpr std::uint32_t kEmoteCollectionDefinitionHash = 3183180185U;
  62. /** Ordinary socket lane count the "Emotes" collection item's real content declares. */
  63. inline constexpr std::size_t kEmoteCollectionSocketLaneCount = 4;
  64. /**
  65. * Native equipment slot the "Emotes" collection item is equipped under, in place of the individual
  66. * emote it replaces. Its own real content carries no native equipment-slot mapping at all, unlike
  67. * every other character-scoped item, so callers that need one for this item specifically fall back
  68. * to this constant through resolve_native_equipment_slot() below.
  69. */
  70. inline constexpr std::uint8_t kEmoteCollectionNativeEquipmentSlot =
  71. static_cast<std::uint8_t>(EquipmentSlot::emote);
  72. /**
  73. * Resolves the native equipment slot a configured item detail occupies.
  74. * Every character-scoped item declares its own native slot except the "Emotes" collection item
  75. * (kEmoteCollectionDefinitionHash), the one item whose real content has none. Any other item
  76. * missing a native slot is rejected instead of silently aliasing this fallback.
  77. * @param definitionHash Authored item definition hash being resolved.
  78. * @param detailEquipmentSlot The installed item detail's own native slot, if it declares one.
  79. * @param nativeSlot Receives the resolved native slot on success.
  80. * @return True when the item declares its own non-negative slot, or is the Emotes collection item.
  81. */
  82. [[nodiscard]] bool
  83. resolve_native_equipment_slot(std::uint32_t definitionHash,
  84. const std::optional<std::int8_t>& detailEquipmentSlot,
  85. std::uint8_t& nativeSlot) noexcept;
  86. /** One authored account-wide item, placed by the inventory bucket its definition names. */
  87. struct ProfileItem {
  88. /** Stable runtime identity required to materialize this row as an inventory action source. */
  89. std::uint64_t instanceSoid{};
  90. std::uint32_t definitionHash{};
  91. std::int32_t quantity{};
  92. /** Rising generation copied into the native row and matched by acquisition feedback. */
  93. std::int32_t mutationSerial{};
  94. };
  95. /** One authored equipment item without native table or wire-layout fields. */
  96. struct Item {
  97. std::uint64_t instanceSoid{};
  98. std::uint32_t definitionHash{};
  99. std::int32_t level{};
  100. std::int32_t quantity{};
  101. /**
  102. * Rising per-character generation assigned whenever this item changes inventory rows. The
  103. * Client also orders a bucket's grid by it, so an equip swap hands the displaced item the
  104. * clicked item's prior serial to keep it in the clicked cell.
  105. */
  106. std::int32_t mutationSerial{};
  107. /** Native accumulated item-state bits such as the finisher favorite marker. */
  108. std::uint32_t flags{};
  109. Sockets sockets;
  110. /**
  111. * Selected ability-node socket entries. Only meaningful on a subclass. Kept on the item, not
  112. * the character, so each owned subclass remembers its own picks. Defaults match
  113. * state::kDefault*AbilityEntry, literal here to avoid a circular include.
  114. */
  115. std::uint8_t movementAbilityEntry{4};
  116. std::uint8_t grenadeAbilityEntry{7};
  117. std::uint8_t superAbilityEntry{10};
  118. std::uint8_t meleeAbilityEntry{11};
  119. std::uint8_t classAbilityEntry{2};
  120. };
  121. /** Ordered unequipped items placed into their native character-inventory bucket ranges. */
  122. struct CharacterItems {
  123. std::array<Item, kCharacterItemCapacity> values{};
  124. std::size_t count{};
  125. };
  126. /** One optional authored item for every semantic equipment slot. */
  127. struct Equipment {
  128. std::array<std::optional<Item>, kEquipmentSlotCount> slots{};
  129. };
  130. /**
  131. * Finds the semantic State slot for one exact JSON equipment name.
  132. * @param name Borrowed case-sensitive equipment name.
  133. * @return Matching slot, or no value for an unknown name.
  134. */
  135. [[nodiscard]] std::optional<EquipmentSlot> slot_from_name(std::string_view name) noexcept;
  136. /**
  137. * Checks the canonical socket policy and every authored plug hash.
  138. * @return True when the policy, count and fixed tail agree.
  139. */
  140. [[nodiscard]] bool valid(const Sockets& sockets) noexcept;
  141. /**
  142. * Checks one whole authored item without reading installed build data.
  143. * @return True when the id, scalar and socket fields are valid.
  144. */
  145. [[nodiscard]] bool valid(const Item& item) noexcept;
  146. /**
  147. * Checks every item present in the fixed semantic equipment array.
  148. * @return True when every used slot holds a whole item.
  149. */
  150. [[nodiscard]] bool valid(const Equipment& equipment) noexcept;
  151. /** Checks the used prefix and empty tail of one character's unequipped item array. */
  152. [[nodiscard]] bool valid(const CharacterItems& items) noexcept;
  153. } // namespace sunrise::state::account::inventory