mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-24 19:26:18 +02:00
Plugins register modes (card, replaces, order, flag, players) and publish documents through reskate.throwdowns.ui: the setup page, the waiting card, HUD slots themed on the game's HUD_<theme>_* widgets, the match panel, flags and match restrictions. SmokeyDawg58's native plumbing (throwdown_menu.cpp and its .inl files) renders them and posts throwdown_ui events back. kit::flag is the one native flag registration. General services added for it: reskate.files, reskate.ui.dialog, reskate.skater push/hold/bone_cam, reskate.camera.pad_flight, reskate.physics competition, reskate.session.world, reskate.tricks feed/gesture, and world entities. His ten modes are now Lua in his plugin: the rules, referee and wire (td/rules, referee, wire), and every page and HUD document (td/ui*.lua). Extension/Modes and reskate.modes are gone, along with every race and 1-UP branch in the SDK. The plugin test drives each mode through kit events. A native setup page is never written to while it closes into flag placement: its rows are not republished, the stock page is put back once the exit is over, and the stock Players slider is left alone while a plugin flag is out. This fixes the crashes on the Deathrace button and on 1-UP's Confirm.
64 lines
2.2 KiB
C++
64 lines
2.2 KiB
C++
#include "skater_push.h"
|
|
#include <Windows.h>
|
|
#include <algorithm>
|
|
#include <atomic>
|
|
#include <cmath>
|
|
#include <mutex>
|
|
|
|
namespace dingosdk::skater_push {
|
|
namespace {
|
|
// A queued request is not delivery: bail/teleport physics may still be busy or have replaced the
|
|
// body, so a push stays pending until the physics step acknowledges it, or two seconds pass.
|
|
struct Delivery {
|
|
std::mutex mutex;
|
|
std::optional<Vec3> pending;
|
|
std::uint64_t until{};
|
|
std::atomic<bool> held{};
|
|
void clear() noexcept { pending.reset(); until = 0; }
|
|
};
|
|
Delivery& delivery() { static auto* value = new Delivery; return *value; }
|
|
} // namespace
|
|
bool valid(const Vec3& velocity) noexcept {
|
|
return std::all_of(velocity.begin(), velocity.end(), [](float n) { return std::isfinite(n); }) && velocity[1] == 0.f &&
|
|
std::hypot(velocity[0], velocity[2]) <= max_speed + .001f;
|
|
}
|
|
void request(const Vec3& velocity) noexcept {
|
|
auto& d = delivery();
|
|
std::lock_guard lock(d.mutex);
|
|
d.clear();
|
|
if (valid(velocity)) { d.pending = velocity; d.until = GetTickCount64() + 2000; }
|
|
}
|
|
void wait() noexcept {
|
|
auto& d = delivery();
|
|
std::lock_guard lock(d.mutex);
|
|
const auto now = GetTickCount64();
|
|
if (d.pending && now < d.until) d.until = now + 2000;
|
|
}
|
|
void reset() noexcept {
|
|
auto& d = delivery();
|
|
std::lock_guard lock(d.mutex);
|
|
d.clear();
|
|
}
|
|
void hold(bool on) noexcept { delivery().held.store(on, std::memory_order_release); }
|
|
bool holding() noexcept { return delivery().held.load(std::memory_order_acquire); }
|
|
bool pending() noexcept {
|
|
auto& d = delivery();
|
|
std::lock_guard lock(d.mutex);
|
|
if (GetTickCount64() >= d.until) d.clear();
|
|
return d.pending.has_value();
|
|
}
|
|
std::optional<Vec3> peek() noexcept {
|
|
auto& d = delivery();
|
|
std::lock_guard lock(d.mutex);
|
|
if (GetTickCount64() >= d.until) d.clear();
|
|
// A pending push wins over the hold: "hold still, then push" needs no release in between.
|
|
if (d.pending) return d.pending;
|
|
return holding() ? std::optional(Vec3{}) : std::nullopt;
|
|
}
|
|
void accepted(const Vec3& velocity) noexcept {
|
|
auto& d = delivery();
|
|
std::lock_guard lock(d.mutex);
|
|
if (d.pending && *d.pending == velocity) d.clear();
|
|
}
|
|
} // namespace dingosdk::skater_push
|