Map downloader
- A host or dedicated server now tells joiners which Thunderstore package
its map comes from (the Mods folder name plus manifest.json).
- A player without the map gets a card: icon, name, author, version and
description, with DOWNLOAD and CANCEL. It works with mouse, keyboard and
controller.
- Only packages listed as Maps in the ReSkate community are offered, and
never deprecated, rejected or NSFW ones.
- On yes the package is downloaded, installed into Mods and applied as a
live mod, then the session loads the map. A small card on the right
shows the progress, so the player can keep skating.
- The player stays connected while it downloads: the host gives a player
who says they are fetching the map up to 45 minutes instead of the
usual load time.
- When the server changes map with the player in it, the card says so.
- Protocol version 47: map package on map_offer and world_state, and a
"fetching the map" flag on map_request and world_ready.
Joining
- The pause-menu server browser shows a CONNECTING card over the page
while a join is under way, and a COULDN'T CONNECT card with the reason
when it does not get in.
- The session and voice tabs no longer show before the player is in.
- Leaving without the map (declined or cancelled download) no longer
counts towards the failed-join limit, on servers and player hosts.
Input
- A card that asks something holds the game's input until the buttons
are released.
- Steam's overlay hooks XInput in front of ReSkate and answers the game
itself, so a controller reached the game behind menus. ReSkate now
hooks that hook as well.
Mod merging
- Mods are read on several threads, at launch and for live merges. A live
merge runs below the game's priority.
- The paid-cosmetics check reads the game's files and the mods on several
threads.
- A live merge reuses the paid-cosmetics verdicts it already has and
reports its progress and timings.
Launcher
- NSFW mods and their categories are not shown in the mod browser.
After 10 bails the leg of the side that took more of them shows road dust
and a graze, its arm one bail later; at 14 the marks are bigger and the
other side starts; at 20 they are raw wounds and the face is bruised. A
mark never gets smaller until the player heals. The worst wounds bleed,
or are dry and scabbed with the blood switch off.
The marks are cosmetic items of a content mod (tattoo items for the limbs,
moles items for the face, named RoadRash_<Set>_[<design>_]<level>). Road
Rash puts them into the local skater's recipe with the game's own recipe
copy, after the validation the multiplayer code runs on a peer's outfit.
Nothing is written to the outfit or the profile's skater, and without the
item pack nothing shows and nothing is changed.
A bail is the physics state selector choosing Wipeout (No Bail's watch).
Its side comes from the ragdoll's contacts through Hall of Meat's reader:
impact and slide of the arm and leg bodies that touch something other than
the skater's own board, summed per side while the body is a ragdoll.
Outfit menus. The game feeds a skater's items either from the player's
outfit or from a recipe of the skater's own: after the recipe copy the
skater in the world no longer gets what the player changes in the menus.
So the skater is given back to the game while a game menu is up, with
nothing to show, on healing, when a switch changes and when switched off:
the four words of the item component the copy had changed go back to what
they were and the component is told its feed changed, and the game puts
the outfit's own items back and feeds the skater again. The marks go back
on, over the outfit as it is by then, a second after the menu has gone.
Whose recipe a skater wears is read from the skater at every look: a
respawn hands over the same skater, items and all, as if it were new.
The player's own tattoos and moles stay unless roadrashtattoos is on, and
come back the same way.
The recipe handed to the copy names no item, only hashes, like the game's
own for the local skater: the game changes that skater's items where they
lie, and a name left beside one would stop every later read of the
recipe, the multiplayer code's too.
Console: roadrash, roadrashblood, roadrashtattoos, roadrash heal,
roadrash bails <count>. Menus: Road Rash, Road Rash blood and Heal Road
Rash beside Hall of Meat (Mod Options > Player, the overlay's skater page,
the native tools view). The three choices are saved with the profile.
No new hooks. The rules (side of a fall, levels per count, item names,
decal placement, comparing parameters the game has rounded) are in
road_rash_model.h with their own test target,
DINGOSDK_BUILD_ROAD_RASH_TESTS. Notes and what is not tried yet:
contrib/road-rash.md.
In the skater's item grids (Apparel, Accessories, Board, Gestures) F favorites
the highlighted item, - (or Ctrl+F) opens a search box that filters as you
type, and X steps a filter (All, Favorites, Mods, Game items). Favorites sit
right after the worn item, carry the game's star where the tile shows its
rarity icon, and are kept in ReSkate.favorites.json beside Skate.exe.
The grids stay the game's own: their tile rows are reordered and filtered
through the native model functions, as the music screen's Mods shelf does.
Nothing is hooked for it and no file of the game or of a mod is changed.
See contrib/native-item-browser.md for how it works and what is not tried yet.
This is the Item Favorites mod done natively, so it no longer needs a DLL
loaded through a custom script.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Multiplayer and Custom Stuff pages of the game's pause menu were
built from the game's own menu widgets: a button, a text box and a line
of text, which cannot make a list with columns. The game now keeps only
the frame around each page (top bar, title, Back prompt) and ReSkate
draws everything in it, tabs included. The native page is one empty
body.
Multiplayer
- Server browser: a list with name, map and skaters columns that sort,
search, filters (all, servers, lobbies, friends, hide full, my map),
and a panel for the session pointed at. Pressing a row joins it; the
row says JOIN while pointed at. Join by code is in the panel, and its
own tab is gone.
- Host lobby, as before.
- Current session (only in one): who is here, leave, map, join code,
party.
- Voice chat (only in a session).
- Session settings (only for a lobby's host or a server's admin). They
are sent as explicit values, which a dedicated server needs.
Custom Stuff
- Official maps and Custom maps: pressing a map loads it.
- World: traffic, pedestrians, time of day.
- Parks: a card for each lot with its style, layout and load.
- Player: noclip, no bail, Hall of Meat, board wear, the camera views,
flight speed and the boosts.
- Online: player and nametag distances, nametags, chat, chat bubbles,
Discord status, and showing your tag and items.
- Visuals: camera effects, challenges, shuffle playlists.
- Binds: record or clear the button for each action.
- The player card name is no longer on the page (cardname in the
console still sets it).
Input: the game keeps the mouse and controller while its menu is up,
so the pages only watch them. They have their own focus, moved with
the D-pad or arrow keys and pressed with A or Enter, with LT/RT or Z/C
for tabs; lists remember the row the focus left. Typing in a text box
or recording a bind takes the keyboard and controller for that long,
as chat does. Nothing is taken while the game is not the window in
front, and the overlay's own menu draws on top.
Layout follows the game's menu at any window shape: scaled to fit
whole, 192 units clear at the sides, centred past 4704 units wide.
Sounds: the pages raise the game's own UI one-shot event for moving
the focus, pressing and changing tab.
As in skate. 3: when the local skater bails, the bones it hurt show over
the world through the body, yellow where a hit bruised one and red where
one broke it, with the bail's Meat card in the bottom left corner in the
place of skate.'s own HUD there: its time, hits (head hits double,
vehicles half again), broken bones, road rash, airtime, fall, top speed
and rotations, each scoring, and the map's best. A bone breaking pulses
the screen's edges red and, in single player, slows the game down a
moment. Off until switched on, as in skate.: in skate.'s menu (Custom
Stuff > Player) or with `hallofmeat 0|1`, saved with the profile.
Everything it draws is skate.'s own, read from the installed game: its
skeleton mesh (the Dem Bones costume) posed with the renderer's own
skinning matrices, its scoring icons, the THRASHER wordmark and its UI
brush strokes. Nothing is shipped.
How it works: No Bail already hooks the skeleton response, which runs
once a physics step right after the body contacts; it now hands that step
on, with the local skater it follows, but only while Hall of Meat is on.
Each step reads what every ragdoll body hit and how hard, and whether the
skater is a ragdoll; the bail runs on the game's own clock so slow motion
measures what the body did. The feature's own hooks, on the renderer's
skinned draw packets and main view and on the UI model's write, are
prepared at startup and switched on only with the feature, and off again
once the HUD corner and the game's speed are given back: switched off, the
game never calls them and the physics step pays nothing. The skeleton mesh
is read the first time it is on; only the images are read at startup,
since the overlay builds its atlas once. The renderer's picture of the
skater is read only while a bail shows. The menu's switch reads the
overlay model like the others. Every address is in the build table with a
fingerprint checked before use. Extension/HallOfMeat/README.md describes
the parts; its tests build with DINGOSDK_BUILD_HALL_OF_MEAT_TESTS.
The slow motion changes SimulationTime's rate, frame cap and time scale as
a session override and steps the local skater along, since skate. sets a
skater's step only when it builds its core. It runs the same at every
break, but never faster than the game ran: with the trainer's game speed
below 1 it only takes the part that is slower still. Afterwards it writes
back what it found, each setting only while it still holds what the slow
motion wrote, so the trainer's speed comes back as it was; a setting
changed from elsewhere meanwhile is left as it is and ends that slow
motion. named_setting_value reads a setting's value for it.
Tuned in play: a bruise from 7 m/s and a break from 12 m/s along the
contact normal (raised twice: a hard fall on flat ground broke bones), a
break worth ten of the lightest hits (a heavy bail's hits and breaks
outweighed the rest of the card) and a fall half of skate. 3's rate.
Fix: the overlay now draws in the back buffer's pixels, not the window's,
so it lines up on displays Windows scales (1920x1080 borderless on 4K).
The skater's render hooks, its skeleton and its body maps were first
found by gBGYo's ReSkate fork (github.com/gBGYo/ReSkate).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Skater slot, menu and throwdown fixes; MY MODS rework; lobby parties
Saved skaters (Extension/Customization, Extension/Skater)
- The selected slot, and slots before it, came up as the standard
skater after a start or map change. The game asks for a slot's saved
outfit once per level, and that happened before the cosmetics catalog
could be read. The first selection now waits for the catalog (60 s at
most), and later map changes check against the catalog already read.
- The retry from abdda77 is removed: the record it wrote to is a
temporary on the game's stack, so it could never work.
Pause menu (Extension/UI/NativeMenu)
- ReSkate's entries stopped working after enough map changes: each
level change took new slots in a fixed table of 1024 for the same
buttons. A button now keeps its slot, and a full table hands out the
slot that has gone longest unused.
Throwdowns (Extension/Throwdowns, Runtime/runtime_init.cpp)
- Multiplayer crashed when someone placed a throwdown after a map
change. The event types are freed with the level but were cached for
the process. They are now cleared when a level is left, checked
before use, and looked for again in each level.
MY MODS (Launcher/gui_mods.cpp, gui.cpp)
- Search, a filter and an order; a switch per mod; a menu per row.
- Multi-select with tick boxes, Shift-click and Ctrl+A, and a bar to
enable, disable, move, update or uninstall everything ticked.
Lobby parties (Extension/Multiplayer/Session)
- A lobby is no longer one party. Its host keeps parties the way a
dedicated server does: invite, accept, join, leave, kick, promote,
open and close, with "/p" party chat. The "Lobby party" switch is
gone. Protocol version unchanged (38).
Mod merge (Engine/Vfs), follow-ups to e715b9b
- Files rewritten into the merged patch are tracked by position, so
another mod's added assets no longer shift the lookup.
- Two mods adding different assets under one name is now noted, with
whose copy the maps get.
- mod_merge_unshift_tests compiles with the launcher tests on.
Videos exported from the replay editor played two to three times too
fast unless the frame rate was capped, or the export was slow enough to
hold it down by itself (4K, WebM). The fault is in the game's own export
path.
Replay export (Extension/Rendering/replay_export.*)
- While exporting, the game steps the replay by one frame of video
(speed / fps) for every frame it renders. The engine's movie encoder
takes a frame only while a permit byte is set; a world update sets it
once, and a frame submitted without it is dropped. Rendering two or
three frames per update, most of a clip never reached the file, and an
MP4 is exactly as long as its frame count. One clip came out as 181
frames at 30 fps and 297 at 60, 6.0 s and 5.0 s.
- The encoder's frame submit is detoured and the permit set before the
original runs, for the replay editor's encoder only (matched by its
vtable). The frame is encoded on the render thread before the call
returns, so the renderer is held to the pace the encoder keeps and no
frame is lost. The replay still runs fast on screen during an export:
that is the encoder's speed, not the file's.
- The same clip afterwards, frame rate uncapped, MP4 1080p: 505 frames
at 30 fps and 1008 at 60, 16.8 s both, audio as long as the video.
WebM and 4K take the same path and were not run again.
- Addresses are in Engine/Game/Build/20260929/replay_export.h. The hook
starts with the others in runtime_init.cpp.