Commit Graph
29 Commits
Author SHA1 Message Date
AyeZeeBB 4f1f5a882e Launcher: the privacy policy and terms of service, and an "I agree" before playing
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.
2026-10-17 18:25:22 -05:00
AyeZeeBB 36ce7cc263 Launcher: "Test pre-releases" only shows when there is one, and either update switch checks again at once
The update check reads GitHub's release list either way (one call, as before) and notes whether a
pre-release newer than the latest release is there; the setting is offered only then, or while it
is on so it can be turned off. Unreachable GitHub keeps what the last check found.

Flipping "Install ReSkate updates" or "Test pre-releases" saves and checks again straight away, so
PLAY or the update button changes to match: updates off while one is offered goes back to PLAY,
pre-releases on offers the pre-release, off the latest release. A flip while a check is running is
checked as soon as it ends (each frame asks; it only compares two settings).
2026-10-17 01:50:50 -05:00
AyeZeeBB b63e2d62bd Launcher: the mod manager's pages redesigned, with a banner and cards
- page_banner: each page opens with its heading, what it is for, and how
  things stand at the right (a status pill and a caption). card: the
  panel the pages draw on, lighter edged on hover, blue edged when marked.
- MY MODS and GET MODS rows are cards with a gap between them (list_row),
  in lists without a border. MY MODS' banner counts problems and waiting
  updates and holds the load-order explanation; GET MODS' says whether
  the listing loaded and what is installed or waiting. The ticked bar on
  GET MODS is a card.
- OFFICIAL: a card per mod with its status and version pills, its
  Thunderstore facts, and THUNDERSTORE and OPEN FOLDER.
- PROFILES: new-profile and import cards side by side; a card per profile
  with a picture of its first mods' icons, pills for what it holds, LOAD
  and UPDATE, and the rest in a menu.
2026-10-16 20:01:53 -05:00
AyeZeeBB a2d6daffbc Official mods: Board Break and Road Rash downloaded from Thunderstore and kept at their latest, with an Official tab
The launcher reads the official list from the ReSkate backend (or the last one it read, or its own)
and keeps each mod in Mods/.reskate-official at its latest version; a copy the player installed is
moved in, the deprecated Board Break retired. The game loads them always on and leaves out Mods
folder copies; the browser no longer lists them. The built-in zips are gone (FPV drone too), and
built-in folders no longer carried are removed.
2026-10-16 18:59:41 -05:00
AyeZeeBB 290089e16d crash fix 2026-10-16 17:34:06 -05:00
AyeZeeBB 228ce65f84 Launcher: changing the update settings checks again without a restart
Turning "Install ReSkate updates" or "Test pre-releases" on or off took
effect at the next start. Closing settings after changing either now runs
the update check again: a pre-release is offered as soon as it is wanted,
the latest release when it no longer is, and a pending update is dropped
when updates are turned off.

- Not while a download, an update or a launch is under way, while the game
  runs, or while a merge waits on an answer about mods; nor as the launcher
  closes. The next check or start picks the change up then.
- The "Test pre-releases" help says the check happens when settings close.
2026-10-15 18:43:11 -05:00
AyeZeeBB 310922556c Launcher: a setting to test pre-releases
Settings > Launcher > "Test pre-releases" (off by default). On, the update
check takes the newest GitHub release that is not a draft and carries a
launcher.json, pre-release or not, in place of the latest full release:
a pre-release newer than the last release is installed, pinned by size
and SHA-256 as any release is. Turned off, the next check goes back to
the latest release, whose files then replace the pre-release's.

- The update notice says "Pre-release" for one, and the log names which
  kind of release was taken.
- The changelog shows the release the setting picks, marked as a
  pre-release, and is fetched again when the setting changes.
- --no-gui launches follow the same setting.
2026-10-15 14:23:06 -05:00
AyeZeeBB 2e186b9839 Launcher: mod profiles, sharing them by code or file, and Thunderstore dependencies
The Mods page has a third tab, PROFILES. A profile is a saved list of which
mods are on, in what order and at what version; every mod stays installed
once, in the one Mods folder. Loading a profile rewrites mods.json, switches
off what it does not name, and downloads from Thunderstore what it names
that is missing. Profiles live in Mods/profiles.json.

