Contents

Elite Duel Speed manual

This manual ships with the game as manual.md in the game folder. In game, open it from the main menu with Manual, bottom right.

Getting started

  • Play: servers, your own lobby, and race time trials.
  • Watch: replays saved on this machine.
  • Maps: installed maps, custom maps, tracks, and the map and track editors.
  • Settings: everything in Settings.
  • The profile button, top right, opens Customize: character, outfit, emotes, dances and cards.
  • Feedback, bottom right next to Manual and also on the pause screen, sends a bug report or an idea to the developers. A report carries what you type, your Steam name and ID, the game build, what you were doing, and this session's log unless you untick it.

The line next to Manual shows the game version, build number and commit. Settings > About has the full report and a Copy report button for bug reports.

Play

  • Browse: dedicated servers run by other people. See Playing online.
  • Custom: host a lobby on this machine. See Listen server.
  • Race: time trials against the clock and other players' ghosts.
  • The code box at the top joins a lobby by its five character invite code.

Online play needs Steam running.

Game modes

ModeIdRules
DuelduelTwo teams. Win two fights to take a round. Each fight draws a gun from the lobby's pool.
Free-for-allffaEveryone for themselves. The last player standing takes the round.
TagtagOne player is it, with a one round pistol. Shoot someone to pass it on. The least time spent as it wins. By default only a headshot tags.
RaceraceTime trials on a track.
Gun GamegungameKills move you up a ladder of guns.
HORSEhorseOne player sets a mark. Everyone else has to reach it before time runs out.
BombbombTwo teams, one bomb. A random attacker starts with it on key 3, in place of their utility gun for the round. Attackers plant it on a site; defenders stop them or defuse it. Needs a map with bomb sites.
Capture the FlagctfTwo teams, two flags. Bring the enemy flag home while yours is on its stand. Needs a map with flag stands.

Warmup and matches

A lobby starts in warmup. Everyone can move and shoot, and a death only costs a short respawn. The lobby owner starts a match from Esc > Manage lobby > New match, which sets the mode, map, guns and round limit. If the owner leaves, the next player in the lobby becomes owner.

Movement

  • Hold jump to bunny hop. Jumping skips ground friction.
  • Strafe and turn in the air to gain speed.
  • Crouch while running fast to slide. Jump out of a slide to keep the speed.
  • Press jump in the air next to a wall to wall jump. Chains of wall jumps work on any wall.
  • Hold forward into a ledge between waist and head height to climb it.
  • Face a ladder and hold forward to climb. Jump to get off.
  • Steps up to 18 units are climbed without jumping. Slopes steeper than 45 degrees are surfable.

The training range is the default map. It has lanes and props for practicing each of these.

Controls

Default binds

KeyNameCommandAction
WKeyW+forwardMove forward
SKeyS+backMove back
AKeyA+leftStrafe left
DKeyD+rightStrafe right
SpaceSpace+jumpJump
L CtrlControlLeft+crouchCrouch / slide
CapsCapsLock+crouchCrouch / slide
L ShiftShiftLeft+sprintSprint
Mouse 1MouseLeft+fireFire
Mouse 2MouseRight+adsAim down sights
RKeyR+reloadReload
EKeyE+useUse / open door
TabTab+scoreboardScoreboard
TKeyT+chatChat
GKeyG+emoteEmote wheel
FKeyF+danceDance wheel
EscapeEscape+menuMenu
VKeyV+resetReset / restart run
CKeyC+checkpoint_backBack to last checkpoint
F7F7toggle hud.show
F1F1hud_editEdit HUD
1Digit1+weapon_1Weapon slot 1
2Digit2+weapon_2Weapon slot 2
3Digit3+weapon_3Weapon slot 3
4Digit4+cardPlaying card
BKeyB+loadoutLoadout
BackquoteBackquotetoggleconsoleConsole

Loadout and wheels

Keys 1 to 3 draw your loadout slots: a primary, a sidearm and something to throw. Hold one to open the gun wheel and pick a gun for that slot. 4 draws your playing card; hold it for the card wheel. G and F open the emote and dance wheels. B opens the loadout screen with four named presets.

In a duel the fight hands out the gun. Loadouts apply in warmup, on the range, and in modes where everyone brings their own guns.

A loadout mode gives each key a job. By default key 1 takes any rifle, SMG, sniper or shotgun, key 2 any sidearm, and key 3 the grenade or the sawed-off, carrying three, four and two magazines. Servers set their own with sv.loadout_1 to sv.loadout_3 and sv.spares_1 to sv.spares_3; a lobby owner moves the same values with game.loadout_* and game.spares_*. A rule is a list of words, where a plural is a whole class (rifles, smgs, shotguns, snipers, sidearms, specials) and a singular is one gun by tag. The spare counts are magazines beyond the one loaded; -1 leaves reloads unlimited.

The loadout screen shows the rules: each slot says what it takes and how much ammo it carries, every gun is badged with the keys it may sit on, and choosing a slot narrows the grid to what fits. Guns that belong on another key, and guns the server does not offer, sit dimmed below. A preset that does not fit the server is flagged, with one button to move its guns onto keys that will take them.

Spectating

Fire and reload cycle the player you watch. Jump switches between following and free camera. Crouch switches between first and third person.

Changing binds

Settings > Controls has a bind table with two keys per action. Click a slot and press a key or mouse button. Escape cancels. Right click clears a slot.

From the console:

bind KeyG +emote
bind MouseMiddle "toggle hud.show"
unbind KeyG
binds

Key names follow the table above: KeyA to KeyZ, Digit0 to Digit9, F1 to F24, Space, Tab, Escape, Backquote, ShiftLeft, ControlLeft, AltLeft, arrow keys, Numpad0 to Numpad9, MouseLeft, MouseRight, MouseMiddle, MouseBack, MouseForward, WheelUp and WheelDown. Short forms like mouse1, ctrl, shift and single letters also work.

The last key bound to +menu cannot be unbound.

Settings

Settings are console variables. Every row below shows its variable, so you can also set it from the console or a config file. See Console and config files.

Reset all, top right of the settings screen, restores every setting and bind to its default.

General

Gameplay

SettingDefaultValuesVariableDescription
Aim down sightsHoldHold, Toggleinput.ads_toggleThe aim key toggles the sights instead of being held
Gun handRightRight, Leftprofile.handGun hand

Replays

SettingDefaultValuesVariableDescription
Save replaysOnOff, Onnet.auto_replaysSave a replay of every match

Discord

SettingDefaultValuesVariableDescription
PresenceOnOff, Ondiscord.presenceRich presence
Lobby invitesOnOff, Ondiscord.lobby_invitesLobby invites in presence

Steam

SettingDefaultValuesVariableDescription
Keep settings and HUD layouts in Steam CloudOffOff, Onapp.cloud_syncPush config.cfg and hud_profiles.json to Steam Cloud on every save

Controls

Mouse

SettingDefaultValuesVariableDescription
Mouse sensitivity0.040.005 to 0.3input.sensitivityDegrees of view rotation per mouse count
Zoom sensitivity10.2 to 2input.zoom_sensMultiplier on the focal-length sensitivity scale through a magnified scope

Crosshair

The crosshair panel sets style, length, gap, thickness, colour and outline, with a live preview. The variables start at crosshair.style.

HUD

Overlay

SettingDefaultValuesVariableDescription
Show HUDOnOff, Onhud.showDraw the HUD
Scale10.5 to 2hud.scaleSize of the overlay
Update rate0 Hz0 to 1000 Hzhud.max_hzHUD updates per second; 0 sends one every frame

HUD editor

