Trainer: Grind lock-on is the game's own Grind Assist

The GRINDS section's Grind lock-on row now shows and sets egf_grindassistamount,
the same number as the game's Settings menu (trainer grind assist <0-100>). It
is the player's own setting: never MODIFIED, in no preset or reset. Sticky
Grinds stays as a switch; the lock-on tuning values are rows of their own.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
andrewnakasandClaude Opus 5.5 committed 2026-10-24 15:50:40 -06:00
1 parent 96aa7ea6e8
commit fe0db52d2b
5 files changed
+41 -3

No files matched your search

+17 -1
View File
@@ -245,6 +245,7 @@ struct State {
return a;
}();
std::uint64_t tr_option_at{};
int grind_assist{-1}; // the game's own Grind Assist (grind_assist_setting), read with the options above
// What the player's own game settings hold for the settings the trainer can force (read with the options above):
// a row that is not forced shows this, not the game's default.
std::array<std::int8_t, grind_settings.size()> grind_own = [] {
@@ -2289,6 +2290,10 @@ void drive_transition(std::uintptr_t base, std::uintptr_t client, std::uint64_t
if (now >= s.tr_option_at) {
// The game's own options: whatever its Settings menu (or the trainer) last set.
s.tr_option_at = now + 500;
if (const auto held = profile_runtime::local_game_option(grind_assist_setting); (held ? static_cast<int>(std::lround(*held)) : -1) != s.grind_assist) {
s.grind_assist = held ? static_cast<int>(std::lround(*held)) : -1;
s.view_due = true;
}
for (std::size_t i = 0; i < transition_options.size(); ++i) {
const auto held = profile_runtime::local_game_option(transition_options[i].setting);
const int value = held ? static_cast<int>(std::lround(*held)) : transition_options[i].stock;
@@ -2531,6 +2536,7 @@ void build_view() {
next->grind_own = s.grind_own;
next->tr_own = s.tr_own;
next->tr_option = s.tr_option;
next->grind_assist = s.grind_assist;
next->offboard_height = s.offboard_height;
next->flip_speed = s.flip_speed;
next->underflip_speed = s.underflip_speed;
@@ -3398,8 +3404,18 @@ std::string run(std::string_view verb, const std::vector<std::string> &a) {
if (v == "transition") return transition_command(a);
if (v == "foot") return foot_command(a);
if (v == "grind") {
// trainer grind | grind watch 0|1 | grind side <x> | grind <key>|all game|off|on
// trainer grind | grind watch 0|1 | grind side <x> | grind assist <0-100> | grind <key>|all game|off|on
const auto what = lower(arg(0)), to = lower(arg(1));
if (what == "assist") {
// The player's own game setting, as its Settings menu sets it: in any session, never part of presets or resets.
const auto value = number(to);
if (!value || !(*value >= 0 && *value <= 100)) return "error: usage: trainer grind assist <0 to 100> (the game's own Grind Assist)";
if (!profile_runtime::set_local_game_option(grind_assist_setting, std::round(*value), false)) return "error: the game's settings are not ready yet.";
s.grind_assist = static_cast<int>(std::lround(*value));
s.tr_option_at = 0; // read back from the game on the next tick
s.view_due = true;
return std::format("Grind Assist (the game's own setting) is {}.", s.grind_assist);
}
const auto word = [](std::int8_t value) { return value < 0 ? "-" : value ? "on" : "off"; };
if (what.empty()) {
std::string out = std::format("Side force off grinds x {:.2f}.", s.grind_side);
+1
View File
@@ -137,6 +137,7 @@ struct View {
bool tr_spine{};
std::array<std::int8_t, transition_settings.size()> tr_setting{};
std::array<int, transition_options.size()> tr_option{}; // the game's own options, as the game holds them now
int grind_assist{-1}; // the game's own Grind Assist as the game holds it (-1: not saved in the profile yet)
// What the player's own game settings hold for the settings the trainer can force (0 off / 1 on).
std::array<std::int8_t, grind_settings.size()> grind_own{};
std::array<std::int8_t, transition_settings.size()> tr_own{};
+2
View File
@@ -272,6 +272,8 @@ struct TransitionOption {
int stock{}; // the game's default
int low{}, high{};
};
// The game's own Grind Assist (its Settings menu): what the trainer's Grind lock-on row shows and sets, 0 to 100.
inline constexpr std::string_view grind_assist_setting = "egf_grindassistamount";
inline constexpr std::array<TransitionOption, 3> transition_options{{
{"pumpassist", "Pump assist", "The game's own Pump Assist: how much of a pump you get without pressing for it. The game takes the larger of your left stick and this, "
"so at its default of 85 the stick only adds the last 15 percent. 0 is fully manual: no press, no pump. Skate 3 gave about 70 percent of a pump by "
+20 -1
View File
@@ -1088,10 +1088,29 @@ void topic_body(SkateMenu &menu, const Model &model, const CallbacksV3 &callback
ImGui::EndDisabled();
from_trickline({"trick-pops", "trick-spins"});
break;
case trainer::topic_grinds:
case trainer::topic_grinds: {
// Grind lock-on is the game's own Grind Assist: the same number as its Settings menu, changed from either place. Never
// MODIFIED, in no preset or reset, and the player's own in any session (the owner's ask, 2026-10-24).
ImGui::PushID("grind-assist");
const char *help = "Your game's own Grind Assist, the same number as in its Settings menu: change it here or there. How much the game "
"helps the board onto a rail or ledge. It is your setting, so it never counts as MODIFIED and no preset or reset "
"changes it. The lock-on distance, the reach from the air and the lock-on speeds and angle are the game's tuning "
"values, in the rows of this section.";
field(menu, "Grind lock-on (GAME SETTING: Grind Assist)", help);
if (view.grind_assist < 0) {
ImGui::TextDisabled("not saved yet: set it once in the game's Settings");
} else {
double assist = view.grind_assist;
ImGui::BeginDisabled(!callbacks.queue_console_command);
if (slider_double("##assist", &assist, 0.0, 100.0, "%.0f")) trainer_command(menu, callbacks, std::format("grind assist {:.0f}", assist));
ImGui::EndDisabled();
}
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) wrapped_tooltip("%s", help);
ImGui::PopID();
from_trickline({"grind-feel", "grind-stick", "grind-exits"});
dials_card(menu, callbacks, p, view, topic, can_edit);
break;
}
case trainer::topic_trickline:
from_trickline({"trickline", "trick-revert"});
// Dark Pop is ReSkate's own switch (not a tuning value), so it is live even where the tuning is locked.
+1 -1
View File
@@ -365,7 +365,7 @@ PresetDial preset_dial(std::string_view name) {
{"Fast Flips", "Body flip speed", topic_pop},
{"Fast Spins", "Body spin speed", topic_pop},
{"Hard To Bail", "Bail resistance (higher: harder to bail)", topic_bails},
{"Sticky Grinds", "Grind lock-on", topic_grinds},
{"Sticky Grinds", "", topic_grinds}, // a switch: Grind lock-on is the game's own Grind Assist (the owner's ask, 2026-10-24)
{"Slick Grinds", "Grind friction", topic_grinds},
{"Moon Jump", "On foot: jump height", topic_foot},
{"Fast On Foot", "On foot: sprint speed", topic_foot},