Every export was forced to 100 Mbps, about 750 MB per minute of replay, whichever quality
was chosen. The bitrate patch is removed; the frame pacing fix stays.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Underflip speed: the game holds the underflip's two playback rate controllers
(cdbchooser_onboard_underflips_(pbrate) 1-1.2, ..._toair(pbrate) 0.6-1.2) to a band it
copies into each controller as it is made; the trainer scales that band, and the state
copy that starts the underflip, so the slider sets the whole underflip.
- Underflip part only: the band spans the flip's speed and Underflip speed from the start;
where the board turns back the trainer scales the rate the game computes for its rate
controllers every tick (0x10dd2f0, called by their update 0x10de730) until the landing.
- A speed for each underflip at the bottom of Advanced trick speed (kickflip, heelflip, pop
shuvit, FS pop shuvit and the four impossible underflips), times Underflip speed, and the
Late flip slider beside them.
- Late flip speed in the TRICKS card; dial sliders reach 0; Underflip speed named on the
MODIFIED line and shared by a session's host (session extras version 2).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A preset's dial refused 0 in its box and in `trainer dial` (it works on a log scale). A factor of
0 now sets every value the dial moves to 0; a value that moves the other way stays stock instead
of going to infinity.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011m6eM3ps6bttTbZqo9Gz6Y
The game plans each flight's landing with its own gravity and the air pose reaches for the ground
as that countdown runs out. Above x1 the skater came down early, the body sank into the ground
before the wheels touched and the landing came late (x3: a flat ollie bailed). The countdown is
now set to this flight's time down to the planned height at the trainer's gravity.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011m6eM3ps6bttTbZqo9Gz6Y
MY MODS: a table with an animated drag for the load order, a conflicts bar with Check conflicts, and a Resolve popup whose choices are kept. The check runs at startup and after changes; conflicts no longer show as problems, block Play, or hold mod files during an update.
Conflicts: only game EBX that cannot be combined, or Lua scripts with different versions; colourways and same-name additions are not conflicts.
Official mods: installed in Mods/<Namespace-Name> and turned on or off through mods.json, so they show in MY MODS; the old .reskate-official folder is moved over.
Merge: a scan cache (Mods/.reskate-scan.txt) keeps each unchanged mod's repair, mesh and texture scans, so big maps are not re-read every merge.
Launcher: an announcement from the backend shows under STATUS, with HIDE.
The device-removal watcher always runs, and the fatal handler notes a DXGI stop in gpu-breadcrumbs.txt. Crash reports carry a gpu.breadcrumbs tag (protocol 5).
The forward, up and off-board up boost speeds defaulted to +20, which counted as not
stock. They now default to 0: the boost adds nothing until a speed is set, and resets
(RESET EVERYTHING, the console resets, restore_debug) put them back to 0.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Forward, up and off-board up boosts take a typed value up to 10000 (sliders still end
at 300 / 25), Revert Boost strength up to x100. Noclip, No Bail, Dark Pop, a boost
that is not +20, Revert Boost, grind exit triggers and Board Break are listed at the
top of QUICK SETTINGS with their values (Go to, Reset), make the SANDBOX line say
MODIFIED, and RESET EVERYTHING turns them back.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Full screen sliders (stepper): a click still steps, press and move slides the
value; a number box beside each (the controller's focus skips it). A typed
value past a slider's end stays there, and stepping does not snap it back.
- No slider end is a limit for a typed number: game speed, return delay, the
full screen value rows (their bar now spans 0 to 4x the game's own), and the
trainer's own limits behind the commands (gravity 0.001 to 1000, flip speed to
1000, pump power and bending boost to 1e6, transition and grind numbers, the
bending rules).
- Help: the 74 named rows that had none now explain themselves; every slider's
explanation shows on hover and in the full screen bottom bar; unnamed rows
say what they are.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Where two mods change one of the game's assets in ways that cannot both be
in the game (a resource or chunk changed differently, an EBX whose changes
cannot be combined, different assets added under one name), the one lower
in the load order is left out whole, so neither loads half its changes.
The merge used to keep the higher copy of each asset and lose the rest of
the lower mod's change silently, which broke Skaterize beside deckorate.
A check before the merge (find_conflicts) reads only the bundles two or
more mods ship and applies the merge's rule: about 2 s for 296 mods, on
several threads, each mod's copy of a bundle by itself. When it finds
conflicts nothing is built, the catalog leaves the losing mods out and
merges once. The merge keeps its own check behind it, tracking per asset
the last change a mod made itself, so a change carried through other mods'
copies is still caught. A conflict is remembered in .reskate-excluded.json
with the mod it lost to, and stays out while both are unchanged and the
winner still loads above it.
The launcher says "Checking the mods" and "Checking the mods for
conflicts" during those steps. Its mod problems screen says MOD CONFLICT
when that is all there is, and the Mod Manager shows a CONFLICT badge, an
N CONFLICTS banner, a Conflicts filter and, on the mod, which mod it lost
to and how to load it instead.
The trainer keeps upstream's page and naming (SANDBOX; noclip, No Bail and
the boosts on Skater > Cheats; the full screen controller menu) with its own
TUNE sections, presets card and search inside. The MOVEMENT tab is gone:
`trainer open movement` opens Skater > Cheats, where the Revert Boost rows
now sit. Upstream's Hardcore preset sits beside Realistic; saving
trainer.json and reading the map file stay off the client thread.
Board Break's wear and the trainer no longer undo each other: wear writes
four tuning values itself, and every trainer write used to put them back to
the trainer's copy (and a level loaded on a worn board took them as stock).
board_break::handling_value() tells the trainer what wear wants; values the
player has not changed are handed back to it, their stock is the game's own.
Tests: Hardcore's check follows the sections (topic, not the old lists);
the session test pokes a flip speed past the trainer's own limit (100).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
UNINSTALL, under OPEN FOLDER, takes the mod's stamp away first (a folder
without it is no mod to the game), then its folder, and clears whether it
was turned off so an install brings it back on. The card says UNINSTALLING
meanwhile, and UNINSTALL FAILED when Windows keeps the files (Skate still
running). Cards are as tall as their buttons.
The launcher still reads the list at start and looks up each mod's latest
version, moves in a copy installed from Thunderstore and takes away retired
mods, but it downloads nothing by itself. Each card on the OFFICIAL tab says
NOT INSTALLED, INSTALLED, UPDATE AVAILABLE, DOWNLOADING or UPDATING, with an
INSTALL or UPDATE TO vX button (official_mods::install, on a thread of its
own), OPEN FOLDER once installed, and the On / Off switch beside its pills.
The banner counts how many are installed. Play waits for an install under
way.
Board Break and Road Rash start only when their official mod is installed
and on (mods::official_in_use), and say in the log which it is not; the
menus leave them out otherwise, as when turned off.
The live test (RESKATE_OFFICIAL_LIVE) checks that nothing downloads until
asked, then installs each.
The game's info sign shows on the first of the notice's three reserved
lines, where the mod's icon covered it. The icon, tag, name and details
now take the two lines under it, the icon 40 instead of 46 so it still
ends on the card's bottom text margin.
The OFFICIAL tab has an on/off switch on each mod's card, with an OFF pill
while it is off. The list of those turned off is
Mods/.reskate-official/official-off.txt, one folder name a line, which the
launcher's sync never removes. A mod turned off stays downloaded and kept
up to date, but official_packs() leaves it out, so nothing merges it, no
deck comes from it and the in-game Mods page does not list it.
Board Break and Road Rash do not start while their official mod is off,
and say so in the log. The menu model carries that as `off`, and the side
rail, the addon tabs and tiles, the home tiles, the pause menu's settings
and the native tools menu leave them out without a gap. category_tabs
takes a list built at run time for that.
Tests: an official mod turned off stays in place and is left out, comes
back when turned on, and only a plain folder name is written.
A model made for another player's drone crashed the game a few seconds
later in the per-frame update of its shader sections (Skate.exe+0x505b04b,
2.1.0): 28 of 29 reports there came right after one was made. Real
players' drones show as markers and are heard as before until that is
found; the pretend one from dronemodeltest remote still gets its model.
The warning sign on a mod item's description notice was cleared by writing
an empty IconOverride. The game resolves that override again later in its
UI update and crashed on the empty one (Skate.exe+0x3e897fb, a lookup that
finds nothing): about a quarter of 2.1.0's crash reports, all of them after
the sign was cleared.
The notice now gets the game's own info sign (img_generic_info_64), set the
way the favorites star is. When that texture is not loaded the warning sign
stays and it is looked for again two seconds later; an empty override is
never written. Texture assets are matched by name ignoring case.
Both documents come from the ReSkate backend (GET /api/v1/legal/privacy and /terms, edited on its
Legal page), so a change reaches players without a release. Settings has a button for each, opening
a panel like the changelogs': title, version and date, the Markdown drawn as the README viewer draws
it, and a switch to the other one.
Each launch looks up the current versions (GET /api/v1/legal) in the background. One newer than
the player agreed to, or none agreed to yet, puts up an agreement over the home screen: a short
summary, a way into each document, QUIT and I AGREE, which saves the versions agreed to
(accepted_privacy_version, accepted_terms_version in the launcher's settings). A backend that
cannot be reached holds nobody up. Launches that skip the window (--no-gui, Discord joins) are
not asked.
The merge measures each custom map's own meshes, every level of detail of every MeshSet in its
level bundles, into Mods/.reskate/reskate-map-meshes.json. A custom map's mesh streaming pool is
the game's 520 MB and half as much again as those meshes, at most half the video memory free (as
before): most maps have 25 to 70 MB of meshes and reserved 1 to 2 GB for them. When the map needs
more than the card has room for, Mesh.GlobalLodScale goes from the quality preset's 1.25 or 1.5
to 1, so coarser levels take over nearer; the game's value comes back for the next map that fits.
A map's world textures (texture group Worlds_*) flagged to stream that keep every mip with the
bundle, as an older Studio built them (404 MB of PQS Cordoba's), are made to stream as the game's
own do: the bundle keeps the mip tail from a 64 KB block, both first-mip fields of the header and
the chunk record say so, and the sharper mips stream from the chunk the map's TOC lists in full.
Only in a map's own level bundles (Studio keeps cosmetics whole; changing those left a load at
Starting server), and only for chunks whose guid marks them compressed (the streamer reads any
other as raw pixels and copied past what it read).
The pool was sized from the video memory free when the load was asked for, while the map being
left still held its textures and meshes. From one custom map to the next it came out smaller each
time (1846 MB down to 1253 MB over five maps on an 8 GB RTX 5050), until The Mashup loaded to a
black screen. A custom map's pool is now measured again at Starting level load, after the old map
has left and before the pools are re-created from the new level's data (FUN_14507a2d0), and raised
when more is free then; it is never lowered there. The log says which measurement the load used.
The window listed one ADDONS row that opened an overview of tiles, and showed the addons under it
only while that page was open. EXTRAS now lists Drone, Board Break, Road Rash, Hall of Meat, Grind
Exits and Music as rows of their own, always; a window left on the overview (switched from full
screen on ALL ADDONS) shows Drone. Every row of the rail is as tall as fits it without scrolling,
from 28 to 36. Full screen keeps its ADDONS page and ALL ADDONS tab.
With the in-game connection timeouts off, players were still dropped to the splash screen by a long
export: the game also ends a session after a stretch without input (DingoOnline.InactivityTimeOut*,
SecureReason_InteractivityTimeout), and no one touches the pad while an export runs.
DingoOnline.InactivityTimeOutEnabled is set to false at startup with the connection timeouts, as
the game's own disableAllTimeouts config does. The loading timeouts that config also clears are
left alone, so a load that never finishes still ends.
Master Chief and TASM2 Spider-Man ship appearance presets whose EBX lists a type reference on the
slot of an import, which the game's load reads as a type index and crashes on (Skate.exe+0x3def285
and +0x3def262 in Sentry). The merge now checks every mod's own EBX, including bundles it would pass
through whole, and takes such entries (or a repeated one) out of the copy in the merged patch and of
the copies carried into other mods' bundles; the mod's original still feeds any combine, and the
merge notes say how many per mod and bundle. The check reads only the fixup lists.
A material lookup row pointing past the shader programs the game ships is left out of the merged
lookup, with a note, instead of reaching the shader registry. Tests for both.
The shader expression registry registers a database from a queued job, and builds its per-key item
lists from the database's lookup without a bounds check. A database destroyed before its job ran,
or a lookup index past its items, left the registry holding pointers that crash it later
(Skate.exe+0x3f7cf33, +0x3f7ceed, +0x20960b in Sentry). The guard skips a registration for a
database already destroyed and points an out-of-range index at a valid item of the same key,
logging each.
A custom map's mesh streaming pool is half the video memory the card has free (its budget less what
is in use, counting the pool itself), never under the stock 520 MB; the game's own maps keep the
stock pool. It is set for each load and the size is logged. Large maps ran out of the fixed pool on
8 GB cards and ended in the game's DirectX error box (KERNELBASE+0xc408a in Sentry).
The game finds its own folder with the ANSI GetModuleFileNameA and decodes it as UTF-8, so a path
with Cyrillic, accented or Japanese characters (often a OneDrive folder) crashes it on start
(Skate.exe+0x18df4cf in Sentry). The launcher now says so and asks before starting; No is the default.
On a dedicated server with object scaling off, a loaded park's scaled objects were resized anyway
(and after a refused resize the pose poll saved 1x over their scale), and a scaled paste, set or
undo ended in a resize the server would not take, so the edit waited on it. The placements now
know whether this game may resize (set by the session from the server's setting and the role, the
host and roles that may always build exempt, allowed outside a session): where it may not, objects
stay 1x in the world, nothing waits on a resize, and the layout keeps their scale for when scaling
is allowed again. A transaction test pastes a scaled object with scaling off.
A light slam had a flat 25% chance to break a board (about 50% worn), a bail with no recorded
force counted as light, and any board could give way on a timer while just riding. Now a slam
under 60% of the breaking force never breaks it and the chance rises smoothly to certain (a new
board: never under 6, half the time at 8, always from 10); a bail of unknown force never breaks it;
and the riding timer is gone: a board that is done (85% worn) gives way on a hard landing instead,
from a big drop as it becomes done down to a curb's when worn out. The player is told when the
board becomes beat and done, and each break's cause is logged at info level.
A lock an admin sets is kept for the player's SteamID until unlocked or the server restarts, so
leaving and joining again no longer lifts it: they are locked again and told on joining. lock and
unlock take a player who is not here by SteamID64 (unlock also by the name they had), and locks
lists them as not here. A throwdown's own locks still end when the player leaves. Changing
throwdown-locks while a throwdown runs unlocks and locks just the tools that changed for its
players, saying the setting changed instead of that their throwdown is over.
Steam for Mac with NotProton or CrossOver passes the compatibility tool a path inside its app
bundle, below the folder with config/loginusers.vdf, and the tool's stand-in keeps no record of the
running client, so the launcher said Steam was not running and started offline. It now looks up
from that path for config/loginusers.vdf, and when started by the native Steam client under Wine
takes its most recent account where the running-client checks fail. Windows and Proton, where those
checks pass, are unchanged. The offline panel's hint about the launch option shows only under Wine.
MACOS-SETUP.md gives the launch option (/bin/bash, ROSETTA_ADVERTISE_AVX=1 for the game's CPU
check) for the launcher in a folder of its own.
Based on https://github.com/Dingo-Shenanigans/ReSkate/pull/219.
Co-authored-by: codejunky <pmp.codejunky@gmail.com>
A rebuild builds one segment per key and each needed every key's slot, so a long replay built
them once per segment: the game's rebuild is hooked too and the slots built for its first segment
are kept for the rest of it (per Behaviour and Subject). The segment player is no longer hooked
(it only counted plays for keysmooth status, every frame). The smoothness is a slider beside the
switch in the overlay (sent when let go, as each change rebuilds the open replay's camera) and
Keyframe smoothness (100, 75, 50, 25%) in the pause menu and Mod Options > Visuals. The startup
line logs on the runtime channel.
A mod's item (or one of the game's own a mod changes) keeps three empty description lines, so
the game's item card, which grows upward from a fixed bottom edge, always has room in the same
place; the overlay draws the mod there: its icon (decoded off the render thread into a fourth
texture slot, the last 32 kept), a MOD or CHANGED BY MOD tag, its name, author, version and how
many items it has. The card is placed as the game places its own, measured at many window sizes:
by the smaller of its scales, a 21:9 frame centred on wider screens (the search bar follows it
too). The warning sign the game's focus script gives any description is taken off that notice
each tick while it shows the reserved lines.
The merge's item list records each mod's version and folder (an older list falls back to the mods
loaded at launch). The item grids now run every client tick instead of at the 500 ms
customization pace, follow the highlight between their 40 ms passes, and let go of a grid as soon
as its screen closes, so the card, the search bar and favorites keep up with the player.