Trainer: revert boost also for landings out of line with the direction of travel

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
andrewnakasandClaude Opus 5.5 committed 2026-10-06 11:49:15 -06:00
1 parent 1c62ea4f36
commit 5bd986e258
5 files changed
+18 -6

No files matched your search

+13 -4
View File
@@ -312,6 +312,10 @@ void trainer_push_speed(std::uintptr_t core) noexcept {
// land with the board 1-3 degrees off the body, auto reverts 71-130 degrees off.
constexpr float revert_min_spin = 90.0f; // degrees the skater turned in the air
constexpr float revert_min_board_offset = 40.0f; // board out of line with the body (forward or fakie) at touchdown
// The other revert, and the common one (measured 2026-10-06: twelve spins of 90 to 120 degrees all
// landed with the board 0 to 3 degrees off the body): board and body together out of line with the
// direction of travel, which the game then swings round. A clean 180 lands in line and gets nothing.
constexpr float revert_min_slip = 12.0f;
constexpr float revert_max_speed = 40.0f; // m/s (144 km/h): no boost above this
constexpr ULONGLONG revert_min_air_ms = 250, revert_max_age_ms = 400, revert_cooldown_ms = 500;
// How much, at strength 1, from how far the board turned relative to the body over the flight:
@@ -378,10 +382,15 @@ void trainer_revert_boost(std::uintptr_t core) noexcept {
const float spin = std::abs(landing.spin_degrees);
const float board_rotation = landing.board_valid ? std::abs(landing.board_spin_degrees - landing.spin_degrees) : 0.0f;
const float speed = std::hypot(velocities[0][0], velocities[0][2]);
// Out of line with the travel, forward or fakie: 0 = lined up, 90 = sideways.
float slip = 0.0f;
if (std::isfinite(speed) && speed >= 1.0f) {
slip = std::fmod(std::abs(landing.heading_degrees - std::atan2(velocities[0][0], velocities[0][2]) * 57.29578f), 180.0f);
slip = std::min(slip, 180.0f - slip);
}
const float added = std::isfinite(speed) ? std::min(revert_boost_amount(board_rotation) * strength, revert_max_speed - speed) : 0.0f;
const char *outcome = !landing.board_valid ? "no boost: the board's pose could not be read"
: spin < revert_min_spin ? "no boost: under 90 degrees of spin"
: board_offset < revert_min_board_offset ? "no boost: the board landed in line (a clean landing)"
const char *outcome = spin < revert_min_spin ? "no boost: under 90 degrees of spin"
: (!landing.board_valid || board_offset < revert_min_board_offset) && slip < revert_min_slip ? "no boost: the board landed in line (a clean landing)"
: landing.to < 100 || landing.to >= 200 || bodies.offboard ? "no boost: not riding"
: now < landing.landed_at || now - landing.landed_at > revert_max_age_ms ? "no boost: seen too late"
: landing.air_ms < revert_min_air_ms ? "no boost: too short a flight"
@@ -390,7 +399,7 @@ void trainer_revert_boost(std::uintptr_t core) noexcept {
: "boost";
const bool fire = std::string_view(outcome) == "boost";
AcquireSRWLockExclusive(&r.report_lock);
r.report = {r.report.sequence + 1, spin, board_offset, board_rotation, speed, fire ? added : 0.0f, static_cast<std::uint32_t>(landing.air_ms),
r.report = {r.report.sequence + 1, spin, board_offset, board_rotation, slip, speed, fire ? added : 0.0f, static_cast<std::uint32_t>(landing.air_ms),
landing.to, landing.board_valid, outcome};
ReleaseSRWLockExclusive(&r.report_lock);
if (!fire) return;
+1
View File
@@ -33,6 +33,7 @@ void set_revert_boost(std::uintptr_t client, std::uintptr_t entity, float streng
struct RevertBoostReport {
std::uint64_t sequence{}; // one more per landing judged; 0: none yet
float spin{}, board_offset{}, board_rotation{}; // degrees
float slip{}; // degrees the board landed out of line with the direction of travel
float speed{}, added{}; // m/s
std::uint32_t air_ms{}, landed_state{};
bool board_read{};
+1
View File
@@ -140,6 +140,7 @@ void track_spin(std::uintptr_t selector, std::uint32_t chosen) noexcept {
landing.board_spin_degrees = s.board_spin * 180.0f / pi;
landing.board_valid = s.board_ok;
landing.board_offset_degrees = wrap(board_yaw - yaw) * 180.0f / pi;
landing.heading_degrees = (s.board_ok ? board_yaw : yaw) * 180.0f / pi;
landing.from = s.last_air;
landing.to = chosen;
landing.steps = s.steps;
+1
View File
@@ -35,6 +35,7 @@ struct RevertLanding {
float spin_degrees{}; // signed turn about the vertical axis from takeoff to landing
float board_spin_degrees{}; // the same for the board's deck (if board_valid)
float board_offset_degrees{}; // the deck's heading minus the skater's at touchdown (if board_valid)
float heading_degrees{}; // where the deck (the skater, without a deck pose) points at touchdown: 0 = +Z, as atan2(x, z)
bool board_valid{};
std::uint32_t from{}, to{}; // the last air state, and the state chosen on landing
std::uint32_t steps{}; // physics steps in the air
+2 -2
View File
@@ -1747,9 +1747,9 @@ void tick(std::uintptr_t base, std::uintptr_t client, bool playing, const std::s
// Every landing with some spin in it, boosted or not, so a report can say why not.
if ((s.hud_jump || s.logging) && report.spin >= 30.0f)
say(logging::Level::info,
std::format("Trainer revert: landed after {} ms with {:.0f} deg of spin, board {} off the body, board turned {:.0f} deg past the body, state {}, "
std::format("Trainer revert: landed after {} ms with {:.0f} deg of spin, board {} off the body and {:.0f} deg off the travel, board turned {:.0f} deg past the body, state {}, "
"{:.1f} m/s: {}{}.",
report.air_ms, report.spin, report.board_read ? std::format("{:.0f} deg", report.board_offset) : std::string("unread"),
report.air_ms, report.spin, report.board_read ? std::format("{:.0f} deg", report.board_offset) : std::string("unread"), report.slip,
report.board_rotation, report.landed_state, report.speed, report.outcome,
report.added > 0 ? std::format(" +{:.1f} m/s", report.added) : std::string()));
}