Input Devices and Keybinds
The easiest way to bind keys is via the controls menu in the game options. Just click on one of the available commands, and press a key (or mouse button) to bind it to that command. A key can be bound to multiple commands, too.
To enable controller and joystick inputs, make sure "Enable Controllers" in the controls menu is checked. All controller devices should be detected automatically.
You can bind controller/joystick buttons to keys just like keyboard buttons, however joysticks are special cases.
To bind a joystick axis, turn/push the joystick in the axis direction halfway to the limit and the game should recognize it as a kew press.
Some commands have additional support for joysticks (e.g. for smoother camera movement), others will just run regularly.
If you want to bind a key to a command which is not listed in the menu, or you want to assign more than 2 keys to a command, you'll have to bind the keys directly through the console - They will still be saved when the game is exited.
You can also use the "bind" console command to bind a key to a command. To get a list of available commands, type "list" (for serverside commands), or "cl_list" (for clientside commands) in the console.
You can get a list of available keys that you can bind by typing "bind_keys".
For example, if you want to bind the key h to jump, you could use: bind h +jump.
You can also bind several commands to a key at once: bind h "+jump; +forward; +left" (Pressing h will make the player jump, move forward and move left at the same time.)
To unbind a key, use unbind <key>.
Note: If you have a controller or joystick plugged in, there are more keys available than are shown by the bind_keys command.
Controller keys are named like this:
- The first button of the first controller is called "joy0bt0". Each subsequent button of that controller increments the second number, meaning the fifth button would be "joy0bt4". You'll have to experiment to find out which button the numbers actually correspond to.
- If your controller has one or more joysticks, they can be bound using "joy0axis0", etc, following the same rules as for buttons.
- If you have more than one controller, each subsequent controller will increment the first number of these commands, so the 4th axis of the 3rd controller would be "joy2axis3".
There's also the command "toggle", which you can use to bind a key to a console variable. You could use that for example to bind a key to turning cheats on or off:
bind c "toggle sv_cheats"
There's also the command "unbindall", which unbinds all currently bound keys.
And lastly, there's the command "keymappings", which lists all currently bound keys with their respective commands.
Adding new keybind commands
To add a new keybind command in Lua, you'll have to create a console command first. To do so you can use cvar.create_concommand.
cvar.create_concommand("freeze",function(pl,...) if(pl == nil) then return end pl:SetFrozen(not pl:IsFrozen()) end)
Put that somewhere in a severside script which is executed when the game is started.
Typing freeze in the console, or binding a key to the command, will freeze or unfreeze the player that called the command.
If you're creating an addon, you can also add the command to the controls menu in the options. To do so, follow these instructions:
- Create an empty XML-file called "menu.xml" in the root directory of your addon ("addons/<your_addon>/menu.xml") and set it up like this:
<?xml version="1.0" encoding="UTF-8" ?> <locale>addon_locale_file.txt</locale> <game> <menu> <options> <controls> <control header="true"> <!-- Creates a new segment in the controls menu for your addon --> <name>your_addon</name> </control> <control> <!-- This adds a new row for the command we created earlier. You can specify multiple such blocks if you want to specify multiple bindings --> <name>freeze_player</name> <cmd>freeze</cmd> </control> </controls> </options> </menu> </game>
Depending on your needs, there are different command types. For example, you can also add a key-binding for a toggle command:
and change the menu.xml accordingly:
[...] <control> <name>toggle_con_var</name> <cmd>toggle some_console_variable</cmd> </control> [...]
This will allow the player to bind a key to that variable, and toggle it between 0 and 1 by pressing that key.
By default, if a controller joystick is bound to a command, that command will be executed if the joystick is turned/pushed down to a certain threshold.
Each joystick axis is also split into two, which makes it possible to, for example, bind pushing the joystick away from you to a different command than pulling it towards you.
You can influence this behavior for your command with two flags: cvar.FLAG_JOYSTICK_AXIS_CONTINUOUS and cvar.FLAG_JOYSTICK_AXIS_SINGLE.
If either of these flags is set, the callback for the command will have an additional parameter (after the player and before the command's arguments), which represents the joystick's position on the axis.
A value of 1 means the joystick is fully tilted in one direction, -1 means it's fully tilted in the other direction. Unless cvar.FLAG_JOYSTICK_AXIS_SINGLE is set, the value will never be negative!
With this flag, the command will be called constantly if bound to a joystick axis and if the joystick isn't at the home position of that axis (Home position is axisVal = 0).
local dirForward = Vector(1,0,0) local dirRight = Vector(0,0,1) cvar.create_concommand("test_joystick",function(pl,axisVal,...) if(pl == nil) then return end local pos = pl:GetCenter() local valForward = math.sin(axisVal *math.pi /2.0) local valRight = math.cos(axisVal *math.pi /2.0) local dir = dirForward *valForward +dirRight *valRight dir:Normalize() debugrenderer.draw_line(pos,pos +dir *100.0,Color.Red,0.1) end,cvar.FLAG_JOYSTICK_AXIS_CONTINUOUS)
If you run this clientside, and bind a joystick axis to the command, you'll see a red line appearing around the player (unless the joystick is at the axis' home position), representing the current position on the axis.
Note how the line only covers 90 degrees. (Axis range: [0,1])
This is, for instance, used for the commands +forward and +backward. Both commands control movement on the same axis, but have to be bound individually.
By default each joystick axis is split into two.
If you want your command to use the full axis instead (and you don't want to use two commands), you can use this flag.
local dirForward = Vector(1,0,0) local dirRight = Vector(0,0,1) cvar.create_concommand("test_joystick",function(pl,axisVal,...) if(pl == nil) then return end local pos = pl:GetCenter() local valForward = math.sin(axisVal *math.pi /2.0) local valRight = math.cos(axisVal *math.pi /2.0) local dir = dirForward *valForward +dirRight *valRight dir:Normalize() debugrenderer.draw_line(pos,pos +dir *100.0,Color.Red,1) end,cvar.FLAG_JOYSTICK_AXIS_SINGLE)
The above command would draw a red line if the joystick is tilted above a certain threshold in either direction of the axis bound to the command.
Without the flag, the line would only be drawn if the joystick is tilted in one of the directions of the axis.
Note how the line appears for the full 180 degree range. (Axis range: [-1,1])
You can combine both flags to get a continuous callback with the full axis range:
While the cvar.FLAG_JOYSTICK_AXIS_CONTINUOUS could be used serverside (cvar.FLAG_JOYSTICK_AXIS_SINGLE cannot!), you should avoid doing so, because it's a significant burden on network throughput.
Commands with the prefix '+' and '-' receive special treatment when used with Key-Binds.
These commands always come in pairs, so if you define a '+'-command, you also have to define a '-'-command with the same name.
cvar.create_concommand("+test_cmd",function(pl,...) console.print("Command In") end) cvar.create_concommand("-test_cmd",function(pl,...) console.print("Command Out") end)
Only the command with the '+'-prefix has to be bound to a key. The '+'-command will be called just as usual when the key is pressed, and the '-'-command will be called when the key is released.
This can also be combined with the joystick flags.