Files
AyeZeeBB 30a320ff62 Throwdowns: a grouped line score is no longer cut at its first separator
A Jam Session takes the score of the line just landed from the score HUD's
text, with the script native ParseInt, which is the C library's atoi. atoi
stops at the first character that is not a digit, so a line shown as 5,432
was read as 5 and added 5 to the player's total. Reported for Jam Sessions
and Spot Battles: lines of 5,000 and more adding one or two points.

ParseInt now reads groups of three digits whole, set apart by a comma, a
full stop, an apostrophe or a space: "5,432" is 5432. Text that is not a
grouped number is read exactly as before. The first few grouped scores are
logged, to confirm the cause in play.
2026-10-13 01:14:01 -05:00

187 lines
14 KiB
C++

#pragma once
#include <array>
#include <cstdint>
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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<u32>* added, const vector<u32>* 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 9> bool_and_prefix{0x80,0x39,0x00,0x74,0x0a,0x80,0x3a,0x00,0x74};
inline constexpr std::array<unsigned char, 9> bool_or_prefix{0x80,0x39,0x00,0x75,0x0a,0x80,0x3a,0x00,0x75};
inline constexpr std::array<unsigned char, 9> 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<unsigned char, 10> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> 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<unsigned char, 19> set_participants_prefix{
0x40,0x55,0x53,0x41,0x55,0x48,0x8d,0x6c,0x24,0x80,0x48,0x81,0xec,0x80,0x01,0x00,0x00,0x48,0x8b};
}