Repository navigation
Making a Gamemode
A gamemode gives maps their rules: what kind of event they are ridden as (a race against the clock, a trick contest, survival …), the time limit, what the end of the time means, and the medal targets of each map. It may also bring server scripts that add to the rules: notices, splits, records. Gamemodes appear on the game's Maps page next to the built-in modes, and run on servers.
The rules themselves are data: the game and a server apply them without a script. Scripts add to them (notices, records, ending a round early); they cannot change a run's time or points.
sprint is a race against the clock on the template course (Making a Map), with medals and a
script that announces each round, tells a rider its splits and keeps the best finish.
sprint/
resource.toml
map.toml
maps/course.gltf
gamemodes/sprint.toml
server/main.luau
resource.toml:
[resource]
name = "sprint"
version = "1.0.0"
title = "Sprint"
description = "A race against the clock with medals, on the template course"
api = 1
type = "gamemode"
[add]
"map/course" = "map.toml"
"gamemode/sprint" = "gamemodes/sprint.toml"
[scripts]
server = ["server/*.luau"]map.toml:
[map]
title = "Sprint course"
scene = "maps/course.gltf"
modes = ["race", "freeride"]gamemodes/sprint.toml:
[gamemode]
title = "Sprint"
event = "race_clock"
time_up = "fail" # a race can only fail at its time limit
[[gamemode.map]]
id = "sprint:map/course"
targets = [13.0, 15.0, 20.0] # gold, silver, bronze: seconds, best first
time_limit_s = 90.0server/main.luau:
-- Announces each round, tells a rider each split, and keeps the best finish.
addEventHandler("onRoundStart", root, function(round, drop)
print("sprint: round " .. round .. " on " .. drop)
showNotice(source, "Sprint", "Gold under 13 s", 5)
end)
addEventHandler("onRiderCheckpoint", root, function(checkpoint, index, clock)
local player = getRiderPlayer(source)
if player then
showNotice(player, "Split " .. index, string.format("%.2f s", clock / 1000), 3)
end
end)
addEventHandler("onRiderFinish", root, function(clock, points, failed)
local best = storage.get("best")
if not failed and (best == nil or clock < best) then
storage.set("best", clock)
print("sprint: a new best, " .. clock .. " ms")
end
end)
addEventHandler("onRoundEnd", root, function(round)
print("sprint: round " .. round .. " ended")
end)
-- `endround` in the console ends every round under way
addCommandHandler("endround", function(player, command)
for _, instance in getInstances() do
print("sprint: endRound " .. tostring(endRound(instance, "ended by the operator")))
end
end)On a server with
[game]
mode = "race"
map = "sprint:map/course"
gamemode = "sprint:gamemode/sprint"
lobby_wait = 5
countdown = 3
[resources]
start = ["sprint"]one player rode three rounds; the operator typed endround during the third. The server's log:
map sprint:map/course (Sprint course) under sprint:gamemode/sprint "Sprint" (EventType_RaceClock 5, a time limit of 90000 ms ending failed, 3 targets) loaded in 2156 ms: …
instance 1 round 0: running on map sprint:map/course (sprint:gamemode/sprint)
scripts: sprint: sprint: round 0 on sprint:map/course
instance 1 round 0: results on map sprint:map/course (sprint:gamemode/sprint); the standings: 1. Player Finished 13700 ms 0 pts 90443 mm
scripts: sprint: sprint: a new best, 13700 ms
scripts: sprint: sprint: round 0 ended
…
scripts: sprint: sprint: round 2 on sprint:map/course
scripts: ran endround
scripts: sprint: sprint: endRound true
instance 1 round 2: ended by the scripts: sprint: ended by the operator
instance 1 round 2: results on map sprint:map/course (sprint:gamemode/sprint); the standings: 1. Player Racing 10666 ms 0 pts 76686 mm
The second round's 13 700 ms equalled the best, so no new best was printed. On the rider's HUD the round's notice
shows for 5 s and each gate's split for 3 s: "Split 0 / 3.73 s" at the first gate (index counts from 0).
Ridden alone from the Maps page, the same package gives the same lines in the game's log, from the local script
host, and keeps its best in ScriptData/local-server/sprint/:
scripts: the local script host runs sprint's 1 server scripts for Player
scripts: local server: [sprint] sprint: round 1 on sprint:map/course
scripts: local server: [sprint] sprint: a new best, 13700 ms
scripts: local server: [sprint] sprint: round 1 ended
| Key | Required | Rule |
|---|---|---|
title |
yes | 1 to 64 characters |
event |
yes |
race_clock, race_ghosts, race_bots, trick_score, trick_ghosts, trick_bots, survive_to_bottom, survive_to_death, freeride
|
time_up |
no | what the time limit's end does: fail (the run fails) or result (the run counts as it stands). The default is result for survive_to_death and fail for every other; a race can only fail
|
time_limit_s |
no | the default time limit, above 0 and at most 3599.999 |
any_map |
no |
true: the gamemode takes any map that has what its event needs (a finish, except free ride), without targets |
[[gamemode.map]] |
yes, unless any_map
|
the maps it takes, at most 256 |
Each [[gamemode.map]]:
| Key | Rule |
|---|---|
id |
the map's id (<package>:map/<name>), each once |
targets |
none, or three medal targets (gold, silver, bronze), best first, strictly in order: seconds for races, points for trick events, metres for survival. Not for survive_to_bottom and freeride
|
time_limit_s |
this map's time limit |
A gamemode's server scripts are ordinary server scripts. The round's events are the useful
ones (Events and Messages): onRoundStart, onRiderCheckpoint, onRiderFinish,
onRoundEnd, with getStandings, getRiderState, showNotice and endRound from the
Server Script API. storage keeps records across rounds and restarts.
In single player the game runs the gamemode's server scripts in a local script host when you ride the gamemode
from the Maps page, so the same package plays alone and online. There, privileged calls are always refused and the
storage is ScriptData/local-server/<package>/ in your Project Avalanche folder.
Servers
- Hosting a Server
- Server Configuration
- Ports and Firewalls
- Server Console
- Operators and Remote Console
- Access Control List
- Bans and Mutes
- The Server List
- Query and LAN Discovery
- Server Resources
- Blocklists
- Maps and Gamemodes
- Logs and Metrics
- Running as a Service
- Running in Docker
- Joining a Server
Scripting
- Resource Packages
- Content IDs and Kinds
- Scripting Overview
- Server Script API
- Client Script API
- Events and Messages
- Script Permissions
- Script Examples
Modding