Press F1 in game to edit the HUD. Drag panels to move them and drag edges to resize. Delete removes a panel, Ctrl+Z undoes, Ctrl+D duplicates, arrow keys nudge by 1 pixel and Shift with an arrow key by 10. Esc or F1 leaves the editor.

HUD profiles

A profile is one HUD layout. The Profiles panel picks the default profile and can assign a different one to each game mode and to spectating. Profiles are stored in hud_profiles.json next to config.cfg. The hud_profile and hud_profiles commands do the same from the console.

Video

Display

SettingDefaultValuesVariableDescription
WindowBorderlessWindowed, Borderless, Fullscreenvideo.modeWindow mode
DisplayPrimaryPrimary or a monitorvideo.monitorDisplay to use; empty means the primary
Window width1600 px640 to 16384 pxvideo.widthWindow width in windowed mode
Window height900 px480 to 16384 pxvideo.heightWindow height in windowed mode
V-syncOffOff, On, Fastvideo.vsyncOff presents as soon as a frame is done, On waits for the display, Fast keeps only the newest frame
Frame cap0 Hz0 to 1000 Hzvideo.fps_capFrame cap; 0 follows the monitor
Low latencyOnOff, On, Boostvideo.low_latencyNVIDIA Reflex or AMD Anti-Lag when the driver offers it
Render scale100%50 to 200%video.render_scaleScene resolution as a share of the window; above 100 supersamples
Field of view105 deg70 to 130 degvideo.fovHorizontal field of view
View model FOV65 deg50 to 90 degvideo.viewmodel_fovField of view the held weapon is drawn with
Brightness10.5 to 2video.brightnessExposure multiplier
Reticle brightness10.2 to 2.5video.reticle_brightnessHow bright a red dot or holo reticle is drawn
Gamma2.21.8 to 2.6video.gammaOutput gamma

Quality

SettingDefaultValuesVariableDescription
QualityMediumCompetitive, Low, Medium, High, Ultra, Customvideo.qualityRender preset; changing a detail below makes it Custom
ShadingQualityCompetitive, Qualityvideo.shadingCompetitive is the flat, high contrast look; Quality is the full lighting model
Surface detailHighLow, Highvideo.surface_detailNormal, roughness, emissive and directional lightmap detail on surfaces
ShadowsMediumOff, Low, Medium, High, Ultravideo.shadowsSun shadow resolution, reach and softness
Dynamic shadowsOnOff, Onvideo.dynamic_shadowsShadows cast by players and props
Ambient occlusionLowOff, Low, Medium, Highvideo.ambient_occlusionScreen space contact shading
ReflectionsLowOff, Low, Highvideo.reflectionsReflection detail
WaterMediumLow, Medium, Highvideo.waterWater surface detail; Medium refracts and reflects the scene, High adds screen space reflections and caustics
BloomOffOff, Onvideo.bloomGlow around bright light, where the map style uses it
Dynamic lightsOnOff, Onvideo.dynamic_lightsMuzzle flashes and explosions light the world
Physics propsOnOff, Onvideo.physics_propsBottles, crates and barrels react to the player, shots and blasts
Card trailsOnOff, Onvideo.card_trailsRibbons, glyph walls, smoke, stars and wires trailing behind players holding a foil card
Anisotropic filtering8xOff, 2x, 4x, 8x, 16xvideo.anisotropyTexture sharpness at grazing angles
Texture detailHighLow, Medium, Highvideo.texture_detailLower levels skip the sharpest mip levels
Anti-aliasingOffOff, FXAAvideo.antialiasingEdge smoothing; render scale above 100 supersamples as well
Sharpening00 to 1video.sharpenContrast adaptive sharpening after anti-aliasing

Picking a Quality preset sets the detail rows under it. Changing one of those rows sets Quality to Custom. Window width and height only apply in Windowed mode.

Audio

Volume

SettingDefaultValuesVariableDescription
Master volume0.750 to 1audio.masterMaster volume
Sound effects10 to 1audio.sfxSound effects

Spatial

SettingDefaultValuesVariableDescription
Spatial audioHeadphonesHeadphones, Speakersaudio.spatializerSpatial audio
ReverbOnOff, Onaudio.reverbReverb

Radio

SettingDefaultValuesVariableDescription
Play the stationOnOff, Onaudio.radioPlay the music a server is streaming; off tells the server to send none of it
Station volume0.50 to 1audio.radio_volumeHow loud the server's station is

Network

Crash reports

SettingDefaultValuesVariableDescription
Upload crash reportsOffOff, Onoiko.upload_crash_dumpsAfter a crash, send the minidump, the log and the build to the developers on the next launch

Maps

SettingDefaultValuesVariableDescription
Download mapsOnOff, Onnet.auto_mapsDownload a lobby's map when this client lacks it

Replays

SettingDefaultValuesVariableDescription
Upload match replaysOnOff, Onnet.upload_replaysSend a replay of every match you host to the backend

Dedicated server keys

A server key lets a dedicated server upload replays and match results. Sign in, then use Generate. Keys start with eds_sk_. Copy, rename or revoke them here. See Server list and server key.

About

Build, Steam and session details. Copy report puts all of it on the clipboard. The version and status console commands print the same.

Steam Cloud

With Settings > General > Steam > Keep settings and HUD layouts in Steam Cloud on, config.cfg and hud_profiles.json sync through Steam Cloud. Video settings stay local to each machine.

Console and config files

Console

