mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-24 19:26:18 +02:00
The SDK knew grind exits: reskate.skater.grind_exit took a toe/heel/left/right wish, and C++ worked
out the rail's direction, toe and heel from the stance and facing, the 1.8 m/s and the strength.
That logic is now the grind-exits mod's own Lua (plugin/exits.lua, kept on this machine). What has
to run on the physics thread is general:
- Extension/Skater/launches: every launch of the local skater (ollie, grind, no_comply, boneless),
classified by its call site and the state before it, with the board's direction of travel; the
`launch` event for plugins with events.skater; reskate.skater.shape_launch(from, {across, along,
up}) sets those speeds against the travel, one plugin a kind.
- reskate.skater.get() gains `right` (the root's right axis) and `switch` (the game's stance flag).
- Extension/Skater/pad_hide: reskate.input.hide's pad filter, out of the old grind exit file.
Removed: reskate.skater.grind_exit, the grind_exit event, GrindExitWish and GrindPop.
Physics state 701 is a grind too (the game checks it with 400 in about a dozen places; the
2026-10-11 measurement only reached the 400s): pops out of it were dropped, and skater_state called
it "other". Launches, skater_state ("grinding") and the trainer's grind pop all count it now.
Tests: the grind-exits plugin test drives the new path (11 checks of its own).
69 lines
2.9 KiB
C++
69 lines
2.9 KiB
C++
#include "pad_hide.h"
|
|
#include "launches.h"
|
|
#include "Extension/UI/Overlay/overlay.h"
|
|
#include <atomic>
|
|
#include <map>
|
|
#include <mutex>
|
|
#include <string>
|
|
|
|
namespace dingosdk::pad_hide {
|
|
namespace {
|
|
struct Control {
|
|
std::mutex mutex;
|
|
std::map<std::string, Hidden, std::less<>> hidden;
|
|
std::atomic<bool> lt{}, rt{}, left_x{}, right_stick{}, l3{}, r3{};
|
|
};
|
|
Control& control() {
|
|
static auto* value = new Control; // process lifetime: the game polls its pad until exit
|
|
return *value;
|
|
}
|
|
// Any thread the game polls its pad from.
|
|
void filter_pad(unsigned, overlay::GamepadValues& pad) noexcept {
|
|
auto& c = control();
|
|
if (c.lt.load(std::memory_order_acquire)) pad.left_trigger = 0;
|
|
if (c.rt.load(std::memory_order_acquire)) pad.right_trigger = 0;
|
|
if (c.left_x.load(std::memory_order_acquire) && launches::grinding()) pad.left_x = 0;
|
|
if (c.right_stick.load(std::memory_order_acquire)) pad.right_x = pad.right_y = 0;
|
|
if (c.l3.load(std::memory_order_acquire)) pad.buttons &= static_cast<std::uint16_t>(~0x0040u); // XINPUT_GAMEPAD_LEFT_THUMB
|
|
if (c.r3.load(std::memory_order_acquire)) pad.buttons &= static_cast<std::uint16_t>(~0x0080u); // XINPUT_GAMEPAD_RIGHT_THUMB
|
|
}
|
|
void publish(Control& c) {
|
|
Hidden all;
|
|
for (const auto& [owner, h] : c.hidden) {
|
|
all.left_trigger = all.left_trigger || h.left_trigger;
|
|
all.right_trigger = all.right_trigger || h.right_trigger;
|
|
all.left_x_grinding = all.left_x_grinding || h.left_x_grinding;
|
|
all.right_stick = all.right_stick || h.right_stick;
|
|
all.left_stick_click = all.left_stick_click || h.left_stick_click;
|
|
all.right_stick_click = all.right_stick_click || h.right_stick_click;
|
|
}
|
|
c.lt.store(all.left_trigger, std::memory_order_release);
|
|
c.rt.store(all.right_trigger, std::memory_order_release);
|
|
c.left_x.store(all.left_x_grinding, std::memory_order_release);
|
|
c.right_stick.store(all.right_stick, std::memory_order_release);
|
|
c.l3.store(all.left_stick_click, std::memory_order_release);
|
|
c.r3.store(all.right_stick_click, std::memory_order_release);
|
|
DingoSDKOverlaySetGamepadFilter(c.hidden.empty() ? nullptr : &filter_pad);
|
|
}
|
|
} // namespace
|
|
|
|
bool available() noexcept { return launches::available(); }
|
|
void hide(std::string_view owner, Hidden hidden) {
|
|
if (!available()) return;
|
|
if (hidden.left_x_grinding) (void)launches::grinding(); // the physics steps followed from now on
|
|
auto& c = control();
|
|
std::lock_guard lock(c.mutex);
|
|
if (hidden.any()) c.hidden.insert_or_assign(std::string(owner), hidden);
|
|
else if (const auto found = c.hidden.find(owner); found != c.hidden.end()) c.hidden.erase(found);
|
|
publish(c);
|
|
}
|
|
void release(std::string_view owner) {
|
|
auto& c = control();
|
|
std::lock_guard lock(c.mutex);
|
|
if (const auto found = c.hidden.find(owner); found != c.hidden.end()) {
|
|
c.hidden.erase(found);
|
|
publish(c);
|
|
}
|
|
}
|
|
}
|