A profile travels the way r2modman's do, so the two managers read each
other's: export.r2x inside a .r2z file, and a code on Thunderstore's
profile service. Config files in an r2modman profile are ignored.

Installing or updating a Thunderstore package now brings the packages it
depends on, needed ones first, leaving out any already installed at a new
enough version. A mod pack is a package that is nothing else.

A kick, by an admin or by a passed vote, used to keep the player out until
the server restarted. "kick_minutes" in the players section of the config
(1-1440; 0, the default, is still until the restart) and the console
command "kick-time <minutes>|restart" now set how long it lasts.

The player is told how long when they are kicked, and how many minutes are
left if they try to join early. A kick keeps the time it was given, so
changing the setting is for later kicks. Bans are unchanged.
2026-10-13 00:55:29 -05:00
AyeZeeBB 4ac1343b95 Crash reports: self-hosted Sentry instead of Backtrace, and opt-in performance timings
Crash dumps now go to the project's own Sentry server. The launcher's
out-of-process helper is unchanged; only where it posts and what it expects
back are:

- The default endpoint is the Sentry project's minidump URL. Report
  attributes travel as Sentry tags, with the release as reskate@<version>.
- An upload counts as accepted when the server answers with an event ID.
- "backtrace" is "crash_report" throughout: the namespace, files, CMake
  targets, DINGOSDK_CRASH_REPORT_URL, DINGOSDK_BUILD_CRASH_REPORT_TESTS and
  the RESKATE_CRASH_REPORT_URL override.

Performance timings are new, and off unless "Send performance timings" is
ticked in the launcher's settings (RESKATE_TRACING=1). A small tracer
(Engine/Core/Debug/trace.h) posts each finished step to Sentry as a
transaction from a background thread; the launcher and the game it starts
share one trace. Timed: the update check, the Steam download, Thunderstore
installs, the mod merge, starting the game, the launch up to the first
playable level, each level load, joining a session, fetching the identity
lists, and the time spent in each level with its average frame rate and
long frames. Turning crash reports off turns timings off too.
2026-10-12 23:24:33 -05:00
AyeZeeBB 94ce8fddd7 Launcher: edit skate.'s own settings (graphics, audio, camera, controls, replay)
Settings has five more pages, under "SKATE. SETTINGS" in the rail, for the
settings the game saves per PC:

- GRAPHICS: window mode, resolution, HDR, brightness, UI brightness, HUD
  display, then the game's graphics options (frame rate limit, VSync,
  dynamic resolution, upscaler and its quality, antialiasing, textures,
  lighting, shadows, mesh, effects, post processing, global illumination,
  ambient occlusion, depth of field, motion blur) with buttons that set
  every low-to-ultra option at once.
- AUDIO: volumes, voice chat, text and voice language, subtitles, party
  menu narration.
- CAMERA: sensitivity, and the on board, off board and climbing options.
- CONTROLS: vibration, trigger force feedback, show controller on HUD,
  highlight indicator, the experimental toggles.
- REPLAY: editor speeds and sensitivity, effects, first-person keyframes.

They are written straight into the game's save containers under
%LOCALAPPDATA%\ReSkate\Game\Skate\data (game_settings.h): a DATA file of
sections and an INDEX naming them, the body one binary object of named
values. Only the values changed are rewritten, in both of the game's
copies; every other byte is kept. A container that cannot be walked whole
is left alone. The first change copies the untouched files to
%LOCALAPPDATA%\ReSkate\game-settings-backup.

Keys, kinds, ranges, steps and choices are the game's own
(DingoUISettingAsset in its data, build 20260929). The labels are ours.
Resolution is saved by the game as a place in the PC's list of display
sizes; the launcher lists Windows' sizes smallest first, which matches the
one PC it was checked on.

