From 5bd986e258c6dcbc9aa35677337bca5479ecbc0c Mon Sep 17 00:00:00 2001 From: andrewnakas Date: Tue, 6 Oct 2026 11:49:15 -0600 Subject: [PATCH] Trainer: revert boost also for landings out of line with the direction of travel Co-Authored-By: Claude Opus 5.5 (1M context) --- Extension/Skater/client_noclip.cpp | 17 +++++++++++++---- Extension/Skater/client_source_spawn.h | 1 + Extension/Skater/no_bail.cpp | 1 + Extension/Skater/no_bail.h | 1 + Extension/Trainer/trainer.cpp | 4 ++-- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Extension/Skater/client_noclip.cpp b/Extension/Skater/client_noclip.cpp index 815a098a..8d108706 100644 --- a/Extension/Skater/client_noclip.cpp +++ b/Extension/Skater/client_noclip.cpp @@ -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(landing.air_ms), + r.report = {r.report.sequence + 1, spin, board_offset, board_rotation, slip, speed, fire ? added : 0.0f, static_cast(landing.air_ms), landing.to, landing.board_valid, outcome}; ReleaseSRWLockExclusive(&r.report_lock); if (!fire) return; diff --git a/Extension/Skater/client_source_spawn.h b/Extension/Skater/client_source_spawn.h index ab541864..cfbe7fdf 100644 --- a/Extension/Skater/client_source_spawn.h +++ b/Extension/Skater/client_source_spawn.h @@ -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{}; diff --git a/Extension/Skater/no_bail.cpp b/Extension/Skater/no_bail.cpp index 2a3d7e10..859ca7e8 100644 --- a/Extension/Skater/no_bail.cpp +++ b/Extension/Skater/no_bail.cpp @@ -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; diff --git a/Extension/Skater/no_bail.h b/Extension/Skater/no_bail.h index 0ae61b7e..1f206ff1 100644 --- a/Extension/Skater/no_bail.h +++ b/Extension/Skater/no_bail.h @@ -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 diff --git a/Extension/Trainer/trainer.cpp b/Extension/Trainer/trainer.cpp index 33027819..dc5462c7 100644 --- a/Extension/Trainer/trainer.cpp +++ b/Extension/Trainer/trainer.cpp @@ -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())); }