| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- #pragma once
- #include <array>
- #include <cstddef>
- #include <cstdint>
- #include "inventory/inventory_state.h"
- #include "settings/settings_state.h"
- namespace sunrise::state {
- /** One account can own at most the 3 playable character slots. */
- inline constexpr std::size_t kCharacterCapacity = 3;
- /** A server-authored dismantle policy: a few rows per rarity and gear class. */
- inline constexpr std::size_t kDismantleRewardPolicyCapacity = 32;
- /** Gear classes a dismantle payout row can be limited to. */
- enum class DismantleGearClass : std::uint8_t {
- weapon = 1U << 0U,
- armor = 1U << 1U,
- };
- /** Whether a payout row wants the dismantled item masterworked. */
- enum class DismantleMasterworkFilter : std::uint8_t {
- any = 0,
- masterworked = 1,
- notMasterworked = 2,
- };
- /**
- * One profile material credited when ordinary character gear is dismantled. Every filter left at
- * its "any" value matches every item; the payout is the sum of the matching rows.
- */
- struct DismantleRewardPolicy {
- std::uint32_t definitionHash{};
- std::int32_t quantity{};
- /** Bit (1 << tier) per native tier 1-5 the row pays for; 0 pays for every tier. */
- std::uint8_t tierMask{};
- /** DismantleGearClass bits the row pays for; 0 pays for both. */
- std::uint8_t classMask{};
- DismantleMasterworkFilter masterwork{DismantleMasterworkFilter::any};
- };
- /** @return True when both rows are the same row: same material under the same filters. */
- [[nodiscard]] constexpr bool
- same_dismantle_policy_key(const DismantleRewardPolicy& left,
- const DismantleRewardPolicy& right) noexcept {
- return left.definitionHash == right.definitionHash && left.tierMask == right.tierMask
- && left.classMask == right.classMask && left.masterwork == right.masterwork;
- }
- /** Stable character race values authored independently of package definition mappings. */
- enum class CharacterRace : std::uint8_t {
- /** Wire value 0 is a Human character. */
- human = 0,
- /** Wire value 1 is an Awoken character. */
- awoken = 1,
- /** Wire value 2 is an Exo character. */
- exo = 2,
- };
- /** Stable character gender values authored independently of package definition mappings. */
- enum class CharacterGender : std::uint8_t {
- /** Wire value 0 is a male character. */
- male = 0,
- /** Wire value 1 is a female character. */
- female = 1,
- };
- /** Stable character class values authored independently of package definition mappings. */
- enum class CharacterClass : std::uint8_t {
- /** Wire value 0 is a Titan character. */
- titan = 0,
- /** Wire value 1 is a Hunter character. */
- hunter = 1,
- /** Wire value 2 is a Warlock character. */
- warlock = 2,
- };
- /** Default movement entry. Each subclass offers 3, as entries 4, 5 and 6 of its group. */
- inline constexpr std::uint8_t kDefaultMovementAbilityEntry = 4;
- /** No socket entry list declares more entries than this, so a larger value is not an entry. */
- inline constexpr std::uint8_t kMaximumMovementAbilityEntry = 63;
- /**
- * Socket entries of the other abilities a subclass lets the player choose. Each names one entry
- * of that ability's group. The subclass offers several and the character picks one. These
- * defaults are the first option of each group, where every shipped subclass starts.
- */
- inline constexpr std::uint8_t kDefaultGrenadeAbilityEntry = 7;
- /** Default super entry. It is the lane that carries no plug source and kind 34. */
- inline constexpr std::uint8_t kDefaultSuperAbilityEntry = 10;
- /** Default melee entry. */
- inline constexpr std::uint8_t kDefaultMeleeAbilityEntry = 11;
- /** Default class-ability entry. Which bucket it publishes into follows the character class. */
- inline constexpr std::uint8_t kDefaultClassAbilityEntry = 2;
- /**
- * Semantic ability-bucket destinations shared by the wire encoder and the selection logic that
- * routes a clicked socket entry to a character field. A subclass entry's authored selector chain,
- * not its table position, decides which it reaches; a bundled pick can mix members across them.
- */
- inline constexpr std::uint8_t kGrenadeAbilityBucket = 0;
- inline constexpr std::uint8_t kSuperAbilityBucket = 1;
- inline constexpr std::uint8_t kMeleeAbilityBucket = 2;
- inline constexpr std::uint8_t kMovementAbilityBucket = 3;
- inline constexpr std::uint8_t kSprintAbilityBucket = 4;
- /**
- * Widest node bundle one summary pick can publish together.
- * Some groups (an Attunement pick, for example) hold several consecutive entries that all
- * activate, and contribute their hashes, as one unit rather than a single alternative per group.
- */
- inline constexpr std::size_t kMaxAttunementBundleSize = 4;
- /** @param characterClass Authored class. @return The bucket its class ability publishes into. */
- [[nodiscard]] inline constexpr std::uint8_t
- class_ability_bucket(CharacterClass characterClass) noexcept {
- switch (characterClass) {
- case CharacterClass::hunter:
- return 9;
- case CharacterClass::warlock:
- return 11;
- case CharacterClass::titan:
- default:
- return 6;
- }
- }
- /** Authored state for one playable character slot. */
- struct CharacterState {
- std::uint64_t soid{};
- /** Runtime selection, moved only by the character pick. No character is selected at boot. */
- bool selected{};
- CharacterRace race{CharacterRace::human};
- CharacterGender gender{CharacterGender::male};
- CharacterClass characterClass{CharacterClass::titan};
- std::uint8_t level{};
- bool accepted{};
- bool previewAvailable{};
- /** Authored scalar kept for the family-specific character presentation encoders. */
- float appearanceValue{};
- /** Compact default destination hash used until a later runtime selection replaces it. */
- std::uint32_t lastOrbitedDestination{};
- /**
- * Activity whose orbit bubble the character is in, family-4 `+45896`. Authored at sign-in.
- * A launch moves it to the target before the client's launch commit, which latches it.
- */
- std::uint16_t currentActivityIndex{};
- /** Server policy that arms content checks only with the matching family-5 flag. */
- bool contentBypass{};
- /**
- * Unix seconds the account signed in, from one clock read shared by every character.
- * The character records publish it as their last applied daily and weekly reset; zero
- * makes both rollovers due the moment the client accepts the record.
- */
- std::uint64_t signInSeconds{};
- /**
- * Runtime-only socket entries the player has selected at least once. Selected entries still
- * publish active; this mask keeps a later inactive entry acquired instead of new. Unverified:
- * defaulted all-set, assuming the Client only allows clicking an already-acquired node.
- */
- std::uint64_t acquiredSubclassAbilityMask{~std::uint64_t{0}};
- /** Authored loadout keyed only by stable semantic equipment slots. */
- account::inventory::Equipment equipment;
- /** Unequipped items routed into their installed character-inventory bucket ranges. */
- account::inventory::CharacterItems inventory;
- /** Next row generation; equip transactions consume two values for the two moved items. */
- std::uint32_t nextInventorySerial{};
- };
- /** Account identity shared by backend object families. */
- struct AccountState {
- std::uint64_t primarySoid{};
- /** Economy policy comes from configuration, never from item-specific runtime constants. */
- std::array<DismantleRewardPolicy, kDismantleRewardPolicyCapacity> dismantleRewards{};
- std::size_t dismantleRewardCount{};
- /** Account-wide currencies and materials, placed by bucket rather than by authored slot. */
- std::array<account::inventory::ProfileItem, account::inventory::kProfileItemCapacity>
- profileItems{};
- std::size_t profileItemCount{};
- std::array<CharacterState, kCharacterCapacity> characters{};
- std::size_t characterCount{};
- /** True after this account has completed the client's one-time profile setup flow. */
- bool profileSetupCompleted{};
- account::settings::AccountSettings settings;
- };
- namespace account {
- [[nodiscard]] bool valid(const AccountState& state) noexcept;
- /** Checks settings-authored State before runtime-only profile stack SOIDs are assigned. */
- [[nodiscard]] bool valid_authored(const AccountState& state) noexcept;
- [[nodiscard]] std::uint64_t selected_character_soid(const AccountState& state) noexcept;
- /**
- * Reports the character the family-zero banner pair names.
- * The pair is published before any pick. A refusal spends the family's only acceptance window,
- * so it falls back to the first character.
- * @param state Account snapshot read under the lock.
- * @return The character's SOID, or zero when the account owns none.
- */
- [[nodiscard]] std::uint64_t banner_character_soid(const AccountState& state) noexcept;
- } // namespace account
- } // namespace sunrise::state
|