mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-23 13:05:54 +02:00
Docs: the throwdown kit for Lua, and Board Break and Road Rash as plugins inside their packs
contrib/throwdown-kit.md is the reference for making a throwdown mode in Lua: registering modes, the documents (setup page, waiting card, HUD, match panel, flags, match), the throwdown_ui events, the native flag, and the services a mode uses. Board Break's doc says how the deck is chosen now (the pack's decks as variants, reskate.package.choose, reskate.board.fit); Road Rash's that it ships inside its item pack. The plugin list and the README name the throwdown plugins.
This commit is contained in:
1 parent
e246acd24b
commit
91b754bfb0
5 files changed
+297
-70
No files matched your search
@@ -15,15 +15,16 @@ the launcher, the runtime that loads into the game, and the dedicated server.
|
||||
- Join dedicated servers from the in-game server browser.
|
||||
- Proximity voice chat, and text chat with emotes and an optional bad-word filter.
|
||||
- Parties in lobbies and on dedicated servers: invite, join, leave, promote.
|
||||
- Throwdowns with other players (Jam, Spot Battle and S.K.A.T.E.), and co-op challenges.
|
||||
- Throwdowns with other players (Jam, Spot Battle and S.K.A.T.E.), and co-op challenges. Plugins add
|
||||
throwdown modes of their own to the Throwdowns page ([contrib/throwdown-kit.md](contrib/throwdown-kit.md)).
|
||||
- **In-game menu and console.**
|
||||
- Map and fast travel.
|
||||
- World: time of day, population, district levels, rotating parks.
|
||||
- The **Park Editor**: place, move and save objects with freecam, snapping and undo. Save a selection as a
|
||||
set and place it again anywhere, on any map.
|
||||
- Skater options: first person, movement, boosts, noclip.
|
||||
- Hall of Meat and grind exit triggers are plugin mods now
|
||||
([contrib/plugins/hall-of-meat](contrib/plugins/hall-of-meat), [contrib/plugins/grind-exits](contrib/plugins/grind-exits)).
|
||||
- Hall of Meat, grind exit triggers, Board Break, Road Rash and the FPV drone are plugin mods now
|
||||
([contrib/plugins](contrib/plugins)). Board Break and Road Rash ship inside their asset mods.
|
||||
- Progression, controls, graphics and multiplayer settings.
|
||||
- **Mods.**
|
||||
- Drop a mod in `Mods/` and it is merged into the game at launch. Mods can add custom maps, loading
|
||||
|
||||
+56
-65
@@ -4,8 +4,8 @@ A hard slam can break the local skater's board: at the nose, in the middle or at
|
||||
time the grip tape holds the pieces together and the board folds or an end hangs; otherwise a piece
|
||||
comes off, flies and lies where it lands, truck and wheels with it. The board is whole again once
|
||||
the skater has picked it up, rides again or respawns. A plugin, [board-break](plugins/board-break)
|
||||
(it was built into ReSkate until 2026-10); the broken pieces themselves come from a content mod
|
||||
with the deck shapes in it.
|
||||
(it was built into ReSkate until 2026-10), that ships inside the Board Break deck pack: the broken
|
||||
pieces themselves are the pack's deck models.
|
||||
|
||||
Boards also wear: every hard landing, rail hit, grind and slam takes something out of the board of
|
||||
the deck in the game, and a worn board steers lazier, wobbles, breaks from less and in the end can
|
||||
@@ -13,14 +13,12 @@ give way under the rider. A boardslide or darkslide that comes down too hard ont
|
||||
the board and throw the rider. A break cracks (and sounds like metal when it happened on metal),
|
||||
and the body's hits in a bail are heard where and as hard as they land. The player sets all of it.
|
||||
|
||||
Code: the plugin's Lua in [plugins/board-break/plugin](plugins/board-break/plugin) (the break,
|
||||
wear, rail snaps, sounds, its console command and menu), drawn through reskate.board
|
||||
([board_pose.cpp](../Extension/Skater/board_pose.cpp)). What every board needs while a deck pack
|
||||
is in the game stays in core whichever plugins run:
|
||||
[breakable_deck.cpp](../Extension/Skater/breakable_deck.cpp) (which deck, its name and wheel
|
||||
spacing, the `boarddeck` command), board_pose.cpp (the deck's stretches kept out of sight, the
|
||||
baseplates on the deck, the wheels at the deck's spacing, on every board), and the deck's place in
|
||||
the mod list in [mod_catalog.cpp](../Engine/Vfs/mod_catalog.cpp).
|
||||
Code: the plugin's Lua in [plugins/board-break/plugin](plugins/board-break/plugin): the break,
|
||||
wear, rail snaps, sounds, the deck, its console command and its page. It draws through
|
||||
`reskate.board` (set, hide, park and toss the board's bones; `fit` every board for the deck in
|
||||
the game), and picks the deck with `reskate.package.variants` and `reskate.package.choose`: the
|
||||
pack's decks are variants of its mod, which its `reskate-plugin.json` declares. Nothing in ReSkate
|
||||
knows Board Break.
|
||||
|
||||
## What the player gets
|
||||
|
||||
@@ -28,10 +26,9 @@ the mod list in [mod_catalog.cpp](../Engine/Vfs/mod_catalog.cpp).
|
||||
in between (the force is the bail cause's that led to the wipeout). Now and then a board gives way
|
||||
while it is ridden: the nose goes.
|
||||
- `boardbreak 0|1`, `boardbreak snap [nose|mid|tail]` to look at a break (that one stays until
|
||||
`boardbreak mend` or a respawn), from the plugin; its settings are on its page in the overlay's PLUGINS
|
||||
section. `boarddeck [name|number|next]` (core) and the overlay's BREAKABLE DECK card on the
|
||||
Mods page pick the deck: a press asks for that deck, the mods are applied and the level loads
|
||||
again with it.
|
||||
`boardbreak mend` or a respawn). Its settings are on its page in the overlay's PLUGINS section.
|
||||
`boardbreak deck [name|number|next]` and the DECK card on that page pick the deck: a press asks
|
||||
for that deck, the mods are applied and the level loads again with it.
|
||||
- A break plays back in the replay editor as it happened.
|
||||
- **Wear and tear.** Each deck's board wears from 0% (new) to 100% (worn out): a landing coming down
|
||||
faster than 3.5 m/s, a hit onto a rail or ledge (harder on a slide than on the trucks), every second
|
||||
@@ -46,14 +43,12 @@ the mod list in [mod_catalog.cpp](../Engine/Vfs/mod_catalog.cpp).
|
||||
rider goes down with it. Grinds on the trucks never do.
|
||||
- **Sounds.** A crack by the size of the break, a metal one on top when the board broke on metal,
|
||||
and the body's hits in a bail, louder the harder they land.
|
||||
- **Settings**, on the overlay's Skater page in a card BOARD BREAK SETTINGS (with how worn the board
|
||||
is): always break (for replay clips), rail snaps, wear and tear, break sounds, body hit sounds,
|
||||
break sensitivity (10% to 400%), how many breaks the grip tape holds (0% to 100%), wear speed (0%
|
||||
to 500%), and New board. Always break and wear and tear are also rows in the game's Mod Options.
|
||||
The console has them all: `boardbreak always|sensitivity|joined|rails|wear|wearrate|cracks|bodysounds
|
||||
[value]`, `boardbreak worn [percent]`, `boardbreak status`, and for metal `boardbreak metal
|
||||
mark|unmark|clear|list` and `boardbreak materials`. They are kept, with each deck's wear and the
|
||||
materials marked as metal, in `%LOCALAPPDATA%\ReSkate\BoardBreak.settings`.
|
||||
- **Settings**, on the plugin's page in the overlay's PLUGINS section (with how worn the board is):
|
||||
always break (for replay clips), rail snaps, wear and tear, break sounds, body hit sounds, break
|
||||
sensitivity, how many breaks the grip tape holds, wear speed, and New board. The console has them
|
||||
all: `boardbreak always|sensitivity|joined|rails|wear|wearrate|cracks|bodysounds [value]`,
|
||||
`boardbreak worn [percent]`, `boardbreak status`. They are kept, with the board's wear, in the
|
||||
plugin's storage.
|
||||
- Without a deck pack installed nothing breaks and nothing is changed.
|
||||
|
||||
## How it works
|
||||
@@ -82,18 +77,15 @@ the mod list in [mod_catalog.cpp](../Engine/Vfs/mod_catalog.cpp).
|
||||
that passes the hook (the local one, other players'), the stretches of a whole board are moved
|
||||
away like a broken board's deck. The call into Board Break is the last thing the hook does, after
|
||||
another player's pose has been written, so that pose's bones do not bring them back.
|
||||
- **Which deck is in the game** is a question for the mod list, because any mod that reshapes the
|
||||
deck replaces the same mesh and the one higher in the order has it. When the mods are put
|
||||
together, the Board Break deck the player chose goes first, and what would fight it is set
|
||||
aside for the run: the other Board Break decks, and other mods whose bundle lists name the
|
||||
deck's bundle. Those are left out whole (with the breakable deck in place of its own, a wide-deck
|
||||
mod has its trucks and wheels on a deck they were not made for). mods.json is not changed; the
|
||||
mod list shows them as SET ASIDE.
|
||||
- **Another deck without a restart.** The deck mesh is in the items superbundle, which a live apply
|
||||
of the mods already refreshes, and the game reads the mesh when a level loads. Choosing a deck
|
||||
saves the choice, applies the mods and loads the level again (live_mods.h).
|
||||
- **The choice** is a line in `%LOCALAPPDATA%\ReSkate\BoardBreak.deck`, not a profile preference:
|
||||
the mods are put together before the profile is there.
|
||||
- **Which deck is in the game.** Any mod that reshapes the deck replaces the same mesh, so the
|
||||
pack's decks are variants of its mod: one is in the game at a time, the one the player chose
|
||||
(else the first of the manifest's `order`). The manifest names the deck's bundle in `displaces`,
|
||||
so any other mod that brings a deck model is set aside while a deck is in the game (with the
|
||||
breakable deck in place of its own, a wide-deck mod has its trucks and wheels on a deck they
|
||||
were not made for). The mod list shows those as SET ASIDE.
|
||||
- **Another deck without a restart.** `reskate.package.choose(deck)` keeps the choice, applies the
|
||||
mods and loads the level again: the deck mesh is in the items superbundle, which a live apply
|
||||
refreshes, and the game reads it when a level loads.
|
||||
- **The sound** is a wave file from the `sounds` folder of an installed deck pack (subfolders
|
||||
`light`, `medium`, `heavy`, by the size of the break), played straight to the speakers.
|
||||
- **The slam's force** comes through No Bail's existing hooks: the cause it records for the watched
|
||||
@@ -139,35 +131,35 @@ the mod list in [mod_catalog.cpp](../Engine/Vfs/mod_catalog.cpp).
|
||||
- **The sounds** play through XAudio2 on a thread of their own, several at once and each at its own
|
||||
loudness; 16-bit and 32-bit float wave files both play.
|
||||
- **Wider decks, wider trucks.** The game puts each wheel on its truck's bone along the axle, about
|
||||
0.0876 m out. A deck that says so (deck.ini `axle`) has its wheels set further apart, or closer,
|
||||
by the render pose hook: set, not scaled, so a pose that comes by twice is not moved twice, and
|
||||
only what is drawn changes. The deck's own truck model is made to match.
|
||||
- Off, the board holds. Without a deck pack in the game the hook returns at once.
|
||||
0.0876 m out. A deck that says so (deck.ini `axle`) has its wheels set further apart, or closer:
|
||||
the plugin reads it and asks `reskate.board.fit{plates = true, axle = ...}`, which sets them in
|
||||
the render pose hook (set, not scaled, so a pose that comes by twice is not moved twice, and only
|
||||
what is drawn changes) and holds the baseplates on the deck, on every board. The deck's own truck
|
||||
model is made to match.
|
||||
- Off, the board holds. With no deck in the game the plugin fits nothing.
|
||||
|
||||
## The deck packs
|
||||
## The deck pack
|
||||
|
||||
A deck is a content mod's copy of the deck model (no code), and comes in one of two ways:
|
||||
A deck is a copy of the deck model (no code). The Board Break deck pack holds a deck in each
|
||||
`decks/<name>/`, laid out like a mod folder (`layout.toc`, `Win32/...`), and the plugin beside
|
||||
them (`reskate-plugin.json`, `plugin/`). The plugin's manifest declares the decks:
|
||||
|
||||
- a mod folder named `Board_Break_<Name>` holds the deck `<name>`;
|
||||
- a deck pack, a mod folder of any name, holds a deck in each `decks/<name>/`, laid out like a mod
|
||||
folder (`layout.toc`, `Win32/...`). The launcher installs one mod folder per package, so this is
|
||||
how one package brings every deck. When the mods are put together each deck inside becomes a mod
|
||||
of its own for the run, listed as `<folder>#<name>`: it is chosen, set aside and switched like a
|
||||
deck in a folder of its own (its archives are placed like a disabled mod's). mods.json and the
|
||||
mod list only know the pack, which counts as loaded when one of its decks is. The launcher takes
|
||||
a folder for a mod only when it has a `layout.toc` of its own. That layout is not one of the
|
||||
pack's decks, whatever the folder is named, and is set aside like any other deck model; it is
|
||||
what an older ReSkate loads from the pack. ReSkate 2.0.6 knows a deck by its folder's name only,
|
||||
so a pack in a folder named `Board_Break_<Name>` (the package `Board_Break_Pack`, installed as
|
||||
`Team-Board_Break_Pack`) with a breakable deck as its own layout breaks boards there with that
|
||||
one deck, and brings all its decks from this version on. The truck model with the baseplates on
|
||||
the effectors belongs in the decks inside the pack only: a ReSkate that does not place those
|
||||
bones would draw the baseplates turning with the hangers, and such a version reads the pack's
|
||||
own layout, never `decks/`.
|
||||
```json
|
||||
"variants": {
|
||||
"folder": "decks",
|
||||
"order": ["standard", "wide", "concave", "powell", "slim", "egg", "square", "shaped", "oldschool", "pig"],
|
||||
"displaces": ["deck_gen_popsicle_cas_main_bundlereftable"]
|
||||
}
|
||||
```
|
||||
|
||||
The name is what the deck goes by. The ten the feature was made with are standard, wide,
|
||||
concave, powell, slim, egg, square, shaped, oldschool and pig, and the console also knows those by
|
||||
number. Any other deck that follows the recipe works, with no change to ReSkate:
|
||||
The pack's own `layout.toc` is set aside while one of its decks is in the game; it is what an older
|
||||
ReSkate loads from the pack. The truck model with the baseplates on the effectors belongs in the
|
||||
decks inside the pack only: a ReSkate that does not place those bones would draw the baseplates
|
||||
turning with the hangers, and such a version reads the pack's own layout, never `decks/`.
|
||||
|
||||
The name is what the deck goes by (its folder's name: letters, digits, `_` and `-`). The ten the
|
||||
feature was made with are in the manifest's `order`, which is also how the console numbers them.
|
||||
Any other deck folder that follows the recipe works, with no change to ReSkate or the plugin:
|
||||
|
||||
- Start from the deck mesh as ReSkate Studio exports it (three parts on the bone Deck: the grip
|
||||
sheet, the wood, and a plain copy of the whole deck). Studio only takes back a mesh whose
|
||||
@@ -186,10 +178,9 @@ number. Any other deck that follows the recipe works, with no change to ReSkate:
|
||||
- The sounds are `sounds/light|medium|heavy|metal|body/*.wav` in the folder of any mod that brings
|
||||
a deck (a crack size without sounds of its own takes the nearest that has some), and
|
||||
`sounds/metal/materials.txt` may list the level's materials that are metal, by number.
|
||||
- A deck may say something of itself in a `deck.ini` in its folder (a pack's `decks/<name>/`, or the
|
||||
`Board_Break_<Name>` folder): `label = Old School`, its name in the menus, and `axle = 1.17`, how
|
||||
far apart its wheels sit against a standard board's (0.8 to 1.6), for a deck wider or narrower
|
||||
than the standard one.
|
||||
- A deck may say something of itself in a `deck.ini` in its folder (`decks/<name>/deck.ini`):
|
||||
`label = Old School`, its name in the menus, and `axle = 1.17`, how far apart its wheels sit
|
||||
against a standard board's (0.8 to 1.6), for a deck wider or narrower than the standard one.
|
||||
|
||||
## Seen working in game
|
||||
|
||||
@@ -232,8 +223,8 @@ too fast (the rates are a third of that now).
|
||||
- The online route: all of the above ran on the offline profile.
|
||||
- The replay editor on this branch (the replay was checked on the older build the feature was
|
||||
developed on).
|
||||
- The deck card with a deck that is not one of the eight, and with none installed (it draws
|
||||
nothing then).
|
||||
- The plugin's DECK card and `boardbreak deck` (2026-10-20, built and tested without the game):
|
||||
choosing a deck, a deck that is not one of the ten, and a pack with no decks.
|
||||
- A board that does not pass the render pose hook, with the truck model from a pack: its
|
||||
baseplates would follow the hangers.
|
||||
- A mod that brings a truck model of its own beside a deck pack: the pack's is the one that loads.
|
||||
|
||||
@@ -33,3 +33,14 @@ test`) that `dingosdk_plugin_tests` runs too, and its own page in the ReSkate me
|
||||
pictures (`d:game_image`). `hallofmeat 0|1`.
|
||||
- **grind-exits**: LT / RT in a grind pick the side of the pop (`reskate.skater.grind_exit`,
|
||||
`reskate.input.hide`). `grindexit status`.
|
||||
|
||||
## Throwdown modes
|
||||
|
||||
Throwdown modes made in Lua with the throwdown kit ([throwdown-kit.md](../throwdown-kit.md)): the
|
||||
plugin registers its modes and publishes what the player should see; ReSkate shows it with skate.'s
|
||||
native Throwdowns page, setup page, flag, HUD and match panel.
|
||||
|
||||
- **throwdown-modes-test**: two modes through the whole native flow (card, setup page, flag,
|
||||
waiting card) and no match. The smallest example of the kit.
|
||||
- **SmokeyDawg58-ReSkate_Throwdown**: SmokeyDawg58's ten modes, with their rules, HUDs, gates and
|
||||
route editor, all in Lua, inside his asset mod. `tdm help`.
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
Bails leave marks on the local skater that build up over a session: road dust and a graze first,
|
||||
then scrapes and bruises, then raw wounds, a bruised face and (if the player leaves it on) blood.
|
||||
A plugin, [road-rash](plugins/road-rash); the pictures themselves come from a content mod. It was
|
||||
built into ReSkate until 2026-10; what follows is how that worked, and how the plugin still works.
|
||||
A plugin, [road-rash](plugins/road-rash), that ships inside the Road Rash item pack: the pictures
|
||||
themselves are the pack's skin items. It was built into ReSkate until 2026-10; what follows is how
|
||||
that worked, and how the plugin still works.
|
||||
|
||||
Code: the plugin's Lua in [plugins/road-rash/plugin](plugins/road-rash/plugin), and the core
|
||||
service it wears its marks through, reskate.outfit:
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
# The throwdown kit: throwdown modes in Lua
|
||||
|
||||
A throwdown mode is a plugin. ReSkate knows no particular mode: a plugin registers its modes,
|
||||
publishes documents that say what the player should see, and hears what the player does as
|
||||
events. ReSkate shows the documents with skate.'s own native widgets: the Throwdowns page, the
|
||||
setup page, the start flag, the waiting card, the in-game HUD and the match panel. A new mode needs
|
||||
no change to ReSkate.
|
||||
|
||||
Two plugins use it:
|
||||
|
||||
- [throwdown-modes-test](plugins/throwdown-modes-test): two modes through the whole native flow
|
||||
(card, setup page, flag, waiting card) and no match. The smallest example.
|
||||
- [SmokeyDawg58-ReSkate_Throwdown](plugins/SmokeyDawg58-ReSkate_Throwdown): SmokeyDawg58's ten
|
||||
modes (Deathrace, 1-UP, Spot Jam and the rest), with their rules, HUDs and route editor, all in
|
||||
Lua. The full example.
|
||||
|
||||
Everything below needs the `throwdowns` permission in `reskate-plugin.json`. A plugin's documents
|
||||
only drive its own modes, and its events only reach it.
|
||||
|
||||
## 1. Registering a mode
|
||||
|
||||
```lua
|
||||
reskate.throwdowns.mode{
|
||||
id = "duel", -- unique in the plugin, 1 to 32 characters, no "/"
|
||||
name = "Duel",
|
||||
description = "Beat the last total. Three misses and you're out.",
|
||||
art = "UI/MyMod/Throwdowns/img_duel", -- the card's logo: a texture or image asset path
|
||||
color = 0xff3434ff, -- the card's tint, 0xAABBGGRR (optional)
|
||||
card = "spot", -- the stock card it is drawn like: "skate", "spot" or "jam"
|
||||
replaces = "skate", -- optional: takes that stock card's place on the page
|
||||
order = 10, -- its place among the plugins' modes
|
||||
flag = "World/MyMod/Flags/duel_Placement", -- optional: the flag's placement preview prefab
|
||||
cursor_height = 4, -- optional: metres the placement cursor may rise onto things
|
||||
players = {min = 1, max = 6, default = 2},
|
||||
}
|
||||
```
|
||||
|
||||
Calling it again with the same id updates the mode; `reskate.throwdowns.remove_mode(id)` takes it
|
||||
off the page. The page shows the stock S.K.A.T.E. (unless a mode replaces it), Spot Battle and
|
||||
Skate Jam, then every plugin mode by `order`. Clicking a card sends the `open` event.
|
||||
|
||||
## 2. Documents
|
||||
|
||||
```lua
|
||||
reskate.throwdowns.ui{setup = ..., waiting = ..., hud = ..., panel = ..., flags = ..., match = ...}
|
||||
```
|
||||
|
||||
Publish whenever something changes; every tick is fine, since an unchanged document costs only a
|
||||
comparison. Any part left out shows nothing. In documents, `mode` is the plugin's own id ("duel").
|
||||
Colours are 0xAABBGGRR, times are milliseconds, positions are vectors in world metres, and Steam
|
||||
IDs are strings. Texts may also be numbers.
|
||||
|
||||
### setup: the setup page
|
||||
|
||||
The stock Spot Battle setup page, relabelled. It shows while the player is on it after `open`.
|
||||
|
||||
```lua
|
||||
setup = {
|
||||
mode = "duel", title = "DUEL", art = "UI/...", description = "...", back = "BACK",
|
||||
players = {caption = "Players", min = 1, max = 6, step = 1, value = 2},
|
||||
timer = {caption = "Turn", min = 10, max = 120, step = 10, value = 20}, -- nil: no timer row
|
||||
rows = { -- at most 12
|
||||
{id = "laps", kind = "choice", caption = "Laps", options = {"1", "2", "3"}, value = 1}, -- value from 1
|
||||
{id = "boost", kind = "slider", caption = "Boost", min = 0, max = 5, step = 1, value = 2},
|
||||
{id = "route", kind = "button", caption = "Route", label = "Place gates"},
|
||||
{id = "note", kind = "info", caption = "Area", label = "Anywhere"},
|
||||
},
|
||||
hide_native = {"rounds"}, -- stock rows taken off (the default)
|
||||
}
|
||||
```
|
||||
|
||||
Moving a slider or a choice sends `setup_row`; pressing a button row sends `setup_button`. Confirm
|
||||
places the start flag (section 4).
|
||||
|
||||
### waiting: the waiting card
|
||||
|
||||
Shown while the flag is down and the match has not started.
|
||||
|
||||
```lua
|
||||
waiting = {mode = "duel", title = "DUEL", art = "UI/...", status = "Enrolled skaters | Host starts",
|
||||
enrolled = 1, capacity = 6, can_start = true,
|
||||
countdown = {remaining_ms = 5000, total_ms = 10000}} -- optional
|
||||
```
|
||||
|
||||
Start sends `start`, Leave sends `leave`.
|
||||
|
||||
### hud: the in-game HUD
|
||||
|
||||
Slots of the native HUD, drawn with the widget family `theme` names (`HUD_<theme>_Title_..._Widget`
|
||||
and so on; a mod brings its own in its assets). Every slot is optional.
|
||||
|
||||
```lua
|
||||
hud = {
|
||||
active = true, theme = "race",
|
||||
header = {title, art, status, offset = {x, y}, icon_size = 96, frame_width = 704}, -- 0: the theme's
|
||||
layout = "side", -- where the board sits: "side" (right edge) or "bottom"
|
||||
counters = {"LEADER 1,200", "SCORE 900"}, score_width = 480, score_art = "",
|
||||
clock = Clock, -- the match clock
|
||||
board = {title = "LEADERBOARD", columns = {"POS", "NAME", "SCORE"},
|
||||
variant = "", -- "stamps": a stamp per mark instead of joined letters
|
||||
style = "outlined", -- or "plain"
|
||||
heading = "list", -- or "shared"
|
||||
name_art = "", out_art = "", rank_art = "", value_art = "", value_width = 0, reserve = "",
|
||||
rows = {BoardRow, ...}},
|
||||
results = {title, notice, caption, heading_art = "", title_width = 0, style = "outlined", rows = {BoardRow, ...}},
|
||||
intro = {title, art_key, rules, until_ms},
|
||||
countdown = Clock, -- 3-2-1-GO
|
||||
banner = {title, subtitle, art, serial, ms}, -- a new serial shows it again
|
||||
callout = {text, style, serial, ms},
|
||||
warning = {text, art, serial, ms},
|
||||
card = {caption, title, image}, -- a trick card; image is a texture path
|
||||
list = {caption, items = {"KICKFLIP", ...}},
|
||||
position = {place = 1, medal = "gold", art = ""}, -- "gold" | "silver" | "bronze" | "white"
|
||||
timers = {{caption, text = "0:12.40" or Clock}, ...}, timer_art = "",
|
||||
compass = {at = vector, art = "UI/..."},
|
||||
markers = {{at = vector, text = "GATE 3", distance = true}, ...}, -- distance from the skater
|
||||
blackout = {text},
|
||||
editor = {title, variant = "builder", -- or "compact"
|
||||
prompts = {{inputs = {"UI_DpadLeft"}, caption = "Move", glyph = "", hold = 0.5}, ...},
|
||||
info = {title, rows = {{caption, value}, ...}},
|
||||
toast = {text, alpha},
|
||||
modal = {text, actions = {{input, caption}, ...}}},
|
||||
}
|
||||
-- BoardRow: {rank, name, value, color, self = bool, out = bool,
|
||||
-- marks = {{text = "S", on = true}, ...}, clock = Clock}
|
||||
-- Clock: {remaining_ms, total_ms, sampled_ms, ticking = true, up = false}, or a stopwatch
|
||||
-- {base_ms, sampled_ms, running, cap_ms}. The HUD ticks a clock itself between documents;
|
||||
-- sampled_ms is reskate.time.now() when the numbers were true.
|
||||
```
|
||||
|
||||
### panel: the match panel
|
||||
|
||||
The native details page the pause menu opens during a match.
|
||||
|
||||
```lua
|
||||
panel = {title, description, art, score_caption = "SCORE", quit = "Quit",
|
||||
settings = {{icon = "players", caption = "Players", value = "4"}, ...}, -- at most 3;
|
||||
-- icon "players" | "timer" | "rounds" | a texture
|
||||
prompts = {{input = "UI_ShoulderL", caption = "Spectate", command = "spectate"}, ...},
|
||||
players = {{id = "7656...", name, value, rank, outcome, portrait = "steam", self = true}, ...}}
|
||||
```
|
||||
|
||||
Opening it sends `panel_open`; a prompt's button sends `panel_command` with its command.
|
||||
|
||||
### flags: flags for other players
|
||||
|
||||
```lua
|
||||
flags = {{id = "f1", mode = "duel", leader = "7656...", game = 123, at = vector, yaw = 0,
|
||||
players = 1, capacity = 6, open = true,
|
||||
stats = {{title = "LAPS", value = "3"}, ...}}} -- at most 3
|
||||
```
|
||||
|
||||
Each shows on other players' games as a native flag (map point, bubble, map card, Enroll card).
|
||||
Their Join reaches this plugin on their game as `join`.
|
||||
|
||||
### match: what a running match asks of the game
|
||||
|
||||
```lua
|
||||
match = {markers = true, -- session markers and Return are blocked; the pause menu's Quit is the plugin's
|
||||
input_lock = true, -- no skating input (a countdown)
|
||||
offboard = true, -- the skater is kept off the board
|
||||
hidden = {"7656..."},-- players whose skater, nametag, map dot and chat bubble are hidden
|
||||
teleports = true, -- the plugin may teleport the skater even where noclip is off
|
||||
in_activity = true} -- the game treats the player as in an activity
|
||||
```
|
||||
|
||||
## 3. Events
|
||||
|
||||
```lua
|
||||
reskate.on("throwdown_ui", function(e) -- e = {action, mode, args}: args are strings
|
||||
end)
|
||||
```
|
||||
|
||||
| action | args |
|
||||
| --- | --- |
|
||||
| `open` | game: a card was clicked, and the flag registration began (section 4) |
|
||||
| `setup_row` | row id ("players" and "timer" for those), value (a choice's from 0) |
|
||||
| `setup_button` | row id |
|
||||
| `setup_back` | game |
|
||||
| `setup_confirm` | players, timer seconds |
|
||||
| `flag_placed` | game, x, y, z, yaw |
|
||||
| `flag_left` | game |
|
||||
| `start` | game |
|
||||
| `leave` | game |
|
||||
| `quit` | (the pause menu's or the panel's Quit) |
|
||||
| `join` | flag id, leader, game |
|
||||
| `panel_open` | |
|
||||
| `panel_command` | command |
|
||||
| `dialog` | dialog id, button, text, row, file text (section 5) |
|
||||
|
||||
## 4. The native flag
|
||||
|
||||
One native flag registration exists at a time. Clicking a mode's card begins it at once, with the
|
||||
mode's players and the setup page, and then sends `open {game}`. Confirm on the setup page goes on
|
||||
to native flag placement (`setup_confirm`, then `flag_placed`), then to the waiting card, until the
|
||||
plugin starts the match or the owner leaves.
|
||||
|
||||
```lua
|
||||
reskate.throwdowns.flag.begin(mode, game, {players, seconds, setup_page = true, cursor_height})
|
||||
-- false while another registration is busy; setup_page = false goes straight to placement
|
||||
reskate.throwdowns.flag.state()
|
||||
-- {owned, waiting, placing, busy, mine, mode, game}: mode and game only when it is one of the plugin's
|
||||
reskate.throwdowns.flag.leave() -- refused, finished or cancelled: the registration goes
|
||||
```
|
||||
|
||||
## 5. Services a mode uses
|
||||
|
||||
None of these knows a throwdown mode; any plugin may use them under its permission.
|
||||
|
||||
| Call | Permission | What it does |
|
||||
| --- | --- | --- |
|
||||
| `reskate.files.list/read/write/remove(path)` | files | the plugin's own data folder, for saved routes and the like: 1 MB a file, 1000 files, 64 calls a second |
|
||||
| `reskate.ui.dialog(id, {title, message, field, list, buttons, file})`, `reskate.ui.close_dialog(id)` | ui.screen and throwdowns | an overlay dialog: a text field, a list with buttons on each row, up to 4 buttons, a file to open; answers come as `dialog` events, Esc answers "cancel" |
|
||||
| `reskate.skater.push(velocity)`, `push_wait()`, `push_reset()` | skater.control | the skater's velocity once it is back on its board |
|
||||
| `reskate.skater.hold(on)` | skater.control | the skater held where it is |
|
||||
| `reskate.physics.competition(on)`, `stock_ready()`, `prepare()` | skater.control | the game's stock physics while the player competes |
|
||||
| `reskate.skater.telemetry()`, `reskate.skater.goofy()` | skater.read | speed, air time, the last jump, the physics state |
|
||||
| `reskate.skater.bone_cam(word, ...)` | camera | the Bone Cam |
|
||||
| `reskate.camera.free(...)`, `reskate.camera.pad_flight(on)` | camera | the free camera, flown from the pad while placing things from the air |
|
||||
| `reskate.session.world()`, `reskate.session.spectate(...)` | session.read | the session's world id and map; spectating a player |
|
||||
| `reskate.tricks.feed(on)`, `reskate.tricks.gesture(name)` | events.tricks | skate.'s trick list as `trick_notes` events; a flip trick's flick diagram |
|
||||
| `reskate.input.pad_bits/key/wheel/game_buttons/allowed/focus` | input | the pad, keys and wheel, and game buttons kept from the game |
|
||||
| `reskate.entities.set(id, blueprint, transform, hidden?)`, `remove`, `clear`, `ready`, `status` | world.entities | world objects of the plugin's own (gates, arrows, flags) |
|
||||
Reference in new issue
Block a user