mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-19 20:05:24 +02:00
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.
187 lines
14 KiB
C++
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};
|
|
}
|