mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-17 19:47:08 +02:00
Follow-ups to the trainer (PR 37), and one multiplayer change.
Off until asked for (Extension/Trainer)
- The jump read-out and the LB+RB controller shortcuts start off. Jumps
are logged only while the read-out or telemetry recording is on, and
trick launches only when the trainer scaled them. A saved trainer.json
keeps what the player chose.
Memory search on demand (trainer.cpp, trainer_classes.cpp)
- The search for the game's tuning classes reads all writable memory.
It ran for every player after a level loaded, and up to seven times
when it found nothing. It now runs only when a class value or the flip
speed is not the game's own (the player's, or a host's they skate
with) or the EVERYTHING list is open, and at most three times a level.
- For those players it runs again on each level, which brings fresh
copies; a search from an earlier level used to count as done.
Guests under enforced physics
- A guest is locked by the session's enforce setting, from the moment
of joining (Engine/Game/Multiplayer/session_physics.h), not by whether
the enforcement status text was set yet.
- A guest's class values no longer come back after a map change.
The host's whole setup reaches its guests (protocol 39)
- Only Gameplay/SkatePhysicsTuning travelled, so a host could push,
sprint or jump further than the guests it held to the game's own.
- New packet physics_extras (30): the host's class values, trick
multipliers and auto push (trainer_session.h), sent when they change
and to players who join later, taken from the host only. A dedicated
server's are the game's own and it ignores the packet.
- Under enforcement a guest's own trick multipliers stand down for the
host's, whatever the boosts switch says. With enforcement off nothing
changes.
- A guest refuses bytes that are not an encoding, holds values to the
trainer's own ranges, and leaves out class values written for another
game build's table.
- protocol_version 38 -> 39: released versions disconnect from a peer
that sends a packet they cannot decode.
Out-of-view players are posed every frame again (Session/session.cpp)
- Players outside the camera's view and past 8 m were sampled at 20 Hz
(b763631). The game's replays record each skater as it stood every
frame and their camera looks anywhere, so those players moved at
20 Hz in replays. Removed; the distance rule (20 Hz past 200 m, 10 Hz
past 350 m) stays. This gives back the client-tick time it saved on
busy servers.
61 lines
3.1 KiB
C++
61 lines
3.1 KiB
C++
#pragma once
|
|
// The game keeps much of its tuning outside Gameplay/SkatePhysicsTuning, in data-defined classes
|
|
// (push speeds, on-foot jumps, flips and rolls, dive and glide, bail speeds...). Their defaults
|
|
// and field order ship in the game's data (trainer_classes.inc); a live copy has no name to look
|
|
// up, so it is found by searching writable memory for the class's defaults laid out as the
|
|
// class lays them out. Game thread, except the search itself, which runs on its own thread.
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <string>
|
|
|
|
namespace dingosdk::trainer {
|
|
struct ClassField {
|
|
const char *name;
|
|
float stock;
|
|
std::uint16_t offset;
|
|
// The game was seen reading it (hardware read watches on every copy) while a scripted skater
|
|
// rode, pushed, ollied, flipped, ran, jumped and sprinted, or while a player ground, pumped,
|
|
// climbed, vaulted and bailed; or its effect was measured. False: no read turned up in any
|
|
// of that, and no other copy of the numbers was found in memory.
|
|
bool seen;
|
|
};
|
|
struct ClassSpec {
|
|
const char *group; // shown in the menu
|
|
const char *key; // in value ids: "<key>.<field>"
|
|
std::uint16_t first, count, anchor;
|
|
};
|
|
#include "trainer_classes.inc"
|
|
inline constexpr std::size_t class_count = sizeof(class_specs) / sizeof(class_specs[0]);
|
|
inline constexpr std::size_t class_field_count = sizeof(class_fields) / sizeof(class_fields[0]);
|
|
|
|
// Starts a search for every class's live copies unless one is running. Copies found earlier
|
|
// that still hold what the trainer last wrote are kept.
|
|
void find_classes() noexcept;
|
|
bool finding_classes() noexcept;
|
|
// How many searches have finished (0: none yet).
|
|
std::uint64_t class_searches() noexcept;
|
|
// Copies of class `index` found.
|
|
std::size_t class_copies(std::size_t index) noexcept;
|
|
// What field `field` (an index into class_fields) should hold. Written by apply_classes.
|
|
void want_class_value(std::size_t field, float value) noexcept;
|
|
// Whether anything is wanted that is not the game's own (a field, or the flip speed): until
|
|
// then there is nothing to write and no reason to search.
|
|
bool classes_wanted() noexcept;
|
|
// Writes the wanted values into every copy found; call each tick. Returns the fields written.
|
|
std::size_t apply_classes() noexcept;
|
|
std::string classes_summary();
|
|
// Board flip trick speed. The game's flip trick tuning is a class of eight curves and no numbers
|
|
// (speed against the flick, against the ollie...); the search finds it as eight curve references
|
|
// in a row and apply_classes multiplies the outputs of its four speed curves by this.
|
|
void want_flip_speed(float factor) noexcept;
|
|
// How many flip trick speed curves were found (0: the multiplier does nothing yet).
|
|
std::size_t flip_curves() noexcept;
|
|
// Where field `field` (an index into class_fields) lives: each copy's address and kind ('c' the
|
|
// class's own layout, 's' the eight-byte slots, 'n' native code's copy). Returns how many.
|
|
struct FieldCopy {
|
|
std::uintptr_t address{};
|
|
char kind{};
|
|
};
|
|
std::size_t class_field_copies(std::size_t field, FieldCopy *out, std::size_t capacity) noexcept;
|
|
} // namespace dingosdk::trainer
|