{
  "version": "0.1",
  "items": [
    {
      "name": "highlight",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "summary": "Sets how the entities this player sees are drawn, at no network cost: `rule` gives each a highlight, or nil for none.",
      "doc": "Sets how the entities this player sees are drawn, at no network cost: `rule` gives each a highlight, or nil for\nnone.\n\nIt is given at a script's top, one rule a script, and asked of each body, NPC, prop, shape and part drawn as it\nappears, given its entity, and again only as what it read changes, as a render is. With several scripts' rules,\nthe last loaded that gives one wins. A highlight is `{fill, filter, outline, through_walls, transition}`: `fill` a\nCSS colour mixed over the entity by its alpha, `\"#ffffff\"` a flat silhouette; `filter` CSS's functions but\n`blur()`; `outline` a width of up to 4 pixels and a colour, `\"2px #ffcc33\"`; `through_walls` shows the fill and the\noutline where the entity is hidden; `transition` eases it in and out, its seconds finite.\n\nWhat rides an entity is drawn as it is, unless highlighted itself; the weapon before the eyes never is. Highlights\nare drawn as the HUD's `zIndex` 0 starts, over a frame filter below it, so greying the world leaves highlighted\nbodies as they are. 16 different ones show at once among what the camera sees, past which the rest are drawn\nplain. A highlight shows only what the server sends this player.\n\nA new highlight eases in by its own transition and the last out by its own; an entity that comes into view is\nshown highlighted at once.",
      "params": [
        {
          "name": "rule",
          "type": "(entity: Entity) -> Highlight?"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To outline the zombies through walls",
          "side": "client",
          "code": "highlight(function(e)\n    if e.kind == \"npc\" then\n        return { outline = \"2px #ff3333\", through_walls = true, transition = { seconds = 0.2 } }\n    end\n    return nil\nend)\n"
        },
        {
          "title": "To see in thermal",
          "side": "client",
          "code": "view:set({ exposure = 0.5 })\nmount(function()\n    local filter = \"grayscale(1) contrast(1.4)\"\n    return Box { style = { left = 0, top = 0, right = 0, bottom = 0, zIndex = -1, backdropFilter = filter } }\nend)\nhighlight(function(e)\n    if e.kind == \"player\" or e.kind == \"npc\" then\n        return { filter = \"grayscale(1) brightness(3)\", fill = \"rgba(255, 255, 255, 0.3)\" }\n    end\n    return nil\nend)\n"
        }
      ]
    },
    {
      "name": "keyframes",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "summary": "Defines keyframes, as CSS's `@keyframes`, which a style's `animation` plays by name; nil frames remove them.",
      "doc": "Defines keyframes, as CSS's `@keyframes`, which a style's `animation` plays by name; nil frames remove them.\n\n`frames` is keyed `\"from\"`, `\"to\"` or a percentage, a comma between several, each a style of the properties\n`transition` eases and its own `animationTimingFunction`, 8 keyframes at most. A name is up to 16 lowercase\nletters, digits and `_`, but no word `animation` takes, such as `linear`. An animation drawn again under its name\nplays on; one whose name went away starts over. A style plays 4 animations at most.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "frames",
          "type": "{[string]: Style}",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To pulse a warning",
          "side": "client",
          "code": "keyframes(\"pulse\", {\n    from = { opacity = 1 },\n    [\"50%\"] = { opacity = 0.3, animationTimingFunction = \"ease-in\" },\n    to = { opacity = 1 },\n})\nmount(function()\n    return Box { \"LOW AMMO\", style = { left = 40, top = 80, color = \"#ff3333\", animation = \"pulse 1s infinite\" } }\nend)\n"
        }
      ]
    },
    {
      "name": "set",
      "group": "Boxes and styles",
      "side": "client",
      "on": "View",
      "since": "0.1",
      "summary": "Changes how this player's view looks, at no network cost, each value given eased by `transition`, at once without one; the rest stay as they are, the last set winning.",
      "doc": "Changes how this player's view looks, at no network cost, each value given eased by `transition`, at once\nwithout one; the rest stay as they are, the last set winning.\n\n`view.fov`, `view.exposure`, `view.fog`, `view.listener` and `view.crosshair` read back what was last set, `fov`\nand `fog` nil while the player's and the map's own. A fog is exponential: `half_at` metres away, half of what lies\nthere is hidden; `{half_at = math.huge}` is none. A frame takes 64 changes to the view at most.",
      "params": [
        {
          "name": "values",
          "fields": [
            {
              "name": "fov",
              "doc": "The field of view, in degrees across a 4:3 screen as the player's `fov` setting has them, over the setting\nand the weapon's sights; `false` for the player's own.",
              "type": "number | false",
              "optional": true
            },
            {
              "name": "exposure",
              "doc": "How bright the scene is before tone mapping, 1 as without it; the HUD is as bright as ever.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                null
              ]
            },
            {
              "name": "fog",
              "doc": "A fog over the map's, the sky fading into it; `false` for the map's own.",
              "type": "Fog | false",
              "optional": true
            },
            {
              "name": "listener",
              "doc": "Where the sound is heard: at the view, wherever the mod's camera puts it, or at the eyes of the body the view\nis of; at once, whatever the transition.",
              "type": "\"camera\" | \"body\"",
              "optional": true
            },
            {
              "name": "crosshair",
              "doc": "Whether the engine's crosshair shows, fading.",
              "type": "boolean",
              "optional": true
            }
          ]
        },
        {
          "name": "transition",
          "type": "Transition",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To zoom in through a scope, then back",
          "side": "client",
          "code": "view:set({ fov = 20 }, { seconds = 0.2, timing = \"ease-out\" })\nview:set({ fov = false }, { seconds = 0.2 })\n"
        },
        {
          "title": "To fade into a thick fog",
          "side": "client",
          "code": "view:set({ fog = { color = \"#8a8f99\", half_at = 12 }, crosshair = false }, { seconds = 3 })\n"
        }
      ]
    },
    {
      "name": "stop",
      "group": "Boxes and styles",
      "side": "client",
      "on": "Shake",
      "since": "0.1",
      "summary": "Fades the shake out from where it is, at once without a transition, a later stop replacing an earlier.",
      "doc": "Fades the shake out from where it is, at once without a transition, a later stop replacing an earlier.",
      "params": [
        {
          "name": "transition",
          "type": "Transition",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To sway the aim until the player steadies it",
          "side": "client",
          "code": "local sway = shake(\"aim\", { amplitude = { yaw = 0.01, pitch = 0.01 }, frequency = 0.5 }, { seconds = math.huge })\nsway:stop({ seconds = 1 })\n"
        }
      ]
    },
    {
      "name": "shake",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "summary": "Shakes this player's view, `\"view\"`, the picture alone, or `\"aim\"`, where the player aims and shoots too, and gives its handle, whose `stop(transition)` fades it out.",
      "doc": "Shakes this player's view, `\"view\"`, the picture alone, or `\"aim\"`, where the player aims and shoots too, and gives\nits handle, whose `stop(transition)` fades it out.\n\n`transition`'s seconds are how long it lasts, above 0, `math.huge` until stopped, and its timing how it fades.\nShakes add up, 32 at once, a new one past them ending the oldest. An aim shake reaches the server with the\nplayer's aim, which a modified client could skip, as it can a weapon's kick.",
      "params": [
        {
          "name": "target",
          "type": "\"view\" | \"aim\""
        },
        {
          "name": "wave",
          "fields": [
            {
              "name": "amplitude",
              "doc": "How far it turns each way on each axis.",
              "type": "Amplitude",
              "optional": true,
              "fields": [
                {
                  "name": "yaw",
                  "doc": "About the vertical, left and right.",
                  "type": "number",
                  "optional": true,
                  "range": [
                    0.0,
                    3.141592653589793
                  ]
                },
                {
                  "name": "pitch",
                  "doc": "Up and down.",
                  "type": "number",
                  "optional": true,
                  "range": [
                    0.0,
                    3.141592653589793
                  ]
                },
                {
                  "name": "roll",
                  "doc": "About the line of sight: the view's alone, not the aim's.",
                  "type": "number",
                  "optional": true,
                  "range": [
                    0.0,
                    3.141592653589793
                  ]
                }
              ]
            },
            {
              "name": "frequency",
              "doc": "How often it turns, a second, above 0: a smooth noise rather than a sine.",
              "type": "number",
              "required": true,
              "range": [
                0.0,
                60.0
              ]
            }
          ]
        },
        {
          "name": "transition",
          "type": "Transition"
        }
      ],
      "returns": "Shake",
      "examples": [
        {
          "title": "To shake the screen as a blast goes off",
          "side": "client",
          "code": "local wave = { amplitude = { yaw = 0.02, pitch = 0.03, roll = 0.01 }, frequency = 8 }\nshake(\"view\", wave, { seconds = 1.5, timing = \"ease-out\" })\n"
        },
        {
          "title": "To sway the aim until the player steadies it",
          "side": "client",
          "code": "local sway = shake(\"aim\", { amplitude = { yaw = 0.01, pitch = 0.01 }, frequency = 0.5 }, { seconds = math.huge })\nsway:stop({ seconds = 1 })\n"
        }
      ]
    },
    {
      "name": "merge",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "summary": "Gives a component's defaults with its props over them, the caller's winning, to pass on to a `Box`.",
      "doc": "Gives a component's defaults with its props over them, the caller's winning, to pass on to a `Box`.\n\nA `style` is merged property by property, a function of `is` among them; content given replaces the default's.",
      "params": [
        {
          "name": "defaults",
          "type": "D"
        },
        {
          "name": "props",
          "type": "P"
        }
      ],
      "returns": "D & P",
      "examples": [
        {
          "title": "To make a button its caller may restyle",
          "side": "client",
          "code": "local Button = component(function(props)\n    return Box(merge({ style = { padding = \"4px 8px\", color = \"#ffffff\" } }, props))\nend)\nmount(function() return Button { \"Leave\", style = { color = \"#ff3333\" } } end)\n"
        }
      ]
    },
    {
      "name": "omit",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "summary": "Gives a copy of props without the keys named, a component's own, which a `Box` refuses.",
      "doc": "Gives a copy of props without the keys named, a component's own, which a `Box` refuses.",
      "params": [
        {
          "name": "props",
          "type": "P"
        },
        {
          "name": "keys",
          "type": "string",
          "variadic": true
        }
      ],
      "returns": "P",
      "examples": [
        {
          "title": "To pass on all but a component's own prop",
          "side": "client",
          "code": "local Badge = component(function(props)\n    return Box(merge({ if props.danger then \"!\" else \"\" }, omit(props, \"danger\")))\nend)\nmount(function() return Badge { danger = true, style = { color = \"#ff3333\" } } end)\n"
        }
      ]
    },
    {
      "name": "store",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "summary": "Gives a table of the script's own data, which a render reads as it reads the game: one that read a key renders again as it changes.",
      "doc": "Gives a table of the script's own data, which a render reads as it reads the game: one that read a key renders\nagain as it changes.\n\nIt is read and written as a table, `banner.count += 1`, gone over with `for key, value in banner`, and keyed by any\nkey a table takes. Once a frame, after the handlers, each store of a script that ran is compared deeply with its\ncopy, on the script's time. A list goes in a field, `store { items = {} }`: `table.insert`, `table.remove` and\n`table.sort` write past a store, and what they write there is dropped and said.",
      "params": [
        {
          "name": "first",
          "type": "T",
          "optional": true
        }
      ],
      "returns": "T",
      "examples": [
        {
          "title": "To count this player's kills",
          "side": "client",
          "code": "local banner = store { kills = 0 }\non(\"killed\", function(e)\n    if e.killer == me then banner.kills += 1 end\nend)\nmount(function() return Box { `{banner.kills} kills` } end)\n"
        }
      ]
    },
    {
      "name": "Box",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "summary": "A box: its content, unnamed and first, then its props, named.",
      "doc": "A box: its content, unnamed and first, then its props, named.\n\nIts content is its text, strings and numbers joined, and its children: Boxes, components' calls and lists of\nthem, flattened, `nil` and `false` skipped. Every element of a list needs a `key`, unique among its siblings; a\nnew key is a new box, its animations started again. A `style` table is read where it is written, so a property\nthe HUD lacks fails at that line; a function of `is` runs as its box renders, and again as `hovered`, `pressed`\nor `disabled` flips. No style is inherited.\n\nA root box is placed on the screen as CSS's `position: absolute`; its children flow in it. `at` and `follow` lay\na box out from a point in the world, keeping its size at any distance and showing through walls: `left` and\n`top` measure from where the point shows, `right` and `bottom` back from it. It hides while the point is behind\nthe eye or what it follows is not drawn, unless `edge`. A text is up to 256 bytes, `\\n` between lines, shown as\nwritten, braces and all. A box under more than 8 parents is not drawn. Past 8 frames' worth of pictures, or 32\nboxes reading what is behind them, a frame draws boxes without their effects, and masked ones not at all.",
      "params": [
        {
          "name": "props",
          "type": "BoxProps"
        }
      ],
      "returns": "Node",
      "examples": [
        {
          "title": "To show a player's health in a corner",
          "side": "client",
          "code": "mount(function()\n    return Box {\n        `{me.health or 0} HP`,\n        style = { right = 40, bottom = 40, fontSize = 32, color = \"#ffcc33\" },\n    }\nend)\n"
        },
        {
          "title": "To light a button up under the pointer",
          "side": "client",
          "code": "mount(function()\n    return Box {\n        \"Ready\",\n        style = function(is)\n            return { padding = \"4px 8px\", background = if is.hovered then \"#ffcc33\" else \"#333333\" }\n        end,\n        onClick = function() print(\"ready\") end,\n    }\nend)\n"
        },
        {
          "title": "To mark where a bomb was planted",
          "side": "client",
          "code": "mount(function()\n    return Box { \"BOMB\", at = vector.create(4, 1, -2), edge = true, style = { color = \"#ff3333\" } }\nend)\n"
        }
      ]
    },
    {
      "name": "Each",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "summary": "Renders each item of a list, `render(item, index)` of its 1 to `#list`, each its own redraw boundary.",
      "doc": "Renders each item of a list, `render(item, index)` of its 1 to `#list`, each its own redraw boundary.\n\nEach element it gives needs a `key`, unique among them; an item giving nil shows nothing. An item renders again\nonly as what it read changes, so a long list costs only what changed.",
      "params": [
        {
          "name": "list",
          "type": "{T}",
          "optional": true
        },
        {
          "name": "render",
          "type": "(item: T, index: number) -> Node?"
        }
      ],
      "returns": "{Node}",
      "examples": [
        {
          "title": "To list the players by name",
          "side": "client",
          "code": "mount(function()\n    local listed = {}\n    for _, p in players do\n        table.insert(listed, p)\n    end\n    return Box {\n        Each(listed, function(p) return Box { p.name, key = p.id } end),\n        style = { display = \"flex\", flexDirection = \"column\" },\n    }\nend)\n"
        }
      ]
    },
    {
      "name": "component",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "summary": "Makes a component of a function of props: a call of it, `Row { key = id, … }`, renders as its own redraw boundary.",
      "doc": "Makes a component of a function of props: a call of it, `Row { key = id, … }`, renders as its own redraw boundary.\n\nIt renders again only as what it read changes, or as its parent gives it props that differ, functions all alike.\nA component's props extend `BoxProps`, as `BoxProps & { danger: boolean? }`.",
      "params": [
        {
          "name": "render",
          "type": "(props: P) -> Node?"
        }
      ],
      "returns": "(props: P) -> Node",
      "examples": [
        {
          "title": "To make each row its own boundary",
          "side": "client",
          "code": "local Row = component(function(props)\n    return Box { props.name, style = { color = if props.dead then \"#888888\" else \"#ffffff\" } }\nend)\nmount(function()\n    return Box { Row { key = 1, name = \"Ann\", dead = false }, Row { key = 2, name = \"Bo\", dead = true } }\nend)\n"
        }
      ]
    },
    {
      "name": "mount",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "summary": "Shows a component, or a function of no props, from the first frame its match plays until its script loads again or is stopped.",
      "doc": "Shows a component, or a function of no props, from the first frame its match plays until its script loads again\nor is stopped.\n\nA render gives one `Box`, a component's call or nil, and renders again as what it read changes: `match`,\n`server`, `me`, `players`, `entities`, a store and `now(step)`; only what differs reaches the screen. Mounts are\ndrawn in the order mounted, `zIndex` ordering them, and never take the pointer. The engine's own HUD is drawn at\n`zIndex` 0: a box below it is drawn under it. For a HUD in several corners, mount each part, or give the root\n`left = 0, top = 0, right = 0, bottom = 0` and its parts `position = \"absolute\"`.\n\nWhat the scripts keep on screen, their boxes and keyframes, takes 8 MB a script and 64 MB in all, each counting\n1 KB beside its bytes; past it, the script is stopped and its trees go. A frame makes 4096 changes to the screen\nat most.",
      "params": [
        {
          "name": "component",
          "type": "(props: P) -> Node?"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To show the player's name in a corner",
          "side": "client",
          "code": "mount(function()\n    return Box { me.name or \"\", style = { left = 40, top = 40 } }\nend)\n"
        }
      ]
    },
    {
      "name": "await",
      "group": "Calls",
      "side": "server",
      "since": "0.1",
      "summary": "Pauses the handler until each task is answered, and gives their answers in order.",
      "doc": "Pauses the handler until each task is answered, and gives their answers in order.\n\nIt goes on at the first tick after the last answer came, when what it held may be gone: check a player's or an\nentity's `exists`. A task already answered, as its `done` says, gives its answer at once. A handler, a timer or a\ncommand awaits, never a module's top, `on_tick` or `on_event`. A paused handler is undone, resumed and dropped as one\npaused in `wait` is.\n\nEvery answer has `ok`, and `error` once it is false: no answer came, the call took longer than its `timeout`, or\nthe answers on their way together passed the memory the mod has left. A failed call never raises an error; one no\nhandler awaits is said once as the mod's error.",
      "params": [
        {
          "name": "tasks",
          "type": "Task",
          "variadic": true
        }
      ],
      "returns": "...Answer",
      "examples": [
        {
          "title": "To fetch two things at once",
          "side": "server",
          "code": "local rank, kills = await(\n    http.request(\"GET\", \"https://stats.example/rank/\" .. p.id),\n    http.request(\"GET\", \"https://stats.example/kills/\" .. p.id)\n)\nif rank.ok and kills.ok and p.exists then\n    print(`{p.name}: rank {json.decode(rank.body).rank}, {json.decode(kills.body).kills} kills`)\nend\n"
        }
      ]
    },
    {
      "name": "request",
      "group": "Calls",
      "side": "server",
      "table": "http",
      "since": "0.1",
      "summary": "Sends an HTTP or HTTPS request, and gives its task at once, which `await` answers.",
      "doc": "Sends an HTTP or HTTPS request, and gives its task at once, which `await` answers.\n\nAny status, 500 too, is an answer: `ok`, with `status`, `headers` and `body`. A header's name is in lower case,\nand a name sent several times has its values joined by `, `. No answer, as a refused connection or a `timeout`\npassed, fails the call, its `error` saying why. Redirects are followed, never telling the next host where they came\nfrom; a request carrying a secret, in its URL or a header, follows them only to the same scheme, host and port,\nanswering one elsewhere as it is. A call made at a module's top, or in a group, fails.",
      "params": [
        {
          "name": "method",
          "type": "string"
        },
        {
          "name": "url",
          "type": "string | Secret"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "headers",
              "doc": "Headers to send, by name; a value may be a secret.",
              "type": "{[string]: string | Secret}",
              "optional": true
            },
            {
              "name": "body",
              "doc": "The body, a string's or a buffer's bytes as they are.",
              "type": "string | buffer",
              "optional": true,
              "not_with": [
                "json"
              ]
            },
            {
              "name": "json",
              "doc": "A value sent as the body, as `json.encode` writes it, with its content type unless `headers` names one.",
              "type": "any",
              "optional": true,
              "not_with": [
                "body"
              ]
            },
            {
              "name": "timeout",
              "doc": "How long it may take, in seconds, before it fails.",
              "type": "number",
              "default": 30.0
            }
          ]
        }
      ],
      "returns": "Task",
      "examples": [
        {
          "title": "To fetch a player's rank",
          "side": "server",
          "code": "local answer = await(http.request(\"GET\", \"https://stats.example/rank/\" .. p.id))\nif answer.ok and answer.status == 200 then\n    local rank = json.decode(answer.body).rank\n    print(`{p.name} is ranked {rank}`)\nend\n"
        },
        {
          "title": "To post a kill to a stats site",
          "side": "server",
          "code": "local answer = await(http.request(\"POST\", \"https://stats.example/kills\", {\n    headers = { [\"x-server\"] = \"eu-1\" },\n    json = { player = p.name, weapon = \"weapons/ak47\" },\n    timeout = 5,\n}))\nif not answer.ok then\n    print(\"the stats site is down: \" .. answer.error)\nend\n"
        }
      ]
    },
    {
      "name": "encode",
      "group": "Calls",
      "side": "server",
      "table": "json",
      "since": "0.1",
      "summary": "Writes a value as JSON text.",
      "doc": "Writes a value as JSON text.\n\nA table of keys 1 to n is a list, an empty table too, and any other table an object of string keys, in sorted\norder; nil is null. A whole number is written without a decimal point. A table holding itself fails, as does a\nfunction, a key neither a string nor 1 to n, or text larger than the memory the mod has left.",
      "params": [
        {
          "name": "value",
          "type": "any"
        }
      ],
      "returns": "string",
      "examples": [
        {
          "title": "To save a player's stats as text",
          "side": "server",
          "code": "local text = json.encode({ name = \"ann\", kills = 4, weapons = { \"weapons/ak47\", \"weapons/usp\" } })\n"
        }
      ]
    },
    {
      "name": "decode",
      "group": "Calls",
      "side": "server",
      "table": "json",
      "since": "0.1",
      "summary": "Reads JSON text: gives its value, or nil and why it is not JSON.",
      "doc": "Reads JSON text: gives its value, or nil and why it is not JSON.\n\nAn array is a table of keys 1 to n and an object a table of string keys; null is nil, leaving a hole in a list.",
      "params": [
        {
          "name": "text",
          "type": "string"
        }
      ],
      "returns": "(any, string?)",
      "examples": [
        {
          "title": "To read what a stats site answered",
          "side": "server",
          "code": "local stats, why = json.decode('{\"rank\": 3, \"best\": null}')\nif stats then\n    print(`rank {stats.rank}`)\nelse\n    print(\"not JSON: \" .. why)\nend\n"
        }
      ]
    },
    {
      "name": "pool",
      "group": "Calls",
      "side": "server",
      "table": "sql",
      "since": "0.1",
      "summary": "Makes a pool of connections to a SQLite, Postgres or MySQL database, which connects on its first call.",
      "doc": "Makes a pool of connections to a SQLite, Postgres or MySQL database, which connects on its first call.\n\nThe URL starts `sqlite:`, `postgres://` or `mysql://`, and may be a secret. A SQLite file is in the server's\ndirectory, made if missing, and its SQL opens no other file. The pool is made at once, so a module's top may make\none: keep it in a global, as a reload in place runs a module's top again. It closes once the mod no longer holds\nit and its calls have finished.",
      "params": [
        {
          "name": "url",
          "type": "string | Secret"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "max_connections",
              "doc": "The most connections it opens at once, 10 without.",
              "type": "number",
              "optional": true,
              "range": [
                1.0,
                4294967295.0
              ]
            },
            {
              "name": "min_connections",
              "doc": "The connections it keeps open, even idle; kept within `max_connections`, refused above it when both are given.",
              "type": "number",
              "default": 0
            },
            {
              "name": "acquire_timeout",
              "doc": "How long a call waits for a free connection, in seconds, before it fails.",
              "type": "number",
              "default": 30.0
            },
            {
              "name": "idle_timeout",
              "doc": "How long a connection with no call on it stays open, in seconds.",
              "type": "number",
              "default": 600.0
            },
            {
              "name": "max_lifetime",
              "doc": "How long a connection stays open at most, in seconds, before a new one takes its place.",
              "type": "number",
              "default": 1800.0
            }
          ]
        }
      ],
      "returns": "Pool",
      "examples": [
        {
          "title": "To keep a SQLite file of stats",
          "side": "server",
          "code": "db = db or sql.pool(\"sqlite:stats.db\")\n"
        },
        {
          "title": "To share a Postgres database between servers",
          "side": "server",
          "code": "db = db or sql.pool(\"postgres://game@db.example/stats\", { max_connections = 4 })\n"
        }
      ]
    },
    {
      "name": "query",
      "group": "Calls",
      "side": "server",
      "on": "Pool",
      "since": "0.1",
      "summary": "Runs a query on one of the pool's connections, and gives its task at once, which answers `rows`.",
      "doc": "Runs a query on one of the pool's connections, and gives its task at once, which answers `rows`.\n\nThe SQL is one statement in the database's own SQL, each `?` (`$1` and on in Postgres) a parameter after it, the\noptions last. Each row is a table of its values by column name, a database's null as nil and its bytes as a\nbuffer. A call made at a module's top, or in a group, fails.",
      "params": [
        {
          "name": "sql",
          "type": "string"
        },
        {
          "name": "params",
          "type": "SqlParam",
          "variadic": true
        }
      ],
      "returns": "Task",
      "examples": [
        {
          "title": "To list the best players",
          "side": "server",
          "code": "db = db or sql.pool(\"sqlite:stats.db\")\nlocal answer = await(db:query(\"SELECT name, kills FROM players WHERE kills > ? ORDER BY kills DESC\", 5))\nif answer.ok then\n    for i, row in answer.rows do\n        print(`{i}. {row.name}, {row.kills} kills`)\n    end\nend\n"
        }
      ]
    },
    {
      "name": "execute",
      "group": "Calls",
      "side": "server",
      "on": "Pool",
      "since": "0.1",
      "summary": "Runs a statement that changes the database on one of the pool's connections, and gives its task at once, which answers the rows it `changed`.",
      "doc": "Runs a statement that changes the database on one of the pool's connections, and gives its task at once, which\nanswers the rows it `changed`.\n\nIts SQL and parameters are as `Pool:query`'s. A call made at a module's top, or in a group, fails.",
      "params": [
        {
          "name": "sql",
          "type": "string"
        },
        {
          "name": "params",
          "type": "SqlParam",
          "variadic": true
        }
      ],
      "returns": "Task",
      "examples": [
        {
          "title": "To count a player's kill",
          "side": "server",
          "code": "db = db or sql.pool(\"sqlite:stats.db\")\nlocal answer = await(db:execute(\"UPDATE players SET kills = kills + 1 WHERE name = ?\", p.name, { timeout = 5 }))\nif not answer.ok then\n    print(\"not saved: \" .. answer.error)\nend\n"
        }
      ]
    },
    {
      "name": "query",
      "group": "Calls",
      "side": "server",
      "on": "Tx",
      "since": "0.1",
      "summary": "Runs a query in the transaction, after the calls on it before, and gives its task at once, which answers `rows`.",
      "doc": "Runs a query in the transaction, after the calls on it before, and gives its task at once, which answers `rows`.\n\nIts SQL, parameters and rows are as `Pool:query`'s. One that fails rolls the transaction back, and those after it\nfail. It fails once the transaction's function has ended.",
      "params": [
        {
          "name": "sql",
          "type": "string"
        },
        {
          "name": "params",
          "type": "SqlParam",
          "variadic": true
        }
      ],
      "returns": "Task",
      "examples": [
        {
          "title": "To read a wallet within a transaction",
          "side": "server",
          "code": "db = db or sql.pool(\"sqlite:stats.db\")\nawait(db:transaction(function(tx)\n    local wallet = await(tx:query(\"SELECT points FROM wallets WHERE name = ?\", \"ann\")).rows[1]\n    print(`ann has {wallet and wallet.points or 0} points`)\nend))\n"
        }
      ]
    },
    {
      "name": "execute",
      "group": "Calls",
      "side": "server",
      "on": "Tx",
      "since": "0.1",
      "summary": "Runs a statement that changes the database in the transaction, after the calls on it before, and gives its task at once, which answers the rows it `changed`.",
      "doc": "Runs a statement that changes the database in the transaction, after the calls on it before, and gives its task at\nonce, which answers the rows it `changed`.\n\nIts SQL and parameters are as `Pool:query`'s. One that fails rolls the transaction back, and those after it fail.\nIt fails once the transaction's function has ended.",
      "params": [
        {
          "name": "sql",
          "type": "string"
        },
        {
          "name": "params",
          "type": "SqlParam",
          "variadic": true
        }
      ],
      "returns": "Task",
      "examples": [
        {
          "title": "To save a round's scores together",
          "side": "server",
          "code": "db = db or sql.pool(\"sqlite:stats.db\")\nawait(db:transaction(function(tx)\n    for _, p in players do\n        tx:execute(\"UPDATE players SET kills = kills + ? WHERE name = ?\", 1, p.name)\n    end\nend))\n"
        }
      ]
    },
    {
      "name": "transaction",
      "group": "Calls",
      "side": "server",
      "on": "Pool",
      "since": "0.1",
      "summary": "Runs a function's calls on one connection as a transaction, and gives its task at once, which answers once it is committed or rolled back.",
      "doc": "Runs a function's calls on one connection as a transaction, and gives its task at once, which answers once it is\ncommitted or rolled back.\n\nThe function runs at once, as a handler of its own given the transaction, `tx`, so it may `await`. Its `tx:query`\nand `tx:execute` go to the database in order. It commits as the function returns; it is rolled back if the\nfunction returns false or fails, a call on `tx` fails, or `timeout` passes. A call made at a module's top, or in a\ngroup, fails.",
      "params": [
        {
          "name": "fn",
          "type": "(tx: Tx) -> ...any"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "timeout",
              "doc": "How long it may take, in seconds, from its start to its commit, before it is rolled back.",
              "type": "number",
              "default": 30.0
            }
          ]
        }
      ],
      "returns": "Task",
      "examples": [
        {
          "title": "To move points from one wallet to another, or not at all",
          "side": "server",
          "code": "db = db or sql.pool(\"sqlite:stats.db\")\nlocal moved = await(db:transaction(function(tx)\n    local from = await(tx:query(\"SELECT points FROM wallets WHERE name = ?\", \"ann\")).rows[1]\n    if not from or from.points < 100 then\n        return false\n    end\n    tx:execute(\"UPDATE wallets SET points = points - 100 WHERE name = ?\", \"ann\")\n    tx:execute(\"UPDATE wallets SET points = points + 100 WHERE name = ?\", \"bob\")\nend, { timeout = 10 }))\nprint(moved.ok and \"moved\" or \"not moved: \" .. moved.error)\n"
        }
      ]
    },
    {
      "name": "connect",
      "group": "Calls",
      "side": "server",
      "table": "ws",
      "since": "0.1",
      "summary": "Connects a WebSocket, and gives its task at once, which answers `socket` once it is open.",
      "doc": "Connects a WebSocket, and gives its task at once, which answers `socket` once it is open.\n\nThe URL starts `ws://` or `wss://`, and it and a header's value may be secrets. `message` and `closed` run as\nhandlers of the module that connected, in the order the socket heard, never a player's; what they hear has secrets\nhidden. The messages on their way, either way, count against the memory the mod has left, the socket closing past\nit. A socket closes once the mod no longer holds it, unless one of its own callbacks holds it, and with its match:\nreconnecting is the mod's. `socket.open` is false once either side closes it. A call made at a module's top, or in\na group, fails.",
      "params": [
        {
          "name": "url",
          "type": "string | Secret"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "headers",
              "doc": "Headers to send with the handshake, by name; a value may be a secret.",
              "type": "{[string]: string | Secret}",
              "optional": true
            },
            {
              "name": "protocols",
              "doc": "The subprotocols offered, of which the host picks one, `socket.protocol`.",
              "type": "{string}",
              "optional": true
            },
            {
              "name": "timeout",
              "doc": "How long it may take to connect, in seconds, before it fails.",
              "type": "number",
              "default": 30.0
            },
            {
              "name": "message",
              "doc": "Runs for each message the socket hears: a string for text, a buffer for binary.",
              "type": "(data: string | buffer) -> ()",
              "optional": true
            },
            {
              "name": "closed",
              "doc": "Runs once as the socket closes, whichever side closed it, with the close's code and reason.",
              "type": "(code: number, reason: string) -> ()",
              "optional": true
            }
          ]
        }
      ],
      "returns": "Task",
      "examples": [
        {
          "title": "To follow a chat relay",
          "side": "server",
          "code": "local answer = await(ws.connect(\"wss://chat.example/relay\", {\n    message = function(data)\n        say(`[relay] {data}`)\n    end,\n    closed = function(code, reason)\n        print(`the relay closed: {code} {reason}`)\n    end,\n}))\nif answer.ok then\n    relay = answer.socket\nend\n"
        }
      ]
    },
    {
      "name": "send",
      "group": "Calls",
      "side": "server",
      "on": "Socket",
      "since": "0.1",
      "summary": "Sends a message, after those sent before it, and gives its task at once, which answers once it is sent.",
      "doc": "Sends a message, after those sent before it, and gives its task at once, which answers once it is sent.\n\nA string is sent as a text message and a buffer as a binary one. A message to a socket no longer open fails.",
      "params": [
        {
          "name": "data",
          "type": "string | buffer"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "timeout",
              "doc": "How long it may take, in seconds, before it fails.",
              "type": "number",
              "default": 30.0
            }
          ]
        }
      ],
      "returns": "Task",
      "examples": [
        {
          "title": "To tell a relay a player joined",
          "side": "server",
          "code": "local answer = await(ws.connect(\"wss://chat.example/relay\"))\nif answer.ok then\n    answer.socket:send(json.encode({ joined = p.name }), { timeout = 5 })\nend\n"
        }
      ]
    },
    {
      "name": "close",
      "group": "Calls",
      "side": "server",
      "on": "Socket",
      "since": "0.1",
      "summary": "Closes the socket, after the messages sent before, and gives its task at once, which answers once the close is sent.",
      "doc": "Closes the socket, after the messages sent before, and gives its task at once, which answers once the close is\nsent.\n\nThe code is 1000 without one, or 3000 to 4999 for the mod's own, and the reason up to 123 bytes. The socket is no\nlonger open at once, and its `closed` runs once the host closes too.",
      "params": [
        {
          "name": "code",
          "type": "number",
          "optional": true
        },
        {
          "name": "reason",
          "type": "string",
          "optional": true
        }
      ],
      "returns": "Task",
      "examples": [
        {
          "title": "To close a relay as the match ends",
          "side": "server",
          "code": "local answer = await(ws.connect(\"wss://chat.example/relay\"))\nif answer.ok then\n    answer.socket:close(4000, \"the match ended\")\nend\n"
        }
      ]
    },
    {
      "name": "say",
      "group": "Chat",
      "side": "server",
      "since": "0.1",
      "summary": "Writes a line of up to 150 bytes into the chat boxes of the players `to` lists, or of everyone.",
      "doc": "Writes a line of up to 150 bytes into the chat boxes of the players `to` lists, or of everyone.\n\nEvery line reaches each player it is for, in order with the rest of what they are told. A label is up to 16 bytes.",
      "params": [
        {
          "name": "text",
          "type": "string | number | Secret"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "to",
              "doc": "The players who see it; everyone without.",
              "type": "{Player | number}",
              "optional": true
            },
            {
              "name": "label",
              "doc": "A tag before the line, as a channel's.",
              "type": "string",
              "optional": true
            },
            {
              "name": "color",
              "doc": "The colour of the label, or of the whole line without one, as CSS writes it.",
              "type": "string",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To greet everyone",
          "side": "server",
          "code": "say(\"Round 1: survive!\")\n"
        },
        {
          "title": "To whisper to a player in red, labelled as the server",
          "side": "server",
          "code": "say(\"You are out of lives\", { to = { p }, label = \"Server\", color = \"#ff4040\" })\n"
        }
      ]
    },
    {
      "name": "set_channel",
      "group": "Chat",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Gives a player a channel to say lines on, or changes the one they have; with nil, takes it away.",
      "doc": "Gives a player a channel to say lines on, or changes the one they have; with nil, takes it away.\n\nA name is up to 16 lowercase letters, digits and `_`, and a label up to 16 bytes. A player has 8 channels at most,\n`all` among them, which every player has first, labelled All, and the mod can neither change nor take away. They\ngo round them with Shift+Tab in the order given, and lose them when they leave. Who sees a line said on a channel is\nthe mod's to say, with the `said` event.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "channel",
          "optional": true,
          "fields": [
            {
              "name": "label",
              "doc": "What lines on it are tagged with, before the speaker's name.",
              "type": "string",
              "required": true
            },
            {
              "name": "color",
              "doc": "The label's colour, as CSS writes it.",
              "type": "string",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To give a player a channel to their squad",
          "side": "server",
          "code": "p:set_channel(\"squad\", { label = \"Squad\", color = \"#7cff4d\" })\n"
        },
        {
          "title": "To take it away",
          "side": "server",
          "code": "p:set_channel(\"squad\", nil)\n"
        }
      ]
    },
    {
      "name": "print",
      "group": "Chat",
      "side": "server",
      "since": "0.1",
      "summary": "Prints a line to the server's console and log, each value as `tostring` shows it, a tab between them.",
      "doc": "Prints a line to the server's console and log, each value as `tostring` shows it, a tab between them.\n\nPlayers never see it: `say` writes to their chat. A secret's text is hidden as `<secret name>`, wherever it is in\nthe line.",
      "params": [
        {
          "name": "values",
          "type": "any",
          "variadic": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To log each round as it starts",
          "side": "server",
          "code": "print(\"round\", 3, \"starts with\", p.name)\n"
        }
      ]
    },
    {
      "name": "is_held",
      "group": "Commands",
      "side": "client",
      "since": "0.1",
      "summary": "Gives whether the player holds an action, as Tab for `scoreboard`, Shift for `sprint` or Q for `tactical`, on whatever keys the player put it. Crouch, prone, sprint, aim and the scoreboard a player may toggle in place of holding: a press turns one on and the next off, and it reads held while on.",
      "doc": "Gives whether the player holds an action, as Tab for `scoreboard`, Shift for `sprint` or Q for `tactical`, on\nwhatever keys the player put it. Crouch, prone, sprint, aim and the scoreboard a player may toggle in place of\nholding: a press turns one on and the next off, and it reads held while on.\n\nA render that reads it draws again as it changes. A name of no action fails.",
      "params": [
        {
          "name": "action",
          "type": "string"
        }
      ],
      "returns": "boolean",
      "examples": [
        {
          "title": "To show the scoreboard while it is held, or toggled on",
          "side": "client",
          "code": "mount(function()\n    if not is_held(\"scoreboard\") then\n        return nil\n    end\n    return Box { \"Scores\", style = { position = \"absolute\", top = 100, left = 0, right = 0, textAlign = \"center\" } }\nend)\n"
        }
      ]
    },
    {
      "name": "keys_of",
      "group": "Commands",
      "side": "client",
      "since": "0.1",
      "summary": "Gives the player's keys for an action, as `\"tactical\"`, or a command line they bound, as `\"open shop\"`: an array of the keys' names, in the order Controls shows them, a key bound for this server alone first, empty for none.",
      "doc": "Gives the player's keys for an action, as `\"tactical\"`, or a command line they bound, as `\"open shop\"`: an array of\nthe keys' names, in the order Controls shows them, a key bound for this server alone first, empty for none.\n\nA render that reads it draws again as the player rebinds, so a hint names the key they press.",
      "params": [
        {
          "name": "action",
          "type": "string"
        }
      ],
      "returns": "{string}",
      "examples": [
        {
          "title": "To tell the player which key plants the bomb",
          "side": "client",
          "code": "mount(function() return Box { `Hold {keys_of(\"use\")[1] or \"use\"} to plant`, style = { position = \"absolute\", top =\n700, left = 900 } } end)\n"
        }
      ]
    },
    {
      "name": "choices",
      "group": "Commands",
      "side": "server",
      "since": "0.1",
      "summary": "Fills the list `name`, whose words a command's `t.choices(name)` argument takes, as maps to vote for; with nil words, empties it.",
      "doc": "Fills the list `name`, whose words a command's `t.choices(name)` argument takes, as maps to vote for; with nil\nwords, empties it.\n\nA list is everyone's, or with `player` that player's own, read over everyone's for them. It has any number of\nwords, each up to 32 bytes without spaces, as many as a player's game can be sent; a mod has 8 names of lists in\nall, each 1 to 16 lowercase letters, digits and `_`. Each player's game is told a list again as it changes, and\ncompletes its words as they are typed.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "words",
          "type": "{string}",
          "optional": true
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "player",
              "doc": "The player whose own list it is, read over everyone's; everyone's without.",
              "type": "Player | number",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To let players vote for a map of a list",
          "side": "server",
          "code": "command(\"vote\", { help = \"Vote for the next map\", args = { { \"map\", t.choices(\"maps\") } } }, function(e)\n\tsay(`{e.player.name} votes for {e.map}`)\nend)\non(\"start\", function()\n\tchoices(\"maps\", { \"yard\", \"testbed\" })\nend)\n"
        },
        {
          "title": "To give one player a list of their own, and take it away",
          "side": "server",
          "code": "choices(\"maps\", { \"yard\" }, { player = p })\nchoices(\"maps\", nil, { player = p })\n"
        }
      ]
    },
    {
      "name": "command",
      "group": "Commands",
      "side": "server",
      "since": "0.1",
      "summary": "Declares one of the mod's commands, which players type in the chat box after a `/` or run by a key they bind, and its handler, `run`.",
      "doc": "Declares one of the mod's commands, which players type in the chat box after a `/` or run by a key they bind, and\nits handler, `run`.\n\nA module declares its commands at its top as it loads. The box reaches one by its name, an alias, or either as\n`module.name` (`/admins.mute`, `main.` for `main.server.luau`'s). A name or an alias two modules declare fails at\nload, naming both; a module declaring one again replaces its own. Names, aliases and argument names are 1 to 16\nlowercase letters, digits and `_`, an argument's not a Luau keyword, as its handler reads `e.<name>`; none is named\n`player`. No name or alias is one of the client's own (`bind`, `binds`, `clear`, `connect`, `disconnect`, `forget`,\n`fov`, `help`, `maxfps`, `name`, `netgraph`, `quit`, `rate`, `request`, `screenshot`, `sensitivity`, `unbind`,\n`volume`), nor the engine's (`set`, `reset`, `match`, `match_next`, `match_restart`, `match_rotation`, `kick`,\n`ban`, `unban`), nor an action's, as `jump`, `slot1` or `map`. A mod has up to 256 commands.\n\nEach argument of `args` is `{ name, type }`, its type one of `t`'s: `t.player`, typed by any part of a name or as\n`#id` and given as the player; `t.int`, `t.number`, `t.string` (one word) or `t.one_of`, refused outside their\nlimits (`/mode: rounds: 1 to 9, got 10`); `t.duration`, a whole number and its unit, `30s`, `5m`, `12h` or `7d`, up\nto 3650 days, given in seconds; `t.text`, the rest of the line, so last; or `t.choices(name)`, a word of the list\n`choices` fills. Any of them `t.optional(…)` may be left out, after those needed, and reads nil.\n\nEach player's game is told the commands they may run and the lists those read, again as what a `run_by` reads\nchanges, so a player's box never lists one they may not run. The box completes them and checks a line before it is\nsent; the server checks it again, tells the player why one is dropped, and runs `run` with `e.player`, who ran it,\nand each argument by its name. The server prints each command run, and each one dropped. A command typed counts as a\nline said, one a second either kind; one run by a key, 10 a second after a burst of 5. No mod binds a key: a\nplayer binds a command themselves, and a key held down is an action's (`action`).\n\nWhat `run` returns before any `wait`, `{to, label, color}` as `say` takes them, shows the line typed as chat to the\nplayers `to` lists, written from what the server took, players by name, never back to the player; without `to`, or\nif `run` fails, no one sees it. A command declared without `run` is heard by `on_event(\"command\", player, name,\nargs)`, `args` in order and players by id, whose answer routes it the same.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "spec",
          "fields": [
            {
              "name": "help",
              "doc": "What `/help` shows of it, up to 64 bytes.",
              "type": "string",
              "optional": true
            },
            {
              "name": "aliases",
              "doc": "Other names the box runs it by, up to 4.",
              "type": "{string}",
              "optional": true
            },
            {
              "name": "args",
              "doc": "Its arguments in order, up to 8, each `{ name, type }` of a type of `t`; none without.",
              "type": "{{string | Type}}",
              "optional": true
            },
            {
              "name": "run_by",
              "doc": "Who may run it: any group but those that pick by an owner (`owner`, `team`, `spectators`); everyone without.",
              "type": "Group | ((Player?, Player) -> boolean)",
              "optional": true
            }
          ]
        },
        {
          "name": "run",
          "type": "(e: {player: Player, [string]: any}) -> Routing?",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To let players act in chat, as `/me waves`",
          "side": "server",
          "code": "command(\"me\", { help = \"Say what you do\", args = { { \"action\", t.text } } }, function(e)\n\tsay(`* {e.player.name} {e.action}`)\nend)\n"
        },
        {
          "title": "To give admins a command, shown to the player it is run on",
          "side": "server",
          "code": "command(\"slay\", {\n\thelp = \"Kill a player\",\n\taliases = { \"sl\" },\n\targs = { { \"target\", t.player }, { \"reason\", t.optional(t.text) } },\n\trun_by = admins,\n}, function(e)\n\te.target:hurt(e.target.health, e.player)\n\treturn { to = { e.target }, label = \"Admin\", color = \"#ff4040\" }\nend)\n"
        }
      ]
    },
    {
      "name": "action",
      "group": "Commands",
      "side": "server",
      "since": "0.1",
      "summary": "Handles a purpose action, hearing its key go down and up: `tactical`, `lethal`, `utility`, `ultimate`, `buy`, `drop`, `quick_menu`, `ping` or `map`, named by what it is for.",
      "doc": "Handles a purpose action, hearing its key go down and up: `tactical`, `lethal`, `utility`, `ultimate`, `buy`,\n`drop`, `quick_menu`, `ping` or `map`, named by what it is for.\n\nA player binds each action once, for every server, so a mod uses the keys they chose and binds none. Their Controls\nand loading screen show `label` beside it. A module declares it at its top as it loads; one two modules declare\nfails at load, naming both, and a module declaring it again replaces its own.\n\n`handler` runs for every player as their key goes down and as it goes up, `e.down` saying which, on the player's\nown time, as their requests do. When that time is spent, a press is dropped: a key still held is heard at the next\nmod tick, and a key let go is heard only if its press was. A tap between mod ticks is heard down and up a tick\napart; one held as its player leaves is heard let go before `leaving`; `p.held.<action>` is true in between. A\nplayer typing `/<action>` taps it. A tap or a hold is the mod's to tell apart: the engine never toggles one.\n\nUntil weapons go on these keys, `lethal` throws a frag grenade the player carries, and `tactical` a smoke grenade,\nwhether a mod handles them or not.",
      "params": [
        {
          "name": "name",
          "type": "\"tactical\" | \"lethal\" | \"utility\" | \"ultimate\" | \"buy\" | \"drop\" | \"quick_menu\" | \"ping\" | \"map\""
        },
        {
          "name": "options",
          "fields": [
            {
              "name": "label",
              "doc": "What a player's Controls and loading screen show beside the action, up to 64 bytes.",
              "type": "string",
              "required": true
            }
          ]
        },
        {
          "name": "handler",
          "type": "(e: {player: Player, down: boolean}) -> ()"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To call in a killstreak",
          "side": "server",
          "code": "action(\"ultimate\", { label = \"Call in the airstrike\" }, function(e)\n\tif e.down then\n\t\tsay(`{e.player.name} calls in an airstrike`)\n\tend\nend)\n"
        },
        {
          "title": "To walk slowly while a key is held",
          "side": "server",
          "code": "action(\"utility\", { label = \"Walk slowly\" }, function(e)\n\te.player:tune({ speed = if e.down then 0.5 else 1 })\nend)\n"
        }
      ]
    },
    {
      "name": "switch_off",
      "group": "Commands",
      "side": "server",
      "since": "0.1",
      "summary": "Switches stock actions off for the mod: their keys do nothing, and the server drops their buttons.",
      "doc": "Switches stock actions off for the mod: their keys do nothing, and the server drops their buttons.\n\nAny module may switch any off, at its top as it loads. `slots` is the keys taking the weapons in the slots, while\nthe wheel stays; `scoreboard` is the key showing the scoreboard, which client scripts draw while it is held.",
      "params": [
        {
          "name": "actions",
          "type": "\"use\" | \"slots\" | \"scoreboard\" | \"reload\" | \"crouch\" | \"prone\" | \"sprint\" | \"melee\"",
          "variadic": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To play without sprinting or going prone",
          "side": "server",
          "code": "switch_off(\"sprint\", \"prone\")\n"
        }
      ]
    },
    {
      "name": "play_effect",
      "group": "Effects",
      "side": "server",
      "since": "0.1",
      "summary": "Sets off a particle effect for the players who see it, once, or again and again with `loop` until `stop_effect`.",
      "doc": "Sets off a particle effect for the players who see it, once, or again and again with `loop` until `stop_effect`.\n\nAn effect played once ends by itself; with `loop`, `play_effect` gives the effect's entity, which `kind` names, so\n`kind` without `loop` fails. One that rides something absent is not set off. Once what it rides goes, a burst stays\nwhere it was last; a loop goes with it.",
      "params": [
        {
          "name": "name",
          "type": "effect"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "at",
              "doc": "The point it bursts at, the origin without; with `follow`, an offset from where what it rides stands.",
              "type": "vector",
              "optional": true
            },
            {
              "name": "dir",
              "doc": "The way it points, up without.",
              "type": "vector",
              "optional": true
            },
            {
              "name": "follow",
              "doc": "A player or an entity it rides as it is drawn.",
              "type": "Player | Entity | number",
              "optional": true
            },
            {
              "name": "loop",
              "doc": "Plays again each time it is over, until `stop_effect`, and `play_effect` gives the effect's entity.",
              "type": "boolean",
              "default": false
            },
            {
              "name": "start",
              "doc": "When it starts, in seconds from now: up to an hour ago, seen from part-way through, or up to 5 s ahead.",
              "type": "number",
              "range": [
                -3600.0,
                5.0
              ],
              "default": 0.0
            },
            {
              "name": "owner",
              "doc": "The player it is about, whom `owner`, `team` and `spectators` pick by.",
              "type": "Player | number",
              "optional": true
            },
            {
              "name": "read_by",
              "doc": "Who is shown it; everyone without.",
              "type": "Group | ((Player?, Player) -> boolean)",
              "optional": true
            },
            {
              "name": "kind",
              "doc": "Its kind, one `entity_kind` declared on its base; the base's own without.",
              "type": "string",
              "optional": true
            }
          ]
        }
      ],
      "returns": "Entity?",
      "examples": [
        {
          "title": "To burst a grenade where it lands",
          "side": "server",
          "code": "play_effect(\"explosion\", { at = p.position })\n"
        },
        {
          "title": "To puff smoke from a wall, pointing away from it",
          "side": "server",
          "code": "play_effect(\"smoke\", { at = vector.create(0, 1, 4), dir = vector.create(0, 0, -1) })\n"
        },
        {
          "title": "To keep a zombie smoking as it walks, and stop it",
          "side": "server",
          "code": "local zombie = spawn()\nlocal smoke = play_effect(\"smoke\", { follow = zombie, at = vector.create(0, 1.6, 0), loop = true })\nwait(5)\nstop_effect(smoke)\n"
        }
      ]
    },
    {
      "name": "stop_effect",
      "group": "Effects",
      "side": "server",
      "since": "0.1",
      "summary": "Stops a looping effect `play_effect` gave; one stopped already, or gone with what it rode, is left as it is.",
      "doc": "Stops a looping effect `play_effect` gave; one stopped already, or gone with what it rode, is left as it is.",
      "params": [
        {
          "name": "effect",
          "type": "Entity"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To stop a fire once it has burned for ten seconds",
          "side": "server",
          "code": "local fire = play_effect(\"smoke\", { at = vector.create(2, 0, 2), loop = true })\nwait(10)\nstop_effect(fire)\n"
        }
      ]
    },
    {
      "name": "animate",
      "group": "Entities and models",
      "side": "server",
      "on": "both",
      "since": "0.1",
      "summary": "Plays an animation, an `.anim` file, on a player's body, an NPC or a model.",
      "doc": "Plays an animation, an `.anim` file, on a player's body, an NPC or a model.\n\nIt is told to each player's game once, as it starts, so a model walking a path with its walk looping costs no more\nthan one standing still, and a player who joins sees one under way. The one that started last shows: a later one\nreplaces it, and one looping goes on until another starts. A skinned model plays it whole; a body over its upper\nhalf, its legs walking, crouching and jumping as it moves, its hands kept on a weapon it holds. The engine's own, as\na shot or a reload, neither end one nor are ended by one. Four are kept at a time, the one shown, one before it and\ntwo to come: past them, the one starting last is dropped. On a part, a sound or an effect it fails; on what is gone\nit does nothing.",
      "params": [
        {
          "name": "animation",
          "type": "animation"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "length",
              "doc": "How long one play lasts, in seconds, above 0, at the pace that fits; the clip's own without.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                3600.0
              ]
            },
            {
              "name": "loop",
              "doc": "Plays it again and again, until another starts.",
              "type": "boolean",
              "default": false
            },
            {
              "name": "start",
              "doc": "When it starts, in seconds from now: up to an hour ago, seen from part-way through, or up to 5 s ahead.",
              "type": "number",
              "range": [
                -3600.0,
                5.0
              ],
              "default": 0.0
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To make a player dance",
          "side": "server",
          "code": "p:animate(\"dance_loop\", { loop = true })\n"
        },
        {
          "title": "To walk a model of a character along a path",
          "side": "server",
          "code": "local guard = model(\"mannequin\")\nguard:animate(\"walk_loop\", { loop = true })\nguard:move_along({ vector.create(0, 0, 10), vector.create(10, 0, 10) }, 8, { face = true })\n"
        }
      ]
    },
    {
      "name": "preload",
      "group": "Entities and models",
      "side": "server",
      "since": "0.1",
      "summary": "Names files of a kind that every player's game loads as they join, on their loading screen, not as the mod first uses them.",
      "doc": "Names files of a kind that every player's game loads as they join, on their loading screen, not as the mod first\nuses them.\n\nEach file named so far, by this or by any call, is in what a joining player loads before they play. A file first\nnamed later is loaded in the background as it comes: until then a model or an image is not drawn, a sound not heard,\nan animation not played, and a weapon neither held nor heard; a sound or an effect then starts from where it would\nbe by then. The server says once of each, `sound \"hum\" was not preloaded: clients load it as it is first used`.\nPreload what plays in a hurry, at load or before it is needed, as a nuke's sound once it is bought. A name of no\nfile fails at the call, and a mod names 4096 files of each kind at most.",
      "params": [
        {
          "name": "kind",
          "type": "\"model\" | \"sound\" | \"effect\" | \"image\" | \"weapon\" | \"animation\" | \"material\""
        },
        {
          "name": "names",
          "type": "string",
          "variadic": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To load a boss's sounds and model at load",
          "side": "server",
          "code": "preload(\"sound\", \"zombie_groan1\", \"explosion_boom\")\npreload(\"model\", \"rocket\")\n"
        }
      ]
    },
    {
      "name": "spawn_camera",
      "group": "Entities and models",
      "side": "server",
      "since": "0.1",
      "summary": "Makes a camera, an entity a player's view can be put on with `set_camera`, and gives it.",
      "doc": "Makes a camera, an entity a player's view can be put on with `set_camera`, and gives it.\n\nIts kind is `camera`. It moves, turns, rides and goes as a model does, but is never drawn nor solid, and only the\nplayers looking through it are sent it, so its `solid` and `read_by` fail.",
      "params": [
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "at",
              "doc": "Where it is; the map's origin without.",
              "type": "vector",
              "optional": true
            },
            {
              "name": "angles",
              "doc": "Which way it looks; unturned without.",
              "type": "Angles",
              "optional": true
            }
          ]
        }
      ],
      "returns": "Entity",
      "examples": [
        {
          "title": "To show a player the map from above",
          "side": "server",
          "code": "local cam = spawn_camera({ at = vector.create(0, 30, -20), angles = { pitch = -0.9 } })\np:set_camera(cam, { look = \"target\" })\n"
        }
      ]
    },
    {
      "name": "set_camera",
      "group": "Entities and models",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Puts a player's view on an entity, a player or a point; nil puts it back at their eyes.",
      "doc": "Puts a player's view on an entity, a player or a point; nil puts it back at their eyes.\n\nOn their own body it is third person. An offset from a body stays level, so an offset to the left and behind stays\nover the shoulder. A point takes no offset and looks with the player's mouse. A player's shots leave from the\nview, a bash and a throw from the body. The weapon in first person stays unless `hide_weapon` hides it; on the\nplayer's own body none is drawn. A camera outlasts death and goes with a new match; one on what goes is back at\nthe eyes. It takes effect a ping after the call. On a player who left, or what is gone, it does nothing.\n\nWhoever watches the player sees through their camera too; a dead player with a camera of their own watches no one.\nSounds are heard where the camera is, unless a client script hears them at the body (`view:set`). What the view is\non, and what that rides, is sent to the player whatever its `read_by`.",
      "params": [
        {
          "name": "target",
          "type": "Player | Entity | number | vector",
          "optional": true
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "offset",
              "doc": "How far from what it is on, turned by it: from a body's eyes, by its view's yaw alone.",
              "type": "vector",
              "optional": true
            },
            {
              "name": "look",
              "doc": "`\"aim\"` turns the view with the player's mouse; `\"target\"` faces it as what it is on faces. Aim without.",
              "type": "\"aim\" | \"target\"",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To watch a player from over their shoulder",
          "side": "server",
          "code": "p:set_camera(p, { offset = vector.create(0.5, 0.3, -2.5) })\n"
        },
        {
          "title": "To show a killcam from where the killer stood, and back",
          "side": "server",
          "code": "victim:set_camera(killer.position + vector.create(0, 1.6, 0))\nwait(3)\nvictim:set_camera(nil)\n"
        }
      ]
    },
    {
      "name": "remove",
      "group": "Entities and models",
      "side": "server",
      "on": "both",
      "since": "0.1",
      "summary": "Takes away an NPC, a model, a shape, a camera, a part, or a looping sound or effect.",
      "doc": "Takes away an NPC, a model, a shape, a camera, a part, or a looping sound or effect.\n\nIts handlers go with it, and any order on it after does nothing. On a player it fails: a player is kicked.",
      "params": [],
      "returns": "()",
      "examples": [
        {
          "title": "To remove a crate once it is broken",
          "side": "server",
          "code": "local crate = model(\"rocket\")\ncrate:remove()\n"
        },
        {
          "title": "To clear every zombie at the end of a round",
          "side": "server",
          "code": "for _ = 1, 3 do\n\tspawn()\nend\nfor _, e in entities do\n\tif e.kind == \"body\" then\n\t\te:remove()\n\tend\nend\n"
        }
      ]
    },
    {
      "name": "on",
      "group": "Entities and models",
      "side": "server",
      "on": "entity",
      "since": "0.1",
      "summary": "Hears a model's, a shape's or a part's move or turn arrive, or its pause for a body in its way and going on.",
      "doc": "Hears a model's, a shape's or a part's move or turn arrive, or its pause for a body in its way and going on.\n\n`move_finished` and `rotate_finished` are heard as its move or its turn arrives, never after a `stop` nor of a\nloop; `blocked` and `unblocked` as it pauses for the players and NPCs in its way, which the event lists, and goes\non. The handler is given the object as `part` for a part, `entity` for what the mod made, and runs as a coroutine\nthat may `wait`. A part's handlers are given at a module's top, and again as the module loads again in place; an\nentity's whenever the mod holds it, kept until it is removed. A module has one handler an event for each object in\neach of its files: a second `on` replaces the first. On a player, an NPC, a sound or an effect it fails; on what is\ngone it does nothing.",
      "params": [
        {
          "name": "event",
          "type": "\"move_finished\" | \"rotate_finished\" | \"blocked\" | \"unblocked\""
        },
        {
          "name": "fn",
          "type": "(e: Moved) -> ()"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To say when a lift arrives",
          "side": "server",
          "code": "local lift = model(\"rocket\")\nlocal arrived = false\nlift:on(\"move_finished\", function(e)\n\tarrived = true\n\tsay(\"the lift is up\")\nend)\nlift:move_by(vector.create(0, 4, 0), 1)\n"
        }
      ]
    },
    {
      "name": "on",
      "group": "Entities and models",
      "side": "server",
      "on": "entity",
      "since": "0.1",
      "summary": "Hears a model, a shape or a part struck by a shot, a bash or an explosion, which makes it damageable.",
      "doc": "Hears a model, a shape or a part struck by a shot, a bash or an explosion, which makes it damageable.\n\nThe event says who struck it, if anyone, `attacker`; for how much, `amount`; by what means and with which weapon;\nwhere, `point`, and going which way, `dir`; and the projectile whose burst it was, if one. A shot strikes each wall\nit goes into once, with the damage it carries there; an explosion strikes the point of its box nearest the burst, if\nin its sight. The server works out no damage for what no handler hears. Its handlers are given and kept as the other\nevents' are.",
      "params": [
        {
          "name": "event",
          "type": "\"damaged\""
        },
        {
          "name": "fn",
          "type": "(e: Damaged) -> ()"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To break a crate after three hits",
          "side": "server",
          "code": "local crate = model(\"rocket\", { at = vector.create(0, 0, 3) })\ncrate.solid = true\nlocal hits = 0\ncrate:on(\"damaged\", function(e)\n\thits += 1\n\tif hits == 3 then\n\t\tcrate:remove()\n\tend\nend)\n"
        }
      ]
    },
    {
      "name": "model",
      "group": "Entities and models",
      "side": "server",
      "since": "0.1",
      "summary": "Places a model, a `.model` file of the mod's, and gives its entity.",
      "doc": "Places a model, a `.model` file of the mod's, and gives its entity.\n\nIt stands still until an order moves it, and is not solid until its `solid` is set. A model and a part of the map\ntake the same orders: `move_to`, `rotate_by`, `attach` and the rest.",
      "params": [
        {
          "name": "name",
          "type": "model"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "at",
              "doc": "Where it stands; the map's origin without.",
              "type": "vector",
              "optional": true
            },
            {
              "name": "angles",
              "doc": "How it is turned; unturned without.",
              "type": "Angles",
              "optional": true
            },
            {
              "name": "owner",
              "doc": "The player it is about, whom `owner`, `team` and `spectators` pick by.",
              "type": "Player | number",
              "optional": true
            },
            {
              "name": "read_by",
              "doc": "Who is shown it; everyone without.",
              "type": "Group | ((Player?, Player) -> boolean)",
              "optional": true
            },
            {
              "name": "kind",
              "doc": "Its kind, one `entity_kind` declared on its base; the base's own without.",
              "type": "string",
              "optional": true
            }
          ]
        }
      ],
      "returns": "Entity",
      "examples": [
        {
          "title": "To place a solid crate, turned",
          "side": "server",
          "code": "local crate = model(\"rocket\", { at = vector.create(4, 0, 2), angles = { yaw = math.pi / 2 } })\ncrate.solid = true\n"
        },
        {
          "title": "To show a player alone the flag they carry",
          "side": "server",
          "code": "local flag = model(\"rocket\", { owner = p, read_by = owner })\nflag:attach(p, { offset = vector.create(0, 1.2, -0.3) })\n"
        }
      ]
    },
    {
      "name": "move_to",
      "group": "Entities and models",
      "side": "server",
      "on": "entity",
      "since": "0.1",
      "summary": "Moves a model or a part to a point in a straight line, over some seconds.",
      "doc": "Moves a model or a part to a point in a straight line, over some seconds.\n\nThe seconds are above 0 and up to an hour, rounded to whole ticks, one at least; `set_position` moves it at once. A\nmove and a turn go on together, and a new move starts from where it is then. `move_seconds_left` reads how long it\nhas to go, as of the last tick, so the call that orders a move reads the old one. `on(\"move_finished\", fn)` hears it\narrive. On an NPC, a player, a sound or an effect it fails; on one gone it does nothing.",
      "params": [
        {
          "name": "point",
          "type": "vector"
        },
        {
          "name": "seconds",
          "type": "number"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "timing",
              "doc": "How it eases, each lap if it loops; linear without.",
              "type": "Timing",
              "optional": true
            },
            {
              "name": "face",
              "doc": "Points its nose the way it goes while it moves, its roll kept, until it is turned again.",
              "type": "boolean",
              "default": false
            },
            {
              "name": "loop",
              "doc": "Repeats it for good: it comes back to where it started, each lap taking its seconds.",
              "type": "boolean",
              "default": false
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To open a sliding door",
          "side": "server",
          "code": "local door = model(\"rocket\", { at = vector.create(0, 0, 4) })\ndoor:move_to(vector.create(2, 0, 4), 1.5, { timing = \"ease-in-out\" })\n"
        },
        {
          "title": "To run a lift up and down for good",
          "side": "server",
          "code": "local lift = model(\"rocket\")\nlift:move_to(vector.create(0, 6, 0), 4, { timing = \"ease-in-out\", loop = true })\n"
        }
      ]
    },
    {
      "name": "move_by",
      "group": "Entities and models",
      "side": "server",
      "on": "entity",
      "since": "0.1",
      "summary": "Moves a model or a part by an offset from where it is, in a straight line, over some seconds.",
      "doc": "Moves a model or a part by an offset from where it is, in a straight line, over some seconds.\n\nIt takes its seconds and options as `move_to` does. A move that would take it past the map's reach is dropped.",
      "params": [
        {
          "name": "offset",
          "type": "vector"
        },
        {
          "name": "seconds",
          "type": "number"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "timing",
              "doc": "How it eases, each lap if it loops; linear without.",
              "type": "Timing",
              "optional": true
            },
            {
              "name": "face",
              "doc": "Points its nose the way it goes while it moves, its roll kept, until it is turned again.",
              "type": "boolean",
              "default": false
            },
            {
              "name": "loop",
              "doc": "Repeats it for good: it comes back to where it started, each lap taking its seconds.",
              "type": "boolean",
              "default": false
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To raise a platform by 3 m",
          "side": "server",
          "code": "local platform = model(\"rocket\")\nplatform:move_by(vector.create(0, 3, 0), 2)\n"
        }
      ]
    },
    {
      "name": "move_along",
      "group": "Entities and models",
      "side": "server",
      "on": "entity",
      "since": "0.1",
      "summary": "Moves a model or a part from where it is through each point in turn, over some seconds.",
      "doc": "Moves a model or a part from where it is through each point in turn, over some seconds.\n\nIt takes 1 to 31 points, as markers' positions, and goes on a curve through them, or straight from one to the\nnext with `straight`. Each stretch takes its share of the seconds by its length. An easing that overshoots stops\nat the path's ends.",
      "params": [
        {
          "name": "points",
          "type": "{vector}"
        },
        {
          "name": "seconds",
          "type": "number"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "timing",
              "doc": "How it eases, each lap if it loops; linear without.",
              "type": "Timing",
              "optional": true
            },
            {
              "name": "straight",
              "doc": "Goes straight from one point to the next, rather than on a curve through them.",
              "type": "boolean",
              "default": false
            },
            {
              "name": "face",
              "doc": "Points its nose the way it goes while it moves, its roll kept, until it is turned again.",
              "type": "boolean",
              "default": false
            },
            {
              "name": "loop",
              "doc": "Goes round for good, from its last point back to where it started, each lap taking its seconds.",
              "type": "boolean",
              "default": false
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To fly a camera along a path, facing its way",
          "side": "server",
          "code": "local cam = spawn_camera({ at = vector.create(0, 5, 0) })\nlocal path = { vector.create(10, 5, 0), vector.create(10, 5, 10), vector.create(0, 8, 10) }\ncam:move_along(path, 8, { face = true, timing = \"ease-in-out\" })\n"
        },
        {
          "title": "To run a cart round a closed track",
          "side": "server",
          "code": "local cart = model(\"rocket\")\nlocal track = { vector.create(8, 0, 0), vector.create(8, 0, 8), vector.create(0, 0, 8) }\ncart:move_along(track, 12, { straight = true, face = true, loop = true })\n"
        }
      ]
    },
    {
      "name": "rotate_to",
      "group": "Entities and models",
      "side": "server",
      "on": "entity",
      "since": "0.1",
      "summary": "Turns a model or a part to angles, over some seconds.",
      "doc": "Turns a model or a part to angles, over some seconds.\n\nEach angle turns the way it says, so a yaw from 0 to 2π turns once round, up to a thousand turns either way; an\nangle left out is kept. Yaw turns left, pitch lifts the front, roll tips it to its right. The seconds are above 0\nand up to an hour, rounded to whole ticks, one at least; `set_angles` turns it at once. `on(\"rotate_finished\", fn)`\nhears it arrive.",
      "params": [
        {
          "name": "angles",
          "type": "Angles"
        },
        {
          "name": "seconds",
          "type": "number"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "timing",
              "doc": "How it eases, each lap if it loops; linear without.",
              "type": "Timing",
              "optional": true
            },
            {
              "name": "loop",
              "doc": "Turns on for good, by as much again each lap, as a fan.",
              "type": "boolean",
              "default": false
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To swing a door open",
          "side": "server",
          "code": "local door = model(\"rocket\")\ndoor:rotate_to({ yaw = math.pi / 2 }, 1, { timing = \"ease-out\" })\n"
        }
      ]
    },
    {
      "name": "rotate_by",
      "group": "Entities and models",
      "side": "server",
      "on": "entity",
      "since": "0.1",
      "summary": "Turns a model or a part by angles from how it is turned, over some seconds.",
      "doc": "Turns a model or a part by angles from how it is turned, over some seconds.\n\nIt takes its seconds and options as `rotate_to` does. A turn that would go past a thousand turns is dropped.",
      "params": [
        {
          "name": "angles",
          "type": "Angles"
        },
        {
          "name": "seconds",
          "type": "number"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "timing",
              "doc": "How it eases, each lap if it loops; linear without.",
              "type": "Timing",
              "optional": true
            },
            {
              "name": "loop",
              "doc": "Turns on for good, by as much again each lap, as a fan.",
              "type": "boolean",
              "default": false
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To spin a fan for good",
          "side": "server",
          "code": "local fan = model(\"rocket\")\nfan:rotate_by({ yaw = 2 * math.pi }, 3, { loop = true })\n"
        }
      ]
    },
    {
      "name": "stop",
      "group": "Entities and models",
      "side": "server",
      "on": "both",
      "since": "0.1",
      "summary": "Stops a model's or a part's move and turn where it is, or an NPC's walk.",
      "doc": "Stops a model's or a part's move and turn where it is, or an NPC's walk.\n\n`\"move\"` stops its move alone and `\"rotate\"` its turn; an NPC stops with neither. A stopped move or turn is never\nheard as finished.",
      "params": [
        {
          "name": "what",
          "type": "\"move\" | \"rotate\"",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To stop a lift between floors",
          "side": "server",
          "code": "local lift = model(\"rocket\")\nlift:move_to(vector.create(0, 6, 0), 4)\nlift:rotate_by({ yaw = math.pi }, 4)\nwait(1)\nlift:stop(\"move\")\n"
        },
        {
          "title": "To stop a zombie in its tracks",
          "side": "server",
          "code": "local zombie = spawn({ at = vector.create(0, 0, 10) })\nzombie:chase(p)\nzombie:stop()\n"
        }
      ]
    },
    {
      "name": "turn_with",
      "group": "Entities and models",
      "side": "server",
      "on": "entity",
      "since": "0.1",
      "summary": "Makes a model, a shape or a part face where a player looks, without moving it; nil stops it where it faces.",
      "doc": "Makes a model, a shape or a part face where a player looks, without moving it; nil stops it where it faces.\n\nIt turns level, in the world, whatever it rides, from how it faces as the call is made, as a mounted gun's barrel\nfollows its gunner. It costs no network a tick: each player's game turns it toward the player as it draws them.\n`angles` reads it as of the last tick, and what collides with it, and `limit_view` about it, take it as it faced\nwhen it began to turn. A turn, a stop of its turn, or its player leaving ends it, facing where it was.",
      "params": [
        {
          "name": "player",
          "type": "Player | number",
          "optional": true
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "rate",
              "doc": "The fastest it turns, in radians a second, above 0; at once without.",
              "type": "number",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To mount a gun that follows its gunner",
          "side": "server",
          "code": "local gun = model(\"ak47\", { at = vector.create(0, 1, 2) })\ngun:turn_with(p, { rate = math.pi })\n"
        },
        {
          "title": "To let the gun go",
          "side": "server",
          "code": "local gun = model(\"ak47\", { at = vector.create(0, 1, 2) })\ngun:turn_with(p)\ngun:turn_with(nil)\n"
        }
      ]
    },
    {
      "name": "attach",
      "group": "Entities and models",
      "side": "server",
      "on": "entity",
      "since": "0.1",
      "summary": "Makes a model, a part, a looping sound or a looping effect ride a player, an NPC, a model or a part.",
      "doc": "Makes a model, a part, a looping sound or a looping effect ride a player, an NPC, a model or a part.\n\nIt rides turned as what it rides is turned, and its moves and turns after are in that space: a flag on a\ncarrier's back, a turret on a lift, a charge stuck to a zombie. A sound or an effect rides by its offset alone. An\nattach that would make a ring, or put anything more than 16 deep, is dropped; one to a player who left does\nnothing. `detach`, or what it rides going, lets it go where it is.",
      "params": [
        {
          "name": "to",
          "type": "Player | Entity | number"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "bone",
              "doc": "The joint of a body it rides, by name, as `\"DEF-spine.003\"`; the body's origin without.",
              "type": "string",
              "optional": true
            },
            {
              "name": "offset",
              "doc": "How far from what it rides, or from the joint, in that one's space.",
              "type": "vector",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To put a turret on a lift",
          "side": "server",
          "code": "local lift = model(\"rocket\")\nlocal turret = model(\"ak47\")\nturret:attach(lift, { offset = vector.create(0, 1, 0) })\nlift:move_by(vector.create(0, 5, 0), 3)\n"
        },
        {
          "title": "To strap a charge to a player's back",
          "side": "server",
          "code": "local charge = model(\"grenade\")\ncharge:attach(p, { bone = \"DEF-spine.003\", offset = vector.create(0, 0, -0.15) })\n"
        }
      ]
    },
    {
      "name": "detach",
      "group": "Entities and models",
      "side": "server",
      "on": "entity",
      "since": "0.1",
      "summary": "Lets a model, a part, a looping sound or a looping effect go of what it rides, where it is.",
      "doc": "Lets a model, a part, a looping sound or a looping effect go of what it rides, where it is.",
      "params": [],
      "returns": "()",
      "examples": [
        {
          "title": "To drop a carried flag",
          "side": "server",
          "code": "local flag = model(\"rocket\")\nflag:attach(p, { offset = vector.create(0, 1.2, -0.3) })\nflag:detach()\n"
        }
      ]
    },
    {
      "name": "shape",
      "group": "Entities and models",
      "side": "server",
      "since": "0.1",
      "summary": "Makes a shape of a form filling a size, or the convex hull of points, and gives its entity.",
      "doc": "Makes a shape of a form filling a size, or the convex hull of points, and gives its entity.\n\nA form is `\"box\"`, `\"wedge\"` (a ramp rising from nothing at its front, -z, to its height at its back),\n`\"cylinder\"`, `\"sphere\"` or `\"capsule\"`, filling `size`, standing on its origin, upright and round across x and z.\n`\"hull\"` takes a list of up to 64 points about its origin in place of a size, spanning a volume. A size is above 0\neach way. Its kind is `shape`: it moves, rides, is solid and goes as a model does.",
      "params": [
        {
          "name": "form",
          "type": "\"box\" | \"wedge\" | \"cylinder\" | \"sphere\" | \"capsule\" | \"hull\""
        },
        {
          "name": "size",
          "type": "vector | {vector}"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "material",
              "doc": "The `.material` file it is drawn with; not drawn without, a clip.",
              "type": "material",
              "optional": true
            },
            {
              "name": "solid",
              "doc": "What it stops, as its `solid` says: true, false or a mask; everything without.",
              "type": "Solid",
              "optional": true
            },
            {
              "name": "at",
              "doc": "Where it stands; the map's origin without.",
              "type": "vector",
              "optional": true
            },
            {
              "name": "angles",
              "doc": "How it is turned; unturned without.",
              "type": "Angles",
              "optional": true
            }
          ]
        }
      ],
      "returns": "Entity",
      "examples": [
        {
          "title": "To build a wooden ramp",
          "side": "server",
          "code": "local ramp = shape(\"wedge\", vector.create(2, 1, 4), { material = \"wood\", at = vector.create(0, 0, 6) })\n"
        },
        {
          "title": "To block a doorway to players alone, unseen",
          "side": "server",
          "code": "shape(\"box\", vector.create(2, 3, 0.2), { solid = { players = true }, at = vector.create(0, 0, 3) })\n"
        },
        {
          "title": "To make a rock of a few points",
          "side": "server",
          "code": "local points = {\n\tvector.create(0, 0, 0), vector.create(1, 0, 0), vector.create(0, 0, 1), vector.create(0.3, 0.8, 0.3),\n}\nshape(\"hull\", points, { material = \"wood\" })\n"
        }
      ]
    },
    {
      "name": "explode",
      "group": "Health",
      "side": "server",
      "since": "0.1",
      "summary": "Sets off an explosion at a point, hurting the players and NPCs around it as a grenade's does.",
      "doc": "Sets off an explosion at a point, hurting the players and NPCs around it as a grenade's does.\n\nIt plays no effect and no sound: play those with `play_effect` and `play_sound`. It goes off on the next tick, and\nwhat stops shots shields from it. It hurts `by` too, if near. 16 go off a tick and the rest wait their turn; past\n256 waiting, more are dropped.",
      "params": [
        {
          "name": "at",
          "type": "vector"
        },
        {
          "name": "options",
          "fields": [
            {
              "name": "radius",
              "doc": "How far it reaches, in metres, over 0.",
              "type": "number",
              "required": true,
              "range": [
                0.0,
                50.0
              ]
            },
            {
              "name": "damage",
              "doc": "The damage at its middle.",
              "type": "number",
              "required": true,
              "range": [
                0.0,
                null
              ]
            },
            {
              "name": "min_damage",
              "doc": "The damage at its edge, `radius` away; in between it falls in a straight line from `damage`.",
              "type": "number",
              "range": [
                0.0,
                null
              ],
              "default": 0.0
            },
            {
              "name": "by",
              "doc": "Who set it off, a player or an NPC, as its hurts and kills name them.",
              "type": "Player | number",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To drop a mortar where a player stands",
          "side": "server",
          "code": "local at = p.position\nexplode(at, { radius = 6, damage = 150, min_damage = 10 })\nplay_effect(\"explosion\", { at = at })\nplay_sound(\"explosion_boom\", { at = at, range = 200 })\n"
        },
        {
          "title": "To blow up the charge a player planted, so its kills are theirs",
          "side": "server",
          "code": "local charge = model(\"grenade\", { at = p.position })\nwait(3)\nexplode(charge.position, { radius = 8, damage = 300, by = p })\ncharge:remove()\n"
        }
      ]
    },
    {
      "name": "hurt",
      "group": "Health",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Hurts a player, as a hit would, taking `damage` from their health; at 0 they die.",
      "doc": "Hurts a player, as a hit would, taking `damage` from their health; at 0 they die.\n\n`by` is who did it, a player or an NPC, and `weapon` what with: any weapon's name, a file of `weapons/` or not.\nThe player hurt sees a red bar pointing at `by`, and `by` sees a hit mark, as do those watching either through their\neyes; a `by` not in play counts as no one. A death it causes is shown to everyone with who did it, the weapon, the\nkind and the limb, as a kill feed needs. The dead stay dead. An NPC has no health of the engine's, so `hurt` on one\nfails: the mod keeps its own.",
      "params": [
        {
          "name": "damage",
          "type": "number",
          "range": [
            0.0,
            null
          ]
        },
        {
          "name": "by",
          "type": "Player | number",
          "optional": true
        },
        {
          "name": "weapon",
          "type": "string",
          "optional": true
        },
        {
          "name": "how",
          "optional": true,
          "fields": [
            {
              "name": "kind",
              "doc": "How it was done, as the kill feed and the `damaged` and `killed` events' `means` name it.",
              "type": "\"bullet\" | \"melee\" | \"explosion\" | \"fall\" | \"mod\"",
              "default": "mod"
            },
            {
              "name": "location",
              "doc": "The limb it hit, one of a weapon's `locations`; none, a hurt of the whole body, without one.",
              "type": "\"head\" | \"neck\" | \"chest\" | \"stomach\" | \"upper_arm\" | \"lower_arm\" | \"hand\" | \"upper_leg\" | \"lower_leg\" | \"foot\"",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To hurt a player standing in fire",
          "side": "server",
          "code": "p:hurt(5)\n"
        },
        {
          "title": "To deal a zombie's claw, so the kill feed names it",
          "side": "server",
          "code": "local zombie = spawn()\np:hurt(40, zombie, \"zombie_claw\", { kind = \"melee\", location = \"chest\" })\n"
        }
      ]
    },
    {
      "name": "heal",
      "group": "Health",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Gives a living player back `amount` health, up to their maximum.",
      "doc": "Gives a living player back `amount` health, up to their maximum.",
      "params": [
        {
          "name": "amount",
          "type": "number",
          "range": [
            0.0,
            null
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To heal a player a little each second, for five seconds",
          "side": "server",
          "code": "for _ = 1, 5 do\n    p:heal(5)\n    wait(1)\nend\n"
        }
      ]
    },
    {
      "name": "set_health",
      "group": "Health",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Sets a living player's health, no higher than their maximum; at 0 they die, as by a hurt.",
      "doc": "Sets a living player's health, no higher than their maximum; at 0 they die, as by a hurt.",
      "params": [
        {
          "name": "health",
          "type": "number",
          "range": [
            0.0,
            10000.0
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To give a player full health",
          "side": "server",
          "code": "p:set_health(p.max_health)\n"
        }
      ]
    },
    {
      "name": "set_max_health",
      "group": "Health",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Sets a player's maximum health; everyone starts at 100.",
      "doc": "Sets a player's maximum health; everyone starts at 100.\n\nIt is kept through death, and a respawn brings the player back at it. Health over it comes down to it.",
      "params": [
        {
          "name": "max",
          "type": "number",
          "range": [
            1.0,
            10000.0
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To give a player the Juggernog perk",
          "side": "server",
          "code": "p:set_max_health(250)\np:set_health(250)\n"
        }
      ]
    },
    {
      "name": "respawn",
      "group": "Health",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Brings a dead player back at the next marker whose name starts with `spawn`, at full health, with the loadout.",
      "doc": "Brings a dead player back at the next marker whose name starts with `spawn`, at full health, with the loadout.\n\nFollowed at once by `p:set_position` and `p:set_angles` on the same player, in the same handler, timer or tick, it\nbrings anyone back there instead, dead or alive, and leaves that spawn for the next. A player alive is left as they\nare otherwise. A push, turn or move not yet carried out goes with the life before; `tune`, `hold` and `limit_view`\noutlast it.",
      "params": [],
      "returns": "()",
      "examples": [
        {
          "title": "To bring every dead player back at the start of a round",
          "side": "server",
          "code": "for _, p in players do\n    if not p.npc and p.health == 0 then\n        p:respawn()\n    end\nend\n"
        },
        {
          "title": "To bring a player back at a point of your choosing",
          "side": "server",
          "code": "local at = vector.create(4, 0, 2)\np:respawn()\np:set_position(at)\np:set_angles({ yaw = math.pi })\n"
        }
      ]
    },
    {
      "name": "on",
      "group": "Map",
      "side": "client",
      "on": "Trigger",
      "since": "0.1",
      "summary": "Runs `fn` each time a trigger that fires on this client hears `event` of the client's own player, given `{trigger, player}`, as its game first predicts the player through it.",
      "doc": "Runs `fn` each time a trigger that fires on this client hears `event` of the client's own player, given\n`{trigger, player}`, as its game first predicts the player through it.\n\nIt is given at a script's top by the trigger's name, so one the server tells this client later, or makes at run\ntime, is heard too; a set, `triggers(\"pad*\"):on(…)`, listens by its pattern. Only the server's triggers that fire\non clients are heard, and of them what a damage trigger hears is not. The server's handler of the same trigger\nhears it too, a moment later.\n\nWhile it runs, `me` reads the player as that moment left them, and `me:set_velocity`, `add_velocity`, `tune`,\n`limit_view`, `set_position` and `set_angles` move them from the next moment on, as the server's handler orders\nit: the two agreeing show nothing, and differing a correction, once. Anywhere else, or on another player, those\nfail.",
      "params": [
        {
          "name": "event",
          "type": "TriggerHears"
        },
        {
          "name": "fn",
          "type": "(e: TriggerEvent) -> ()"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To launch a player off a jump pad as soon as they step on it",
          "side": "client",
          "code": "triggers.jump_pad:on(\"entered\", function(e)\n    me:set_velocity(vector.create(0, e.trigger.properties.launch, 0))\nend)\n"
        }
      ]
    },
    {
      "name": "is_inside",
      "group": "Map",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Whether the player stands inside `trigger`, a touch or a use trigger, as the server last found them.",
      "doc": "Whether the player stands inside `trigger`, a touch or a use trigger, as the server last found them.\n\nIt fails for a trigger of another type, and is false for one removed.",
      "params": [
        {
          "name": "trigger",
          "type": "Trigger"
        }
      ],
      "returns": "boolean",
      "examples": [
        {
          "title": "To heal a player while they stand in a spring",
          "side": "server",
          "code": "local spring = trigger(\"spring\", \"touch\", { box = vector.create(6, 3, 6) })\nif p:is_inside(spring) then\n    p:heal(5)\nend\n"
        }
      ]
    },
    {
      "name": "is_looking_at",
      "group": "Map",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Whether the player is looking at `trigger`, a look trigger, as the server last found them: their view meeting it before anything that stops shots.",
      "doc": "Whether the player is looking at `trigger`, a look trigger, as the server last found them: their view meeting it\nbefore anything that stops shots.\n\nIt fails for a trigger of another type, and is false for one removed.",
      "params": [
        {
          "name": "trigger",
          "type": "Trigger"
        }
      ],
      "returns": "boolean",
      "examples": [
        {
          "title": "To tell a player what they look at",
          "side": "server",
          "code": "local statue = trigger(\"statue\", \"look\", { box = vector.create(1, 3, 1) })\nif p:is_looking_at(statue) then\n    say(\"The founder, 1921\", { to = { p } })\nend\n"
        }
      ]
    },
    {
      "name": "is_using",
      "group": "Map",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Whether the player holds the use key on `trigger`, a use trigger, as the server last found them.",
      "doc": "Whether the player holds the use key on `trigger`, a use trigger, as the server last found them.\n\nIt fails for a trigger of another type, and is false for one removed.",
      "params": [
        {
          "name": "trigger",
          "type": "Trigger"
        }
      ],
      "returns": "boolean",
      "examples": []
    },
    {
      "name": "time_inside",
      "group": "Map",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "How many seconds the player has stood inside `trigger`, a touch or a use trigger, as the server last found them; nil when they are not.",
      "doc": "How many seconds the player has stood inside `trigger`, a touch or a use trigger, as the server last found them;\nnil when they are not.\n\nIt fails for a trigger of another type.",
      "params": [
        {
          "name": "trigger",
          "type": "Trigger"
        }
      ],
      "returns": "number?",
      "examples": []
    },
    {
      "name": "time_looking_at",
      "group": "Map",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "How many seconds the player has looked at `trigger`, a look trigger, as the server last found them; nil when they do not.",
      "doc": "How many seconds the player has looked at `trigger`, a look trigger, as the server last found them; nil when they\ndo not.\n\nIt fails for a trigger of another type.",
      "params": [
        {
          "name": "trigger",
          "type": "Trigger"
        }
      ],
      "returns": "number?",
      "examples": []
    },
    {
      "name": "time_using",
      "group": "Map",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "How many seconds the player has held the use key on `trigger`, a use trigger, as the server last found them; nil when they do not.",
      "doc": "How many seconds the player has held the use key on `trigger`, a use trigger, as the server last found them; nil\nwhen they do not.\n\nIt fails for a trigger of another type.",
      "params": [
        {
          "name": "trigger",
          "type": "Trigger"
        }
      ],
      "returns": "number?",
      "examples": [
        {
          "title": "To show how far a player is through opening a crate",
          "side": "server",
          "code": "local crate = trigger(\"crate\", \"use\", { box = vector.create(1, 1, 1) }, { activation_time = 4 })\nlocal held = p:time_using(crate)\nif held then\n    say(`Opening: {math.floor(held / 4 * 100)}%`, { to = { p } })\nend\n"
        }
      ]
    },
    {
      "name": "on",
      "group": "Map",
      "side": "server",
      "on": "Trigger",
      "since": "0.1",
      "summary": "Runs `fn` each time this trigger of the map hears `event`, given `{trigger, player}`.",
      "doc": "Runs `fn` each time this trigger of the map hears `event`, given `{trigger, player}`.\n\nIt is given at a module's top: a second for the same event in the same file replaces the first. A trigger hears\nits type's events alone: a touch trigger `entered` and `left`, a look trigger `looked_at` and `looked_away`, a use\ntrigger `use_pressed`, `use_released` and `use_cancelled`, a hold ended early by letting go, looking away or\nwalking out. Each hears `activated` once its condition has lasted its `activation_time`: at once without one, once\na stay, a look or a hold. A damage trigger hears `activated` on each shot or blast that reaches it, given\n`attacker`, as `player` too, `amount`, `means`, `weapon`, `point`, `dir` and `projectile`.\n\n`player` is a person, a bot or an NPC: players and NPCs touch, players alone look and use. The dead and the gone\nare heard leaving, as `left`, `looked_away` and `use_cancelled`, and so is whom it held as it is disabled. Removed\nby a handler, it hears nothing more of what the server found that tick; disabled by one, nothing that starts or\nsets it off, so of four players pressing the use key on one buy trigger in a tick, one buys it. A trigger made at\nrun time is listened to by its name before it is made, `triggers.revive:on` (`DeclaredTrigger:on`).\n\nA body is followed along the way it went during the tick, so one crossing a thin trigger at a sprint is heard\nentering and leaving, in order. A player standing in several use triggers uses the first `look` trigger their view\nmeets, else the one nearest their eyes. A damage trigger hears a shot only up to where it struck, with the damage it\ndoes that far.",
      "params": [
        {
          "name": "event",
          "type": "TriggerHears"
        },
        {
          "name": "fn",
          "type": "(e: TriggerEvent) -> ()"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To open a door for the player who buys it",
          "side": "server",
          "code": "triggers.buy_door:on(\"activated\", function(e)\n    say(`{e.player.name} opened the door`)\n    e.trigger:remove()\nend)\n"
        }
      ]
    },
    {
      "name": "on",
      "group": "Map",
      "side": "server",
      "on": "DeclaredTrigger",
      "since": "0.1",
      "summary": "Runs `fn` each time a trigger of this name, made at run time, hears `event`, given `{trigger, player}` as `Trigger:on`'s handlers are.",
      "doc": "Runs `fn` each time a trigger of this name, made at run time, hears `event`, given `{trigger, player}` as\n`Trigger:on`'s handlers are.\n\nA name the map has no trigger of reads as one declared: its handlers, given at a module's top, declare the name,\nso `trigger` makes triggers of it. Their type is known only as one is made, which fails if its type does not hear\nan event its handlers do.",
      "params": [
        {
          "name": "event",
          "type": "TriggerHears"
        },
        {
          "name": "fn",
          "type": "(e: TriggerEvent) -> ()"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To bring a player back where a teammate revived them",
          "side": "server",
          "code": "triggers.revive:on(\"activated\", function(e)\n    local fallen = e.trigger.owner\n    if fallen then\n        fallen:respawn()\n        fallen:set_position(e.trigger.position)\n    end\n    e.trigger:remove()\nend)\n"
        }
      ]
    },
    {
      "name": "remove",
      "group": "Map",
      "side": "server",
      "on": "Trigger",
      "since": "0.1",
      "summary": "Removes the trigger: it hears nothing more, reads `exists` false, and is left out of the sets made after. One removed already is left as it is.",
      "doc": "Removes the trigger: it hears nothing more, reads `exists` false, and is left out of the sets made after. One\nremoved already is left as it is.",
      "params": [],
      "returns": "()",
      "examples": [
        {
          "title": "To take away a revive point once it is used",
          "side": "server",
          "code": "local revive = trigger(\"revive\", \"use\", { sphere = 1 })\nrevive:remove()\n"
        }
      ]
    },
    {
      "name": "players",
      "group": "Map",
      "side": "server",
      "on": "Trigger",
      "since": "0.1",
      "summary": "The players and NPCs it holds, as the server last found them: those inside a touch trigger, looking at a look trigger or using a use trigger; none while it is disabled.",
      "doc": "The players and NPCs it holds, as the server last found them: those inside a touch trigger, looking at a look\ntrigger or using a use trigger; none while it is disabled.",
      "params": [],
      "returns": "{Player}",
      "examples": [
        {
          "title": "To heal everyone standing in a spring",
          "side": "server",
          "code": "local spring = trigger(\"spring\", \"touch\", { box = vector.create(6, 3, 6) })\nfor _, p in spring:players() do\n    p:heal(5)\nend\n"
        }
      ]
    },
    {
      "name": "attach",
      "group": "Map",
      "side": "server",
      "on": "Trigger",
      "since": "0.1",
      "summary": "Makes the trigger ride a player, an NPC, a model or a part, turning as it turns; once that goes, the trigger stays where it was.",
      "doc": "Makes the trigger ride a player, an NPC, a model or a part, turning as it turns; once that goes, the trigger stays\nwhere it was.\n\nOne gone already is left as it is.",
      "params": [
        {
          "name": "to",
          "type": "Player | Entity | number"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "offset",
              "doc": "Where its origin stays in the space of what it rides; at that origin without.",
              "type": "vector",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To make a zone that follows a player",
          "side": "server",
          "code": "local aura = trigger(\"aura\", \"touch\", { sphere = 3 }, { owner = p, triggered_by = everyone - owner })\naura:attach(p, { offset = vector.create(0, 1, 0) })\n"
        }
      ]
    },
    {
      "name": "detach",
      "group": "Map",
      "side": "server",
      "on": "Trigger",
      "since": "0.1",
      "summary": "Lets go of what the trigger rides, so it stays where it is.",
      "doc": "Lets go of what the trigger rides, so it stays where it is.",
      "params": [],
      "returns": "()",
      "examples": []
    },
    {
      "name": "set_position",
      "group": "Map",
      "side": "server",
      "on": "Trigger",
      "since": "0.1",
      "summary": "Moves the trigger's origin to `point` at once, letting go of what it rides; it sweeps nothing on the way.",
      "doc": "Moves the trigger's origin to `point` at once, letting go of what it rides; it sweeps nothing on the way.",
      "params": [
        {
          "name": "point",
          "type": "vector"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To move a buy point to where the box now stands",
          "side": "server",
          "code": "local box = trigger(\"mystery_box\", \"use\", { box = vector.create(2, 1, 1) })\nbox:set_position(vector.create(12, 0, -4))\n"
        }
      ]
    },
    {
      "name": "set_angles",
      "group": "Map",
      "side": "server",
      "on": "Trigger",
      "since": "0.1",
      "summary": "Turns the trigger about its origin to `angles` at once, letting go of what it rides; an angle left out is 0.",
      "doc": "Turns the trigger about its origin to `angles` at once, letting go of what it rides; an angle left out is 0.",
      "params": [
        {
          "name": "angles",
          "type": "Angles"
        }
      ],
      "returns": "()",
      "examples": []
    },
    {
      "name": "trigger",
      "group": "Map",
      "side": "server",
      "since": "0.1",
      "summary": "Makes a trigger at run time of a name a handler declared, of `kind` and `shape`, and gives it.",
      "doc": "Makes a trigger at run time of a name a handler declared, of `kind` and `shape`, and gives it.\n\nA name the map has no trigger of is declared by its handlers, `triggers.revive:on(…)`, given at a module's top;\nmaking one of a name no handler declared, or whose handlers hear an event `kind` does not, fails, as does one of a\nname the map has. An option of another type than `kind`'s fails: `detect` is a touch trigger's, `look` a use\ntrigger's, `means` and `weapons` a damage trigger's, and `activation_time` that of every type but damage. Each shape\nstands on its origin, a sphere and a box too. 1024 made at run time are alive at most.\n\nOne that `fires_on_client` is told each client as its player meets it, so their scripts hear it too: its name and\nproperties, and those of all such, within what a client joining is told at once.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "kind",
          "type": "\"touch\" | \"look\" | \"use\" | \"damage\""
        },
        {
          "name": "shape",
          "fields": [
            {
              "name": "box",
              "doc": "A box of this size along x, y and z, in metres, each 0.01 to 1000.",
              "type": "vector",
              "optional": true,
              "not_with": [
                "cylinder",
                "sphere"
              ]
            },
            {
              "name": "cylinder",
              "doc": "An upright cylinder.",
              "type": "TriggerCylinder",
              "optional": true,
              "fields": [
                {
                  "name": "radius",
                  "doc": "How far its side is from its upright axis.",
                  "type": "number",
                  "required": true,
                  "range": [
                    0.01,
                    1000.0
                  ]
                },
                {
                  "name": "height",
                  "doc": "How tall it stands from its origin up.",
                  "type": "number",
                  "required": true,
                  "range": [
                    0.01,
                    1000.0
                  ]
                }
              ],
              "not_with": [
                "box",
                "sphere"
              ]
            },
            {
              "name": "sphere",
              "doc": "A ball of this radius, in metres.",
              "type": "number",
              "optional": true,
              "range": [
                0.01,
                1000.0
              ],
              "not_with": [
                "box",
                "cylinder"
              ]
            }
          ]
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "at",
              "doc": "Where its origin stands; at the world's origin without.",
              "type": "vector",
              "optional": true
            },
            {
              "name": "angles",
              "doc": "How it is turned about its origin.",
              "type": "Angles",
              "optional": true
            },
            {
              "name": "owner",
              "doc": "The player it is about, whom `triggered_by` picks by.",
              "type": "Player | number",
              "optional": true
            },
            {
              "name": "triggered_by",
              "doc": "Who sets it off, and no NPC; everyone, NPCs too, without.",
              "type": "Group | ((Player?, Player) -> boolean)",
              "optional": true
            },
            {
              "name": "properties",
              "doc": "Its properties, as a mapper's: each a boolean, a number, a string or a list of them, 1024 at most.",
              "type": "{[string]: Property}",
              "optional": true
            },
            {
              "name": "fires_on_client",
              "doc": "Whether the scripts of each client hear what it hears of their own player too.",
              "type": "boolean",
              "default": false
            },
            {
              "name": "detect",
              "doc": "A touch trigger's: what of a body counts as inside, any of its box, its middle or all of it.",
              "type": "\"overlap\" | \"center\" | \"contain\"",
              "optional": true
            },
            {
              "name": "activation_time",
              "doc": "A touch, look or use trigger's: the seconds its condition lasts before `activated`; at once without.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                null
              ]
            },
            {
              "name": "look",
              "doc": "A use trigger's: whether the use key counts only while the player's view meets it.",
              "type": "boolean",
              "optional": true
            },
            {
              "name": "means",
              "doc": "A damage trigger's: the means of damage it hears, as `\"bullet\"`; any without.",
              "type": "{string}",
              "optional": true
            },
            {
              "name": "weapons",
              "doc": "A damage trigger's: the weapons it hears, by name; any without.",
              "type": "{string}",
              "optional": true
            }
          ]
        }
      ],
      "returns": "Trigger",
      "examples": [
        {
          "title": "To mark where a player fell, for a teammate to revive them",
          "side": "server",
          "code": "triggers.revive:on(\"activated\", function(e)\n    e.trigger:remove()\nend)\n\nlocal function revive_point(fallen)\n    return trigger(\"revive\", \"use\", { cylinder = { radius = 1, height = 2 } }, {\n        at = fallen.position,\n        owner = fallen,\n        activation_time = 3,\n        triggered_by = everyone - owner,\n        properties = { hint = `Revive {fallen.name}` },\n    })\nend\n\non(\"killed\", function(e)\n    revive_point(e.victim)\nend)\n"
        }
      ]
    },
    {
      "name": "loading_screen",
      "group": "Menus",
      "side": "client",
      "since": "0.1",
      "summary": "Draws the loading screen in place of the stock one while the match loads, once a mod, at a script's top.",
      "doc": "Draws the loading screen in place of the stock one while the match loads, once a mod, at a script's top.\n\nThe component is given `{map, title, image, gametype, stage, progress, bytes_done, bytes_total, bytes_per_second,\nbinds}` and draws again as they or what it read change. `title` and `image` are the map's, `image` nil for none.\nWhile connecting, `map` and `gametype` are empty and `title` is the server's address. `stage` is `\"connecting\"`,\n`\"waiting\"` (while the mod's `connecting` holds the join), `\"downloading\"`, `\"map\"`, `\"files\"` or\n`\"declarations\"`; `progress` is the share of the match's files loaded, 0 to 1, or while downloading of the bytes,\n`bytes_done` of `bytes_total` coming at `bytes_per_second`, all 0 at the other stages. `binds` are the purpose\nactions the server handles, each `{action, label, keys}`: the action, as `\"tactical\"`, the label it has here, and\nthe keys the player put it on, the first as Controls shows it first, empty for none.\n\nIt takes no pointer and goes once the match plays. The stock screen shows while none is declared, and from when\nits render fails until the match plays. Another script's call fails, naming both.",
      "params": [
        {
          "name": "component",
          "type": "(props: LoadingProps) -> Node?"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To show the map and a bar",
          "side": "client",
          "code": "loading_screen(function(props)\n    return Box {\n        `{props.title} ({props.stage})`,\n        Box { style = { width = `{props.progress * 100}%`, height = 8, background = \"#ffcc33\" } },\n        style = { left = 0, right = 0, bottom = 80, padding = 40, background = \"rgba(0, 0, 0, 0.6)\" },\n    }\nend)\n"
        },
        {
          "title": "To list the keys of what the server's mod does on them",
          "side": "client",
          "code": "loading_screen(function(props)\n    return Box {\n        Each(props.binds, function(bind)\n            return Box { `{bind.keys[1] or \"unbound\"}: {bind.label}`, key = bind.action }\n        end),\n        style = { left = 80, top = 80, fontSize = 28 },\n    }\nend)\n"
        }
      ]
    },
    {
      "name": "menu",
      "group": "Menus",
      "side": "client",
      "since": "0.1",
      "summary": "Declares a menu, which `open(menu, props)` shows over the HUD, freeing the pointer; gives its handle.",
      "doc": "Declares a menu, which `open(menu, props)` shows over the HUD, freeing the pointer; gives its handle.\n\nIt is declared at a script's top. Its name is up to 16 lowercase letters, digits and `_`, one script's: another\nscript declaring it fails, naming both. `render` is given the props `open` gave, copied, with `close(value)`,\nwhich closes it. One menu is open at a time, `open` replacing it. A player opens one with its action's key, a key\nthey bind to `open <name>`, or `/open <name>`, with no props.\n\nWhile a menu shows, the player's binds do nothing and the keys held are let go. A tap of Esc runs its\n`keys.Escape`, `false` for a forced choice, or else opens its `back`, or else closes it. Holding Esc a second always\nopens the engine's menu over the game, a ring filling from a quarter second: no script sees the hold.\n\n`action` takes a purpose action, as `\"buy\"`, which no mod binds to a key: the player has, once for every server. Two\nmenus on one action fail at load. A menu on an action the server handles opens as its handler hears the key go\ndown.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "pointer",
              "doc": "Frees the pointer, its tree taking hover and clicks, and takes every key; `false` keeps the player playing\nbut for its `keys`, which cannot then be Esc: the keys the player moves, jumps and chats with stay theirs.",
              "type": "boolean",
              "default": true
            },
            {
              "name": "keys",
              "doc": "What its keys do, as `{ Q = fn, [\"1\"] = fn, Enter = fn, Escape = false }`: a key a player binds or Escape,\neach given the props, `false` doing nothing; Mouse1 and Mouse2 only with `pointer = false`, as they click.",
              "type": "{[string]: ((props: MenuProps) -> ()) | false}",
              "optional": true
            },
            {
              "name": "onOpen",
              "doc": "Runs as it opens, given the props.",
              "type": "(props: MenuProps) -> ()",
              "optional": true
            },
            {
              "name": "onClose",
              "doc": "Runs as it closes, given the props.",
              "type": "(props: MenuProps) -> ()",
              "optional": true
            },
            {
              "name": "back",
              "doc": "The menu a tap of Esc opens in its place, by name, rather than closing it.",
              "type": "string",
              "optional": true
            },
            {
              "name": "toggle",
              "doc": "A key bound to open it, or to its action, closes it.",
              "type": "boolean",
              "default": false
            },
            {
              "name": "action",
              "doc": "The purpose action whose keys open it, as `\"buy\"`; the server's handler of it runs too.",
              "type": "\"tactical\" | \"lethal\" | \"utility\" | \"ultimate\" | \"buy\" | \"drop\" | \"quick_menu\" | \"ping\" | \"map\"",
              "optional": true
            },
            {
              "name": "hold",
              "doc": "Closes as the key that opened it is let go.",
              "type": "boolean",
              "default": false
            },
            {
              "name": "help",
              "doc": "Its line on Settings → Controls, up to 64 bytes.",
              "type": "string",
              "optional": true
            }
          ]
        },
        {
          "name": "render",
          "type": "(props: MenuProps) -> Node?"
        }
      ],
      "returns": "Menu",
      "examples": [
        {
          "title": "To open a shop on the player's buy key",
          "side": "client",
          "code": "local Shop = menu(\"shop\", { action = \"buy\", toggle = true, help = \"Buy weapons\" }, function(props)\n    return Box {\n        \"Shop\",\n        Box { \"Close\", onClick = function() props.close() end },\n        style = { left = \"40%\", top = \"30%\", padding = 24, background = \"rgba(0, 0, 0, 0.8)\" },\n    }\nend)\n"
        }
      ]
    },
    {
      "name": "dialog",
      "group": "Menus",
      "side": "client",
      "since": "0.1",
      "summary": "Declares a dialog, which `open(dialog, props)` shows over the menu, waiting for its answer; gives its handle.",
      "doc": "Declares a dialog, which `open(dialog, props)` shows over the menu, waiting for its answer; gives its handle.\n\nIt 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\none waits, in a handler only, until it closes, and gives what `props.close(value)` passed, or nil if it closed\notherwise: by Esc, which closes it unanswered unless its `keys.Escape` says, another dialog, or its menu closing.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "pointer",
              "doc": "Frees the pointer, its tree taking hover and clicks, and takes every key; `false` keeps the player playing\nbut for its `keys`, which cannot then be Esc: the keys the player moves, jumps and chats with stay theirs.",
              "type": "boolean",
              "default": true
            },
            {
              "name": "keys",
              "doc": "What its keys do, as `{ Q = fn, [\"1\"] = fn, Enter = fn, Escape = false }`: a key a player binds or Escape,\neach given the props, `false` doing nothing; Mouse1 and Mouse2 only with `pointer = false`, as they click.",
              "type": "{[string]: ((props: MenuProps) -> ()) | false}",
              "optional": true
            },
            {
              "name": "onOpen",
              "doc": "Runs as it opens, given the props.",
              "type": "(props: MenuProps) -> ()",
              "optional": true
            },
            {
              "name": "onClose",
              "doc": "Runs as it closes, given the props.",
              "type": "(props: MenuProps) -> ()",
              "optional": true
            }
          ]
        },
        {
          "name": "render",
          "type": "(props: MenuProps) -> Node?"
        }
      ],
      "returns": "Menu",
      "examples": [
        {
          "title": "To ask before buying",
          "side": "client",
          "code": "local Confirm = dialog(\"confirm\", { keys = { Enter = function(props) props.close(true) end } }, function(props)\n    return Box {\n        props.question,\n        Box { \"Yes\", onClick = function() props.close(true) end },\n        Box { \"No\", onClick = function() props.close(false) end },\n    }\nend)\nlocal Shop = menu(\"shop\", nil, function()\n    return Box {\n        \"Buy the MP40\",\n        onClick = function()\n            if open(Confirm, { question = \"Buy the MP40?\" }) then request(\"buy\") end\n        end,\n    }\nend)\n"
        }
      ]
    },
    {
      "name": "open",
      "group": "Menus",
      "side": "client",
      "since": "0.1",
      "summary": "Opens 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.",
      "doc": "Opens a menu, in place of the one open, or a dialog over it, its render given a copy of `props` with\n`close(value)`; a dialog's `open` gives its answer.\n\nA dialog opens in a handler alone, `on`, `onClick`, a menu's key or `onOpen`, as it waits until it closes: then\nit gives what `props.close(value)` passed, or nil if it closed otherwise.",
      "params": [
        {
          "name": "menu",
          "type": "Menu"
        },
        {
          "name": "props",
          "type": "{[string]: any}",
          "optional": true
        }
      ],
      "returns": "any",
      "examples": [
        {
          "title": "To open the shop when the player says so",
          "side": "client",
          "code": "local Shop = menu(\"shop\", nil, function(props)\n    return Box { `Shop, opened by {props.by}`, onClick = function() props.close() end }\nend)\non(\"said\", function(e)\n    if e.text == \"shop\" then open(Shop, { by = \"chat\" }) end\nend)\n"
        }
      ]
    },
    {
      "name": "close",
      "group": "Menus",
      "side": "client",
      "since": "0.1",
      "summary": "Closes a menu, and a dialog over it, or a dialog, unanswered; one not open is left as it is.",
      "doc": "Closes a menu, and a dialog over it, or a dialog, unanswered; one not open is left as it is.",
      "params": [
        {
          "name": "menu",
          "type": "Menu"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To close the shop as the player dies",
          "side": "client",
          "code": "local Shop = menu(\"shop\", nil, function() return Box { \"Shop\" } end)\non(\"killed\", function(e)\n    if e.victim == me then close(Shop) end\nend)\n"
        }
      ]
    },
    {
      "name": "is_open",
      "group": "Menus",
      "side": "client",
      "since": "0.1",
      "summary": "Whether a menu or a dialog is open: a read a render draws again on.",
      "doc": "Whether a menu or a dialog is open: a read a render draws again on.",
      "params": [
        {
          "name": "menu",
          "type": "Menu"
        }
      ],
      "returns": "boolean",
      "examples": [
        {
          "title": "To dim the HUD while the shop is open",
          "side": "client",
          "code": "local Shop = menu(\"shop\", nil, function() return Box { \"Shop\" } end)\nmount(function()\n    return Box { \"Round 1\", style = { left = 40, top = 40, opacity = if is_open(Shop) then 0.3 else 1 } }\nend)\n"
        }
      ]
    },
    {
      "name": "escape_menu",
      "group": "Menus",
      "side": "client",
      "since": "0.1",
      "summary": "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.",
      "doc": "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\neach tap, whose nil opens the engine's.\n\nA mod calls it once, at a script's top; another script's call fails, naming both. Holding Esc a second always\nopens the engine's menu.",
      "params": [
        {
          "name": "menu",
          "type": "Menu | () -> Menu?"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To open the mod's own pause menu",
          "side": "client",
          "code": "local Pause = menu(\"pause\", nil, function(props)\n    return Box { \"Paused\", Box { \"Resume\", onClick = function() props.close() end } }\nend)\nescape_menu(Pause)\n"
        }
      ]
    },
    {
      "name": "set_velocity",
      "group": "Movement",
      "side": "client",
      "on": "player",
      "since": "0.1",
      "summary": "Sets the player's own velocity, in metres a second, in a handler of a trigger that fires on clients, so a jump pad throws them at once.",
      "doc": "Sets the player's own velocity, in metres a second, in a handler of a trigger that fires on clients, so a jump pad\nthrows them at once.\n\nThe player's game carries it out from the next command on, and the server's handler of the same trigger gives the\nsame order, which the game then confirms: the two agreeing show nothing, and differing a correction, once. It is\nchecked as the server's is. Anywhere else, or on another player, it fails.",
      "params": [
        {
          "name": "velocity",
          "type": "vector"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To throw the player up off a jump pad at once",
          "side": "client",
          "code": "triggers.jump_pad:on(\"entered\", function()\n    me:set_velocity(vector.create(0, 8, 0))\nend)\n"
        }
      ]
    },
    {
      "name": "add_velocity",
      "group": "Movement",
      "side": "client",
      "on": "player",
      "since": "0.1",
      "summary": "Adds to the player's own velocity, in metres a second, in a handler of a trigger that fires on clients, as `me:set_velocity` sets it.",
      "doc": "Adds to the player's own velocity, in metres a second, in a handler of a trigger that fires on clients, as\n`me:set_velocity` sets it.",
      "params": [
        {
          "name": "velocity",
          "type": "vector"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To push the player along a conveyor at once",
          "side": "client",
          "code": "triggers.conveyor:on(\"entered\", function()\n    me:add_velocity(vector.create(4, 0, 0))\nend)\n"
        }
      ]
    },
    {
      "name": "tune",
      "group": "Movement",
      "side": "client",
      "on": "player",
      "since": "0.1",
      "summary": "Scales how the player's own body moves, in a handler of a trigger that fires on clients, as `me:set_velocity` pushes it; a player's game scales no weapons.",
      "doc": "Scales how the player's own body moves, in a handler of a trigger that fires on clients, as `me:set_velocity`\npushes it; a player's game scales no weapons.",
      "params": [
        {
          "name": "scales",
          "fields": [
            {
              "name": "speed",
              "doc": "Their running speed.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                10.0
              ]
            },
            {
              "name": "jump",
              "doc": "How high they jump.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                10.0
              ]
            },
            {
              "name": "gravity",
              "doc": "Their gravity: at 0 a jump stays on the ground and a landing is no fall.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                10.0
              ]
            },
            {
              "name": "bob",
              "doc": "How much their eyes bob with each stride.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                10.0
              ]
            },
            {
              "name": "sway",
              "doc": "How much their weapon moves before their eyes: its bob, its lag behind the view's turns and its breathing.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                10.0
              ]
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To slow the player at once as they step into mud",
          "side": "client",
          "code": "triggers.mud:on(\"entered\", function()\n    me:tune({ speed = 0.5 })\nend)\n"
        }
      ]
    },
    {
      "name": "limit_view",
      "group": "Movement",
      "side": "client",
      "on": "player",
      "since": "0.1",
      "summary": "Limits the player's own view, in a handler of a trigger that fires on clients, as `me:set_velocity` pushes them; `around` is angles or an entity, which the server checks.",
      "doc": "Limits the player's own view, in a handler of a trigger that fires on clients, as `me:set_velocity` pushes them;\n`around` is angles or an entity, which the server checks.",
      "params": [
        {
          "name": "limits",
          "optional": true,
          "fields": [
            {
              "name": "around",
              "doc": "What `yaw`, `pitch` and `cone` are measured from: angles, a roll ignored, or a model, a shape or a part as it\nturns.",
              "type": "Angles | Entity",
              "optional": true
            },
            {
              "name": "yaw",
              "doc": "How far the view turns left and right of `around`: radians either way, or `{min, max}` within half a turn,\npositive turning left.",
              "type": "AngleRange",
              "optional": true,
              "not_with": [
                "cone"
              ]
            },
            {
              "name": "pitch",
              "doc": "How far the view turns down and up from `around`, as `yaw`, positive looking up.",
              "type": "AngleRange",
              "optional": true,
              "not_with": [
                "cone"
              ]
            },
            {
              "name": "cone",
              "doc": "The most the view strays from `around`'s direction, in radians, in place of `yaw` and `pitch`.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                3.1415927410125732
              ],
              "not_with": [
                "pitch",
                "yaw"
              ]
            },
            {
              "name": "speed",
              "doc": "The fastest the view turns, in radians a second; 0 freezes it.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                null
              ]
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To hold the player's view ahead as they sit in a turret",
          "side": "client",
          "code": "triggers.turret_seat:on(\"entered\", function()\n    me:limit_view({ around = { yaw = 0 }, yaw = 0.8, pitch = 0.4 })\nend)\n"
        }
      ]
    },
    {
      "name": "set_position",
      "group": "Movement",
      "side": "client",
      "on": "player",
      "since": "0.1",
      "summary": "Moves the player's own body to a point at once, in a handler of a trigger that fires on clients, so a teleport shows at once, as `me:set_velocity` pushes them.",
      "doc": "Moves the player's own body to a point at once, in a handler of a trigger that fires on clients, so a teleport\nshows at once, as `me:set_velocity` pushes them.",
      "params": [
        {
          "name": "point",
          "type": "vector"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To teleport the player at once as they step onto a pad",
          "side": "client",
          "code": "triggers.teleport:on(\"entered\", function()\n    me:set_position(vector.create(0, 1, 20))\nend)\n"
        }
      ]
    },
    {
      "name": "set_angles",
      "group": "Movement",
      "side": "client",
      "on": "player",
      "since": "0.1",
      "summary": "Turns the player's own view, by `yaw` and `pitch`, in a handler of a trigger that fires on clients, as `me:set_velocity` pushes them; a roll fails.",
      "doc": "Turns the player's own view, by `yaw` and `pitch`, in a handler of a trigger that fires on clients, as\n`me:set_velocity` pushes them; a roll fails.",
      "params": [
        {
          "name": "angles",
          "type": "Angles"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To turn the player round as they come out of a teleport",
          "side": "client",
          "code": "triggers.teleport:on(\"entered\", function()\n    me:set_angles({ yaw = math.pi })\nend)\n"
        }
      ]
    },
    {
      "name": "control",
      "group": "Movement",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Hands a player's input to a model, a shape, a camera or a part in place of their body, until `p:control(nil)` gives it back.",
      "doc": "Hands a player's input to a model, a shape, a camera or a part in place of their body, until `p:control(nil)`\ngives it back.\n\nTheir movement keys, their view and their buttons then drive the entity. Without `movement` they drive nothing:\nthe mod moves the entity with its orders and reads `p.move` and `p.held` as it likes. `movement` names a file of\nthe mod's that moves a model or a camera at each of the player's commands: `<name>.server.luau`, run on the server\nalone, so the player sees it move a ping late, or `<name>.shared.luau`, run on their game too, so they see it move\nat once, as their body. A module's own `<name>.server.luau` is no movement, so name a movement apart from it.\n\nA movement file returns `{ hull = { radius, height }, state = t.record { … }, step = function(car, input, dt,\nworld) … end }`. `step` changes `car` in place: its `position`, `velocity`, `angles`, `on_ground`, and `state`, a\nrecord of up to 16 numbers, whole numbers, booleans, short strings, vectors and choices, starting at each field's\nzero. `input` is `{ move = { forward, right }, angles = { yaw, pitch }, held }`, and `dt` a tick. `world:move(car,\nby)` sweeps the hull, an upright capsule, by up to 3.9 m, sliding along what it meets, and gives `{ position,\non_ground }`; `world:ground(point)` gives the floor under a point, and `world:trace(from, to)` the first thing on a\nline, `{ position, normal }`. A step is pure: it reads Luau's libraries, `vector`, `angles` and `t` alone, gives no\norders, and `math.random` and `now()` fail in it. The state goes whole to the player in every snapshot, so keep it\nto a few numbers. The steps of a tick share 2 ms, past which the commands left are dropped.\n\nThe hull's radius and height are each 5 cm or more, up to 3 m and 4 m. It meets what stops players and never a body;\na hull starting inside something is moved out by an inch. A step leaves the entity riding nothing, and an order of\nthe mod's moving it is where the next step starts. A string in the state is 32 bytes at most. A step that fails\nleaves the entity as it was, and the error is said once. Loaded again in place with a state of another type, a\nmovement starts its state afresh.\n\nMeanwhile the body stands where it was, and can be hurt and killed there; its view turns with the input and its\nweapon still fires, unless the mod disables it. Control outlasts death and a respawn. It ends as the entity is\nremoved, as the player leaves, or at a new match. On an NPC or a player it fails, and with a movement on a shape or\na part, which every player's game is told of; on what is gone it does nothing. A movement file that fails to load\nfails `control`.",
      "params": [
        {
          "name": "target",
          "type": "Entity",
          "optional": true
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "movement",
              "doc": "The movement file of the mod's that steps it, by its path without `.server.luau` or `.shared.luau`.",
              "type": "string",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To fly a player's gunship along its path while they aim from it",
          "side": "server",
          "code": "local plane = spawn_camera({ at = vector.create(0, 40, -30) })\nplane:move_along({ vector.create(30, 40, 0), vector.create(0, 40, 30), vector.create(-30, 40, 0) }, 20, { loop = true })\np:set_camera(plane)\np:control(plane)\n"
        },
        {
          "title": "To give a player back their body",
          "side": "server",
          "code": "p:control(nil)\np:set_camera(nil)\n"
        }
      ]
    },
    {
      "name": "set_position",
      "group": "Movement",
      "side": "server",
      "on": "both",
      "since": "0.1",
      "summary": "Moves a player, an NPC, a model, a shape, a camera or a part to a point at once.",
      "doc": "Moves a player, an NPC, a model, a shape, a camera or a part to a point at once.\n\nA player goes on as fast, in the same stance and looking the same way, off any ladder or ledge, as CoD's\n`setOrigin`; a dead one is not moved. An NPC lands on the navmesh's point nearest it, and finds its way on from\nthere. The point is within 100 km of the map's origin. `move_to` moves a model or a part over some seconds. On a\nlooping sound or effect it fails; on what is gone it does nothing.",
      "params": [
        {
          "name": "point",
          "type": "vector"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To send a player back to where they started",
          "side": "server",
          "code": "local start = p.position\nwait(5)\np:set_position(start)\n"
        },
        {
          "title": "To put a crate on a ledge",
          "side": "server",
          "code": "local crate = model(\"rocket\")\ncrate:set_position(vector.create(3, 2, -4))\n"
        }
      ]
    },
    {
      "name": "set_angles",
      "group": "Movement",
      "side": "server",
      "on": "both",
      "since": "0.1",
      "summary": "Turns a player's view, an NPC, a model, a shape, a camera or a part at once, each angle left out kept.",
      "doc": "Turns a player's view, an NPC, a model, a shape, a camera or a part at once, each angle left out kept.\n\nA player turns by `yaw` and `pitch`, and an NPC by its `yaw` alone: a roll on either, or a pitch on an NPC, fails.\nA dead player is not turned. `rotate_to` turns a model or a part over some seconds. On a looping sound or effect it\nfails; on what is gone it does nothing.",
      "params": [
        {
          "name": "angles",
          "type": "Angles"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To turn a player to face the way they came",
          "side": "server",
          "code": "p:set_angles({ yaw = p.yaw + math.pi })\n"
        },
        {
          "title": "To tip a crate onto its side",
          "side": "server",
          "code": "local crate = model(\"rocket\")\ncrate:set_angles({ roll = math.pi / 2 })\n"
        }
      ]
    },
    {
      "name": "tune",
      "group": "Movement",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Scales how a player moves: their running speed, jump height and gravity, their view's bob and their weapon's sway.",
      "doc": "Scales how a player moves: their running speed, jump height and gravity, their view's bob and their weapon's sway.\n\nEach scale is 1 as the engine has it, and those left out are kept; the scales outlast death. `weapons` scales the\nstats of every weapon the player holds, after the weapon's own tune, each by 0 to 10: `interval`'s scales a burst's\ntoo, and each result stays within what a weapon's file may give. A weapon taken away is back to its own stats, and\nthe next player to hold it scales it by their own. Each scaled weapon counts as one of the 4096 a mod names: past\nthem, a weapon stays unscaled, which the server says as the mod's error. On an NPC it fails.",
      "params": [
        {
          "name": "scales",
          "fields": [
            {
              "name": "speed",
              "doc": "Their running speed.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                10.0
              ]
            },
            {
              "name": "jump",
              "doc": "How high they jump.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                10.0
              ]
            },
            {
              "name": "gravity",
              "doc": "Their gravity: at 0 a jump stays on the ground and a landing is no fall.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                10.0
              ]
            },
            {
              "name": "bob",
              "doc": "How much their eyes bob with each stride.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                10.0
              ]
            },
            {
              "name": "sway",
              "doc": "How much their weapon moves before their eyes: its bob, its lag behind the view's turns and its breathing.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                10.0
              ]
            },
            {
              "name": "weapons",
              "doc": "Every weapon they hold, after its own tune: each stat named, by its scale, as a perk such as Double Tap does.",
              "type": "{[\"damage\" | \"interval\" | \"range\" | \"penetrate\" | \"spread\" | \"spread_moving\" | \"spread_air\" | \"reload\" | \"drop\" | \"raise\" | \"sprint_out\" | \"move_speed\" | \"fire_delay\" | \"aim_time\" | \"aim_spread\" | \"melee_damage\" | \"melee_range\" | \"melee_time\" | \"melee_delay\"]: number}",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To slow a player wading through mud",
          "side": "server",
          "code": "p:tune({ speed = 0.5, jump = 0.5 })\n"
        },
        {
          "title": "To give a player Double Tap",
          "side": "server",
          "code": "p:tune({ weapons = { interval = 0.75, damage = 2 } })\n"
        },
        {
          "title": "To float in low gravity for ten seconds",
          "side": "server",
          "code": "p:tune({ gravity = 0.2 })\nwait(10)\np:tune({ gravity = 1 })\n"
        }
      ]
    },
    {
      "name": "hold",
      "group": "Movement",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Holds a player where they are, in the air too, until `p:hold(false)` lets them go.",
      "doc": "Holds a player where they are, in the air too, until `p:hold(false)` lets them go.\n\nA held player still looks around, fires and changes stance, as CoD2's `linkTo` holds them, and what they stand on\nstill carries them. The hold outlasts death. On an NPC it fails.",
      "params": [
        {
          "name": "held",
          "type": "boolean"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To freeze everyone for a round's countdown",
          "side": "server",
          "code": "for _, p in players do\n    if not p.npc then\n        p:hold(true)\n    end\nend\nwait(5)\nfor _, p in players do\n    if not p.npc then\n        p:hold(false)\n    end\nend\n"
        }
      ]
    },
    {
      "name": "limit_view",
      "group": "Movement",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Keeps a player's view within ranges, or turning no faster than a speed, until `p:limit_view(nil)` lifts it.",
      "doc": "Keeps a player's view within ranges, or turning no faster than a speed, until `p:limit_view(nil)` lifts it.\n\n`yaw`, `pitch` and `cone` are measured from `around`, which they need. At an edge the view stops, and it moves off\nit at once, never winding past it; the ranges win over the speed there. A limit about an entity removed keeps its\nspeed alone. A new limit replaces the last, and the limit outlasts death. On an NPC it fails.",
      "params": [
        {
          "name": "limits",
          "optional": true,
          "fields": [
            {
              "name": "around",
              "doc": "What `yaw`, `pitch` and `cone` are measured from: angles, a roll ignored, or a model, a shape or a part as it\nturns.",
              "type": "Angles | Entity",
              "optional": true
            },
            {
              "name": "yaw",
              "doc": "How far the view turns left and right of `around`: radians either way, or `{min, max}` within half a turn,\npositive turning left.",
              "type": "AngleRange",
              "optional": true,
              "not_with": [
                "cone"
              ]
            },
            {
              "name": "pitch",
              "doc": "How far the view turns down and up from `around`, as `yaw`, positive looking up.",
              "type": "AngleRange",
              "optional": true,
              "not_with": [
                "cone"
              ]
            },
            {
              "name": "cone",
              "doc": "The most the view strays from `around`'s direction, in radians, in place of `yaw` and `pitch`.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                3.1415927410125732
              ],
              "not_with": [
                "pitch",
                "yaw"
              ]
            },
            {
              "name": "speed",
              "doc": "The fastest the view turns, in radians a second; 0 freezes it.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                null
              ]
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To keep a player in a turret looking ahead",
          "side": "server",
          "code": "local turret = model(\"rocket\")\np:limit_view({ around = turret, yaw = math.pi / 4, pitch = { min = -0.2, max = 0.5 } })\n"
        },
        {
          "title": "To freeze a player's view for a cutscene",
          "side": "server",
          "code": "p:limit_view({ speed = 0 })\nwait(3)\np:limit_view(nil)\n"
        }
      ]
    },
    {
      "name": "set_velocity",
      "group": "Movement",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Sets a player's velocity, in metres a second, as a jump pad throws them.",
      "doc": "Sets a player's velocity, in metres a second, as a jump pad throws them.\n\nThe velocity is up to 100 m/s long. A dead player is not pushed. On an NPC it fails.",
      "params": [
        {
          "name": "velocity",
          "type": "vector"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To throw a player up into the air",
          "side": "server",
          "code": "p:set_velocity(vector.create(0, 8, 0))\n"
        }
      ]
    },
    {
      "name": "add_velocity",
      "group": "Movement",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Adds to a player's velocity, in metres a second, as a blast pushes them.",
      "doc": "Adds to a player's velocity, in metres a second, as a blast pushes them.\n\nThe push is up to 100 m/s long, and takes them no faster than 100 m/s or than they already went. A dead player is\nnot pushed. On an NPC it fails.",
      "params": [
        {
          "name": "velocity",
          "type": "vector"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To knock a player back from a blast",
          "side": "server",
          "code": "local blast = vector.create(0, 0, 0)\nlocal away = vector.normalize(p.position - blast + vector.create(0, 1, 0))\np:add_velocity(away * 6)\n"
        }
      ]
    },
    {
      "name": "attack",
      "group": "NPCs",
      "side": "server",
      "on": "both",
      "since": "0.1",
      "summary": "Plays an NPC's attack: a jab, or the clip it names, so each of an NPC's attacks may have its own.",
      "doc": "Plays an NPC's attack: a jab, or the clip it names, so each of an NPC's attacks may have its own.\n\nIt hurts no one: the mod hurts whom the attack reaches, as it likes. On a player it fails; on an NPC gone it does\nnothing.",
      "params": [
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "animation",
              "doc": "The `.anim` file it plays; `punch_jab` without.",
              "type": "animation",
              "optional": true
            },
            {
              "name": "length",
              "doc": "How long it lasts, in seconds, above 0; the clip's own without.",
              "type": "number",
              "optional": true,
              "range": [
                0.0,
                3600.0
              ]
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To have a zombie jab, then swing a cross",
          "side": "server",
          "code": "local zombie = spawn({ at = vector.create(0, 0, 1) })\nzombie:attack()\nwait(0.5)\nzombie:attack({ animation = \"punch_cross\", length = 0.6 })\n"
        }
      ]
    },
    {
      "name": "spawn",
      "group": "NPCs",
      "side": "server",
      "since": "0.1",
      "summary": "Spawns an NPC on the navmesh, standing still, and gives it as a player's object.",
      "doc": "Spawns an NPC on the navmesh, standing still, and gives it as a player's object.\n\nIt is listed among the players, and takes the orders an NPC takes whether held from `players` or `entities`. It\nhas no health nor weapons of the engine's: a mod that lets players kill it keeps its own count, and removes it.",
      "params": [
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "at",
              "doc": "Where it stands, on the navmesh's point nearest; the map's origin without.",
              "type": "vector",
              "optional": true
            },
            {
              "name": "owner",
              "doc": "The player it is about, whom `owner`, `team` and `spectators` pick by.",
              "type": "Player | number",
              "optional": true
            },
            {
              "name": "read_by",
              "doc": "Who is shown it; everyone without.",
              "type": "Group | ((Player?, Player) -> boolean)",
              "optional": true
            },
            {
              "name": "kind",
              "doc": "Its kind, one `entity_kind` declared on its base; the base's own without.",
              "type": "string",
              "optional": true
            }
          ]
        }
      ],
      "returns": "Player",
      "examples": [
        {
          "title": "To spawn a zombie that hunts a player",
          "side": "server",
          "code": "local zombie = spawn({ at = vector.create(0, 0, 20) })\nzombie:set_name(\"Zombie\")\nzombie:chase(p)\n"
        },
        {
          "title": "To spawn a boss its target alone sees",
          "side": "server",
          "code": "local boss = spawn({ at = vector.create(0, 0, 20), owner = p, read_by = owner })\nboss:set_speed(2)\n"
        }
      ]
    },
    {
      "name": "walk_to",
      "group": "NPCs",
      "side": "server",
      "on": "both",
      "since": "0.1",
      "summary": "Walks an NPC across the navmesh to the point nearest a point, finding its way around walls and closed doors.",
      "doc": "Walks an NPC across the navmesh to the point nearest a point, finding its way around walls and closed doors.\n\nIt walks there and stands, until another order. On a player, a model or a part it fails; on an NPC gone it does\nnothing.",
      "params": [
        {
          "name": "point",
          "type": "vector"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To send a zombie to a window",
          "side": "server",
          "code": "local zombie = spawn()\nzombie:walk_to(vector.create(12, 0, 4))\n"
        }
      ]
    },
    {
      "name": "chase",
      "group": "NPCs",
      "side": "server",
      "on": "both",
      "since": "0.1",
      "summary": "Makes an NPC chase a player across the navmesh, following them as they move, until another order.",
      "doc": "Makes an NPC chase a player across the navmesh, following them as they move, until another order.",
      "params": [
        {
          "name": "player",
          "type": "Player | number"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To set a zombie on a player",
          "side": "server",
          "code": "local zombie = spawn({ at = vector.create(0, 0, 15) })\nzombie:chase(p)\n"
        }
      ]
    },
    {
      "name": "set_speed",
      "group": "NPCs",
      "side": "server",
      "on": "both",
      "since": "0.1",
      "summary": "Sets how fast an NPC walks, in meters a second.",
      "doc": "Sets how fast an NPC walks, in meters a second.",
      "params": [
        {
          "name": "speed",
          "type": "number",
          "range": [
            0.0,
            null
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To make a zombie sprint",
          "side": "server",
          "code": "local zombie = spawn()\nzombie:set_speed(6)\n"
        }
      ]
    },
    {
      "name": "set_name",
      "group": "NPCs",
      "side": "server",
      "on": "both",
      "since": "0.1",
      "summary": "Names an NPC, so it passes as a player: every player's game lists it with the players, as a scoreboard does, and shows its name, as in chat and a kill feed.",
      "doc": "Names an NPC, so it passes as a player: every player's game lists it with the players, as a scoreboard does, and\nshows its name, as in chat and a kill feed.\n\nThe name is cleaned and cut as a player's is. Nil, or a name empty once cleaned, takes the name away. On a player\nit fails: their name is their own.",
      "params": [
        {
          "name": "name",
          "type": "string",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To name a boss",
          "side": "server",
          "code": "local boss = spawn()\nboss:set_name(\"The Butcher\")\n"
        }
      ]
    },
    {
      "name": "bumps",
      "group": "NPCs",
      "side": "server",
      "since": "0.1",
      "summary": "Declares which kinds of body a kind bumps into: a player's body, or an NPC's.",
      "doc": "Declares which kinds of body a kind bumps into: a player's body, or an NPC's.\n\nBodies are round, stop a move as a wall does, can be stood on, and are never pushed. Without it nothing bumps, and\nNPCs only steer clear of each other. Each kind's is declared by one module, at its top as it loads: a second\nmodule's fails at load, naming both, and a module declaring it again replaces its own.",
      "params": [
        {
          "name": "kind",
          "type": "\"player\" | \"npc\""
        },
        {
          "name": "kinds",
          "type": "{\"player\" | \"npc\"}"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To make players and zombies block each other",
          "side": "server",
          "code": "bumps(\"player\", { \"player\", \"npc\" })\nbumps(\"npc\", { \"player\", \"npc\" })\n"
        }
      ]
    },
    {
      "name": "net_usage",
      "group": "Players",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Gives what the server sent a player's game over the last second, or nil for a player with none, as a bot.",
      "doc": "Gives what the server sent a player's game over the last second, or nil for a player with none, as a bot.\n\n`rate` is the most the player's game takes and `sent` the bytes sent, both a second; `full` is the share of the rate\nsent. `kinds` holds the bytes by what they carried: `own_player`, `players`, `npcs`, `props`, `parts`, `sounds`,\n`effects`, `projectiles`, `damage`, `kills`, `hits_too_late`, `lines`, `file_names`, `rules`, `commands`,\n`settings`, `channels`, `player_records`, `state_values`, `mod_events`, `netgraph`, `hidden_shapes` and `framing`;\nand `declared` those each of the modules' declarations took, its values, its events and the state riding with\nentities, by its name, an entity kind's state as `kind.name`; a state, a player state and an event of one name add\nup under it. `packets` and `lost` count the packets sent and those found lost, and `left_out` the entities the rate\nleft out. The server rolls it over once a second, so read it in a handler or a timer. On an NPC it fails.",
      "params": [],
      "returns": "NetUsage?",
      "examples": [
        {
          "title": "To warn the players whose rate is nearly full",
          "side": "server",
          "code": "for _, p in players do\n    local usage = if p.npc then nil else p:net_usage()\n    if usage and usage.full > 0.8 then\n        say(`{math.floor(usage.full * 100)}% of your rate is used`, { to = { p } })\n    end\nend\n"
        }
      ]
    },
    {
      "name": "set_team",
      "group": "Players",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Puts a player on a team, 0 being none, as everyone starts.",
      "doc": "Puts a player on a team, 0 being none, as everyone starts.\n\nThe team is kept through death, and every player's game tints the player by it: 1 red, 2 blue, 3 yellow. Each\nplayer's team reaches everyone, however far they are. On an NPC it fails.",
      "params": [
        {
          "name": "team",
          "type": "number",
          "range": [
            0.0,
            3.0
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To split the players into two teams",
          "side": "server",
          "code": "local count = 0\nfor _, p in players do\n    if not p.npc then\n        count += 1\n        p:set_team(if count % 2 == 1 then 1 else 2)\n    end\nend\n"
        }
      ]
    },
    {
      "name": "kick",
      "group": "Players",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Drops a player from the server, their game back at the main menu showing \"Kicked:\" and the reason.",
      "doc": "Drops a player from the server, their game back at the main menu showing \"Kicked:\" and the reason.\n\nThe reason is cut to 100 bytes, without control characters. The player may join again at once, unlike after an\nadmin's `/kick`. On an NPC it fails: remove it instead.",
      "params": [
        {
          "name": "reason",
          "type": "string"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To kick a player who idles",
          "side": "server",
          "code": "p:kick(\"idle for too long\")\n"
        }
      ]
    },
    {
      "name": "announce_next_match",
      "group": "Settings",
      "side": "server",
      "since": "0.1",
      "summary": "Tells every player the match that comes next, so their game downloads its files while this one plays; it starts nothing.",
      "doc": "Tells every player the match that comes next, so their game downloads its files while this one plays; it starts\nnothing.\n\nIt is checked as `start_match` is. A later call replaces it, and a player who joins is told the last. `start_match()`\nstill starts the rotation's next match, which the rotation announces itself as each match starts.",
      "params": [
        {
          "name": "map",
          "type": "string"
        },
        {
          "name": "gametype",
          "type": "string"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To announce the map a vote chose",
          "side": "server",
          "code": "announce_next_match(\"yard\", \"tdm\")\n"
        }
      ]
    },
    {
      "name": "start_match",
      "group": "Settings",
      "side": "server",
      "since": "0.1",
      "summary": "Ends this match and starts the next: with no arguments the rotation's, else that map and gametype.",
      "doc": "Ends this match and starts the next: with no arguments the rotation's, else that map and gametype.\n\nIt fails at the call for a map the server has not, a gametype the map does not list, or one the mod has not. The\nnext map loads while this match plays on; then this match's `ending` handlers run, and the switch removes every\nentity, timer and waiting handler and starts `match_state` and `player_state` from their defaults, while\n`server_state` stays and `match.number` counts on. Without a rotation, `start_match()` plays this match again;\n`start_match(match.map, match.gametype)` restarts it and leaves the rotation where it is.",
      "params": [
        {
          "name": "map",
          "type": "string",
          "optional": true
        },
        {
          "name": "gametype",
          "type": "string",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To play team deathmatch on yard once a team wins",
          "side": "server",
          "code": "event(\"team_won\", t.record { team = t.int })\n\non(\"team_won\", function()\n  start_match(\"yard\", \"tdm\")\nend)\n"
        },
        {
          "title": "To go on to the rotation's next match",
          "side": "server",
          "code": "start_match()\n"
        }
      ]
    },
    {
      "name": "snapshot_rate",
      "group": "Settings",
      "side": "server",
      "since": "0.1",
      "summary": "Asks for `rate` snapshots a second: 10, 12, 15, 20, 30 or 60, which divide the server's 60 ticks a second; 20 without it.",
      "doc": "Asks for `rate` snapshots a second: 10, 12, 15, 20, 30 or 60, which divide the server's 60 ticks a second; 20\nwithout it.\n\nOne module declares it, at its top as it loads: a second module's fails at load, naming both. Any other rate fails\nat load, and on an edit is printed and the rate kept. The server sends at the most of those within it and its\n`max_snapshot_rate` setting, 60 by default, and prints the rate it sends at. Each player's game gets the most of the\nrates dividing that one whose snapshots each have 500 bytes of its `rate`: at 60 a second, a player at 10000 bytes a\nsecond gets 20, and one at 25000 gets 30. A player's game draws the others two of its snapshots behind the newest,\n100 ms at 20 and 33 ms at 60, easing into a new rate's delay. `on_tick` runs 20 times a second at any rate.",
      "params": [
        {
          "name": "rate",
          "type": "number"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To send fast moves at once, for a mod of duels",
          "side": "server",
          "code": "snapshot_rate(60)\n"
        }
      ]
    },
    {
      "name": "stop",
      "group": "Sounds",
      "side": "client",
      "on": "PlayingSound",
      "since": "0.1",
      "summary": "Fades the sound out, or stops it at once without a transition; one stopped already is left as it is.",
      "doc": "Fades the sound out, or stops it at once without a transition; one stopped already is left as it is.",
      "params": [
        {
          "name": "transition",
          "type": "Transition",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To ring in the ear after a blast, then fade it out",
          "side": "client",
          "code": "local ring = play_sound(\"tinnitus\", { loop = true, volume = 0.6 })\nring:stop({ seconds = 3 })\n"
        }
      ]
    },
    {
      "name": "set",
      "group": "Sounds",
      "side": "client",
      "on": "SoundMix",
      "since": "0.1",
      "summary": "Turns down and muffles each category it names, eased over `transition`, at once without; `sound_mix.world` and the rest read back what was last set.",
      "doc": "Turns down and muffles each category it names, eased over `transition`, at once without; `sound_mix.world` and\nthe rest read back what was last set.\n\nIt changes this player's mix alone, the sounds the server plays among it. Each category reads `{volume = 1,\nmuffle = 0}` until set, and a new match sets them so again. A muffle is a low-pass from 20 kHz, clear, down to\n200 Hz at 1.",
      "params": [
        {
          "name": "categories",
          "fields": [
            {
              "name": "weapons",
              "doc": "Shots, reloads and the rest of the weapons' sounds.",
              "type": "Mix",
              "optional": true,
              "fields": [
                {
                  "name": "volume",
                  "doc": "How loud, 0 silent and 1 as made.",
                  "type": "number",
                  "optional": true,
                  "range": [
                    0.0,
                    1.0
                  ]
                },
                {
                  "name": "muffle",
                  "doc": "How muffled, 0 clear and 1 as through a wall.",
                  "type": "number",
                  "optional": true,
                  "range": [
                    0.0,
                    1.0
                  ]
                }
              ]
            },
            {
              "name": "world",
              "doc": "The world's own sounds: steps, doors, blasts and voices.",
              "type": "Mix",
              "optional": true,
              "fields": [
                {
                  "name": "volume",
                  "doc": "How loud, 0 silent and 1 as made.",
                  "type": "number",
                  "optional": true,
                  "range": [
                    0.0,
                    1.0
                  ]
                },
                {
                  "name": "muffle",
                  "doc": "How muffled, 0 clear and 1 as through a wall.",
                  "type": "number",
                  "optional": true,
                  "range": [
                    0.0,
                    1.0
                  ]
                }
              ]
            },
            {
              "name": "music",
              "doc": "The music the mod plays.",
              "type": "Mix",
              "optional": true,
              "fields": [
                {
                  "name": "volume",
                  "doc": "How loud, 0 silent and 1 as made.",
                  "type": "number",
                  "optional": true,
                  "range": [
                    0.0,
                    1.0
                  ]
                },
                {
                  "name": "muffle",
                  "doc": "How muffled, 0 clear and 1 as through a wall.",
                  "type": "number",
                  "optional": true,
                  "range": [
                    0.0,
                    1.0
                  ]
                }
              ]
            },
            {
              "name": "interface",
              "doc": "Menus' and the HUD's clicks and banners.",
              "type": "Mix",
              "optional": true,
              "fields": [
                {
                  "name": "volume",
                  "doc": "How loud, 0 silent and 1 as made.",
                  "type": "number",
                  "optional": true,
                  "range": [
                    0.0,
                    1.0
                  ]
                },
                {
                  "name": "muffle",
                  "doc": "How muffled, 0 clear and 1 as through a wall.",
                  "type": "number",
                  "optional": true,
                  "range": [
                    0.0,
                    1.0
                  ]
                }
              ]
            }
          ]
        },
        {
          "name": "transition",
          "type": "Transition",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To muffle the world after a blast, then bring it back",
          "side": "client",
          "code": "sound_mix:set({ world = { volume = 0.3, muffle = 0.85 }, weapons = { muffle = 1 } }, { seconds = 0.3 })\nsound_mix:set({ world = { volume = 1, muffle = 0 }, weapons = { muffle = 0 } }, { seconds = 4, timing = \"ease-in\" })\n"
        }
      ]
    },
    {
      "name": "play_sound",
      "group": "Sounds",
      "side": "client",
      "since": "0.1",
      "summary": "Plays a sound for this player alone, as hover and click sounds, banners and a ringing ear need; gives its handle, whose `stop(transition)` fades it out.",
      "doc": "Plays a sound for this player alone, as hover and click sounds, banners and a ringing ear need; gives its handle,\nwhose `stop(transition)` fades it out.\n\nNo other player hears it, and it costs no network. It starts as the frame ends, 16 a frame at most, and 64 plays\nand stops wait at most. A sound whose file still loads is not heard. The scripts' sounds play 32 at once, a new one\nstopping the oldest, and 16 longer than 30 s, past which one is not heard. A name the server never named fails.",
      "params": [
        {
          "name": "name",
          "type": "sound"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "volume",
              "doc": "How loud, 1 as the file was made.",
              "type": "number",
              "range": [
                0.0,
                1.0
              ],
              "default": 1.0
            },
            {
              "name": "speed",
              "doc": "How fast it plays, its pitch rising with it.",
              "type": "number",
              "range": [
                0.25,
                4.0
              ],
              "default": 1.0
            },
            {
              "name": "loop",
              "doc": "Plays again and again, until its handle's `stop`.",
              "type": "boolean",
              "default": false
            },
            {
              "name": "at",
              "doc": "The point in the world it is heard from; alike in both ears without.",
              "type": "vector",
              "optional": true
            },
            {
              "name": "range",
              "doc": "How far from `at` it is heard, in metres; at any distance, from its direction, with `math.huge`.",
              "type": "number",
              "range": [
                1.0,
                1000.0
              ],
              "or_huge": true,
              "default": 40.0
            },
            {
              "name": "category",
              "doc": "The part of the mix it plays in, which `sound_mix` turns down and muffles.",
              "type": "\"weapons\" | \"world\" | \"music\" | \"interface\"",
              "default": "interface"
            }
          ]
        }
      ],
      "returns": "PlayingSound",
      "examples": [
        {
          "title": "To reload in this player's ears alone",
          "side": "client",
          "code": "play_sound(\"ak47_reload\", { volume = 0.5, category = \"weapons\" })\n"
        },
        {
          "title": "To ring in the ear after a blast, then fade it out",
          "side": "client",
          "code": "local ring = play_sound(\"tinnitus\", { loop = true, volume = 0.6 })\nring:stop({ seconds = 3 })\n"
        },
        {
          "title": "To hear a blast where it went off, for this player alone",
          "side": "client",
          "code": "play_sound(\"explosion_boom\", { at = vector.create(4, 1, -2), range = 100, category = \"world\" })\n"
        }
      ]
    },
    {
      "name": "play_sound",
      "group": "Sounds",
      "side": "server",
      "since": "0.1",
      "summary": "Plays a sound for the players who hear it, once, or again and again with `loop` until `stop_sound`.",
      "doc": "Plays a sound for the players who hear it, once, or again and again with `loop` until `stop_sound`.\n\nA sound at a point, or following a player or an entity, is heard by the players within its `range`; one with neither\nby everyone, alike in both ears. Each sound costs network for every player who hears it, so on a busy server far\nsounds wait for near ones. A player hears a sound where they stand, or while dead where the player they watch\nstands. A player who joins while a loop plays hears it from where it is. A sound played once ends by itself; with\n`loop`, `play_sound` gives the sound's entity, which `kind` names, so `kind` without `loop` fails. One played once\nthat follows something absent is not heard; a loop is silent while what it follows is absent. A player's game plays\n16 sounds longer than 30 s at once, and not one past them.",
      "params": [
        {
          "name": "name",
          "type": "sound"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "at",
              "doc": "The point it is heard from; alike everywhere, by everyone, without `at` or `follow`.",
              "type": "vector",
              "optional": true,
              "not_with": [
                "follow"
              ]
            },
            {
              "name": "follow",
              "doc": "A player or an entity it moves with; a loop stops once the entity is removed or the player leaves.",
              "type": "Player | Entity | number",
              "optional": true,
              "not_with": [
                "at"
              ]
            },
            {
              "name": "loop",
              "doc": "Plays again and again until `stop_sound`, and `play_sound` gives the sound's entity.",
              "type": "boolean",
              "default": false
            },
            {
              "name": "volume",
              "doc": "How loud, 1 as the file was made.",
              "type": "number",
              "range": [
                0.0,
                1.0
              ],
              "default": 1.0
            },
            {
              "name": "speed",
              "doc": "How fast it plays, its pitch rising with it.",
              "type": "number",
              "range": [
                0.25,
                4.0
              ],
              "default": 1.0
            },
            {
              "name": "range",
              "doc": "How far from `at` or `follow` it is heard, in metres; at any distance, from its direction, with `math.huge`.",
              "type": "number",
              "range": [
                1.0,
                1000.0
              ],
              "or_huge": true,
              "default": 40.0
            },
            {
              "name": "category",
              "doc": "The part of each player's mix it plays in, which a client script turns down and muffles (`sound_mix`).",
              "type": "\"weapons\" | \"world\" | \"music\" | \"interface\"",
              "default": "world"
            },
            {
              "name": "start",
              "doc": "When it starts, in seconds from now: up to an hour ago, heard from part-way through, or up to 5 s ahead.",
              "type": "number",
              "range": [
                -3600.0,
                5.0
              ],
              "default": 0.0
            },
            {
              "name": "owner",
              "doc": "The player it is about, whom `owner`, `team` and `spectators` pick by.",
              "type": "Player | number",
              "optional": true
            },
            {
              "name": "read_by",
              "doc": "Who is shown it; everyone without.",
              "type": "Group | ((Player?, Player) -> boolean)",
              "optional": true
            },
            {
              "name": "kind",
              "doc": "Its kind, one `entity_kind` declared on its base; the base's own without.",
              "type": "string",
              "optional": true
            }
          ]
        }
      ],
      "returns": "Entity?",
      "examples": [
        {
          "title": "To play a shot where it was fired",
          "side": "server",
          "code": "play_sound(\"awp_fire\", { at = p.position, range = 200, category = \"weapons\" })\n"
        },
        {
          "title": "To blast every player's ears, wherever they are",
          "side": "server",
          "code": "play_sound(\"explosion_boom\", { volume = 0.8 })\n"
        },
        {
          "title": "To groan from a zombie as it walks, and stop the groan",
          "side": "server",
          "code": "local zombie = spawn()\nlocal groan = play_sound(\"zombie_groan1\", { follow = zombie, loop = true, range = 25 })\nstop_sound(groan)\n"
        }
      ]
    },
    {
      "name": "stop_sound",
      "group": "Sounds",
      "side": "server",
      "since": "0.1",
      "summary": "Stops a looping sound `play_sound` gave; one stopped already, or gone with what it followed, is left as it is.",
      "doc": "Stops a looping sound `play_sound` gave; one stopped already, or gone with what it followed, is left as it is.",
      "params": [
        {
          "name": "sound",
          "type": "Entity"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To hold a grenade's hiss until it is thrown",
          "side": "server",
          "code": "local hiss = play_sound(\"grenade_hold\", { follow = p, loop = true, range = 10 })\nstop_sound(hiss)\n"
        }
      ]
    },
    {
      "name": "on",
      "group": "State and events",
      "side": "client",
      "since": "0.1",
      "summary": "Hears an event, the engine's or one of the modules' the server sends this player, by its name or as `<module>.<name>`: `fn` is given its fields, frozen.",
      "doc": "Hears an event, the engine's or one of the modules' the server sends this player, by its name or as\n`<module>.<name>`: `fn` is given its fields, frozen.\n\nA handler is given at a script's top, as it loads, one a name in each file of the script, its own and each it\nrequires: a second replaces the first. Several scripts may hear one name, in the order they listened. Each frame,\nthe players who joined and left come first, then what the triggers heard of the player, then the events in order,\nthen `frame`. A module's event with no `read_by`, which stays on the server, fails, as does a request. A value an\nevent reads may come after it: check for nil where that matters. A client has no `wait`: a handler that yields\nfails, but where `open` waits for a dialog's answer.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "fn",
          "type": "(e: {[string]: any}) -> ()"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To count the frames drawn",
          "side": "client",
          "code": "local frames = 0\non(\"frame\", function(e)\n  frames += 1\nend)\n"
        },
        {
          "title": "To count this player's deaths",
          "side": "client",
          "code": "local deaths = 0\non(\"killed\", function(e)\n  if e.victim == me then\n    deaths += 1\n  end\nend)\n"
        }
      ]
    },
    {
      "name": "request",
      "group": "State and events",
      "side": "client",
      "since": "0.1",
      "summary": "Sends the server one of its requests, by its name or as `<module>.<name>`, its payload checked against the declaration here and again there, as the frame ends.",
      "doc": "Sends the server one of its requests, by its name or as `<module>.<name>`, its payload checked against the\ndeclaration here and again there, as the frame ends.\n\nThe payload may be left out where none of its fields is needed. While the match loads, requests wait until it\nplays, 64 at most; those past it are dropped. A request has no reply: what it does comes back as state or an\nevent.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "payload",
          "type": "{[string]: any}",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To buy armor at a click",
          "side": "client",
          "code": "mount(function()\n  return Box {\n    \"Buy armor\",\n    onClick = function()\n      request(\"buy_armor\")\n    end,\n  }\nend)\n"
        }
      ]
    },
    {
      "name": "require",
      "group": "State and events",
      "side": "client",
      "since": "0.1",
      "summary": "Runs another of the mod's client or shared files, by its path in its layer and its side without `.luau`, and gives what it returns.",
      "doc": "Runs another of the mod's client or shared files, by its path in its layer and its side without `.luau`, and gives\nwhat it returns.\n\nA path is a `.client` file (`modules/ui/button.client`), a `.shared` one the server runs too\n(`modules/ranks/ranks.shared`) or another script (`modules/teams/teams.client`). A server file, even by name, or a\nfile the server did not name fails, as does a file requiring itself. Each script runs a file once a load, in an\nenvironment of its own, and keeps what it gave: two scripts requiring one component get one each, each listening\nand drawing for itself. Its time is the script's that required it.",
      "params": [
        {
          "name": "path",
          "type": "string"
        }
      ],
      "returns": "any",
      "examples": []
    },
    {
      "name": "group",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "summary": "Makes a group of a function, which `+` and `-` combine with the others: it picks the players it returns true for.",
      "doc": "Makes a group of a function, which `+` and `-` combine with the others: it picks the players it returns true for.\n\nA `read_by` takes the function as it is too. The same function makes the same group. It is given each player's\nobject as `viewer`, and picks them for any value but nil and false; it may only read. It is asked again at once when\na declared value it read changes, or a player's name or team, or someone joins or leaves; else once a second.",
      "params": [
        {
          "name": "picks",
          "type": "(owner: Player?, viewer: Player) -> boolean"
        }
      ],
      "returns": "Group",
      "examples": [
        {
          "title": "To show a flag to the living and the admins",
          "side": "server",
          "code": "local living = group(function(_, viewer)\n  return viewer.health > 0\nend)\nlocal flag = model(\"rocket\", { read_by = living + admins })\n"
        }
      ]
    },
    {
      "name": "on",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "summary": "Hears an event, the engine's or a module's, by its name or as `<module>.<name>`: `fn` is given its fields.",
      "doc": "Hears an event, the engine's or a module's, by its name or as `<module>.<name>`: `fn` is given its fields.\n\nA handler is given at a module's top, as it loads, and a module has one of a name in each of its files: a second\nreplaces the first. Handlers run in the order the modules loaded, those `after` once the rest have. Each runs as a\ncoroutine: before its first `wait` it may change the event's fields, which those after it and the clients get, or\nreturn false, which stops the event there, and the clients hear nothing. After a `wait`, what it held may be gone:\ncheck `exists`. A handler's error is said once and undoes what it did since it started or last waited, its changes\nto the event among them; the other handlers run on. A name no module declares and the engine has not fails the load.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "fn",
          "type": "(e: {[string]: any}) -> any"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "after",
              "doc": "Runs once the handlers without it have, as a module's default does after a gametype's own.",
              "type": "boolean",
              "default": false
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To greet each player who joins",
          "side": "server",
          "code": "on(\"joined\", function(e)\n  say(`Welcome, {e.player.name}`)\nend)\n"
        },
        {
          "title": "To halve fall damage",
          "side": "server",
          "code": "on(\"fell\", function(e)\n  e.amount /= 2\nend)\n"
        },
        {
          "title": "To keep a kill quiet once every other module has heard of it",
          "side": "server",
          "code": "on(\"killed\", function(e)\n  return false\nend, { after = true })\n"
        }
      ]
    },
    {
      "name": "emit",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "summary": "Sends a module's event, its payload checked against its declaration: to its handlers here, then to the players its `read_by` picks.",
      "doc": "Sends a module's event, its payload checked against its declaration: to its handlers here, then to the players its\n`read_by` picks.\n\nThe name may be another module's as `module.name`. The payload may be left out where none of its fields is needed.\nIt gives the event as its handlers left it, or nil if one stopped it. An event naming an entity, or an NPC as its\n`player`, goes only to those shown it, and to no one once its handlers removed it. Its `read_by` is asked again at\neach `emit`. A request is not emitted: clients send it.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "payload",
          "type": "{[string]: any}",
          "optional": true
        }
      ],
      "returns": "({[any]: any})?",
      "examples": [
        {
          "title": "To tell everyone a round was won, and say so here",
          "side": "server",
          "code": "event(\"round_won\", t.record { team = t.int }, { read_by = everyone })\n\non(\"round_won\", function(e)\n  say(`Team {e.team} wins the round`)\nend)\n\non(\"start\", function()\n  emit(\"round_won\", { team = 1 })\nend)\n"
        }
      ]
    },
    {
      "name": "on_request",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "summary": "Declares a request clients send, its payload a `t.record`, and its one handler, given its sender as `player`.",
      "doc": "Declares a request clients send, its payload a `t.record`, and its one handler, given its sender as `player`.\n\nIt is declared at a module's top, as it loads, and named as an event is; a second handler of a name fails the load.\nA client script sends it with `request`, a player with `/request` or a key bound to it. It arrives checked against\nits declaration, the players it names here and the entities alive and shown to the sender, at most 10 a second after\na burst of 5; anything else is dropped. Any player may send any request at any time, so its handler checks what it\nis asked and never takes a price from the client. It has no reply: the result goes back as state or an event. Its\nhandler runs on the sender's time, 2 ms a tick: one past it is dropped, and a player past it 20 ticks in a row is\nkicked. 16 handlers of one player's requests wait at once at most; the rest are dropped.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "schema",
          "type": "Type"
        },
        {
          "name": "fn",
          "type": "(e: {player: Player, [string]: any}) -> ()"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To sell armor to a player who can pay",
          "side": "server",
          "code": "player_state(\"coins\", t.int { min = 0 }, 0, { read_by = owner })\n\non_request(\"buy_armor\", t.record {}, function(e)\n  if e.player.coins >= 100 then\n    e.player.coins -= 100\n    e.player:set_max_health(150)\n  end\nend)\n"
        }
      ]
    },
    {
      "name": "require",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "summary": "Runs another of the mod's server or shared files, by its path in its layer and its side without `.luau`, and gives what it returns.",
      "doc": "Runs another of the mod's server or shared files, by its path in its layer and its side without `.luau`, and gives\nwhat it returns.\n\nA file runs once a load, the first time it is required, with `main.server.luau`'s globals, and every module\nrequiring it gets the one value it gave: keep what changes in declared state, not in it. A path is lowercase\nletters, digits and `_` between slashes, as `modules/teams/teams_lib.server` or `modules/ranks/ranks.shared`. A\nclient file is the clients' alone and a weapon's the engine's, so neither is required here, and a file requiring\nitself fails. A mod of one file has no `require`.",
      "params": [
        {
          "name": "path",
          "type": "string"
        }
      ],
      "returns": "any",
      "examples": []
    },
    {
      "name": "match_state",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "summary": "Declares a value of the match's, which `match.<name>` reads and writes, from `default` again each match.",
      "doc": "Declares a value of the match's, which `match.<name>` reads and writes, from `default` again each match.\n\nA declaration is made at a module's top, as it loads. Its name is up to 32 lowercase letters, digits and `_`, not a\nLuau word nor one of the engine's (`map`, `gametype`, `number`), and is the module's alone: another module's of the\nname fails the load, naming both. It is read as `match[\"<module>.<name>\"]` too, `main.` for `main.server.luau`'s and\n`engine.` for the engine's (`match[\"engine.number\"]`). A write is checked against its type at its line, and a value\noutside its limits is refused, never clamped. A list, a record or a map read is frozen: change it by writing it\nwhole. Without a `read_by` it is the server's alone; one picking by an owner (`owner`, `team`, `spectators`) fails,\nas the match has none.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "type",
          "type": "Type"
        },
        {
          "name": "default",
          "type": "any"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "read_by",
              "doc": "The players sent it, whose client scripts read it; the server's alone without.",
              "type": "Group | ((Player?, Player) -> boolean)",
              "optional": true
            },
            {
              "name": "help",
              "doc": "What it is, in a line of up to 128 bytes, which the editor shows on hover.",
              "type": "string",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To count the rounds, for everyone's screen",
          "side": "server",
          "code": "match_state(\"round\", t.int { min = 0 }, 0, { read_by = everyone, help = \"The round being played\" })\n\non(\"start\", function()\n  match.round += 1\nend)\n"
        }
      ]
    },
    {
      "name": "server_state",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "summary": "Declares a value of the server's, which `server.<name>` reads and writes, kept from match to match until the server stops; with `set_by`, a setting.",
      "doc": "Declares a value of the server's, which `server.<name>` reads and writes, kept from match to match until the server\nstops; with `set_by`, a setting.\n\nIt is checked as `match_state`'s is. A setting has its value as soon as it is declared, so the lines after it read\nit as configured: its default, under the server's file, under the environment (`SET_SCORE_LIMIT`, or\n`SET_TDM__SCORE_LIMIT` for module `tdm`'s), under `--set`, under `/set` or a write of the mod's. A setting is not\nnamed as one of the engine's commands or the client's settings. One the server's `--lock` fixes refuses a write,\nfailing at its line (`server.score_limit is locked at 30`), and at a module's top failing the load. A secret,\n`t.secret(t.string)`, is `set_by = config` and has no `read_by`.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "type",
          "type": "Type"
        },
        {
          "name": "default",
          "type": "any"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "read_by",
              "doc": "The players sent it, whose client scripts read it; the server's alone without.",
              "type": "Group | ((Player?, Player) -> boolean)",
              "optional": true
            },
            {
              "name": "set_by",
              "doc": "Who may change it with `/set`, which makes it a setting, or `config` for the server's configuration alone.",
              "type": "Group | ((Player?, Player) -> boolean) | Config",
              "optional": true
            },
            {
              "name": "help",
              "doc": "What it is, in a line of up to 128 bytes, which `/set` and the editor show.",
              "type": "string",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To keep the best round played since the server started",
          "side": "server",
          "code": "server_state(\"best_round\", t.int { min = 0 }, 0, { read_by = everyone })\n"
        },
        {
          "title": "To let admins set the points that win a match",
          "side": "server",
          "code": "server_state(\"score_limit\", t.int { min = 1, max = 999 }, 50, {\n  read_by = everyone,\n  set_by = admins,\n  help = \"Team points that win the match\",\n})\n"
        },
        {
          "title": "To take a database's address from the server's configuration alone",
          "side": "server",
          "code": "server_state(\"stats_db\", t.secret(t.string), \"sqlite:stats.sqlite3\", { set_by = config })\n"
        }
      ]
    },
    {
      "name": "player_state",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "summary": "Declares a value of each player's, the NPCs among them, which `p.<name>` reads and writes, from `default` as they join, until they leave or the match ends.",
      "doc": "Declares a value of each player's, the NPCs among them, which `p.<name>` reads and writes, from `default` as they\njoin, until they leave or the match ends.\n\nIt is checked as `match_state`'s is, and is not named as a player's own field or method (`health`, `hurt`). Its\nowner is the player, whom `owner`, `team` and `spectators` pick by. A person's reaches the players its `read_by`\npicks wherever they are; an NPC's rides with its body, so it reaches only those shown the NPC.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "type",
          "type": "Type"
        },
        {
          "name": "default",
          "type": "any"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "read_by",
              "doc": "The players sent it, whose client scripts read it; the server's alone without.",
              "type": "Group | ((Player?, Player) -> boolean)",
              "optional": true
            },
            {
              "name": "help",
              "doc": "What it is, in a line of up to 128 bytes, which the editor shows on hover.",
              "type": "string",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To count each player's kills, shown to everyone",
          "side": "server",
          "code": "player_state(\"kills\", t.int { min = 0 }, 0, { read_by = everyone })\n\non(\"killed\", function(e)\n  if e.killer then\n    e.killer.kills += 1\n  end\nend)\n"
        }
      ]
    },
    {
      "name": "entity_kind",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "summary": "Declares a kind of entity, on one of the engine's bases, which the calls making one take as their `kind`.",
      "doc": "Declares a kind of entity, on one of the engine's bases, which the calls making one take as their `kind`.\n\nA `\"prop\"` is made by `model`, a `\"body\"` by `spawn`, a `\"sound\"` by `play_sound` and an `\"effect\"` by\n`play_effect`, each a looping one. Its `entity_state` is each such entity's. A kind is named as state is, and is\nits module's alone.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "base",
          "type": "\"prop\" | \"body\" | \"sound\" | \"effect\""
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To give crates coins a player takes",
          "side": "server",
          "code": "entity_kind(\"crate\", \"prop\")\nentity_state(\"crate\", \"coins\", t.int { min = 0 }, 10)\n\non(\"start\", function()\n  local box = model(\"rocket\", { kind = \"crate\" })\n  box.coins -= 1\nend)\n"
        }
      ]
    },
    {
      "name": "entity_state",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "summary": "Declares a value of each entity of a kind `entity_kind` declared, which `e.<name>` reads and writes, from `default` as it is made, until it is removed.",
      "doc": "Declares a value of each entity of a kind `entity_kind` declared, which `e.<name>` reads and writes, from `default`\nas it is made, until it is removed.\n\nIt is checked as `match_state`'s is, and is not named as an entity's own field or method (`position`, `move_to`).\nIts owner is the entity's, whom `owner`, `team` and `spectators` pick by. A client is sent it only while it is shown\nthe entity.",
      "params": [
        {
          "name": "kind",
          "type": "string"
        },
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "type",
          "type": "Type"
        },
        {
          "name": "default",
          "type": "any"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "read_by",
              "doc": "The players sent it, whose client scripts read it; the server's alone without.",
              "type": "Group | ((Player?, Player) -> boolean)",
              "optional": true
            },
            {
              "name": "help",
              "doc": "What it is, in a line of up to 128 bytes, which the editor shows on hover.",
              "type": "string",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To show a turret's shells to its owner alone",
          "side": "server",
          "code": "entity_kind(\"turret\", \"prop\")\nentity_state(\"turret\", \"shells\", t.int { min = 0, max = 6 }, 6, { read_by = owner })\n"
        }
      ]
    },
    {
      "name": "event",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "summary": "Declares an event of the module's, its payload a `t.record`, which `emit` sends and `on` hears, on the server and on the clients its `read_by` picks.",
      "doc": "Declares an event of the module's, its payload a `t.record`, which `emit` sends and `on` hears, on the server and on\nthe clients its `read_by` picks.\n\nIt is named as state is, and not as one of the engine's events. Its payload's `player`, of `t.player` or\n`t.optional(t.player)`, names the player it is about, else its `entity` an entity, whose owner `owner`, `team` and\n`spectators` pick by; one naming an entity reaches only those shown it. A `read_by` picking by an owner needs one of\nthe two.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "schema",
          "type": "Type"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "read_by",
              "doc": "The players sent it, whose client scripts hear it; the server's alone without.",
              "type": "Group | ((Player?, Player) -> boolean)",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To tell a player, and those watching them, that they bought something",
          "side": "server",
          "code": "event(\"bought\", t.record { player = t.player, item = t.string }, { read_by = owner + spectators })\n\non(\"start\", function()\n  emit(\"bought\", { player = players[1], item = \"armor\" })\nend)\n"
        }
      ]
    },
    {
      "name": "now",
      "group": "Timers",
      "side": "client",
      "since": "0.1",
      "summary": "The server's mod clock as this client reckons it, in seconds, 0 before the first snapshot; with `step`, rounded down to a whole number of `step` seconds.",
      "doc": "The server's mod clock as this client reckons it, in seconds, 0 before the first snapshot; with `step`, rounded\ndown to a whole number of `step` seconds.\n\nIt reads the same clock as the server's `now()`, so a time the mod keeps in state reads here as there:\n`now() - match.started`. Read in a render, `now()` draws it again every frame, but `now(step)` once a step: `now(1)`\nfor a countdown of seconds. `step` is above 0.",
      "params": [
        {
          "name": "step",
          "type": "number",
          "optional": true
        }
      ],
      "returns": "number",
      "examples": [
        {
          "title": "To count down the last minute",
          "side": "client",
          "code": "local ends = now() + 60\n\nmount(function()\n  return Box { `{math.max(0, math.ceil(ends - now(1)))} s`, style = { right = 40, top = 40 } }\nend)\n"
        }
      ]
    },
    {
      "name": "wait",
      "group": "Timers",
      "side": "server",
      "since": "0.1",
      "summary": "Pauses the handler, timer or command for `seconds`: it goes on with the next line at the first mod tick that much later.",
      "doc": "Pauses the handler, timer or command for `seconds`: it goes on with the next line at the first mod tick that much\nlater.\n\nWhat it held may be gone by then: check a player's or an entity's `exists`. A handler waits, never a module's\ntop, `on_tick`, `on_event`, a group or a function called outside a handler. A reload in place, or a new match,\ndrops the handlers waiting. A handler's error undoes what it did since it last waited, or since it started.",
      "params": [
        {
          "name": "seconds",
          "type": "number",
          "range": [
            0.0,
            3600.0
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To respawn a player after a countdown",
          "side": "server",
          "code": "for left = 3, 1, -1 do\n  say(`Respawning in {left}`, { to = { p } })\n  wait(1)\nend\nif p.exists then\n  p:respawn()\nend\n"
        }
      ]
    },
    {
      "name": "timer",
      "group": "Timers",
      "side": "server",
      "since": "0.1",
      "summary": "Names the function the module's timer `name` runs, given the timer's player if it has one.",
      "doc": "Names the function the module's timer `name` runs, given the timer's player if it has one.\n\nA module names its timers at its top, as it loads, and starts them with `delay` or `loop`. A timer is its module's,\nby its name and its player, so two modules' timers of one name never meet. It runs the function its name has as it\nfires, so after a reload in place an edit takes effect at its next run. A module's names are those its last load\ngave, or those before if that load failed; a timer whose name has no function as it fires is dropped, and said. A\ntimer goes with its player, and with its module.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "fn",
          "type": "(player: Player?) -> ()"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To end a round once its time is up",
          "side": "server",
          "code": "timer(\"time_up\", function()\n  say(\"Time is up\")\n  start_match()\nend)\n\non(\"start\", function()\n  delay(\"time_up\", 300)\nend)\n"
        }
      ]
    },
    {
      "name": "delay",
      "group": "Timers",
      "side": "server",
      "since": "0.1",
      "summary": "Runs the module's timer `name` once, `seconds` from now, given `player` if one is given; given again before it runs, it starts over.",
      "doc": "Runs the module's timer `name` once, `seconds` from now, given `player` if one is given; given again before it\nruns, it starts over.\n\nA timer given a player is separate from one of the same name with no player or another player, and goes as they\nleave. It runs as a handler does, a coroutine that may `wait`, on the mod tick within half a tick of its time, after\nthat tick's handlers. Timers outlast a reload in place, and go as the map changes. A name the module gave no\n`timer` fails.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "seconds",
          "type": "number",
          "range": [
            0.0,
            3600.0
          ]
        },
        {
          "name": "player",
          "type": "Player | number",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To bring a player back 5 seconds after they die",
          "side": "server",
          "code": "timer(\"respawn\", function(p)\n  p:respawn()\nend)\n\non(\"killed\", function(e)\n  delay(\"respawn\", 5, e.victim)\nend)\n"
        }
      ]
    },
    {
      "name": "loop",
      "group": "Timers",
      "side": "server",
      "since": "0.1",
      "summary": "Runs the module's timer `name` every `seconds`, given `player` if one is given, until `cancel`; given again, it takes the new time and keeps its beat.",
      "doc": "Runs the module's timer `name` every `seconds`, given `player` if one is given, until `cancel`; given again, it\ntakes the new time and keeps its beat.\n\n`seconds` is above 0 and up to an hour. A beat that ran late counts on from then, and one that fails is done for\nthat beat alone. Otherwise it is a timer as `delay`'s.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "seconds",
          "type": "number"
        },
        {
          "name": "player",
          "type": "Player | number",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To give every player 10 points every 5 seconds",
          "side": "server",
          "code": "player_state(\"points\", t.int { min = 0 }, 0, { read_by = everyone })\n\ntimer(\"income\", function()\n  for _, p in players do\n    p.points += 10\n  end\nend)\n\non(\"start\", function()\n  loop(\"income\", 5)\nend)\n"
        }
      ]
    },
    {
      "name": "cancel",
      "group": "Timers",
      "side": "server",
      "since": "0.1",
      "summary": "Stops the module's timer `name`, of `player` if one is given; one not running is left as it is.",
      "doc": "Stops the module's timer `name`, of `player` if one is given; one not running is left as it is.",
      "params": [
        {
          "name": "name",
          "type": "string"
        },
        {
          "name": "player",
          "type": "Player | number",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To bleed a player who is hit until they bandage",
          "side": "server",
          "code": "timer(\"bleed\", function(p)\n  p:hurt(2)\nend)\n\non(\"hit\", function(e)\n  loop(\"bleed\", 1, e.victim)\nend)\n\ncommand(\"bandage\", { help = \"Stop your bleeding\" }, function(e)\n  cancel(\"bleed\", e.player)\nend)\n"
        }
      ]
    },
    {
      "name": "now",
      "group": "Timers",
      "side": "server",
      "since": "0.1",
      "summary": "The mod's time, in seconds, as of its last tick.",
      "doc": "The mod's time, in seconds, as of its last tick.\n\nA client's `now()` reckons the same clock, so a time the mod keeps in state reads there as it does here.",
      "params": [],
      "returns": "number",
      "examples": [
        {
          "title": "To keep when the match started, for the clients' clocks",
          "side": "server",
          "code": "match_state(\"started\", t.number, 0, { read_by = everyone })\n\non(\"start\", function()\n  match.started = now()\nend)\n"
        }
      ]
    },
    {
      "name": "aimed",
      "group": "Traces",
      "side": "client",
      "since": "0.1",
      "summary": "Gives the player or NPC under the crosshair as the player's game draws this frame, or nil for none.",
      "doc": "Gives the player or NPC under the crosshair as the player's game draws this frame, or nil for none.\n\nIt looks along the line from the eye through the middle of the screen, against the map and the bodies drawn.\nModels, parts and shapes are never aimed at. A render that reads it draws again as it changes. The server checks\nagain anything that matters, as a player's game may lie.",
      "params": [],
      "returns": "Player?",
      "examples": [
        {
          "title": "To name whoever the player aims at",
          "side": "client",
          "code": "mount(function()\n    local aimed_at = aimed()\n    if not aimed_at then\n        return nil\n    end\n    return Box { aimed_at.name or \"\", style = { position = \"absolute\", top = 560, left = 0, right = 0, textAlign = \"center\" } }\nend)\n"
        }
      ]
    },
    {
      "name": "trace",
      "group": "Traces",
      "side": "server",
      "since": "0.1",
      "summary": "Gives the first thing on the line from one point to another, or nil if the line is clear.",
      "doc": "Gives the first thing on the line from one point to another, or nil if the line is clear.\n\nIt meets the map and its parts, solid models and shapes where they stand at the call's tick, and with `bodies` the\nplayers and NPCs too. What it gives is a table: `position` and `normal`, vectors; `player`, the player or NPC hit;\n`entity`, the part, model or shape hit; `ladder`, whether the surface is a ladder's; and `mantle`, whether it may be\nclimbed over, false for a body. A line starting inside a body meets it where it starts, so put whoever traces in\n`ignore`. A body is met by its capsule, not by its limbs as a shot is.\n\nTraces run only in handlers, timers and ticks, 1024 a call at most, `is_trace_clear` and `ground` among them.",
      "params": [
        {
          "name": "from",
          "type": "vector"
        },
        {
          "name": "to",
          "type": "vector"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "mask",
              "doc": "What of the map and its obstacles it meets; anything solid without.",
              "type": "Mask",
              "optional": true,
              "fields": [
                {
                  "name": "players",
                  "doc": "What stops players.",
                  "type": "boolean",
                  "default": false
                },
                {
                  "name": "npcs",
                  "doc": "What stops NPCs.",
                  "type": "boolean",
                  "default": false
                },
                {
                  "name": "shots",
                  "doc": "What stops bullets: `{ shots = true }` meets what a shot does.",
                  "type": "boolean",
                  "default": false
                },
                {
                  "name": "projectiles",
                  "doc": "What stops thrown grenades and rockets.",
                  "type": "boolean",
                  "default": false
                }
              ]
            },
            {
              "name": "bodies",
              "doc": "Meets the players alive and the NPCs too, where they stood at the start of the call.",
              "type": "boolean",
              "default": false
            },
            {
              "name": "ignore",
              "doc": "Players and NPCs whose bodies it passes through, 1088 at most.",
              "type": "{Player | number}",
              "optional": true
            }
          ]
        }
      ],
      "returns": "Hit?",
      "examples": [
        {
          "title": "To find what a player looks at",
          "side": "server",
          "code": "local eye = p.position + vector.create(0, 1.6, 0)\nlocal hit = trace(eye, eye + angles.forward(p) * 100, { bodies = true, ignore = { p } })\nif hit and hit.player then\n    say(`{p.name} looks at {hit.player.name}`)\nend\n"
        },
        {
          "title": "To fire a bullet of your own, stopped by what stops shots",
          "side": "server",
          "code": "local from = p.position + vector.create(0, 1.6, 0)\nlocal hit = trace(from, from + angles.forward(p) * 50, { mask = { shots = true }, bodies = true, ignore = { p } })\nif hit and hit.player then\n    hit.player:hurt(30, p, \"laser\", { kind = \"bullet\" })\nend\n"
        }
      ]
    },
    {
      "name": "is_trace_clear",
      "group": "Traces",
      "side": "server",
      "since": "0.1",
      "summary": "Whether the line between two points is clear: true if `trace` would meet nothing on it, the bodies aside.",
      "doc": "Whether the line between two points is clear: true if `trace` would meet nothing on it, the bodies aside.",
      "params": [
        {
          "name": "a",
          "type": "vector"
        },
        {
          "name": "b",
          "type": "vector"
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "mask",
              "doc": "What of the map and its obstacles it meets; anything solid without.",
              "type": "Mask",
              "optional": true,
              "fields": [
                {
                  "name": "players",
                  "doc": "What stops players.",
                  "type": "boolean",
                  "default": false
                },
                {
                  "name": "npcs",
                  "doc": "What stops NPCs.",
                  "type": "boolean",
                  "default": false
                },
                {
                  "name": "shots",
                  "doc": "What stops bullets: `{ shots = true }` meets what a shot does.",
                  "type": "boolean",
                  "default": false
                },
                {
                  "name": "projectiles",
                  "doc": "What stops thrown grenades and rockets.",
                  "type": "boolean",
                  "default": false
                }
              ]
            }
          ]
        }
      ],
      "returns": "boolean",
      "examples": [
        {
          "title": "To send each zombie that can see a player after them",
          "side": "server",
          "code": "local eyes = vector.create(0, 1.6, 0)\nfor _, zombie in players do\n    if zombie.npc and is_trace_clear(zombie.position + eyes, p.position + eyes) then\n        zombie:chase(p)\n    end\nend\n"
        }
      ]
    },
    {
      "name": "ground",
      "group": "Traces",
      "side": "server",
      "since": "0.1",
      "summary": "Gives the floor below a point, the map's or a part's, a model's or a shape's, as a vector; nil if there is none.",
      "doc": "Gives the floor below a point, the map's or a part's, a model's or a shape's, as a vector; nil if there is none.\n\nA point resting on a floor, or a hair below it, finds that floor.",
      "params": [
        {
          "name": "point",
          "type": "vector"
        }
      ],
      "returns": "vector?",
      "examples": [
        {
          "title": "To drop a grenade onto the floor below a player",
          "side": "server",
          "code": "local floor = ground(p.position + vector.create(0, 2, 0))\nif floor then\n    model(\"grenade\", { at = floor })\nend\n"
        }
      ]
    },
    {
      "name": "forward",
      "group": "Types",
      "side": "both",
      "table": "angles",
      "since": "0.1",
      "summary": "Gives the way angles face, a vector of length 1: yaw 0 faces +Z, positive yaw turns left, and pitch looks up.",
      "doc": "Gives the way angles face, a vector of length 1: yaw 0 faces +Z, positive yaw turns left, and pitch looks up.\n\nIt takes angles, `{ yaw, pitch, roll }` in radians, each 0 where it is left out, or anything with them: a\nmarker, a player, a model or a part.",
      "params": [
        {
          "name": "a",
          "type": "Angled"
        }
      ],
      "returns": "vector",
      "examples": [
        {
          "title": "To put a model 2 m in front of a player",
          "side": "server",
          "code": "model(\"rocket\", { at = p.position + angles.forward(p) * 2 })\n"
        }
      ]
    },
    {
      "name": "right",
      "group": "Types",
      "side": "both",
      "table": "angles",
      "since": "0.1",
      "summary": "Gives the way to the right of angles, a vector of length 1, as roll tips it.",
      "doc": "Gives the way to the right of angles, a vector of length 1, as roll tips it.",
      "params": [
        {
          "name": "a",
          "type": "Angled"
        }
      ],
      "returns": "vector",
      "examples": [
        {
          "title": "To put a model beside a player, on their right",
          "side": "server",
          "code": "model(\"rocket\", { at = p.position + angles.right(p) * 1.5 })\n"
        }
      ]
    },
    {
      "name": "up",
      "group": "Types",
      "side": "both",
      "table": "angles",
      "since": "0.1",
      "summary": "Gives the way up from angles, a vector of length 1, as pitch and roll tip it.",
      "doc": "Gives the way up from angles, a vector of length 1, as pitch and roll tip it.",
      "params": [
        {
          "name": "a",
          "type": "Angled"
        }
      ],
      "returns": "vector",
      "examples": [
        {
          "title": "To put a model on top of a leaning one",
          "side": "server",
          "code": "local at, leaning = vector.create(0, 0, 5), { pitch = 0.3 }\nmodel(\"rocket\", { at = at, angles = leaning })\nmodel(\"rocket\", { at = at + angles.up(leaning) * 2, angles = leaning })\n"
        }
      ]
    },
    {
      "name": "of",
      "group": "Types",
      "side": "both",
      "table": "angles",
      "since": "0.1",
      "summary": "Gives the yaw and pitch that face a direction; one straight up or down faces yaw 0.",
      "doc": "Gives the yaw and pitch that face a direction; one straight up or down faces yaw 0.",
      "params": [
        {
          "name": "dir",
          "type": "vector"
        }
      ],
      "returns": "Angles",
      "examples": [
        {
          "title": "To turn a model to face a player",
          "side": "server",
          "code": "local at = vector.create(0, 0, 5)\nmodel(\"rocket\", { at = at, angles = angles.of(p.position - at) })\n"
        }
      ]
    },
    {
      "name": "rotate",
      "group": "Types",
      "side": "both",
      "table": "angles",
      "since": "0.1",
      "summary": "Gives an offset turned by angles: where it is from what has them, as `vector.create(0, 0, 1)` is 1 m in front.",
      "doc": "Gives an offset turned by angles: where it is from what has them, as `vector.create(0, 0, 1)` is 1 m in front.",
      "params": [
        {
          "name": "v",
          "type": "vector"
        },
        {
          "name": "a",
          "type": "Angled"
        }
      ],
      "returns": "vector",
      "examples": [
        {
          "title": "To put a model at the tip of a player's gun",
          "side": "server",
          "code": "model(\"rocket\", { at = p.position + vector.create(0, 1.5, 0) + angles.rotate(vector.create(-0.2, 0, 0.8), p) })\n"
        }
      ]
    },
    {
      "name": "delta",
      "group": "Types",
      "side": "both",
      "table": "angles",
      "since": "0.1",
      "summary": "Gives the shortest turn from one angles to another, each from -π to π: of the angles either has, the other's 0 where it has none.",
      "doc": "Gives the shortest turn from one angles to another, each from -π to π: of the angles either has, the other's 0\nwhere it has none.",
      "params": [
        {
          "name": "a",
          "type": "Angled"
        },
        {
          "name": "b",
          "type": "Angled"
        }
      ],
      "returns": "Angles",
      "examples": [
        {
          "title": "To tell whether a player aims at a point",
          "side": "server",
          "code": "local target = vector.create(5, 0, 5)\nlocal turn = angles.delta(p, angles.of(target - p.position))\nif math.abs(turn.yaw) < 0.1 then\n\tsay(`{p.name} aims at it`)\nend\n"
        }
      ]
    },
    {
      "name": "lerp",
      "group": "Types",
      "side": "both",
      "table": "angles",
      "since": "0.1",
      "summary": "Gives the angles `t` of the way from one to another, the short way round, 0.5 halfway: of the angles either has, the other's 0 where it has none.",
      "doc": "Gives the angles `t` of the way from one to another, the short way round, 0.5 halfway: of the angles either has,\nthe other's 0 where it has none.",
      "params": [
        {
          "name": "a",
          "type": "Angled"
        },
        {
          "name": "b",
          "type": "Angled"
        },
        {
          "name": "t",
          "type": "number"
        }
      ],
      "returns": "Angles",
      "examples": [
        {
          "title": "To aim a camera halfway from yaw 0 to where a player looks",
          "side": "server",
          "code": "spawn_camera({ at = vector.create(0, 2, 0), angles = angles.lerp({ yaw = 0 }, p, 0.5) })\n"
        }
      ]
    },
    {
      "name": "distance",
      "group": "Types",
      "side": "both",
      "table": "vector",
      "since": "0.1",
      "summary": "Gives the distance between two points, in metres.",
      "doc": "Gives the distance between two points, in metres.",
      "params": [
        {
          "name": "a",
          "type": "vector"
        },
        {
          "name": "b",
          "type": "vector"
        }
      ],
      "returns": "number",
      "examples": [
        {
          "title": "To hurt the players within 10 m of a blast",
          "side": "server",
          "code": "local at = vector.create(0, 0, 0)\nfor _, p in players do\n\tif vector.distance(p.position, at) < 10 then\n\t\tp:hurt(20)\n\tend\nend\n"
        }
      ]
    },
    {
      "name": "cubic_bezier",
      "group": "Types",
      "side": "both",
      "table": "timing",
      "since": "0.1",
      "summary": "Makes a timing of a cubic Bézier curve from (0, 0) to (1, 1), as CSS's `cubic-bezier()`: y1 and y2 past 0 or 1 overshoot.",
      "doc": "Makes a timing of a cubic Bézier curve from (0, 0) to (1, 1), as CSS's `cubic-bezier()`: y1 and y2 past 0 or 1\novershoot.\n\nA timing is how a change eases: one of the words `\"linear\"`, `\"ease\"`, `\"ease-in\"`, `\"ease-out\"` and\n`\"ease-in-out\"`, or what `timing.cubic_bezier` and `timing.steps` make. A move order takes one, and a client\nscript's transition, `{ seconds, timing }`, linear without it. CSS's strings, as `\"cubic-bezier(…)\"`, are none.",
      "params": [
        {
          "name": "x1",
          "type": "number",
          "range": [
            0.0,
            1.0
          ]
        },
        {
          "name": "y1",
          "type": "number",
          "range": [
            -1000.0,
            1000.0
          ]
        },
        {
          "name": "x2",
          "type": "number",
          "range": [
            0.0,
            1.0
          ]
        },
        {
          "name": "y2",
          "type": "number",
          "range": [
            -1000.0,
            1000.0
          ]
        }
      ],
      "returns": "TimingFunction",
      "examples": [
        {
          "title": "To raise a platform, overshooting a little before it settles",
          "side": "server",
          "code": "local platform = model(\"rocket\")\nplatform:move_by(vector.create(0, 3, 0), 2, { timing = timing.cubic_bezier(0.3, 1.4, 0.6, 1) })\n"
        }
      ]
    },
    {
      "name": "steps",
      "group": "Types",
      "side": "both",
      "table": "timing",
      "since": "0.1",
      "summary": "Makes a timing of equal jumps, as CSS's `steps()`, `jump` saying where they fall: `jump-end` without it.",
      "doc": "Makes a timing of equal jumps, as CSS's `steps()`, `jump` saying where they fall: `jump-end` without it.\n\n`jump-start` jumps at the start of each step and `jump-end` at its end; `jump-none` at neither end of the whole,\nso it takes 2 steps at least, and `jump-both` at both.",
      "params": [
        {
          "name": "count",
          "type": "number",
          "range": [
            1.0,
            65535.0
          ]
        },
        {
          "name": "jump",
          "type": "Jump",
          "optional": true
        }
      ],
      "returns": "TimingFunction",
      "examples": [
        {
          "title": "To zoom a scope in four clicks",
          "side": "client",
          "code": "view:set({ fov = 30 }, { seconds = 0.4, timing = timing.steps(4) })\n"
        }
      ]
    },
    {
      "name": "one_of",
      "group": "Types",
      "side": "both",
      "table": "t",
      "since": "0.1",
      "summary": "Makes a type of one of a list of words, or of numbers, at least one and none twice.",
      "doc": "Makes a type of one of a list of words, or of numbers, at least one and none twice.\n\nA value not in the list is refused. A command's argument of words takes one of them, which a player's game\ncompletes as it is typed; a `one_of` of words keys a `t.map`.",
      "params": [
        {
          "name": "values",
          "type": "{string} | {number}"
        }
      ],
      "returns": "Type",
      "examples": [
        {
          "title": "To let admins choose how hard the zombies are",
          "side": "server",
          "code": "server_state(\"difficulty\", t.one_of { \"easy\", \"normal\", \"hard\" }, \"normal\", { read_by = everyone, set_by = admins })\n"
        }
      ]
    },
    {
      "name": "choices",
      "group": "Types",
      "side": "both",
      "table": "t",
      "since": "0.1",
      "summary": "Makes a command's argument's type of a word of the list `choices` fills, by the list's name.",
      "doc": "Makes a command's argument's type of a word of the list `choices` fills, by the list's name.\n\nA player's game completes the words as they are typed; a word not in the list is refused.",
      "params": [
        {
          "name": "list",
          "type": "string"
        }
      ],
      "returns": "Type",
      "examples": [
        {
          "title": "To let players vote for the next map",
          "side": "server",
          "code": "command(\"nextmap\", { help = \"Vote for the next map\", args = { { \"map\", t.choices(\"maps\") } } }, function(e)\n\tsay(`{e.player.name} votes for {e.map}`)\nend)\non(\"start\", function()\n\tchoices(\"maps\", { \"yard\", \"testbed\" })\nend)\n"
        }
      ]
    },
    {
      "name": "optional",
      "group": "Types",
      "side": "both",
      "table": "t",
      "since": "0.1",
      "summary": "Makes a type of a value of another, or nil.",
      "doc": "Makes a type of a value of another, or nil.\n\nAn optional type stays as it is. A command's optional argument may be left out, after those it needs, and reads\nnil.",
      "params": [
        {
          "name": "inner",
          "type": "Type"
        }
      ],
      "returns": "Type",
      "examples": [
        {
          "title": "To keep whom each player marked, if anyone",
          "side": "server",
          "code": "player_state(\"marked\", t.optional(t.player), nil, { read_by = owner })\n"
        },
        {
          "title": "To give a kick an optional reason",
          "side": "server",
          "code": "command(\"boot\", { args = { { \"target\", t.player }, { \"reason\", t.optional(t.text) } }, run_by = admins }, function(e)\n\te.target:kick(e.reason or \"booted\")\nend)\n"
        }
      ]
    },
    {
      "name": "secret",
      "group": "Types",
      "side": "both",
      "table": "t",
      "since": "0.1",
      "summary": "Makes the type of a setting's secret, `t.secret(t.string)`: text the mod passes to a call but never reads.",
      "doc": "Makes the type of a setting's secret, `t.secret(t.string)`: text the mod passes to a call but never reads.\n\nA secret is a `server_state` of `set_by = config` without `read_by`, or it fails at load; `t.optional` of one may\nbe left unset, blank text making it nil. The mod holds a handle that shows as `<secret name>` wherever it is\nprinted, joins into another with `..`, and gives its text only where a call connects: `sql.pool` takes one as its\nURL, and `http.request` as its URL or a header's value. Whatever the server prints of the mod and of what a call\nanswers has its text replaced so.",
      "params": [
        {
          "name": "inner",
          "type": "Type"
        }
      ],
      "returns": "Type",
      "examples": [
        {
          "title": "To keep the stats database's address out of the mod",
          "side": "server",
          "code": "server_state(\"stats_db\", t.secret(t.string), \"sqlite::memory:\", { set_by = config })\n"
        }
      ]
    },
    {
      "name": "list",
      "group": "Types",
      "side": "both",
      "table": "t",
      "since": "0.1",
      "summary": "Makes a type of a list of values of another: a table of keys 1 to n and no other.",
      "doc": "Makes a type of a list of values of another: a table of keys 1 to n and no other.",
      "params": [
        {
          "name": "element",
          "type": "Type"
        }
      ],
      "returns": "Type",
      "examples": [
        {
          "title": "To keep the perks each player bought",
          "side": "server",
          "code": "player_state(\"perks\", t.list(t.string { max = 16 }), {}, { read_by = owner })\n"
        }
      ]
    },
    {
      "name": "record",
      "group": "Types",
      "side": "both",
      "table": "t",
      "since": "0.1",
      "summary": "Makes a type of a table of named fields, each of its own type: a field's name is up to 32 lowercase letters, digits and `_`.",
      "doc": "Makes a type of a table of named fields, each of its own type: a field's name is up to 32 lowercase letters,\ndigits and `_`.\n\nEvery field is given, but an optional one, and no other; an event's or a request's payload is one.",
      "params": [
        {
          "name": "fields",
          "type": "{[string]: Type}"
        }
      ],
      "returns": "Type",
      "examples": [
        {
          "title": "To tell everyone what a player bought",
          "side": "server",
          "code": "event(\"bought\", t.record { player = t.player, weapon = t.weapon, price = t.int { min = 0 } }, { read_by = everyone })\n"
        }
      ]
    },
    {
      "name": "map",
      "group": "Types",
      "side": "both",
      "table": "t",
      "since": "0.1",
      "summary": "Makes a type of a table of keys of one type to values of another.",
      "doc": "Makes a type of a table of keys of one type to values of another.\n\nA key is an int, a string, a bool, a player, an entity, a file or a `one_of` of words, up to 32 bytes as sent.",
      "params": [
        {
          "name": "key",
          "type": "Type"
        },
        {
          "name": "value",
          "type": "Type"
        }
      ],
      "returns": "Type",
      "examples": [
        {
          "title": "To count each player's kills by weapon",
          "side": "server",
          "code": "player_state(\"kills_by_weapon\", t.map(t.weapon, t.int { min = 0 }), {}, { read_by = owner })\n"
        }
      ]
    },
    {
      "name": "give",
      "group": "Weapons",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Gives a player a weapon by its file's name, its magazine full and its reserve the weapon's `reserve` stat.",
      "doc": "Gives a player a weapon by its file's name, its magazine full and its reserve the weapon's `reserve` stat.\n\nIt goes in `slot`, 1, 2, 3 or 5, or else where the player already carries it, or else in the first empty slot, or\nelse in hand, taking what was there. A player carries one weapon of a file at most, tuned or not, so one of the same\nfile in another slot is taken. It comes up when it is given in hand, to empty hands, or in place of the same weapon\nin hand. A grenade is carried apart from the slots, in place of the one its key throws. A name of no weapon's file\nfails at the call.",
      "params": [
        {
          "name": "weapon",
          "type": "weapon"
        },
        {
          "name": "slot",
          "type": "number",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To give a player a pistol in their second slot",
          "side": "server",
          "code": "p:give(\"weapons/usp\", 2)\n"
        }
      ]
    },
    {
      "name": "give",
      "group": "Weapons",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Gives a player back a weapon as it was carried: its rounds, its reserve and its tune.",
      "doc": "Gives a player back a weapon as it was carried: its rounds, its reserve and its tune.\n\n`carried` is a value of `p.slots` or `p:take`, so a weapon taken from one player and given to another keeps its\nrounds. It goes where a weapon given by name goes. Nothing stops one value being given twice. A reserve above 0 on a\nmelee weapon or a grenade, which reload nothing, fails at the call.",
      "params": [
        {
          "name": "carried",
          "fields": [
            {
              "name": "weapon",
              "doc": "The weapon's name, its base's if it is tuned.",
              "type": "string",
              "required": true
            },
            {
              "name": "rounds",
              "doc": "The rounds in its magazine; more than it holds are left out.",
              "type": "number",
              "required": true
            },
            {
              "name": "reserve",
              "doc": "The rounds its reloads draw from.",
              "type": "number",
              "required": true,
              "range": [
                0.0,
                9999.0
              ]
            },
            {
              "name": "tune",
              "doc": "Its tune, if it has one.",
              "type": "Tune",
              "optional": true,
              "fields": [
                {
                  "name": "stats",
                  "doc": "Stats laid over the weapon's file, by name, each as the file writes it; `false` takes an optional one away.",
                  "type": "{[string]: any}",
                  "optional": true
                },
                {
                  "name": "attach",
                  "doc": "The model drawn at each marker of the weapon's model, by the marker's name.",
                  "type": "{[string]: string}",
                  "optional": true
                },
                {
                  "name": "sounds",
                  "doc": "The name the weapon's sounds take in place of its model's: `<sounds>_fire` and the rest.",
                  "type": "string",
                  "optional": true
                }
              ]
            }
          ]
        },
        {
          "name": "slot",
          "type": "number",
          "optional": true
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To hand a player's rifle to another, rounds and all",
          "side": "server",
          "code": "local rifle = p:take(\"weapons/ak47\")\nif rifle then\n    q:give(rifle, 1)\nend\n"
        }
      ]
    },
    {
      "name": "take",
      "group": "Weapons",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Takes a weapon away from a player and returns its value, which `p:give` gives back as it was; nil if they do not carry it.",
      "doc": "Takes a weapon away from a player and returns its value, which `p:give` gives back as it was; nil if they do not\ncarry it.\n\nThe value is the weapon as carried when the handler was called: orders are carried out after it, so `p:give(x)`\nthen `p:take(x)` in one handler returns nil. The weapon in hand taken, the first left comes up. A name of no\nweapon's file fails at the call.",
      "params": [
        {
          "name": "weapon",
          "type": "weapon"
        }
      ],
      "returns": "Carried?",
      "examples": [
        {
          "title": "To trade a player's rifle for a pistol with as many rounds in reserve",
          "side": "server",
          "code": "local rifle = p:take(\"weapons/ak47\")\nif rifle then\n    p:give(\"weapons/usp\")\n    p:set_ammo(\"weapons/usp\", nil, rifle.reserve)\nend\n"
        }
      ]
    },
    {
      "name": "take",
      "group": "Weapons",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Takes every weapon away from a player, grenades too, and returns the values of those in slots, by slot number.",
      "doc": "Takes every weapon away from a player, grenades too, and returns the values of those in slots, by slot number.\n\nEach is as carried when the handler was called, as `p:take(weapon)` returns it; a grenade taken returns none.",
      "params": [],
      "returns": "{[number]: Carried}",
      "examples": [
        {
          "title": "To take a player's weapons through a cutscene and give them back after",
          "side": "server",
          "code": "local kept = p:take()\nwait(5)\nfor slot, carried in kept do\n    p:give(carried, slot)\nend\n"
        }
      ]
    },
    {
      "name": "switch",
      "group": "Weapons",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Switches a player to a weapon they carry, as its slot's key does; nothing happens if they carry none of it.",
      "doc": "Switches a player to a weapon they carry, as its slot's key does; nothing happens if they carry none of it.\n\nA name of no weapon's file fails at the call.",
      "params": [
        {
          "name": "weapon",
          "type": "weapon"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To bring up a player's pistol as they climb a ladder",
          "side": "server",
          "code": "p:switch(\"weapons/usp\")\n"
        }
      ]
    },
    {
      "name": "set_ammo",
      "group": "Weapons",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Sets the rounds in a carried weapon's magazine and in the reserve its reloads draw from, each left as it is if nil.",
      "doc": "Sets the rounds in a carried weapon's magazine and in the reserve its reloads draw from, each left as it is if nil.\n\nMore rounds than the magazine holds are left out. A `reserve` above 0 on a melee weapon or a grenade, which reload\nnothing, fails at the call, as does a name of no weapon's file. Nothing happens for a weapon the player does not\ncarry. For an endless reserve, set it again every tick.",
      "params": [
        {
          "name": "weapon",
          "type": "weapon"
        },
        {
          "name": "rounds",
          "type": "number",
          "optional": true
        },
        {
          "name": "reserve",
          "type": "number",
          "optional": true,
          "range": [
            0.0,
            9999.0
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To refill a player's rifle from an ammo box",
          "side": "server",
          "code": "p:set_ammo(\"weapons/ak47\", 30, 90)\n"
        },
        {
          "title": "To empty a player's pistol magazine",
          "side": "server",
          "code": "p:set_ammo(\"weapons/usp\", 0)\n"
        }
      ]
    },
    {
      "name": "disable_weapon",
      "group": "Weapons",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Puts a player's weapon down, as for a sprint, until `p:enable_weapon`: no firing, aiming nor reloading.",
      "doc": "Puts a player's weapon down, as for a sprint, until `p:enable_weapon`: no firing, aiming nor reloading.\n\nIt stays down through a respawn.",
      "params": [],
      "returns": "()",
      "examples": [
        {
          "title": "To keep players from firing through a countdown",
          "side": "server",
          "code": "for _, p in players do\n    p:disable_weapon()\nend\nwait(3)\nfor _, p in players do\n    p:enable_weapon()\nend\n"
        }
      ]
    },
    {
      "name": "enable_weapon",
      "group": "Weapons",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Brings a player's weapon back up after `p:disable_weapon`.",
      "doc": "Brings a player's weapon back up after `p:disable_weapon`.",
      "params": [],
      "returns": "()",
      "examples": [
        {
          "title": "To let a player fire again once a stun wears off",
          "side": "server",
          "code": "p:disable_weapon()\nwait(2)\np:enable_weapon()\n"
        }
      ]
    },
    {
      "name": "hide_weapon",
      "group": "Weapons",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Draws the weapon in a player's hand nowhere until `p:show_weapon`: not before their eyes, not in their body's hands for everyone, and with no muzzle flash.",
      "doc": "Draws the weapon in a player's hand nowhere until `p:show_weapon`: not before their eyes, not in their body's hands\nfor everyone, and with no muzzle flash.\n\nThey keep it, its slot and its rounds, and it still fires and is heard, as a mounted gun's gunner fires while the\ngun on the map shows. It stays hidden through a respawn.",
      "params": [],
      "returns": "()",
      "examples": [
        {
          "title": "To seat a player at a mounted gun",
          "side": "server",
          "code": "p:hide_weapon()\n"
        }
      ]
    },
    {
      "name": "show_weapon",
      "group": "Weapons",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Draws a player's weapon again after `p:hide_weapon`.",
      "doc": "Draws a player's weapon again after `p:hide_weapon`.",
      "params": [],
      "returns": "()",
      "examples": [
        {
          "title": "To give a player their own weapon back as they leave a mounted gun",
          "side": "server",
          "code": "p:hide_weapon()\nwait(10)\np:show_weapon()\n"
        }
      ]
    },
    {
      "name": "loadout",
      "group": "Weapons",
      "side": "server",
      "since": "0.1",
      "summary": "Names the weapons a player carries on joining and after every respawn, in slot order: up to 4, but grenades, carried apart. Without it, none.",
      "doc": "Names the weapons a player carries on joining and after every respawn, in slot order: up to 4, but grenades,\ncarried apart. Without it, none.\n\nOne module declares it, at its top as it loads: a second module's fails at load, naming both, and a module declaring\nit again replaces its own. A weapon named twice, or one no file of the mod is, fails at load. `p:respawn()` gives\nthe loadout again, so give after it; a weapon disabled or hidden stays so.",
      "params": [
        {
          "name": "weapons",
          "type": "{string}"
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To start every player with a rifle, a pistol and a grenade",
          "side": "server",
          "code": "loadout({ \"weapons/ak47\", \"weapons/usp\", \"weapons/frag_grenade\" })\n"
        }
      ]
    },
    {
      "name": "stats_of",
      "group": "Weapons",
      "side": "both",
      "since": "0.1",
      "summary": "Gives a weapon file's stats as it writes them, with the defaults it is read with filled in, its `model` too.",
      "doc": "Gives a weapon file's stats as it writes them, with the defaults it is read with filled in, its `model` too.\n\nThe table is frozen, nested tables kept. The file is read again only once it changes, and nothing is loaded by\nplayers for it, so a mod may look up any weapon it has: a part adds to a stat,\n`stats.damage = (stats.damage or stats_of(weapon).damage) - 3`, and a HUD shows a magazine's size. A name of no\nweapon's file fails.",
      "params": [
        {
          "name": "weapon",
          "type": "weapon"
        }
      ],
      "returns": "{[string]: any}",
      "examples": []
    },
    {
      "name": "tune_weapon",
      "group": "Weapons",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Tunes a weapon a player carries, as a mod's parts or a burst switched on do: its stats, the parts on it and its sounds.",
      "doc": "Tunes a weapon a player carries, as a mod's parts or a burst switched on do: its stats, the parts on it and its\nsounds.\n\nEach call replaces the weapon's whole set of changes; nil, or no changes, takes them all off. `changes.stats` takes\nany of a weapon file's stats but `model` and `name`, laid over its file as written and read as the file is, so it fails as the\nfile would: `burst = false` takes a burst away, but `automatic` is true or false, and a `pattern` is only another of\nthe engine's. A tune may not set `offhand` nor `projectile`, nor move `magazine` to or from 0, and a grenade is not\ntuned. `changes.attach` draws up to 8 models at markers of the weapon's model, on the weapon in hand in first person\nalone, a shot's flash leaving from a part's own `muzzle` marker if it has one; the stock guns have `muzzle`, `rail`\non top and `under` below the handguard. `changes.sounds` names the weapon's sounds in place of its model's,\n`<sounds>_fire` and its `_reload`, `_melee` and `_hold`, each the name lacks the model's own.\n\nThe tune belongs to the weapon carried: its rounds and reserve are kept, its name stays the base's in `p.weapon`,\n`p.slots` and the events, and its value's `tune` is the changes, so `p:give` of the value tunes it again; a give by\nname or a respawn gives it untuned. `options.clip` plays on the weapon if it is in hand, busy for the clip's length\nas in a reload, which a sprint or a switch drops; the changes land at once, but its owner sees the parts only once\nthe clip ends. It fails for a weapon the player does not carry, this handler's `give`s and `take`s before it\ncounted, and for a model, a marker, a sound or a clip of no file.",
      "params": [
        {
          "name": "weapon",
          "type": "weapon"
        },
        {
          "name": "changes",
          "optional": true,
          "fields": [
            {
              "name": "stats",
              "doc": "Stats laid over the weapon's file, by name, each as the file writes it; `false` takes an optional one away.",
              "type": "{[string]: any}",
              "optional": true
            },
            {
              "name": "attach",
              "doc": "The model drawn at each marker of the weapon's model, by the marker's name.",
              "type": "{[string]: string}",
              "optional": true
            },
            {
              "name": "sounds",
              "doc": "The name the weapon's sounds take in place of its model's: `<sounds>_fire` and the rest.",
              "type": "string",
              "optional": true
            }
          ]
        },
        {
          "name": "options",
          "optional": true,
          "fields": [
            {
              "name": "clip",
              "doc": "A clip of the weapon's model played as the changes are fitted, `<model>_<clip>.anim`.",
              "type": "string",
              "optional": true
            }
          ]
        }
      ],
      "returns": "()",
      "examples": [
        {
          "title": "To switch a pistol to three-round bursts",
          "side": "server",
          "code": "p:give(\"weapons/usp\", 2)\np:tune_weapon(\"weapons/usp\", { stats = { burst = { count = 3, interval = 0.05 }, interval = 0.35 } })\n"
        },
        {
          "title": "To take every change off a pistol",
          "side": "server",
          "code": "p:tune_weapon(\"weapons/usp\", nil)\n"
        }
      ]
    },
    {
      "name": "animate_weapon",
      "group": "Weapons",
      "side": "server",
      "on": "player",
      "since": "0.1",
      "summary": "Plays a clip on the weapon in a player's hand, `<model>_<name>.anim` of the weapon's model: before their eyes, and in their body's hands for everyone.",
      "doc": "Plays a clip on the weapon in a player's hand, `<model>_<name>.anim` of the weapon's model: before their eyes, and\nin their body's hands for everyone.\n\nIt plays until it ends or the weapon fires, reloads, bashes, is switched or goes down for a sprint or a grenade;\nthe weapon stays free to do so meanwhile. It fails for a name of no file, and with no weapon in hand, this\nhandler's `give`s and `take`s before it counted: `p:animate_weapon(\"silencer_on\")` plays `usp_silencer_on.anim` on\nthe stock pistol in hand.",
      "params": [
        {
          "name": "name",
          "type": "string"
        }
      ],
      "returns": "()",
      "examples": []
    }
  ],
  "fields": [
    {
      "name": "id",
      "of": "player",
      "group": "Players",
      "side": "both",
      "since": "0.1",
      "type": "number",
      "doc": "Their id, as `players[id]` finds them, theirs while they are here."
    },
    {
      "name": "name",
      "of": "player",
      "group": "Players",
      "side": "both",
      "since": "0.1",
      "type": "string?",
      "doc": "The name they joined with, up to 16 bytes, not unique; an NPC's its `set_name`."
    },
    {
      "name": "team",
      "of": "player",
      "group": "Players",
      "side": "both",
      "since": "0.1",
      "type": "number",
      "doc": "Their team, a number; `set_team` changes it."
    },
    {
      "name": "bot",
      "of": "player",
      "group": "Players",
      "side": "both",
      "since": "0.1",
      "type": "boolean",
      "doc": "Whether the server plays them, not a person: a bot or an NPC."
    },
    {
      "name": "npc",
      "of": "player",
      "group": "NPCs",
      "side": "both",
      "since": "0.1",
      "type": "boolean",
      "doc": "Whether they are an NPC the mod spawned."
    },
    {
      "name": "exists",
      "of": "player",
      "group": "Players",
      "side": "both",
      "since": "0.1",
      "type": "boolean",
      "doc": "Whether they are still here; after a `wait`, check it."
    },
    {
      "name": "identity",
      "of": "player",
      "group": "Players",
      "side": "server",
      "since": "0.1",
      "type": "string?",
      "doc": "The same on every join from one install of the game, as their name is not: key what you keep across joins by it. 32 hex digits, `bot` for the server's bots, nil for an NPC."
    },
    {
      "name": "position",
      "of": "player",
      "group": "Movement",
      "side": "both",
      "since": "0.1",
      "type": "vector?",
      "doc": "Where they stand, at their feet."
    },
    {
      "name": "yaw",
      "of": "player",
      "group": "Movement",
      "side": "server",
      "since": "0.1",
      "type": "number?",
      "doc": "Which way they face, in radians: 0 faces +Z, more turns left."
    },
    {
      "name": "pitch",
      "of": "player",
      "group": "Movement",
      "side": "server",
      "since": "0.1",
      "type": "number?",
      "doc": "How far up they look, in radians."
    },
    {
      "name": "camera",
      "of": "player",
      "group": "Entities and models",
      "side": "server",
      "since": "0.1",
      "type": "CameraView?",
      "doc": "Where they see from and which way: their eyes, or the camera `set_camera` gave them."
    },
    {
      "name": "health",
      "of": "player",
      "group": "Health",
      "side": "both",
      "since": "0.1",
      "type": "number?",
      "doc": "Their health; on a client, the shown player's alone."
    },
    {
      "name": "max_health",
      "of": "player",
      "group": "Health",
      "side": "both",
      "since": "0.1",
      "type": "number?",
      "doc": "The health they have at most; on a client, the shown player's alone."
    },
    {
      "name": "weapon",
      "of": "player",
      "group": "Weapons",
      "side": "both",
      "since": "0.1",
      "type": "string?",
      "doc": "The weapon in their hand; on a client, the shown player's alone."
    },
    {
      "name": "slots",
      "of": "player",
      "group": "Weapons",
      "side": "both",
      "since": "0.1",
      "type": "{[number]: Carried}?",
      "doc": "The weapons they carry, by slot, as carried still while `killed` runs; on a client, the shown player's alone."
    },
    {
      "name": "ground",
      "of": "player",
      "group": "Movement",
      "side": "server",
      "since": "0.1",
      "type": "(Entity | Player)?",
      "doc": "What they stand on; nil in the air or on the map."
    },
    {
      "name": "held",
      "of": "player",
      "group": "Commands",
      "side": "server",
      "since": "0.1",
      "type": "{[string]: boolean}?",
      "doc": "The actions they held as of the last tick, as `p.held.fire` or `p.held.tactical`: the buttons, the movement keys and the purpose actions; a dead player's too. Crouch, prone, sprint and aim toggled by the player read held while on."
    },
    {
      "name": "pressed",
      "of": "player",
      "group": "Commands",
      "side": "server",
      "since": "0.1",
      "type": "{[string]: boolean}?",
      "doc": "The actions they held at any point since the tick before, as `held` names them."
    },
    {
      "name": "move",
      "of": "player",
      "group": "Movement",
      "side": "server",
      "since": "0.1",
      "type": "Move?",
      "doc": "Their movement keys, each -1 to 1, as of their latest command."
    },
    {
      "name": "read_by",
      "of": "player",
      "group": "Players",
      "side": "server",
      "since": "0.1",
      "type": "(Group | ((Player?, Player) -> boolean))?",
      "doc": "Who is shown them; everyone for nil. Written, not read: keep what you gave it in state."
    },
    {
      "name": "use_target",
      "of": "player",
      "group": "Map",
      "side": "both",
      "since": "0.1",
      "type": "(Trigger & {held: number?})?",
      "doc": "The use trigger they would use, with the seconds `held` its key so far; on a client, the shown player's alone."
    },
    {
      "name": "spectating",
      "of": "player",
      "group": "Players",
      "side": "client",
      "since": "0.1",
      "type": "boolean?",
      "doc": "Whether this player watches another, as a spectator or while dead."
    },
    {
      "name": "ammo",
      "of": "player",
      "group": "Weapons",
      "side": "client",
      "since": "0.1",
      "type": "number?",
      "doc": "The rounds in the shown player's weapon."
    },
    {
      "name": "reserve",
      "of": "player",
      "group": "Weapons",
      "side": "client",
      "since": "0.1",
      "type": "number?",
      "doc": "The rounds the shown player carries for their weapon beside those."
    },
    {
      "name": "id",
      "of": "entity",
      "group": "Entities and models",
      "side": "both",
      "since": "0.1",
      "type": "number",
      "doc": "Its id, as `entities[id]` finds it."
    },
    {
      "name": "kind",
      "of": "entity",
      "group": "Entities and models",
      "side": "both",
      "since": "0.1",
      "type": "string?",
      "doc": "What it is: `part` for the map's, else the kind the mod made it of."
    },
    {
      "name": "exists",
      "of": "entity",
      "group": "Entities and models",
      "side": "both",
      "since": "0.1",
      "type": "boolean",
      "doc": "Whether it is still there; after a `wait`, check it."
    },
    {
      "name": "owner",
      "of": "entity",
      "group": "Entities and models",
      "side": "both",
      "since": "0.1",
      "type": "Player?",
      "doc": "The player it is of, as it was made with `owner`."
    },
    {
      "name": "position",
      "of": "entity",
      "group": "Entities and models",
      "side": "both",
      "since": "0.1",
      "type": "vector?",
      "doc": "Where it is."
    },
    {
      "name": "angles",
      "of": "entity",
      "group": "Entities and models",
      "side": "both",
      "since": "0.1",
      "type": "Angles?",
      "doc": "How it is turned."
    },
    {
      "name": "move_seconds_left",
      "of": "entity",
      "group": "Entities and models",
      "side": "server",
      "since": "0.1",
      "type": "number?",
      "doc": "The seconds its move has left; nil once it is still, `math.huge` for a loop."
    },
    {
      "name": "rotation_seconds_left",
      "of": "entity",
      "group": "Entities and models",
      "side": "server",
      "since": "0.1",
      "type": "number?",
      "doc": "The seconds its turn has left; nil once it is still."
    },
    {
      "name": "name",
      "of": "entity",
      "group": "Map",
      "side": "server",
      "since": "0.1",
      "type": "string?",
      "doc": "A part's name in the map; nil for what the mod made."
    },
    {
      "name": "properties",
      "of": "entity",
      "group": "Map",
      "side": "server",
      "since": "0.1",
      "type": "{[string]: Property}?",
      "doc": "A part's properties, as the mapper set them."
    },
    {
      "name": "solid",
      "of": "entity",
      "group": "Entities and models",
      "side": "server",
      "since": "0.1",
      "type": "Solid?",
      "doc": "What it blocks: `true`, `false`, or a table of who by kind, of `players` (true or a group), `npcs`, the mod's body kinds, `shots`, `projectiles` and `one_way`. Read back as written."
    },
    {
      "name": "blocked_by",
      "of": "entity",
      "group": "Entities and models",
      "side": "server",
      "since": "0.1",
      "type": "{Player}",
      "doc": "The players in its way as it last moved."
    },
    {
      "name": "read_by",
      "of": "entity",
      "group": "Entities and models",
      "side": "server",
      "since": "0.1",
      "type": "(Group | ((Player?, Player) -> boolean))?",
      "doc": "Who is shown it; everyone for nil. Written, not read: keep what you gave it in state."
    }
  ],
  "events": [
    {
      "name": "start",
      "group": "State and events",
      "since": "0.1",
      "doc": "The match started: the first moment a module may give orders, before any other event. Heard once a match.",
      "server": []
    },
    {
      "name": "connecting",
      "group": "Players",
      "since": "0.1",
      "doc": "Someone asks to join. They wait until every handler ends, and are refused if one sets `e.refuse`. The server's bots skip it.",
      "server": [
        {
          "name": "identity",
          "type": "string",
          "doc": "Theirs: the same on every join from one install of the game."
        },
        {
          "name": "name",
          "type": "string",
          "doc": "The name they join with."
        },
        {
          "name": "address",
          "type": "string",
          "doc": "Where they connect from."
        },
        {
          "name": "refuse",
          "type": "string?",
          "doc": "Set it to a reason to refuse them, cut to 100 bytes."
        }
      ]
    },
    {
      "name": "joined",
      "group": "Players",
      "since": "0.1",
      "doc": "A player can play: their game loaded the server's files. On a client, a player came into its list, and those here as it joins.",
      "server": [
        {
          "name": "player",
          "type": "Player",
          "doc": "Who joined."
        }
      ],
      "client": [
        {
          "name": "player",
          "type": "Player",
          "doc": "Who joined."
        }
      ]
    },
    {
      "name": "leaving",
      "group": "Players",
      "since": "0.1",
      "doc": "A player is going. They are out of `players`, but their object reads their values until every handler ends.",
      "server": [
        {
          "name": "player",
          "type": "Player",
          "doc": "Who is leaving."
        }
      ]
    },
    {
      "name": "left",
      "group": "Players",
      "since": "0.1",
      "doc": "A player left the client's list of players.",
      "client": [
        {
          "name": "player",
          "type": "Player",
          "doc": "Who left."
        }
      ]
    },
    {
      "name": "ending",
      "group": "State and events",
      "since": "0.1",
      "doc": "The match is to switch to the next, which waits until every handler ends: the time to save what a mod keeps.",
      "server": []
    },
    {
      "name": "stopping",
      "group": "State and events",
      "since": "0.1",
      "doc": "The server is to stop, which waits until every handler ends and every call is answered.",
      "server": []
    },
    {
      "name": "fired",
      "group": "Weapons",
      "since": "0.1",
      "doc": "A player fired a shot or let a grenade go: once a shot, whatever its pellets.",
      "server": [
        {
          "name": "player",
          "type": "Player",
          "doc": "Who fired."
        },
        {
          "name": "weapon",
          "type": "string",
          "doc": "What they fired."
        },
        {
          "name": "origin",
          "type": "{x: number, y: number, z: number}",
          "doc": "Where the shot started."
        },
        {
          "name": "dir",
          "type": "{x: number, y: number, z: number}",
          "doc": "Which way it went, a unit vector: the view, turned by a spray pattern; 0 for a grenade bursting in the hand."
        }
      ]
    },
    {
      "name": "hit",
      "group": "Health",
      "since": "0.1",
      "doc": "Something struck a player or an NPC, once for each pellet that hits. It takes no health itself: the mod hurts them, as with `p:hurt`.",
      "server": [
        {
          "name": "victim",
          "type": "Player",
          "doc": "Who was struck."
        },
        {
          "name": "attacker",
          "type": "Player?",
          "doc": "Who struck them; nil for no one, or one no longer here."
        },
        {
          "name": "amount",
          "type": "number",
          "doc": "The damage it would do."
        },
        {
          "name": "means",
          "type": "string",
          "doc": "How: `bullet`, `melee`, `explosion`, `fall` or `mod`, the mod's own."
        },
        {
          "name": "location",
          "type": "string?",
          "doc": "The limb it struck, as `head`; nil for an explosion or a fall."
        },
        {
          "name": "weapon",
          "type": "string?",
          "doc": "The weapon it was done with; nil for none."
        },
        {
          "name": "point",
          "type": "{x: number, y: number, z: number}",
          "doc": "Where it struck."
        },
        {
          "name": "dir",
          "type": "{x: number, y: number, z: number}",
          "doc": "Which way it was going, a unit vector."
        }
      ]
    },
    {
      "name": "fell",
      "group": "Health",
      "since": "0.1",
      "doc": "A player landed from over 6.5 m, a fall that would hurt, all their health from 12.2 m. It takes no health itself: the mod hurts them.",
      "server": [
        {
          "name": "player",
          "type": "Player",
          "doc": "Who landed."
        },
        {
          "name": "amount",
          "type": "number",
          "doc": "The damage the fall would do."
        },
        {
          "name": "height",
          "type": "number",
          "doc": "How far they fell, in metres."
        }
      ]
    },
    {
      "name": "killed",
      "group": "Health",
      "since": "0.1",
      "doc": "A player or an NPC died, heard on the next mod tick.",
      "server": [
        {
          "name": "victim",
          "type": "Player",
          "doc": "Who died: a player or an NPC."
        },
        {
          "name": "killer",
          "type": "Player?",
          "doc": "Who killed them; nil for no one, or one no longer here."
        },
        {
          "name": "weapon",
          "type": "string?",
          "doc": "The weapon it was done with; nil for none."
        },
        {
          "name": "means",
          "type": "string",
          "doc": "How: `bullet`, `melee`, `explosion`, `fall` or `mod`, the mod's own."
        },
        {
          "name": "location",
          "type": "string?",
          "doc": "The limb it struck, as `head`; nil for an explosion or a fall."
        }
      ],
      "client": [
        {
          "name": "victim",
          "type": "Player",
          "doc": "Who died: a player or an NPC."
        },
        {
          "name": "killer",
          "type": "Player?",
          "doc": "Who killed them; nil for no one, or one no longer here."
        },
        {
          "name": "weapon",
          "type": "string?",
          "doc": "The weapon it was done with; nil for none."
        },
        {
          "name": "means",
          "type": "string",
          "doc": "How: `bullet`, `melee`, `explosion`, `fall` or `mod`, the mod's own."
        },
        {
          "name": "location",
          "type": "string?",
          "doc": "The limb it struck, as `head`; nil for an explosion or a fall."
        }
      ]
    },
    {
      "name": "damaged",
      "group": "Health",
      "since": "0.1",
      "doc": "A player or an NPC lost health.",
      "server": [
        {
          "name": "victim",
          "type": "Player",
          "doc": "Who was hurt: a player or an NPC."
        },
        {
          "name": "attacker",
          "type": "Player?",
          "doc": "Who hurt them; nil for no one, or one no longer here."
        },
        {
          "name": "amount",
          "type": "number",
          "doc": "The health it took."
        },
        {
          "name": "weapon",
          "type": "string?",
          "doc": "The weapon it was done with; nil for none."
        },
        {
          "name": "means",
          "type": "string",
          "doc": "How: `bullet`, `melee`, `explosion`, `fall` or `mod`, the mod's own."
        },
        {
          "name": "location",
          "type": "string?",
          "doc": "The limb it struck, as `head`; nil for an explosion or a fall."
        }
      ],
      "client": [
        {
          "name": "victim",
          "type": "Player",
          "doc": "Who was hurt: a player or an NPC."
        },
        {
          "name": "attacker",
          "type": "Player?",
          "doc": "Who hurt them; nil for no one, or one no longer here."
        },
        {
          "name": "amount",
          "type": "number",
          "doc": "The health it took."
        },
        {
          "name": "weapon",
          "type": "string?",
          "doc": "The weapon it was done with; nil for none."
        },
        {
          "name": "means",
          "type": "string",
          "doc": "How: `bullet`, `melee`, `explosion`, `fall` or `mod`, the mod's own."
        },
        {
          "name": "location",
          "type": "string?",
          "doc": "The limb it struck, as `head`; nil for an explosion or a fall."
        }
      ]
    },
    {
      "name": "said",
      "group": "Chat",
      "since": "0.1",
      "doc": "A line was said in the chat, one a second a player, cleaned and cut to 150 bytes. On the server, what its handlers leave in `to`, `label` and `color` routes it, never back to the speaker; on a client, it is shown.",
      "server": [
        {
          "name": "player",
          "type": "Player",
          "doc": "Who said it."
        },
        {
          "name": "text",
          "type": "string",
          "doc": "What they said."
        },
        {
          "name": "channel",
          "type": "string",
          "doc": "The channel they said it on."
        },
        {
          "name": "to",
          "type": "{Player | number}?",
          "doc": "Who is shown it, as players; set it to players or ids. Everyone for nil."
        },
        {
          "name": "label",
          "type": "string?",
          "doc": "What it shows before the line."
        },
        {
          "name": "color",
          "type": "string?",
          "doc": "The label's colour, as CSS `#rrggbbaa`."
        }
      ],
      "client": [
        {
          "name": "from",
          "type": "Player?",
          "doc": "Who said it; nil for the mod's own lines."
        },
        {
          "name": "text",
          "type": "string",
          "doc": "What was said."
        },
        {
          "name": "label",
          "type": "string?",
          "doc": "What it shows before the line."
        },
        {
          "name": "color",
          "type": "string?",
          "doc": "The label's colour, as CSS `#rrggbbaa`."
        }
      ]
    },
    {
      "name": "screenshot",
      "group": "Players",
      "since": "0.1",
      "doc": "A player saved a screenshot, as their game says, which proves nothing. One a second at most.",
      "server": [
        {
          "name": "player",
          "type": "Player",
          "doc": "Who saved it."
        }
      ]
    },
    {
      "name": "kicked",
      "group": "Players",
      "since": "0.1",
      "doc": "The engine's `/kick` or `/ban` drops a player. Heard before `leaving`.",
      "server": [
        {
          "name": "player",
          "type": "Player",
          "doc": "Who is dropped."
        },
        {
          "name": "by",
          "type": "Player?",
          "doc": "Who ran it; nil for the server's console."
        },
        {
          "name": "duration",
          "type": "number?",
          "doc": "The seconds they are kept out; nil for a kick."
        },
        {
          "name": "reason",
          "type": "string?",
          "doc": "Why, if it said."
        }
      ]
    },
    {
      "name": "tick",
      "group": "Timers",
      "since": "0.1",
      "doc": "The mod ticked: heard as often as the server's mod ticks.",
      "server": [
        {
          "name": "delta",
          "type": "number",
          "doc": "The seconds since the last."
        }
      ],
      "client": [
        {
          "name": "delta",
          "type": "number",
          "doc": "The seconds since the last."
        }
      ]
    },
    {
      "name": "frame",
      "group": "Timers",
      "since": "0.1",
      "doc": "A frame is drawn: heard once a frame, as often as the player's game draws.",
      "client": [
        {
          "name": "delta",
          "type": "number",
          "doc": "The seconds since the last frame."
        }
      ]
    },
    {
      "name": "hit_too_late",
      "group": "Health",
      "since": "0.1",
      "doc": "A shot of this player's reached its victim as they died or left, so it did nothing.",
      "client": [
        {
          "name": "victim",
          "type": "Player",
          "doc": "Who the shot reached."
        }
      ]
    }
  ],
  "values": [
    {
      "name": "players",
      "group": "Players",
      "side": "both",
      "since": "0.1",
      "type": "{[number]: Player}",
      "doc": "The players here, people, bots and NPCs, by id: `players[id]`, and `for id, p in players do`."
    },
    {
      "name": "me",
      "group": "Players",
      "side": "client",
      "since": "0.1",
      "type": "Player",
      "doc": "The player this game is of."
    },
    {
      "name": "entities",
      "group": "Entities and models",
      "side": "both",
      "since": "0.1",
      "type": "{[number]: Entity}",
      "doc": "The entities by id, `entities[id]`: on the server those the mod made, alive; on a client those it draws."
    },
    {
      "name": "match",
      "group": "State and events",
      "side": "both",
      "since": "0.1",
      "type": "table",
      "doc": "The match's state: the engine's, `match.map`, `match.gametype` and `match.number`, and each `match_state`."
    },
    {
      "name": "server",
      "group": "State and events",
      "side": "both",
      "since": "0.1",
      "type": "table",
      "doc": "The server's state: its settings, as `server.hostname`, and each `server_state`."
    },
    {
      "name": "config",
      "group": "Settings",
      "side": "server",
      "since": "0.1",
      "type": "Config",
      "doc": "As a `server_state`'s `set_by`: the server's configuration alone may set it, never a player's `/set`."
    },
    {
      "name": "everyone",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "type": "Group",
      "doc": "Every player."
    },
    {
      "name": "owner",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "type": "Group",
      "doc": "The owner of what it is given to: the player it is about, alone."
    },
    {
      "name": "team",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "type": "Group",
      "doc": "The players on the owner's team, the owner too; no one when they are on none."
    },
    {
      "name": "spectators",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "type": "Group",
      "doc": "The players watching the owner through their eyes while dead."
    },
    {
      "name": "admins",
      "group": "State and events",
      "side": "server",
      "since": "0.1",
      "type": "Group",
      "doc": "The players the `admins` setting lists."
    },
    {
      "name": "markers",
      "group": "Map",
      "side": "server",
      "since": "0.1",
      "type": "Markers",
      "doc": "The map's markers, points with a facing, by name, `markers.spawn0`, or by a pattern, `markers(\"spawn*\")`, in the map's order. A name the map has not fails."
    },
    {
      "name": "parts",
      "group": "Map",
      "side": "server",
      "since": "0.1",
      "type": "Parts",
      "doc": "The map's parts, by name, `parts.door_a`, or by a pattern, `parts(\"barrier*\")`, whose methods call each. One removed is left out of the sets made after."
    },
    {
      "name": "triggers",
      "group": "Map",
      "side": "both",
      "since": "0.1",
      "type": "Triggers",
      "doc": "The map's triggers, and those the mod's handlers declare, by name, `triggers.buy_door`, or by a pattern, which lists those made at run time after the map's. One removed is left out of the sets made after."
    },
    {
      "name": "view",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "type": "View",
      "doc": "What this player's view shows: its field of view, exposure, fog and crosshair."
    },
    {
      "name": "sound_mix",
      "group": "Sounds",
      "side": "client",
      "since": "0.1",
      "type": "SoundMix",
      "doc": "How loud each category of sounds plays, and how muffled, on top of the player's own volumes."
    },
    {
      "name": "int",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Limited",
      "doc": "A whole number. Called with limits, `t.int { min = 1, max = 999 }`, it refuses one outside them, never clamping it."
    },
    {
      "name": "number",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Limited",
      "doc": "A finite number. Called with limits, `t.number { min = 0 }`, it refuses one outside them, never clamping it."
    },
    {
      "name": "string",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Sized",
      "doc": "Text. Called with its most bytes, `t.string { max = 32 }`, it refuses longer text; a command's argument is one word."
    },
    {
      "name": "bool",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Type",
      "doc": "`true` or `false`."
    },
    {
      "name": "vector",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Type",
      "doc": "A point or a direction: given as a vector or a table of `x`, `y` and `z`, read as a vector."
    },
    {
      "name": "player",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Type",
      "doc": "A player or an NPC: sent as its id, read as the player. A command's argument is typed as part of a name or `#id`."
    },
    {
      "name": "entity",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Type",
      "doc": "An entity: sent as its id, read as the entity."
    },
    {
      "name": "model",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Type",
      "doc": "A model's file, by its name, checked as it is given."
    },
    {
      "name": "sound",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Type",
      "doc": "A sound's file, by its name, checked as it is given."
    },
    {
      "name": "effect",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Type",
      "doc": "An effect's file, by its name, checked as it is given."
    },
    {
      "name": "image",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Type",
      "doc": "An image's file, by its name, checked as it is given."
    },
    {
      "name": "weapon",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Type",
      "doc": "A weapon's file, by its name, checked as it is given."
    },
    {
      "name": "animation",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Type",
      "doc": "An animation's file, by its name, checked as it is given."
    },
    {
      "name": "material",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Type",
      "doc": "A material's file, by its name, checked as it is given."
    },
    {
      "name": "text",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Type",
      "doc": "The rest of a command's line: its last argument's type alone."
    },
    {
      "name": "duration",
      "table": "t",
      "group": "Types",
      "side": "both",
      "since": "0.1",
      "type": "Type",
      "doc": "A whole number of seconds typed with its unit, `30s`, `5m`, `12h` or `7d`, up to 3650 days: a command's argument's type alone."
    }
  ],
  "styles": [
    {
      "name": "left",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "length",
      "doc": "How far its left edge is from its parent's, or the screen's; or `auto`."
    },
    {
      "name": "top",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "length",
      "doc": "How far its top edge is from its parent's, or the screen's; or `auto`."
    },
    {
      "name": "right",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "length",
      "doc": "How far its right edge is from its parent's, or the screen's; or `auto`."
    },
    {
      "name": "bottom",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "length",
      "doc": "How far its bottom edge is from its parent's, or the screen's; or `auto`."
    },
    {
      "name": "width",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "length",
      "doc": "Its width, not negative; or `auto`, as its content needs."
    },
    {
      "name": "height",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "length",
      "doc": "Its height, not negative; or `auto`, as its content needs."
    },
    {
      "name": "padding",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "lengths",
      "doc": "The room inside its border: one to four lengths, as CSS's sides, no `%`."
    },
    {
      "name": "color",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "color",
      "doc": "Its text's colour; white without it."
    },
    {
      "name": "fontSize",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "length",
      "doc": "Its text's size, 24 pixels without it; `em` and `%` are of the screen's 24."
    },
    {
      "name": "fontWeight",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "number",
      "doc": "`normal`, `bold` or 1 to 1000, bold from 700."
    },
    {
      "name": "textAlign",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "left",
        "center",
        "right",
        "start",
        "end"
      ],
      "doc": "Where its lines sit."
    },
    {
      "name": "lineHeight",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "number",
      "doc": "The height of a line: a multiple of the font size, a length, `%` or `normal`."
    },
    {
      "name": "letterSpacing",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "length",
      "doc": "The room between letters, or `normal`."
    },
    {
      "name": "textTransform",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "none",
        "uppercase",
        "lowercase",
        "capitalize"
      ],
      "doc": "Its text's case."
    },
    {
      "name": "fontStyle",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "normal",
        "italic",
        "oblique"
      ],
      "doc": "Slanted, `oblique 10deg` under 90deg."
    },
    {
      "name": "overflow",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "visible",
        "hidden",
        "clip"
      ],
      "doc": "Whether what passes its box shows."
    },
    {
      "name": "textOverflow",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "clip",
        "ellipsis"
      ],
      "doc": "How a line cut by `overflow` ends."
    },
    {
      "name": "background",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "css",
      "doc": "Its background colour, or image, position and size, as CSS's shorthand."
    },
    {
      "name": "backgroundColor",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "color",
      "doc": "The colour behind its content."
    },
    {
      "name": "backgroundImage",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "image",
      "doc": "An image the server named, or a gradient, drawn behind its content."
    },
    {
      "name": "backgroundPosition",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "position",
      "doc": "Where its background image sits; at its top-left without it."
    },
    {
      "name": "backgroundSize",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "size",
      "doc": "How big its background image is; its own size without it."
    },
    {
      "name": "border",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "css",
      "doc": "A width, `solid` or `none`, and a colour, in any order."
    },
    {
      "name": "borderWidth",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "length",
      "doc": "Its border's width, one for all sides, no `%`."
    },
    {
      "name": "borderStyle",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "solid",
        "none",
        "hidden"
      ],
      "doc": "Whether its border is drawn."
    },
    {
      "name": "borderColor",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "color",
      "doc": "Its border's colour."
    },
    {
      "name": "borderRadius",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "lengths",
      "doc": "How round its corners are: one to four lengths, as CSS's corners."
    },
    {
      "name": "boxShadow",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "css",
      "doc": "One shadow: x and y, a blur and a spread if given, and a colour; or `none`."
    },
    {
      "name": "transform",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "css",
      "doc": "CSS's transform functions, in order: `translate()`, `rotate()`, `scale()`…"
    },
    {
      "name": "transformOrigin",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "position",
      "doc": "The point it turns and scales about; its middle without it."
    },
    {
      "name": "transition",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "css",
      "doc": "How a change to its properties eases: a property, seconds, a timing, a delay. It eases the place and the size, padding, colours, text sizes and spacing, backgrounds, borders, shadows, transforms, opacity, filters and masks, or `all`."
    },
    {
      "name": "animation",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "css",
      "doc": "Up to 4 animations of `keyframes` by name, as CSS's shorthand."
    },
    {
      "name": "opacity",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "number",
      "doc": "How opaque it and all inside it are, 0 to 1 or a percentage."
    },
    {
      "name": "filter",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "css",
      "doc": "Up to 8 of CSS's filter functions on it and all inside it, as one: blur, brightness, contrast, grayscale, hue-rotate, invert, opacity, saturate and sepia."
    },
    {
      "name": "backdropFilter",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "css",
      "doc": "Up to 8 of CSS's filter functions on what is behind it, within its border."
    },
    {
      "name": "mixBlendMode",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "normal",
        "multiply",
        "screen",
        "overlay",
        "darken",
        "lighten",
        "color-dodge",
        "color-burn",
        "hard-light",
        "soft-light",
        "difference",
        "exclusion",
        "hue",
        "saturation",
        "color",
        "luminosity",
        "plus-lighter"
      ],
      "doc": "How it and all inside it blend with what is behind it."
    },
    {
      "name": "isolation",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "auto",
        "isolate"
      ],
      "doc": "Keeps what is inside it blending only with each other."
    },
    {
      "name": "maskImage",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "image",
      "doc": "An image or a gradient whose opacity shows it, nothing outside it; nothing while its image loads."
    },
    {
      "name": "maskSize",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "size",
      "doc": "How big its mask is."
    },
    {
      "name": "maskPosition",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "position",
      "doc": "Where its mask sits."
    },
    {
      "name": "zIndex",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "whole",
      "doc": "Its order among its siblings, or `auto`; the engine's HUD is at 0."
    },
    {
      "name": "userSelect",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "none",
        "auto",
        "text"
      ],
      "doc": "Whether its text may be selected."
    },
    {
      "name": "display",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "block",
        "flex",
        "none"
      ],
      "doc": "How it lays its children out, or hides."
    },
    {
      "name": "position",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "static",
        "relative",
        "absolute"
      ],
      "doc": "Whether it flows in its parent."
    },
    {
      "name": "flexDirection",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "row",
        "row-reverse",
        "column",
        "column-reverse"
      ],
      "doc": "Which way a flex box lays its children."
    },
    {
      "name": "flexWrap",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "nowrap",
        "wrap",
        "wrap-reverse"
      ],
      "doc": "Whether a flex box's children wrap."
    },
    {
      "name": "justifyContent",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "normal",
        "flex-start",
        "flex-end",
        "start",
        "end",
        "center",
        "space-between",
        "space-around",
        "space-evenly"
      ],
      "doc": "Where a flex box's children sit along its way."
    },
    {
      "name": "alignItems",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "normal",
        "stretch",
        "flex-start",
        "flex-end",
        "start",
        "end",
        "center"
      ],
      "doc": "Where a flex box's children sit across its way."
    },
    {
      "name": "alignSelf",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "keyword",
      "words": [
        "auto",
        "normal",
        "stretch",
        "flex-start",
        "flex-end",
        "start",
        "end",
        "center"
      ],
      "doc": "Where it sits across its flex parent's way, over its `alignItems`."
    },
    {
      "name": "gap",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "lengths",
      "doc": "The room between a flex box's rows and columns: one for both, or two."
    },
    {
      "name": "rowGap",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "length",
      "doc": "The room between a flex box's rows, or `normal`."
    },
    {
      "name": "columnGap",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "length",
      "doc": "The room between a flex box's columns, or `normal`."
    },
    {
      "name": "flex",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "css",
      "doc": "Grow and shrink factors and a basis, or `none`, `auto` or `initial`."
    },
    {
      "name": "flexGrow",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "number",
      "doc": "How much of a flex box's room to spare it takes."
    },
    {
      "name": "flexShrink",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "number",
      "doc": "How much it gives up when a flex box lacks room."
    },
    {
      "name": "flexBasis",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "length",
      "doc": "Its size along its flex parent's way before growing, or `auto` or `content`."
    },
    {
      "name": "order",
      "group": "Boxes and styles",
      "side": "client",
      "since": "0.1",
      "kind": "whole",
      "doc": "Its place among a flex box's children."
    }
  ]
}
