#pragma once #include #include namespace dingosdk::game::build::v20260929::native_throwdowns { // Hooked functions. // Reports whether a throwdown mode exists in the backend catalogue. inline constexpr std::uintptr_t mode_available = 0x807130; inline constexpr std::array mode_available_prefix{ 0x40,0x53,0x48,0x83,0xec,0x20,0x48,0x8b,0xd9,0x48,0x8d,0x4c,0x24,0x38,0xe8,0x9d,0xf9,0x0a,0x01}; // GetUIPlayerInfoByPlayerId expression native. inline constexpr std::uintptr_t player_info = 0x793080; inline constexpr std::array player_info_prefix{ 0x8b,0xd1,0x48,0x8b,0x0d,0x67,0x2e,0xa6,0x06,0x48,0x85,0xc9,0x0f,0x85,0xee,0x66,0xf4,0xff,0x33}; // UIPlayerService's own PlayerId lookup; the throwdown leaderboard (0x6718c0) // links each row to its player through it. inline constexpr std::uintptr_t service_player_info = 0x6d9780; inline constexpr std::array service_player_info_prefix{ 0x44,0x8b,0x49,0x28,0x4c,0x8b,0x51,0x20,0x44,0x8b,0xc2,0x8b,0xc2,0x33,0xd2,0x49,0xf7,0xf1,0x8b}; // SendNetworkedEvent. inline constexpr std::uintptr_t send_event = 0x733250; inline constexpr std::array send_event_prefix{ 0x4d,0x8b,0xc8,0x4c,0x8b,0xc2,0x48,0x8b,0xd1,0x48,0x8d,0x4c,0x24,0x20,0xe9,0xed,0x60,0,0}; // Requests throwdown mode parameters from throwdowns_v1. The native response // flattener (0x84f2f0) builds the array build_mode_parameters mirrors. inline constexpr std::uintptr_t parameters = 0x852f60; inline constexpr std::array parameters_prefix{ 0x40,0x55,0x57,0x41,0x54,0x41,0x56,0x48,0x8d,0x6c,0x24,0xa8,0x48,0x81,0xec,0x58,0x01,0x00,0x00}; // Throwdowner client system gate (expression native 7d0a4c0e): true unless the system's // +0x100 is set, then the backend's answer at +0xfa (written by a service response, // 0x7ab990, that never arrives offline). Other players' drops show only when it is true. inline constexpr std::uintptr_t others_throwdowns_allowed = 0x7aaec0; inline constexpr std::array others_throwdowns_allowed_prefix{ 0x48,0x83,0xec,0x28,0x48,0x8d,0x4c,0x24,0x30,0xe8,0x12,0xbc,0x10,0x01,0x48,0x8d,0x4c,0x24,0x30}; // Called helpers. // Returns the registered throwdowns_v1 container of the backend services. inline constexpr std::uintptr_t container_lookup = 0x84dc60; inline constexpr std::array container_lookup_prefix{ 0x48,0x89,0x5c,0x24,0x10,0x57,0x48,0x83,0xec,0x30,0x48,0x8d,0x99,0x90,0x04,0x00,0x00,0x48,0x8b}; // Assigns a character range to an engine string. inline constexpr std::uintptr_t string_assign_chars = 0x1584dd0; inline constexpr std::array string_assign_chars_prefix{ 0x48,0x89,0x5c,0x24,0x10,0x48,0x89,0x6c,0x24,0x20,0x56,0x48,0x83,0xec,0x20,0x41,0x8b,0xd8,0x48}; // Releases the mode parameter array. inline constexpr std::uintptr_t array_release = 0x6ccd40; inline constexpr std::array array_release_prefix{ 0x48,0x89,0x74,0x24,0x18,0x41,0x56,0x48,0x83,0xec,0x20,0x48,0x8b,0x31,0x4c,0x8b,0xf1,0xe8,0xaa}; // Expected code of the engine delegate and native_party array helpers. inline constexpr std::array delegate_copy_prefix{ 0x48,0x89,0x5c,0x24,0x08,0x57,0x48,0x83,0xec,0x20,0x48,0xc7,0x01,0x00,0x00,0x00,0x00,0x48,0x8b}; inline constexpr std::array delegate_destroy_prefix{ 0x48,0x8b,0x11,0xf6,0xc2,0x01,0x74,0x1b,0x48,0x83,0xe2,0xfe,0x74,0x15,0x48,0x8b,0x0d,0xe3,0x16}; inline constexpr std::array delegate_invoke_prefix{ 0x48,0x83,0xec,0x38,0x4c,0x8b,0x01,0x49,0x8b,0x08,0x48,0x8b,0x41,0x40,0x48,0x85,0xc0,0x74,0x10}; inline constexpr std::array empty_array_prefix{ 0x48,0x8d,0x05,0x79,0x8d,0x70,0x02,0xc3,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x40,0x53,0x57}; inline constexpr std::array array_allocate_prefix{ 0x48,0x89,0x5c,0x24,0x08,0x57,0x48,0x83,0xec,0x20,0x49,0x8b,0xc1,0x49,0x8b,0xd8,0x48,0x8b,0xfa}; // Developer-variable native (hash 0xbc999b66): its table row and the shared // "return the default" stub the row points at in retail. inline constexpr std::uintptr_t debug_variable_row = 0x7159028; inline constexpr std::uintptr_t debug_variable_stub = 0x2d70d60; // Globals // uint32 registration offset of the player identity base class. inline constexpr std::uintptr_t player_identity_offset = 0x6f7cfb0; // Throwdown lab (research; analysis/throwdowns-native-mp.md). // Posts MPParticipantsChanged(activity, const vector* added, const vector* removed) // to the activity's subscribers: server natives call it on every participant change, // the client calls it after diffing the replicated participant list. inline constexpr std::uintptr_t participants_changed = 0x810e30; inline constexpr std::array participants_changed_prefix{ 0x48,0x8b,0xc4,0x55,0x53,0x57,0x48,0x8d,0x68,0xa1,0x48,0x81,0xec,0xd0,0x00,0x00,0x00,0x48,0x89}; // GetPlayerName expression native (c4f60162): (const PlayerRef*, String* out). Leaves // `out` unwritten when the player reference is null. inline constexpr std::uintptr_t player_name = 0x820fe0; inline constexpr std::array player_name_prefix{ 0x48,0x89,0x5c,0x24,0x08,0x57,0x48,0x83,0xec,0x20,0x48,0x8b,0xd9,0x48,0x8b,0xfa,0x48,0x8d,0x4c}; // FindPlayerById expression native (55dbc76a): PlayerRef* (PlayerRef* out, u32 id); writes 0 // when no player has that id. Server graphs name participants as GetPlayerName(FindPlayerById). inline constexpr std::uintptr_t find_player_by_id = 0x8545d0; inline constexpr std::array find_player_by_id_prefix{ 0x48,0x89,0x5c,0x24,0x08,0x56,0x57,0x41,0x56,0x48,0x83,0xec,0x30,0x4c,0x8b,0xf1,0x8b,0xda,0x48}; // Coop challenges (analysis/coop-challenges-mp.md). Every challenge start, solo or coop, goes // through the coordinator's StartChallenge method thunk: (coordinator, String* SeriesId, // u32Array* participants, String* Id, bool isCoop, u64 group, u32 host, bool available, // bool contest). The caller owns (and frees) the participant array. inline constexpr std::uintptr_t start_challenge = 0x593d2b0; inline constexpr std::array start_challenge_prefix{ 0x40,0x55,0x53,0x56,0x57,0x41,0x56,0x48,0x8d,0x6c,0x24,0xf1,0x48,0x81,0xec,0xd0,0x00,0x00,0x00}; // Native arrays: a data pointer with u32 capacity at -8 and u32 count at -4 (bit 31 a flag). // Append one u32 (u32Array*, 0) -> slot; allocate a block for a wrapper (wrapper, bytes, align, // 0) -> block (data = block + 8), from the allocator that owns the wrapper's memory. inline constexpr std::uintptr_t array_append_u32 = 0x67c920; inline constexpr std::array array_append_u32_prefix{ 0x40,0x55,0x56,0x57,0x41,0x54,0x41,0x55,0x48,0x83,0xec,0x20,0x48,0x8b,0x31,0x4c,0x8b,0xca,0x4c}; inline constexpr std::uintptr_t array_allocate = 0x3dc7540; // prefix: array_allocate_prefix above // Client side of the coordinator's solo start (d52a4a77's native): (coordinator (unused), // const String* SeriesId, const String* Id, bool contest) sends RequestStartSoloChallenge // 3102c715 {Id, NetworkedEventPayload, SeriesId, available (its own 0x80a200 check), contest}. // Must run in the client realm. A String is one pointer; the empty one points at // empty_string; destroy frees any other. inline constexpr std::uintptr_t challenge_start_request = 0x7f3dd0; inline constexpr std::array challenge_start_request_prefix{ 0x40,0x53,0x55,0x56,0x57,0x48,0x83,0xec,0x48,0x49,0x8b,0xc8,0x41,0x0f,0xb6,0xf1,0x49,0x8b,0xf8}; inline constexpr std::uintptr_t empty_string = 0x72fe704, string_destroy = 0x1586050; // Player lookups the party beacon's walk-up prompt makes (analysis/party-re/beacons.md): // FindPlayerByName (Address* out player ref, const String* name) and GetPlayerPersonaId // (const Address* player ref, u64* out), which leaves `out` alone for no player. inline constexpr std::uintptr_t find_player_by_name = 0x834d90, player_persona_id = 0x822170; inline constexpr std::array find_player_by_name_prefix{ 0x48,0x8b,0xc4,0x41,0x54,0x48,0x83,0xec,0x40,0x48,0x89,0x58,0x18,0x4c,0x8b,0xe1,0x48,0x89,0x68}; inline constexpr std::array player_persona_id_prefix{ 0x48,0x89,0x5c,0x24,0x08,0x57,0x48,0x83,0xec,0x20,0x48,0x8b,0xf9,0x48,0x8b,0xda,0x48,0x8d,0x4c}; inline constexpr std::array string_destroy_prefix{ 0x48,0x8b,0x09,0x48,0x8d,0x05,0xaa,0x86,0xd7,0x05,0x48,0x3b,0xc8,0x0f,0x85,0xbd,0x9b,0xff,0xff}; // String assign (dst, chars, length) that GetPlayerName uses for its own empty answer. inline constexpr std::uintptr_t string_assign = 0x1587620; inline constexpr std::array string_assign_prefix{ 0x48,0x89,0x5c,0x24,0x10,0x48,0x89,0x6c,0x24,0x18,0x56,0x57,0x41,0x56,0x48,0x83,0xec,0x20,0x48}; // Data-defined type instances: construct(typeObject, allocator) -> instance, // destroy(typeObject, allocator, instance); the allocator is *event_allocator. inline constexpr std::uintptr_t type_construct = 0x3dd73a0; inline constexpr std::array type_construct_prefix{ 0x48,0x89,0x5c,0x24,0x10,0x48,0x89,0x74,0x24,0x18,0x57,0x48,0x83,0xec,0x30,0x48,0x8b,0x01,0x48}; inline constexpr std::uintptr_t type_destroy = 0x3dd7500; inline constexpr std::array type_destroy_prefix{ 0x48,0x89,0x5c,0x24,0x10,0x57,0x48,0x83,0xec,0x20,0x48,0x8b,0x01,0x49,0x8b,0xd8,0x48,0x8b,0xfa}; inline constexpr std::uintptr_t event_allocator = 0x72f6e78; // GetPlayerIdByName expression native (0b2f3855): u32 (const String* name). Server // handlers name the sender of an event with it (e.g. TurnBasedServer.OnRequestTurnEnd). inline constexpr std::uintptr_t player_id_by_name = 0x854aa0; inline constexpr std::array player_id_by_name_prefix{ 0x40,0x53,0x48,0x83,0xec,0x20,0x48,0x8b,0xd1,0x48,0x8d,0x4c,0x24,0x38,0xe8,0xdd,0x02,0xfe,0xff}; // GetPlayerId expression native (bc02374d): u32 (const PlayerRef*). Handlers that // resolve the sender as GetPlayerId(FindPlayerByName(eid)) end here. // SetLeaderboardPlayerScore expression native (3339e0b8): (Leaderboard*, bool, u32 playerId, // float score). Client realm; sends the row to the server, which trusts playerId. inline constexpr std::uintptr_t leaderboard_score = 0x8109f0; inline constexpr std::array leaderboard_score_prefix{ 0x48,0x89,0x5c,0x24,0x08,0x48,0x89,0x74,0x24,0x10,0x57,0x48,0x83,0xec,0x40,0x48,0x8b,0xd9,0x48}; // Boolean core ops every authored condition goes through: (const bool* a[, const bool* b], bool* out). // Graphs cache these pointers at load, so the functions themselves are replaced. inline constexpr std::uintptr_t bool_and = 0x16e7130, bool_or = 0x16eb6e0, bool_not = 0x16eb600; inline constexpr std::array bool_and_prefix{0x80,0x39,0x00,0x74,0x0a,0x80,0x3a,0x00,0x74}; inline constexpr std::array bool_or_prefix{0x80,0x39,0x00,0x75,0x0a,0x80,0x3a,0x00,0x75}; inline constexpr std::array bool_not_prefix{0x80,0x39,0x00,0x0f,0x94,0xc0,0x88,0x02,0xc3}; // ParseInt expression native (09586973): int (const char* const* text), which is // "mov rcx, [rcx]; jmp [atoi]". Its record's generic and fast entries both call this. inline constexpr std::uintptr_t parse_int = 0x864dc0; inline constexpr std::array parse_int_prefix{0x48,0x8b,0x09,0x48,0xff,0x25,0x7e,0x66,0x78,0x05}; inline constexpr std::uintptr_t player_id = 0x854b90; inline constexpr std::array player_id_prefix{ 0x40,0x53,0x48,0x83,0xec,0x20,0x48,0x8b,0x11,0x48,0x8b,0xd9,0x48,0x85,0xd2,0x0f,0x84,0xb9,0x00}; // Entity component lookup: component* (entity value, const TypeInfo*). SetLeaderboardPlayerScore // finds the activity leaderboard manager (type info 0x7225350) on leaderboard+0x58 with it. inline constexpr std::uintptr_t component_lookup = 0x7215d0, leaderboard_manager_type = 0x7225350; inline constexpr std::array component_lookup_prefix{ 0x40,0x53,0x55,0x56,0x57,0x48,0x81,0xec,0xd8,0x00,0x00,0x00,0x48,0x8b,0x05,0xdd,0x2d,0xaa,0x06}; // The row write behind SetLeaderboardPlayerScore: (manager*, const u64* leaderboard key, bool add, // u32 playerId, float score). The manager keeps its leaderboards' keys at +0x78..+0x80; the // server receives the key's index there. // EventHandle of the event a leaderboard manager belongs to (u32 (manager*)); every row // write carries it and the server checks it. inline constexpr std::uintptr_t leaderboard_event_handle = 0x801860; inline constexpr std::array leaderboard_event_handle_prefix{ 0x40,0x53,0x48,0x83,0xec,0x70,0x48,0x8b,0x05,0x53,0x2b,0x9c,0x06,0x48,0x33,0xc4,0x48,0x89,0x44}; inline constexpr std::uintptr_t leaderboard_write = 0x810a70; inline constexpr std::array leaderboard_write_prefix{ 0x40,0x53,0x55,0x56,0x57,0x48,0x81,0xec,0xb8,0x00,0x00,0x00,0x48,0x8b,0x81,0x80,0x00,0x00,0x00}; // SetMpActivityParticipants (d3618745): (activity component*, const u32 array*). Server realm; // ThrowdownRegistration.QueueFilled passes the queue in join order, which becomes the turn order. // OrderPlayerIdsByParticipants (1781cc70): (participants component*, const u32 array*) rewrites // the replicated participant list (= turn order) into the array's order; TurnBasedServer Round // End calls it with the next round's order (RoundRobin there swaps the first and last player). inline constexpr std::uintptr_t order_participants = 0x813660; inline constexpr std::array order_participants_prefix{ 0x40,0x55,0x53,0x57,0x48,0x8d,0x6c,0x24,0xd0,0x48,0x81,0xec,0x30,0x01,0x00,0x00,0x48,0x8b,0x05}; inline constexpr std::uintptr_t set_participants = 0x811de0; inline constexpr std::array set_participants_prefix{ 0x40,0x55,0x53,0x41,0x55,0x48,0x8d,0x6c,0x24,0x80,0x48,0x81,0xec,0x80,0x01,0x00,0x00,0x48,0x8b}; }