A change is stored once the control is let go. The pages are disabled while
a game this launcher started is running, and say so when the game has not
saved its settings on the PC yet.

Not offered: refresh rate, fullscreen monitor and audio devices (places in
lists the game builds at run time), the mobile-only settings, and settings
the game saves to the account rather than the PC.
2026-10-10 02:30:50 -05:00
AyeZeeBB 63955e51ff Launcher changelogs, download total, Discord joins skip the launcher window; Mod Options
Changelogs. The launcher's main screen has a CHANGELOGS tile in the
bottom-left corner. It opens a panel with the newest GitHub release: its
tag, title, date and notes. The notes are the release's description, read
as markdown and drawn like a mod's README (headings, bullets, code, rules).
A release published without a description shows what its GitHub page shows,
the tagged commit's message, taken from the releases feed. Fetched once,
the first time the panel opens; "Open on GitHub" goes to the releases page.

Download total. On GET MODS, the bar for ticked mods now gives the size of
what installing them downloads: "3 mods selected / 1.27 GB to download".
It is the sum of each mod's newest version as Thunderstore lists it.

Discord joins. The command the game registers for Discord to start ReSkate
now passes --no-gui, so pressing Join with the game closed goes straight
into the game instead of stopping at the launcher window.

--no-gui with no other launch flags now starts the game with the launcher's
saved settings (window size, menu and console keys, loose files, GPU
diagnostics, Discord status, offline, log level, extra launch options), as
pressing PLAY does. With flags of its own it behaves as before.

Mod Options. The pause menu's "Custom Stuff" page is renamed "Mod Options",
in the menu, the READMEs and the comments.

Not tested in game: the Discord join with the game closed, and the renamed
page. The changelog panel has only been seen with the earlier API-only
fetch.
2026-10-10 01:42:36 -05:00
AyeZeeBB 8a4980c26a Discord Rich Presence, with joining from Discord
The game shows on the player's Discord profile where they are skating.
It talks to the Discord app on the same PC over its local pipe, with no
SDK; without Discord running nothing happens.
- Solo: "On <map>", "Solo skating", and how long they have been in.
- In a session: "On <map>", "Server: <name>" or "Lobby: <name>", the
  player count, and how long since they joined. A session with a
  password shows "Private server" or "Private lobby" and no name.
