Menus
Screens a client script opens over the game: a buy menu, a vote, a dialog asking a question. A menu frees the mouse and takes keys; one opens at a time, and a dialog opens over it and gives back its answer. A menu may open on a purpose action’s key, as a buy menu on buy, which the player chose for every server.
Here too is the loading screen a mod may draw in place of the stock one while players load a match. The stock one lists the purpose actions your mod handles, with their labels and the player’s keys; your own gets them as props.binds.
loading_screen
Section titled “loading_screen”loading_screen(component)Draws the loading screen in place of the stock one while the match loads, once a mod, at a script's top.
The component is given {map, title, image, gametype, stage, progress, bytes_done, bytes_total, bytes_per_second, binds} and draws again as they or what it read change. title and image are the map’s, image nil for none.
While connecting, map and gametype are empty and title is the server’s address. stage is "connecting",
"waiting" (while the mod’s connecting holds the join), "downloading", "map", "files" or
"declarations"; progress is the share of the match’s files loaded, 0 to 1, or while downloading of the bytes,
bytes_done of bytes_total coming at bytes_per_second, all 0 at the other stages. binds are the purpose
actions the server handles, each {action, label, keys}: the action, as "tactical", the label it has here, and
the keys the player put it on, the first as Controls shows it first, empty for none.
It takes no pointer and goes once the match plays. The stock screen shows while none is declared, and from when its render fails until the match plays. Another script’s call fails, naming both.
| Name | Type | What it is |
|---|---|---|
component | (props: LoadingProps) -> Node? | Needed. |
- Fails
- a value of the wrong type
To show the map and a bar
Section titled “To show the map and a bar”loading_screen(function(props) return Box { `{props.title} ({props.stage})`, Box { style = { width = `{props.progress * 100}%`, height = 8, background = "#ffcc33" } }, style = { left = 0, right = 0, bottom = 80, padding = 40, background = "rgba(0, 0, 0, 0.6)" }, }end)To list the keys of what the server’s mod does on them
Section titled “To list the keys of what the server’s mod does on them”loading_screen(function(props) return Box { Each(props.binds, function(bind) return Box { `{bind.keys[1] or "unbound"}: {bind.label}`, key = bind.action } end), style = { left = 80, top = 80, fontSize = 28 }, }end)menu(name, options?, render) → MenuDeclares a menu, which open(menu, props) shows over the HUD, freeing the pointer; gives its handle.
It is declared at a script’s top. Its name is up to 16 lowercase letters, digits and _, one script’s: another
script declaring it fails, naming both. render is given the props open gave, copied, with close(value),
which closes it. One menu is open at a time, open replacing it. A player opens one with its action’s key, a key
they bind to open <name>, or /open <name>, with no props.
While a menu shows, the player’s binds do nothing and the keys held are let go. A tap of Esc runs its
keys.Escape, false for a forced choice, or else opens its back, or else closes it. Holding Esc a second always
opens the engine’s menu over the game, a ring filling from a quarter second: no script sees the hold.
action takes a purpose action, as "buy", which no mod binds to a key: the player has, once for every server. Two
menus on one action fail at load. A menu on an action the server handles opens as its handler hears the key go
down.
| Name | Type | What it is |
|---|---|---|
name | string | Needed. |
options | table? | A table of the options below. It, and each option, may be left out. |
pointer | booleandefault true | Frees the pointer, its tree taking hover and clicks, and takes every key; false keeps the player playing
but for its keys, which cannot then be Esc: the keys the player moves, jumps and chats with stay theirs. |
keys | ({[string]: ((props: MenuProps) -> ()) | false})? | What its keys do, as { Q = fn, ["1"] = fn, Enter = fn, Escape = false }: a key a player binds or Escape,
each given the props, false doing nothing; Mouse1 and Mouse2 only with pointer = false, as they click. |
onOpen | ((props: MenuProps) -> ())? | Runs as it opens, given the props. |
onClose | ((props: MenuProps) -> ())? | Runs as it closes, given the props. |
back | string? | The menu a tap of Esc opens in its place, by name, rather than closing it. |
toggle | booleandefault false | A key bound to open it, or to its action, closes it. |
action | ("tactical" | "lethal" | "utility" | "ultimate" | "buy" | "drop" | "quick_menu" | "ping" | "map")? | The purpose action whose keys open it, as "buy"; the server's handler of it runs too. |
hold | booleandefault false | Closes as the key that opened it is let go. |
help | string? | Its line on Settings → Controls, up to 64 bytes. |
render | (props: MenuProps) -> Node? | Needed. |
- Returns
Menu- Fails
- a value of the wrong type
- an option it does not have
To open a shop on the player’s buy key
Section titled “To open a shop on the player’s buy key”local Shop = menu("shop", { action = "buy", toggle = true, help = "Buy weapons" }, function(props) return Box { "Shop", Box { "Close", onClick = function() props.close() end }, style = { left = "40%", top = "30%", padding = 24, background = "rgba(0, 0, 0, 0.8)" }, }end)dialog
Section titled “dialog”dialog(name, options?, render) → MenuDeclares a dialog, which open(dialog, props) shows over the menu, waiting for its answer; gives its handle.
It is declared at a script’s top, as a menu is. One dialog is open at a time, over the menu if one is. open of
one waits, in a handler only, until it closes, and gives what props.close(value) passed, or nil if it closed
otherwise: by Esc, which closes it unanswered unless its keys.Escape says, another dialog, or its menu closing.
| Name | Type | What it is |
|---|---|---|
name | string | Needed. |
options | table? | A table of the options below. It, and each option, may be left out. |
pointer | booleandefault true | Frees the pointer, its tree taking hover and clicks, and takes every key; false keeps the player playing
but for its keys, which cannot then be Esc: the keys the player moves, jumps and chats with stay theirs. |
keys | ({[string]: ((props: MenuProps) -> ()) | false})? | What its keys do, as { Q = fn, ["1"] = fn, Enter = fn, Escape = false }: a key a player binds or Escape,
each given the props, false doing nothing; Mouse1 and Mouse2 only with pointer = false, as they click. |
onOpen | ((props: MenuProps) -> ())? | Runs as it opens, given the props. |
onClose | ((props: MenuProps) -> ())? | Runs as it closes, given the props. |
render | (props: MenuProps) -> Node? | Needed. |
- Returns
Menu- Fails
- a value of the wrong type
- an option it does not have
To ask before buying
Section titled “To ask before buying”local Confirm = dialog("confirm", { keys = { Enter = function(props) props.close(true) end } }, function(props) return Box { props.question, Box { "Yes", onClick = function() props.close(true) end }, Box { "No", onClick = function() props.close(false) end }, }end)local Shop = menu("shop", nil, function() return Box { "Buy the MP40", onClick = function() if open(Confirm, { question = "Buy the MP40?" }) then request("buy") end end, }end)open(menu, props?) → anyOpens a menu, in place of the one open, or a dialog over it, its render given a copy of props with close(value); a dialog's open gives its answer.
A dialog opens in a handler alone, on, onClick, a menu’s key or onOpen, as it waits until it closes: then
it gives what props.close(value) passed, or nil if it closed otherwise.
| Name | Type | What it is |
|---|---|---|
menu | Menu | Needed. |
props | ({[string]: any})? | May be left out. |
- Returns
any- Fails
- a value of the wrong type
To open the shop when the player says so
Section titled “To open the shop when the player says so”local Shop = menu("shop", nil, function(props) return Box { `Shop, opened by {props.by}`, onClick = function() props.close() end }end)on("said", function(e) if e.text == "shop" then open(Shop, { by = "chat" }) endend)close(menu)Closes a menu, and a dialog over it, or a dialog, unanswered; one not open is left as it is.
| Name | Type | What it is |
|---|---|---|
menu | Menu | Needed. |
- Fails
- a value of the wrong type
To close the shop as the player dies
Section titled “To close the shop as the player dies”local Shop = menu("shop", nil, function() return Box { "Shop" } end)on("killed", function(e) if e.victim == me then close(Shop) endend)is_open
Section titled “is_open”is_open(menu) → booleanWhether a menu or a dialog is open: a read a render draws again on.
| Name | Type | What it is |
|---|---|---|
menu | Menu | Needed. |
- Returns
boolean- Fails
- a value of the wrong type
To dim the HUD while the shop is open
Section titled “To dim the HUD while the shop is open”local Shop = menu("shop", nil, function() return Box { "Shop" } end)mount(function() return Box { "Round 1", style = { left = 40, top = 40, opacity = if is_open(Shop) then 0.3 else 1 } }end)escape_menu
Section titled “escape_menu”escape_menu(menu)Names what a tap of Esc opens while nothing is open, in place of the engine's menu: a menu, or a function asked at each tap, whose nil opens the engine's.
A mod calls it once, at a script’s top; another script’s call fails, naming both. Holding Esc a second always opens the engine’s menu.
| Name | Type | What it is |
|---|---|---|
menu | Menu | () -> Menu? | Needed. |
- Fails
- a value of the wrong type
To open the mod’s own pause menu
Section titled “To open the mod’s own pause menu”local Pause = menu("pause", nil, function(props) return Box { "Paused", Box { "Resume", onClick = function() props.close() end } }end)escape_menu(Pause)