Press ` (Backquote) to open the console. Tab completes names. Up and Down walk history. Ctrl+R searches history. Ctrl+F searches the output. Esc closes it.

  • help lists everything. help <name> explains one command or variable.
  • vars lists variables. vars video lists one namespace. vars --changed lists what differs from the defaults. vars --table opens a searchable table.

Console size, font and opacity are the console.* variables, starting at console.height.

Syntax

set video.fov 110
get video.fov
toggle hud.show
cycle video.vsync
inc input.sensitivity 0.005
reset video.fov
set profile.loadout_names [Assault, Close, Long, Utility]
alias fast "set video.quality Competitive"
exec practice.cfg
writeconfig backup.cfg --changed
  • One statement per line, or several split with ;.
  • Quote values with spaces.
  • Lists use [a, b].
  • Enum values ignore case. The console uses the names from Console variables, which can differ from the menu labels. For example video.vsync Mailbox is shown as Fast.
  • Numbers outside a variable's range are clamped.
  • Lines starting with # or // are comments.

config.cfg

The game saves settings, binds and aliases to config.cfg shortly after every change. It uses the first of these that applies:

  1. The path in the EDS_SETTINGS environment variable.
  2. config.cfg in the working directory, if it exists.
  3. config.cfg next to the game executable, if it exists. Use this for a portable install.
  4. ~/.config/eds/config.cfg on Linux, %APPDATA%\eds\config.cfg on Windows.

autoexec.cfg

autoexec.cfg in the same folder as config.cfg runs after it on every start. Use it for commands you want to run every time the game starts.

Playing online

Server browser

Play > Browse lists servers.

  • Internet: every public server. Filter by mode and hide full, empty or other version servers.
  • Favorites: servers you starred.
  • History: servers you connected to recently.
  • Lobbies: public lobbies hosted by players.
  • Direct: type host:port and press Connect or Watch. The port is required. The default server port is 27960.

Connect takes a seat. Watch joins as a spectator. A server that asks for a password prompts for it.

From the console: connect <host:port>.

Servers and the hub

Joining a dedicated server puts you in its hub. The hub shows the server's arenas, the rotation, and the ranked ladder or track records. Play takes a seat. On a ranked server Play joins the solo or duo queue.

Invite codes

Every lobby has a five character code. Type it into the box on the Play screen, or use join <code> to play and watch <code> to spectate. Esc > Manage lobby shows the code with a Copy button.

Map downloads

If a lobby runs a map you do not have, the game downloads it. Turn this off with Settings > Network > Download maps. Downloaded maps are cached and do not show in your map list.

Replays

With Settings > General > Save replays on, every match is saved on this machine. Watch lists them. Open folder shows where they are.

  • savereplay saves the current match so far.
  • record starts a server-side recording, including warmup. stop ends it and saves it here. Lobby owner or admin only.

Replay controls: Space play and pause, Left and Right seek (hold Shift for bigger steps), , and . step one tick, [ and ] change speed, Tab switches camera, Up and Down jump between marks.

Hosting a server

Listen server

Play > Custom hosts a lobby on this machine. Others join through Steam, so no port forwarding is needed.

  • Who can join: Invite only, Friends or Public. Public lobbies show in Browse > Lobbies.
  • Invite friends sends invites through Steam. The invite code works too.
  • New match sets the mode, map, guns and limits. End match returns to warmup.
  • The owner can kick players.

Lobby rules are the game.* variables. See game. Set them from the lobby screens, or with set in the console while you own the lobby.

Dedicated server

eds-server is the dedicated server. It ships in the game folder next to the game executable (eds-server.exe on Windows). In Steam, find the folder with right click > Manage > Browse local files.

Run it from a terminal inside the game folder. It reads server.cfg, writes its database and looks for maps relative to the folder it is started from.

cd "<game folder>"
./eds-server --hostname "my server" --map ut_uptown

A server runs one of three modes, set with sv.mode:

  • game: a rotation of maps and modes for whoever joins.
  • ranked: a rated ladder with solo and duo queues.
  • race: time trials on a rotation of tracks, with server records.

Settings apply in this order, later wins:

  1. server.cfg in the working directory.
  2. Environment variables.
  3. Command line flags.

Changes to sv.bind, sv.mode, sv.backend, sv.db, sv.default_map, sv.tracks_dir, sv.record and sv.record_dir need a restart. Everything else applies live.

Stop the server with Ctrl+C. It logs to the terminal.

Ports

The server uses one UDP port, 27960 by default, for gameplay, browser pings and map downloads. Forward that UDP port on your router to host on the internet. No TCP ports are needed.

Change it with --bind 0.0.0.0:27970 or sv.bind.

On Linux the server asks for large UDP buffers. If it logs that it got less, raise net.core.rmem_max and net.core.wmem_max.

server.cfg

server.cfg uses console syntax. Every sv.* variable is listed under sv.

set sv.mode game
set sv.hostname "my server"
set sv.region "eu-west"
set sv.password ""
set sv.admins [steam:76561198000000000]
set sv.rotation [ut_uptown:ffa, q3_aerowalk:gungame, ut_uptown:tag]
set sv.max_players 16
set sv.warmup_secs 20
exec extra.cfg

Command line flags

FlagDoes
--bind <addr:port>Sets sv.bind.
--mode <game|ranked|race>Sets sv.mode.
--hostname <name>Sets sv.hostname.
--password <text>Sets sv.password.
--map <name>Sets sv.default_map.
--max-players <n>Sets sv.max_players.
--max-viewers <n>Sets sv.max_viewers.
--public-addr <host:port>Sets sv.public_addr.
--privateSets sv.public to false.
--db <file>Sets sv.db.
--backend <url>Sets sv.backend.
--maps-dir <dir>Looks for maps here. Repeat for more folders. The first one replaces the default assets/maps.
--radio-dir <dir>Sets sv.radio_dir, and turns the station on.
--record-dir <dir>Records matches to this folder.
--no-recordDoes not record matches.
--no-downloadsDoes not send maps or replays to clients.
--cheatsAllows noclip in every arena.
--exec "<line>"Runs a console line after server.cfg. Repeat for more.
--snapshot-div <n>Sets sv.snapshot_div.
--spectator-snapshot-div <n>Sets sv.spectator_snapshot_div.
--download-mbits <n>Sets sv.download_mbits.
--max-downloads <n>Sets sv.max_downloads.
--max-replays <n>Sets sv.max_replays.
--replay-keep-secs <n>Sets sv.replay_keep_secs.
--race-track-secs <n>Sets sv.race_track_secs.
--control-socket <path>Serves the control API on a unix socket.
--control-tcp <addr:port>Serves the control API on TCP. Anyone who can reach it controls the server.
--no-controlTurns the control API off.
-v, -vvMore logging.

Environment variables

VariableDoes
EDS_BINDSets sv.bind.
EDS_PUBLIC_ADDRSets sv.public_addr.
EDS_BACKENDSets sv.backend.
EDS_BACKEND_KEYSets sv.key.
EDS_MAPS_DIRMap folders, separated by : on Linux and ; on Windows. Default assets/maps.
EDS_REPLAY_DIRWhere recordings go.
EDS_RADIO_DIRWhere the station's songs and playlists live. Default radio beside the server.
EDS_CONTROL_SOCKETControl API address. tcp:<addr:port> or <ip:port> is TCP, anything else a unix socket path.

Server list and server key

While sv.public is on, the server lists itself in every player's browser. --private keeps it off the list. Players can still connect directly.

The browser shows the address the server registered from, with its bound port. If players reach it on a different address or port, set sv.public_addr.

To upload replays and match results, the server needs a key. Generate one in game under Settings > Network > Dedicated server keys, then pass it with the EDS_BACKEND_KEY environment variable or set sv.key in server.cfg. Prefer the environment variable so the key stays out of files you share.

Players and admins

  • sv.password makes players enter a password to connect.
  • sv.auth is required by default: players must be signed in through Steam. optional and off relax it.
  • sv.admins lists admin player ids, like steam:76561198000000000. Find your Steam ID in Settings > About. With sv.auth required, an empty list means nobody is admin.

Admins get the server panel from the hub or the Esc menu: players, kicks and bans, banlists, the rotation, every sv.* variable, and a server console. A ban keeps somebody off this one server; a banlist is kept on the backend and shared with every server that follows it, and the official banlist is one every server takes unless its operator turns sv.official_bans off. In the game console, rcon <line> runs a line on the server, and set sv.<name> <value> on a server you administer is sent over rcon. The server commands are listed under Server.

Maps on a server

The server loads every .blvl file in its map folders, assets/maps by default. The map name is the file name without .blvl, in lowercase. The extension must be lowercase. Add folders with --maps-dir or EDS_MAPS_DIR.

Players who lack a map download it from the server. sv.download_mbits and sv.max_downloads limit the upload. sv.map_url points players at a web mirror first, as <url>/<name>.blvl. sv.map_url_only sends maps only through that mirror.

Rotation, ranked and race

  • Game servers: sv.rotation lists map or map:mode entries. Rotation modes are ffa, tag, gungame, horse, bomb and ctf. A match starts once sv.autostart_players players are seated. sv.warmup_secs and sv.results_secs set the pauses. Use rotation add, rotation remove, nextmap and map to change it live.
  • Map voting: sv.mapvote true puts a ballot in front of players when a match ends instead of simply stepping to the next entry. The match summary steps aside after a few seconds, so everyone is back on the map and free to move while they pick with the number keys or the vote command. sv.mapvote_choices is how many entries are offered and sv.mapvote_secs how long the ballot stays up, holding the results screen for at least that long. The pool is drawn from the rotation, never including what is playing now, weighted by sv.mapvote_recency (how hard it keeps off what was played lately) and sv.mapvote_popularity (above 0 offers frequent winners more often, below 0 less, 0 ignores the record). Ties break at random, and a ballot nobody answers still picks one of its own entries. mapvote status|open|close|cancel|reset drives it by hand; reset forgets what has been played and what has won.
  • Ranked servers: set sv.mode ranked. The sv.ranked_* variables set rounds, queue widening and pauses.
  • Race servers: set sv.mode race and sv.tracks_dir to a folder of .btrk files. sv.rotation lists track ids. sv.race_track_secs sets how long each track runs. With sv.race_rules practice, a runner who falls goes back to their last checkpoint instead of restarting.

Radio

A server can play music to everyone on it. Put songs in a radio directory beside the server, turn it on, and restart:

set sv.radio true

Every sv.radio_* variable is listed under sv. sv.radio and sv.radio_dir need a restart because they decide whether the server owns a station at all; everything else applies live.

What plays. Any .flac, .mp3, .ogg, .wav, .aiff, .m4a or .aac file under radio, including in subdirectories, so an Artist/Album tree works as it is. Titles, artists, albums and album art are read from the files' own tags; a file with no title shows its name. A cover can also sit beside the songs as cover.jpg, folder.jpg, front.jpg or album.jpg.

.opus files are not played. The decoder the game ships has no Opus support, so they are skipped with a line in the log saying so — convert them to FLAC and they will play.

Playlists. A name.txt at the top of radio is a playlist. One entry per line, each a path relative to radio or just a file name; # and ; start a comment and blank lines are ignored. Pick one with set sv.radio_playlist name, or leave it empty to play everything. set sv.radio_shuffle true plays in a random order either way, and never repeats a song immediately.

How it sounds. Whatever the operator collected is decoded and re-encoded to 48 kHz stereo FLAC, so a lossless source stays lossless and players receive a stream rather than your files. That costs about 0.9 Mbit/s per listener; sv.radio_mbits caps what the station may spend in total and sv.radio_max_listeners caps how many people it takes. A listener past either is told the station is full rather than everyone being turned down. The radio has first call on sv.download_mbits and map transfers take what is left, because a download that slows down merely finishes later while a stream that slows down stutters.

Players hear it about sv.radio_buffer_secs behind the server, all at the same point in the song. They can turn it off in Settings > Audio, which stops the server sending them anything at all.

Driving it. radio on the console, or the Radio tab of the server panel:

radio status
radio skip
radio pause
radio play
radio playlist chill
radio shuffle on
radio list drive
radio jump 41
radio rescan

radio list searches and pages the library and prints each track's number; radio jump takes one of those numbers, or part of a title. sv.radio_scan_secs re-reads the directory on a timer if songs are added while the server runs.

Control API

--control-socket serves a JSON API for scripts and panels: server status, lobbies, console lines and events. Whoever can open the socket controls the server, so set its file permissions with care.

The station is on there too: GET /radio for what is playing, GET /radio/tracks?q=&page= and GET /radio/playlists for the library, and POST /radio/<action> for play, pause, skip, restart, rescan, playlist, shuffle and jump. They run the same code the radio console command does, so nothing can do one thing here and another there.

Scripting

A dedicated server can run JavaScript files that react to what happens on it, add ! chat commands, and run console commands. Each script runs in its own sandbox on a thread of its own, so a slow or broken script never holds up the game.

Enabling scripts

Put scripts in a scripts directory beside the server (/srv/eds/scripts in the Docker image), then name the ones to run:

set sv.scripts [skipsong, skipvote]

A name is the file name without .mjs or .js. Take a name out of the list to stop that script and put it back to start it again. script reload <name> loads a changed file, script list shows what is running, and script info <name> shows a script's commands, what it listens to and its last error. Scripts do not run on a listen server.

sv.scripts_dir moves the directory and needs a restart. sv.script_mem_mb caps each script's memory. sv.script_budget_ms caps how long a script may run for one event, command or timer: past it, the script is stopped mid-call. A script that errors 10 times in a minute is unloaded.

What a script may run

A script must start with a list of every console command it will run:

export const commands = ["radio skip", "announce", "tell"];

Only comments may come before it, and the list holds plain strings. The server reads it before the script runs and refuses any other command the script tries. An entry is a command, or a command and its first word:

  • "announce" allows announce with anything after it.
  • "radio skip" allows radio skip and nothing else from radio.
  • Variables must be named: "set sv.warmup_secs" or "get sv.rotation". A bare set is refused.

Some commands and variables are never given to a script, and a script that lists one does not load: exec, writeconfig, alias, unalias, bind, unbind, binds, vars, script, history and clear, and sv.key, sv.backend, sv.password, sv.admins, sv.auth, sv.auth_keys and every sv.script* variable. Read the list before enabling somebody else's script. Every command a script runs is written to the server log.

Writing a script

Scripts import what they need from eds:

export const commands = ["tell"];

import { command, on, exec, cmd } from "eds";

command("ping", async (c) => {
  await c.reply("pong");
}, "Check the server is listening");

on("player_join", async (e) => {
  await exec(cmd`tell ${e.player.ref} welcome, ${e.player.name}`);
});
  • command(name, handler, help) adds !name to chat. The line is not shown to other players. The handler gets lobby, player, name, args, raw and reply(text), which sends the player a private line and needs tell in the list. One script owns each name.
  • on(event, handler) calls the handler for every event of that kind, and returns a function that stops it.
  • exec(line) runs a console line and resolves to { ok, lines }. It rejects when the line is not in the list.
  • cmd`...` builds a line and quotes every value put into it, so a player's name can never turn into a second command. quote(value) does the same for one value.
  • log, warn and console.log write to the server log. sleep(ms) waits. every(ms, handler) repeats until the function it returns is called.

A script is a single file with no file system, network or other modules.

Every event has the lobby's invite code in lobby, empty for the hub:

EventFields
player_joinplayer, watching
player_leaveplayer, reason: left, kicked, timeout or closed
chatplayer, text; ! commands are not included
killkiller (null for a fall or the world), victim, weapon
match_startmap, mode
match_endmap, mode, result
round_wonwinner, tally
map_changedmap
lobby_created
lobby_closedreason

A player is { ref, id, name, slot, admin }. Use ref to name them in commands like tell and kick.

tell <player> <text>, announce <text> and lobbysay <code> <text> send a system line. It shows in the chat box marked as coming from the server, or from the script that sent it. start, end, map and nextmap act on the rotation arena.

TypeScript and examples

sdk/script/eds.d.ts types the whole API. sdk/script/examples has two scripts:

  • skipsong.js lets anyone skip the radio song with !skipsong, with a cooldown for each player.
  • skipvote.js ends the match when three players type !skip, which opens the map vote on a server with sv.mapvote true.

The server runs JavaScript only, so compile TypeScript first. tsc keeps the commands list at the top of the file. A bundler may move exports to the end, so with esbuild put the list in --banner:js= instead.

Map editor

Opening

  • Maps > New map creates a starter map with a floor and a player start.
  • Maps > select a custom map > Edit opens it.

Only maps made in the editor can be edited. Other maps open read-only in the map debugger. Leave any lobby before editing.

Camera

  • Hold right mouse and move to look.
  • W A S D fly. E or Space moves up, Q moves down.
  • Hold Shift to fly fast.
  • Mouse wheel changes fly speed.
  • F focuses the selection.

Selecting and editing

  • Left click selects. Shift adds, Ctrl toggles. Drag on empty space to box select.
  • G moves, T scales, R rotates by 90 degrees. Tab switches between move and scale.
  • H hides the selection, Shift+H shows everything.
  • Ctrl+C, Ctrl+V and Ctrl+D copy, paste and duplicate.
  • Delete or Backspace removes the selection.
  • [ and ] change the grid size. Snap in the top bar turns grid snapping on and off.
  • Ctrl+Z undoes. Ctrl+Y or Ctrl+Shift+Z redoes.

The inspector edits the selection: position, size, rotation, name, shape, colour, and whether a block is a ladder, water or glass. Glass has a pane preset, break speed, opacity, and whether it holds or breaks underfoot. The outliner lists every block and marker.

Placing

The left panel has blocks, markers and colours. Click an entry, then click in the world to place it. Shift click keeps placing. Esc or right click puts the tool down. 1 to 9 pick the first nine blocks.

  • Blocks: box, floor, wall, platform, pillar, wedge, ramps at 15, 30 and 45 degrees, a 60 degree surf ramp, stairs, ladder, water, and four glass panes.
  • Markers: player start, deathmatch spawn, dummy, and dummy rail.
  • A dummy is a target. Killable dummies take damage. A dummy rail moves a dummy along a path.

Movement helpers

The top bar has tools for checking jumps:

  • Arc draws the jump arc from the cursor along the camera direction.
  • Reach shows how far a jump from the cursor lands in every direction.
  • Gap: click two points to see if the gap can be jumped.
  • The gait button switches the helpers between walk, sprint and strafe.

O toggles the run overlay.

Saving and testing

Ctrl+S or Save writes the map to the custom maps folder as <name>.blvl. See Installing a map. Map names use lowercase letters, digits, _ and -.

Test run plays the map right away without saving. Esc returns to the editor. Leaving with unsaved changes asks to save, discard or keep editing.

Edit tracks opens the track editor on the same map.

Map debugger

The map debugger inspects any map read-only. Open it with Debug in the editor, Inspect on a map that is not editable, or the mapdebug console command in game. It can show colliders, triggers, teleports, spawns, doors and lights, colour colliders by flags or source, list map problems, and copy or save a text dump of a selection.

Track editor

A track is a race course on a map: a start, checkpoints in order, and a finish.

Opening

  • Maps > select a map > Tracks.
  • Maps > Tracks tab > Edit on a track.
  • Edit tracks in the map editor.

The track editor uses the same camera, selection and grid keys as the map editor. The map's blocks are read-only here.

Placing

Pick a tool from the Track menu or press its key, then click in the world.

KeyTool
1Start
2Checkpoint
3Finish zone
4Reset zone
5NPC
  • Start sets where runs begin and which way the runner faces.
  • Checkpoints must be touched in order. PgUp and PgDn move the selected checkpoint earlier or later.
  • A finish zone ends the run.
  • A reset zone counts as a fall. In a race the run restarts. In practice the runner goes back to the last checkpoint.
  • NPCs are dummies placed on the track.

Zones are boxes. Set their center and half size in the inspector.

Track settings

Track > Settings sets the name, id, author and loadout. The loadout is either the runner's own preset, or guns chosen by the track with spare magazines per slot. -1 magazines means unlimited reloads.

Runs

View > Runs opens saved runs, leaderboard runs and test runs, and draws them in the world. Toggle marks, jumps, second ticks and X-ray drawing from the View menu or the runs window. O toggles the run overlay.

Checks

A track cannot be run until it has a start and at least one checkpoint or finish zone, every zone has a size, and a track loadout names at least one gun. Save still works on an unfinished track and lists what is missing. Test run refuses until it is fixed.

Saving and publishing

Ctrl+S saves the track as <tracks folder>/<map>/<id>.btrk. See Files and folders. File > Test run plays it.

To share a track, open Play > Race, select the track and press Publish.

Custom maps and blvl

blvl

.blvl is an open level format for first person shooters. The blvl tool bakes maps from other games into .blvl files the game can load. See https://blvl.lol for how to get blvl, its documentation and the format spec.

blvl reads maps from:

  • Quake 3 and Urban Terror (--pk3)
  • Source: Counter-Strike: Source, Half-Life 2, Team Fortress 2, older CS:GO (--source)
  • Source 2: Counter-Strike 2, Deadlock (--source2)
  • Valorant (--valorant)
  • Overwatch 2 (--ow2)
  • Call of Duty 4, Modern Warfare 2, Black Ops (--cod4, --mw2, --bo1)
  • Halo 2 from the Master Chief Collection (--halo2)
  • Reflex Arena (--reflex)

No game content ships with blvl. You bake from games you own.

Baking a map

blvl bake --pk3 ut4_uptown.pk3 --map ut4_uptown --out ut4_uptown.blvl
blvl bake --source2 --steam --map de_mirage --out de_mirage.blvl
blvl bake --reflex steam --map Aerowalk --out rfx_aerowalk.blvl
  • --map names the map inside the game files. --out is the file to write.
  • steam in place of a path finds the game in your Steam library, where supported.
  • --fast does a quick bake in seconds to check that a map loads.
  • blvl list with a frontend flag lists the maps it can find.
  • blvl info <file.blvl> and blvl probe <file.blvl> --problems check a baked map.
  • blvl help prints every option.

A bake also writes a .bsym file next to the map. Keep it with the .blvl for better debugging in the map debugger.

Installing a map

Put the .blvl file in the custom maps folder:

  • Linux: ~/.local/share/eds/maps
  • Windows: %APPDATA%\eds\maps

Then press Rescan on the Maps screen. Open folder on the same screen opens this folder. The EDS_CUSTOM_MAPS_DIR environment variable moves it. Maps made in the map editor are saved here too.

Maps that ship with the game are in assets/maps in the game folder. A shipped map hides a custom map with the same name.

Maps on servers

A custom map is only on your machine. To play it with others, host a lobby on it, or put it in a dedicated server's map folder. Players download it when they join. See Maps on a server.

Files and folders

On Linux, data goes under ~/.local/share/eds and settings under ~/.config/eds. On Windows both go under %APPDATA%\eds.

WhatDefault locationOverride
Settings~/.config/eds/config.cfgEDS_SETTINGS
Startup scriptautoexec.cfg next to config.cfg
HUD profileshud_profiles.json next to config.cfg
Console historyconsole_history next to config.cfg
Loglatest.log in the game folder, or eds.log next to config.cfgEDS_LOG
Custom maps~/.local/share/eds/mapsEDS_CUSTOM_MAPS_DIR
Downloaded maps~/.local/share/eds/servermapsEDS_SERVER_MAPS_DIR
Tracks~/.local/share/eds/tracksEDS_TRACKS_DIR
Runs~/.local/share/eds/runsEDS_RUNS_DIR
Replays~/.local/share/eds/replaysEDS_REPLAY_DIR
Screenshots~/.local/share/eds/screenshotsEDS_SCREENSHOT_DIR
Shipped mapsassets/maps in the game folderEDS_MAPS_DIR

EDS_SERVER_MAPS_CACHE_MB caps the downloaded map cache, 4096 MB by default.

Command line

eds

OptionDoes
--maps-dir <dir>Adds a map folder. Repeat for more.
--createHosts a lobby on start.
--join <code>Joins a lobby by invite code on start.
--spectate <code>Watches a lobby by invite code on start.
--server <host:port>Connects to a server on start.
--replay <file.brep>Opens a replay file.
--display <name>Opens the window on this monitor.
-v, -vvMore logging.

In Steam, set these under the game's Properties > Launch options.

eds-server

See Command line flags under Hosting a server.

Console variables

Every variable, its default, its allowed values and what it does. Set them with set <name> <value> or in config.cfg.

  • game.* variables are lobby rules. Only the lobby owner can set them.
  • sv.* variables belong to dedicated servers. Set them in server.cfg, or over rcon as an admin.

input

Mouse and keys.

VariableDefaultValuesDescription
input.sensitivity0.040.005 to 0.3Degrees of view rotation per mouse count
input.ads_togglefalseThe aim key toggles the sights instead of being held
input.zoom_sens10.2 to 2Multiplier on the focal-length sensitivity scale through a magnified scope

video

Display and renderer.

VariableDefaultValuesDescription
video.modeBorderlessWindowed, Borderless, FullscreenWindow mode
video.display_serverAutoAuto, X11, WaylandLinux only: which display server to open the window on; the Steam overlay needs X11, auto follows the session
video.monitoremptyDisplay to use; empty means the primary
video.width1600640 to 16384 pxWindow width in windowed mode
video.height900480 to 16384 pxWindow height in windowed mode
video.vsyncOffOff, On, MailboxOff presents as soon as a frame is done, On waits for the display, Fast keeps only the newest frame
video.fps_cap00 to 1000 HzFrame cap; 0 follows the monitor
video.low_latencyOnOff, On, BoostNVIDIA Reflex or AMD Anti-Lag when the driver offers it
video.render_scale10050 to 200%Scene resolution as a share of the window; above 100 supersamples
video.fov10570 to 130 degHorizontal field of view
video.viewmodel_fov6550 to 90 degField of view the held weapon is drawn with
video.brightness10.5 to 2Exposure multiplier
video.reticle_brightness10.2 to 2.5How bright a red dot or holo reticle is drawn
video.gamma2.21.8 to 2.6Output gamma
video.qualityMediumCompetitive, Low, Medium, High, Ultra, CustomRender preset; changing a detail below makes it Custom
video.shadingQualityCompetitive, QualityCompetitive is the flat, high contrast look; Quality is the full lighting model
video.surface_detailHighLow, HighNormal, roughness, emissive and directional lightmap detail on surfaces
video.shadowsMediumOff, Low, Medium, High, UltraSun shadow resolution, reach and softness
video.dynamic_shadowstrueShadows cast by players and props
video.ambient_occlusionLowOff, Low, Medium, HighScreen space contact shading
video.reflectionsLowOff, Low, HighReflection detail
video.waterMediumLow, Medium, HighWater surface detail; Medium refracts and reflects the scene, High adds screen space reflections and caustics
video.bloomfalseGlow around bright light, where the map style uses it
video.dynamic_lightstrueMuzzle flashes and explosions light the world
video.physics_propstrueBottles, crates and barrels react to the player, shots and blasts
video.card_trailstrueRibbons, glyph walls, smoke, stars and wires trailing behind players holding a foil card
video.anisotropyX8Off, X2, X4, X8, X16Texture sharpness at grazing angles
video.texture_detailHighLow, Medium, HighLower levels skip the sharpest mip levels
video.antialiasingOffOff, FxaaEdge smoothing; render scale above 100 supersamples as well
video.sharpen00 to 1Contrast adaptive sharpening after anti-aliasing

audio

Sound.

VariableDefaultValuesDescription
audio.master0.750 to 1Master volume
audio.sfx10 to 1Sound effects
audio.spatializerHrtfHrtf, PanSpatial audio
audio.reverbtrueReverb
audio.radiotruePlay the music a server is streaming; off tells the server to send none of it
audio.radio_volume0.50 to 1How loud the server's station is
audio.radio_duck00 to 1How far the station drops while a round is live; 0 leaves it alone

profile

Player.

VariableDefaultValuesDescription
profile.modelmaleCharacter model: male or female
profile.handRightRight, LeftGun hand
profile.emotes[0, 1, 2, 3, 4]list, 0 to 15Emote wheel slots
profile.dances[0, 1, 2, 3, 4]listDance wheel slots
profile.loadout12 entrieslistWeapon slots, three per preset
profile.loadout_names[Assault, Close, Long, Utility]listPreset names
profile.loadout_pick00 to 3The preset in hand

hud

Overlay.

VariableDefaultValuesDescription
hud.showtrueDraw the HUD
hud.scale10.5 to 2Size of the overlay
hud.max_hz00 to 1000 HzHUD updates per second; 0 sends one every frame
hud.profiledefaultHUD profile used where the game mode has none of its own

crosshair

Crosshair.

VariableDefaultValuesDescription
crosshair.styleDotDot, Cross, CrossDot, CircleShape
crosshair.size60 to 40 pxArm length
crosshair.gap40 to 40 pxGap from the centre
crosshair.thickness21 to 8 pxLine thickness
crosshair.color#e8f7ffColour as #rrggbb
crosshair.outlinetrueDark outline

cosmetics

Cosmetics.

VariableDefaultValuesDescription
cosmetics.presetemptyOutfit preset
cosmetics.paletteemptyOutfit palette
cosmetics.partsemptylistPart overrides on top of the preset, one slot=id per entry; none empties an optional slot

card

Playing card.

VariableDefaultValuesDescription
card.slots4 entrieslistCard wheel slots, one id or id:foil per entry
card.pick00 to 3The slot the card comes out of

maps

Maps.

VariableDefaultValuesDescription
maps.recentemptylistMaps a match was played on lately, newest first

oiko

Crash reports.

VariableDefaultValuesDescription
oiko.upload_crash_dumpsfalseAfter a crash, send the minidump, the log and the build to the developers on the next launch

net

Servers.

VariableDefaultValuesDescription
net.favoritesemptylistServers starred in the browser; an entry is [label=]host:port
net.historyemptylistServers connected to lately, newest first
net.auto_replaystrueSave a replay of every match
net.auto_mapstrueDownload a lobby's map when this client lacks it
net.upload_replaystrueSend a replay of every match you host to the backend

discord

Discord.

VariableDefaultValuesDescription
discord.presencetrueRich presence
discord.lobby_invitestrueLobby invites in presence

watch

Spectator HUD layers.

VariableDefaultValuesDescription
watch.hudtrueGame HUD while the replay controls are hidden
watch.teamfalseTeam panel
watch.playerfalsePlayer panel
watch.feedfalseKill feed
watch.scoreboardfalseScoreboard
watch.minimapfalseMinimap
watch.statsfalseStats block
watch.phasetrueMatch phase

console

Console.

VariableDefaultValuesDescription
console.height0.450.2 to 1Fraction of the window the console covers
console.vifalseVi editing on the prompt
console.font_size149 to 32 pxFont size
console.opacity0.920.3 to 1Background opacity

app

Application.

VariableDefaultValuesDescription
app.versionBuild version (read only)
app.cloud_syncfalsePush config.cfg and hud_profiles.json to Steam Cloud on every save

game

Lobby rules.

VariableDefaultValuesDescription
game.mapThe map the lobby is on (read only)
game.modeduelduel, ffa, tag, race, gungame, horse, bomb, ctfGame mode
game.weapons15 entrieslistGuns the per-fight draw may hand out
game.rounds00 to 30Round wins that take the match; 0 plays without a limit
game.tag_time300120 to 1200 sHow long a tag match runs
game.tag_headshottrueOnly a headshot tags
game.bomb_plant31 to 600 sHow long planting the bomb takes
game.bomb_defuse101 to 600 sHow long defusing it takes
game.bomb_fuse401 to 600 sHow long a planted bomb burns for
game.bomb_round1801 to 600 sHow long a bomb round runs before the defenders take it
game.ctf_time120060 to 3600 sHow long a capture the flag match runs
game.ctf_respawn50 to 3600 sHow long a death costs in capture the flag
game.ctf_return301 to 3600 sHow long a dropped flag lies before it goes home
game.loadout_1[rifles, smgs, shotguns, snipers]listWhat the first loadout slot may hold: class plurals or weapon tags
game.loadout_2[sidearms]listWhat the second loadout slot may hold
game.loadout_3[grenade, shotgun_short]listWhat the third loadout slot may hold
game.spares_12-1 to 99Spare magazines for the first slot; -1 leaves reloads unlimited
game.spares_23-1 to 99Spare magazines for the second slot; -1 leaves reloads unlimited
game.spares_31-1 to 99Spare magazines for the third slot; -1 leaves reloads unlimited
game.visibilityprivateprivate, friends, publicWho can find the lobby
game.cheatsfalseNoclip is allowed here (read only)
game.warmup_wait00 to 3600 sSeconds a match waits in warmup before it may start; 0 means none
game.max_players00 to 16Player cap; 0 means the mode's own

sv

Server.

VariableDefaultValuesDescription
sv.bind0.0.0.0:27960UDP address to listen on (restart)
sv.modegameWhat this server runs: ranked, race or game (restart)
sv.hostnameemptyThe name the browser shows
sv.publictrueList this server on the backend directory
sv.backendhttps://eds-backend.plus3.devBackend URL: the directory and the track registry (restart)
sv.public_addremptyThe host:port players reach this server on, when the backend cannot tell
sv.passwordemptyPlayers must give this to connect; empty means anyone
sv.adminsemptylistPlayer ids that may use rcon; empty means only the local console and the host's own client
sv.authrequiredWhether a UDP client must prove who it is: required, optional or off
sv.auth_keysemptylistkid:hex signing keys to trust; empty fetches them from the backend
sv.cardsverifiedWhether a card a player shows must be backed by a backend-signed entitlement: verified or trusted
sv.dbemptyThe SQLite file for stats, ratings, bans and records; empty means eds-server.db (restart)
sv.snapshot_div11 to 16Ticks between snapshots to a player
sv.spectator_snapshot_div41 to 64Ticks between snapshots to a viewer
sv.spectator_delay_secs00 to 120 sHow far behind the match viewers see it; 0 is live
sv.max_players161 to 16Seats in the rotation arena
sv.max_viewers3000 to 10000Viewers this server takes
sv.default_mapemptyMap arenas start on; empty means the training range (restart)
sv.rotationemptylistRotation entries: map or map:mode for a game server, track ids for a race server
sv.tracks_diremptyWhere a race server looks for .btrk files named by the rotation (restart)
sv.autostart_players22 to 16Seated players before a rotation match starts itself
sv.warmup_secs200 to 600 sWarmup before a rotation match starts
sv.results_secs101 to 120 sHow long results stay up before the rotation moves on
sv.mapvotefalsePlayers vote on the next rotation entry instead of it simply moving on
sv.mapvote_choices42 to 8Entries on the ballot, drawn from the rotation
sv.mapvote_secs305 to 120 sHow long a vote runs after a match; it holds the results up for at least this long
sv.mapvote_recency10 to 4How hard the ballot keeps off what was played recently; 0 ignores it
sv.mapvote_popularity0-2 to 2How much winning votes change an entry's odds of being offered: above 0 favours the crowd-pleasers, below 0 spreads the load
sv.rounds_to_win00 to 30Round wins that take a rotation match; 0 plays without a limit
sv.weaponsemptylistGuns the fights may draw from, by tag; empty means all of them
sv.loadout_1emptylistWhat the first loadout slot may hold: class plurals or weapon tags; empty means the shipped rule
sv.loadout_2emptylistWhat the second loadout slot may hold; empty means the shipped rule
sv.loadout_3emptylistWhat the third loadout slot may hold; empty means the shipped rule
sv.spares_1-2-2 to 99Spare magazines for the first slot; -1 is unlimited and -2 means the shipped rule
sv.spares_2-2-2 to 99Spare magazines for the second slot; -1 is unlimited and -2 means the shipped rule
sv.spares_3-2-2 to 99Spare magazines for the third slot; -1 is unlimited and -2 means the shipped rule
sv.tag_time_secs30030 to 1800 sTag time limit
sv.tag_headshottrueTag passes on headshots only
sv.late_joinfalseSeat a player who joins during a match to sit out until the next fight; off has them watch until it ends
sv.bomb_plant_secs31 to 600 sHow long planting the bomb takes
sv.bomb_defuse_secs101 to 600 sHow long defusing it takes
sv.bomb_fuse_secs401 to 600 sHow long a planted bomb burns for
sv.bomb_round_secs1801 to 600 sHow long a bomb round runs before the defenders take it
sv.ctf_time_secs120060 to 3600 sCapture the flag time limit
sv.ctf_respawn_secs50 to 3600 sHow long a capture the flag death costs
sv.ctf_return_secs301 to 3600 sHow long a dropped flag lies before it goes home
sv.ranked_max_matches41 to 64Ranked matches at once; queues wait when every arena is busy
sv.ranked_rounds61 to 30Round wins that take a ranked match
sv.ranked_window15010 to 2000Rating gap the queue pairs across, widening with wait
sv.ranked_widen_secs[15, 45, 90]listSeconds queued before the window widens, one per stage
sv.ranked_pause_secs300 to 300 sHow long a ranked match waits for a dropped player
sv.ranked_warmup_wait_secs605 to 600 sHow long a ranked arena waits for everyone to arrive
sv.ranked_warmup_players160 to 16Seats in the ranked warmup room players wait in; 0 opens none
sv.ranked_tau0.50.1 to 1.2Glicko-2 volatility constraint
sv.ranked_margintrueScale rating moves by the round margin
sv.race_track_secs9000 to 86400 sHow long a race server stays on one track; 0 rotates by hand
sv.race_rulesraceRun rules on a race server: race or practice
sv.heartbeat_secs305 to 600 sHow often the directory hears from this server
sv.regionemptyWhere this server is, for the browser
sv.tagsemptylistWords the browser can filter on
sv.official_banstrueRefuse players on the official backend banlist
sv.banlist_sync_secs3010 to 600 sHow often this server pulls banlist changes from the backend
sv.upload_replaystrueShip finished recordings to the backend
sv.recordtrueRecord every match (restart)
sv.record_diremptyWhere recordings go; empty means the default replay directory (restart)
sv.download_mbits8000 to 10000 Mbit/sUpload the server will spend on map and replay downloads, shared between them; 0 turns downloads off
sv.max_downloads321 to 1024Downloads at once
sv.map_urlemptyBase URL clients try first for a map, as <url>/<name>.blvl; empty sends every map in-game
sv.map_url_onlyfalseNever send maps in-game; clients get them only from sv.map_url
sv.max_replays641 to 100000Recordings kept on disk
sv.replay_keep_secs0sRecordings older than this are dropped; 0 keeps them
sv.cheatsfalseAllow noclip in every arena
sv.radiofalseRun a station: stream the radio directory to everyone who asks for it (restart)
sv.radio_diremptyWhere the songs and the .txt playlists live; empty means the radio directory beside the server (restart)
sv.radio_playlistemptyThe playlist to play, by file name without .txt; empty plays the whole library
sv.radio_shufflefalsePlay in a random order
sv.radio_mbits1000 to 10000 Mbit/sUpload the station may spend across all its listeners; 0 stops the audio but keeps the track information
sv.radio_max_listeners640 to 1024Listeners the station takes at once
sv.radio_buffer_secs52 to 30 sHow much audio a listener is sent ahead of the playhead; also how far behind the server they hear it
sv.radio_gain_db0-24 to 6 dBLevel trim applied to every song
sv.radio_art_px2560 to 512 pxLongest side of the album art listeners are sent; 0 sends none
sv.radio_scan_secs00 to 86400 sRe-read the radio directory this often; 0 reads it on start and on radio rescan
sv.scriptsemptylistScripts to run from sv.scripts_dir, by file name without .mjs or .js; take one out to stop it
sv.scripts_dirscriptsWhere scripts live (restart)
sv.script_mem_mb161 to 256 MBMemory each script may use; applies the next time it loads
sv.script_budget_ms201 to 1000 msHow long a script may run for one event, command or timer before it is stopped

Console commands

Client

Commands that start with + are held actions for binds, listed under Default binds.

CommandArgumentsDescription
adminOpen the admin panel
alias[name] [command...]Name a command line; alone, list aliases
bind[key] [command...]Run a command when a key is pressed; alone, list binds
bindsList every bound key
card[id|next|prev [foil]|slot <1-4> [id] [foil]|pick <1-4>|give <id|all> [foil]|revoke all]Fill a slot on the card wheel, or give and revoke cards in dev builds; alone, list the cards
clearClear the console
connect<host:port>Create a lobby on a server
createCreate a lobby
cycle<var>Move an enum variable to its next value
dec<var> [step]Subtract from a number variable
disconnectLeave the lobby
echo<text...>Print text
exec<file>Run every line of a config file
get<var>Show a variable's value
help[name]What a command or variable does; alone, list everything
history[count]Show recent commands
hud_editMove and resize the HUD, or leave the editor
hud_profile[name|next|prev]Show the HUD profiles or switch to one
hud_profiles[list|new <name>|duplicate <from> <to>|rename <from> <to>|reset <name>|delete <name>|mode <slot> [name]]Create, copy, rename, reset, delete or assign HUD profiles
inc<var> [step]Add to a number variable
inventory_refreshFetch cards and entitlements from the backend again
join<code>Join a lobby by invite code
log_level[level|spec]Show or set the log filter: error, warn, info, debug, trace, or an env_logger spec
map[name]Change map; alone, list the maps
mapdebugOpen the map debugger here, on this map, at this camera
quitLeave the game
rcon<line...>Run a console line on the dedicated server
recordStart recording the lobby on the server, warmup and all; owner or admin
reset<var> | --allPut a variable back to its default; --all resets everything including binds
savereplaySave the match so far to this machine
say<text...>Say something to the lobby
screenshot[clean]Save a screenshot; clean drops the UI and the view model
set<var> <value...>Set a variable
statusWhat the game is doing: screen, connection and server
stopStop the recording record started and save it to this machine
thumbcamPrint this camera as a cameras/<map>.toml entry for the map's thumbnail
toggle<var>Flip a bool variable
toggleconsoleOpen or close the console
unalias<name>Remove an alias
unbind<key>Free a key
vars[prefix] [--all] [--changed] [--table]List variables and their values
versionShow the game, gewy and protocol versions
vote<n>Pick an entry on the open map vote
watch<code>Watch a lobby by invite code
writeconfig[file] [--changed]Write the config file; --changed writes only what differs from the defaults

Server

These run in a dedicated server's console: through rcon, the server panel, or the control API. set, get, vars, help and exec work there too.

CommandArgumentsDescription
statusWhat this server is doing
playersWho is seated where
viewersWho is watching
kick<name|#id|playerid>Drop a player or viewer
ban<name|#id|playerid> [secs] [reason]Drop somebody and keep them out; no seconds means forever
unban<playerid>Lift a ban
bansList the bans
banlistsThe banlists this server keeps and follows
banlist[list|new <name> [public]|rm <id>|add <id> <who> [secs] [reason]|del <id> <who>|find <id> <who>|sub <id>|unsub <id>|sync]Manage the banlists on this server's backend key
map<map>Put the rotation arena on a map now
nextmapMove the rotation on
rotation[list|add <entry>|remove <n>|clear|shuffle]Show or edit the rotation
mapvote[status|open|close|cancel|reset]Show, run or drop the vote on the next rotation entry
radio[status|play|pause|skip|restart|playlist [name|none]|shuffle [on|off]|rescan|jump <n|text>|list [text]|playlists]Show or drive the station
startStart the rotation arena's match
endEnd the rotation arena's match
say<text>Say something to everyone
tell<name|#id|playerid> <text>Send one player a private system line
announce<text>Send everyone a system line
lobbysay<code> <text>Send one lobby a system line
script[list|reload <name>|info <name>]List, reload or inspect the scripts in sv.scripts
ratings[solo|duo] [page]The ranked ladder
records[page]The records on the current track
log_level[level|spec]Show or set the log filter: error, warn, info, debug, trace, or an env_logger spec

Developer

Everything on this page exists only in development builds. Release builds do not have these binds, variables or commands.

Binds

KeyNameCommandAction
F3F3noclipNoclip
F2F2mapdebugMap debugger
F4F4dumpDump state
F5F5screenshotScreenshot
F6F6toggle dev.third_person
F8F8cycle dev.hitboxes
F9F9dev
F10F10dev camera

Variables

profile

Player.

VariableDefaultValuesDescription
profile.nameplayerDisplay name

net

Servers.

VariableDefaultValuesDescription
net.backendhttps://eds-backend.plus3.devBackend URL: the server list, invite codes and the race registry

dev

Developer.

VariableDefaultValuesDescription
dev.third_personfalseChase camera
dev.cam_dist1100 to 600 quChase camera arm length
dev.cam_shoulder18-200 to 200 quChase camera shoulder offset, right is positive
dev.cam_height0-100 to 200 quChase camera focus height above the eye
dev.cam_yaw0-180 to 180 degChase camera orbit yaw; 180 puts it in front looking back
dev.cam_pitch0-89 to 89 degChase camera orbit pitch
dev.cam_min240 to 600 quClosest the wall pull-in may bring the chase camera
dev.cam_clearance160 to 200 quGap the chase camera keeps off whatever it hits
dev.cam_in_rate300 to 120How fast the chase camera pulls in
dev.cam_out_rate60 to 120How fast the chase camera eases back out
dev.cam_fov00 to 170 degChase camera field of view; 0 keeps video.fov
dev.cam_roll0-180 to 180 degChase camera roll
dev.cam_collidetruePull the chase camera in at walls
dev.hitboxesOffOff, Xray, DepthHit capsule overlay
dev.reticle_rulerfalseDraw MOA circles about the crosshair
dev.shot_viewmodelfalseKeep the view model in clean screenshots
dev.hide_viewmodelfalseHide the first-person view model
dev.styleAutoAuto, Eds, Urt, Q3, Cs2, Val, Css, Csgo, Tf2, Ow2, Cod4, Halo2, ReflexRenderer style
dev.exposure_lockfalsePin auto-exposure to the map's authored midpoint
dev.q3_overbright-1idTech3 r_overBrightBits override; -1 keeps the map's
dev.q3_map_overbright-1idTech3 r_mapOverBrightBits override; -1 keeps the map's
dev.q3_gamma0idTech3 r_gamma override; 0 keeps the map's
dev.src_hdrtrueSource 1 HDR path; off forces the LDR chain
dev.cod4_filmtrueCoD4 film tweak
dev.cod4_glowtrueCoD4 glow
dev.light_stylestrueAnimate the light style table
dev.halo2_lightmap_gain20 to 4Halo 2 lightmap modulate; 0 keeps the map's gain
dev.halo2_detailtrueHalo 2 detail maps
dev.halo2_env10 to 4Halo 2 environment map scale
dev.halo2_fogtrueHalo 2 atmospheric fog
dev.depth_prepasstrueFill depth before shading the opaque world, so an overdrawn pixel is only shaded once
dev.gpu_timingfalseTimestamp every render pass so the HUD and timing can report per-zone GPU cost

Commands

CommandArgumentsDescription
achievement[list|unlock <api>|reset]List the Steam achievements, unlock one or reset them all
cloud[list|delete <file>]List the files in Steam Cloud for this app, or delete one
crash[segv|abort]Crash the client on purpose to test the minidump and the oiko upload
dump[player|probe|collision|pose]Print the player, what the crosshair is on, the nearby collision and the pose
noclipFly through walls
rig[anim|pose|tp|cards]Open the rig tool here, on this map; again to close and go back
timing[on|off]Turn per-pass GPU timing on or off; alone, print the last frame's zones