Joining: a status carries the session's join code when anyone may walk
in (no password, not full, a dedicated server or a publicly listed
lobby). Discord shows that as "Ask to Join"; the game answers yes for
the player at once, and the other player's game is handed the code and
joins. If their game is not running, Discord starts the ReSkate
launcher, which the game registers for under the player's own
discord-<application id> URL scheme.
Switches: "Discord status" in the launcher's settings (off starts the
game with --no-discord, and the game never opens Discord's pipe), and
the same in the in-game Multiplayer settings, kept in the profile.
The model gains join_code: the code of the session a player is in as
host or guest (invite was a host's only).
2026-10-09 22:51:22 -05:00
AyeZeeBB c8c6cf16f2 Launcher: mod overviews show the README, in a larger two-column layout
The overview that opens when a mod is clicked, on both MY MODS and GET MODS,
now shows the mod's README and has more room for it.

README:
- GET MODS fetches a package's README from Thunderstore the first time its
  overview opens (/api/experimental/package/<owner>/<name>/<version>/readme/)
  and keeps it while the launcher runs.
- MY MODS shows the mod's own README.md from its folder, or the package's
  from Thunderstore when the folder has none.
- The markdown is laid out as plain text: headings in bold, lists, rules and
  code blocks kept; links keep their text; images and HTML are dropped; a
  table row shows its cells side by side. A README is cut at 400 lines, with
  a note that the rest is on the mod's page, and one over 512 KB is not read.

Layout:
- The overview is up to 1080 x 740, from 680 x 560.
- The header has a larger icon with the name, the author and the short
  description beside it. An installed mod shows its Thunderstore icon.
- Under the buttons the README has the wide column and the facts (version,
  downloads, updated, size, categories, folder, maps and so on) have a panel
  of their own on the right.
2026-10-08 22:12:48 -05:00
zeex64 63ee53382a Merge pull request #63 from northdroplet/feat/gamepad-touchpad
Launcher: controller support and the Steam Deck trackpad as a mouse
2026-10-08 21:04:34 -05:00
NorthDroplet 7a34ead2d5 Launcher: steadier trackpad pointer and list navigation
- The trackpad pointer follows the whole swipe; Steam stops the tilt when
  the thumb lifts, so nothing has to be cut off.
- Up and down stay inside the mod lists and leave a row from any of its
  parts (tick, switch, buttons) in one press.
- Left from anywhere in a list reaches the nearest rail tile, BACK included.
- The focus no longer falls back to a tab when ImGui lets go of a row the
  list only partly shows.
2026-10-08 07:21:05 +00:00
AyeZeeBB 56b687b058 Launcher: Thunderstore's mark on MODS and its button; ask about enabled mods' updates only
- The MODS tile shows Thunderstore's mark in its own green instead of
  the skate tool, which stays as the fallback when the mark is not
  built in
- "Open Thunderstore" in the mod manager is a branded button: the mark
  and name in Thunderstore green on its dark blue, taller than the
  plain buttons beside it
- The mark is a new asset, assets/launcher/icon_thunderstore.png,
  embedded like the other tile icons
- A disabled mod's update is no longer asked about before PLAY or
  counted on the MODS tile, and "UPDATE AND PLAY" no longer installs
  it. A disabled mod does not load, so its update stays on the Mods
  page, where it can still be updated by choice
2026-10-07 15:01:55 -05:00
AyeZeeBB a9742673da log changes 2026-10-05 17:27:50 -05:00
AyeZeeBB de631ad9e6 leave out mods that copy store items, chat badge check
- Mods that add copies of store items under new names are no longer
  loaded. The launcher, mod manager and game say why.
- A chat line passed on by the host only shows a Dev/Creator/Homie
  badge when the player's own copy of it arrives too, so a host
  can't put one on a line that player never wrote.
2026-10-05 16:29:37 -05:00
NorthDroplet 360338e6e1 Launcher: controller navigation and the Steam Deck trackpad as a mouse
The launcher read no controller at all. Started from Steam (Desktop or Game
Mode on a Steam Deck), Steam Input applies the game's gamepad layout to it,
where the right trackpad is the right stick and its click is R3, so the
trackpad did nothing; only the touch screen, which arrives as mouse
messages, worked.

- Every XInput pad is merged (Xbox, Steam Input's virtual pad), else a
  DualShock 4 / DualSense is read over HID with the reader the in-game menu
  already uses, now its own library (dingosdk_playstation_input).
- D-pad and left stick move ImGui's focus, outlined in the launcher's blue;
  A / Cross presses. The hand-drawn tiles, switches and menu buttons take
  part in navigation (ImGuiButtonFlags_EnableNav).
- B / Circle closes an open combo or menu and leaves a text field, and is
  Escape otherwise, which the launcher's pages already go back on. Escape
  now also closes the mod overviews and answers Cancel in the uninstall and
  replace confirmations; closing an overview no longer also leaves the page.
- The right stick (the trackpad) moves a pointer that ImGui draws, and R3
  (the trackpad's click) is the left button. The system cursor follows it;
  a mouse move or a touch elsewhere takes the pointer back.
- The ImGui Win32 backend's own gamepad code (slot 0 only) is compiled out
  so it cannot fight the launcher's events; nothing else used it.
2026-10-05 14:27:08 +00:00
AyeZeeBB 76330e40bb Skater slot, menu and throwdown fixes; MY MODS rework; lobby parties
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.
2026-10-04 13:27:21 -05:00
AyeZeeBB 9c03edda34 Show each mod's size in the mod manager
Show each mod's size in the mod manager

A mod's size was only visible in the package overview and the install
prompt, so there was no telling from either list what a mod costs to
download or how much room the installed ones take.

- MY MODS: each row carries the size of the mod's folder on disk after
  the version ("v1.0.1 / 410 MB / by anton / 1 map"), and so does the
  line under the title in a mod's overview. The folders are measured
  when the Mods folder is scanned, so the figure follows an install, an
  update or Refresh. The game's merged patch hard links a mod's archives
  rather than copying them, so this is also what removing the mod gives
  back.
- GET MODS: each row carries the download size Thunderstore reports for
  the latest version, in the same place ("v1.0.0 / 101 MB / 0 downloads
  / 2026-10-04"), as the package overview already did.
- size_text moves out of gui_mods_browse.cpp's file-local namespace so
  both pages format a size the same way.

The two figures are not the same thing: one is the unpacked folder, the
other the zip, so a mod reads a little larger once installed.
2026-10-04 00:37:15 -05:00
AyeZeeBB d895c9e915 Say on PLAY when mods have updates, and ask before launching without
A mod update was only visible on the mod manager's own page, so the
usual way to find one was a mod behaving oddly in game.

- PLAY carries a pill in its corner while Thunderstore has newer
  versions: "1 MOD UPDATE", or the count. Dark on the blue tile, blue on
  a grey one.
- Pressing it asks first, listing each mod and the version it would move
  to, with three ways on: update them and play, open the mod manager, or
  play anyway. Playing on the versions you have is a real choice -- a map
  you are part-way through, an update you do not trust yet -- so it stays
  offered, and taking it is remembered for the session rather than asked
  again on every launch.
- Only from READY. INSTALL, DOWNLOAD, UPDATE and RETRY are untouched: a
  mod update has no business standing between someone and a 14 GB game
  download.
- The dialog re-checks as it draws. If the pending list emptied while it
  was open, it launches instead of showing an empty box.

"Update them and play" launches when the install finishes, which is what
it says and what it did not do:
- The promise is only made if the install really started, so a refused
  start cannot launch instantly with nothing updated.
- An update that failed stays on the page with the reason on screen and
  logs why it did not launch. Starting the game on a half-updated mod set
  is how the cosmetic crash in a30a838 happened.
- Leaving the page with BACK cancels it: that is a change of mind, not a
  request to be launched into the game a minute later.

collect_install takes the result under the panel's mutex at the top of
the frame, so once installing is false the outcome is settled and the
error check is reading the real answer.
2026-10-03 22:23:34 -05:00
AyeZeeBB 201571c225 Merge mods before launch; name the mod that could not be merged
A mod the merge could not use was left out silently. The game started
without it, three minutes into a loading screen, and only ReSkate.log said
which one.

Merging before launch
- PLAY runs the merge the game would have run behind its splash, on the
  launcher's worker, with the step and progress on the STATUS tile
  (Phase::merging). The launcher links dingosdk_mods for it, which costs
  about 600 KB of exe.
- When every mod merges, the launch goes ahead and the game's own
  load_catalog finds the patch already built, so the splash is shorter
  rather than the work being done twice.
- When mods were left out, the launch stops at Phase::mods_broken and a
  dialog names each one and its first problem, with three ways on: switch
  them off and play (which writes mods.json, so the next launch does not
  rediscover it the hard way), open the mod manager, or play anyway.
- Mods built for another game version do not block. They already have
  their own notice and message box, and blocking on them would stop play
  after every Steam update.
- The launcher resolves -dataPath out of the extra-arguments setting, so
  it merges against the root the game will read.

One SDK identity for both binaries
- Two places recorded "which ReSkate did this" as the module the code was
  running in, which is ReSkate.dll in the game and ReSkateLauncher.exe in
  the launcher now that both merge. merge_fingerprint hashes it, so the
  game matched no stamp the launcher wrote and merged everything a second
  time; sdk_identity keys the exclusions file, so each would have called
  the other's exclusions stale.
- Both now name ReSkate.dll beside the running executable. Skate.exe and
  ReSkateLauncher.exe sit beside it and launch.cpp enforces that, so the
  two agree, and unlike the data root it does not move under -dataPath.
  The value is unchanged from what the runtime computed before, so nothing
  re-merges on upgrade.

Naming the mod
- In game, a mod left out of the merge altogether said nothing on screen:
  only a mod that merged partially did, which is the lesser failure. Both
  are named now.
- The MOD MANAGER tile says which mod did not load, in the detail line's
  colour rather than a pill, clipped so a long name cannot run under the
  tile's artwork.
- MY MODS carries a line naming them above the list, and NOT LOADED and
  OUTDATED are badges on the row instead of words at the front of its
  summary.

MY MODS reaches Thunderstore parity
- Rows carry the package's icon, the same one the store shows, through a
  shared mod_icon(); a mod that never came from Thunderstore keeps the
  placeholder.
- An update is a button on the row, not a badge you had to open the mod to
  act on, and every row has Uninstall. Rows grew to fit, and "Remove" is
  "Uninstall" throughout.
- No pill for a mod that is up to date: the absence of an update button
  says it, and eight green pills said nothing eight times.

Fixes
- The install panel was drawn on the Mods page's own draw list after its
  children, and ImGui renders a child after its parent, so it was painted
  behind the mod rows along with its Cancel button: installs ran with no
  sign of it. It is its own window over the page now.
- pump_icons, which uploads decoded icons, only ran on the store page, so
  MY MODS showed placeholders until a visit to GET MODS uploaded them for
  it. The page does it for both lists.
- The merge dialog's closing advice overlapped its buttons.
2026-10-03 17:08:03 -05:00
AyeZeeBB aef269497e Rebuild the launcher's mod manager, settings and status tile
The mod browser was a 960x620 panel inside a 1180x680 window, reached from
a tile the same size as SETTINGS. People could not find it, and once they
did there was room for about six mods.

Window
- The design size is 1440x840. Everything is laid out in design units and
  multiplied by g_scale, which now scales down when that would not fit the
  screen's work area, so a small laptop or a high DPI no longer gets a
  window running off under the taskbar.
- The MODS tile is MOD MANAGER: taller than SETTINGS, directly above PLAY,
  with the pending update count as a pill on its subtitle line.
- background.jpg is 1920x1027, so the bigger window is not upscaling a
  1280x720 photo.

Mod manager, a page rather than a panel
- begin_page fills the window and draws its own minimise and close, since
  it covers the main screen's. BACK or Escape leaves it.
- A nav rail holds MY MODS and GET MODS (count badges, blue for the open
  one), the install actions and BACK. Refresh sits with what it refreshes,
  top right of the content.
- Every mod is a full-width row: icon, name, author, description, version
  and downloads, with a blue INSTALL or UPDATE and a tick box on the right.
  Ticking several installs them in one run.
- Clicking a row opens that mod's overview in a popup, replacing the
  side-by-side details pane that halved the list's width.
- virtual_rows draws only the rows a scrolling child actually shows.
  ImGuiListClipper cannot do this, as it assumes every row is a fixed
  height.
- Installing is a centred panel over a dimmed page with the activity, a
  striped bar and Cancel, instead of a progress bar in the footer.

Settings
- The same page and rail: GAME, DISPLAY, KEYS and ADVANCED are nav tiles
  rather than a row of tab buttons, and the content keeps to a 760 px
  column so the explanations stay a readable measure.
- The Steam sign-in, Steam Guard and QR dialogs stay centred panels. They
  are prompts, not pages.

Status and failures
- The STATUS tile carries its state in a coloured edge and a pill (WORKING,
  READY, ACTION NEEDED, PROBLEM), its headline is 22 pt over muted detail,
  and the standing facts (game build, ReSkate version) sit under a rule
  instead of competing with the live status as equal rows.
- Launcher::fail keeps the raw message for the log, and problem.h turns it
  into a headline and the next thing to try. The injection and PE-identity
  failures ("VirtualAllocEx failed", "Injected ReSkate.dll is not present
  in the child module list") all become "ReSkate could not attach to
  Skate", with the anti-virus and overlay advice that actually fixes it;
  the Steam download, a missing or damaged ReSkate.dll, the content cache
  and a shared menu/console key each get their own. Anything unmatched
  keeps its raw text.
- A failed tile grows Open logs and Copy details. Copy details puts the raw
  message and the versions on the clipboard, ready to paste into Discord.
2026-10-03 16:10:55 -05:00
ReGlitched 2fd92ba989 crash fix + launch arg 2026-10-03 00:23:44 -06:00
AyeZeeBB b763631b77 Trim per-frame multiplayer client work; size mesh pool to the GPU
Mesh streaming pool (fixes loading crashes on older GPUs)
- 1.0.0 forced MeshStreaming.PoolSize to 3.5 GiB on every card. An RX 580
  crashed while loading with DXGI_ERROR_DEVICE_RESET, and the oversized pool
  is the likely cause. The pool is now a quarter of the largest hardware
  adapter's dedicated video memory, capped at 3.5 GiB; cards of 6 GB or less
  keep the game's own 520 MB. The card, its memory and the chosen size are
  logged once at startup.

Remote players (busy servers)
- Transform interpolate is inline plain arithmetic: 22 -> 5.8 ns per joint.
  It was 4% of a busy server's client frame, since every player within
  200 m has the whole skeleton interpolated every frame.
- Players out of the camera's view and more than 8 m away are sampled at
  20 Hz, like far players. Their position still updates every frame for
  collision, sound and nametags, and a player coming into view is sampled
  that frame.

Expression hooks (run for every expression the game executes)
- No profiler zones in the expression hooks: taking a sample switched them
  on, inflating the very samples that measured the hooks.
- The throwdown lab pump does one sorted lookup of the running graph and
  skips everything else for graphs it doesn't watch (graph_throttle gets
  throttled_graph for this).

Settings and memory reads
- Script gameplay-setting and native-setting gets are served from small
  per-thread caches, keyed on the asset/key address, its first 8 name
  bytes and a new profile::Store::changes() counter, instead of a store
  lookup each call.
- Per-frame reads in the client tick, native settings and population
  controls use memory::peek instead of ReadProcessMemory.
- Script error logging probes each argument pointer once.
2026-10-02 21:07:43 -05:00
AyeZeeBB f7fc909ca7 Revert "Keep launcher alive through Skate startup; trim per-frame client work"
This reverts commit b7932535e5.
2026-10-02 20:19:51 -05:00
AyeZeeBB b7932535e5 Keep launcher alive through Skate startup; trim per-frame client work
Launcher
- "Close the launcher when Skate starts" now hides the launcher and exits
  when Skate.exe does, instead of exiting as the splash opens. Outside a
  Steam library, Skate's protection closed the game (TerminateProcess 0x32)
  when the launcher exited during startup; players confirmed turning the
  setting off avoided it.
- STATUS tile warns when Steam isn't open or signed in that PLAY starts
  offline as Unknown Player (hidden when Offline mode is chosen or while
  launching).
- Setting description updated to match.
Startup interventions (20260929)
- exit_return 0x87755f2 -> 0x87fe7fb: the last LEA RSP,[RSP]; JMP stub
  before the PUSHFQ / LOCK CMPXCHG routine, as 0x87367cf was in 20260908,
  and the return address player logs show. Only enforced once a frame site
  is armed; this build's protector has no equivalent rep stosb frame clear.
Client frame cost (profiled 2026-10-02)
- Transform interpolate is inline plain arithmetic (~1% of an MP frame).
- Script gameplay-setting and native-setting gets are served from small
  per-thread caches keyed on asset/key address, name prefix and a new
  profile::Store::changes() counter, instead of a store lookup each call.
- Hot-path reads in client tick, native settings and population controls
  use memory::peek instead of ReadProcessMemory.
- Script error logging probes each argument pointer once.
2026-10-02 18:56:57 -05:00
AyeZeeBB ca1d82f636 1.0.0 Release! 2026-10-02 14:40:41 -05:00